@files-preview-app/preview-file 1.3.1 → 1.3.2
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/README.md +69 -0
- package/dist/angular.cjs +1307 -468
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +1307 -468
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +1307 -468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d-B79v0jxi.d.cts +570 -0
- package/dist/index.d-B79v0jxi.d.ts +570 -0
- package/dist/index.d.cts +3227 -19
- package/dist/index.d.ts +3227 -19
- package/dist/index.js +1307 -468
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1307 -468
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -16
- package/dist/react.d.ts +1 -16
- package/dist/react.js +1307 -468
- package/dist/react.js.map +1 -1
- package/dist/styles.css +195 -14
- package/dist/vue.cjs +1307 -468
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1307 -468
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
package/dist/angular.cjs
CHANGED
|
@@ -575,8 +575,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
575
575
|
var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
|
|
576
576
|
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>`;
|
|
577
577
|
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>`;
|
|
578
|
-
var
|
|
579
|
-
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"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>`;
|
|
578
|
+
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>`;
|
|
580
579
|
var ICON_MAP = {
|
|
581
580
|
"zoom-in": ICON_ZOOM_IN,
|
|
582
581
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -603,28 +602,177 @@ var ICON_MAP = {
|
|
|
603
602
|
"forward-10": ICON_FAST_FORWARD,
|
|
604
603
|
"rewind": ICON_REWIND,
|
|
605
604
|
"replay-10": ICON_REWIND,
|
|
606
|
-
"speed": ICON_SPEED,
|
|
607
605
|
"open-window": ICON_EXTERNAL_WINDOW,
|
|
608
|
-
"external-window": ICON_EXTERNAL_WINDOW
|
|
606
|
+
"external-window": ICON_EXTERNAL_WINDOW,
|
|
607
|
+
"openWindow": ICON_EXTERNAL_WINDOW,
|
|
608
|
+
"openSeparateWindow": ICON_EXTERNAL_WINDOW
|
|
609
609
|
};
|
|
610
610
|
var ToolbarController = class {
|
|
611
611
|
el;
|
|
612
612
|
toolbarEl;
|
|
613
613
|
actions = [];
|
|
614
|
+
config = {};
|
|
614
615
|
pageInputEl = null;
|
|
615
616
|
pageLabelEl = null;
|
|
616
|
-
|
|
617
|
+
prevPageBtn = null;
|
|
618
|
+
nextPageBtn = null;
|
|
619
|
+
constructor(container, config) {
|
|
617
620
|
this.el = container;
|
|
621
|
+
if (config) this.config = { ...config };
|
|
618
622
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
619
623
|
this.el.appendChild(this.toolbarEl);
|
|
620
624
|
}
|
|
625
|
+
setConfig(config) {
|
|
626
|
+
this.config = { ...config };
|
|
627
|
+
this.render();
|
|
628
|
+
}
|
|
629
|
+
getConfig() {
|
|
630
|
+
return { ...this.config };
|
|
631
|
+
}
|
|
632
|
+
hideAction(actionId) {
|
|
633
|
+
this.config[actionId] = false;
|
|
634
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = false;
|
|
635
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = false;
|
|
636
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
637
|
+
this.config.fitPage = false;
|
|
638
|
+
this.config.fitToPage = false;
|
|
639
|
+
this.config.fitWidth = false;
|
|
640
|
+
}
|
|
641
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
|
|
642
|
+
if (actionId === "fullscreen") this.config.fullscreen = false;
|
|
643
|
+
if (actionId === "download") this.config.download = false;
|
|
644
|
+
if (actionId === "print") this.config.print = false;
|
|
645
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
646
|
+
this.config.openWindow = false;
|
|
647
|
+
this.config.openSeparateWindow = false;
|
|
648
|
+
}
|
|
649
|
+
if (actionId === "copy") this.config.copy = false;
|
|
650
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
651
|
+
this.config.pageNav = false;
|
|
652
|
+
this.config.pagination = false;
|
|
653
|
+
}
|
|
654
|
+
this.render();
|
|
655
|
+
}
|
|
656
|
+
showAction(actionId) {
|
|
657
|
+
this.config[actionId] = true;
|
|
658
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = true;
|
|
659
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = true;
|
|
660
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
661
|
+
this.config.fitPage = true;
|
|
662
|
+
this.config.fitToPage = true;
|
|
663
|
+
this.config.fitWidth = true;
|
|
664
|
+
}
|
|
665
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
|
|
666
|
+
if (actionId === "fullscreen") this.config.fullscreen = true;
|
|
667
|
+
if (actionId === "download") this.config.download = true;
|
|
668
|
+
if (actionId === "print") this.config.print = true;
|
|
669
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
670
|
+
this.config.openWindow = true;
|
|
671
|
+
this.config.openSeparateWindow = true;
|
|
672
|
+
}
|
|
673
|
+
if (actionId === "copy") this.config.copy = true;
|
|
674
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
675
|
+
this.config.pageNav = true;
|
|
676
|
+
this.config.pagination = true;
|
|
677
|
+
}
|
|
678
|
+
this.render();
|
|
679
|
+
}
|
|
680
|
+
normalizeActionId(actionId) {
|
|
681
|
+
if (actionId === "zoomIn") return "zoom-in";
|
|
682
|
+
if (actionId === "zoomOut") return "zoom-out";
|
|
683
|
+
if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
|
|
684
|
+
if (actionId === "rotateCW") return "rotate-cw";
|
|
685
|
+
if (actionId === "rotateCCW") return "rotate-ccw";
|
|
686
|
+
if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
|
|
687
|
+
if (actionId === "pageNav") return "page-nav";
|
|
688
|
+
return actionId;
|
|
689
|
+
}
|
|
690
|
+
enableAction(actionId) {
|
|
691
|
+
const norm = this.normalizeActionId(actionId);
|
|
692
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
693
|
+
if (btn) {
|
|
694
|
+
btn.disabled = false;
|
|
695
|
+
btn.classList.remove("disabled");
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
disableAction(actionId) {
|
|
699
|
+
const norm = this.normalizeActionId(actionId);
|
|
700
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
701
|
+
if (btn) {
|
|
702
|
+
btn.disabled = true;
|
|
703
|
+
btn.classList.add("disabled");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
setActionActive(actionId, active) {
|
|
707
|
+
const norm = this.normalizeActionId(actionId);
|
|
708
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
709
|
+
if (btn) {
|
|
710
|
+
if (active) {
|
|
711
|
+
btn.classList.add("active");
|
|
712
|
+
} else {
|
|
713
|
+
btn.classList.remove("active");
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
isActionEnabled(action) {
|
|
718
|
+
const c = this.config;
|
|
719
|
+
const id = action.id;
|
|
720
|
+
if (c[id] === false) return false;
|
|
721
|
+
if (id === "zoom-in" && (c.zoomIn === false || c["zoom-in"] === false)) return false;
|
|
722
|
+
if (id === "zoom-out" && (c.zoomOut === false || c["zoom-out"] === false)) return false;
|
|
723
|
+
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)) {
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
729
|
+
if (id === "fullscreen" && c.fullscreen === false) return false;
|
|
730
|
+
if (id === "download" && c.download === false) return false;
|
|
731
|
+
if (id === "print" && c.print === false) return false;
|
|
732
|
+
if ((id === "open-window" || id === "external-window") && (c.openWindow === false || c.openSeparateWindow === false || c["open-window"] === false)) {
|
|
733
|
+
return false;
|
|
734
|
+
}
|
|
735
|
+
if (id === "copy" && c.copy === false) return false;
|
|
736
|
+
if (id === "thumbnails" && c.thumbnails === false) return false;
|
|
737
|
+
if (id === "page-nav" && (c.pageNav === false || c.pagination === false || c["page-nav"] === false)) {
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
if ((id === "prev" || id === "page-prev") && (c.prevPage === false || c.prev === false || c["prev"] === false || c.pageNav === false || c.pagination === false)) {
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
if ((id === "next" || id === "page-next") && (c.nextPage === false || c.next === false || c["next"] === false || c.pageNav === false || c.pagination === false)) {
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
if (id === "play" && c.play === false) return false;
|
|
747
|
+
if (id === "pause" && c.pause === false) return false;
|
|
748
|
+
if ((id === "fast-forward" || id === "forward-10") && (c.fastForward === false || c["fast-forward"] === false)) {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
if ((id === "rewind" || id === "replay-10") && (c.rewind === false || c["rewind"] === false)) {
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
if (id === "speed" && c.speed === false) return false;
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
621
757
|
setPage(page, max) {
|
|
622
758
|
if (this.pageInputEl) {
|
|
623
759
|
this.pageInputEl.value = page.toString();
|
|
760
|
+
if (max !== void 0) {
|
|
761
|
+
this.pageInputEl.max = max.toString();
|
|
762
|
+
}
|
|
624
763
|
}
|
|
625
764
|
if (max !== void 0 && this.pageLabelEl) {
|
|
626
765
|
this.pageLabelEl.textContent = ` / ${max}`;
|
|
627
766
|
}
|
|
767
|
+
const currentMax = max !== void 0 ? max : parseInt(this.pageInputEl?.max || "1", 10) || 1;
|
|
768
|
+
if (this.prevPageBtn) {
|
|
769
|
+
this.prevPageBtn.disabled = page <= 1;
|
|
770
|
+
this.prevPageBtn.style.opacity = page <= 1 ? "0.4" : "1";
|
|
771
|
+
}
|
|
772
|
+
if (this.nextPageBtn) {
|
|
773
|
+
this.nextPageBtn.disabled = page >= currentMax;
|
|
774
|
+
this.nextPageBtn.style.opacity = page >= currentMax ? "0.4" : "1";
|
|
775
|
+
}
|
|
628
776
|
}
|
|
629
777
|
update(actions) {
|
|
630
778
|
this.actions = actions;
|
|
@@ -647,8 +795,9 @@ var ToolbarController = class {
|
|
|
647
795
|
view: [],
|
|
648
796
|
actions: []
|
|
649
797
|
};
|
|
650
|
-
const
|
|
651
|
-
const
|
|
798
|
+
const enabledActions = this.actions.filter((a) => this.isActionEnabled(a));
|
|
799
|
+
const hasPageNav = enabledActions.some((a) => a.type === "page-nav");
|
|
800
|
+
const effectiveActions = hasPageNav ? enabledActions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : enabledActions;
|
|
652
801
|
for (const action of effectiveActions) {
|
|
653
802
|
if (groups[action.group]) {
|
|
654
803
|
groups[action.group].push(action);
|
|
@@ -708,6 +857,13 @@ var ToolbarController = class {
|
|
|
708
857
|
action.execute("go", val);
|
|
709
858
|
});
|
|
710
859
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
860
|
+
const curVal = action.value ?? 1;
|
|
861
|
+
prevBtn.disabled = curVal <= 1;
|
|
862
|
+
prevBtn.style.opacity = curVal <= 1 ? "0.4" : "1";
|
|
863
|
+
nextBtn.disabled = curVal >= max;
|
|
864
|
+
nextBtn.style.opacity = curVal >= max ? "0.4" : "1";
|
|
865
|
+
this.prevPageBtn = prevBtn;
|
|
866
|
+
this.nextPageBtn = nextBtn;
|
|
711
867
|
this.pageInputEl = input;
|
|
712
868
|
this.pageLabelEl = label;
|
|
713
869
|
groupEl.appendChild(prevBtn);
|
|
@@ -763,25 +919,63 @@ var ToolbarController = class {
|
|
|
763
919
|
var ThumbnailPanel = class {
|
|
764
920
|
el;
|
|
765
921
|
panelEl;
|
|
922
|
+
listEl;
|
|
923
|
+
headerEl;
|
|
766
924
|
thumbnails = [];
|
|
767
925
|
onSelect;
|
|
926
|
+
onToggleCallback;
|
|
768
927
|
activeIndex = 0;
|
|
769
|
-
|
|
928
|
+
observer;
|
|
929
|
+
renderedIndices = /* @__PURE__ */ new Set();
|
|
930
|
+
constructor(container, onToggle) {
|
|
770
931
|
this.el = container;
|
|
932
|
+
this.onToggleCallback = onToggle;
|
|
771
933
|
this.panelEl = createElement("div", { className: "fp-thumbnail-panel hidden" });
|
|
934
|
+
this.panelEl.style.width = "0px";
|
|
935
|
+
this.panelEl.style.minWidth = "0px";
|
|
936
|
+
this.panelEl.style.opacity = "0";
|
|
937
|
+
this.headerEl = createElement("div", { className: "fp-thumbnail-header" });
|
|
938
|
+
const title = createElement("span", { className: "fp-thumbnail-title" }, "Pages");
|
|
939
|
+
const closeBtn = createElement("button", {
|
|
940
|
+
className: "fp-thumbnail-close-btn",
|
|
941
|
+
title: "Close Thumbnails",
|
|
942
|
+
type: "button"
|
|
943
|
+
});
|
|
944
|
+
closeBtn.innerHTML = ICON_CLOSE;
|
|
945
|
+
closeBtn.addEventListener("click", (e) => {
|
|
946
|
+
e.stopPropagation();
|
|
947
|
+
this.hide();
|
|
948
|
+
});
|
|
949
|
+
this.headerEl.appendChild(title);
|
|
950
|
+
this.headerEl.appendChild(closeBtn);
|
|
951
|
+
this.listEl = createElement("div", { className: "fp-thumbnail-list" });
|
|
952
|
+
this.panelEl.appendChild(this.headerEl);
|
|
953
|
+
this.panelEl.appendChild(this.listEl);
|
|
772
954
|
this.el.appendChild(this.panelEl);
|
|
773
955
|
}
|
|
956
|
+
isOpen() {
|
|
957
|
+
return !this.panelEl.classList.contains("hidden") && this.panelEl.style.width !== "0px";
|
|
958
|
+
}
|
|
774
959
|
update(thumbnails, onSelect) {
|
|
775
960
|
this.thumbnails = thumbnails;
|
|
776
961
|
this.onSelect = onSelect;
|
|
962
|
+
this.renderedIndices.clear();
|
|
963
|
+
const titleEl = this.headerEl.querySelector(".fp-thumbnail-title");
|
|
964
|
+
if (titleEl) {
|
|
965
|
+
titleEl.textContent = `Pages (${thumbnails.length})`;
|
|
966
|
+
}
|
|
777
967
|
this.render();
|
|
968
|
+
if (this.isOpen()) {
|
|
969
|
+
this.renderAllVisible();
|
|
970
|
+
}
|
|
778
971
|
}
|
|
779
972
|
setActive(index) {
|
|
780
973
|
this.activeIndex = index;
|
|
781
|
-
const items = this.
|
|
974
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
782
975
|
items.forEach((item, i) => {
|
|
783
976
|
if (i === index) {
|
|
784
977
|
item.classList.add("active");
|
|
978
|
+
item.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
785
979
|
} else {
|
|
786
980
|
item.classList.remove("active");
|
|
787
981
|
}
|
|
@@ -789,37 +983,102 @@ var ThumbnailPanel = class {
|
|
|
789
983
|
}
|
|
790
984
|
show() {
|
|
791
985
|
this.panelEl.classList.remove("hidden");
|
|
986
|
+
this.panelEl.style.width = "200px";
|
|
987
|
+
this.panelEl.style.minWidth = "200px";
|
|
988
|
+
this.panelEl.style.opacity = "1";
|
|
989
|
+
this.panelEl.style.display = "flex";
|
|
990
|
+
this.onToggleCallback?.(true);
|
|
991
|
+
this.renderAllVisible();
|
|
792
992
|
}
|
|
793
993
|
hide() {
|
|
794
994
|
this.panelEl.classList.add("hidden");
|
|
995
|
+
this.panelEl.style.width = "0px";
|
|
996
|
+
this.panelEl.style.minWidth = "0px";
|
|
997
|
+
this.panelEl.style.opacity = "0";
|
|
998
|
+
this.onToggleCallback?.(false);
|
|
795
999
|
}
|
|
796
1000
|
toggle() {
|
|
797
|
-
this.
|
|
1001
|
+
if (this.isOpen()) {
|
|
1002
|
+
this.hide();
|
|
1003
|
+
} else {
|
|
1004
|
+
this.show();
|
|
1005
|
+
}
|
|
798
1006
|
}
|
|
799
1007
|
destroy() {
|
|
1008
|
+
if (this.observer) {
|
|
1009
|
+
this.observer.disconnect();
|
|
1010
|
+
this.observer = void 0;
|
|
1011
|
+
}
|
|
1012
|
+
this.renderedIndices.clear();
|
|
800
1013
|
this.el.innerHTML = "";
|
|
801
1014
|
}
|
|
802
|
-
|
|
803
|
-
this.
|
|
1015
|
+
renderAllVisible() {
|
|
1016
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
1017
|
+
items.forEach((item) => {
|
|
1018
|
+
const idx = parseInt(item.dataset.thumbIndex || "-1", 10);
|
|
1019
|
+
if (idx >= 0 && !this.renderedIndices.has(idx)) {
|
|
1020
|
+
this.renderThumbnailItem(idx, item);
|
|
1021
|
+
}
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
renderThumbnailItem(idx, itemEl) {
|
|
1025
|
+
if (this.renderedIndices.has(idx)) return;
|
|
1026
|
+
this.renderedIndices.add(idx);
|
|
1027
|
+
const canvas = itemEl.querySelector("canvas");
|
|
1028
|
+
const thumb = this.thumbnails[idx];
|
|
1029
|
+
if (canvas && thumb) {
|
|
1030
|
+
Promise.resolve(thumb.render(canvas)).catch((err) => {
|
|
1031
|
+
console.warn(`[FilePreview] Error rendering thumbnail ${idx}:`, err);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
render() {
|
|
1036
|
+
if (this.observer) {
|
|
1037
|
+
this.observer.disconnect();
|
|
1038
|
+
}
|
|
1039
|
+
this.listEl.innerHTML = "";
|
|
1040
|
+
const useObserver = typeof IntersectionObserver !== "undefined";
|
|
1041
|
+
if (useObserver) {
|
|
1042
|
+
this.observer = new IntersectionObserver(
|
|
1043
|
+
(entries) => {
|
|
1044
|
+
for (const entry of entries) {
|
|
1045
|
+
if (entry.isIntersecting) {
|
|
1046
|
+
const target = entry.target;
|
|
1047
|
+
const idx = parseInt(target.dataset.thumbIndex || "-1", 10);
|
|
1048
|
+
if (idx >= 0) {
|
|
1049
|
+
this.renderThumbnailItem(idx, target);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
root: this.listEl,
|
|
1056
|
+
rootMargin: "120px 0px 120px 0px"
|
|
1057
|
+
}
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
804
1060
|
for (let i = 0; i < this.thumbnails.length; i++) {
|
|
805
1061
|
const thumb = this.thumbnails[i];
|
|
806
|
-
const itemEl = createElement("div", {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1062
|
+
const itemEl = createElement("div", {
|
|
1063
|
+
className: "fp-thumbnail-item" + (i === this.activeIndex ? " active" : "")
|
|
1064
|
+
});
|
|
1065
|
+
itemEl.dataset.thumbIndex = i.toString();
|
|
810
1066
|
itemEl.addEventListener("click", () => {
|
|
811
1067
|
this.setActive(i);
|
|
812
1068
|
this.onSelect?.(i);
|
|
813
1069
|
});
|
|
814
|
-
const
|
|
815
|
-
const
|
|
816
|
-
|
|
1070
|
+
const canvasWrapper = createElement("div", { className: "fp-thumbnail-canvas-wrapper" });
|
|
1071
|
+
const canvas = createElement("canvas", { width: "130", height: "170" });
|
|
1072
|
+
canvasWrapper.appendChild(canvas);
|
|
1073
|
+
const label = createElement("span", { className: "fp-thumbnail-label" }, thumb.label || `Page ${i + 1}`);
|
|
1074
|
+
itemEl.appendChild(canvasWrapper);
|
|
817
1075
|
itemEl.appendChild(label);
|
|
818
|
-
this.
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
|
|
1076
|
+
this.listEl.appendChild(itemEl);
|
|
1077
|
+
if (this.observer) {
|
|
1078
|
+
this.observer.observe(itemEl);
|
|
1079
|
+
}
|
|
1080
|
+
if (i < 4) {
|
|
1081
|
+
this.renderThumbnailItem(i, itemEl);
|
|
823
1082
|
}
|
|
824
1083
|
}
|
|
825
1084
|
}
|
|
@@ -840,6 +1099,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
840
1099
|
currentOptions = {};
|
|
841
1100
|
resizeObserver = null;
|
|
842
1101
|
fullscreenHandler = null;
|
|
1102
|
+
titleBarEl = null;
|
|
843
1103
|
/**
|
|
844
1104
|
* Register a preview plugin.
|
|
845
1105
|
*/
|
|
@@ -876,6 +1136,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
876
1136
|
}
|
|
877
1137
|
this.currentBuffer = buffer.slice(0);
|
|
878
1138
|
this.currentMetadata = metadata;
|
|
1139
|
+
this.updateTitleBar(options, metadata);
|
|
879
1140
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
880
1141
|
const fileInfo = { metadata, buffer };
|
|
881
1142
|
const matchedPlugin = await this.findPlugin(fileInfo);
|
|
@@ -899,15 +1160,21 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
899
1160
|
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
900
1161
|
const total = payload.total ?? payload.totalPages;
|
|
901
1162
|
this.toolbar?.setPage(payload.page, total);
|
|
1163
|
+
this.thumbnailPanel?.setActive(payload.page - 1);
|
|
902
1164
|
}
|
|
903
1165
|
this.eventEmitter.emit(event, payload);
|
|
904
|
-
}
|
|
1166
|
+
},
|
|
1167
|
+
toggleThumbnails: () => this.toggleThumbnails()
|
|
905
1168
|
});
|
|
906
1169
|
this.activeInstance = instance;
|
|
907
1170
|
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
1171
|
+
instance.toggleThumbnails = () => this.toggleThumbnails();
|
|
908
1172
|
this.hideLoading();
|
|
909
1173
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
910
|
-
|
|
1174
|
+
const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
|
|
1175
|
+
if (isToolbarVisible && this.toolbar) {
|
|
1176
|
+
const toolbarConfig = this.extractToolbarConfig(options);
|
|
1177
|
+
this.toolbar.setConfig(toolbarConfig);
|
|
911
1178
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
912
1179
|
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
913
1180
|
if (!hasFullscreen && this.wrapperEl) {
|
|
@@ -957,6 +1224,12 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
957
1224
|
}
|
|
958
1225
|
});
|
|
959
1226
|
}
|
|
1227
|
+
const thumbAction = actions.find((a) => a.id === "thumbnails");
|
|
1228
|
+
if (thumbAction) {
|
|
1229
|
+
thumbAction.execute = () => {
|
|
1230
|
+
this.toggleThumbnails();
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
960
1233
|
this.toolbar.update(actions);
|
|
961
1234
|
this.toolbar.show();
|
|
962
1235
|
}
|
|
@@ -1041,7 +1314,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1041
1314
|
if (targetUrl) {
|
|
1042
1315
|
const newWin2 = window.open(targetUrl, "_blank");
|
|
1043
1316
|
if (!newWin2) {
|
|
1044
|
-
|
|
1317
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1045
1318
|
return null;
|
|
1046
1319
|
}
|
|
1047
1320
|
return newWin2;
|
|
@@ -1049,7 +1322,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1049
1322
|
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1050
1323
|
const newWin = window.open("", "_blank");
|
|
1051
1324
|
if (!newWin) {
|
|
1052
|
-
|
|
1325
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1053
1326
|
return null;
|
|
1054
1327
|
}
|
|
1055
1328
|
newWin.document.title = title;
|
|
@@ -1126,6 +1399,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1126
1399
|
this.currentBuffer = null;
|
|
1127
1400
|
this.currentMetadata = null;
|
|
1128
1401
|
this.currentContainer = null;
|
|
1402
|
+
this.titleBarEl = null;
|
|
1129
1403
|
}
|
|
1130
1404
|
/**
|
|
1131
1405
|
* Get the currently active preview instance.
|
|
@@ -1133,7 +1407,218 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1133
1407
|
getInstance() {
|
|
1134
1408
|
return this.activeInstance;
|
|
1135
1409
|
}
|
|
1410
|
+
// --- Toolbar Configuration & Feature Toggles ---
|
|
1411
|
+
/**
|
|
1412
|
+
* Configure toolbar features dynamically through options or methods.
|
|
1413
|
+
* e.g. viewer.setToolbarConfig({ zoomIn: false, print: false })
|
|
1414
|
+
*/
|
|
1415
|
+
setToolbarConfig(config) {
|
|
1416
|
+
this.toolbar?.setConfig(config);
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Get current toolbar configuration.
|
|
1420
|
+
*/
|
|
1421
|
+
getToolbarConfig() {
|
|
1422
|
+
return this.toolbar?.getConfig() ?? {};
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Hide a specific toolbar action by ID or alias (e.g. 'zoom-in', 'print', 'download').
|
|
1426
|
+
*/
|
|
1427
|
+
hideToolbarAction(actionId) {
|
|
1428
|
+
this.toolbar?.hideAction(actionId);
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Show a specific toolbar action by ID or alias.
|
|
1432
|
+
*/
|
|
1433
|
+
showToolbarAction(actionId) {
|
|
1434
|
+
this.toolbar?.showAction(actionId);
|
|
1435
|
+
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Enable a specific toolbar action button.
|
|
1438
|
+
*/
|
|
1439
|
+
enableToolbarAction(actionId) {
|
|
1440
|
+
this.toolbar?.enableAction(actionId);
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* Disable a specific toolbar action button.
|
|
1444
|
+
*/
|
|
1445
|
+
disableToolbarAction(actionId) {
|
|
1446
|
+
this.toolbar?.disableAction(actionId);
|
|
1447
|
+
}
|
|
1448
|
+
// --- Programmatic Toolbar Action Methods ---
|
|
1449
|
+
/**
|
|
1450
|
+
* Fit document to page so it fills the frame width with minimal margins.
|
|
1451
|
+
*/
|
|
1452
|
+
fitToPage() {
|
|
1453
|
+
this.activeInstance?.fitToPage?.();
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Zoom in.
|
|
1457
|
+
*/
|
|
1458
|
+
zoomIn() {
|
|
1459
|
+
this.activeInstance?.zoomIn?.();
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Zoom out.
|
|
1463
|
+
*/
|
|
1464
|
+
zoomOut() {
|
|
1465
|
+
this.activeInstance?.zoomOut?.();
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Set specific zoom level.
|
|
1469
|
+
*/
|
|
1470
|
+
setZoom(level) {
|
|
1471
|
+
this.activeInstance?.setZoom?.(level);
|
|
1472
|
+
}
|
|
1473
|
+
/**
|
|
1474
|
+
* Get current zoom level.
|
|
1475
|
+
*/
|
|
1476
|
+
getZoom() {
|
|
1477
|
+
return this.activeInstance?.getZoom?.() ?? 1;
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Rotate 90 degrees clockwise.
|
|
1481
|
+
*/
|
|
1482
|
+
rotateCW() {
|
|
1483
|
+
this.activeInstance?.rotateCW?.();
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Rotate 90 degrees counter-clockwise.
|
|
1487
|
+
*/
|
|
1488
|
+
rotateCCW() {
|
|
1489
|
+
this.activeInstance?.rotateCCW?.();
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Navigate to a specific page number.
|
|
1493
|
+
*/
|
|
1494
|
+
goToPage(page) {
|
|
1495
|
+
this.activeInstance?.goToPage?.(page);
|
|
1496
|
+
this.toolbar?.setPage(page);
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Navigate to next page.
|
|
1500
|
+
*/
|
|
1501
|
+
nextPage() {
|
|
1502
|
+
const cur = this.getCurrentPage();
|
|
1503
|
+
const max = this.getPageCount();
|
|
1504
|
+
if (cur < max) {
|
|
1505
|
+
this.goToPage(cur + 1);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Navigate to previous page.
|
|
1510
|
+
*/
|
|
1511
|
+
prevPage() {
|
|
1512
|
+
const cur = this.getCurrentPage();
|
|
1513
|
+
if (cur > 1) {
|
|
1514
|
+
this.goToPage(cur - 1);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Get total page count.
|
|
1519
|
+
*/
|
|
1520
|
+
getPageCount() {
|
|
1521
|
+
return this.activeInstance?.getPageCount?.() ?? 1;
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Get current page number.
|
|
1525
|
+
*/
|
|
1526
|
+
getCurrentPage() {
|
|
1527
|
+
return this.activeInstance?.getCurrentPage?.() ?? 1;
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Download the current document.
|
|
1531
|
+
*/
|
|
1532
|
+
download() {
|
|
1533
|
+
this.activeInstance?.download?.();
|
|
1534
|
+
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Print the current document.
|
|
1537
|
+
*/
|
|
1538
|
+
print() {
|
|
1539
|
+
this.activeInstance?.print?.();
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* Toggle fullscreen mode.
|
|
1543
|
+
*/
|
|
1544
|
+
toggleFullscreen() {
|
|
1545
|
+
try {
|
|
1546
|
+
if (!document.fullscreenElement) {
|
|
1547
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
1548
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
1549
|
+
} else {
|
|
1550
|
+
document.exitFullscreen?.();
|
|
1551
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
1552
|
+
}
|
|
1553
|
+
} catch {
|
|
1554
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
1555
|
+
}
|
|
1556
|
+
setTimeout(() => {
|
|
1557
|
+
this.activeInstance?.fitToPage?.();
|
|
1558
|
+
}, 120);
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Toggle thumbnails sidebar panel.
|
|
1562
|
+
*/
|
|
1563
|
+
toggleThumbnails() {
|
|
1564
|
+
if (!this.thumbnailPanel) return;
|
|
1565
|
+
this.thumbnailPanel.toggle();
|
|
1566
|
+
const isOpen = this.thumbnailPanel.isOpen();
|
|
1567
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1568
|
+
setTimeout(() => {
|
|
1569
|
+
this.activeInstance?.fitToPage?.();
|
|
1570
|
+
}, 260);
|
|
1571
|
+
}
|
|
1572
|
+
/**
|
|
1573
|
+
* Set whether to display the file name / title bar above the toolbar.
|
|
1574
|
+
*/
|
|
1575
|
+
setShowFileName(show) {
|
|
1576
|
+
if (this.currentOptions) {
|
|
1577
|
+
this.currentOptions.showFileName = show;
|
|
1578
|
+
}
|
|
1579
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Set or override the displayed file name in the preview panel.
|
|
1583
|
+
*/
|
|
1584
|
+
setFileName(name) {
|
|
1585
|
+
if (this.currentOptions) {
|
|
1586
|
+
this.currentOptions.fileName = name;
|
|
1587
|
+
}
|
|
1588
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1589
|
+
}
|
|
1136
1590
|
// --- Private methods ---
|
|
1591
|
+
updateTitleBar(options, metadata) {
|
|
1592
|
+
if (!this.titleBarEl) return;
|
|
1593
|
+
const show = options?.showFileName !== false;
|
|
1594
|
+
if (!show) {
|
|
1595
|
+
this.titleBarEl.style.display = "none";
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
const name = options?.fileName || metadata?.name || this.currentMetadata?.name || "";
|
|
1599
|
+
if (!name) {
|
|
1600
|
+
this.titleBarEl.style.display = "none";
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
this.titleBarEl.style.display = "flex";
|
|
1604
|
+
const ext = metadata?.extension || (name.includes(".") ? "." + name.split(".").pop() : "");
|
|
1605
|
+
const badge = ext ? ext.replace(".", "").toUpperCase() : "";
|
|
1606
|
+
this.titleBarEl.innerHTML = `
|
|
1607
|
+
<div class="fp-titlebar-info">
|
|
1608
|
+
<span class="fp-titlebar-icon">\u{1F4C4}</span>
|
|
1609
|
+
<span class="fp-titlebar-name" title="${name}">${name}</span>
|
|
1610
|
+
${badge ? `<span class="fp-titlebar-badge">${badge}</span>` : ""}
|
|
1611
|
+
</div>
|
|
1612
|
+
`;
|
|
1613
|
+
}
|
|
1614
|
+
extractToolbarConfig(options) {
|
|
1615
|
+
if (!options) return {};
|
|
1616
|
+
const nested = typeof options.toolbar === "object" ? options.toolbar : {};
|
|
1617
|
+
return {
|
|
1618
|
+
...options,
|
|
1619
|
+
...nested
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1137
1622
|
abort() {
|
|
1138
1623
|
if (this.abortController) {
|
|
1139
1624
|
this.abortController.abort();
|
|
@@ -1176,17 +1661,29 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1176
1661
|
bodyEl.className = "fp-body";
|
|
1177
1662
|
bodyEl.appendChild(thumbnailEl);
|
|
1178
1663
|
bodyEl.appendChild(this.contentEl);
|
|
1664
|
+
const titleBarEl = document.createElement("div");
|
|
1665
|
+
titleBarEl.className = "fp-titlebar";
|
|
1666
|
+
this.titleBarEl = titleBarEl;
|
|
1667
|
+
this.updateTitleBar(options, this.currentMetadata);
|
|
1179
1668
|
if (toolbarPos === "top") {
|
|
1669
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1180
1670
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1181
1671
|
this.wrapperEl.appendChild(bodyEl);
|
|
1182
1672
|
} else {
|
|
1673
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1183
1674
|
this.wrapperEl.appendChild(bodyEl);
|
|
1184
1675
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1185
1676
|
}
|
|
1186
1677
|
container.innerHTML = "";
|
|
1187
1678
|
container.appendChild(this.wrapperEl);
|
|
1188
|
-
|
|
1189
|
-
this.
|
|
1679
|
+
const initialToolbarConfig = this.extractToolbarConfig(options);
|
|
1680
|
+
this.toolbar = new ToolbarController(toolbarEl, initialToolbarConfig);
|
|
1681
|
+
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl, (isOpen) => {
|
|
1682
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1683
|
+
setTimeout(() => {
|
|
1684
|
+
this.activeInstance?.fitToPage?.();
|
|
1685
|
+
}, 260);
|
|
1686
|
+
});
|
|
1190
1687
|
this.setupKeyboardShortcuts();
|
|
1191
1688
|
this.setupDragAndDrop(container, options);
|
|
1192
1689
|
this.setupResizeAndFullscreenListeners();
|
|
@@ -1576,6 +2073,14 @@ var PdfPlugin = class {
|
|
|
1576
2073
|
group: "zoom",
|
|
1577
2074
|
execute: () => instance.fitToPage?.()
|
|
1578
2075
|
},
|
|
2076
|
+
{
|
|
2077
|
+
id: "fit-width",
|
|
2078
|
+
icon: "fit-width",
|
|
2079
|
+
label: "Fit to Width",
|
|
2080
|
+
type: "button",
|
|
2081
|
+
group: "zoom",
|
|
2082
|
+
execute: () => instance.fitToWidth?.()
|
|
2083
|
+
},
|
|
1579
2084
|
{
|
|
1580
2085
|
id: "rotate-cw",
|
|
1581
2086
|
icon: "rotate-cw",
|
|
@@ -1584,6 +2089,14 @@ var PdfPlugin = class {
|
|
|
1584
2089
|
group: "view",
|
|
1585
2090
|
execute: () => instance.rotateCW?.()
|
|
1586
2091
|
},
|
|
2092
|
+
{
|
|
2093
|
+
id: "rotate-ccw",
|
|
2094
|
+
icon: "rotate-ccw",
|
|
2095
|
+
label: "Rotate Counter-Clockwise",
|
|
2096
|
+
type: "button",
|
|
2097
|
+
group: "view",
|
|
2098
|
+
execute: () => instance.rotateCCW?.()
|
|
2099
|
+
},
|
|
1587
2100
|
{
|
|
1588
2101
|
id: "download",
|
|
1589
2102
|
icon: "download",
|
|
@@ -1615,12 +2128,13 @@ var PdfPlugin = class {
|
|
|
1615
2128
|
container.className = "fp-pdf-container";
|
|
1616
2129
|
container.style.width = "100%";
|
|
1617
2130
|
container.style.height = "100%";
|
|
1618
|
-
container.style.
|
|
2131
|
+
container.style.overflowX = "hidden";
|
|
2132
|
+
container.style.overflowY = "auto";
|
|
1619
2133
|
container.style.display = "flex";
|
|
1620
2134
|
container.style.flexDirection = "column";
|
|
1621
2135
|
container.style.alignItems = "center";
|
|
1622
2136
|
container.style.justifyContent = "flex-start";
|
|
1623
|
-
container.style.padding = "
|
|
2137
|
+
container.style.padding = "16px 8px";
|
|
1624
2138
|
container.style.backgroundColor = "#0f172a";
|
|
1625
2139
|
container.style.boxSizing = "border-box";
|
|
1626
2140
|
container.style.position = "relative";
|
|
@@ -1631,30 +2145,12 @@ var PdfPlugin = class {
|
|
|
1631
2145
|
pageCard.style.borderRadius = "4px";
|
|
1632
2146
|
pageCard.style.overflow = "hidden";
|
|
1633
2147
|
pageCard.style.lineHeight = "0";
|
|
1634
|
-
pageCard.style.transition = "transform 0.15s ease";
|
|
1635
2148
|
pageCard.style.position = "relative";
|
|
1636
2149
|
pageCard.style.flexShrink = "0";
|
|
2150
|
+
pageCard.style.transition = "box-shadow 0.2s ease";
|
|
1637
2151
|
let canvas = document.createElement("canvas");
|
|
1638
2152
|
pageCard.appendChild(canvas);
|
|
1639
2153
|
container.appendChild(pageCard);
|
|
1640
|
-
const indicator = document.createElement("div");
|
|
1641
|
-
indicator.className = "fp-pdf-page-indicator";
|
|
1642
|
-
indicator.style.position = "sticky";
|
|
1643
|
-
indicator.style.bottom = "16px";
|
|
1644
|
-
indicator.style.marginTop = "16px";
|
|
1645
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1646
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
1647
|
-
indicator.style.color = "#f8fafc";
|
|
1648
|
-
indicator.style.fontSize = "12px";
|
|
1649
|
-
indicator.style.fontWeight = "600";
|
|
1650
|
-
indicator.style.padding = "5px 14px";
|
|
1651
|
-
indicator.style.borderRadius = "20px";
|
|
1652
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1653
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1654
|
-
indicator.style.zIndex = "10";
|
|
1655
|
-
indicator.style.userSelect = "none";
|
|
1656
|
-
indicator.style.pointerEvents = "none";
|
|
1657
|
-
container.appendChild(indicator);
|
|
1658
2154
|
ctx.container.appendChild(container);
|
|
1659
2155
|
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1660
2156
|
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
@@ -1670,8 +2166,9 @@ var PdfPlugin = class {
|
|
|
1670
2166
|
let currentPage = 1;
|
|
1671
2167
|
let zoomScale = 1;
|
|
1672
2168
|
let rotation = 0;
|
|
1673
|
-
let fitMode = "
|
|
2169
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
1674
2170
|
let currentRenderTask = null;
|
|
2171
|
+
let textLayerDiv = null;
|
|
1675
2172
|
const renderPage = async (pageNum) => {
|
|
1676
2173
|
if (currentRenderTask) {
|
|
1677
2174
|
try {
|
|
@@ -1683,30 +2180,37 @@ var PdfPlugin = class {
|
|
|
1683
2180
|
const newCanvas = document.createElement("canvas");
|
|
1684
2181
|
pageCard.replaceChild(newCanvas, canvas);
|
|
1685
2182
|
canvas = newCanvas;
|
|
2183
|
+
if (textLayerDiv) {
|
|
2184
|
+
textLayerDiv.remove();
|
|
2185
|
+
textLayerDiv = null;
|
|
2186
|
+
}
|
|
1686
2187
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1687
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1688
2188
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1689
2189
|
const page = await pdfDoc.getPage(currentPage);
|
|
1690
2190
|
const containerWidth = container.clientWidth || 900;
|
|
1691
2191
|
const containerHeight = container.clientHeight || 700;
|
|
1692
2192
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1693
|
-
const availWidth = Math.max(
|
|
1694
|
-
const availHeight = Math.max(
|
|
2193
|
+
const availWidth = Math.max(280, containerWidth - 36);
|
|
2194
|
+
const availHeight = Math.max(280, containerHeight - 32);
|
|
1695
2195
|
const scaleW = availWidth / unscaledVp.width;
|
|
1696
2196
|
const scaleH = availHeight / unscaledVp.height;
|
|
1697
2197
|
let fitScale;
|
|
1698
2198
|
if (fitMode === "page") {
|
|
1699
|
-
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
2199
|
+
fitScale = Math.max(0.2, Math.min(4, Math.min(scaleW, scaleH)));
|
|
1700
2200
|
} else {
|
|
1701
|
-
fitScale = Math.max(0.
|
|
2201
|
+
fitScale = Math.max(0.2, Math.min(4, scaleW));
|
|
1702
2202
|
}
|
|
1703
2203
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1704
2204
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1705
2205
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
2206
|
+
const displayWidth = Math.floor(viewport.width);
|
|
2207
|
+
const displayHeight = Math.floor(viewport.height);
|
|
1706
2208
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1707
2209
|
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1708
|
-
canvas.style.width = `${
|
|
1709
|
-
canvas.style.height = `${
|
|
2210
|
+
canvas.style.width = `${displayWidth}px`;
|
|
2211
|
+
canvas.style.height = `${displayHeight}px`;
|
|
2212
|
+
pageCard.style.width = `${displayWidth}px`;
|
|
2213
|
+
pageCard.style.height = `${displayHeight}px`;
|
|
1710
2214
|
const canvasCtx = canvas.getContext("2d");
|
|
1711
2215
|
if (!canvasCtx) return;
|
|
1712
2216
|
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
@@ -1720,9 +2224,31 @@ var PdfPlugin = class {
|
|
|
1720
2224
|
if (err?.name !== "RenderingCancelledException") {
|
|
1721
2225
|
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1722
2226
|
}
|
|
2227
|
+
return;
|
|
1723
2228
|
} finally {
|
|
1724
2229
|
currentRenderTask = null;
|
|
1725
2230
|
}
|
|
2231
|
+
try {
|
|
2232
|
+
textLayerDiv = document.createElement("div");
|
|
2233
|
+
textLayerDiv.className = "textLayer";
|
|
2234
|
+
textLayerDiv.style.width = `${displayWidth}px`;
|
|
2235
|
+
textLayerDiv.style.height = `${displayHeight}px`;
|
|
2236
|
+
textLayerDiv.style.position = "absolute";
|
|
2237
|
+
textLayerDiv.style.top = "0";
|
|
2238
|
+
textLayerDiv.style.left = "0";
|
|
2239
|
+
textLayerDiv.style.lineHeight = "1";
|
|
2240
|
+
pageCard.appendChild(textLayerDiv);
|
|
2241
|
+
if (pdfjsLib__namespace.TextLayer) {
|
|
2242
|
+
const textLayer = new pdfjsLib__namespace.TextLayer({
|
|
2243
|
+
textContentSource: page.streamTextContent(),
|
|
2244
|
+
container: textLayerDiv,
|
|
2245
|
+
viewport
|
|
2246
|
+
});
|
|
2247
|
+
await textLayer.render();
|
|
2248
|
+
}
|
|
2249
|
+
} catch (err) {
|
|
2250
|
+
console.debug("[PdfPlugin] TextLayer notice:", err);
|
|
2251
|
+
}
|
|
1726
2252
|
};
|
|
1727
2253
|
renderPage(1);
|
|
1728
2254
|
let resizeTimer = null;
|
|
@@ -1732,11 +2258,48 @@ var PdfPlugin = class {
|
|
|
1732
2258
|
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1733
2259
|
renderPage(currentPage);
|
|
1734
2260
|
}
|
|
1735
|
-
},
|
|
2261
|
+
}, 120);
|
|
1736
2262
|
});
|
|
1737
2263
|
resizeObserver.observe(container);
|
|
2264
|
+
const onWheel = (e) => {
|
|
2265
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2266
|
+
e.preventDefault();
|
|
2267
|
+
const delta = e.deltaY > 0 ? -0.15 : 0.15;
|
|
2268
|
+
zoomScale = Math.max(0.25, Math.min(4, Math.round((zoomScale + delta) * 100) / 100));
|
|
2269
|
+
renderPage(currentPage);
|
|
2270
|
+
}
|
|
2271
|
+
};
|
|
2272
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
2273
|
+
const onKeyDown = (e) => {
|
|
2274
|
+
const tag = e.target?.tagName?.toLowerCase();
|
|
2275
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
2276
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
2277
|
+
if (currentPage < totalPages) {
|
|
2278
|
+
e.preventDefault();
|
|
2279
|
+
container.scrollTop = 0;
|
|
2280
|
+
renderPage(currentPage + 1);
|
|
2281
|
+
}
|
|
2282
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
2283
|
+
if (currentPage > 1) {
|
|
2284
|
+
e.preventDefault();
|
|
2285
|
+
container.scrollTop = 0;
|
|
2286
|
+
renderPage(currentPage - 1);
|
|
2287
|
+
}
|
|
2288
|
+
} else if (e.key === "Home") {
|
|
2289
|
+
e.preventDefault();
|
|
2290
|
+
container.scrollTop = 0;
|
|
2291
|
+
renderPage(1);
|
|
2292
|
+
} else if (e.key === "End") {
|
|
2293
|
+
e.preventDefault();
|
|
2294
|
+
container.scrollTop = 0;
|
|
2295
|
+
renderPage(totalPages);
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1738
2299
|
const cleanup = () => {
|
|
1739
2300
|
resizeObserver.disconnect();
|
|
2301
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2302
|
+
container.removeEventListener("wheel", onWheel);
|
|
1740
2303
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1741
2304
|
if (currentRenderTask) {
|
|
1742
2305
|
try {
|
|
@@ -1755,22 +2318,26 @@ var PdfPlugin = class {
|
|
|
1755
2318
|
const instance = {
|
|
1756
2319
|
destroy: cleanup,
|
|
1757
2320
|
zoomIn: () => {
|
|
1758
|
-
zoomScale = Math.min(
|
|
2321
|
+
zoomScale = Math.min(4, Math.round((zoomScale + 0.2) * 10) / 10);
|
|
1759
2322
|
renderPage(currentPage);
|
|
1760
2323
|
},
|
|
1761
2324
|
zoomOut: () => {
|
|
1762
|
-
zoomScale = Math.max(0.
|
|
2325
|
+
zoomScale = Math.max(0.25, Math.round((zoomScale - 0.2) * 10) / 10);
|
|
1763
2326
|
renderPage(currentPage);
|
|
1764
2327
|
},
|
|
1765
2328
|
getZoom: () => zoomScale,
|
|
1766
2329
|
setZoom: (level) => {
|
|
1767
|
-
zoomScale = Math.max(0.
|
|
2330
|
+
zoomScale = Math.max(0.25, Math.min(4, level));
|
|
1768
2331
|
renderPage(currentPage);
|
|
1769
2332
|
},
|
|
1770
2333
|
fitToPage: () => {
|
|
1771
|
-
fitMode =
|
|
2334
|
+
fitMode = "page";
|
|
2335
|
+
zoomScale = 1;
|
|
2336
|
+
renderPage(currentPage);
|
|
2337
|
+
},
|
|
2338
|
+
fitToWidth: () => {
|
|
2339
|
+
fitMode = "width";
|
|
1772
2340
|
zoomScale = 1;
|
|
1773
|
-
rotation = 0;
|
|
1774
2341
|
renderPage(currentPage);
|
|
1775
2342
|
},
|
|
1776
2343
|
rotateCW: () => {
|
|
@@ -1788,6 +2355,9 @@ var PdfPlugin = class {
|
|
|
1788
2355
|
container.scrollTop = 0;
|
|
1789
2356
|
renderPage(page);
|
|
1790
2357
|
},
|
|
2358
|
+
toggleThumbnails: () => {
|
|
2359
|
+
ctx?.toggleThumbnails?.();
|
|
2360
|
+
},
|
|
1791
2361
|
download: () => {
|
|
1792
2362
|
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1793
2363
|
const url = URL.createObjectURL(blob);
|
|
@@ -1821,7 +2391,7 @@ var PdfPlugin = class {
|
|
|
1821
2391
|
},
|
|
1822
2392
|
getThumbnails: async () => {
|
|
1823
2393
|
const thumbnails = [];
|
|
1824
|
-
const count =
|
|
2394
|
+
const count = totalPages;
|
|
1825
2395
|
for (let i = 1; i <= count; i++) {
|
|
1826
2396
|
thumbnails.push({
|
|
1827
2397
|
index: i,
|
|
@@ -1829,9 +2399,10 @@ var PdfPlugin = class {
|
|
|
1829
2399
|
render: async (thumbCanvas) => {
|
|
1830
2400
|
try {
|
|
1831
2401
|
const p = await pdfDoc.getPage(i);
|
|
1832
|
-
const baseVp = p.getViewport({ scale: 1 });
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
2402
|
+
const baseVp = p.getViewport({ scale: 1, rotation });
|
|
2403
|
+
const targetW = thumbCanvas.width || 130;
|
|
2404
|
+
const thumbScale = targetW / baseVp.width;
|
|
2405
|
+
const thumbVp = p.getViewport({ scale: thumbScale, rotation });
|
|
1835
2406
|
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1836
2407
|
const tCtx = thumbCanvas.getContext("2d");
|
|
1837
2408
|
if (tCtx) {
|
|
@@ -2175,28 +2746,26 @@ var DocxPlugin = class {
|
|
|
2175
2746
|
getToolbarActions(instance) {
|
|
2176
2747
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2177
2748
|
const actions = [];
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
if (
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
instance.goToPage?.(page);
|
|
2196
|
-
}
|
|
2749
|
+
actions.push({
|
|
2750
|
+
id: "page-nav",
|
|
2751
|
+
icon: "",
|
|
2752
|
+
label: "Page Navigation",
|
|
2753
|
+
type: "page-nav",
|
|
2754
|
+
group: "navigation",
|
|
2755
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2756
|
+
max: totalPages,
|
|
2757
|
+
execute: (action, page) => {
|
|
2758
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2759
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2760
|
+
if (action === "prev") {
|
|
2761
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2762
|
+
} else if (action === "next") {
|
|
2763
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2764
|
+
} else if (typeof page === "number") {
|
|
2765
|
+
instance.goToPage?.(page);
|
|
2197
2766
|
}
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2767
|
+
}
|
|
2768
|
+
});
|
|
2200
2769
|
actions.push(
|
|
2201
2770
|
{
|
|
2202
2771
|
id: "zoom-out",
|
|
@@ -2262,11 +2831,17 @@ var DocxPlugin = class {
|
|
|
2262
2831
|
wrapper.className = "fp-docx-wrapper";
|
|
2263
2832
|
wrapper.style.transformOrigin = "top center";
|
|
2264
2833
|
wrapper.style.transition = "transform 0.2s ease";
|
|
2265
|
-
wrapper.style.padding = "
|
|
2266
|
-
wrapper.style.maxWidth = "
|
|
2834
|
+
wrapper.style.padding = "0";
|
|
2835
|
+
wrapper.style.maxWidth = "none";
|
|
2836
|
+
wrapper.style.width = "816px";
|
|
2267
2837
|
wrapper.style.margin = "0 auto";
|
|
2838
|
+
wrapper.style.display = "flex";
|
|
2839
|
+
wrapper.style.flexDirection = "column";
|
|
2840
|
+
wrapper.style.alignItems = "center";
|
|
2268
2841
|
wrapper.style.boxSizing = "border-box";
|
|
2269
|
-
ctx.container.style.
|
|
2842
|
+
ctx.container.style.overflowX = "hidden";
|
|
2843
|
+
ctx.container.style.overflowY = "auto";
|
|
2844
|
+
ctx.container.style.padding = "16px 8px";
|
|
2270
2845
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
2271
2846
|
ctx.container.appendChild(wrapper);
|
|
2272
2847
|
const styleOverride = document.createElement("style");
|
|
@@ -2440,39 +3015,13 @@ var DocxPlugin = class {
|
|
|
2440
3015
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2441
3016
|
const totalPages = Math.max(1, pageElements.length);
|
|
2442
3017
|
let currentPage = 1;
|
|
2443
|
-
let indicator = null;
|
|
2444
|
-
if (totalPages > 1) {
|
|
2445
|
-
indicator = document.createElement("div");
|
|
2446
|
-
indicator.className = "fp-docx-page-indicator";
|
|
2447
|
-
indicator.style.position = "sticky";
|
|
2448
|
-
indicator.style.bottom = "16px";
|
|
2449
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2450
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
2451
|
-
indicator.style.color = "#f8fafc";
|
|
2452
|
-
indicator.style.fontSize = "12px";
|
|
2453
|
-
indicator.style.fontWeight = "600";
|
|
2454
|
-
indicator.style.padding = "5px 14px";
|
|
2455
|
-
indicator.style.borderRadius = "20px";
|
|
2456
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2457
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2458
|
-
indicator.style.zIndex = "10";
|
|
2459
|
-
indicator.style.userSelect = "none";
|
|
2460
|
-
indicator.style.pointerEvents = "none";
|
|
2461
|
-
indicator.style.textAlign = "center";
|
|
2462
|
-
indicator.style.width = "fit-content";
|
|
2463
|
-
indicator.style.margin = "16px auto 0";
|
|
2464
|
-
ctx.container.appendChild(indicator);
|
|
2465
|
-
}
|
|
2466
3018
|
const showPage = (pageNum) => {
|
|
2467
3019
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2468
3020
|
if (pageElements.length > 1) {
|
|
2469
3021
|
pageElements.forEach((sec, idx) => {
|
|
2470
|
-
sec.style.display = idx + 1 === currentPage ? "
|
|
3022
|
+
sec.style.display = idx + 1 === currentPage ? "" : "none";
|
|
2471
3023
|
});
|
|
2472
3024
|
}
|
|
2473
|
-
if (indicator) {
|
|
2474
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2475
|
-
}
|
|
2476
3025
|
ctx.container.scrollTop = 0;
|
|
2477
3026
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2478
3027
|
};
|
|
@@ -2481,31 +3030,46 @@ var DocxPlugin = class {
|
|
|
2481
3030
|
}
|
|
2482
3031
|
scale = 1;
|
|
2483
3032
|
let rotation = 0;
|
|
2484
|
-
let fitMode = "
|
|
2485
|
-
|
|
2486
|
-
|
|
3033
|
+
let fitMode = "page";
|
|
3034
|
+
let isUserZoomed = false;
|
|
3035
|
+
const calculateFitScale = (_mode = fitMode) => {
|
|
3036
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2487
3037
|
const elW = activeEl.offsetWidth || 816;
|
|
2488
|
-
const
|
|
2489
|
-
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2490
|
-
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
3038
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
2491
3039
|
const sW = availW / elW;
|
|
2492
|
-
|
|
2493
|
-
if (mode === "page") {
|
|
2494
|
-
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2495
|
-
}
|
|
2496
|
-
return Math.max(0.65, Math.min(1.05, sW));
|
|
3040
|
+
return Math.max(0.35, Math.min(3, sW));
|
|
2497
3041
|
};
|
|
2498
3042
|
const applyTransform = () => {
|
|
2499
3043
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2500
3044
|
wrapper.style.transformOrigin = "top center";
|
|
3045
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
3046
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
3047
|
+
if (scale > 1) {
|
|
3048
|
+
wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
|
|
3049
|
+
} else {
|
|
3050
|
+
wrapper.style.marginBottom = "32px";
|
|
3051
|
+
}
|
|
2501
3052
|
};
|
|
3053
|
+
let resizeObserver = null;
|
|
3054
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
3055
|
+
resizeObserver = new ResizeObserver(() => {
|
|
3056
|
+
if (!isUserZoomed) {
|
|
3057
|
+
const newFit = calculateFitScale("page");
|
|
3058
|
+
if (Math.abs(scale - newFit) > 0.015) {
|
|
3059
|
+
scale = newFit;
|
|
3060
|
+
applyTransform();
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
});
|
|
3064
|
+
resizeObserver.observe(ctx.container);
|
|
3065
|
+
}
|
|
2502
3066
|
setTimeout(() => {
|
|
2503
|
-
|
|
2504
|
-
scale = calculateFitScale("width");
|
|
3067
|
+
scale = calculateFitScale("page");
|
|
2505
3068
|
applyTransform();
|
|
2506
|
-
},
|
|
3069
|
+
}, 40);
|
|
2507
3070
|
const cleanup = () => {
|
|
2508
|
-
|
|
3071
|
+
resizeObserver?.disconnect();
|
|
3072
|
+
resizeObserver = null;
|
|
2509
3073
|
for (const url of createdBlobUrls) {
|
|
2510
3074
|
URL.revokeObjectURL(url);
|
|
2511
3075
|
}
|
|
@@ -2522,21 +3086,24 @@ var DocxPlugin = class {
|
|
|
2522
3086
|
showPage(page);
|
|
2523
3087
|
},
|
|
2524
3088
|
zoomIn: () => {
|
|
2525
|
-
|
|
3089
|
+
isUserZoomed = true;
|
|
3090
|
+
scale = Math.min(3.5, scale + 0.15);
|
|
2526
3091
|
applyTransform();
|
|
2527
3092
|
},
|
|
2528
3093
|
zoomOut: () => {
|
|
3094
|
+
isUserZoomed = true;
|
|
2529
3095
|
scale = Math.max(0.2, scale - 0.15);
|
|
2530
3096
|
applyTransform();
|
|
2531
3097
|
},
|
|
2532
3098
|
getZoom: () => scale,
|
|
2533
3099
|
setZoom: (level) => {
|
|
3100
|
+
isUserZoomed = true;
|
|
2534
3101
|
scale = level;
|
|
2535
3102
|
applyTransform();
|
|
2536
3103
|
},
|
|
2537
3104
|
fitToPage: () => {
|
|
2538
|
-
|
|
2539
|
-
scale = calculateFitScale(
|
|
3105
|
+
isUserZoomed = false;
|
|
3106
|
+
scale = calculateFitScale("page");
|
|
2540
3107
|
rotation = 0;
|
|
2541
3108
|
applyTransform();
|
|
2542
3109
|
},
|
|
@@ -2926,7 +3493,7 @@ var ExcelPlugin = class {
|
|
|
2926
3493
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
2927
3494
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
2928
3495
|
];
|
|
2929
|
-
weight =
|
|
3496
|
+
weight = 85;
|
|
2930
3497
|
supports(file) {
|
|
2931
3498
|
const ext = file.metadata.extension?.toLowerCase();
|
|
2932
3499
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
@@ -2938,6 +3505,14 @@ var ExcelPlugin = class {
|
|
|
2938
3505
|
getToolbarActions(instance) {
|
|
2939
3506
|
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2940
3507
|
const actions = [];
|
|
3508
|
+
actions.push({
|
|
3509
|
+
id: "thumbnails",
|
|
3510
|
+
icon: "thumbnails",
|
|
3511
|
+
label: "Sheet Thumbnails",
|
|
3512
|
+
type: "button",
|
|
3513
|
+
group: "navigation",
|
|
3514
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3515
|
+
});
|
|
2941
3516
|
if (totalSheets > 1) {
|
|
2942
3517
|
actions.push({
|
|
2943
3518
|
id: "page-nav",
|
|
@@ -3020,6 +3595,16 @@ var ExcelPlugin = class {
|
|
|
3020
3595
|
execute: () => {
|
|
3021
3596
|
instance.print?.();
|
|
3022
3597
|
}
|
|
3598
|
+
},
|
|
3599
|
+
{
|
|
3600
|
+
id: "open-window",
|
|
3601
|
+
icon: "open-window",
|
|
3602
|
+
label: "Open in Separate Full Window",
|
|
3603
|
+
type: "button",
|
|
3604
|
+
group: "actions",
|
|
3605
|
+
execute: () => {
|
|
3606
|
+
instance.openInSeparateWindow?.();
|
|
3607
|
+
}
|
|
3023
3608
|
}
|
|
3024
3609
|
);
|
|
3025
3610
|
return actions;
|
|
@@ -3185,6 +3770,63 @@ var ExcelPlugin = class {
|
|
|
3185
3770
|
},
|
|
3186
3771
|
getPageCount: () => sheetNames.length,
|
|
3187
3772
|
getCurrentPage: () => currentSheetIndex,
|
|
3773
|
+
getThumbnails: () => {
|
|
3774
|
+
return sheetNames.map((name, idx) => ({
|
|
3775
|
+
index: idx,
|
|
3776
|
+
label: name,
|
|
3777
|
+
render: async (canvas) => {
|
|
3778
|
+
canvas.width = 140;
|
|
3779
|
+
canvas.height = 100;
|
|
3780
|
+
const c = canvas.getContext("2d");
|
|
3781
|
+
if (!c) return;
|
|
3782
|
+
c.fillStyle = "#ffffff";
|
|
3783
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3784
|
+
c.fillStyle = "#107c41";
|
|
3785
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3786
|
+
c.fillStyle = "#ffffff";
|
|
3787
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
3788
|
+
c.fillText(`\u{1F4CA} ${name.slice(0, 16)}`, 6, 11);
|
|
3789
|
+
const startY = 17;
|
|
3790
|
+
const rowH = 13;
|
|
3791
|
+
const colW = 30;
|
|
3792
|
+
const colHeaders = ["A", "B", "C", "D"];
|
|
3793
|
+
c.fillStyle = "#f1f5f9";
|
|
3794
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3795
|
+
c.strokeStyle = "#cbd5e1";
|
|
3796
|
+
c.lineWidth = 0.8;
|
|
3797
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3798
|
+
c.fillStyle = "#64748b";
|
|
3799
|
+
c.font = "bold 7px sans-serif";
|
|
3800
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3801
|
+
c.fillText(colHeaders[ci], 14 + ci * colW, startY + 9);
|
|
3802
|
+
}
|
|
3803
|
+
const ws = wb?.Sheets[name];
|
|
3804
|
+
for (let ri = 1; ri <= 5; ri++) {
|
|
3805
|
+
const y = startY + ri * rowH;
|
|
3806
|
+
if (y > canvas.height - 2) break;
|
|
3807
|
+
c.fillStyle = "#f8fafc";
|
|
3808
|
+
c.fillRect(0, y, 12, rowH);
|
|
3809
|
+
c.fillStyle = "#94a3b8";
|
|
3810
|
+
c.font = "6px sans-serif";
|
|
3811
|
+
c.fillText(String(ri), 3, y + 9);
|
|
3812
|
+
c.strokeStyle = "#e2e8f0";
|
|
3813
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3814
|
+
c.fillStyle = "#334155";
|
|
3815
|
+
c.font = "6px sans-serif";
|
|
3816
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3817
|
+
const cellRef = `${colHeaders[ci]}${ri}`;
|
|
3818
|
+
const cellVal = ws?.[cellRef]?.w || ws?.[cellRef]?.v;
|
|
3819
|
+
if (cellVal !== void 0) {
|
|
3820
|
+
c.fillText(String(cellVal).slice(0, 6), 14 + ci * colW, y + 9);
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
c.strokeStyle = "#cbd5e1";
|
|
3825
|
+
c.lineWidth = 1;
|
|
3826
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
3827
|
+
}
|
|
3828
|
+
}));
|
|
3829
|
+
},
|
|
3188
3830
|
download: () => {
|
|
3189
3831
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
3190
3832
|
const url = URL.createObjectURL(blob);
|
|
@@ -3217,7 +3859,39 @@ var CsvPlugin = class {
|
|
|
3217
3859
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3218
3860
|
}
|
|
3219
3861
|
getToolbarActions(instance) {
|
|
3220
|
-
|
|
3862
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3863
|
+
const actions = [];
|
|
3864
|
+
actions.push({
|
|
3865
|
+
id: "thumbnails",
|
|
3866
|
+
icon: "thumbnails",
|
|
3867
|
+
label: "Page Thumbnails",
|
|
3868
|
+
type: "button",
|
|
3869
|
+
group: "navigation",
|
|
3870
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3871
|
+
});
|
|
3872
|
+
if (totalPages > 1) {
|
|
3873
|
+
actions.push({
|
|
3874
|
+
id: "page-nav",
|
|
3875
|
+
icon: "",
|
|
3876
|
+
label: "Page Navigation",
|
|
3877
|
+
type: "page-nav",
|
|
3878
|
+
group: "navigation",
|
|
3879
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3880
|
+
max: totalPages,
|
|
3881
|
+
execute: (action, page) => {
|
|
3882
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3883
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3884
|
+
if (action === "prev") {
|
|
3885
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3886
|
+
} else if (action === "next") {
|
|
3887
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3888
|
+
} else if (typeof page === "number") {
|
|
3889
|
+
instance.goToPage?.(page);
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
});
|
|
3893
|
+
}
|
|
3894
|
+
actions.push(
|
|
3221
3895
|
{
|
|
3222
3896
|
id: "zoom-out",
|
|
3223
3897
|
icon: "zoom-out",
|
|
@@ -3238,6 +3912,16 @@ var CsvPlugin = class {
|
|
|
3238
3912
|
instance.zoomIn?.();
|
|
3239
3913
|
}
|
|
3240
3914
|
},
|
|
3915
|
+
{
|
|
3916
|
+
id: "fit-page",
|
|
3917
|
+
icon: "fit-page",
|
|
3918
|
+
label: "Fit to View",
|
|
3919
|
+
type: "button",
|
|
3920
|
+
group: "zoom",
|
|
3921
|
+
execute: () => {
|
|
3922
|
+
instance.fitToPage?.();
|
|
3923
|
+
}
|
|
3924
|
+
},
|
|
3241
3925
|
{
|
|
3242
3926
|
id: "download",
|
|
3243
3927
|
icon: "download",
|
|
@@ -3257,8 +3941,19 @@ var CsvPlugin = class {
|
|
|
3257
3941
|
execute: () => {
|
|
3258
3942
|
instance.print?.();
|
|
3259
3943
|
}
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
id: "open-window",
|
|
3947
|
+
icon: "open-window",
|
|
3948
|
+
label: "Open in Separate Full Window",
|
|
3949
|
+
type: "button",
|
|
3950
|
+
group: "actions",
|
|
3951
|
+
execute: () => {
|
|
3952
|
+
instance.openInSeparateWindow?.();
|
|
3953
|
+
}
|
|
3260
3954
|
}
|
|
3261
|
-
|
|
3955
|
+
);
|
|
3956
|
+
return actions;
|
|
3262
3957
|
}
|
|
3263
3958
|
async render(ctx) {
|
|
3264
3959
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -3270,33 +3965,62 @@ var CsvPlugin = class {
|
|
|
3270
3965
|
container.style.padding = "16px";
|
|
3271
3966
|
container.style.boxSizing = "border-box";
|
|
3272
3967
|
container.style.transformOrigin = "top left";
|
|
3968
|
+
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
3969
|
+
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
3970
|
+
const headerLine = allLines[0] || "";
|
|
3971
|
+
const headerCells = headerLine.split(delimiter);
|
|
3972
|
+
const dataLines = allLines.slice(1);
|
|
3973
|
+
const ROWS_PER_PAGE = 100;
|
|
3974
|
+
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
3975
|
+
let currentPage = 1;
|
|
3273
3976
|
const table = document.createElement("table");
|
|
3274
3977
|
table.style.borderCollapse = "collapse";
|
|
3275
3978
|
table.style.width = "100%";
|
|
3276
|
-
table.style.fontFamily = "monospace
|
|
3979
|
+
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3277
3980
|
table.style.fontSize = "13px";
|
|
3278
|
-
const
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
td.style.fontWeight = "bold";
|
|
3292
|
-
}
|
|
3293
|
-
tr.appendChild(td);
|
|
3981
|
+
const renderPage = (pageNum) => {
|
|
3982
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3983
|
+
table.innerHTML = "";
|
|
3984
|
+
const headerTr = document.createElement("tr");
|
|
3985
|
+
headerCells.forEach((cell) => {
|
|
3986
|
+
const th = document.createElement("th");
|
|
3987
|
+
th.textContent = cell.trim();
|
|
3988
|
+
th.style.border = "1px solid #d0d7de";
|
|
3989
|
+
th.style.padding = "8px 12px";
|
|
3990
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
3991
|
+
th.style.fontWeight = "600";
|
|
3992
|
+
th.style.whiteSpace = "nowrap";
|
|
3993
|
+
headerTr.appendChild(th);
|
|
3294
3994
|
});
|
|
3295
|
-
table.appendChild(
|
|
3296
|
-
|
|
3995
|
+
table.appendChild(headerTr);
|
|
3996
|
+
const start = (currentPage - 1) * ROWS_PER_PAGE;
|
|
3997
|
+
const end = Math.min(dataLines.length, start + ROWS_PER_PAGE);
|
|
3998
|
+
const pageRows = dataLines.slice(start, end);
|
|
3999
|
+
pageRows.forEach((row, idx) => {
|
|
4000
|
+
const tr = document.createElement("tr");
|
|
4001
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
4002
|
+
const cells = row.split(delimiter);
|
|
4003
|
+
cells.forEach((cell) => {
|
|
4004
|
+
const td = document.createElement("td");
|
|
4005
|
+
td.textContent = cell.trim();
|
|
4006
|
+
td.style.border = "1px solid #d0d7de";
|
|
4007
|
+
td.style.padding = "6px 12px";
|
|
4008
|
+
td.style.whiteSpace = "nowrap";
|
|
4009
|
+
tr.appendChild(td);
|
|
4010
|
+
});
|
|
4011
|
+
table.appendChild(tr);
|
|
4012
|
+
});
|
|
4013
|
+
container.scrollTop = 0;
|
|
4014
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4015
|
+
};
|
|
4016
|
+
renderPage(1);
|
|
3297
4017
|
container.appendChild(table);
|
|
3298
4018
|
ctx.container.appendChild(container);
|
|
3299
4019
|
let scale = 1;
|
|
4020
|
+
const applyScale = () => {
|
|
4021
|
+
container.style.transform = `scale(${scale})`;
|
|
4022
|
+
container.style.transformOrigin = "top left";
|
|
4023
|
+
};
|
|
3300
4024
|
const cleanup = () => {
|
|
3301
4025
|
container.remove();
|
|
3302
4026
|
ctx.container.innerHTML = "";
|
|
@@ -3304,22 +4028,86 @@ var CsvPlugin = class {
|
|
|
3304
4028
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3305
4029
|
return {
|
|
3306
4030
|
destroy: cleanup,
|
|
4031
|
+
getPageCount: () => totalPages,
|
|
4032
|
+
getCurrentPage: () => currentPage,
|
|
4033
|
+
goToPage: (page) => renderPage(page),
|
|
4034
|
+
getThumbnails: () => {
|
|
4035
|
+
const thumbnails = [];
|
|
4036
|
+
for (let i = 0; i < totalPages; i++) {
|
|
4037
|
+
const pageIdx = i;
|
|
4038
|
+
const startRow = pageIdx * ROWS_PER_PAGE + 1;
|
|
4039
|
+
const endRow = Math.min(dataLines.length, (pageIdx + 1) * ROWS_PER_PAGE);
|
|
4040
|
+
const label = totalPages === 1 ? "Table" : `Page ${pageIdx + 1} (${startRow}-${endRow})`;
|
|
4041
|
+
thumbnails.push({
|
|
4042
|
+
index: pageIdx,
|
|
4043
|
+
label,
|
|
4044
|
+
render: async (canvas) => {
|
|
4045
|
+
canvas.width = 140;
|
|
4046
|
+
canvas.height = 100;
|
|
4047
|
+
const c = canvas.getContext("2d");
|
|
4048
|
+
if (!c) return;
|
|
4049
|
+
c.fillStyle = "#ffffff";
|
|
4050
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4051
|
+
c.fillStyle = "#2563eb";
|
|
4052
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
4053
|
+
c.fillStyle = "#ffffff";
|
|
4054
|
+
c.font = "bold 8px sans-serif";
|
|
4055
|
+
c.fillText(`\u{1F4C8} ${label.slice(0, 18)}`, 6, 11);
|
|
4056
|
+
const startY = 17;
|
|
4057
|
+
const rowH = 13;
|
|
4058
|
+
const colW = 28;
|
|
4059
|
+
const cols = Math.min(4, headerCells.length || 4);
|
|
4060
|
+
c.fillStyle = "#f1f5f9";
|
|
4061
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
4062
|
+
c.strokeStyle = "#cbd5e1";
|
|
4063
|
+
c.lineWidth = 0.8;
|
|
4064
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
4065
|
+
c.fillStyle = "#64748b";
|
|
4066
|
+
c.font = "bold 7px sans-serif";
|
|
4067
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4068
|
+
const hName = headerCells[ci] || `Col ${ci + 1}`;
|
|
4069
|
+
c.fillText(hName.slice(0, 5), 8 + ci * colW, startY + 9);
|
|
4070
|
+
}
|
|
4071
|
+
const rowsToPreview = dataLines.slice(pageIdx * ROWS_PER_PAGE, pageIdx * ROWS_PER_PAGE + 5);
|
|
4072
|
+
for (let ri = 0; ri < rowsToPreview.length; ri++) {
|
|
4073
|
+
const y = startY + (ri + 1) * rowH;
|
|
4074
|
+
if (y > canvas.height - 2) break;
|
|
4075
|
+
c.strokeStyle = "#e2e8f0";
|
|
4076
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
4077
|
+
const cVals = rowsToPreview[ri].split(delimiter);
|
|
4078
|
+
c.fillStyle = "#334155";
|
|
4079
|
+
c.font = "6px sans-serif";
|
|
4080
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4081
|
+
const val = cVals[ci] || "";
|
|
4082
|
+
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
c.strokeStyle = "#cbd5e1";
|
|
4086
|
+
c.lineWidth = 1;
|
|
4087
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4088
|
+
}
|
|
4089
|
+
});
|
|
4090
|
+
}
|
|
4091
|
+
return thumbnails;
|
|
4092
|
+
},
|
|
3307
4093
|
zoomIn: () => {
|
|
3308
4094
|
scale += 0.1;
|
|
3309
|
-
|
|
4095
|
+
applyScale();
|
|
3310
4096
|
},
|
|
3311
4097
|
zoomOut: () => {
|
|
3312
4098
|
scale = Math.max(0.2, scale - 0.1);
|
|
3313
|
-
|
|
4099
|
+
applyScale();
|
|
3314
4100
|
},
|
|
3315
4101
|
getZoom: () => scale,
|
|
3316
4102
|
setZoom: (level) => {
|
|
3317
4103
|
scale = level;
|
|
3318
|
-
|
|
4104
|
+
applyScale();
|
|
3319
4105
|
},
|
|
3320
4106
|
fitToPage: () => {
|
|
3321
|
-
|
|
3322
|
-
|
|
4107
|
+
const availW = Math.max(280, (ctx.container.clientWidth || window.innerWidth) - 48);
|
|
4108
|
+
const tW = table.offsetWidth || 600;
|
|
4109
|
+
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4110
|
+
applyScale();
|
|
3323
4111
|
},
|
|
3324
4112
|
download: () => {
|
|
3325
4113
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
@@ -3383,28 +4171,34 @@ var CodePlugin = class {
|
|
|
3383
4171
|
getToolbarActions(instance) {
|
|
3384
4172
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3385
4173
|
const actions = [];
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
4174
|
+
actions.push({
|
|
4175
|
+
id: "thumbnails",
|
|
4176
|
+
icon: "thumbnails",
|
|
4177
|
+
label: "Page Thumbnails",
|
|
4178
|
+
type: "button",
|
|
4179
|
+
group: "navigation",
|
|
4180
|
+
execute: () => instance.toggleThumbnails?.()
|
|
4181
|
+
});
|
|
4182
|
+
actions.push({
|
|
4183
|
+
id: "page-nav",
|
|
4184
|
+
icon: "",
|
|
4185
|
+
label: "Page Navigation",
|
|
4186
|
+
type: "page-nav",
|
|
4187
|
+
group: "navigation",
|
|
4188
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4189
|
+
max: totalPages,
|
|
4190
|
+
execute: (action, page) => {
|
|
4191
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4192
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4193
|
+
if (action === "prev") {
|
|
4194
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4195
|
+
} else if (action === "next") {
|
|
4196
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4197
|
+
} else if (typeof page === "number") {
|
|
4198
|
+
instance.goToPage?.(page);
|
|
3405
4199
|
}
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
4200
|
+
}
|
|
4201
|
+
});
|
|
3408
4202
|
actions.push(
|
|
3409
4203
|
{
|
|
3410
4204
|
id: "zoom-out",
|
|
@@ -3548,16 +4342,19 @@ var CodePlugin = class {
|
|
|
3548
4342
|
let fontSize = 13;
|
|
3549
4343
|
let rotation = 0;
|
|
3550
4344
|
let zoomLevel = 1;
|
|
4345
|
+
let isUserZoomed = false;
|
|
3551
4346
|
const pre = document.createElement("pre");
|
|
3552
4347
|
const code = document.createElement("code");
|
|
3553
4348
|
if (isTxt) {
|
|
4349
|
+
container.style.overflowX = "hidden";
|
|
4350
|
+
container.style.overflowY = "auto";
|
|
3554
4351
|
container.style.backgroundColor = "#f1f5f9";
|
|
3555
|
-
container.style.padding = "
|
|
4352
|
+
container.style.padding = "16px 8px";
|
|
3556
4353
|
container.style.boxSizing = "border-box";
|
|
3557
4354
|
container.style.display = "flex";
|
|
3558
4355
|
container.style.flexDirection = "column";
|
|
3559
4356
|
container.style.alignItems = "center";
|
|
3560
|
-
pre.style.margin = "0";
|
|
4357
|
+
pre.style.margin = "0 auto";
|
|
3561
4358
|
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3562
4359
|
pre.style.fontSize = "13px";
|
|
3563
4360
|
pre.style.color = "#1e293b";
|
|
@@ -3569,10 +4366,12 @@ var CodePlugin = class {
|
|
|
3569
4366
|
pre.style.minHeight = "1056px";
|
|
3570
4367
|
pre.style.padding = "72px 56px";
|
|
3571
4368
|
pre.style.boxSizing = "border-box";
|
|
3572
|
-
pre.style.boxShadow = "0 4px
|
|
4369
|
+
pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
3573
4370
|
pre.style.borderRadius = "4px";
|
|
3574
4371
|
pre.style.transformOrigin = "top center";
|
|
4372
|
+
pre.style.transition = "transform 0.15s ease";
|
|
3575
4373
|
} else {
|
|
4374
|
+
container.style.overflow = "auto";
|
|
3576
4375
|
container.style.backgroundColor = "#1e1e1e";
|
|
3577
4376
|
container.style.color = "#d4d4d4";
|
|
3578
4377
|
container.style.padding = "16px";
|
|
@@ -3604,42 +4403,9 @@ var CodePlugin = class {
|
|
|
3604
4403
|
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3605
4404
|
pre.appendChild(code);
|
|
3606
4405
|
container.appendChild(pre);
|
|
3607
|
-
let indicator = null;
|
|
3608
|
-
if (totalPages > 1) {
|
|
3609
|
-
indicator = document.createElement("div");
|
|
3610
|
-
indicator.className = "fp-code-page-indicator";
|
|
3611
|
-
indicator.style.position = "sticky";
|
|
3612
|
-
indicator.style.bottom = "16px";
|
|
3613
|
-
if (isTxt) {
|
|
3614
|
-
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3615
|
-
indicator.style.color = "#334155";
|
|
3616
|
-
indicator.style.border = "1px solid #e2e8f0";
|
|
3617
|
-
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3618
|
-
} else {
|
|
3619
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3620
|
-
indicator.style.color = "#f8fafc";
|
|
3621
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3622
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3623
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
3624
|
-
}
|
|
3625
|
-
indicator.style.fontSize = "12px";
|
|
3626
|
-
indicator.style.fontWeight = "600";
|
|
3627
|
-
indicator.style.padding = "5px 14px";
|
|
3628
|
-
indicator.style.borderRadius = "20px";
|
|
3629
|
-
indicator.style.zIndex = "10";
|
|
3630
|
-
indicator.style.userSelect = "none";
|
|
3631
|
-
indicator.style.pointerEvents = "none";
|
|
3632
|
-
indicator.style.textAlign = "center";
|
|
3633
|
-
indicator.style.width = "fit-content";
|
|
3634
|
-
indicator.style.margin = "16px auto 0";
|
|
3635
|
-
container.appendChild(indicator);
|
|
3636
|
-
}
|
|
3637
4406
|
const showPage = (pageNum) => {
|
|
3638
4407
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3639
4408
|
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3640
|
-
if (indicator) {
|
|
3641
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3642
|
-
}
|
|
3643
4409
|
container.scrollTop = 0;
|
|
3644
4410
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3645
4411
|
};
|
|
@@ -3647,36 +4413,90 @@ var CodePlugin = class {
|
|
|
3647
4413
|
showPage(1);
|
|
3648
4414
|
}
|
|
3649
4415
|
ctx.container.appendChild(container);
|
|
3650
|
-
const
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
ctx.container.innerHTML = "";
|
|
4416
|
+
const calculateTxtFit = () => {
|
|
4417
|
+
const availW = Math.max(280, container.clientWidth - 32);
|
|
4418
|
+
return Math.max(0.4, Math.min(3, availW / 816));
|
|
3654
4419
|
};
|
|
3655
|
-
ctx.signal.addEventListener("abort", cleanup);
|
|
3656
4420
|
const updateTransform = () => {
|
|
3657
4421
|
if (isTxt) {
|
|
3658
4422
|
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
4423
|
+
const scaledH = 1056 * zoomLevel;
|
|
4424
|
+
const extraH = Math.max(0, scaledH - 1056);
|
|
4425
|
+
pre.style.marginBottom = `${extraH + 32}px`;
|
|
3659
4426
|
} else {
|
|
3660
4427
|
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3661
4428
|
pre.style.fontSize = `${fontSize}px`;
|
|
3662
4429
|
}
|
|
3663
4430
|
};
|
|
4431
|
+
let resizeObserver = null;
|
|
4432
|
+
if (isTxt) {
|
|
4433
|
+
setTimeout(() => {
|
|
4434
|
+
zoomLevel = calculateTxtFit();
|
|
4435
|
+
updateTransform();
|
|
4436
|
+
}, 60);
|
|
4437
|
+
resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
4438
|
+
if (!isUserZoomed) {
|
|
4439
|
+
zoomLevel = calculateTxtFit();
|
|
4440
|
+
updateTransform();
|
|
4441
|
+
}
|
|
4442
|
+
}) : null;
|
|
4443
|
+
resizeObserver?.observe(container);
|
|
4444
|
+
}
|
|
4445
|
+
const cleanup = () => {
|
|
4446
|
+
resizeObserver?.disconnect();
|
|
4447
|
+
container.remove();
|
|
4448
|
+
ctx.container.innerHTML = "";
|
|
4449
|
+
};
|
|
4450
|
+
ctx.signal.addEventListener("abort", cleanup);
|
|
3664
4451
|
return {
|
|
3665
4452
|
destroy: cleanup,
|
|
3666
4453
|
getPageCount: () => totalPages,
|
|
3667
4454
|
getCurrentPage: () => currentPage,
|
|
3668
4455
|
goToPage: (page) => showPage(page),
|
|
4456
|
+
getThumbnails: () => {
|
|
4457
|
+
return rawPages.map((pageText, idx) => ({
|
|
4458
|
+
index: idx,
|
|
4459
|
+
label: `Page ${idx + 1}`,
|
|
4460
|
+
render: async (canvas) => {
|
|
4461
|
+
canvas.width = 140;
|
|
4462
|
+
canvas.height = 180;
|
|
4463
|
+
const c = canvas.getContext("2d");
|
|
4464
|
+
if (!c) return;
|
|
4465
|
+
c.fillStyle = "#ffffff";
|
|
4466
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4467
|
+
c.strokeStyle = "#cbd5e1";
|
|
4468
|
+
c.lineWidth = 1;
|
|
4469
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4470
|
+
c.fillStyle = "#64748b";
|
|
4471
|
+
const lines = (pageText || "").split("\n").slice(0, 24);
|
|
4472
|
+
const lineH = 6;
|
|
4473
|
+
const startY = 14;
|
|
4474
|
+
const startX = 12;
|
|
4475
|
+
const maxW = canvas.width - 24;
|
|
4476
|
+
c.font = "5px monospace";
|
|
4477
|
+
for (let li = 0; li < lines.length; li++) {
|
|
4478
|
+
const l = lines[li].trim();
|
|
4479
|
+
if (!l) continue;
|
|
4480
|
+
const y = startY + li * lineH;
|
|
4481
|
+
if (y > canvas.height - 12) break;
|
|
4482
|
+
c.fillText(l.slice(0, 30), startX, y, maxW);
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
}));
|
|
4486
|
+
},
|
|
3669
4487
|
zoomIn: () => {
|
|
4488
|
+
isUserZoomed = true;
|
|
3670
4489
|
if (isTxt) {
|
|
3671
|
-
zoomLevel = Math.min(3, zoomLevel + 0.
|
|
4490
|
+
zoomLevel = Math.min(3.5, zoomLevel + 0.15);
|
|
3672
4491
|
} else {
|
|
3673
4492
|
fontSize = Math.min(32, fontSize + 2);
|
|
3674
4493
|
}
|
|
3675
4494
|
updateTransform();
|
|
3676
4495
|
},
|
|
3677
4496
|
zoomOut: () => {
|
|
4497
|
+
isUserZoomed = true;
|
|
3678
4498
|
if (isTxt) {
|
|
3679
|
-
zoomLevel = Math.max(0.1, zoomLevel - 0.
|
|
4499
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.15);
|
|
3680
4500
|
} else {
|
|
3681
4501
|
fontSize = Math.max(8, fontSize - 2);
|
|
3682
4502
|
}
|
|
@@ -3684,6 +4504,7 @@ var CodePlugin = class {
|
|
|
3684
4504
|
},
|
|
3685
4505
|
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3686
4506
|
setZoom: (level) => {
|
|
4507
|
+
isUserZoomed = true;
|
|
3687
4508
|
if (isTxt) {
|
|
3688
4509
|
zoomLevel = level;
|
|
3689
4510
|
} else {
|
|
@@ -3692,9 +4513,10 @@ var CodePlugin = class {
|
|
|
3692
4513
|
updateTransform();
|
|
3693
4514
|
},
|
|
3694
4515
|
fitToPage: () => {
|
|
4516
|
+
isUserZoomed = false;
|
|
3695
4517
|
fontSize = 13;
|
|
3696
4518
|
rotation = 0;
|
|
3697
|
-
zoomLevel = isTxt ?
|
|
4519
|
+
zoomLevel = isTxt ? calculateTxtFit() : 1;
|
|
3698
4520
|
updateTransform();
|
|
3699
4521
|
},
|
|
3700
4522
|
rotateCW: () => {
|
|
@@ -4575,28 +5397,26 @@ var RtfPlugin = class {
|
|
|
4575
5397
|
getToolbarActions(instance) {
|
|
4576
5398
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4577
5399
|
const actions = [];
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
if (
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
instance.goToPage?.(page);
|
|
4596
|
-
}
|
|
5400
|
+
actions.push({
|
|
5401
|
+
id: "page-nav",
|
|
5402
|
+
icon: "",
|
|
5403
|
+
label: "Page Navigation",
|
|
5404
|
+
type: "page-nav",
|
|
5405
|
+
group: "navigation",
|
|
5406
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5407
|
+
max: totalPages,
|
|
5408
|
+
execute: (action, page) => {
|
|
5409
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5410
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5411
|
+
if (action === "prev") {
|
|
5412
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5413
|
+
} else if (action === "next") {
|
|
5414
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5415
|
+
} else if (typeof page === "number") {
|
|
5416
|
+
instance.goToPage?.(page);
|
|
4597
5417
|
}
|
|
4598
|
-
}
|
|
4599
|
-
}
|
|
5418
|
+
}
|
|
5419
|
+
});
|
|
4600
5420
|
actions.push(
|
|
4601
5421
|
{
|
|
4602
5422
|
id: "zoom-out",
|
|
@@ -4668,43 +5488,57 @@ var RtfPlugin = class {
|
|
|
4668
5488
|
async render(ctx) {
|
|
4669
5489
|
const wrapper = document.createElement("div");
|
|
4670
5490
|
wrapper.className = "fp-rtf-wrapper";
|
|
4671
|
-
wrapper.style.padding = "
|
|
4672
|
-
wrapper.style.
|
|
5491
|
+
wrapper.style.padding = "0";
|
|
5492
|
+
wrapper.style.width = "816px";
|
|
4673
5493
|
wrapper.style.margin = "0 auto";
|
|
4674
|
-
wrapper.style.
|
|
4675
|
-
wrapper.style.
|
|
4676
|
-
wrapper.style.
|
|
4677
|
-
wrapper.style.
|
|
5494
|
+
wrapper.style.boxSizing = "border-box";
|
|
5495
|
+
wrapper.style.display = "flex";
|
|
5496
|
+
wrapper.style.flexDirection = "column";
|
|
5497
|
+
wrapper.style.alignItems = "center";
|
|
5498
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4678
5499
|
wrapper.style.transformOrigin = "top center";
|
|
4679
|
-
wrapper.style.transition = "transform 0.
|
|
4680
|
-
ctx.container.style.
|
|
4681
|
-
ctx.container.style.
|
|
5500
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5501
|
+
ctx.container.style.overflowX = "hidden";
|
|
5502
|
+
ctx.container.style.overflowY = "auto";
|
|
5503
|
+
ctx.container.style.padding = "16px 8px";
|
|
4682
5504
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
4683
5505
|
ctx.container.appendChild(wrapper);
|
|
4684
5506
|
let scale = 1;
|
|
4685
5507
|
let rotation = 0;
|
|
4686
5508
|
let pageElements = [];
|
|
4687
|
-
let
|
|
5509
|
+
let isUserZoomed = false;
|
|
5510
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
4688
5511
|
const calculateFitScale = (mode = fitMode) => {
|
|
4689
5512
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4690
|
-
const elW =
|
|
4691
|
-
const singlePageH =
|
|
4692
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
4693
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
5513
|
+
const elW = 816;
|
|
5514
|
+
const singlePageH = activeEl?.offsetHeight || 1056;
|
|
5515
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5516
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
4694
5517
|
const sW = availW / elW;
|
|
4695
5518
|
const sH = availH / singlePageH;
|
|
4696
5519
|
if (mode === "page") {
|
|
4697
|
-
return Math.max(0.
|
|
5520
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
4698
5521
|
}
|
|
4699
|
-
return Math.max(0.
|
|
5522
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
4700
5523
|
};
|
|
4701
5524
|
const applyTransform = () => {
|
|
4702
5525
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4703
5526
|
wrapper.style.transformOrigin = "top center";
|
|
5527
|
+
const activeEl = pageElements[currentPage - 1];
|
|
5528
|
+
const baseH = activeEl?.offsetHeight || 1056;
|
|
5529
|
+
const scaledH = baseH * scale;
|
|
5530
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5531
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
4704
5532
|
};
|
|
5533
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5534
|
+
if (!isUserZoomed) {
|
|
5535
|
+
scale = calculateFitScale(fitMode);
|
|
5536
|
+
applyTransform();
|
|
5537
|
+
}
|
|
5538
|
+
}) : null;
|
|
5539
|
+
resizeObserver?.observe(ctx.container);
|
|
4705
5540
|
setTimeout(() => {
|
|
4706
|
-
|
|
4707
|
-
scale = calculateFitScale("width");
|
|
5541
|
+
scale = calculateFitScale(fitMode);
|
|
4708
5542
|
applyTransform();
|
|
4709
5543
|
}, 60);
|
|
4710
5544
|
try {
|
|
@@ -4714,20 +5548,34 @@ var RtfPlugin = class {
|
|
|
4714
5548
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
4715
5549
|
const htmlElements = await doc.render();
|
|
4716
5550
|
const contentNodes = [];
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
5551
|
+
const extractBlocks = (nodes) => {
|
|
5552
|
+
for (const item of nodes) {
|
|
5553
|
+
if (!item || !(item instanceof HTMLElement)) continue;
|
|
5554
|
+
const tag = item.tagName.toLowerCase();
|
|
5555
|
+
const hasChildBlocks = Array.from(item.children).some((c) => {
|
|
5556
|
+
const ct = c.tagName.toLowerCase();
|
|
5557
|
+
return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
|
|
5558
|
+
});
|
|
5559
|
+
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5560
|
+
extractBlocks(Array.from(item.children));
|
|
5561
|
+
} else {
|
|
5562
|
+
if (tag === "p" || tag === "div") {
|
|
5563
|
+
item.style.display = "block";
|
|
5564
|
+
item.style.marginBottom = "12px";
|
|
5565
|
+
item.style.lineHeight = "1.6";
|
|
5566
|
+
}
|
|
5567
|
+
contentNodes.push(item);
|
|
5568
|
+
}
|
|
4722
5569
|
}
|
|
4723
|
-
}
|
|
5570
|
+
};
|
|
5571
|
+
extractBlocks(htmlElements);
|
|
4724
5572
|
wrapper.innerHTML = "";
|
|
4725
5573
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4726
5574
|
const childHeights = contentNodes.map((c) => {
|
|
4727
5575
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4728
5576
|
const offH = c.offsetHeight || 0;
|
|
4729
5577
|
const textLen = c.textContent?.trim().length || 0;
|
|
4730
|
-
const estH = Math.max(
|
|
5578
|
+
const estH = Math.max(28, Math.ceil(textLen / 75) * 24 + 16);
|
|
4731
5579
|
return Math.max(rectH, offH, estH);
|
|
4732
5580
|
});
|
|
4733
5581
|
wrapper.innerHTML = "";
|
|
@@ -4744,6 +5592,7 @@ var RtfPlugin = class {
|
|
|
4744
5592
|
card.style.marginBottom = "24px";
|
|
4745
5593
|
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4746
5594
|
card.style.lineHeight = "1.6";
|
|
5595
|
+
card.style.color = "#1e293b";
|
|
4747
5596
|
return card;
|
|
4748
5597
|
};
|
|
4749
5598
|
let curCard = createRtfCard();
|
|
@@ -4779,9 +5628,8 @@ var RtfPlugin = class {
|
|
|
4779
5628
|
pageCard.style.padding = "72px 56px";
|
|
4780
5629
|
pageCard.style.width = "816px";
|
|
4781
5630
|
pageCard.style.minHeight = "1056px";
|
|
4782
|
-
pageCard.style.maxWidth = "100%";
|
|
4783
5631
|
pageCard.style.boxSizing = "border-box";
|
|
4784
|
-
pageCard.style.fontFamily = "serif
|
|
5632
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4785
5633
|
pageCard.style.fontSize = "12pt";
|
|
4786
5634
|
pageCard.style.lineHeight = "1.6";
|
|
4787
5635
|
pageCard.style.color = "#1e293b";
|
|
@@ -4794,29 +5642,6 @@ var RtfPlugin = class {
|
|
|
4794
5642
|
}
|
|
4795
5643
|
const totalPages = Math.max(1, pageElements.length);
|
|
4796
5644
|
let currentPage = 1;
|
|
4797
|
-
let indicator = null;
|
|
4798
|
-
if (totalPages > 1) {
|
|
4799
|
-
indicator = document.createElement("div");
|
|
4800
|
-
indicator.className = "fp-rtf-page-indicator";
|
|
4801
|
-
indicator.style.position = "sticky";
|
|
4802
|
-
indicator.style.bottom = "16px";
|
|
4803
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4804
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
4805
|
-
indicator.style.color = "#f8fafc";
|
|
4806
|
-
indicator.style.fontSize = "12px";
|
|
4807
|
-
indicator.style.fontWeight = "600";
|
|
4808
|
-
indicator.style.padding = "5px 14px";
|
|
4809
|
-
indicator.style.borderRadius = "20px";
|
|
4810
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4811
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4812
|
-
indicator.style.zIndex = "10";
|
|
4813
|
-
indicator.style.userSelect = "none";
|
|
4814
|
-
indicator.style.pointerEvents = "none";
|
|
4815
|
-
indicator.style.textAlign = "center";
|
|
4816
|
-
indicator.style.width = "fit-content";
|
|
4817
|
-
indicator.style.margin = "16px auto 0";
|
|
4818
|
-
ctx.container.appendChild(indicator);
|
|
4819
|
-
}
|
|
4820
5645
|
const showPage = (pageNum) => {
|
|
4821
5646
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4822
5647
|
if (totalPages > 1) {
|
|
@@ -4824,9 +5649,6 @@ var RtfPlugin = class {
|
|
|
4824
5649
|
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4825
5650
|
});
|
|
4826
5651
|
}
|
|
4827
|
-
if (indicator) {
|
|
4828
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4829
|
-
}
|
|
4830
5652
|
ctx.container.scrollTop = 0;
|
|
4831
5653
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4832
5654
|
};
|
|
@@ -4834,7 +5656,7 @@ var RtfPlugin = class {
|
|
|
4834
5656
|
showPage(1);
|
|
4835
5657
|
}
|
|
4836
5658
|
const cleanup = () => {
|
|
4837
|
-
|
|
5659
|
+
resizeObserver?.disconnect();
|
|
4838
5660
|
wrapper.remove();
|
|
4839
5661
|
ctx.container.innerHTML = "";
|
|
4840
5662
|
};
|
|
@@ -4845,21 +5667,25 @@ var RtfPlugin = class {
|
|
|
4845
5667
|
getCurrentPage: () => currentPage,
|
|
4846
5668
|
goToPage: (page) => showPage(page),
|
|
4847
5669
|
zoomIn: () => {
|
|
5670
|
+
isUserZoomed = true;
|
|
4848
5671
|
scale += 0.15;
|
|
4849
5672
|
applyTransform();
|
|
4850
5673
|
},
|
|
4851
5674
|
zoomOut: () => {
|
|
5675
|
+
isUserZoomed = true;
|
|
4852
5676
|
scale = Math.max(0.2, scale - 0.15);
|
|
4853
5677
|
applyTransform();
|
|
4854
5678
|
},
|
|
4855
5679
|
getZoom: () => scale,
|
|
4856
5680
|
setZoom: (level) => {
|
|
5681
|
+
isUserZoomed = true;
|
|
4857
5682
|
scale = level;
|
|
4858
5683
|
applyTransform();
|
|
4859
5684
|
},
|
|
4860
5685
|
fitToPage: () => {
|
|
4861
|
-
|
|
4862
|
-
|
|
5686
|
+
isUserZoomed = false;
|
|
5687
|
+
fitMode = "width";
|
|
5688
|
+
scale = calculateFitScale("width");
|
|
4863
5689
|
rotation = 0;
|
|
4864
5690
|
applyTransform();
|
|
4865
5691
|
},
|
|
@@ -5047,40 +5873,36 @@ var OpenDocumentPlugin = class {
|
|
|
5047
5873
|
const isPresentation = instance.isPresentation;
|
|
5048
5874
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5049
5875
|
const actions = [];
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
max
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
if (
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
instance.goToPage?.(page);
|
|
5078
|
-
} else if (typeof action === "number") {
|
|
5079
|
-
instance.goToPage?.(action);
|
|
5080
|
-
}
|
|
5876
|
+
actions.push({
|
|
5877
|
+
id: "thumbnails",
|
|
5878
|
+
icon: "thumbnails",
|
|
5879
|
+
label: isPresentation ? "Slide Thumbnails" : "Page Thumbnails",
|
|
5880
|
+
type: "button",
|
|
5881
|
+
group: "navigation",
|
|
5882
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5883
|
+
});
|
|
5884
|
+
actions.push({
|
|
5885
|
+
id: "page-nav",
|
|
5886
|
+
icon: "",
|
|
5887
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
5888
|
+
type: "page-nav",
|
|
5889
|
+
group: "navigation",
|
|
5890
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5891
|
+
max: totalPages,
|
|
5892
|
+
execute: (action, page) => {
|
|
5893
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5894
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5895
|
+
if (action === "prev") {
|
|
5896
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5897
|
+
} else if (action === "next") {
|
|
5898
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5899
|
+
} else if (typeof page === "number") {
|
|
5900
|
+
instance.goToPage?.(page);
|
|
5901
|
+
} else if (typeof action === "number") {
|
|
5902
|
+
instance.goToPage?.(action);
|
|
5081
5903
|
}
|
|
5082
|
-
}
|
|
5083
|
-
}
|
|
5904
|
+
}
|
|
5905
|
+
});
|
|
5084
5906
|
actions.push(
|
|
5085
5907
|
{
|
|
5086
5908
|
id: "zoom-out",
|
|
@@ -5171,49 +5993,65 @@ var OpenDocumentPlugin = class {
|
|
|
5171
5993
|
container.className = "fp-odf-container";
|
|
5172
5994
|
container.style.width = "100%";
|
|
5173
5995
|
container.style.height = "100%";
|
|
5174
|
-
container.style.
|
|
5175
|
-
container.style.
|
|
5996
|
+
container.style.overflowX = "hidden";
|
|
5997
|
+
container.style.overflowY = "auto";
|
|
5998
|
+
container.style.padding = "16px 8px";
|
|
5176
5999
|
container.style.backgroundColor = "#f1f5f9";
|
|
5177
6000
|
const wrapper = document.createElement("div");
|
|
5178
6001
|
wrapper.className = "fp-odf-wrapper";
|
|
5179
6002
|
wrapper.style.margin = "0 auto";
|
|
6003
|
+
wrapper.style.width = isPresentation ? "960px" : "816px";
|
|
6004
|
+
wrapper.style.boxSizing = "border-box";
|
|
5180
6005
|
wrapper.style.backgroundColor = "#ffffff";
|
|
5181
6006
|
wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
5182
6007
|
wrapper.style.borderRadius = "4px";
|
|
5183
6008
|
wrapper.style.transformOrigin = "top center";
|
|
5184
|
-
wrapper.style.transition = "transform 0.
|
|
6009
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5185
6010
|
container.appendChild(wrapper);
|
|
5186
6011
|
ctx.container.appendChild(container);
|
|
5187
6012
|
let scale = 1;
|
|
5188
6013
|
let rotation = 0;
|
|
5189
|
-
let
|
|
6014
|
+
let isUserZoomed = false;
|
|
6015
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6016
|
+
let currentPage = 1;
|
|
6017
|
+
let totalPages = 1;
|
|
6018
|
+
let slides = [];
|
|
5190
6019
|
const calculateFitScale = (mode = fitMode) => {
|
|
5191
|
-
const
|
|
5192
|
-
const
|
|
5193
|
-
const
|
|
5194
|
-
const
|
|
6020
|
+
const activeSlide = slides[currentPage - 1];
|
|
6021
|
+
const elW = isPresentation ? 960 : 816;
|
|
6022
|
+
const singlePageH = Math.min(activeSlide?.offsetHeight || wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
6023
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6024
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5195
6025
|
const sW = availW / elW;
|
|
5196
6026
|
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
5197
6027
|
if (isPresentation) {
|
|
5198
|
-
return Math.min(
|
|
6028
|
+
return Math.min(2.5, Math.min(sW, sH));
|
|
5199
6029
|
}
|
|
5200
6030
|
if (mode === "page") {
|
|
5201
|
-
return Math.max(0.
|
|
6031
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5202
6032
|
}
|
|
5203
|
-
return Math.max(0.
|
|
6033
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5204
6034
|
};
|
|
5205
6035
|
const applyTransform = () => {
|
|
5206
6036
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5207
6037
|
wrapper.style.transformOrigin = "top center";
|
|
6038
|
+
const activeSlide = slides[currentPage - 1];
|
|
6039
|
+
const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
|
|
6040
|
+
const scaledH = baseH * scale;
|
|
6041
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6042
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
5208
6043
|
};
|
|
6044
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6045
|
+
if (!isUserZoomed) {
|
|
6046
|
+
scale = calculateFitScale(fitMode);
|
|
6047
|
+
applyTransform();
|
|
6048
|
+
}
|
|
6049
|
+
}) : null;
|
|
6050
|
+
resizeObserver?.observe(ctx.container);
|
|
5209
6051
|
setTimeout(() => {
|
|
5210
|
-
|
|
5211
|
-
scale = calculateFitScale("width");
|
|
6052
|
+
scale = calculateFitScale(fitMode);
|
|
5212
6053
|
applyTransform();
|
|
5213
6054
|
}, 60);
|
|
5214
|
-
let currentPage = 1;
|
|
5215
|
-
let totalPages = 1;
|
|
5216
|
-
let slides = [];
|
|
5217
6055
|
if (isPresentation) {
|
|
5218
6056
|
wrapper.style.maxWidth = "960px";
|
|
5219
6057
|
wrapper.style.aspectRatio = "16 / 9";
|
|
@@ -5314,24 +6152,9 @@ var OpenDocumentPlugin = class {
|
|
|
5314
6152
|
wrapper.appendChild(page);
|
|
5315
6153
|
slides.push(page);
|
|
5316
6154
|
});
|
|
5317
|
-
const pageIndicator = document.createElement("div");
|
|
5318
|
-
pageIndicator.className = "fp-odt-page-indicator";
|
|
5319
|
-
pageIndicator.style.position = "sticky";
|
|
5320
|
-
pageIndicator.style.bottom = "16px";
|
|
5321
|
-
pageIndicator.style.left = "50%";
|
|
5322
|
-
pageIndicator.style.transform = "translateX(-50%)";
|
|
5323
|
-
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
5324
|
-
pageIndicator.style.color = "#fff";
|
|
5325
|
-
pageIndicator.style.padding = "6px 12px";
|
|
5326
|
-
pageIndicator.style.borderRadius = "16px";
|
|
5327
|
-
pageIndicator.style.fontSize = "12px";
|
|
5328
|
-
pageIndicator.style.zIndex = "100";
|
|
5329
|
-
pageIndicator.style.display = "inline-block";
|
|
5330
|
-
pageIndicator.style.width = "fit-content";
|
|
5331
|
-
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
5332
|
-
container.appendChild(pageIndicator);
|
|
5333
6155
|
}
|
|
5334
6156
|
const cleanup = () => {
|
|
6157
|
+
resizeObserver?.disconnect();
|
|
5335
6158
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
5336
6159
|
container.remove();
|
|
5337
6160
|
ctx.container.innerHTML = "";
|
|
@@ -5343,10 +6166,6 @@ var OpenDocumentPlugin = class {
|
|
|
5343
6166
|
slides.forEach((s, idx) => {
|
|
5344
6167
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
5345
6168
|
});
|
|
5346
|
-
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
5347
|
-
if (indicator) {
|
|
5348
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5349
|
-
}
|
|
5350
6169
|
container.scrollTop = 0;
|
|
5351
6170
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5352
6171
|
};
|
|
@@ -5354,21 +6173,25 @@ var OpenDocumentPlugin = class {
|
|
|
5354
6173
|
destroy: cleanup,
|
|
5355
6174
|
isPresentation,
|
|
5356
6175
|
zoomIn: () => {
|
|
6176
|
+
isUserZoomed = true;
|
|
5357
6177
|
scale += 0.15;
|
|
5358
6178
|
applyTransform();
|
|
5359
6179
|
},
|
|
5360
6180
|
zoomOut: () => {
|
|
6181
|
+
isUserZoomed = true;
|
|
5361
6182
|
scale = Math.max(0.2, scale - 0.15);
|
|
5362
6183
|
applyTransform();
|
|
5363
6184
|
},
|
|
5364
6185
|
getZoom: () => scale,
|
|
5365
6186
|
setZoom: (level) => {
|
|
6187
|
+
isUserZoomed = true;
|
|
5366
6188
|
scale = level;
|
|
5367
6189
|
applyTransform();
|
|
5368
6190
|
},
|
|
5369
6191
|
fitToPage: () => {
|
|
5370
|
-
|
|
5371
|
-
|
|
6192
|
+
isUserZoomed = false;
|
|
6193
|
+
fitMode = "width";
|
|
6194
|
+
scale = calculateFitScale("width");
|
|
5372
6195
|
rotation = 0;
|
|
5373
6196
|
applyTransform();
|
|
5374
6197
|
},
|
|
@@ -5384,23 +6207,45 @@ var OpenDocumentPlugin = class {
|
|
|
5384
6207
|
getPageCount: () => totalPages,
|
|
5385
6208
|
getCurrentPage: () => currentPage,
|
|
5386
6209
|
getThumbnails: async () => {
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
canvas
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
6210
|
+
const count = totalPages || slides.length || 1;
|
|
6211
|
+
const items = [];
|
|
6212
|
+
for (let idx = 0; idx < count; idx++) {
|
|
6213
|
+
const itemIdx = idx;
|
|
6214
|
+
items.push({
|
|
6215
|
+
index: itemIdx,
|
|
6216
|
+
label: isPresentation ? `Slide ${itemIdx + 1}` : `Page ${itemIdx + 1}`,
|
|
6217
|
+
render: async (canvas) => {
|
|
6218
|
+
const ctx2d = canvas.getContext("2d");
|
|
6219
|
+
if (!ctx2d) return;
|
|
6220
|
+
if (isPresentation) {
|
|
6221
|
+
canvas.width = 160;
|
|
6222
|
+
canvas.height = 90;
|
|
6223
|
+
ctx2d.fillStyle = "#f8fafc";
|
|
6224
|
+
ctx2d.fillRect(0, 0, 160, 90);
|
|
6225
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6226
|
+
ctx2d.lineWidth = 1;
|
|
6227
|
+
ctx2d.strokeRect(0.5, 0.5, 159, 89);
|
|
6228
|
+
ctx2d.fillStyle = "#334155";
|
|
6229
|
+
ctx2d.font = "bold 11px sans-serif";
|
|
6230
|
+
ctx2d.textAlign = "center";
|
|
6231
|
+
ctx2d.fillText(`Slide ${itemIdx + 1}`, 80, 50);
|
|
6232
|
+
} else {
|
|
6233
|
+
canvas.width = 140;
|
|
6234
|
+
canvas.height = 180;
|
|
6235
|
+
ctx2d.fillStyle = "#ffffff";
|
|
6236
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
6237
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6238
|
+
ctx2d.lineWidth = 1;
|
|
6239
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
6240
|
+
ctx2d.fillStyle = "#64748b";
|
|
6241
|
+
ctx2d.font = "bold 10px sans-serif";
|
|
6242
|
+
ctx2d.textAlign = "center";
|
|
6243
|
+
ctx2d.fillText(`Page ${itemIdx + 1}`, 70, 90);
|
|
6244
|
+
}
|
|
6245
|
+
}
|
|
6246
|
+
});
|
|
6247
|
+
}
|
|
6248
|
+
return items;
|
|
5404
6249
|
},
|
|
5405
6250
|
download: () => {
|
|
5406
6251
|
const mimeType = this.mimeTypes.find((m) => m.includes(ext.replace(".", ""))) || "application/octet-stream";
|
|
@@ -5505,23 +6350,24 @@ var OpenDocumentPlugin = class {
|
|
|
5505
6350
|
case "h": {
|
|
5506
6351
|
const level = Math.min(6, Math.max(1, Number(node.getAttribute("text:outline-level") || 1)));
|
|
5507
6352
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5508
|
-
html += `<h${level} style="${style}; font-family:
|
|
6353
|
+
html += `<h${level} style="${style}; margin: 18px 0 8px; color: #1e3a8a; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${node.textContent || ""}</h${level}>`;
|
|
5509
6354
|
break;
|
|
5510
6355
|
}
|
|
5511
6356
|
case "p": {
|
|
5512
6357
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5513
6358
|
const inner = this.renderSpans(node, styles, images);
|
|
5514
|
-
|
|
6359
|
+
const isInsideLi = node.parentElement?.localName === "list-item" || node.parentElement?.tagName?.toLowerCase() === "list-item";
|
|
6360
|
+
html += `<p style="${style}; line-height: 1.5; margin: ${isInsideLi ? "0" : "8px 0 12px"}; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${inner}</p>`;
|
|
5515
6361
|
break;
|
|
5516
6362
|
}
|
|
5517
6363
|
case "list": {
|
|
5518
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
6364
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
5519
6365
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5520
6366
|
html += "</ul>";
|
|
5521
6367
|
break;
|
|
5522
6368
|
}
|
|
5523
6369
|
case "list-item": {
|
|
5524
|
-
html +=
|
|
6370
|
+
html += '<li style="margin: 4px 0; font-size: 11pt; line-height: 1.5; color: #1e293b;">';
|
|
5525
6371
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5526
6372
|
html += "</li>";
|
|
5527
6373
|
break;
|
|
@@ -5647,28 +6493,26 @@ var DocPlugin = class {
|
|
|
5647
6493
|
getToolbarActions(instance) {
|
|
5648
6494
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5649
6495
|
const actions = [];
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
if (
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
instance.goToPage?.(page);
|
|
5668
|
-
}
|
|
6496
|
+
actions.push({
|
|
6497
|
+
id: "page-nav",
|
|
6498
|
+
icon: "",
|
|
6499
|
+
label: "Page Navigation",
|
|
6500
|
+
type: "page-nav",
|
|
6501
|
+
group: "navigation",
|
|
6502
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
6503
|
+
max: totalPages,
|
|
6504
|
+
execute: (action, page) => {
|
|
6505
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
6506
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
6507
|
+
if (action === "prev") {
|
|
6508
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
6509
|
+
} else if (action === "next") {
|
|
6510
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
6511
|
+
} else if (typeof page === "number") {
|
|
6512
|
+
instance.goToPage?.(page);
|
|
5669
6513
|
}
|
|
5670
|
-
}
|
|
5671
|
-
}
|
|
6514
|
+
}
|
|
6515
|
+
});
|
|
5672
6516
|
actions.push(
|
|
5673
6517
|
{
|
|
5674
6518
|
id: "zoom-out",
|
|
@@ -5742,8 +6586,9 @@ var DocPlugin = class {
|
|
|
5742
6586
|
container.className = "fp-doc-container";
|
|
5743
6587
|
container.style.width = "100%";
|
|
5744
6588
|
container.style.height = "100%";
|
|
5745
|
-
container.style.
|
|
5746
|
-
container.style.
|
|
6589
|
+
container.style.overflowX = "hidden";
|
|
6590
|
+
container.style.overflowY = "auto";
|
|
6591
|
+
container.style.padding = "16px 8px";
|
|
5747
6592
|
container.style.backgroundColor = "#f1f5f9";
|
|
5748
6593
|
container.style.display = "flex";
|
|
5749
6594
|
container.style.justifyContent = "center";
|
|
@@ -5788,16 +6633,15 @@ var DocPlugin = class {
|
|
|
5788
6633
|
const pageCard = document.createElement("div");
|
|
5789
6634
|
pageCard.className = "fp-doc-page-card";
|
|
5790
6635
|
pageCard.style.width = "816px";
|
|
5791
|
-
pageCard.style.
|
|
6636
|
+
pageCard.style.minHeight = "1056px";
|
|
5792
6637
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5793
|
-
pageCard.style.boxShadow = "0
|
|
6638
|
+
pageCard.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5794
6639
|
pageCard.style.borderRadius = "4px";
|
|
5795
|
-
pageCard.style.padding = "
|
|
6640
|
+
pageCard.style.padding = "72px 56px";
|
|
5796
6641
|
pageCard.style.boxSizing = "border-box";
|
|
5797
|
-
pageCard.style.overflow = "hidden";
|
|
5798
6642
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5799
6643
|
pageCard.style.transformOrigin = "top center";
|
|
5800
|
-
pageCard.style.transition = "transform 0.
|
|
6644
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
5801
6645
|
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5802
6646
|
pageCard.style.color = "#1e293b";
|
|
5803
6647
|
if (isFallback && i === 0) {
|
|
@@ -5814,34 +6658,15 @@ var DocPlugin = class {
|
|
|
5814
6658
|
container.appendChild(pageCard);
|
|
5815
6659
|
pageCards.push(pageCard);
|
|
5816
6660
|
}
|
|
5817
|
-
let indicator = null;
|
|
5818
|
-
if (totalPages > 1) {
|
|
5819
|
-
indicator = document.createElement("div");
|
|
5820
|
-
indicator.className = "fp-doc-page-indicator";
|
|
5821
|
-
indicator.style.position = "fixed";
|
|
5822
|
-
indicator.style.bottom = "16px";
|
|
5823
|
-
indicator.style.left = "50%";
|
|
5824
|
-
indicator.style.transform = "translateX(-50%)";
|
|
5825
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
5826
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
5827
|
-
indicator.style.color = "#f8fafc";
|
|
5828
|
-
indicator.style.fontSize = "12px";
|
|
5829
|
-
indicator.style.fontWeight = "600";
|
|
5830
|
-
indicator.style.padding = "5px 14px";
|
|
5831
|
-
indicator.style.borderRadius = "20px";
|
|
5832
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
5833
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
5834
|
-
indicator.style.zIndex = "10";
|
|
5835
|
-
indicator.style.userSelect = "none";
|
|
5836
|
-
indicator.style.pointerEvents = "none";
|
|
5837
|
-
indicator.style.textAlign = "center";
|
|
5838
|
-
container.appendChild(indicator);
|
|
5839
|
-
}
|
|
5840
6661
|
let rotation = 0;
|
|
5841
6662
|
const applyTransform = () => {
|
|
5842
6663
|
const activeCard = pageCards[currentPage - 1];
|
|
5843
6664
|
if (activeCard) {
|
|
5844
6665
|
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
6666
|
+
const baseH = activeCard.offsetHeight || 1056;
|
|
6667
|
+
const scaledH = baseH * scale;
|
|
6668
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6669
|
+
activeCard.style.marginBottom = `${extraH + 32}px`;
|
|
5845
6670
|
}
|
|
5846
6671
|
};
|
|
5847
6672
|
const showPage = (pageNum) => {
|
|
@@ -5854,35 +6679,39 @@ var DocPlugin = class {
|
|
|
5854
6679
|
card.style.display = "none";
|
|
5855
6680
|
}
|
|
5856
6681
|
});
|
|
5857
|
-
if (indicator) {
|
|
5858
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5859
|
-
}
|
|
5860
6682
|
container.scrollTop = 0;
|
|
5861
6683
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5862
6684
|
};
|
|
5863
6685
|
if (totalPages > 1) {
|
|
5864
6686
|
showPage(1);
|
|
5865
6687
|
}
|
|
5866
|
-
let fitMode = "width";
|
|
6688
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6689
|
+
let isUserZoomed = false;
|
|
5867
6690
|
const calculateFitScale = (mode = fitMode) => {
|
|
5868
6691
|
const elW = 816;
|
|
5869
6692
|
const elH = 1056;
|
|
5870
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
5871
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
6693
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6694
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5872
6695
|
const sW = availW / elW;
|
|
5873
6696
|
const sH = availH / elH;
|
|
5874
6697
|
if (mode === "page") {
|
|
5875
|
-
return Math.max(0.
|
|
6698
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5876
6699
|
}
|
|
5877
|
-
return Math.max(0.
|
|
6700
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5878
6701
|
};
|
|
6702
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6703
|
+
if (!isUserZoomed) {
|
|
6704
|
+
scale = calculateFitScale(fitMode);
|
|
6705
|
+
applyTransform();
|
|
6706
|
+
}
|
|
6707
|
+
}) : null;
|
|
6708
|
+
resizeObserver?.observe(ctx.container);
|
|
5879
6709
|
setTimeout(() => {
|
|
5880
|
-
|
|
5881
|
-
scale = calculateFitScale("width");
|
|
6710
|
+
scale = calculateFitScale(fitMode);
|
|
5882
6711
|
applyTransform();
|
|
5883
6712
|
}, 60);
|
|
5884
6713
|
const cleanup = () => {
|
|
5885
|
-
|
|
6714
|
+
resizeObserver?.disconnect();
|
|
5886
6715
|
container.remove();
|
|
5887
6716
|
ctx.container.innerHTML = "";
|
|
5888
6717
|
};
|
|
@@ -5893,21 +6722,25 @@ var DocPlugin = class {
|
|
|
5893
6722
|
getCurrentPage: () => currentPage,
|
|
5894
6723
|
goToPage: (page) => showPage(page),
|
|
5895
6724
|
zoomIn: () => {
|
|
6725
|
+
isUserZoomed = true;
|
|
5896
6726
|
scale += 0.15;
|
|
5897
6727
|
applyTransform();
|
|
5898
6728
|
},
|
|
5899
6729
|
zoomOut: () => {
|
|
6730
|
+
isUserZoomed = true;
|
|
5900
6731
|
scale = Math.max(0.2, scale - 0.15);
|
|
5901
6732
|
applyTransform();
|
|
5902
6733
|
},
|
|
5903
6734
|
getZoom: () => scale,
|
|
5904
6735
|
setZoom: (level) => {
|
|
6736
|
+
isUserZoomed = true;
|
|
5905
6737
|
scale = level;
|
|
5906
6738
|
applyTransform();
|
|
5907
6739
|
},
|
|
5908
6740
|
fitToPage: () => {
|
|
5909
|
-
|
|
5910
|
-
|
|
6741
|
+
isUserZoomed = false;
|
|
6742
|
+
fitMode = "width";
|
|
6743
|
+
scale = calculateFitScale("width");
|
|
5911
6744
|
rotation = 0;
|
|
5912
6745
|
applyTransform();
|
|
5913
6746
|
},
|
|
@@ -6284,25 +7117,31 @@ ${chartSvg}
|
|
|
6284
7117
|
i++;
|
|
6285
7118
|
continue;
|
|
6286
7119
|
}
|
|
6287
|
-
if (
|
|
7120
|
+
if (/^\d{1,2}$/.test(line.trim())) {
|
|
7121
|
+
i++;
|
|
7122
|
+
continue;
|
|
7123
|
+
}
|
|
7124
|
+
const isShortLine = line.length < 60 && !line.endsWith(".") && !line.endsWith(",");
|
|
7125
|
+
const isTitleLike = isShortLine && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#") || /^(?:Chapter|Section|Part|\d+\.)\b/i.test(line) || /^[A-Z][a-zA-Z0-9\s#:-]{2,45}$/.test(line));
|
|
7126
|
+
if (isTitleLike) {
|
|
6288
7127
|
if (inList) {
|
|
6289
7128
|
html += "</ul>";
|
|
6290
7129
|
inList = false;
|
|
6291
7130
|
}
|
|
6292
|
-
html += `<h2 style="font-size:
|
|
7131
|
+
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 18px 0 10px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6__default.default.sanitize(line, sanitizeOptions)}</h2>`;
|
|
6293
7132
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
6294
7133
|
if (!inList) {
|
|
6295
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
7134
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
6296
7135
|
inList = true;
|
|
6297
7136
|
}
|
|
6298
7137
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
6299
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
7138
|
+
html += `<li style="margin: 4px 0; line-height: 1.5; font-size: 11pt; color: #1e293b;">${DOMPurify6__default.default.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
6300
7139
|
} else {
|
|
6301
7140
|
if (inList) {
|
|
6302
7141
|
html += "</ul>";
|
|
6303
7142
|
inList = false;
|
|
6304
7143
|
}
|
|
6305
|
-
html += `<p style="line-height: 1.
|
|
7144
|
+
html += `<p style="line-height: 1.5; margin: 0 0 12px 0; font-size: 11pt; color: #1e293b; text-align: justify;">${DOMPurify6__default.default.sanitize(line, sanitizeOptions)}</p>`;
|
|
6306
7145
|
}
|
|
6307
7146
|
i++;
|
|
6308
7147
|
}
|