@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/index.cjs
CHANGED
|
@@ -609,8 +609,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
609
609
|
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>`;
|
|
610
610
|
var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
|
|
611
611
|
var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
|
|
612
|
-
var
|
|
613
|
-
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>`;
|
|
612
|
+
var ICON_EXTERNAL_WINDOW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="3" y1="8" x2="21" y2="8"></line><circle cx="6" cy="5.5" r="0.75" fill="currentColor"></circle><circle cx="8.5" cy="5.5" r="0.75" fill="currentColor"></circle><polyline points="14 13 18 13 18 17"></polyline><line x1="11" y1="20" x2="18" y2="13"></line></svg>`;
|
|
614
613
|
var ICON_MAP = {
|
|
615
614
|
"zoom-in": ICON_ZOOM_IN,
|
|
616
615
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -637,28 +636,177 @@ var ICON_MAP = {
|
|
|
637
636
|
"forward-10": ICON_FAST_FORWARD,
|
|
638
637
|
"rewind": ICON_REWIND,
|
|
639
638
|
"replay-10": ICON_REWIND,
|
|
640
|
-
"speed": ICON_SPEED,
|
|
641
639
|
"open-window": ICON_EXTERNAL_WINDOW,
|
|
642
|
-
"external-window": ICON_EXTERNAL_WINDOW
|
|
640
|
+
"external-window": ICON_EXTERNAL_WINDOW,
|
|
641
|
+
"openWindow": ICON_EXTERNAL_WINDOW,
|
|
642
|
+
"openSeparateWindow": ICON_EXTERNAL_WINDOW
|
|
643
643
|
};
|
|
644
644
|
var ToolbarController = class {
|
|
645
645
|
el;
|
|
646
646
|
toolbarEl;
|
|
647
647
|
actions = [];
|
|
648
|
+
config = {};
|
|
648
649
|
pageInputEl = null;
|
|
649
650
|
pageLabelEl = null;
|
|
650
|
-
|
|
651
|
+
prevPageBtn = null;
|
|
652
|
+
nextPageBtn = null;
|
|
653
|
+
constructor(container, config) {
|
|
651
654
|
this.el = container;
|
|
655
|
+
if (config) this.config = { ...config };
|
|
652
656
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
653
657
|
this.el.appendChild(this.toolbarEl);
|
|
654
658
|
}
|
|
659
|
+
setConfig(config) {
|
|
660
|
+
this.config = { ...config };
|
|
661
|
+
this.render();
|
|
662
|
+
}
|
|
663
|
+
getConfig() {
|
|
664
|
+
return { ...this.config };
|
|
665
|
+
}
|
|
666
|
+
hideAction(actionId) {
|
|
667
|
+
this.config[actionId] = false;
|
|
668
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = false;
|
|
669
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = false;
|
|
670
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
671
|
+
this.config.fitPage = false;
|
|
672
|
+
this.config.fitToPage = false;
|
|
673
|
+
this.config.fitWidth = false;
|
|
674
|
+
}
|
|
675
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
|
|
676
|
+
if (actionId === "fullscreen") this.config.fullscreen = false;
|
|
677
|
+
if (actionId === "download") this.config.download = false;
|
|
678
|
+
if (actionId === "print") this.config.print = false;
|
|
679
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
680
|
+
this.config.openWindow = false;
|
|
681
|
+
this.config.openSeparateWindow = false;
|
|
682
|
+
}
|
|
683
|
+
if (actionId === "copy") this.config.copy = false;
|
|
684
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
685
|
+
this.config.pageNav = false;
|
|
686
|
+
this.config.pagination = false;
|
|
687
|
+
}
|
|
688
|
+
this.render();
|
|
689
|
+
}
|
|
690
|
+
showAction(actionId) {
|
|
691
|
+
this.config[actionId] = true;
|
|
692
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = true;
|
|
693
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = true;
|
|
694
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
695
|
+
this.config.fitPage = true;
|
|
696
|
+
this.config.fitToPage = true;
|
|
697
|
+
this.config.fitWidth = true;
|
|
698
|
+
}
|
|
699
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
|
|
700
|
+
if (actionId === "fullscreen") this.config.fullscreen = true;
|
|
701
|
+
if (actionId === "download") this.config.download = true;
|
|
702
|
+
if (actionId === "print") this.config.print = true;
|
|
703
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
704
|
+
this.config.openWindow = true;
|
|
705
|
+
this.config.openSeparateWindow = true;
|
|
706
|
+
}
|
|
707
|
+
if (actionId === "copy") this.config.copy = true;
|
|
708
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
709
|
+
this.config.pageNav = true;
|
|
710
|
+
this.config.pagination = true;
|
|
711
|
+
}
|
|
712
|
+
this.render();
|
|
713
|
+
}
|
|
714
|
+
normalizeActionId(actionId) {
|
|
715
|
+
if (actionId === "zoomIn") return "zoom-in";
|
|
716
|
+
if (actionId === "zoomOut") return "zoom-out";
|
|
717
|
+
if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
|
|
718
|
+
if (actionId === "rotateCW") return "rotate-cw";
|
|
719
|
+
if (actionId === "rotateCCW") return "rotate-ccw";
|
|
720
|
+
if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
|
|
721
|
+
if (actionId === "pageNav") return "page-nav";
|
|
722
|
+
return actionId;
|
|
723
|
+
}
|
|
724
|
+
enableAction(actionId) {
|
|
725
|
+
const norm = this.normalizeActionId(actionId);
|
|
726
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
727
|
+
if (btn) {
|
|
728
|
+
btn.disabled = false;
|
|
729
|
+
btn.classList.remove("disabled");
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
disableAction(actionId) {
|
|
733
|
+
const norm = this.normalizeActionId(actionId);
|
|
734
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
735
|
+
if (btn) {
|
|
736
|
+
btn.disabled = true;
|
|
737
|
+
btn.classList.add("disabled");
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
setActionActive(actionId, active) {
|
|
741
|
+
const norm = this.normalizeActionId(actionId);
|
|
742
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
743
|
+
if (btn) {
|
|
744
|
+
if (active) {
|
|
745
|
+
btn.classList.add("active");
|
|
746
|
+
} else {
|
|
747
|
+
btn.classList.remove("active");
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
isActionEnabled(action) {
|
|
752
|
+
const c = this.config;
|
|
753
|
+
const id = action.id;
|
|
754
|
+
if (c[id] === false) return false;
|
|
755
|
+
if (id === "zoom-in" && (c.zoomIn === false || c["zoom-in"] === false)) return false;
|
|
756
|
+
if (id === "zoom-out" && (c.zoomOut === false || c["zoom-out"] === false)) return false;
|
|
757
|
+
if ((id === "fit-page" || id === "fit-width" || id === "fit-slide") && (c.fitPage === false || c.fitToPage === false || c.fitWidth === false || c["fit-page"] === false || c["fit-width"] === false)) {
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
|
|
761
|
+
return false;
|
|
762
|
+
}
|
|
763
|
+
if (id === "fullscreen" && c.fullscreen === false) return false;
|
|
764
|
+
if (id === "download" && c.download === false) return false;
|
|
765
|
+
if (id === "print" && c.print === false) return false;
|
|
766
|
+
if ((id === "open-window" || id === "external-window") && (c.openWindow === false || c.openSeparateWindow === false || c["open-window"] === false)) {
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
if (id === "copy" && c.copy === false) return false;
|
|
770
|
+
if (id === "thumbnails" && c.thumbnails === false) return false;
|
|
771
|
+
if (id === "page-nav" && (c.pageNav === false || c.pagination === false || c["page-nav"] === false)) {
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
if ((id === "prev" || id === "page-prev") && (c.prevPage === false || c.prev === false || c["prev"] === false || c.pageNav === false || c.pagination === false)) {
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
if ((id === "next" || id === "page-next") && (c.nextPage === false || c.next === false || c["next"] === false || c.pageNav === false || c.pagination === false)) {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
if (id === "play" && c.play === false) return false;
|
|
781
|
+
if (id === "pause" && c.pause === false) return false;
|
|
782
|
+
if ((id === "fast-forward" || id === "forward-10") && (c.fastForward === false || c["fast-forward"] === false)) {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
if ((id === "rewind" || id === "replay-10") && (c.rewind === false || c["rewind"] === false)) {
|
|
786
|
+
return false;
|
|
787
|
+
}
|
|
788
|
+
if (id === "speed" && c.speed === false) return false;
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
655
791
|
setPage(page, max) {
|
|
656
792
|
if (this.pageInputEl) {
|
|
657
793
|
this.pageInputEl.value = page.toString();
|
|
794
|
+
if (max !== void 0) {
|
|
795
|
+
this.pageInputEl.max = max.toString();
|
|
796
|
+
}
|
|
658
797
|
}
|
|
659
798
|
if (max !== void 0 && this.pageLabelEl) {
|
|
660
799
|
this.pageLabelEl.textContent = ` / ${max}`;
|
|
661
800
|
}
|
|
801
|
+
const currentMax = max !== void 0 ? max : parseInt(this.pageInputEl?.max || "1", 10) || 1;
|
|
802
|
+
if (this.prevPageBtn) {
|
|
803
|
+
this.prevPageBtn.disabled = page <= 1;
|
|
804
|
+
this.prevPageBtn.style.opacity = page <= 1 ? "0.4" : "1";
|
|
805
|
+
}
|
|
806
|
+
if (this.nextPageBtn) {
|
|
807
|
+
this.nextPageBtn.disabled = page >= currentMax;
|
|
808
|
+
this.nextPageBtn.style.opacity = page >= currentMax ? "0.4" : "1";
|
|
809
|
+
}
|
|
662
810
|
}
|
|
663
811
|
update(actions) {
|
|
664
812
|
this.actions = actions;
|
|
@@ -681,8 +829,9 @@ var ToolbarController = class {
|
|
|
681
829
|
view: [],
|
|
682
830
|
actions: []
|
|
683
831
|
};
|
|
684
|
-
const
|
|
685
|
-
const
|
|
832
|
+
const enabledActions = this.actions.filter((a) => this.isActionEnabled(a));
|
|
833
|
+
const hasPageNav = enabledActions.some((a) => a.type === "page-nav");
|
|
834
|
+
const effectiveActions = hasPageNav ? enabledActions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : enabledActions;
|
|
686
835
|
for (const action of effectiveActions) {
|
|
687
836
|
if (groups[action.group]) {
|
|
688
837
|
groups[action.group].push(action);
|
|
@@ -742,6 +891,13 @@ var ToolbarController = class {
|
|
|
742
891
|
action.execute("go", val);
|
|
743
892
|
});
|
|
744
893
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
894
|
+
const curVal = action.value ?? 1;
|
|
895
|
+
prevBtn.disabled = curVal <= 1;
|
|
896
|
+
prevBtn.style.opacity = curVal <= 1 ? "0.4" : "1";
|
|
897
|
+
nextBtn.disabled = curVal >= max;
|
|
898
|
+
nextBtn.style.opacity = curVal >= max ? "0.4" : "1";
|
|
899
|
+
this.prevPageBtn = prevBtn;
|
|
900
|
+
this.nextPageBtn = nextBtn;
|
|
745
901
|
this.pageInputEl = input;
|
|
746
902
|
this.pageLabelEl = label;
|
|
747
903
|
groupEl.appendChild(prevBtn);
|
|
@@ -797,25 +953,63 @@ var ToolbarController = class {
|
|
|
797
953
|
var ThumbnailPanel = class {
|
|
798
954
|
el;
|
|
799
955
|
panelEl;
|
|
956
|
+
listEl;
|
|
957
|
+
headerEl;
|
|
800
958
|
thumbnails = [];
|
|
801
959
|
onSelect;
|
|
960
|
+
onToggleCallback;
|
|
802
961
|
activeIndex = 0;
|
|
803
|
-
|
|
962
|
+
observer;
|
|
963
|
+
renderedIndices = /* @__PURE__ */ new Set();
|
|
964
|
+
constructor(container, onToggle) {
|
|
804
965
|
this.el = container;
|
|
966
|
+
this.onToggleCallback = onToggle;
|
|
805
967
|
this.panelEl = createElement("div", { className: "fp-thumbnail-panel hidden" });
|
|
968
|
+
this.panelEl.style.width = "0px";
|
|
969
|
+
this.panelEl.style.minWidth = "0px";
|
|
970
|
+
this.panelEl.style.opacity = "0";
|
|
971
|
+
this.headerEl = createElement("div", { className: "fp-thumbnail-header" });
|
|
972
|
+
const title = createElement("span", { className: "fp-thumbnail-title" }, "Pages");
|
|
973
|
+
const closeBtn = createElement("button", {
|
|
974
|
+
className: "fp-thumbnail-close-btn",
|
|
975
|
+
title: "Close Thumbnails",
|
|
976
|
+
type: "button"
|
|
977
|
+
});
|
|
978
|
+
closeBtn.innerHTML = ICON_CLOSE;
|
|
979
|
+
closeBtn.addEventListener("click", (e) => {
|
|
980
|
+
e.stopPropagation();
|
|
981
|
+
this.hide();
|
|
982
|
+
});
|
|
983
|
+
this.headerEl.appendChild(title);
|
|
984
|
+
this.headerEl.appendChild(closeBtn);
|
|
985
|
+
this.listEl = createElement("div", { className: "fp-thumbnail-list" });
|
|
986
|
+
this.panelEl.appendChild(this.headerEl);
|
|
987
|
+
this.panelEl.appendChild(this.listEl);
|
|
806
988
|
this.el.appendChild(this.panelEl);
|
|
807
989
|
}
|
|
990
|
+
isOpen() {
|
|
991
|
+
return !this.panelEl.classList.contains("hidden") && this.panelEl.style.width !== "0px";
|
|
992
|
+
}
|
|
808
993
|
update(thumbnails, onSelect) {
|
|
809
994
|
this.thumbnails = thumbnails;
|
|
810
995
|
this.onSelect = onSelect;
|
|
996
|
+
this.renderedIndices.clear();
|
|
997
|
+
const titleEl = this.headerEl.querySelector(".fp-thumbnail-title");
|
|
998
|
+
if (titleEl) {
|
|
999
|
+
titleEl.textContent = `Pages (${thumbnails.length})`;
|
|
1000
|
+
}
|
|
811
1001
|
this.render();
|
|
1002
|
+
if (this.isOpen()) {
|
|
1003
|
+
this.renderAllVisible();
|
|
1004
|
+
}
|
|
812
1005
|
}
|
|
813
1006
|
setActive(index) {
|
|
814
1007
|
this.activeIndex = index;
|
|
815
|
-
const items = this.
|
|
1008
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
816
1009
|
items.forEach((item, i) => {
|
|
817
1010
|
if (i === index) {
|
|
818
1011
|
item.classList.add("active");
|
|
1012
|
+
item.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
819
1013
|
} else {
|
|
820
1014
|
item.classList.remove("active");
|
|
821
1015
|
}
|
|
@@ -823,37 +1017,102 @@ var ThumbnailPanel = class {
|
|
|
823
1017
|
}
|
|
824
1018
|
show() {
|
|
825
1019
|
this.panelEl.classList.remove("hidden");
|
|
1020
|
+
this.panelEl.style.width = "200px";
|
|
1021
|
+
this.panelEl.style.minWidth = "200px";
|
|
1022
|
+
this.panelEl.style.opacity = "1";
|
|
1023
|
+
this.panelEl.style.display = "flex";
|
|
1024
|
+
this.onToggleCallback?.(true);
|
|
1025
|
+
this.renderAllVisible();
|
|
826
1026
|
}
|
|
827
1027
|
hide() {
|
|
828
1028
|
this.panelEl.classList.add("hidden");
|
|
1029
|
+
this.panelEl.style.width = "0px";
|
|
1030
|
+
this.panelEl.style.minWidth = "0px";
|
|
1031
|
+
this.panelEl.style.opacity = "0";
|
|
1032
|
+
this.onToggleCallback?.(false);
|
|
829
1033
|
}
|
|
830
1034
|
toggle() {
|
|
831
|
-
this.
|
|
1035
|
+
if (this.isOpen()) {
|
|
1036
|
+
this.hide();
|
|
1037
|
+
} else {
|
|
1038
|
+
this.show();
|
|
1039
|
+
}
|
|
832
1040
|
}
|
|
833
1041
|
destroy() {
|
|
1042
|
+
if (this.observer) {
|
|
1043
|
+
this.observer.disconnect();
|
|
1044
|
+
this.observer = void 0;
|
|
1045
|
+
}
|
|
1046
|
+
this.renderedIndices.clear();
|
|
834
1047
|
this.el.innerHTML = "";
|
|
835
1048
|
}
|
|
836
|
-
|
|
837
|
-
this.
|
|
1049
|
+
renderAllVisible() {
|
|
1050
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
1051
|
+
items.forEach((item) => {
|
|
1052
|
+
const idx = parseInt(item.dataset.thumbIndex || "-1", 10);
|
|
1053
|
+
if (idx >= 0 && !this.renderedIndices.has(idx)) {
|
|
1054
|
+
this.renderThumbnailItem(idx, item);
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
renderThumbnailItem(idx, itemEl) {
|
|
1059
|
+
if (this.renderedIndices.has(idx)) return;
|
|
1060
|
+
this.renderedIndices.add(idx);
|
|
1061
|
+
const canvas = itemEl.querySelector("canvas");
|
|
1062
|
+
const thumb = this.thumbnails[idx];
|
|
1063
|
+
if (canvas && thumb) {
|
|
1064
|
+
Promise.resolve(thumb.render(canvas)).catch((err) => {
|
|
1065
|
+
console.warn(`[FilePreview] Error rendering thumbnail ${idx}:`, err);
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
render() {
|
|
1070
|
+
if (this.observer) {
|
|
1071
|
+
this.observer.disconnect();
|
|
1072
|
+
}
|
|
1073
|
+
this.listEl.innerHTML = "";
|
|
1074
|
+
const useObserver = typeof IntersectionObserver !== "undefined";
|
|
1075
|
+
if (useObserver) {
|
|
1076
|
+
this.observer = new IntersectionObserver(
|
|
1077
|
+
(entries) => {
|
|
1078
|
+
for (const entry of entries) {
|
|
1079
|
+
if (entry.isIntersecting) {
|
|
1080
|
+
const target = entry.target;
|
|
1081
|
+
const idx = parseInt(target.dataset.thumbIndex || "-1", 10);
|
|
1082
|
+
if (idx >= 0) {
|
|
1083
|
+
this.renderThumbnailItem(idx, target);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
root: this.listEl,
|
|
1090
|
+
rootMargin: "120px 0px 120px 0px"
|
|
1091
|
+
}
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
838
1094
|
for (let i = 0; i < this.thumbnails.length; i++) {
|
|
839
1095
|
const thumb = this.thumbnails[i];
|
|
840
|
-
const itemEl = createElement("div", {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1096
|
+
const itemEl = createElement("div", {
|
|
1097
|
+
className: "fp-thumbnail-item" + (i === this.activeIndex ? " active" : "")
|
|
1098
|
+
});
|
|
1099
|
+
itemEl.dataset.thumbIndex = i.toString();
|
|
844
1100
|
itemEl.addEventListener("click", () => {
|
|
845
1101
|
this.setActive(i);
|
|
846
1102
|
this.onSelect?.(i);
|
|
847
1103
|
});
|
|
848
|
-
const
|
|
849
|
-
const
|
|
850
|
-
|
|
1104
|
+
const canvasWrapper = createElement("div", { className: "fp-thumbnail-canvas-wrapper" });
|
|
1105
|
+
const canvas = createElement("canvas", { width: "130", height: "170" });
|
|
1106
|
+
canvasWrapper.appendChild(canvas);
|
|
1107
|
+
const label = createElement("span", { className: "fp-thumbnail-label" }, thumb.label || `Page ${i + 1}`);
|
|
1108
|
+
itemEl.appendChild(canvasWrapper);
|
|
851
1109
|
itemEl.appendChild(label);
|
|
852
|
-
this.
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
}
|
|
856
|
-
|
|
1110
|
+
this.listEl.appendChild(itemEl);
|
|
1111
|
+
if (this.observer) {
|
|
1112
|
+
this.observer.observe(itemEl);
|
|
1113
|
+
}
|
|
1114
|
+
if (i < 4) {
|
|
1115
|
+
this.renderThumbnailItem(i, itemEl);
|
|
857
1116
|
}
|
|
858
1117
|
}
|
|
859
1118
|
}
|
|
@@ -874,6 +1133,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
874
1133
|
currentOptions = {};
|
|
875
1134
|
resizeObserver = null;
|
|
876
1135
|
fullscreenHandler = null;
|
|
1136
|
+
titleBarEl = null;
|
|
877
1137
|
/**
|
|
878
1138
|
* Register a preview plugin.
|
|
879
1139
|
*/
|
|
@@ -910,6 +1170,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
910
1170
|
}
|
|
911
1171
|
this.currentBuffer = buffer.slice(0);
|
|
912
1172
|
this.currentMetadata = metadata;
|
|
1173
|
+
this.updateTitleBar(options, metadata);
|
|
913
1174
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
914
1175
|
const fileInfo = { metadata, buffer };
|
|
915
1176
|
const matchedPlugin = await this.findPlugin(fileInfo);
|
|
@@ -933,15 +1194,21 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
933
1194
|
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
934
1195
|
const total = payload.total ?? payload.totalPages;
|
|
935
1196
|
this.toolbar?.setPage(payload.page, total);
|
|
1197
|
+
this.thumbnailPanel?.setActive(payload.page - 1);
|
|
936
1198
|
}
|
|
937
1199
|
this.eventEmitter.emit(event, payload);
|
|
938
|
-
}
|
|
1200
|
+
},
|
|
1201
|
+
toggleThumbnails: () => this.toggleThumbnails()
|
|
939
1202
|
});
|
|
940
1203
|
this.activeInstance = instance;
|
|
941
1204
|
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
1205
|
+
instance.toggleThumbnails = () => this.toggleThumbnails();
|
|
942
1206
|
this.hideLoading();
|
|
943
1207
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
944
|
-
|
|
1208
|
+
const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
|
|
1209
|
+
if (isToolbarVisible && this.toolbar) {
|
|
1210
|
+
const toolbarConfig = this.extractToolbarConfig(options);
|
|
1211
|
+
this.toolbar.setConfig(toolbarConfig);
|
|
945
1212
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
946
1213
|
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
947
1214
|
if (!hasFullscreen && this.wrapperEl) {
|
|
@@ -991,6 +1258,12 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
991
1258
|
}
|
|
992
1259
|
});
|
|
993
1260
|
}
|
|
1261
|
+
const thumbAction = actions.find((a) => a.id === "thumbnails");
|
|
1262
|
+
if (thumbAction) {
|
|
1263
|
+
thumbAction.execute = () => {
|
|
1264
|
+
this.toggleThumbnails();
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
994
1267
|
this.toolbar.update(actions);
|
|
995
1268
|
this.toolbar.show();
|
|
996
1269
|
}
|
|
@@ -1075,7 +1348,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1075
1348
|
if (targetUrl) {
|
|
1076
1349
|
const newWin2 = window.open(targetUrl, "_blank");
|
|
1077
1350
|
if (!newWin2) {
|
|
1078
|
-
|
|
1351
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1079
1352
|
return null;
|
|
1080
1353
|
}
|
|
1081
1354
|
return newWin2;
|
|
@@ -1083,7 +1356,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1083
1356
|
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1084
1357
|
const newWin = window.open("", "_blank");
|
|
1085
1358
|
if (!newWin) {
|
|
1086
|
-
|
|
1359
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1087
1360
|
return null;
|
|
1088
1361
|
}
|
|
1089
1362
|
newWin.document.title = title;
|
|
@@ -1160,6 +1433,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1160
1433
|
this.currentBuffer = null;
|
|
1161
1434
|
this.currentMetadata = null;
|
|
1162
1435
|
this.currentContainer = null;
|
|
1436
|
+
this.titleBarEl = null;
|
|
1163
1437
|
}
|
|
1164
1438
|
/**
|
|
1165
1439
|
* Get the currently active preview instance.
|
|
@@ -1167,7 +1441,218 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1167
1441
|
getInstance() {
|
|
1168
1442
|
return this.activeInstance;
|
|
1169
1443
|
}
|
|
1444
|
+
// --- Toolbar Configuration & Feature Toggles ---
|
|
1445
|
+
/**
|
|
1446
|
+
* Configure toolbar features dynamically through options or methods.
|
|
1447
|
+
* e.g. viewer.setToolbarConfig({ zoomIn: false, print: false })
|
|
1448
|
+
*/
|
|
1449
|
+
setToolbarConfig(config) {
|
|
1450
|
+
this.toolbar?.setConfig(config);
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Get current toolbar configuration.
|
|
1454
|
+
*/
|
|
1455
|
+
getToolbarConfig() {
|
|
1456
|
+
return this.toolbar?.getConfig() ?? {};
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Hide a specific toolbar action by ID or alias (e.g. 'zoom-in', 'print', 'download').
|
|
1460
|
+
*/
|
|
1461
|
+
hideToolbarAction(actionId) {
|
|
1462
|
+
this.toolbar?.hideAction(actionId);
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Show a specific toolbar action by ID or alias.
|
|
1466
|
+
*/
|
|
1467
|
+
showToolbarAction(actionId) {
|
|
1468
|
+
this.toolbar?.showAction(actionId);
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Enable a specific toolbar action button.
|
|
1472
|
+
*/
|
|
1473
|
+
enableToolbarAction(actionId) {
|
|
1474
|
+
this.toolbar?.enableAction(actionId);
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Disable a specific toolbar action button.
|
|
1478
|
+
*/
|
|
1479
|
+
disableToolbarAction(actionId) {
|
|
1480
|
+
this.toolbar?.disableAction(actionId);
|
|
1481
|
+
}
|
|
1482
|
+
// --- Programmatic Toolbar Action Methods ---
|
|
1483
|
+
/**
|
|
1484
|
+
* Fit document to page so it fills the frame width with minimal margins.
|
|
1485
|
+
*/
|
|
1486
|
+
fitToPage() {
|
|
1487
|
+
this.activeInstance?.fitToPage?.();
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Zoom in.
|
|
1491
|
+
*/
|
|
1492
|
+
zoomIn() {
|
|
1493
|
+
this.activeInstance?.zoomIn?.();
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* Zoom out.
|
|
1497
|
+
*/
|
|
1498
|
+
zoomOut() {
|
|
1499
|
+
this.activeInstance?.zoomOut?.();
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Set specific zoom level.
|
|
1503
|
+
*/
|
|
1504
|
+
setZoom(level) {
|
|
1505
|
+
this.activeInstance?.setZoom?.(level);
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Get current zoom level.
|
|
1509
|
+
*/
|
|
1510
|
+
getZoom() {
|
|
1511
|
+
return this.activeInstance?.getZoom?.() ?? 1;
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Rotate 90 degrees clockwise.
|
|
1515
|
+
*/
|
|
1516
|
+
rotateCW() {
|
|
1517
|
+
this.activeInstance?.rotateCW?.();
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Rotate 90 degrees counter-clockwise.
|
|
1521
|
+
*/
|
|
1522
|
+
rotateCCW() {
|
|
1523
|
+
this.activeInstance?.rotateCCW?.();
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Navigate to a specific page number.
|
|
1527
|
+
*/
|
|
1528
|
+
goToPage(page) {
|
|
1529
|
+
this.activeInstance?.goToPage?.(page);
|
|
1530
|
+
this.toolbar?.setPage(page);
|
|
1531
|
+
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Navigate to next page.
|
|
1534
|
+
*/
|
|
1535
|
+
nextPage() {
|
|
1536
|
+
const cur = this.getCurrentPage();
|
|
1537
|
+
const max = this.getPageCount();
|
|
1538
|
+
if (cur < max) {
|
|
1539
|
+
this.goToPage(cur + 1);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Navigate to previous page.
|
|
1544
|
+
*/
|
|
1545
|
+
prevPage() {
|
|
1546
|
+
const cur = this.getCurrentPage();
|
|
1547
|
+
if (cur > 1) {
|
|
1548
|
+
this.goToPage(cur - 1);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Get total page count.
|
|
1553
|
+
*/
|
|
1554
|
+
getPageCount() {
|
|
1555
|
+
return this.activeInstance?.getPageCount?.() ?? 1;
|
|
1556
|
+
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Get current page number.
|
|
1559
|
+
*/
|
|
1560
|
+
getCurrentPage() {
|
|
1561
|
+
return this.activeInstance?.getCurrentPage?.() ?? 1;
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Download the current document.
|
|
1565
|
+
*/
|
|
1566
|
+
download() {
|
|
1567
|
+
this.activeInstance?.download?.();
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Print the current document.
|
|
1571
|
+
*/
|
|
1572
|
+
print() {
|
|
1573
|
+
this.activeInstance?.print?.();
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Toggle fullscreen mode.
|
|
1577
|
+
*/
|
|
1578
|
+
toggleFullscreen() {
|
|
1579
|
+
try {
|
|
1580
|
+
if (!document.fullscreenElement) {
|
|
1581
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
1582
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
1583
|
+
} else {
|
|
1584
|
+
document.exitFullscreen?.();
|
|
1585
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
1586
|
+
}
|
|
1587
|
+
} catch {
|
|
1588
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
1589
|
+
}
|
|
1590
|
+
setTimeout(() => {
|
|
1591
|
+
this.activeInstance?.fitToPage?.();
|
|
1592
|
+
}, 120);
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Toggle thumbnails sidebar panel.
|
|
1596
|
+
*/
|
|
1597
|
+
toggleThumbnails() {
|
|
1598
|
+
if (!this.thumbnailPanel) return;
|
|
1599
|
+
this.thumbnailPanel.toggle();
|
|
1600
|
+
const isOpen = this.thumbnailPanel.isOpen();
|
|
1601
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1602
|
+
setTimeout(() => {
|
|
1603
|
+
this.activeInstance?.fitToPage?.();
|
|
1604
|
+
}, 260);
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Set whether to display the file name / title bar above the toolbar.
|
|
1608
|
+
*/
|
|
1609
|
+
setShowFileName(show) {
|
|
1610
|
+
if (this.currentOptions) {
|
|
1611
|
+
this.currentOptions.showFileName = show;
|
|
1612
|
+
}
|
|
1613
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Set or override the displayed file name in the preview panel.
|
|
1617
|
+
*/
|
|
1618
|
+
setFileName(name) {
|
|
1619
|
+
if (this.currentOptions) {
|
|
1620
|
+
this.currentOptions.fileName = name;
|
|
1621
|
+
}
|
|
1622
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1623
|
+
}
|
|
1170
1624
|
// --- Private methods ---
|
|
1625
|
+
updateTitleBar(options, metadata) {
|
|
1626
|
+
if (!this.titleBarEl) return;
|
|
1627
|
+
const show = options?.showFileName !== false;
|
|
1628
|
+
if (!show) {
|
|
1629
|
+
this.titleBarEl.style.display = "none";
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
const name = options?.fileName || metadata?.name || this.currentMetadata?.name || "";
|
|
1633
|
+
if (!name) {
|
|
1634
|
+
this.titleBarEl.style.display = "none";
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
this.titleBarEl.style.display = "flex";
|
|
1638
|
+
const ext = metadata?.extension || (name.includes(".") ? "." + name.split(".").pop() : "");
|
|
1639
|
+
const badge = ext ? ext.replace(".", "").toUpperCase() : "";
|
|
1640
|
+
this.titleBarEl.innerHTML = `
|
|
1641
|
+
<div class="fp-titlebar-info">
|
|
1642
|
+
<span class="fp-titlebar-icon">\u{1F4C4}</span>
|
|
1643
|
+
<span class="fp-titlebar-name" title="${name}">${name}</span>
|
|
1644
|
+
${badge ? `<span class="fp-titlebar-badge">${badge}</span>` : ""}
|
|
1645
|
+
</div>
|
|
1646
|
+
`;
|
|
1647
|
+
}
|
|
1648
|
+
extractToolbarConfig(options) {
|
|
1649
|
+
if (!options) return {};
|
|
1650
|
+
const nested = typeof options.toolbar === "object" ? options.toolbar : {};
|
|
1651
|
+
return {
|
|
1652
|
+
...options,
|
|
1653
|
+
...nested
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1171
1656
|
abort() {
|
|
1172
1657
|
if (this.abortController) {
|
|
1173
1658
|
this.abortController.abort();
|
|
@@ -1210,17 +1695,29 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1210
1695
|
bodyEl.className = "fp-body";
|
|
1211
1696
|
bodyEl.appendChild(thumbnailEl);
|
|
1212
1697
|
bodyEl.appendChild(this.contentEl);
|
|
1698
|
+
const titleBarEl = document.createElement("div");
|
|
1699
|
+
titleBarEl.className = "fp-titlebar";
|
|
1700
|
+
this.titleBarEl = titleBarEl;
|
|
1701
|
+
this.updateTitleBar(options, this.currentMetadata);
|
|
1213
1702
|
if (toolbarPos === "top") {
|
|
1703
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1214
1704
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1215
1705
|
this.wrapperEl.appendChild(bodyEl);
|
|
1216
1706
|
} else {
|
|
1707
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1217
1708
|
this.wrapperEl.appendChild(bodyEl);
|
|
1218
1709
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1219
1710
|
}
|
|
1220
1711
|
container.innerHTML = "";
|
|
1221
1712
|
container.appendChild(this.wrapperEl);
|
|
1222
|
-
|
|
1223
|
-
this.
|
|
1713
|
+
const initialToolbarConfig = this.extractToolbarConfig(options);
|
|
1714
|
+
this.toolbar = new ToolbarController(toolbarEl, initialToolbarConfig);
|
|
1715
|
+
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl, (isOpen) => {
|
|
1716
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1717
|
+
setTimeout(() => {
|
|
1718
|
+
this.activeInstance?.fitToPage?.();
|
|
1719
|
+
}, 260);
|
|
1720
|
+
});
|
|
1224
1721
|
this.setupKeyboardShortcuts();
|
|
1225
1722
|
this.setupDragAndDrop(container, options);
|
|
1226
1723
|
this.setupResizeAndFullscreenListeners();
|
|
@@ -1610,6 +2107,14 @@ var PdfPlugin = class {
|
|
|
1610
2107
|
group: "zoom",
|
|
1611
2108
|
execute: () => instance.fitToPage?.()
|
|
1612
2109
|
},
|
|
2110
|
+
{
|
|
2111
|
+
id: "fit-width",
|
|
2112
|
+
icon: "fit-width",
|
|
2113
|
+
label: "Fit to Width",
|
|
2114
|
+
type: "button",
|
|
2115
|
+
group: "zoom",
|
|
2116
|
+
execute: () => instance.fitToWidth?.()
|
|
2117
|
+
},
|
|
1613
2118
|
{
|
|
1614
2119
|
id: "rotate-cw",
|
|
1615
2120
|
icon: "rotate-cw",
|
|
@@ -1618,6 +2123,14 @@ var PdfPlugin = class {
|
|
|
1618
2123
|
group: "view",
|
|
1619
2124
|
execute: () => instance.rotateCW?.()
|
|
1620
2125
|
},
|
|
2126
|
+
{
|
|
2127
|
+
id: "rotate-ccw",
|
|
2128
|
+
icon: "rotate-ccw",
|
|
2129
|
+
label: "Rotate Counter-Clockwise",
|
|
2130
|
+
type: "button",
|
|
2131
|
+
group: "view",
|
|
2132
|
+
execute: () => instance.rotateCCW?.()
|
|
2133
|
+
},
|
|
1621
2134
|
{
|
|
1622
2135
|
id: "download",
|
|
1623
2136
|
icon: "download",
|
|
@@ -1649,12 +2162,13 @@ var PdfPlugin = class {
|
|
|
1649
2162
|
container.className = "fp-pdf-container";
|
|
1650
2163
|
container.style.width = "100%";
|
|
1651
2164
|
container.style.height = "100%";
|
|
1652
|
-
container.style.
|
|
2165
|
+
container.style.overflowX = "hidden";
|
|
2166
|
+
container.style.overflowY = "auto";
|
|
1653
2167
|
container.style.display = "flex";
|
|
1654
2168
|
container.style.flexDirection = "column";
|
|
1655
2169
|
container.style.alignItems = "center";
|
|
1656
2170
|
container.style.justifyContent = "flex-start";
|
|
1657
|
-
container.style.padding = "
|
|
2171
|
+
container.style.padding = "16px 8px";
|
|
1658
2172
|
container.style.backgroundColor = "#0f172a";
|
|
1659
2173
|
container.style.boxSizing = "border-box";
|
|
1660
2174
|
container.style.position = "relative";
|
|
@@ -1665,30 +2179,12 @@ var PdfPlugin = class {
|
|
|
1665
2179
|
pageCard.style.borderRadius = "4px";
|
|
1666
2180
|
pageCard.style.overflow = "hidden";
|
|
1667
2181
|
pageCard.style.lineHeight = "0";
|
|
1668
|
-
pageCard.style.transition = "transform 0.15s ease";
|
|
1669
2182
|
pageCard.style.position = "relative";
|
|
1670
2183
|
pageCard.style.flexShrink = "0";
|
|
2184
|
+
pageCard.style.transition = "box-shadow 0.2s ease";
|
|
1671
2185
|
let canvas = document.createElement("canvas");
|
|
1672
2186
|
pageCard.appendChild(canvas);
|
|
1673
2187
|
container.appendChild(pageCard);
|
|
1674
|
-
const indicator = document.createElement("div");
|
|
1675
|
-
indicator.className = "fp-pdf-page-indicator";
|
|
1676
|
-
indicator.style.position = "sticky";
|
|
1677
|
-
indicator.style.bottom = "16px";
|
|
1678
|
-
indicator.style.marginTop = "16px";
|
|
1679
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1680
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
1681
|
-
indicator.style.color = "#f8fafc";
|
|
1682
|
-
indicator.style.fontSize = "12px";
|
|
1683
|
-
indicator.style.fontWeight = "600";
|
|
1684
|
-
indicator.style.padding = "5px 14px";
|
|
1685
|
-
indicator.style.borderRadius = "20px";
|
|
1686
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1687
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1688
|
-
indicator.style.zIndex = "10";
|
|
1689
|
-
indicator.style.userSelect = "none";
|
|
1690
|
-
indicator.style.pointerEvents = "none";
|
|
1691
|
-
container.appendChild(indicator);
|
|
1692
2188
|
ctx.container.appendChild(container);
|
|
1693
2189
|
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1694
2190
|
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
@@ -1704,8 +2200,9 @@ var PdfPlugin = class {
|
|
|
1704
2200
|
let currentPage = 1;
|
|
1705
2201
|
let zoomScale = 1;
|
|
1706
2202
|
let rotation = 0;
|
|
1707
|
-
let fitMode = "
|
|
2203
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
1708
2204
|
let currentRenderTask = null;
|
|
2205
|
+
let textLayerDiv = null;
|
|
1709
2206
|
const renderPage = async (pageNum) => {
|
|
1710
2207
|
if (currentRenderTask) {
|
|
1711
2208
|
try {
|
|
@@ -1717,30 +2214,37 @@ var PdfPlugin = class {
|
|
|
1717
2214
|
const newCanvas = document.createElement("canvas");
|
|
1718
2215
|
pageCard.replaceChild(newCanvas, canvas);
|
|
1719
2216
|
canvas = newCanvas;
|
|
2217
|
+
if (textLayerDiv) {
|
|
2218
|
+
textLayerDiv.remove();
|
|
2219
|
+
textLayerDiv = null;
|
|
2220
|
+
}
|
|
1720
2221
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1721
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1722
2222
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1723
2223
|
const page = await pdfDoc.getPage(currentPage);
|
|
1724
2224
|
const containerWidth = container.clientWidth || 900;
|
|
1725
2225
|
const containerHeight = container.clientHeight || 700;
|
|
1726
2226
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1727
|
-
const availWidth = Math.max(
|
|
1728
|
-
const availHeight = Math.max(
|
|
2227
|
+
const availWidth = Math.max(280, containerWidth - 36);
|
|
2228
|
+
const availHeight = Math.max(280, containerHeight - 32);
|
|
1729
2229
|
const scaleW = availWidth / unscaledVp.width;
|
|
1730
2230
|
const scaleH = availHeight / unscaledVp.height;
|
|
1731
2231
|
let fitScale;
|
|
1732
2232
|
if (fitMode === "page") {
|
|
1733
|
-
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
2233
|
+
fitScale = Math.max(0.2, Math.min(4, Math.min(scaleW, scaleH)));
|
|
1734
2234
|
} else {
|
|
1735
|
-
fitScale = Math.max(0.
|
|
2235
|
+
fitScale = Math.max(0.2, Math.min(4, scaleW));
|
|
1736
2236
|
}
|
|
1737
2237
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1738
2238
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1739
2239
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
2240
|
+
const displayWidth = Math.floor(viewport.width);
|
|
2241
|
+
const displayHeight = Math.floor(viewport.height);
|
|
1740
2242
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1741
2243
|
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1742
|
-
canvas.style.width = `${
|
|
1743
|
-
canvas.style.height = `${
|
|
2244
|
+
canvas.style.width = `${displayWidth}px`;
|
|
2245
|
+
canvas.style.height = `${displayHeight}px`;
|
|
2246
|
+
pageCard.style.width = `${displayWidth}px`;
|
|
2247
|
+
pageCard.style.height = `${displayHeight}px`;
|
|
1744
2248
|
const canvasCtx = canvas.getContext("2d");
|
|
1745
2249
|
if (!canvasCtx) return;
|
|
1746
2250
|
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
@@ -1754,9 +2258,31 @@ var PdfPlugin = class {
|
|
|
1754
2258
|
if (err?.name !== "RenderingCancelledException") {
|
|
1755
2259
|
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1756
2260
|
}
|
|
2261
|
+
return;
|
|
1757
2262
|
} finally {
|
|
1758
2263
|
currentRenderTask = null;
|
|
1759
2264
|
}
|
|
2265
|
+
try {
|
|
2266
|
+
textLayerDiv = document.createElement("div");
|
|
2267
|
+
textLayerDiv.className = "textLayer";
|
|
2268
|
+
textLayerDiv.style.width = `${displayWidth}px`;
|
|
2269
|
+
textLayerDiv.style.height = `${displayHeight}px`;
|
|
2270
|
+
textLayerDiv.style.position = "absolute";
|
|
2271
|
+
textLayerDiv.style.top = "0";
|
|
2272
|
+
textLayerDiv.style.left = "0";
|
|
2273
|
+
textLayerDiv.style.lineHeight = "1";
|
|
2274
|
+
pageCard.appendChild(textLayerDiv);
|
|
2275
|
+
if (pdfjsLib__namespace.TextLayer) {
|
|
2276
|
+
const textLayer = new pdfjsLib__namespace.TextLayer({
|
|
2277
|
+
textContentSource: page.streamTextContent(),
|
|
2278
|
+
container: textLayerDiv,
|
|
2279
|
+
viewport
|
|
2280
|
+
});
|
|
2281
|
+
await textLayer.render();
|
|
2282
|
+
}
|
|
2283
|
+
} catch (err) {
|
|
2284
|
+
console.debug("[PdfPlugin] TextLayer notice:", err);
|
|
2285
|
+
}
|
|
1760
2286
|
};
|
|
1761
2287
|
renderPage(1);
|
|
1762
2288
|
let resizeTimer = null;
|
|
@@ -1766,11 +2292,48 @@ var PdfPlugin = class {
|
|
|
1766
2292
|
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1767
2293
|
renderPage(currentPage);
|
|
1768
2294
|
}
|
|
1769
|
-
},
|
|
2295
|
+
}, 120);
|
|
1770
2296
|
});
|
|
1771
2297
|
resizeObserver.observe(container);
|
|
2298
|
+
const onWheel = (e) => {
|
|
2299
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2300
|
+
e.preventDefault();
|
|
2301
|
+
const delta = e.deltaY > 0 ? -0.15 : 0.15;
|
|
2302
|
+
zoomScale = Math.max(0.25, Math.min(4, Math.round((zoomScale + delta) * 100) / 100));
|
|
2303
|
+
renderPage(currentPage);
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
2307
|
+
const onKeyDown = (e) => {
|
|
2308
|
+
const tag = e.target?.tagName?.toLowerCase();
|
|
2309
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
2310
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
2311
|
+
if (currentPage < totalPages) {
|
|
2312
|
+
e.preventDefault();
|
|
2313
|
+
container.scrollTop = 0;
|
|
2314
|
+
renderPage(currentPage + 1);
|
|
2315
|
+
}
|
|
2316
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
2317
|
+
if (currentPage > 1) {
|
|
2318
|
+
e.preventDefault();
|
|
2319
|
+
container.scrollTop = 0;
|
|
2320
|
+
renderPage(currentPage - 1);
|
|
2321
|
+
}
|
|
2322
|
+
} else if (e.key === "Home") {
|
|
2323
|
+
e.preventDefault();
|
|
2324
|
+
container.scrollTop = 0;
|
|
2325
|
+
renderPage(1);
|
|
2326
|
+
} else if (e.key === "End") {
|
|
2327
|
+
e.preventDefault();
|
|
2328
|
+
container.scrollTop = 0;
|
|
2329
|
+
renderPage(totalPages);
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1772
2333
|
const cleanup = () => {
|
|
1773
2334
|
resizeObserver.disconnect();
|
|
2335
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2336
|
+
container.removeEventListener("wheel", onWheel);
|
|
1774
2337
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1775
2338
|
if (currentRenderTask) {
|
|
1776
2339
|
try {
|
|
@@ -1789,22 +2352,26 @@ var PdfPlugin = class {
|
|
|
1789
2352
|
const instance = {
|
|
1790
2353
|
destroy: cleanup,
|
|
1791
2354
|
zoomIn: () => {
|
|
1792
|
-
zoomScale = Math.min(
|
|
2355
|
+
zoomScale = Math.min(4, Math.round((zoomScale + 0.2) * 10) / 10);
|
|
1793
2356
|
renderPage(currentPage);
|
|
1794
2357
|
},
|
|
1795
2358
|
zoomOut: () => {
|
|
1796
|
-
zoomScale = Math.max(0.
|
|
2359
|
+
zoomScale = Math.max(0.25, Math.round((zoomScale - 0.2) * 10) / 10);
|
|
1797
2360
|
renderPage(currentPage);
|
|
1798
2361
|
},
|
|
1799
2362
|
getZoom: () => zoomScale,
|
|
1800
2363
|
setZoom: (level) => {
|
|
1801
|
-
zoomScale = Math.max(0.
|
|
2364
|
+
zoomScale = Math.max(0.25, Math.min(4, level));
|
|
1802
2365
|
renderPage(currentPage);
|
|
1803
2366
|
},
|
|
1804
2367
|
fitToPage: () => {
|
|
1805
|
-
fitMode =
|
|
2368
|
+
fitMode = "page";
|
|
2369
|
+
zoomScale = 1;
|
|
2370
|
+
renderPage(currentPage);
|
|
2371
|
+
},
|
|
2372
|
+
fitToWidth: () => {
|
|
2373
|
+
fitMode = "width";
|
|
1806
2374
|
zoomScale = 1;
|
|
1807
|
-
rotation = 0;
|
|
1808
2375
|
renderPage(currentPage);
|
|
1809
2376
|
},
|
|
1810
2377
|
rotateCW: () => {
|
|
@@ -1822,6 +2389,9 @@ var PdfPlugin = class {
|
|
|
1822
2389
|
container.scrollTop = 0;
|
|
1823
2390
|
renderPage(page);
|
|
1824
2391
|
},
|
|
2392
|
+
toggleThumbnails: () => {
|
|
2393
|
+
ctx?.toggleThumbnails?.();
|
|
2394
|
+
},
|
|
1825
2395
|
download: () => {
|
|
1826
2396
|
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1827
2397
|
const url = URL.createObjectURL(blob);
|
|
@@ -1855,7 +2425,7 @@ var PdfPlugin = class {
|
|
|
1855
2425
|
},
|
|
1856
2426
|
getThumbnails: async () => {
|
|
1857
2427
|
const thumbnails = [];
|
|
1858
|
-
const count =
|
|
2428
|
+
const count = totalPages;
|
|
1859
2429
|
for (let i = 1; i <= count; i++) {
|
|
1860
2430
|
thumbnails.push({
|
|
1861
2431
|
index: i,
|
|
@@ -1863,9 +2433,10 @@ var PdfPlugin = class {
|
|
|
1863
2433
|
render: async (thumbCanvas) => {
|
|
1864
2434
|
try {
|
|
1865
2435
|
const p = await pdfDoc.getPage(i);
|
|
1866
|
-
const baseVp = p.getViewport({ scale: 1 });
|
|
1867
|
-
const
|
|
1868
|
-
const
|
|
2436
|
+
const baseVp = p.getViewport({ scale: 1, rotation });
|
|
2437
|
+
const targetW = thumbCanvas.width || 130;
|
|
2438
|
+
const thumbScale = targetW / baseVp.width;
|
|
2439
|
+
const thumbVp = p.getViewport({ scale: thumbScale, rotation });
|
|
1869
2440
|
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1870
2441
|
const tCtx = thumbCanvas.getContext("2d");
|
|
1871
2442
|
if (tCtx) {
|
|
@@ -2209,28 +2780,26 @@ var DocxPlugin = class {
|
|
|
2209
2780
|
getToolbarActions(instance) {
|
|
2210
2781
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2211
2782
|
const actions = [];
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
if (
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
instance.goToPage?.(page);
|
|
2230
|
-
}
|
|
2783
|
+
actions.push({
|
|
2784
|
+
id: "page-nav",
|
|
2785
|
+
icon: "",
|
|
2786
|
+
label: "Page Navigation",
|
|
2787
|
+
type: "page-nav",
|
|
2788
|
+
group: "navigation",
|
|
2789
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2790
|
+
max: totalPages,
|
|
2791
|
+
execute: (action, page) => {
|
|
2792
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2793
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2794
|
+
if (action === "prev") {
|
|
2795
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2796
|
+
} else if (action === "next") {
|
|
2797
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2798
|
+
} else if (typeof page === "number") {
|
|
2799
|
+
instance.goToPage?.(page);
|
|
2231
2800
|
}
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2801
|
+
}
|
|
2802
|
+
});
|
|
2234
2803
|
actions.push(
|
|
2235
2804
|
{
|
|
2236
2805
|
id: "zoom-out",
|
|
@@ -2296,11 +2865,17 @@ var DocxPlugin = class {
|
|
|
2296
2865
|
wrapper.className = "fp-docx-wrapper";
|
|
2297
2866
|
wrapper.style.transformOrigin = "top center";
|
|
2298
2867
|
wrapper.style.transition = "transform 0.2s ease";
|
|
2299
|
-
wrapper.style.padding = "
|
|
2300
|
-
wrapper.style.maxWidth = "
|
|
2868
|
+
wrapper.style.padding = "0";
|
|
2869
|
+
wrapper.style.maxWidth = "none";
|
|
2870
|
+
wrapper.style.width = "816px";
|
|
2301
2871
|
wrapper.style.margin = "0 auto";
|
|
2872
|
+
wrapper.style.display = "flex";
|
|
2873
|
+
wrapper.style.flexDirection = "column";
|
|
2874
|
+
wrapper.style.alignItems = "center";
|
|
2302
2875
|
wrapper.style.boxSizing = "border-box";
|
|
2303
|
-
ctx.container.style.
|
|
2876
|
+
ctx.container.style.overflowX = "hidden";
|
|
2877
|
+
ctx.container.style.overflowY = "auto";
|
|
2878
|
+
ctx.container.style.padding = "16px 8px";
|
|
2304
2879
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
2305
2880
|
ctx.container.appendChild(wrapper);
|
|
2306
2881
|
const styleOverride = document.createElement("style");
|
|
@@ -2474,39 +3049,13 @@ var DocxPlugin = class {
|
|
|
2474
3049
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2475
3050
|
const totalPages = Math.max(1, pageElements.length);
|
|
2476
3051
|
let currentPage = 1;
|
|
2477
|
-
let indicator = null;
|
|
2478
|
-
if (totalPages > 1) {
|
|
2479
|
-
indicator = document.createElement("div");
|
|
2480
|
-
indicator.className = "fp-docx-page-indicator";
|
|
2481
|
-
indicator.style.position = "sticky";
|
|
2482
|
-
indicator.style.bottom = "16px";
|
|
2483
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2484
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
2485
|
-
indicator.style.color = "#f8fafc";
|
|
2486
|
-
indicator.style.fontSize = "12px";
|
|
2487
|
-
indicator.style.fontWeight = "600";
|
|
2488
|
-
indicator.style.padding = "5px 14px";
|
|
2489
|
-
indicator.style.borderRadius = "20px";
|
|
2490
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2491
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2492
|
-
indicator.style.zIndex = "10";
|
|
2493
|
-
indicator.style.userSelect = "none";
|
|
2494
|
-
indicator.style.pointerEvents = "none";
|
|
2495
|
-
indicator.style.textAlign = "center";
|
|
2496
|
-
indicator.style.width = "fit-content";
|
|
2497
|
-
indicator.style.margin = "16px auto 0";
|
|
2498
|
-
ctx.container.appendChild(indicator);
|
|
2499
|
-
}
|
|
2500
3052
|
const showPage = (pageNum) => {
|
|
2501
3053
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2502
3054
|
if (pageElements.length > 1) {
|
|
2503
3055
|
pageElements.forEach((sec, idx) => {
|
|
2504
|
-
sec.style.display = idx + 1 === currentPage ? "
|
|
3056
|
+
sec.style.display = idx + 1 === currentPage ? "" : "none";
|
|
2505
3057
|
});
|
|
2506
3058
|
}
|
|
2507
|
-
if (indicator) {
|
|
2508
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2509
|
-
}
|
|
2510
3059
|
ctx.container.scrollTop = 0;
|
|
2511
3060
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2512
3061
|
};
|
|
@@ -2515,31 +3064,46 @@ var DocxPlugin = class {
|
|
|
2515
3064
|
}
|
|
2516
3065
|
scale = 1;
|
|
2517
3066
|
let rotation = 0;
|
|
2518
|
-
let fitMode = "
|
|
2519
|
-
|
|
2520
|
-
|
|
3067
|
+
let fitMode = "page";
|
|
3068
|
+
let isUserZoomed = false;
|
|
3069
|
+
const calculateFitScale = (_mode = fitMode) => {
|
|
3070
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2521
3071
|
const elW = activeEl.offsetWidth || 816;
|
|
2522
|
-
const
|
|
2523
|
-
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2524
|
-
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
3072
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
2525
3073
|
const sW = availW / elW;
|
|
2526
|
-
|
|
2527
|
-
if (mode === "page") {
|
|
2528
|
-
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2529
|
-
}
|
|
2530
|
-
return Math.max(0.65, Math.min(1.05, sW));
|
|
3074
|
+
return Math.max(0.35, Math.min(3, sW));
|
|
2531
3075
|
};
|
|
2532
3076
|
const applyTransform = () => {
|
|
2533
3077
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2534
3078
|
wrapper.style.transformOrigin = "top center";
|
|
3079
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
3080
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
3081
|
+
if (scale > 1) {
|
|
3082
|
+
wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
|
|
3083
|
+
} else {
|
|
3084
|
+
wrapper.style.marginBottom = "32px";
|
|
3085
|
+
}
|
|
2535
3086
|
};
|
|
3087
|
+
let resizeObserver = null;
|
|
3088
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
3089
|
+
resizeObserver = new ResizeObserver(() => {
|
|
3090
|
+
if (!isUserZoomed) {
|
|
3091
|
+
const newFit = calculateFitScale("page");
|
|
3092
|
+
if (Math.abs(scale - newFit) > 0.015) {
|
|
3093
|
+
scale = newFit;
|
|
3094
|
+
applyTransform();
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
});
|
|
3098
|
+
resizeObserver.observe(ctx.container);
|
|
3099
|
+
}
|
|
2536
3100
|
setTimeout(() => {
|
|
2537
|
-
|
|
2538
|
-
scale = calculateFitScale("width");
|
|
3101
|
+
scale = calculateFitScale("page");
|
|
2539
3102
|
applyTransform();
|
|
2540
|
-
},
|
|
3103
|
+
}, 40);
|
|
2541
3104
|
const cleanup = () => {
|
|
2542
|
-
|
|
3105
|
+
resizeObserver?.disconnect();
|
|
3106
|
+
resizeObserver = null;
|
|
2543
3107
|
for (const url of createdBlobUrls) {
|
|
2544
3108
|
URL.revokeObjectURL(url);
|
|
2545
3109
|
}
|
|
@@ -2556,21 +3120,24 @@ var DocxPlugin = class {
|
|
|
2556
3120
|
showPage(page);
|
|
2557
3121
|
},
|
|
2558
3122
|
zoomIn: () => {
|
|
2559
|
-
|
|
3123
|
+
isUserZoomed = true;
|
|
3124
|
+
scale = Math.min(3.5, scale + 0.15);
|
|
2560
3125
|
applyTransform();
|
|
2561
3126
|
},
|
|
2562
3127
|
zoomOut: () => {
|
|
3128
|
+
isUserZoomed = true;
|
|
2563
3129
|
scale = Math.max(0.2, scale - 0.15);
|
|
2564
3130
|
applyTransform();
|
|
2565
3131
|
},
|
|
2566
3132
|
getZoom: () => scale,
|
|
2567
3133
|
setZoom: (level) => {
|
|
3134
|
+
isUserZoomed = true;
|
|
2568
3135
|
scale = level;
|
|
2569
3136
|
applyTransform();
|
|
2570
3137
|
},
|
|
2571
3138
|
fitToPage: () => {
|
|
2572
|
-
|
|
2573
|
-
scale = calculateFitScale(
|
|
3139
|
+
isUserZoomed = false;
|
|
3140
|
+
scale = calculateFitScale("page");
|
|
2574
3141
|
rotation = 0;
|
|
2575
3142
|
applyTransform();
|
|
2576
3143
|
},
|
|
@@ -2960,7 +3527,7 @@ var ExcelPlugin = class {
|
|
|
2960
3527
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
2961
3528
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
2962
3529
|
];
|
|
2963
|
-
weight =
|
|
3530
|
+
weight = 85;
|
|
2964
3531
|
supports(file) {
|
|
2965
3532
|
const ext = file.metadata.extension?.toLowerCase();
|
|
2966
3533
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
@@ -2972,6 +3539,14 @@ var ExcelPlugin = class {
|
|
|
2972
3539
|
getToolbarActions(instance) {
|
|
2973
3540
|
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2974
3541
|
const actions = [];
|
|
3542
|
+
actions.push({
|
|
3543
|
+
id: "thumbnails",
|
|
3544
|
+
icon: "thumbnails",
|
|
3545
|
+
label: "Sheet Thumbnails",
|
|
3546
|
+
type: "button",
|
|
3547
|
+
group: "navigation",
|
|
3548
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3549
|
+
});
|
|
2975
3550
|
if (totalSheets > 1) {
|
|
2976
3551
|
actions.push({
|
|
2977
3552
|
id: "page-nav",
|
|
@@ -3054,6 +3629,16 @@ var ExcelPlugin = class {
|
|
|
3054
3629
|
execute: () => {
|
|
3055
3630
|
instance.print?.();
|
|
3056
3631
|
}
|
|
3632
|
+
},
|
|
3633
|
+
{
|
|
3634
|
+
id: "open-window",
|
|
3635
|
+
icon: "open-window",
|
|
3636
|
+
label: "Open in Separate Full Window",
|
|
3637
|
+
type: "button",
|
|
3638
|
+
group: "actions",
|
|
3639
|
+
execute: () => {
|
|
3640
|
+
instance.openInSeparateWindow?.();
|
|
3641
|
+
}
|
|
3057
3642
|
}
|
|
3058
3643
|
);
|
|
3059
3644
|
return actions;
|
|
@@ -3219,6 +3804,63 @@ var ExcelPlugin = class {
|
|
|
3219
3804
|
},
|
|
3220
3805
|
getPageCount: () => sheetNames.length,
|
|
3221
3806
|
getCurrentPage: () => currentSheetIndex,
|
|
3807
|
+
getThumbnails: () => {
|
|
3808
|
+
return sheetNames.map((name, idx) => ({
|
|
3809
|
+
index: idx,
|
|
3810
|
+
label: name,
|
|
3811
|
+
render: async (canvas) => {
|
|
3812
|
+
canvas.width = 140;
|
|
3813
|
+
canvas.height = 100;
|
|
3814
|
+
const c = canvas.getContext("2d");
|
|
3815
|
+
if (!c) return;
|
|
3816
|
+
c.fillStyle = "#ffffff";
|
|
3817
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3818
|
+
c.fillStyle = "#107c41";
|
|
3819
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3820
|
+
c.fillStyle = "#ffffff";
|
|
3821
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
3822
|
+
c.fillText(`\u{1F4CA} ${name.slice(0, 16)}`, 6, 11);
|
|
3823
|
+
const startY = 17;
|
|
3824
|
+
const rowH = 13;
|
|
3825
|
+
const colW = 30;
|
|
3826
|
+
const colHeaders = ["A", "B", "C", "D"];
|
|
3827
|
+
c.fillStyle = "#f1f5f9";
|
|
3828
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3829
|
+
c.strokeStyle = "#cbd5e1";
|
|
3830
|
+
c.lineWidth = 0.8;
|
|
3831
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3832
|
+
c.fillStyle = "#64748b";
|
|
3833
|
+
c.font = "bold 7px sans-serif";
|
|
3834
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3835
|
+
c.fillText(colHeaders[ci], 14 + ci * colW, startY + 9);
|
|
3836
|
+
}
|
|
3837
|
+
const ws = wb?.Sheets[name];
|
|
3838
|
+
for (let ri = 1; ri <= 5; ri++) {
|
|
3839
|
+
const y = startY + ri * rowH;
|
|
3840
|
+
if (y > canvas.height - 2) break;
|
|
3841
|
+
c.fillStyle = "#f8fafc";
|
|
3842
|
+
c.fillRect(0, y, 12, rowH);
|
|
3843
|
+
c.fillStyle = "#94a3b8";
|
|
3844
|
+
c.font = "6px sans-serif";
|
|
3845
|
+
c.fillText(String(ri), 3, y + 9);
|
|
3846
|
+
c.strokeStyle = "#e2e8f0";
|
|
3847
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3848
|
+
c.fillStyle = "#334155";
|
|
3849
|
+
c.font = "6px sans-serif";
|
|
3850
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3851
|
+
const cellRef = `${colHeaders[ci]}${ri}`;
|
|
3852
|
+
const cellVal = ws?.[cellRef]?.w || ws?.[cellRef]?.v;
|
|
3853
|
+
if (cellVal !== void 0) {
|
|
3854
|
+
c.fillText(String(cellVal).slice(0, 6), 14 + ci * colW, y + 9);
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
c.strokeStyle = "#cbd5e1";
|
|
3859
|
+
c.lineWidth = 1;
|
|
3860
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
3861
|
+
}
|
|
3862
|
+
}));
|
|
3863
|
+
},
|
|
3222
3864
|
download: () => {
|
|
3223
3865
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
3224
3866
|
const url = URL.createObjectURL(blob);
|
|
@@ -3251,7 +3893,39 @@ var CsvPlugin = class {
|
|
|
3251
3893
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3252
3894
|
}
|
|
3253
3895
|
getToolbarActions(instance) {
|
|
3254
|
-
|
|
3896
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3897
|
+
const actions = [];
|
|
3898
|
+
actions.push({
|
|
3899
|
+
id: "thumbnails",
|
|
3900
|
+
icon: "thumbnails",
|
|
3901
|
+
label: "Page Thumbnails",
|
|
3902
|
+
type: "button",
|
|
3903
|
+
group: "navigation",
|
|
3904
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3905
|
+
});
|
|
3906
|
+
if (totalPages > 1) {
|
|
3907
|
+
actions.push({
|
|
3908
|
+
id: "page-nav",
|
|
3909
|
+
icon: "",
|
|
3910
|
+
label: "Page Navigation",
|
|
3911
|
+
type: "page-nav",
|
|
3912
|
+
group: "navigation",
|
|
3913
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3914
|
+
max: totalPages,
|
|
3915
|
+
execute: (action, page) => {
|
|
3916
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3917
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3918
|
+
if (action === "prev") {
|
|
3919
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3920
|
+
} else if (action === "next") {
|
|
3921
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3922
|
+
} else if (typeof page === "number") {
|
|
3923
|
+
instance.goToPage?.(page);
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3928
|
+
actions.push(
|
|
3255
3929
|
{
|
|
3256
3930
|
id: "zoom-out",
|
|
3257
3931
|
icon: "zoom-out",
|
|
@@ -3272,6 +3946,16 @@ var CsvPlugin = class {
|
|
|
3272
3946
|
instance.zoomIn?.();
|
|
3273
3947
|
}
|
|
3274
3948
|
},
|
|
3949
|
+
{
|
|
3950
|
+
id: "fit-page",
|
|
3951
|
+
icon: "fit-page",
|
|
3952
|
+
label: "Fit to View",
|
|
3953
|
+
type: "button",
|
|
3954
|
+
group: "zoom",
|
|
3955
|
+
execute: () => {
|
|
3956
|
+
instance.fitToPage?.();
|
|
3957
|
+
}
|
|
3958
|
+
},
|
|
3275
3959
|
{
|
|
3276
3960
|
id: "download",
|
|
3277
3961
|
icon: "download",
|
|
@@ -3291,8 +3975,19 @@ var CsvPlugin = class {
|
|
|
3291
3975
|
execute: () => {
|
|
3292
3976
|
instance.print?.();
|
|
3293
3977
|
}
|
|
3978
|
+
},
|
|
3979
|
+
{
|
|
3980
|
+
id: "open-window",
|
|
3981
|
+
icon: "open-window",
|
|
3982
|
+
label: "Open in Separate Full Window",
|
|
3983
|
+
type: "button",
|
|
3984
|
+
group: "actions",
|
|
3985
|
+
execute: () => {
|
|
3986
|
+
instance.openInSeparateWindow?.();
|
|
3987
|
+
}
|
|
3294
3988
|
}
|
|
3295
|
-
|
|
3989
|
+
);
|
|
3990
|
+
return actions;
|
|
3296
3991
|
}
|
|
3297
3992
|
async render(ctx) {
|
|
3298
3993
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -3304,33 +3999,62 @@ var CsvPlugin = class {
|
|
|
3304
3999
|
container.style.padding = "16px";
|
|
3305
4000
|
container.style.boxSizing = "border-box";
|
|
3306
4001
|
container.style.transformOrigin = "top left";
|
|
4002
|
+
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
4003
|
+
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
4004
|
+
const headerLine = allLines[0] || "";
|
|
4005
|
+
const headerCells = headerLine.split(delimiter);
|
|
4006
|
+
const dataLines = allLines.slice(1);
|
|
4007
|
+
const ROWS_PER_PAGE = 100;
|
|
4008
|
+
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
4009
|
+
let currentPage = 1;
|
|
3307
4010
|
const table = document.createElement("table");
|
|
3308
4011
|
table.style.borderCollapse = "collapse";
|
|
3309
4012
|
table.style.width = "100%";
|
|
3310
|
-
table.style.fontFamily = "monospace
|
|
4013
|
+
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3311
4014
|
table.style.fontSize = "13px";
|
|
3312
|
-
const
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
td.style.fontWeight = "bold";
|
|
3326
|
-
}
|
|
3327
|
-
tr.appendChild(td);
|
|
4015
|
+
const renderPage = (pageNum) => {
|
|
4016
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4017
|
+
table.innerHTML = "";
|
|
4018
|
+
const headerTr = document.createElement("tr");
|
|
4019
|
+
headerCells.forEach((cell) => {
|
|
4020
|
+
const th = document.createElement("th");
|
|
4021
|
+
th.textContent = cell.trim();
|
|
4022
|
+
th.style.border = "1px solid #d0d7de";
|
|
4023
|
+
th.style.padding = "8px 12px";
|
|
4024
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
4025
|
+
th.style.fontWeight = "600";
|
|
4026
|
+
th.style.whiteSpace = "nowrap";
|
|
4027
|
+
headerTr.appendChild(th);
|
|
3328
4028
|
});
|
|
3329
|
-
table.appendChild(
|
|
3330
|
-
|
|
4029
|
+
table.appendChild(headerTr);
|
|
4030
|
+
const start = (currentPage - 1) * ROWS_PER_PAGE;
|
|
4031
|
+
const end = Math.min(dataLines.length, start + ROWS_PER_PAGE);
|
|
4032
|
+
const pageRows = dataLines.slice(start, end);
|
|
4033
|
+
pageRows.forEach((row, idx) => {
|
|
4034
|
+
const tr = document.createElement("tr");
|
|
4035
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
4036
|
+
const cells = row.split(delimiter);
|
|
4037
|
+
cells.forEach((cell) => {
|
|
4038
|
+
const td = document.createElement("td");
|
|
4039
|
+
td.textContent = cell.trim();
|
|
4040
|
+
td.style.border = "1px solid #d0d7de";
|
|
4041
|
+
td.style.padding = "6px 12px";
|
|
4042
|
+
td.style.whiteSpace = "nowrap";
|
|
4043
|
+
tr.appendChild(td);
|
|
4044
|
+
});
|
|
4045
|
+
table.appendChild(tr);
|
|
4046
|
+
});
|
|
4047
|
+
container.scrollTop = 0;
|
|
4048
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4049
|
+
};
|
|
4050
|
+
renderPage(1);
|
|
3331
4051
|
container.appendChild(table);
|
|
3332
4052
|
ctx.container.appendChild(container);
|
|
3333
4053
|
let scale = 1;
|
|
4054
|
+
const applyScale = () => {
|
|
4055
|
+
container.style.transform = `scale(${scale})`;
|
|
4056
|
+
container.style.transformOrigin = "top left";
|
|
4057
|
+
};
|
|
3334
4058
|
const cleanup = () => {
|
|
3335
4059
|
container.remove();
|
|
3336
4060
|
ctx.container.innerHTML = "";
|
|
@@ -3338,22 +4062,86 @@ var CsvPlugin = class {
|
|
|
3338
4062
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3339
4063
|
return {
|
|
3340
4064
|
destroy: cleanup,
|
|
4065
|
+
getPageCount: () => totalPages,
|
|
4066
|
+
getCurrentPage: () => currentPage,
|
|
4067
|
+
goToPage: (page) => renderPage(page),
|
|
4068
|
+
getThumbnails: () => {
|
|
4069
|
+
const thumbnails = [];
|
|
4070
|
+
for (let i = 0; i < totalPages; i++) {
|
|
4071
|
+
const pageIdx = i;
|
|
4072
|
+
const startRow = pageIdx * ROWS_PER_PAGE + 1;
|
|
4073
|
+
const endRow = Math.min(dataLines.length, (pageIdx + 1) * ROWS_PER_PAGE);
|
|
4074
|
+
const label = totalPages === 1 ? "Table" : `Page ${pageIdx + 1} (${startRow}-${endRow})`;
|
|
4075
|
+
thumbnails.push({
|
|
4076
|
+
index: pageIdx,
|
|
4077
|
+
label,
|
|
4078
|
+
render: async (canvas) => {
|
|
4079
|
+
canvas.width = 140;
|
|
4080
|
+
canvas.height = 100;
|
|
4081
|
+
const c = canvas.getContext("2d");
|
|
4082
|
+
if (!c) return;
|
|
4083
|
+
c.fillStyle = "#ffffff";
|
|
4084
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4085
|
+
c.fillStyle = "#2563eb";
|
|
4086
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
4087
|
+
c.fillStyle = "#ffffff";
|
|
4088
|
+
c.font = "bold 8px sans-serif";
|
|
4089
|
+
c.fillText(`\u{1F4C8} ${label.slice(0, 18)}`, 6, 11);
|
|
4090
|
+
const startY = 17;
|
|
4091
|
+
const rowH = 13;
|
|
4092
|
+
const colW = 28;
|
|
4093
|
+
const cols = Math.min(4, headerCells.length || 4);
|
|
4094
|
+
c.fillStyle = "#f1f5f9";
|
|
4095
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
4096
|
+
c.strokeStyle = "#cbd5e1";
|
|
4097
|
+
c.lineWidth = 0.8;
|
|
4098
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
4099
|
+
c.fillStyle = "#64748b";
|
|
4100
|
+
c.font = "bold 7px sans-serif";
|
|
4101
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4102
|
+
const hName = headerCells[ci] || `Col ${ci + 1}`;
|
|
4103
|
+
c.fillText(hName.slice(0, 5), 8 + ci * colW, startY + 9);
|
|
4104
|
+
}
|
|
4105
|
+
const rowsToPreview = dataLines.slice(pageIdx * ROWS_PER_PAGE, pageIdx * ROWS_PER_PAGE + 5);
|
|
4106
|
+
for (let ri = 0; ri < rowsToPreview.length; ri++) {
|
|
4107
|
+
const y = startY + (ri + 1) * rowH;
|
|
4108
|
+
if (y > canvas.height - 2) break;
|
|
4109
|
+
c.strokeStyle = "#e2e8f0";
|
|
4110
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
4111
|
+
const cVals = rowsToPreview[ri].split(delimiter);
|
|
4112
|
+
c.fillStyle = "#334155";
|
|
4113
|
+
c.font = "6px sans-serif";
|
|
4114
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4115
|
+
const val = cVals[ci] || "";
|
|
4116
|
+
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
c.strokeStyle = "#cbd5e1";
|
|
4120
|
+
c.lineWidth = 1;
|
|
4121
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4122
|
+
}
|
|
4123
|
+
});
|
|
4124
|
+
}
|
|
4125
|
+
return thumbnails;
|
|
4126
|
+
},
|
|
3341
4127
|
zoomIn: () => {
|
|
3342
4128
|
scale += 0.1;
|
|
3343
|
-
|
|
4129
|
+
applyScale();
|
|
3344
4130
|
},
|
|
3345
4131
|
zoomOut: () => {
|
|
3346
4132
|
scale = Math.max(0.2, scale - 0.1);
|
|
3347
|
-
|
|
4133
|
+
applyScale();
|
|
3348
4134
|
},
|
|
3349
4135
|
getZoom: () => scale,
|
|
3350
4136
|
setZoom: (level) => {
|
|
3351
4137
|
scale = level;
|
|
3352
|
-
|
|
4138
|
+
applyScale();
|
|
3353
4139
|
},
|
|
3354
4140
|
fitToPage: () => {
|
|
3355
|
-
|
|
3356
|
-
|
|
4141
|
+
const availW = Math.max(280, (ctx.container.clientWidth || window.innerWidth) - 48);
|
|
4142
|
+
const tW = table.offsetWidth || 600;
|
|
4143
|
+
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4144
|
+
applyScale();
|
|
3357
4145
|
},
|
|
3358
4146
|
download: () => {
|
|
3359
4147
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
@@ -3417,28 +4205,34 @@ var CodePlugin = class {
|
|
|
3417
4205
|
getToolbarActions(instance) {
|
|
3418
4206
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3419
4207
|
const actions = [];
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
4208
|
+
actions.push({
|
|
4209
|
+
id: "thumbnails",
|
|
4210
|
+
icon: "thumbnails",
|
|
4211
|
+
label: "Page Thumbnails",
|
|
4212
|
+
type: "button",
|
|
4213
|
+
group: "navigation",
|
|
4214
|
+
execute: () => instance.toggleThumbnails?.()
|
|
4215
|
+
});
|
|
4216
|
+
actions.push({
|
|
4217
|
+
id: "page-nav",
|
|
4218
|
+
icon: "",
|
|
4219
|
+
label: "Page Navigation",
|
|
4220
|
+
type: "page-nav",
|
|
4221
|
+
group: "navigation",
|
|
4222
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4223
|
+
max: totalPages,
|
|
4224
|
+
execute: (action, page) => {
|
|
4225
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4226
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4227
|
+
if (action === "prev") {
|
|
4228
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4229
|
+
} else if (action === "next") {
|
|
4230
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4231
|
+
} else if (typeof page === "number") {
|
|
4232
|
+
instance.goToPage?.(page);
|
|
3439
4233
|
}
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
3442
4236
|
actions.push(
|
|
3443
4237
|
{
|
|
3444
4238
|
id: "zoom-out",
|
|
@@ -3582,16 +4376,19 @@ var CodePlugin = class {
|
|
|
3582
4376
|
let fontSize = 13;
|
|
3583
4377
|
let rotation = 0;
|
|
3584
4378
|
let zoomLevel = 1;
|
|
4379
|
+
let isUserZoomed = false;
|
|
3585
4380
|
const pre = document.createElement("pre");
|
|
3586
4381
|
const code = document.createElement("code");
|
|
3587
4382
|
if (isTxt) {
|
|
4383
|
+
container.style.overflowX = "hidden";
|
|
4384
|
+
container.style.overflowY = "auto";
|
|
3588
4385
|
container.style.backgroundColor = "#f1f5f9";
|
|
3589
|
-
container.style.padding = "
|
|
4386
|
+
container.style.padding = "16px 8px";
|
|
3590
4387
|
container.style.boxSizing = "border-box";
|
|
3591
4388
|
container.style.display = "flex";
|
|
3592
4389
|
container.style.flexDirection = "column";
|
|
3593
4390
|
container.style.alignItems = "center";
|
|
3594
|
-
pre.style.margin = "0";
|
|
4391
|
+
pre.style.margin = "0 auto";
|
|
3595
4392
|
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3596
4393
|
pre.style.fontSize = "13px";
|
|
3597
4394
|
pre.style.color = "#1e293b";
|
|
@@ -3603,10 +4400,12 @@ var CodePlugin = class {
|
|
|
3603
4400
|
pre.style.minHeight = "1056px";
|
|
3604
4401
|
pre.style.padding = "72px 56px";
|
|
3605
4402
|
pre.style.boxSizing = "border-box";
|
|
3606
|
-
pre.style.boxShadow = "0 4px
|
|
4403
|
+
pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
3607
4404
|
pre.style.borderRadius = "4px";
|
|
3608
4405
|
pre.style.transformOrigin = "top center";
|
|
4406
|
+
pre.style.transition = "transform 0.15s ease";
|
|
3609
4407
|
} else {
|
|
4408
|
+
container.style.overflow = "auto";
|
|
3610
4409
|
container.style.backgroundColor = "#1e1e1e";
|
|
3611
4410
|
container.style.color = "#d4d4d4";
|
|
3612
4411
|
container.style.padding = "16px";
|
|
@@ -3638,42 +4437,9 @@ var CodePlugin = class {
|
|
|
3638
4437
|
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3639
4438
|
pre.appendChild(code);
|
|
3640
4439
|
container.appendChild(pre);
|
|
3641
|
-
let indicator = null;
|
|
3642
|
-
if (totalPages > 1) {
|
|
3643
|
-
indicator = document.createElement("div");
|
|
3644
|
-
indicator.className = "fp-code-page-indicator";
|
|
3645
|
-
indicator.style.position = "sticky";
|
|
3646
|
-
indicator.style.bottom = "16px";
|
|
3647
|
-
if (isTxt) {
|
|
3648
|
-
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3649
|
-
indicator.style.color = "#334155";
|
|
3650
|
-
indicator.style.border = "1px solid #e2e8f0";
|
|
3651
|
-
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3652
|
-
} else {
|
|
3653
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3654
|
-
indicator.style.color = "#f8fafc";
|
|
3655
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3656
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3657
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
3658
|
-
}
|
|
3659
|
-
indicator.style.fontSize = "12px";
|
|
3660
|
-
indicator.style.fontWeight = "600";
|
|
3661
|
-
indicator.style.padding = "5px 14px";
|
|
3662
|
-
indicator.style.borderRadius = "20px";
|
|
3663
|
-
indicator.style.zIndex = "10";
|
|
3664
|
-
indicator.style.userSelect = "none";
|
|
3665
|
-
indicator.style.pointerEvents = "none";
|
|
3666
|
-
indicator.style.textAlign = "center";
|
|
3667
|
-
indicator.style.width = "fit-content";
|
|
3668
|
-
indicator.style.margin = "16px auto 0";
|
|
3669
|
-
container.appendChild(indicator);
|
|
3670
|
-
}
|
|
3671
4440
|
const showPage = (pageNum) => {
|
|
3672
4441
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3673
4442
|
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3674
|
-
if (indicator) {
|
|
3675
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3676
|
-
}
|
|
3677
4443
|
container.scrollTop = 0;
|
|
3678
4444
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3679
4445
|
};
|
|
@@ -3681,36 +4447,90 @@ var CodePlugin = class {
|
|
|
3681
4447
|
showPage(1);
|
|
3682
4448
|
}
|
|
3683
4449
|
ctx.container.appendChild(container);
|
|
3684
|
-
const
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
ctx.container.innerHTML = "";
|
|
4450
|
+
const calculateTxtFit = () => {
|
|
4451
|
+
const availW = Math.max(280, container.clientWidth - 32);
|
|
4452
|
+
return Math.max(0.4, Math.min(3, availW / 816));
|
|
3688
4453
|
};
|
|
3689
|
-
ctx.signal.addEventListener("abort", cleanup);
|
|
3690
4454
|
const updateTransform = () => {
|
|
3691
4455
|
if (isTxt) {
|
|
3692
4456
|
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
4457
|
+
const scaledH = 1056 * zoomLevel;
|
|
4458
|
+
const extraH = Math.max(0, scaledH - 1056);
|
|
4459
|
+
pre.style.marginBottom = `${extraH + 32}px`;
|
|
3693
4460
|
} else {
|
|
3694
4461
|
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3695
4462
|
pre.style.fontSize = `${fontSize}px`;
|
|
3696
4463
|
}
|
|
3697
4464
|
};
|
|
4465
|
+
let resizeObserver = null;
|
|
4466
|
+
if (isTxt) {
|
|
4467
|
+
setTimeout(() => {
|
|
4468
|
+
zoomLevel = calculateTxtFit();
|
|
4469
|
+
updateTransform();
|
|
4470
|
+
}, 60);
|
|
4471
|
+
resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
4472
|
+
if (!isUserZoomed) {
|
|
4473
|
+
zoomLevel = calculateTxtFit();
|
|
4474
|
+
updateTransform();
|
|
4475
|
+
}
|
|
4476
|
+
}) : null;
|
|
4477
|
+
resizeObserver?.observe(container);
|
|
4478
|
+
}
|
|
4479
|
+
const cleanup = () => {
|
|
4480
|
+
resizeObserver?.disconnect();
|
|
4481
|
+
container.remove();
|
|
4482
|
+
ctx.container.innerHTML = "";
|
|
4483
|
+
};
|
|
4484
|
+
ctx.signal.addEventListener("abort", cleanup);
|
|
3698
4485
|
return {
|
|
3699
4486
|
destroy: cleanup,
|
|
3700
4487
|
getPageCount: () => totalPages,
|
|
3701
4488
|
getCurrentPage: () => currentPage,
|
|
3702
4489
|
goToPage: (page) => showPage(page),
|
|
4490
|
+
getThumbnails: () => {
|
|
4491
|
+
return rawPages.map((pageText, idx) => ({
|
|
4492
|
+
index: idx,
|
|
4493
|
+
label: `Page ${idx + 1}`,
|
|
4494
|
+
render: async (canvas) => {
|
|
4495
|
+
canvas.width = 140;
|
|
4496
|
+
canvas.height = 180;
|
|
4497
|
+
const c = canvas.getContext("2d");
|
|
4498
|
+
if (!c) return;
|
|
4499
|
+
c.fillStyle = "#ffffff";
|
|
4500
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4501
|
+
c.strokeStyle = "#cbd5e1";
|
|
4502
|
+
c.lineWidth = 1;
|
|
4503
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4504
|
+
c.fillStyle = "#64748b";
|
|
4505
|
+
const lines = (pageText || "").split("\n").slice(0, 24);
|
|
4506
|
+
const lineH = 6;
|
|
4507
|
+
const startY = 14;
|
|
4508
|
+
const startX = 12;
|
|
4509
|
+
const maxW = canvas.width - 24;
|
|
4510
|
+
c.font = "5px monospace";
|
|
4511
|
+
for (let li = 0; li < lines.length; li++) {
|
|
4512
|
+
const l = lines[li].trim();
|
|
4513
|
+
if (!l) continue;
|
|
4514
|
+
const y = startY + li * lineH;
|
|
4515
|
+
if (y > canvas.height - 12) break;
|
|
4516
|
+
c.fillText(l.slice(0, 30), startX, y, maxW);
|
|
4517
|
+
}
|
|
4518
|
+
}
|
|
4519
|
+
}));
|
|
4520
|
+
},
|
|
3703
4521
|
zoomIn: () => {
|
|
4522
|
+
isUserZoomed = true;
|
|
3704
4523
|
if (isTxt) {
|
|
3705
|
-
zoomLevel = Math.min(3, zoomLevel + 0.
|
|
4524
|
+
zoomLevel = Math.min(3.5, zoomLevel + 0.15);
|
|
3706
4525
|
} else {
|
|
3707
4526
|
fontSize = Math.min(32, fontSize + 2);
|
|
3708
4527
|
}
|
|
3709
4528
|
updateTransform();
|
|
3710
4529
|
},
|
|
3711
4530
|
zoomOut: () => {
|
|
4531
|
+
isUserZoomed = true;
|
|
3712
4532
|
if (isTxt) {
|
|
3713
|
-
zoomLevel = Math.max(0.1, zoomLevel - 0.
|
|
4533
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.15);
|
|
3714
4534
|
} else {
|
|
3715
4535
|
fontSize = Math.max(8, fontSize - 2);
|
|
3716
4536
|
}
|
|
@@ -3718,6 +4538,7 @@ var CodePlugin = class {
|
|
|
3718
4538
|
},
|
|
3719
4539
|
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3720
4540
|
setZoom: (level) => {
|
|
4541
|
+
isUserZoomed = true;
|
|
3721
4542
|
if (isTxt) {
|
|
3722
4543
|
zoomLevel = level;
|
|
3723
4544
|
} else {
|
|
@@ -3726,9 +4547,10 @@ var CodePlugin = class {
|
|
|
3726
4547
|
updateTransform();
|
|
3727
4548
|
},
|
|
3728
4549
|
fitToPage: () => {
|
|
4550
|
+
isUserZoomed = false;
|
|
3729
4551
|
fontSize = 13;
|
|
3730
4552
|
rotation = 0;
|
|
3731
|
-
zoomLevel = isTxt ?
|
|
4553
|
+
zoomLevel = isTxt ? calculateTxtFit() : 1;
|
|
3732
4554
|
updateTransform();
|
|
3733
4555
|
},
|
|
3734
4556
|
rotateCW: () => {
|
|
@@ -4609,28 +5431,26 @@ var RtfPlugin = class {
|
|
|
4609
5431
|
getToolbarActions(instance) {
|
|
4610
5432
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4611
5433
|
const actions = [];
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
if (
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
instance.goToPage?.(page);
|
|
4630
|
-
}
|
|
5434
|
+
actions.push({
|
|
5435
|
+
id: "page-nav",
|
|
5436
|
+
icon: "",
|
|
5437
|
+
label: "Page Navigation",
|
|
5438
|
+
type: "page-nav",
|
|
5439
|
+
group: "navigation",
|
|
5440
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5441
|
+
max: totalPages,
|
|
5442
|
+
execute: (action, page) => {
|
|
5443
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5444
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5445
|
+
if (action === "prev") {
|
|
5446
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5447
|
+
} else if (action === "next") {
|
|
5448
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5449
|
+
} else if (typeof page === "number") {
|
|
5450
|
+
instance.goToPage?.(page);
|
|
4631
5451
|
}
|
|
4632
|
-
}
|
|
4633
|
-
}
|
|
5452
|
+
}
|
|
5453
|
+
});
|
|
4634
5454
|
actions.push(
|
|
4635
5455
|
{
|
|
4636
5456
|
id: "zoom-out",
|
|
@@ -4702,43 +5522,57 @@ var RtfPlugin = class {
|
|
|
4702
5522
|
async render(ctx) {
|
|
4703
5523
|
const wrapper = document.createElement("div");
|
|
4704
5524
|
wrapper.className = "fp-rtf-wrapper";
|
|
4705
|
-
wrapper.style.padding = "
|
|
4706
|
-
wrapper.style.
|
|
5525
|
+
wrapper.style.padding = "0";
|
|
5526
|
+
wrapper.style.width = "816px";
|
|
4707
5527
|
wrapper.style.margin = "0 auto";
|
|
4708
|
-
wrapper.style.
|
|
4709
|
-
wrapper.style.
|
|
4710
|
-
wrapper.style.
|
|
4711
|
-
wrapper.style.
|
|
5528
|
+
wrapper.style.boxSizing = "border-box";
|
|
5529
|
+
wrapper.style.display = "flex";
|
|
5530
|
+
wrapper.style.flexDirection = "column";
|
|
5531
|
+
wrapper.style.alignItems = "center";
|
|
5532
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4712
5533
|
wrapper.style.transformOrigin = "top center";
|
|
4713
|
-
wrapper.style.transition = "transform 0.
|
|
4714
|
-
ctx.container.style.
|
|
4715
|
-
ctx.container.style.
|
|
5534
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5535
|
+
ctx.container.style.overflowX = "hidden";
|
|
5536
|
+
ctx.container.style.overflowY = "auto";
|
|
5537
|
+
ctx.container.style.padding = "16px 8px";
|
|
4716
5538
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
4717
5539
|
ctx.container.appendChild(wrapper);
|
|
4718
5540
|
let scale = 1;
|
|
4719
5541
|
let rotation = 0;
|
|
4720
5542
|
let pageElements = [];
|
|
4721
|
-
let
|
|
5543
|
+
let isUserZoomed = false;
|
|
5544
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
4722
5545
|
const calculateFitScale = (mode = fitMode) => {
|
|
4723
5546
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4724
|
-
const elW =
|
|
4725
|
-
const singlePageH =
|
|
4726
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
4727
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
5547
|
+
const elW = 816;
|
|
5548
|
+
const singlePageH = activeEl?.offsetHeight || 1056;
|
|
5549
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5550
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
4728
5551
|
const sW = availW / elW;
|
|
4729
5552
|
const sH = availH / singlePageH;
|
|
4730
5553
|
if (mode === "page") {
|
|
4731
|
-
return Math.max(0.
|
|
5554
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
4732
5555
|
}
|
|
4733
|
-
return Math.max(0.
|
|
5556
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
4734
5557
|
};
|
|
4735
5558
|
const applyTransform = () => {
|
|
4736
5559
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4737
5560
|
wrapper.style.transformOrigin = "top center";
|
|
5561
|
+
const activeEl = pageElements[currentPage - 1];
|
|
5562
|
+
const baseH = activeEl?.offsetHeight || 1056;
|
|
5563
|
+
const scaledH = baseH * scale;
|
|
5564
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5565
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
4738
5566
|
};
|
|
5567
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5568
|
+
if (!isUserZoomed) {
|
|
5569
|
+
scale = calculateFitScale(fitMode);
|
|
5570
|
+
applyTransform();
|
|
5571
|
+
}
|
|
5572
|
+
}) : null;
|
|
5573
|
+
resizeObserver?.observe(ctx.container);
|
|
4739
5574
|
setTimeout(() => {
|
|
4740
|
-
|
|
4741
|
-
scale = calculateFitScale("width");
|
|
5575
|
+
scale = calculateFitScale(fitMode);
|
|
4742
5576
|
applyTransform();
|
|
4743
5577
|
}, 60);
|
|
4744
5578
|
try {
|
|
@@ -4748,20 +5582,34 @@ var RtfPlugin = class {
|
|
|
4748
5582
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
4749
5583
|
const htmlElements = await doc.render();
|
|
4750
5584
|
const contentNodes = [];
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
5585
|
+
const extractBlocks = (nodes) => {
|
|
5586
|
+
for (const item of nodes) {
|
|
5587
|
+
if (!item || !(item instanceof HTMLElement)) continue;
|
|
5588
|
+
const tag = item.tagName.toLowerCase();
|
|
5589
|
+
const hasChildBlocks = Array.from(item.children).some((c) => {
|
|
5590
|
+
const ct = c.tagName.toLowerCase();
|
|
5591
|
+
return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
|
|
5592
|
+
});
|
|
5593
|
+
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5594
|
+
extractBlocks(Array.from(item.children));
|
|
5595
|
+
} else {
|
|
5596
|
+
if (tag === "p" || tag === "div") {
|
|
5597
|
+
item.style.display = "block";
|
|
5598
|
+
item.style.marginBottom = "12px";
|
|
5599
|
+
item.style.lineHeight = "1.6";
|
|
5600
|
+
}
|
|
5601
|
+
contentNodes.push(item);
|
|
5602
|
+
}
|
|
4756
5603
|
}
|
|
4757
|
-
}
|
|
5604
|
+
};
|
|
5605
|
+
extractBlocks(htmlElements);
|
|
4758
5606
|
wrapper.innerHTML = "";
|
|
4759
5607
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4760
5608
|
const childHeights = contentNodes.map((c) => {
|
|
4761
5609
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4762
5610
|
const offH = c.offsetHeight || 0;
|
|
4763
5611
|
const textLen = c.textContent?.trim().length || 0;
|
|
4764
|
-
const estH = Math.max(
|
|
5612
|
+
const estH = Math.max(28, Math.ceil(textLen / 75) * 24 + 16);
|
|
4765
5613
|
return Math.max(rectH, offH, estH);
|
|
4766
5614
|
});
|
|
4767
5615
|
wrapper.innerHTML = "";
|
|
@@ -4778,6 +5626,7 @@ var RtfPlugin = class {
|
|
|
4778
5626
|
card.style.marginBottom = "24px";
|
|
4779
5627
|
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4780
5628
|
card.style.lineHeight = "1.6";
|
|
5629
|
+
card.style.color = "#1e293b";
|
|
4781
5630
|
return card;
|
|
4782
5631
|
};
|
|
4783
5632
|
let curCard = createRtfCard();
|
|
@@ -4813,9 +5662,8 @@ var RtfPlugin = class {
|
|
|
4813
5662
|
pageCard.style.padding = "72px 56px";
|
|
4814
5663
|
pageCard.style.width = "816px";
|
|
4815
5664
|
pageCard.style.minHeight = "1056px";
|
|
4816
|
-
pageCard.style.maxWidth = "100%";
|
|
4817
5665
|
pageCard.style.boxSizing = "border-box";
|
|
4818
|
-
pageCard.style.fontFamily = "serif
|
|
5666
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4819
5667
|
pageCard.style.fontSize = "12pt";
|
|
4820
5668
|
pageCard.style.lineHeight = "1.6";
|
|
4821
5669
|
pageCard.style.color = "#1e293b";
|
|
@@ -4828,29 +5676,6 @@ var RtfPlugin = class {
|
|
|
4828
5676
|
}
|
|
4829
5677
|
const totalPages = Math.max(1, pageElements.length);
|
|
4830
5678
|
let currentPage = 1;
|
|
4831
|
-
let indicator = null;
|
|
4832
|
-
if (totalPages > 1) {
|
|
4833
|
-
indicator = document.createElement("div");
|
|
4834
|
-
indicator.className = "fp-rtf-page-indicator";
|
|
4835
|
-
indicator.style.position = "sticky";
|
|
4836
|
-
indicator.style.bottom = "16px";
|
|
4837
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4838
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
4839
|
-
indicator.style.color = "#f8fafc";
|
|
4840
|
-
indicator.style.fontSize = "12px";
|
|
4841
|
-
indicator.style.fontWeight = "600";
|
|
4842
|
-
indicator.style.padding = "5px 14px";
|
|
4843
|
-
indicator.style.borderRadius = "20px";
|
|
4844
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4845
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4846
|
-
indicator.style.zIndex = "10";
|
|
4847
|
-
indicator.style.userSelect = "none";
|
|
4848
|
-
indicator.style.pointerEvents = "none";
|
|
4849
|
-
indicator.style.textAlign = "center";
|
|
4850
|
-
indicator.style.width = "fit-content";
|
|
4851
|
-
indicator.style.margin = "16px auto 0";
|
|
4852
|
-
ctx.container.appendChild(indicator);
|
|
4853
|
-
}
|
|
4854
5679
|
const showPage = (pageNum) => {
|
|
4855
5680
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4856
5681
|
if (totalPages > 1) {
|
|
@@ -4858,9 +5683,6 @@ var RtfPlugin = class {
|
|
|
4858
5683
|
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4859
5684
|
});
|
|
4860
5685
|
}
|
|
4861
|
-
if (indicator) {
|
|
4862
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4863
|
-
}
|
|
4864
5686
|
ctx.container.scrollTop = 0;
|
|
4865
5687
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4866
5688
|
};
|
|
@@ -4868,7 +5690,7 @@ var RtfPlugin = class {
|
|
|
4868
5690
|
showPage(1);
|
|
4869
5691
|
}
|
|
4870
5692
|
const cleanup = () => {
|
|
4871
|
-
|
|
5693
|
+
resizeObserver?.disconnect();
|
|
4872
5694
|
wrapper.remove();
|
|
4873
5695
|
ctx.container.innerHTML = "";
|
|
4874
5696
|
};
|
|
@@ -4879,21 +5701,25 @@ var RtfPlugin = class {
|
|
|
4879
5701
|
getCurrentPage: () => currentPage,
|
|
4880
5702
|
goToPage: (page) => showPage(page),
|
|
4881
5703
|
zoomIn: () => {
|
|
5704
|
+
isUserZoomed = true;
|
|
4882
5705
|
scale += 0.15;
|
|
4883
5706
|
applyTransform();
|
|
4884
5707
|
},
|
|
4885
5708
|
zoomOut: () => {
|
|
5709
|
+
isUserZoomed = true;
|
|
4886
5710
|
scale = Math.max(0.2, scale - 0.15);
|
|
4887
5711
|
applyTransform();
|
|
4888
5712
|
},
|
|
4889
5713
|
getZoom: () => scale,
|
|
4890
5714
|
setZoom: (level) => {
|
|
5715
|
+
isUserZoomed = true;
|
|
4891
5716
|
scale = level;
|
|
4892
5717
|
applyTransform();
|
|
4893
5718
|
},
|
|
4894
5719
|
fitToPage: () => {
|
|
4895
|
-
|
|
4896
|
-
|
|
5720
|
+
isUserZoomed = false;
|
|
5721
|
+
fitMode = "width";
|
|
5722
|
+
scale = calculateFitScale("width");
|
|
4897
5723
|
rotation = 0;
|
|
4898
5724
|
applyTransform();
|
|
4899
5725
|
},
|
|
@@ -5081,40 +5907,36 @@ var OpenDocumentPlugin = class {
|
|
|
5081
5907
|
const isPresentation = instance.isPresentation;
|
|
5082
5908
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5083
5909
|
const actions = [];
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
max
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
if (
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
instance.goToPage?.(page);
|
|
5112
|
-
} else if (typeof action === "number") {
|
|
5113
|
-
instance.goToPage?.(action);
|
|
5114
|
-
}
|
|
5910
|
+
actions.push({
|
|
5911
|
+
id: "thumbnails",
|
|
5912
|
+
icon: "thumbnails",
|
|
5913
|
+
label: isPresentation ? "Slide Thumbnails" : "Page Thumbnails",
|
|
5914
|
+
type: "button",
|
|
5915
|
+
group: "navigation",
|
|
5916
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5917
|
+
});
|
|
5918
|
+
actions.push({
|
|
5919
|
+
id: "page-nav",
|
|
5920
|
+
icon: "",
|
|
5921
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
5922
|
+
type: "page-nav",
|
|
5923
|
+
group: "navigation",
|
|
5924
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5925
|
+
max: totalPages,
|
|
5926
|
+
execute: (action, page) => {
|
|
5927
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5928
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5929
|
+
if (action === "prev") {
|
|
5930
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5931
|
+
} else if (action === "next") {
|
|
5932
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5933
|
+
} else if (typeof page === "number") {
|
|
5934
|
+
instance.goToPage?.(page);
|
|
5935
|
+
} else if (typeof action === "number") {
|
|
5936
|
+
instance.goToPage?.(action);
|
|
5115
5937
|
}
|
|
5116
|
-
}
|
|
5117
|
-
}
|
|
5938
|
+
}
|
|
5939
|
+
});
|
|
5118
5940
|
actions.push(
|
|
5119
5941
|
{
|
|
5120
5942
|
id: "zoom-out",
|
|
@@ -5205,49 +6027,65 @@ var OpenDocumentPlugin = class {
|
|
|
5205
6027
|
container.className = "fp-odf-container";
|
|
5206
6028
|
container.style.width = "100%";
|
|
5207
6029
|
container.style.height = "100%";
|
|
5208
|
-
container.style.
|
|
5209
|
-
container.style.
|
|
6030
|
+
container.style.overflowX = "hidden";
|
|
6031
|
+
container.style.overflowY = "auto";
|
|
6032
|
+
container.style.padding = "16px 8px";
|
|
5210
6033
|
container.style.backgroundColor = "#f1f5f9";
|
|
5211
6034
|
const wrapper = document.createElement("div");
|
|
5212
6035
|
wrapper.className = "fp-odf-wrapper";
|
|
5213
6036
|
wrapper.style.margin = "0 auto";
|
|
6037
|
+
wrapper.style.width = isPresentation ? "960px" : "816px";
|
|
6038
|
+
wrapper.style.boxSizing = "border-box";
|
|
5214
6039
|
wrapper.style.backgroundColor = "#ffffff";
|
|
5215
6040
|
wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
5216
6041
|
wrapper.style.borderRadius = "4px";
|
|
5217
6042
|
wrapper.style.transformOrigin = "top center";
|
|
5218
|
-
wrapper.style.transition = "transform 0.
|
|
6043
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5219
6044
|
container.appendChild(wrapper);
|
|
5220
6045
|
ctx.container.appendChild(container);
|
|
5221
6046
|
let scale = 1;
|
|
5222
6047
|
let rotation = 0;
|
|
5223
|
-
let
|
|
6048
|
+
let isUserZoomed = false;
|
|
6049
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6050
|
+
let currentPage = 1;
|
|
6051
|
+
let totalPages = 1;
|
|
6052
|
+
let slides = [];
|
|
5224
6053
|
const calculateFitScale = (mode = fitMode) => {
|
|
5225
|
-
const
|
|
5226
|
-
const
|
|
5227
|
-
const
|
|
5228
|
-
const
|
|
6054
|
+
const activeSlide = slides[currentPage - 1];
|
|
6055
|
+
const elW = isPresentation ? 960 : 816;
|
|
6056
|
+
const singlePageH = Math.min(activeSlide?.offsetHeight || wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
6057
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6058
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5229
6059
|
const sW = availW / elW;
|
|
5230
6060
|
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
5231
6061
|
if (isPresentation) {
|
|
5232
|
-
return Math.min(
|
|
6062
|
+
return Math.min(2.5, Math.min(sW, sH));
|
|
5233
6063
|
}
|
|
5234
6064
|
if (mode === "page") {
|
|
5235
|
-
return Math.max(0.
|
|
6065
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5236
6066
|
}
|
|
5237
|
-
return Math.max(0.
|
|
6067
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5238
6068
|
};
|
|
5239
6069
|
const applyTransform = () => {
|
|
5240
6070
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5241
6071
|
wrapper.style.transformOrigin = "top center";
|
|
6072
|
+
const activeSlide = slides[currentPage - 1];
|
|
6073
|
+
const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
|
|
6074
|
+
const scaledH = baseH * scale;
|
|
6075
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6076
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
5242
6077
|
};
|
|
6078
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6079
|
+
if (!isUserZoomed) {
|
|
6080
|
+
scale = calculateFitScale(fitMode);
|
|
6081
|
+
applyTransform();
|
|
6082
|
+
}
|
|
6083
|
+
}) : null;
|
|
6084
|
+
resizeObserver?.observe(ctx.container);
|
|
5243
6085
|
setTimeout(() => {
|
|
5244
|
-
|
|
5245
|
-
scale = calculateFitScale("width");
|
|
6086
|
+
scale = calculateFitScale(fitMode);
|
|
5246
6087
|
applyTransform();
|
|
5247
6088
|
}, 60);
|
|
5248
|
-
let currentPage = 1;
|
|
5249
|
-
let totalPages = 1;
|
|
5250
|
-
let slides = [];
|
|
5251
6089
|
if (isPresentation) {
|
|
5252
6090
|
wrapper.style.maxWidth = "960px";
|
|
5253
6091
|
wrapper.style.aspectRatio = "16 / 9";
|
|
@@ -5348,24 +6186,9 @@ var OpenDocumentPlugin = class {
|
|
|
5348
6186
|
wrapper.appendChild(page);
|
|
5349
6187
|
slides.push(page);
|
|
5350
6188
|
});
|
|
5351
|
-
const pageIndicator = document.createElement("div");
|
|
5352
|
-
pageIndicator.className = "fp-odt-page-indicator";
|
|
5353
|
-
pageIndicator.style.position = "sticky";
|
|
5354
|
-
pageIndicator.style.bottom = "16px";
|
|
5355
|
-
pageIndicator.style.left = "50%";
|
|
5356
|
-
pageIndicator.style.transform = "translateX(-50%)";
|
|
5357
|
-
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
5358
|
-
pageIndicator.style.color = "#fff";
|
|
5359
|
-
pageIndicator.style.padding = "6px 12px";
|
|
5360
|
-
pageIndicator.style.borderRadius = "16px";
|
|
5361
|
-
pageIndicator.style.fontSize = "12px";
|
|
5362
|
-
pageIndicator.style.zIndex = "100";
|
|
5363
|
-
pageIndicator.style.display = "inline-block";
|
|
5364
|
-
pageIndicator.style.width = "fit-content";
|
|
5365
|
-
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
5366
|
-
container.appendChild(pageIndicator);
|
|
5367
6189
|
}
|
|
5368
6190
|
const cleanup = () => {
|
|
6191
|
+
resizeObserver?.disconnect();
|
|
5369
6192
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
5370
6193
|
container.remove();
|
|
5371
6194
|
ctx.container.innerHTML = "";
|
|
@@ -5377,10 +6200,6 @@ var OpenDocumentPlugin = class {
|
|
|
5377
6200
|
slides.forEach((s, idx) => {
|
|
5378
6201
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
5379
6202
|
});
|
|
5380
|
-
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
5381
|
-
if (indicator) {
|
|
5382
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5383
|
-
}
|
|
5384
6203
|
container.scrollTop = 0;
|
|
5385
6204
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5386
6205
|
};
|
|
@@ -5388,21 +6207,25 @@ var OpenDocumentPlugin = class {
|
|
|
5388
6207
|
destroy: cleanup,
|
|
5389
6208
|
isPresentation,
|
|
5390
6209
|
zoomIn: () => {
|
|
6210
|
+
isUserZoomed = true;
|
|
5391
6211
|
scale += 0.15;
|
|
5392
6212
|
applyTransform();
|
|
5393
6213
|
},
|
|
5394
6214
|
zoomOut: () => {
|
|
6215
|
+
isUserZoomed = true;
|
|
5395
6216
|
scale = Math.max(0.2, scale - 0.15);
|
|
5396
6217
|
applyTransform();
|
|
5397
6218
|
},
|
|
5398
6219
|
getZoom: () => scale,
|
|
5399
6220
|
setZoom: (level) => {
|
|
6221
|
+
isUserZoomed = true;
|
|
5400
6222
|
scale = level;
|
|
5401
6223
|
applyTransform();
|
|
5402
6224
|
},
|
|
5403
6225
|
fitToPage: () => {
|
|
5404
|
-
|
|
5405
|
-
|
|
6226
|
+
isUserZoomed = false;
|
|
6227
|
+
fitMode = "width";
|
|
6228
|
+
scale = calculateFitScale("width");
|
|
5406
6229
|
rotation = 0;
|
|
5407
6230
|
applyTransform();
|
|
5408
6231
|
},
|
|
@@ -5418,23 +6241,45 @@ var OpenDocumentPlugin = class {
|
|
|
5418
6241
|
getPageCount: () => totalPages,
|
|
5419
6242
|
getCurrentPage: () => currentPage,
|
|
5420
6243
|
getThumbnails: async () => {
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
canvas
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
6244
|
+
const count = totalPages || slides.length || 1;
|
|
6245
|
+
const items = [];
|
|
6246
|
+
for (let idx = 0; idx < count; idx++) {
|
|
6247
|
+
const itemIdx = idx;
|
|
6248
|
+
items.push({
|
|
6249
|
+
index: itemIdx,
|
|
6250
|
+
label: isPresentation ? `Slide ${itemIdx + 1}` : `Page ${itemIdx + 1}`,
|
|
6251
|
+
render: async (canvas) => {
|
|
6252
|
+
const ctx2d = canvas.getContext("2d");
|
|
6253
|
+
if (!ctx2d) return;
|
|
6254
|
+
if (isPresentation) {
|
|
6255
|
+
canvas.width = 160;
|
|
6256
|
+
canvas.height = 90;
|
|
6257
|
+
ctx2d.fillStyle = "#f8fafc";
|
|
6258
|
+
ctx2d.fillRect(0, 0, 160, 90);
|
|
6259
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6260
|
+
ctx2d.lineWidth = 1;
|
|
6261
|
+
ctx2d.strokeRect(0.5, 0.5, 159, 89);
|
|
6262
|
+
ctx2d.fillStyle = "#334155";
|
|
6263
|
+
ctx2d.font = "bold 11px sans-serif";
|
|
6264
|
+
ctx2d.textAlign = "center";
|
|
6265
|
+
ctx2d.fillText(`Slide ${itemIdx + 1}`, 80, 50);
|
|
6266
|
+
} else {
|
|
6267
|
+
canvas.width = 140;
|
|
6268
|
+
canvas.height = 180;
|
|
6269
|
+
ctx2d.fillStyle = "#ffffff";
|
|
6270
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
6271
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6272
|
+
ctx2d.lineWidth = 1;
|
|
6273
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
6274
|
+
ctx2d.fillStyle = "#64748b";
|
|
6275
|
+
ctx2d.font = "bold 10px sans-serif";
|
|
6276
|
+
ctx2d.textAlign = "center";
|
|
6277
|
+
ctx2d.fillText(`Page ${itemIdx + 1}`, 70, 90);
|
|
6278
|
+
}
|
|
6279
|
+
}
|
|
6280
|
+
});
|
|
6281
|
+
}
|
|
6282
|
+
return items;
|
|
5438
6283
|
},
|
|
5439
6284
|
download: () => {
|
|
5440
6285
|
const mimeType = this.mimeTypes.find((m) => m.includes(ext.replace(".", ""))) || "application/octet-stream";
|
|
@@ -5539,23 +6384,24 @@ var OpenDocumentPlugin = class {
|
|
|
5539
6384
|
case "h": {
|
|
5540
6385
|
const level = Math.min(6, Math.max(1, Number(node.getAttribute("text:outline-level") || 1)));
|
|
5541
6386
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5542
|
-
html += `<h${level} style="${style}; font-family:
|
|
6387
|
+
html += `<h${level} style="${style}; margin: 18px 0 8px; color: #1e3a8a; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${node.textContent || ""}</h${level}>`;
|
|
5543
6388
|
break;
|
|
5544
6389
|
}
|
|
5545
6390
|
case "p": {
|
|
5546
6391
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5547
6392
|
const inner = this.renderSpans(node, styles, images);
|
|
5548
|
-
|
|
6393
|
+
const isInsideLi = node.parentElement?.localName === "list-item" || node.parentElement?.tagName?.toLowerCase() === "list-item";
|
|
6394
|
+
html += `<p style="${style}; line-height: 1.5; margin: ${isInsideLi ? "0" : "8px 0 12px"}; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${inner}</p>`;
|
|
5549
6395
|
break;
|
|
5550
6396
|
}
|
|
5551
6397
|
case "list": {
|
|
5552
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
6398
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
5553
6399
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5554
6400
|
html += "</ul>";
|
|
5555
6401
|
break;
|
|
5556
6402
|
}
|
|
5557
6403
|
case "list-item": {
|
|
5558
|
-
html +=
|
|
6404
|
+
html += '<li style="margin: 4px 0; font-size: 11pt; line-height: 1.5; color: #1e293b;">';
|
|
5559
6405
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5560
6406
|
html += "</li>";
|
|
5561
6407
|
break;
|
|
@@ -5681,28 +6527,26 @@ var DocPlugin = class {
|
|
|
5681
6527
|
getToolbarActions(instance) {
|
|
5682
6528
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5683
6529
|
const actions = [];
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
if (
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
instance.goToPage?.(page);
|
|
5702
|
-
}
|
|
6530
|
+
actions.push({
|
|
6531
|
+
id: "page-nav",
|
|
6532
|
+
icon: "",
|
|
6533
|
+
label: "Page Navigation",
|
|
6534
|
+
type: "page-nav",
|
|
6535
|
+
group: "navigation",
|
|
6536
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
6537
|
+
max: totalPages,
|
|
6538
|
+
execute: (action, page) => {
|
|
6539
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
6540
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
6541
|
+
if (action === "prev") {
|
|
6542
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
6543
|
+
} else if (action === "next") {
|
|
6544
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
6545
|
+
} else if (typeof page === "number") {
|
|
6546
|
+
instance.goToPage?.(page);
|
|
5703
6547
|
}
|
|
5704
|
-
}
|
|
5705
|
-
}
|
|
6548
|
+
}
|
|
6549
|
+
});
|
|
5706
6550
|
actions.push(
|
|
5707
6551
|
{
|
|
5708
6552
|
id: "zoom-out",
|
|
@@ -5776,8 +6620,9 @@ var DocPlugin = class {
|
|
|
5776
6620
|
container.className = "fp-doc-container";
|
|
5777
6621
|
container.style.width = "100%";
|
|
5778
6622
|
container.style.height = "100%";
|
|
5779
|
-
container.style.
|
|
5780
|
-
container.style.
|
|
6623
|
+
container.style.overflowX = "hidden";
|
|
6624
|
+
container.style.overflowY = "auto";
|
|
6625
|
+
container.style.padding = "16px 8px";
|
|
5781
6626
|
container.style.backgroundColor = "#f1f5f9";
|
|
5782
6627
|
container.style.display = "flex";
|
|
5783
6628
|
container.style.justifyContent = "center";
|
|
@@ -5822,16 +6667,15 @@ var DocPlugin = class {
|
|
|
5822
6667
|
const pageCard = document.createElement("div");
|
|
5823
6668
|
pageCard.className = "fp-doc-page-card";
|
|
5824
6669
|
pageCard.style.width = "816px";
|
|
5825
|
-
pageCard.style.
|
|
6670
|
+
pageCard.style.minHeight = "1056px";
|
|
5826
6671
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5827
|
-
pageCard.style.boxShadow = "0
|
|
6672
|
+
pageCard.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5828
6673
|
pageCard.style.borderRadius = "4px";
|
|
5829
|
-
pageCard.style.padding = "
|
|
6674
|
+
pageCard.style.padding = "72px 56px";
|
|
5830
6675
|
pageCard.style.boxSizing = "border-box";
|
|
5831
|
-
pageCard.style.overflow = "hidden";
|
|
5832
6676
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5833
6677
|
pageCard.style.transformOrigin = "top center";
|
|
5834
|
-
pageCard.style.transition = "transform 0.
|
|
6678
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
5835
6679
|
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5836
6680
|
pageCard.style.color = "#1e293b";
|
|
5837
6681
|
if (isFallback && i === 0) {
|
|
@@ -5848,34 +6692,15 @@ var DocPlugin = class {
|
|
|
5848
6692
|
container.appendChild(pageCard);
|
|
5849
6693
|
pageCards.push(pageCard);
|
|
5850
6694
|
}
|
|
5851
|
-
let indicator = null;
|
|
5852
|
-
if (totalPages > 1) {
|
|
5853
|
-
indicator = document.createElement("div");
|
|
5854
|
-
indicator.className = "fp-doc-page-indicator";
|
|
5855
|
-
indicator.style.position = "fixed";
|
|
5856
|
-
indicator.style.bottom = "16px";
|
|
5857
|
-
indicator.style.left = "50%";
|
|
5858
|
-
indicator.style.transform = "translateX(-50%)";
|
|
5859
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
5860
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
5861
|
-
indicator.style.color = "#f8fafc";
|
|
5862
|
-
indicator.style.fontSize = "12px";
|
|
5863
|
-
indicator.style.fontWeight = "600";
|
|
5864
|
-
indicator.style.padding = "5px 14px";
|
|
5865
|
-
indicator.style.borderRadius = "20px";
|
|
5866
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
5867
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
5868
|
-
indicator.style.zIndex = "10";
|
|
5869
|
-
indicator.style.userSelect = "none";
|
|
5870
|
-
indicator.style.pointerEvents = "none";
|
|
5871
|
-
indicator.style.textAlign = "center";
|
|
5872
|
-
container.appendChild(indicator);
|
|
5873
|
-
}
|
|
5874
6695
|
let rotation = 0;
|
|
5875
6696
|
const applyTransform = () => {
|
|
5876
6697
|
const activeCard = pageCards[currentPage - 1];
|
|
5877
6698
|
if (activeCard) {
|
|
5878
6699
|
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
6700
|
+
const baseH = activeCard.offsetHeight || 1056;
|
|
6701
|
+
const scaledH = baseH * scale;
|
|
6702
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6703
|
+
activeCard.style.marginBottom = `${extraH + 32}px`;
|
|
5879
6704
|
}
|
|
5880
6705
|
};
|
|
5881
6706
|
const showPage = (pageNum) => {
|
|
@@ -5888,35 +6713,39 @@ var DocPlugin = class {
|
|
|
5888
6713
|
card.style.display = "none";
|
|
5889
6714
|
}
|
|
5890
6715
|
});
|
|
5891
|
-
if (indicator) {
|
|
5892
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5893
|
-
}
|
|
5894
6716
|
container.scrollTop = 0;
|
|
5895
6717
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5896
6718
|
};
|
|
5897
6719
|
if (totalPages > 1) {
|
|
5898
6720
|
showPage(1);
|
|
5899
6721
|
}
|
|
5900
|
-
let fitMode = "width";
|
|
6722
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6723
|
+
let isUserZoomed = false;
|
|
5901
6724
|
const calculateFitScale = (mode = fitMode) => {
|
|
5902
6725
|
const elW = 816;
|
|
5903
6726
|
const elH = 1056;
|
|
5904
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
5905
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
6727
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6728
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5906
6729
|
const sW = availW / elW;
|
|
5907
6730
|
const sH = availH / elH;
|
|
5908
6731
|
if (mode === "page") {
|
|
5909
|
-
return Math.max(0.
|
|
6732
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5910
6733
|
}
|
|
5911
|
-
return Math.max(0.
|
|
6734
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5912
6735
|
};
|
|
6736
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6737
|
+
if (!isUserZoomed) {
|
|
6738
|
+
scale = calculateFitScale(fitMode);
|
|
6739
|
+
applyTransform();
|
|
6740
|
+
}
|
|
6741
|
+
}) : null;
|
|
6742
|
+
resizeObserver?.observe(ctx.container);
|
|
5913
6743
|
setTimeout(() => {
|
|
5914
|
-
|
|
5915
|
-
scale = calculateFitScale("width");
|
|
6744
|
+
scale = calculateFitScale(fitMode);
|
|
5916
6745
|
applyTransform();
|
|
5917
6746
|
}, 60);
|
|
5918
6747
|
const cleanup = () => {
|
|
5919
|
-
|
|
6748
|
+
resizeObserver?.disconnect();
|
|
5920
6749
|
container.remove();
|
|
5921
6750
|
ctx.container.innerHTML = "";
|
|
5922
6751
|
};
|
|
@@ -5927,21 +6756,25 @@ var DocPlugin = class {
|
|
|
5927
6756
|
getCurrentPage: () => currentPage,
|
|
5928
6757
|
goToPage: (page) => showPage(page),
|
|
5929
6758
|
zoomIn: () => {
|
|
6759
|
+
isUserZoomed = true;
|
|
5930
6760
|
scale += 0.15;
|
|
5931
6761
|
applyTransform();
|
|
5932
6762
|
},
|
|
5933
6763
|
zoomOut: () => {
|
|
6764
|
+
isUserZoomed = true;
|
|
5934
6765
|
scale = Math.max(0.2, scale - 0.15);
|
|
5935
6766
|
applyTransform();
|
|
5936
6767
|
},
|
|
5937
6768
|
getZoom: () => scale,
|
|
5938
6769
|
setZoom: (level) => {
|
|
6770
|
+
isUserZoomed = true;
|
|
5939
6771
|
scale = level;
|
|
5940
6772
|
applyTransform();
|
|
5941
6773
|
},
|
|
5942
6774
|
fitToPage: () => {
|
|
5943
|
-
|
|
5944
|
-
|
|
6775
|
+
isUserZoomed = false;
|
|
6776
|
+
fitMode = "width";
|
|
6777
|
+
scale = calculateFitScale("width");
|
|
5945
6778
|
rotation = 0;
|
|
5946
6779
|
applyTransform();
|
|
5947
6780
|
},
|
|
@@ -6318,25 +7151,31 @@ ${chartSvg}
|
|
|
6318
7151
|
i++;
|
|
6319
7152
|
continue;
|
|
6320
7153
|
}
|
|
6321
|
-
if (
|
|
7154
|
+
if (/^\d{1,2}$/.test(line.trim())) {
|
|
7155
|
+
i++;
|
|
7156
|
+
continue;
|
|
7157
|
+
}
|
|
7158
|
+
const isShortLine = line.length < 60 && !line.endsWith(".") && !line.endsWith(",");
|
|
7159
|
+
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));
|
|
7160
|
+
if (isTitleLike) {
|
|
6322
7161
|
if (inList) {
|
|
6323
7162
|
html += "</ul>";
|
|
6324
7163
|
inList = false;
|
|
6325
7164
|
}
|
|
6326
|
-
html += `<h2 style="font-size:
|
|
7165
|
+
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>`;
|
|
6327
7166
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
6328
7167
|
if (!inList) {
|
|
6329
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
7168
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
6330
7169
|
inList = true;
|
|
6331
7170
|
}
|
|
6332
7171
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
6333
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
7172
|
+
html += `<li style="margin: 4px 0; line-height: 1.5; font-size: 11pt; color: #1e293b;">${DOMPurify6__default.default.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
6334
7173
|
} else {
|
|
6335
7174
|
if (inList) {
|
|
6336
7175
|
html += "</ul>";
|
|
6337
7176
|
inList = false;
|
|
6338
7177
|
}
|
|
6339
|
-
html += `<p style="line-height: 1.
|
|
7178
|
+
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>`;
|
|
6340
7179
|
}
|
|
6341
7180
|
i++;
|
|
6342
7181
|
}
|