@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/react.cjs
CHANGED
|
@@ -528,8 +528,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
528
528
|
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>`;
|
|
529
529
|
var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
|
|
530
530
|
var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
|
|
531
|
-
var
|
|
532
|
-
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>`;
|
|
531
|
+
var ICON_EXTERNAL_WINDOW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="3" y1="8" x2="21" y2="8"></line><circle cx="6" cy="5.5" r="0.75" fill="currentColor"></circle><circle cx="8.5" cy="5.5" r="0.75" fill="currentColor"></circle><polyline points="14 13 18 13 18 17"></polyline><line x1="11" y1="20" x2="18" y2="13"></line></svg>`;
|
|
533
532
|
var ICON_MAP = {
|
|
534
533
|
"zoom-in": ICON_ZOOM_IN,
|
|
535
534
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -556,28 +555,177 @@ var ICON_MAP = {
|
|
|
556
555
|
"forward-10": ICON_FAST_FORWARD,
|
|
557
556
|
"rewind": ICON_REWIND,
|
|
558
557
|
"replay-10": ICON_REWIND,
|
|
559
|
-
"speed": ICON_SPEED,
|
|
560
558
|
"open-window": ICON_EXTERNAL_WINDOW,
|
|
561
|
-
"external-window": ICON_EXTERNAL_WINDOW
|
|
559
|
+
"external-window": ICON_EXTERNAL_WINDOW,
|
|
560
|
+
"openWindow": ICON_EXTERNAL_WINDOW,
|
|
561
|
+
"openSeparateWindow": ICON_EXTERNAL_WINDOW
|
|
562
562
|
};
|
|
563
563
|
var ToolbarController = class {
|
|
564
564
|
el;
|
|
565
565
|
toolbarEl;
|
|
566
566
|
actions = [];
|
|
567
|
+
config = {};
|
|
567
568
|
pageInputEl = null;
|
|
568
569
|
pageLabelEl = null;
|
|
569
|
-
|
|
570
|
+
prevPageBtn = null;
|
|
571
|
+
nextPageBtn = null;
|
|
572
|
+
constructor(container, config) {
|
|
570
573
|
this.el = container;
|
|
574
|
+
if (config) this.config = { ...config };
|
|
571
575
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
572
576
|
this.el.appendChild(this.toolbarEl);
|
|
573
577
|
}
|
|
578
|
+
setConfig(config) {
|
|
579
|
+
this.config = { ...config };
|
|
580
|
+
this.render();
|
|
581
|
+
}
|
|
582
|
+
getConfig() {
|
|
583
|
+
return { ...this.config };
|
|
584
|
+
}
|
|
585
|
+
hideAction(actionId) {
|
|
586
|
+
this.config[actionId] = false;
|
|
587
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = false;
|
|
588
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = false;
|
|
589
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
590
|
+
this.config.fitPage = false;
|
|
591
|
+
this.config.fitToPage = false;
|
|
592
|
+
this.config.fitWidth = false;
|
|
593
|
+
}
|
|
594
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
|
|
595
|
+
if (actionId === "fullscreen") this.config.fullscreen = false;
|
|
596
|
+
if (actionId === "download") this.config.download = false;
|
|
597
|
+
if (actionId === "print") this.config.print = false;
|
|
598
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
599
|
+
this.config.openWindow = false;
|
|
600
|
+
this.config.openSeparateWindow = false;
|
|
601
|
+
}
|
|
602
|
+
if (actionId === "copy") this.config.copy = false;
|
|
603
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
604
|
+
this.config.pageNav = false;
|
|
605
|
+
this.config.pagination = false;
|
|
606
|
+
}
|
|
607
|
+
this.render();
|
|
608
|
+
}
|
|
609
|
+
showAction(actionId) {
|
|
610
|
+
this.config[actionId] = true;
|
|
611
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = true;
|
|
612
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = true;
|
|
613
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
614
|
+
this.config.fitPage = true;
|
|
615
|
+
this.config.fitToPage = true;
|
|
616
|
+
this.config.fitWidth = true;
|
|
617
|
+
}
|
|
618
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
|
|
619
|
+
if (actionId === "fullscreen") this.config.fullscreen = true;
|
|
620
|
+
if (actionId === "download") this.config.download = true;
|
|
621
|
+
if (actionId === "print") this.config.print = true;
|
|
622
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
623
|
+
this.config.openWindow = true;
|
|
624
|
+
this.config.openSeparateWindow = true;
|
|
625
|
+
}
|
|
626
|
+
if (actionId === "copy") this.config.copy = true;
|
|
627
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
628
|
+
this.config.pageNav = true;
|
|
629
|
+
this.config.pagination = true;
|
|
630
|
+
}
|
|
631
|
+
this.render();
|
|
632
|
+
}
|
|
633
|
+
normalizeActionId(actionId) {
|
|
634
|
+
if (actionId === "zoomIn") return "zoom-in";
|
|
635
|
+
if (actionId === "zoomOut") return "zoom-out";
|
|
636
|
+
if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
|
|
637
|
+
if (actionId === "rotateCW") return "rotate-cw";
|
|
638
|
+
if (actionId === "rotateCCW") return "rotate-ccw";
|
|
639
|
+
if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
|
|
640
|
+
if (actionId === "pageNav") return "page-nav";
|
|
641
|
+
return actionId;
|
|
642
|
+
}
|
|
643
|
+
enableAction(actionId) {
|
|
644
|
+
const norm = this.normalizeActionId(actionId);
|
|
645
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
646
|
+
if (btn) {
|
|
647
|
+
btn.disabled = false;
|
|
648
|
+
btn.classList.remove("disabled");
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
disableAction(actionId) {
|
|
652
|
+
const norm = this.normalizeActionId(actionId);
|
|
653
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
654
|
+
if (btn) {
|
|
655
|
+
btn.disabled = true;
|
|
656
|
+
btn.classList.add("disabled");
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
setActionActive(actionId, active) {
|
|
660
|
+
const norm = this.normalizeActionId(actionId);
|
|
661
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
662
|
+
if (btn) {
|
|
663
|
+
if (active) {
|
|
664
|
+
btn.classList.add("active");
|
|
665
|
+
} else {
|
|
666
|
+
btn.classList.remove("active");
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
isActionEnabled(action) {
|
|
671
|
+
const c = this.config;
|
|
672
|
+
const id = action.id;
|
|
673
|
+
if (c[id] === false) return false;
|
|
674
|
+
if (id === "zoom-in" && (c.zoomIn === false || c["zoom-in"] === false)) return false;
|
|
675
|
+
if (id === "zoom-out" && (c.zoomOut === false || c["zoom-out"] === false)) return false;
|
|
676
|
+
if ((id === "fit-page" || id === "fit-width" || id === "fit-slide") && (c.fitPage === false || c.fitToPage === false || c.fitWidth === false || c["fit-page"] === false || c["fit-width"] === false)) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
if (id === "fullscreen" && c.fullscreen === false) return false;
|
|
683
|
+
if (id === "download" && c.download === false) return false;
|
|
684
|
+
if (id === "print" && c.print === false) return false;
|
|
685
|
+
if ((id === "open-window" || id === "external-window") && (c.openWindow === false || c.openSeparateWindow === false || c["open-window"] === false)) {
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
if (id === "copy" && c.copy === false) return false;
|
|
689
|
+
if (id === "thumbnails" && c.thumbnails === false) return false;
|
|
690
|
+
if (id === "page-nav" && (c.pageNav === false || c.pagination === false || c["page-nav"] === false)) {
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
if ((id === "prev" || id === "page-prev") && (c.prevPage === false || c.prev === false || c["prev"] === false || c.pageNav === false || c.pagination === false)) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
if ((id === "next" || id === "page-next") && (c.nextPage === false || c.next === false || c["next"] === false || c.pageNav === false || c.pagination === false)) {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
if (id === "play" && c.play === false) return false;
|
|
700
|
+
if (id === "pause" && c.pause === false) return false;
|
|
701
|
+
if ((id === "fast-forward" || id === "forward-10") && (c.fastForward === false || c["fast-forward"] === false)) {
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
if ((id === "rewind" || id === "replay-10") && (c.rewind === false || c["rewind"] === false)) {
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
if (id === "speed" && c.speed === false) return false;
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
574
710
|
setPage(page, max) {
|
|
575
711
|
if (this.pageInputEl) {
|
|
576
712
|
this.pageInputEl.value = page.toString();
|
|
713
|
+
if (max !== void 0) {
|
|
714
|
+
this.pageInputEl.max = max.toString();
|
|
715
|
+
}
|
|
577
716
|
}
|
|
578
717
|
if (max !== void 0 && this.pageLabelEl) {
|
|
579
718
|
this.pageLabelEl.textContent = ` / ${max}`;
|
|
580
719
|
}
|
|
720
|
+
const currentMax = max !== void 0 ? max : parseInt(this.pageInputEl?.max || "1", 10) || 1;
|
|
721
|
+
if (this.prevPageBtn) {
|
|
722
|
+
this.prevPageBtn.disabled = page <= 1;
|
|
723
|
+
this.prevPageBtn.style.opacity = page <= 1 ? "0.4" : "1";
|
|
724
|
+
}
|
|
725
|
+
if (this.nextPageBtn) {
|
|
726
|
+
this.nextPageBtn.disabled = page >= currentMax;
|
|
727
|
+
this.nextPageBtn.style.opacity = page >= currentMax ? "0.4" : "1";
|
|
728
|
+
}
|
|
581
729
|
}
|
|
582
730
|
update(actions) {
|
|
583
731
|
this.actions = actions;
|
|
@@ -600,8 +748,9 @@ var ToolbarController = class {
|
|
|
600
748
|
view: [],
|
|
601
749
|
actions: []
|
|
602
750
|
};
|
|
603
|
-
const
|
|
604
|
-
const
|
|
751
|
+
const enabledActions = this.actions.filter((a) => this.isActionEnabled(a));
|
|
752
|
+
const hasPageNav = enabledActions.some((a) => a.type === "page-nav");
|
|
753
|
+
const effectiveActions = hasPageNav ? enabledActions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : enabledActions;
|
|
605
754
|
for (const action of effectiveActions) {
|
|
606
755
|
if (groups[action.group]) {
|
|
607
756
|
groups[action.group].push(action);
|
|
@@ -661,6 +810,13 @@ var ToolbarController = class {
|
|
|
661
810
|
action.execute("go", val);
|
|
662
811
|
});
|
|
663
812
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
813
|
+
const curVal = action.value ?? 1;
|
|
814
|
+
prevBtn.disabled = curVal <= 1;
|
|
815
|
+
prevBtn.style.opacity = curVal <= 1 ? "0.4" : "1";
|
|
816
|
+
nextBtn.disabled = curVal >= max;
|
|
817
|
+
nextBtn.style.opacity = curVal >= max ? "0.4" : "1";
|
|
818
|
+
this.prevPageBtn = prevBtn;
|
|
819
|
+
this.nextPageBtn = nextBtn;
|
|
664
820
|
this.pageInputEl = input;
|
|
665
821
|
this.pageLabelEl = label;
|
|
666
822
|
groupEl.appendChild(prevBtn);
|
|
@@ -716,25 +872,63 @@ var ToolbarController = class {
|
|
|
716
872
|
var ThumbnailPanel = class {
|
|
717
873
|
el;
|
|
718
874
|
panelEl;
|
|
875
|
+
listEl;
|
|
876
|
+
headerEl;
|
|
719
877
|
thumbnails = [];
|
|
720
878
|
onSelect;
|
|
879
|
+
onToggleCallback;
|
|
721
880
|
activeIndex = 0;
|
|
722
|
-
|
|
881
|
+
observer;
|
|
882
|
+
renderedIndices = /* @__PURE__ */ new Set();
|
|
883
|
+
constructor(container, onToggle) {
|
|
723
884
|
this.el = container;
|
|
885
|
+
this.onToggleCallback = onToggle;
|
|
724
886
|
this.panelEl = createElement("div", { className: "fp-thumbnail-panel hidden" });
|
|
887
|
+
this.panelEl.style.width = "0px";
|
|
888
|
+
this.panelEl.style.minWidth = "0px";
|
|
889
|
+
this.panelEl.style.opacity = "0";
|
|
890
|
+
this.headerEl = createElement("div", { className: "fp-thumbnail-header" });
|
|
891
|
+
const title = createElement("span", { className: "fp-thumbnail-title" }, "Pages");
|
|
892
|
+
const closeBtn = createElement("button", {
|
|
893
|
+
className: "fp-thumbnail-close-btn",
|
|
894
|
+
title: "Close Thumbnails",
|
|
895
|
+
type: "button"
|
|
896
|
+
});
|
|
897
|
+
closeBtn.innerHTML = ICON_CLOSE;
|
|
898
|
+
closeBtn.addEventListener("click", (e) => {
|
|
899
|
+
e.stopPropagation();
|
|
900
|
+
this.hide();
|
|
901
|
+
});
|
|
902
|
+
this.headerEl.appendChild(title);
|
|
903
|
+
this.headerEl.appendChild(closeBtn);
|
|
904
|
+
this.listEl = createElement("div", { className: "fp-thumbnail-list" });
|
|
905
|
+
this.panelEl.appendChild(this.headerEl);
|
|
906
|
+
this.panelEl.appendChild(this.listEl);
|
|
725
907
|
this.el.appendChild(this.panelEl);
|
|
726
908
|
}
|
|
909
|
+
isOpen() {
|
|
910
|
+
return !this.panelEl.classList.contains("hidden") && this.panelEl.style.width !== "0px";
|
|
911
|
+
}
|
|
727
912
|
update(thumbnails, onSelect) {
|
|
728
913
|
this.thumbnails = thumbnails;
|
|
729
914
|
this.onSelect = onSelect;
|
|
915
|
+
this.renderedIndices.clear();
|
|
916
|
+
const titleEl = this.headerEl.querySelector(".fp-thumbnail-title");
|
|
917
|
+
if (titleEl) {
|
|
918
|
+
titleEl.textContent = `Pages (${thumbnails.length})`;
|
|
919
|
+
}
|
|
730
920
|
this.render();
|
|
921
|
+
if (this.isOpen()) {
|
|
922
|
+
this.renderAllVisible();
|
|
923
|
+
}
|
|
731
924
|
}
|
|
732
925
|
setActive(index) {
|
|
733
926
|
this.activeIndex = index;
|
|
734
|
-
const items = this.
|
|
927
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
735
928
|
items.forEach((item, i) => {
|
|
736
929
|
if (i === index) {
|
|
737
930
|
item.classList.add("active");
|
|
931
|
+
item.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
738
932
|
} else {
|
|
739
933
|
item.classList.remove("active");
|
|
740
934
|
}
|
|
@@ -742,37 +936,102 @@ var ThumbnailPanel = class {
|
|
|
742
936
|
}
|
|
743
937
|
show() {
|
|
744
938
|
this.panelEl.classList.remove("hidden");
|
|
939
|
+
this.panelEl.style.width = "200px";
|
|
940
|
+
this.panelEl.style.minWidth = "200px";
|
|
941
|
+
this.panelEl.style.opacity = "1";
|
|
942
|
+
this.panelEl.style.display = "flex";
|
|
943
|
+
this.onToggleCallback?.(true);
|
|
944
|
+
this.renderAllVisible();
|
|
745
945
|
}
|
|
746
946
|
hide() {
|
|
747
947
|
this.panelEl.classList.add("hidden");
|
|
948
|
+
this.panelEl.style.width = "0px";
|
|
949
|
+
this.panelEl.style.minWidth = "0px";
|
|
950
|
+
this.panelEl.style.opacity = "0";
|
|
951
|
+
this.onToggleCallback?.(false);
|
|
748
952
|
}
|
|
749
953
|
toggle() {
|
|
750
|
-
this.
|
|
954
|
+
if (this.isOpen()) {
|
|
955
|
+
this.hide();
|
|
956
|
+
} else {
|
|
957
|
+
this.show();
|
|
958
|
+
}
|
|
751
959
|
}
|
|
752
960
|
destroy() {
|
|
961
|
+
if (this.observer) {
|
|
962
|
+
this.observer.disconnect();
|
|
963
|
+
this.observer = void 0;
|
|
964
|
+
}
|
|
965
|
+
this.renderedIndices.clear();
|
|
753
966
|
this.el.innerHTML = "";
|
|
754
967
|
}
|
|
755
|
-
|
|
756
|
-
this.
|
|
968
|
+
renderAllVisible() {
|
|
969
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
970
|
+
items.forEach((item) => {
|
|
971
|
+
const idx = parseInt(item.dataset.thumbIndex || "-1", 10);
|
|
972
|
+
if (idx >= 0 && !this.renderedIndices.has(idx)) {
|
|
973
|
+
this.renderThumbnailItem(idx, item);
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
renderThumbnailItem(idx, itemEl) {
|
|
978
|
+
if (this.renderedIndices.has(idx)) return;
|
|
979
|
+
this.renderedIndices.add(idx);
|
|
980
|
+
const canvas = itemEl.querySelector("canvas");
|
|
981
|
+
const thumb = this.thumbnails[idx];
|
|
982
|
+
if (canvas && thumb) {
|
|
983
|
+
Promise.resolve(thumb.render(canvas)).catch((err) => {
|
|
984
|
+
console.warn(`[FilePreview] Error rendering thumbnail ${idx}:`, err);
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
render() {
|
|
989
|
+
if (this.observer) {
|
|
990
|
+
this.observer.disconnect();
|
|
991
|
+
}
|
|
992
|
+
this.listEl.innerHTML = "";
|
|
993
|
+
const useObserver = typeof IntersectionObserver !== "undefined";
|
|
994
|
+
if (useObserver) {
|
|
995
|
+
this.observer = new IntersectionObserver(
|
|
996
|
+
(entries) => {
|
|
997
|
+
for (const entry of entries) {
|
|
998
|
+
if (entry.isIntersecting) {
|
|
999
|
+
const target = entry.target;
|
|
1000
|
+
const idx = parseInt(target.dataset.thumbIndex || "-1", 10);
|
|
1001
|
+
if (idx >= 0) {
|
|
1002
|
+
this.renderThumbnailItem(idx, target);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
root: this.listEl,
|
|
1009
|
+
rootMargin: "120px 0px 120px 0px"
|
|
1010
|
+
}
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
757
1013
|
for (let i = 0; i < this.thumbnails.length; i++) {
|
|
758
1014
|
const thumb = this.thumbnails[i];
|
|
759
|
-
const itemEl = createElement("div", {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1015
|
+
const itemEl = createElement("div", {
|
|
1016
|
+
className: "fp-thumbnail-item" + (i === this.activeIndex ? " active" : "")
|
|
1017
|
+
});
|
|
1018
|
+
itemEl.dataset.thumbIndex = i.toString();
|
|
763
1019
|
itemEl.addEventListener("click", () => {
|
|
764
1020
|
this.setActive(i);
|
|
765
1021
|
this.onSelect?.(i);
|
|
766
1022
|
});
|
|
767
|
-
const
|
|
768
|
-
const
|
|
769
|
-
|
|
1023
|
+
const canvasWrapper = createElement("div", { className: "fp-thumbnail-canvas-wrapper" });
|
|
1024
|
+
const canvas = createElement("canvas", { width: "130", height: "170" });
|
|
1025
|
+
canvasWrapper.appendChild(canvas);
|
|
1026
|
+
const label = createElement("span", { className: "fp-thumbnail-label" }, thumb.label || `Page ${i + 1}`);
|
|
1027
|
+
itemEl.appendChild(canvasWrapper);
|
|
770
1028
|
itemEl.appendChild(label);
|
|
771
|
-
this.
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
|
|
1029
|
+
this.listEl.appendChild(itemEl);
|
|
1030
|
+
if (this.observer) {
|
|
1031
|
+
this.observer.observe(itemEl);
|
|
1032
|
+
}
|
|
1033
|
+
if (i < 4) {
|
|
1034
|
+
this.renderThumbnailItem(i, itemEl);
|
|
776
1035
|
}
|
|
777
1036
|
}
|
|
778
1037
|
}
|
|
@@ -793,6 +1052,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
793
1052
|
currentOptions = {};
|
|
794
1053
|
resizeObserver = null;
|
|
795
1054
|
fullscreenHandler = null;
|
|
1055
|
+
titleBarEl = null;
|
|
796
1056
|
/**
|
|
797
1057
|
* Register a preview plugin.
|
|
798
1058
|
*/
|
|
@@ -829,6 +1089,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
829
1089
|
}
|
|
830
1090
|
this.currentBuffer = buffer.slice(0);
|
|
831
1091
|
this.currentMetadata = metadata;
|
|
1092
|
+
this.updateTitleBar(options, metadata);
|
|
832
1093
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
833
1094
|
const fileInfo = { metadata, buffer };
|
|
834
1095
|
const matchedPlugin = await this.findPlugin(fileInfo);
|
|
@@ -852,15 +1113,21 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
852
1113
|
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
853
1114
|
const total = payload.total ?? payload.totalPages;
|
|
854
1115
|
this.toolbar?.setPage(payload.page, total);
|
|
1116
|
+
this.thumbnailPanel?.setActive(payload.page - 1);
|
|
855
1117
|
}
|
|
856
1118
|
this.eventEmitter.emit(event, payload);
|
|
857
|
-
}
|
|
1119
|
+
},
|
|
1120
|
+
toggleThumbnails: () => this.toggleThumbnails()
|
|
858
1121
|
});
|
|
859
1122
|
this.activeInstance = instance;
|
|
860
1123
|
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
1124
|
+
instance.toggleThumbnails = () => this.toggleThumbnails();
|
|
861
1125
|
this.hideLoading();
|
|
862
1126
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
863
|
-
|
|
1127
|
+
const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
|
|
1128
|
+
if (isToolbarVisible && this.toolbar) {
|
|
1129
|
+
const toolbarConfig = this.extractToolbarConfig(options);
|
|
1130
|
+
this.toolbar.setConfig(toolbarConfig);
|
|
864
1131
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
865
1132
|
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
866
1133
|
if (!hasFullscreen && this.wrapperEl) {
|
|
@@ -910,6 +1177,12 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
910
1177
|
}
|
|
911
1178
|
});
|
|
912
1179
|
}
|
|
1180
|
+
const thumbAction = actions.find((a) => a.id === "thumbnails");
|
|
1181
|
+
if (thumbAction) {
|
|
1182
|
+
thumbAction.execute = () => {
|
|
1183
|
+
this.toggleThumbnails();
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
913
1186
|
this.toolbar.update(actions);
|
|
914
1187
|
this.toolbar.show();
|
|
915
1188
|
}
|
|
@@ -994,7 +1267,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
994
1267
|
if (targetUrl) {
|
|
995
1268
|
const newWin2 = window.open(targetUrl, "_blank");
|
|
996
1269
|
if (!newWin2) {
|
|
997
|
-
|
|
1270
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
998
1271
|
return null;
|
|
999
1272
|
}
|
|
1000
1273
|
return newWin2;
|
|
@@ -1002,7 +1275,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1002
1275
|
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1003
1276
|
const newWin = window.open("", "_blank");
|
|
1004
1277
|
if (!newWin) {
|
|
1005
|
-
|
|
1278
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1006
1279
|
return null;
|
|
1007
1280
|
}
|
|
1008
1281
|
newWin.document.title = title;
|
|
@@ -1079,6 +1352,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1079
1352
|
this.currentBuffer = null;
|
|
1080
1353
|
this.currentMetadata = null;
|
|
1081
1354
|
this.currentContainer = null;
|
|
1355
|
+
this.titleBarEl = null;
|
|
1082
1356
|
}
|
|
1083
1357
|
/**
|
|
1084
1358
|
* Get the currently active preview instance.
|
|
@@ -1086,7 +1360,218 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1086
1360
|
getInstance() {
|
|
1087
1361
|
return this.activeInstance;
|
|
1088
1362
|
}
|
|
1363
|
+
// --- Toolbar Configuration & Feature Toggles ---
|
|
1364
|
+
/**
|
|
1365
|
+
* Configure toolbar features dynamically through options or methods.
|
|
1366
|
+
* e.g. viewer.setToolbarConfig({ zoomIn: false, print: false })
|
|
1367
|
+
*/
|
|
1368
|
+
setToolbarConfig(config) {
|
|
1369
|
+
this.toolbar?.setConfig(config);
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* Get current toolbar configuration.
|
|
1373
|
+
*/
|
|
1374
|
+
getToolbarConfig() {
|
|
1375
|
+
return this.toolbar?.getConfig() ?? {};
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Hide a specific toolbar action by ID or alias (e.g. 'zoom-in', 'print', 'download').
|
|
1379
|
+
*/
|
|
1380
|
+
hideToolbarAction(actionId) {
|
|
1381
|
+
this.toolbar?.hideAction(actionId);
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Show a specific toolbar action by ID or alias.
|
|
1385
|
+
*/
|
|
1386
|
+
showToolbarAction(actionId) {
|
|
1387
|
+
this.toolbar?.showAction(actionId);
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Enable a specific toolbar action button.
|
|
1391
|
+
*/
|
|
1392
|
+
enableToolbarAction(actionId) {
|
|
1393
|
+
this.toolbar?.enableAction(actionId);
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Disable a specific toolbar action button.
|
|
1397
|
+
*/
|
|
1398
|
+
disableToolbarAction(actionId) {
|
|
1399
|
+
this.toolbar?.disableAction(actionId);
|
|
1400
|
+
}
|
|
1401
|
+
// --- Programmatic Toolbar Action Methods ---
|
|
1402
|
+
/**
|
|
1403
|
+
* Fit document to page so it fills the frame width with minimal margins.
|
|
1404
|
+
*/
|
|
1405
|
+
fitToPage() {
|
|
1406
|
+
this.activeInstance?.fitToPage?.();
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* Zoom in.
|
|
1410
|
+
*/
|
|
1411
|
+
zoomIn() {
|
|
1412
|
+
this.activeInstance?.zoomIn?.();
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Zoom out.
|
|
1416
|
+
*/
|
|
1417
|
+
zoomOut() {
|
|
1418
|
+
this.activeInstance?.zoomOut?.();
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Set specific zoom level.
|
|
1422
|
+
*/
|
|
1423
|
+
setZoom(level) {
|
|
1424
|
+
this.activeInstance?.setZoom?.(level);
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Get current zoom level.
|
|
1428
|
+
*/
|
|
1429
|
+
getZoom() {
|
|
1430
|
+
return this.activeInstance?.getZoom?.() ?? 1;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Rotate 90 degrees clockwise.
|
|
1434
|
+
*/
|
|
1435
|
+
rotateCW() {
|
|
1436
|
+
this.activeInstance?.rotateCW?.();
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Rotate 90 degrees counter-clockwise.
|
|
1440
|
+
*/
|
|
1441
|
+
rotateCCW() {
|
|
1442
|
+
this.activeInstance?.rotateCCW?.();
|
|
1443
|
+
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Navigate to a specific page number.
|
|
1446
|
+
*/
|
|
1447
|
+
goToPage(page) {
|
|
1448
|
+
this.activeInstance?.goToPage?.(page);
|
|
1449
|
+
this.toolbar?.setPage(page);
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Navigate to next page.
|
|
1453
|
+
*/
|
|
1454
|
+
nextPage() {
|
|
1455
|
+
const cur = this.getCurrentPage();
|
|
1456
|
+
const max = this.getPageCount();
|
|
1457
|
+
if (cur < max) {
|
|
1458
|
+
this.goToPage(cur + 1);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Navigate to previous page.
|
|
1463
|
+
*/
|
|
1464
|
+
prevPage() {
|
|
1465
|
+
const cur = this.getCurrentPage();
|
|
1466
|
+
if (cur > 1) {
|
|
1467
|
+
this.goToPage(cur - 1);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Get total page count.
|
|
1472
|
+
*/
|
|
1473
|
+
getPageCount() {
|
|
1474
|
+
return this.activeInstance?.getPageCount?.() ?? 1;
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Get current page number.
|
|
1478
|
+
*/
|
|
1479
|
+
getCurrentPage() {
|
|
1480
|
+
return this.activeInstance?.getCurrentPage?.() ?? 1;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Download the current document.
|
|
1484
|
+
*/
|
|
1485
|
+
download() {
|
|
1486
|
+
this.activeInstance?.download?.();
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Print the current document.
|
|
1490
|
+
*/
|
|
1491
|
+
print() {
|
|
1492
|
+
this.activeInstance?.print?.();
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Toggle fullscreen mode.
|
|
1496
|
+
*/
|
|
1497
|
+
toggleFullscreen() {
|
|
1498
|
+
try {
|
|
1499
|
+
if (!document.fullscreenElement) {
|
|
1500
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
1501
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
1502
|
+
} else {
|
|
1503
|
+
document.exitFullscreen?.();
|
|
1504
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
1505
|
+
}
|
|
1506
|
+
} catch {
|
|
1507
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
1508
|
+
}
|
|
1509
|
+
setTimeout(() => {
|
|
1510
|
+
this.activeInstance?.fitToPage?.();
|
|
1511
|
+
}, 120);
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Toggle thumbnails sidebar panel.
|
|
1515
|
+
*/
|
|
1516
|
+
toggleThumbnails() {
|
|
1517
|
+
if (!this.thumbnailPanel) return;
|
|
1518
|
+
this.thumbnailPanel.toggle();
|
|
1519
|
+
const isOpen = this.thumbnailPanel.isOpen();
|
|
1520
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1521
|
+
setTimeout(() => {
|
|
1522
|
+
this.activeInstance?.fitToPage?.();
|
|
1523
|
+
}, 260);
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Set whether to display the file name / title bar above the toolbar.
|
|
1527
|
+
*/
|
|
1528
|
+
setShowFileName(show) {
|
|
1529
|
+
if (this.currentOptions) {
|
|
1530
|
+
this.currentOptions.showFileName = show;
|
|
1531
|
+
}
|
|
1532
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Set or override the displayed file name in the preview panel.
|
|
1536
|
+
*/
|
|
1537
|
+
setFileName(name) {
|
|
1538
|
+
if (this.currentOptions) {
|
|
1539
|
+
this.currentOptions.fileName = name;
|
|
1540
|
+
}
|
|
1541
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1542
|
+
}
|
|
1089
1543
|
// --- Private methods ---
|
|
1544
|
+
updateTitleBar(options, metadata) {
|
|
1545
|
+
if (!this.titleBarEl) return;
|
|
1546
|
+
const show = options?.showFileName !== false;
|
|
1547
|
+
if (!show) {
|
|
1548
|
+
this.titleBarEl.style.display = "none";
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
const name = options?.fileName || metadata?.name || this.currentMetadata?.name || "";
|
|
1552
|
+
if (!name) {
|
|
1553
|
+
this.titleBarEl.style.display = "none";
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
this.titleBarEl.style.display = "flex";
|
|
1557
|
+
const ext = metadata?.extension || (name.includes(".") ? "." + name.split(".").pop() : "");
|
|
1558
|
+
const badge = ext ? ext.replace(".", "").toUpperCase() : "";
|
|
1559
|
+
this.titleBarEl.innerHTML = `
|
|
1560
|
+
<div class="fp-titlebar-info">
|
|
1561
|
+
<span class="fp-titlebar-icon">\u{1F4C4}</span>
|
|
1562
|
+
<span class="fp-titlebar-name" title="${name}">${name}</span>
|
|
1563
|
+
${badge ? `<span class="fp-titlebar-badge">${badge}</span>` : ""}
|
|
1564
|
+
</div>
|
|
1565
|
+
`;
|
|
1566
|
+
}
|
|
1567
|
+
extractToolbarConfig(options) {
|
|
1568
|
+
if (!options) return {};
|
|
1569
|
+
const nested = typeof options.toolbar === "object" ? options.toolbar : {};
|
|
1570
|
+
return {
|
|
1571
|
+
...options,
|
|
1572
|
+
...nested
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1090
1575
|
abort() {
|
|
1091
1576
|
if (this.abortController) {
|
|
1092
1577
|
this.abortController.abort();
|
|
@@ -1129,17 +1614,29 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1129
1614
|
bodyEl.className = "fp-body";
|
|
1130
1615
|
bodyEl.appendChild(thumbnailEl);
|
|
1131
1616
|
bodyEl.appendChild(this.contentEl);
|
|
1617
|
+
const titleBarEl = document.createElement("div");
|
|
1618
|
+
titleBarEl.className = "fp-titlebar";
|
|
1619
|
+
this.titleBarEl = titleBarEl;
|
|
1620
|
+
this.updateTitleBar(options, this.currentMetadata);
|
|
1132
1621
|
if (toolbarPos === "top") {
|
|
1622
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1133
1623
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1134
1624
|
this.wrapperEl.appendChild(bodyEl);
|
|
1135
1625
|
} else {
|
|
1626
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1136
1627
|
this.wrapperEl.appendChild(bodyEl);
|
|
1137
1628
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1138
1629
|
}
|
|
1139
1630
|
container.innerHTML = "";
|
|
1140
1631
|
container.appendChild(this.wrapperEl);
|
|
1141
|
-
|
|
1142
|
-
this.
|
|
1632
|
+
const initialToolbarConfig = this.extractToolbarConfig(options);
|
|
1633
|
+
this.toolbar = new ToolbarController(toolbarEl, initialToolbarConfig);
|
|
1634
|
+
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl, (isOpen) => {
|
|
1635
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1636
|
+
setTimeout(() => {
|
|
1637
|
+
this.activeInstance?.fitToPage?.();
|
|
1638
|
+
}, 260);
|
|
1639
|
+
});
|
|
1143
1640
|
this.setupKeyboardShortcuts();
|
|
1144
1641
|
this.setupDragAndDrop(container, options);
|
|
1145
1642
|
this.setupResizeAndFullscreenListeners();
|
|
@@ -1529,6 +2026,14 @@ var PdfPlugin = class {
|
|
|
1529
2026
|
group: "zoom",
|
|
1530
2027
|
execute: () => instance.fitToPage?.()
|
|
1531
2028
|
},
|
|
2029
|
+
{
|
|
2030
|
+
id: "fit-width",
|
|
2031
|
+
icon: "fit-width",
|
|
2032
|
+
label: "Fit to Width",
|
|
2033
|
+
type: "button",
|
|
2034
|
+
group: "zoom",
|
|
2035
|
+
execute: () => instance.fitToWidth?.()
|
|
2036
|
+
},
|
|
1532
2037
|
{
|
|
1533
2038
|
id: "rotate-cw",
|
|
1534
2039
|
icon: "rotate-cw",
|
|
@@ -1537,6 +2042,14 @@ var PdfPlugin = class {
|
|
|
1537
2042
|
group: "view",
|
|
1538
2043
|
execute: () => instance.rotateCW?.()
|
|
1539
2044
|
},
|
|
2045
|
+
{
|
|
2046
|
+
id: "rotate-ccw",
|
|
2047
|
+
icon: "rotate-ccw",
|
|
2048
|
+
label: "Rotate Counter-Clockwise",
|
|
2049
|
+
type: "button",
|
|
2050
|
+
group: "view",
|
|
2051
|
+
execute: () => instance.rotateCCW?.()
|
|
2052
|
+
},
|
|
1540
2053
|
{
|
|
1541
2054
|
id: "download",
|
|
1542
2055
|
icon: "download",
|
|
@@ -1568,12 +2081,13 @@ var PdfPlugin = class {
|
|
|
1568
2081
|
container.className = "fp-pdf-container";
|
|
1569
2082
|
container.style.width = "100%";
|
|
1570
2083
|
container.style.height = "100%";
|
|
1571
|
-
container.style.
|
|
2084
|
+
container.style.overflowX = "hidden";
|
|
2085
|
+
container.style.overflowY = "auto";
|
|
1572
2086
|
container.style.display = "flex";
|
|
1573
2087
|
container.style.flexDirection = "column";
|
|
1574
2088
|
container.style.alignItems = "center";
|
|
1575
2089
|
container.style.justifyContent = "flex-start";
|
|
1576
|
-
container.style.padding = "
|
|
2090
|
+
container.style.padding = "16px 8px";
|
|
1577
2091
|
container.style.backgroundColor = "#0f172a";
|
|
1578
2092
|
container.style.boxSizing = "border-box";
|
|
1579
2093
|
container.style.position = "relative";
|
|
@@ -1584,30 +2098,12 @@ var PdfPlugin = class {
|
|
|
1584
2098
|
pageCard.style.borderRadius = "4px";
|
|
1585
2099
|
pageCard.style.overflow = "hidden";
|
|
1586
2100
|
pageCard.style.lineHeight = "0";
|
|
1587
|
-
pageCard.style.transition = "transform 0.15s ease";
|
|
1588
2101
|
pageCard.style.position = "relative";
|
|
1589
2102
|
pageCard.style.flexShrink = "0";
|
|
2103
|
+
pageCard.style.transition = "box-shadow 0.2s ease";
|
|
1590
2104
|
let canvas = document.createElement("canvas");
|
|
1591
2105
|
pageCard.appendChild(canvas);
|
|
1592
2106
|
container.appendChild(pageCard);
|
|
1593
|
-
const indicator = document.createElement("div");
|
|
1594
|
-
indicator.className = "fp-pdf-page-indicator";
|
|
1595
|
-
indicator.style.position = "sticky";
|
|
1596
|
-
indicator.style.bottom = "16px";
|
|
1597
|
-
indicator.style.marginTop = "16px";
|
|
1598
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1599
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
1600
|
-
indicator.style.color = "#f8fafc";
|
|
1601
|
-
indicator.style.fontSize = "12px";
|
|
1602
|
-
indicator.style.fontWeight = "600";
|
|
1603
|
-
indicator.style.padding = "5px 14px";
|
|
1604
|
-
indicator.style.borderRadius = "20px";
|
|
1605
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1606
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1607
|
-
indicator.style.zIndex = "10";
|
|
1608
|
-
indicator.style.userSelect = "none";
|
|
1609
|
-
indicator.style.pointerEvents = "none";
|
|
1610
|
-
container.appendChild(indicator);
|
|
1611
2107
|
ctx.container.appendChild(container);
|
|
1612
2108
|
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1613
2109
|
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
@@ -1623,8 +2119,9 @@ var PdfPlugin = class {
|
|
|
1623
2119
|
let currentPage = 1;
|
|
1624
2120
|
let zoomScale = 1;
|
|
1625
2121
|
let rotation = 0;
|
|
1626
|
-
let fitMode = "
|
|
2122
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
1627
2123
|
let currentRenderTask = null;
|
|
2124
|
+
let textLayerDiv = null;
|
|
1628
2125
|
const renderPage = async (pageNum) => {
|
|
1629
2126
|
if (currentRenderTask) {
|
|
1630
2127
|
try {
|
|
@@ -1636,30 +2133,37 @@ var PdfPlugin = class {
|
|
|
1636
2133
|
const newCanvas = document.createElement("canvas");
|
|
1637
2134
|
pageCard.replaceChild(newCanvas, canvas);
|
|
1638
2135
|
canvas = newCanvas;
|
|
2136
|
+
if (textLayerDiv) {
|
|
2137
|
+
textLayerDiv.remove();
|
|
2138
|
+
textLayerDiv = null;
|
|
2139
|
+
}
|
|
1639
2140
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1640
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1641
2141
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1642
2142
|
const page = await pdfDoc.getPage(currentPage);
|
|
1643
2143
|
const containerWidth = container.clientWidth || 900;
|
|
1644
2144
|
const containerHeight = container.clientHeight || 700;
|
|
1645
2145
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1646
|
-
const availWidth = Math.max(
|
|
1647
|
-
const availHeight = Math.max(
|
|
2146
|
+
const availWidth = Math.max(280, containerWidth - 36);
|
|
2147
|
+
const availHeight = Math.max(280, containerHeight - 32);
|
|
1648
2148
|
const scaleW = availWidth / unscaledVp.width;
|
|
1649
2149
|
const scaleH = availHeight / unscaledVp.height;
|
|
1650
2150
|
let fitScale;
|
|
1651
2151
|
if (fitMode === "page") {
|
|
1652
|
-
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
2152
|
+
fitScale = Math.max(0.2, Math.min(4, Math.min(scaleW, scaleH)));
|
|
1653
2153
|
} else {
|
|
1654
|
-
fitScale = Math.max(0.
|
|
2154
|
+
fitScale = Math.max(0.2, Math.min(4, scaleW));
|
|
1655
2155
|
}
|
|
1656
2156
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1657
2157
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1658
2158
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
2159
|
+
const displayWidth = Math.floor(viewport.width);
|
|
2160
|
+
const displayHeight = Math.floor(viewport.height);
|
|
1659
2161
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1660
2162
|
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1661
|
-
canvas.style.width = `${
|
|
1662
|
-
canvas.style.height = `${
|
|
2163
|
+
canvas.style.width = `${displayWidth}px`;
|
|
2164
|
+
canvas.style.height = `${displayHeight}px`;
|
|
2165
|
+
pageCard.style.width = `${displayWidth}px`;
|
|
2166
|
+
pageCard.style.height = `${displayHeight}px`;
|
|
1663
2167
|
const canvasCtx = canvas.getContext("2d");
|
|
1664
2168
|
if (!canvasCtx) return;
|
|
1665
2169
|
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
@@ -1673,9 +2177,31 @@ var PdfPlugin = class {
|
|
|
1673
2177
|
if (err?.name !== "RenderingCancelledException") {
|
|
1674
2178
|
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1675
2179
|
}
|
|
2180
|
+
return;
|
|
1676
2181
|
} finally {
|
|
1677
2182
|
currentRenderTask = null;
|
|
1678
2183
|
}
|
|
2184
|
+
try {
|
|
2185
|
+
textLayerDiv = document.createElement("div");
|
|
2186
|
+
textLayerDiv.className = "textLayer";
|
|
2187
|
+
textLayerDiv.style.width = `${displayWidth}px`;
|
|
2188
|
+
textLayerDiv.style.height = `${displayHeight}px`;
|
|
2189
|
+
textLayerDiv.style.position = "absolute";
|
|
2190
|
+
textLayerDiv.style.top = "0";
|
|
2191
|
+
textLayerDiv.style.left = "0";
|
|
2192
|
+
textLayerDiv.style.lineHeight = "1";
|
|
2193
|
+
pageCard.appendChild(textLayerDiv);
|
|
2194
|
+
if (pdfjsLib__namespace.TextLayer) {
|
|
2195
|
+
const textLayer = new pdfjsLib__namespace.TextLayer({
|
|
2196
|
+
textContentSource: page.streamTextContent(),
|
|
2197
|
+
container: textLayerDiv,
|
|
2198
|
+
viewport
|
|
2199
|
+
});
|
|
2200
|
+
await textLayer.render();
|
|
2201
|
+
}
|
|
2202
|
+
} catch (err) {
|
|
2203
|
+
console.debug("[PdfPlugin] TextLayer notice:", err);
|
|
2204
|
+
}
|
|
1679
2205
|
};
|
|
1680
2206
|
renderPage(1);
|
|
1681
2207
|
let resizeTimer = null;
|
|
@@ -1685,11 +2211,48 @@ var PdfPlugin = class {
|
|
|
1685
2211
|
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1686
2212
|
renderPage(currentPage);
|
|
1687
2213
|
}
|
|
1688
|
-
},
|
|
2214
|
+
}, 120);
|
|
1689
2215
|
});
|
|
1690
2216
|
resizeObserver.observe(container);
|
|
2217
|
+
const onWheel = (e) => {
|
|
2218
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2219
|
+
e.preventDefault();
|
|
2220
|
+
const delta = e.deltaY > 0 ? -0.15 : 0.15;
|
|
2221
|
+
zoomScale = Math.max(0.25, Math.min(4, Math.round((zoomScale + delta) * 100) / 100));
|
|
2222
|
+
renderPage(currentPage);
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
2226
|
+
const onKeyDown = (e) => {
|
|
2227
|
+
const tag = e.target?.tagName?.toLowerCase();
|
|
2228
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
2229
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
2230
|
+
if (currentPage < totalPages) {
|
|
2231
|
+
e.preventDefault();
|
|
2232
|
+
container.scrollTop = 0;
|
|
2233
|
+
renderPage(currentPage + 1);
|
|
2234
|
+
}
|
|
2235
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
2236
|
+
if (currentPage > 1) {
|
|
2237
|
+
e.preventDefault();
|
|
2238
|
+
container.scrollTop = 0;
|
|
2239
|
+
renderPage(currentPage - 1);
|
|
2240
|
+
}
|
|
2241
|
+
} else if (e.key === "Home") {
|
|
2242
|
+
e.preventDefault();
|
|
2243
|
+
container.scrollTop = 0;
|
|
2244
|
+
renderPage(1);
|
|
2245
|
+
} else if (e.key === "End") {
|
|
2246
|
+
e.preventDefault();
|
|
2247
|
+
container.scrollTop = 0;
|
|
2248
|
+
renderPage(totalPages);
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1691
2252
|
const cleanup = () => {
|
|
1692
2253
|
resizeObserver.disconnect();
|
|
2254
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2255
|
+
container.removeEventListener("wheel", onWheel);
|
|
1693
2256
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1694
2257
|
if (currentRenderTask) {
|
|
1695
2258
|
try {
|
|
@@ -1708,22 +2271,26 @@ var PdfPlugin = class {
|
|
|
1708
2271
|
const instance = {
|
|
1709
2272
|
destroy: cleanup,
|
|
1710
2273
|
zoomIn: () => {
|
|
1711
|
-
zoomScale = Math.min(
|
|
2274
|
+
zoomScale = Math.min(4, Math.round((zoomScale + 0.2) * 10) / 10);
|
|
1712
2275
|
renderPage(currentPage);
|
|
1713
2276
|
},
|
|
1714
2277
|
zoomOut: () => {
|
|
1715
|
-
zoomScale = Math.max(0.
|
|
2278
|
+
zoomScale = Math.max(0.25, Math.round((zoomScale - 0.2) * 10) / 10);
|
|
1716
2279
|
renderPage(currentPage);
|
|
1717
2280
|
},
|
|
1718
2281
|
getZoom: () => zoomScale,
|
|
1719
2282
|
setZoom: (level) => {
|
|
1720
|
-
zoomScale = Math.max(0.
|
|
2283
|
+
zoomScale = Math.max(0.25, Math.min(4, level));
|
|
1721
2284
|
renderPage(currentPage);
|
|
1722
2285
|
},
|
|
1723
2286
|
fitToPage: () => {
|
|
1724
|
-
fitMode =
|
|
2287
|
+
fitMode = "page";
|
|
2288
|
+
zoomScale = 1;
|
|
2289
|
+
renderPage(currentPage);
|
|
2290
|
+
},
|
|
2291
|
+
fitToWidth: () => {
|
|
2292
|
+
fitMode = "width";
|
|
1725
2293
|
zoomScale = 1;
|
|
1726
|
-
rotation = 0;
|
|
1727
2294
|
renderPage(currentPage);
|
|
1728
2295
|
},
|
|
1729
2296
|
rotateCW: () => {
|
|
@@ -1741,6 +2308,9 @@ var PdfPlugin = class {
|
|
|
1741
2308
|
container.scrollTop = 0;
|
|
1742
2309
|
renderPage(page);
|
|
1743
2310
|
},
|
|
2311
|
+
toggleThumbnails: () => {
|
|
2312
|
+
ctx?.toggleThumbnails?.();
|
|
2313
|
+
},
|
|
1744
2314
|
download: () => {
|
|
1745
2315
|
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1746
2316
|
const url = URL.createObjectURL(blob);
|
|
@@ -1774,7 +2344,7 @@ var PdfPlugin = class {
|
|
|
1774
2344
|
},
|
|
1775
2345
|
getThumbnails: async () => {
|
|
1776
2346
|
const thumbnails = [];
|
|
1777
|
-
const count =
|
|
2347
|
+
const count = totalPages;
|
|
1778
2348
|
for (let i = 1; i <= count; i++) {
|
|
1779
2349
|
thumbnails.push({
|
|
1780
2350
|
index: i,
|
|
@@ -1782,9 +2352,10 @@ var PdfPlugin = class {
|
|
|
1782
2352
|
render: async (thumbCanvas) => {
|
|
1783
2353
|
try {
|
|
1784
2354
|
const p = await pdfDoc.getPage(i);
|
|
1785
|
-
const baseVp = p.getViewport({ scale: 1 });
|
|
1786
|
-
const
|
|
1787
|
-
const
|
|
2355
|
+
const baseVp = p.getViewport({ scale: 1, rotation });
|
|
2356
|
+
const targetW = thumbCanvas.width || 130;
|
|
2357
|
+
const thumbScale = targetW / baseVp.width;
|
|
2358
|
+
const thumbVp = p.getViewport({ scale: thumbScale, rotation });
|
|
1788
2359
|
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1789
2360
|
const tCtx = thumbCanvas.getContext("2d");
|
|
1790
2361
|
if (tCtx) {
|
|
@@ -2128,28 +2699,26 @@ var DocxPlugin = class {
|
|
|
2128
2699
|
getToolbarActions(instance) {
|
|
2129
2700
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2130
2701
|
const actions = [];
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
if (
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
instance.goToPage?.(page);
|
|
2149
|
-
}
|
|
2702
|
+
actions.push({
|
|
2703
|
+
id: "page-nav",
|
|
2704
|
+
icon: "",
|
|
2705
|
+
label: "Page Navigation",
|
|
2706
|
+
type: "page-nav",
|
|
2707
|
+
group: "navigation",
|
|
2708
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2709
|
+
max: totalPages,
|
|
2710
|
+
execute: (action, page) => {
|
|
2711
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2712
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2713
|
+
if (action === "prev") {
|
|
2714
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2715
|
+
} else if (action === "next") {
|
|
2716
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2717
|
+
} else if (typeof page === "number") {
|
|
2718
|
+
instance.goToPage?.(page);
|
|
2150
2719
|
}
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2720
|
+
}
|
|
2721
|
+
});
|
|
2153
2722
|
actions.push(
|
|
2154
2723
|
{
|
|
2155
2724
|
id: "zoom-out",
|
|
@@ -2215,11 +2784,17 @@ var DocxPlugin = class {
|
|
|
2215
2784
|
wrapper.className = "fp-docx-wrapper";
|
|
2216
2785
|
wrapper.style.transformOrigin = "top center";
|
|
2217
2786
|
wrapper.style.transition = "transform 0.2s ease";
|
|
2218
|
-
wrapper.style.padding = "
|
|
2219
|
-
wrapper.style.maxWidth = "
|
|
2787
|
+
wrapper.style.padding = "0";
|
|
2788
|
+
wrapper.style.maxWidth = "none";
|
|
2789
|
+
wrapper.style.width = "816px";
|
|
2220
2790
|
wrapper.style.margin = "0 auto";
|
|
2791
|
+
wrapper.style.display = "flex";
|
|
2792
|
+
wrapper.style.flexDirection = "column";
|
|
2793
|
+
wrapper.style.alignItems = "center";
|
|
2221
2794
|
wrapper.style.boxSizing = "border-box";
|
|
2222
|
-
ctx.container.style.
|
|
2795
|
+
ctx.container.style.overflowX = "hidden";
|
|
2796
|
+
ctx.container.style.overflowY = "auto";
|
|
2797
|
+
ctx.container.style.padding = "16px 8px";
|
|
2223
2798
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
2224
2799
|
ctx.container.appendChild(wrapper);
|
|
2225
2800
|
const styleOverride = document.createElement("style");
|
|
@@ -2393,39 +2968,13 @@ var DocxPlugin = class {
|
|
|
2393
2968
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2394
2969
|
const totalPages = Math.max(1, pageElements.length);
|
|
2395
2970
|
let currentPage = 1;
|
|
2396
|
-
let indicator = null;
|
|
2397
|
-
if (totalPages > 1) {
|
|
2398
|
-
indicator = document.createElement("div");
|
|
2399
|
-
indicator.className = "fp-docx-page-indicator";
|
|
2400
|
-
indicator.style.position = "sticky";
|
|
2401
|
-
indicator.style.bottom = "16px";
|
|
2402
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2403
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
2404
|
-
indicator.style.color = "#f8fafc";
|
|
2405
|
-
indicator.style.fontSize = "12px";
|
|
2406
|
-
indicator.style.fontWeight = "600";
|
|
2407
|
-
indicator.style.padding = "5px 14px";
|
|
2408
|
-
indicator.style.borderRadius = "20px";
|
|
2409
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2410
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2411
|
-
indicator.style.zIndex = "10";
|
|
2412
|
-
indicator.style.userSelect = "none";
|
|
2413
|
-
indicator.style.pointerEvents = "none";
|
|
2414
|
-
indicator.style.textAlign = "center";
|
|
2415
|
-
indicator.style.width = "fit-content";
|
|
2416
|
-
indicator.style.margin = "16px auto 0";
|
|
2417
|
-
ctx.container.appendChild(indicator);
|
|
2418
|
-
}
|
|
2419
2971
|
const showPage = (pageNum) => {
|
|
2420
2972
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2421
2973
|
if (pageElements.length > 1) {
|
|
2422
2974
|
pageElements.forEach((sec, idx) => {
|
|
2423
|
-
sec.style.display = idx + 1 === currentPage ? "
|
|
2975
|
+
sec.style.display = idx + 1 === currentPage ? "" : "none";
|
|
2424
2976
|
});
|
|
2425
2977
|
}
|
|
2426
|
-
if (indicator) {
|
|
2427
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2428
|
-
}
|
|
2429
2978
|
ctx.container.scrollTop = 0;
|
|
2430
2979
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2431
2980
|
};
|
|
@@ -2434,31 +2983,46 @@ var DocxPlugin = class {
|
|
|
2434
2983
|
}
|
|
2435
2984
|
scale = 1;
|
|
2436
2985
|
let rotation = 0;
|
|
2437
|
-
let fitMode = "
|
|
2438
|
-
|
|
2439
|
-
|
|
2986
|
+
let fitMode = "page";
|
|
2987
|
+
let isUserZoomed = false;
|
|
2988
|
+
const calculateFitScale = (_mode = fitMode) => {
|
|
2989
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2440
2990
|
const elW = activeEl.offsetWidth || 816;
|
|
2441
|
-
const
|
|
2442
|
-
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2443
|
-
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2991
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
2444
2992
|
const sW = availW / elW;
|
|
2445
|
-
|
|
2446
|
-
if (mode === "page") {
|
|
2447
|
-
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2448
|
-
}
|
|
2449
|
-
return Math.max(0.65, Math.min(1.05, sW));
|
|
2993
|
+
return Math.max(0.35, Math.min(3, sW));
|
|
2450
2994
|
};
|
|
2451
2995
|
const applyTransform = () => {
|
|
2452
2996
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2453
2997
|
wrapper.style.transformOrigin = "top center";
|
|
2998
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2999
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
3000
|
+
if (scale > 1) {
|
|
3001
|
+
wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
|
|
3002
|
+
} else {
|
|
3003
|
+
wrapper.style.marginBottom = "32px";
|
|
3004
|
+
}
|
|
2454
3005
|
};
|
|
3006
|
+
let resizeObserver = null;
|
|
3007
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
3008
|
+
resizeObserver = new ResizeObserver(() => {
|
|
3009
|
+
if (!isUserZoomed) {
|
|
3010
|
+
const newFit = calculateFitScale("page");
|
|
3011
|
+
if (Math.abs(scale - newFit) > 0.015) {
|
|
3012
|
+
scale = newFit;
|
|
3013
|
+
applyTransform();
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
});
|
|
3017
|
+
resizeObserver.observe(ctx.container);
|
|
3018
|
+
}
|
|
2455
3019
|
setTimeout(() => {
|
|
2456
|
-
|
|
2457
|
-
scale = calculateFitScale("width");
|
|
3020
|
+
scale = calculateFitScale("page");
|
|
2458
3021
|
applyTransform();
|
|
2459
|
-
},
|
|
3022
|
+
}, 40);
|
|
2460
3023
|
const cleanup = () => {
|
|
2461
|
-
|
|
3024
|
+
resizeObserver?.disconnect();
|
|
3025
|
+
resizeObserver = null;
|
|
2462
3026
|
for (const url of createdBlobUrls) {
|
|
2463
3027
|
URL.revokeObjectURL(url);
|
|
2464
3028
|
}
|
|
@@ -2475,21 +3039,24 @@ var DocxPlugin = class {
|
|
|
2475
3039
|
showPage(page);
|
|
2476
3040
|
},
|
|
2477
3041
|
zoomIn: () => {
|
|
2478
|
-
|
|
3042
|
+
isUserZoomed = true;
|
|
3043
|
+
scale = Math.min(3.5, scale + 0.15);
|
|
2479
3044
|
applyTransform();
|
|
2480
3045
|
},
|
|
2481
3046
|
zoomOut: () => {
|
|
3047
|
+
isUserZoomed = true;
|
|
2482
3048
|
scale = Math.max(0.2, scale - 0.15);
|
|
2483
3049
|
applyTransform();
|
|
2484
3050
|
},
|
|
2485
3051
|
getZoom: () => scale,
|
|
2486
3052
|
setZoom: (level) => {
|
|
3053
|
+
isUserZoomed = true;
|
|
2487
3054
|
scale = level;
|
|
2488
3055
|
applyTransform();
|
|
2489
3056
|
},
|
|
2490
3057
|
fitToPage: () => {
|
|
2491
|
-
|
|
2492
|
-
scale = calculateFitScale(
|
|
3058
|
+
isUserZoomed = false;
|
|
3059
|
+
scale = calculateFitScale("page");
|
|
2493
3060
|
rotation = 0;
|
|
2494
3061
|
applyTransform();
|
|
2495
3062
|
},
|
|
@@ -2879,7 +3446,7 @@ var ExcelPlugin = class {
|
|
|
2879
3446
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
2880
3447
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
2881
3448
|
];
|
|
2882
|
-
weight =
|
|
3449
|
+
weight = 85;
|
|
2883
3450
|
supports(file) {
|
|
2884
3451
|
const ext = file.metadata.extension?.toLowerCase();
|
|
2885
3452
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
@@ -2891,6 +3458,14 @@ var ExcelPlugin = class {
|
|
|
2891
3458
|
getToolbarActions(instance) {
|
|
2892
3459
|
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2893
3460
|
const actions = [];
|
|
3461
|
+
actions.push({
|
|
3462
|
+
id: "thumbnails",
|
|
3463
|
+
icon: "thumbnails",
|
|
3464
|
+
label: "Sheet Thumbnails",
|
|
3465
|
+
type: "button",
|
|
3466
|
+
group: "navigation",
|
|
3467
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3468
|
+
});
|
|
2894
3469
|
if (totalSheets > 1) {
|
|
2895
3470
|
actions.push({
|
|
2896
3471
|
id: "page-nav",
|
|
@@ -2973,6 +3548,16 @@ var ExcelPlugin = class {
|
|
|
2973
3548
|
execute: () => {
|
|
2974
3549
|
instance.print?.();
|
|
2975
3550
|
}
|
|
3551
|
+
},
|
|
3552
|
+
{
|
|
3553
|
+
id: "open-window",
|
|
3554
|
+
icon: "open-window",
|
|
3555
|
+
label: "Open in Separate Full Window",
|
|
3556
|
+
type: "button",
|
|
3557
|
+
group: "actions",
|
|
3558
|
+
execute: () => {
|
|
3559
|
+
instance.openInSeparateWindow?.();
|
|
3560
|
+
}
|
|
2976
3561
|
}
|
|
2977
3562
|
);
|
|
2978
3563
|
return actions;
|
|
@@ -3138,6 +3723,63 @@ var ExcelPlugin = class {
|
|
|
3138
3723
|
},
|
|
3139
3724
|
getPageCount: () => sheetNames.length,
|
|
3140
3725
|
getCurrentPage: () => currentSheetIndex,
|
|
3726
|
+
getThumbnails: () => {
|
|
3727
|
+
return sheetNames.map((name, idx) => ({
|
|
3728
|
+
index: idx,
|
|
3729
|
+
label: name,
|
|
3730
|
+
render: async (canvas) => {
|
|
3731
|
+
canvas.width = 140;
|
|
3732
|
+
canvas.height = 100;
|
|
3733
|
+
const c = canvas.getContext("2d");
|
|
3734
|
+
if (!c) return;
|
|
3735
|
+
c.fillStyle = "#ffffff";
|
|
3736
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3737
|
+
c.fillStyle = "#107c41";
|
|
3738
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3739
|
+
c.fillStyle = "#ffffff";
|
|
3740
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
3741
|
+
c.fillText(`\u{1F4CA} ${name.slice(0, 16)}`, 6, 11);
|
|
3742
|
+
const startY = 17;
|
|
3743
|
+
const rowH = 13;
|
|
3744
|
+
const colW = 30;
|
|
3745
|
+
const colHeaders = ["A", "B", "C", "D"];
|
|
3746
|
+
c.fillStyle = "#f1f5f9";
|
|
3747
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3748
|
+
c.strokeStyle = "#cbd5e1";
|
|
3749
|
+
c.lineWidth = 0.8;
|
|
3750
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3751
|
+
c.fillStyle = "#64748b";
|
|
3752
|
+
c.font = "bold 7px sans-serif";
|
|
3753
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3754
|
+
c.fillText(colHeaders[ci], 14 + ci * colW, startY + 9);
|
|
3755
|
+
}
|
|
3756
|
+
const ws = wb?.Sheets[name];
|
|
3757
|
+
for (let ri = 1; ri <= 5; ri++) {
|
|
3758
|
+
const y = startY + ri * rowH;
|
|
3759
|
+
if (y > canvas.height - 2) break;
|
|
3760
|
+
c.fillStyle = "#f8fafc";
|
|
3761
|
+
c.fillRect(0, y, 12, rowH);
|
|
3762
|
+
c.fillStyle = "#94a3b8";
|
|
3763
|
+
c.font = "6px sans-serif";
|
|
3764
|
+
c.fillText(String(ri), 3, y + 9);
|
|
3765
|
+
c.strokeStyle = "#e2e8f0";
|
|
3766
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3767
|
+
c.fillStyle = "#334155";
|
|
3768
|
+
c.font = "6px sans-serif";
|
|
3769
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3770
|
+
const cellRef = `${colHeaders[ci]}${ri}`;
|
|
3771
|
+
const cellVal = ws?.[cellRef]?.w || ws?.[cellRef]?.v;
|
|
3772
|
+
if (cellVal !== void 0) {
|
|
3773
|
+
c.fillText(String(cellVal).slice(0, 6), 14 + ci * colW, y + 9);
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
c.strokeStyle = "#cbd5e1";
|
|
3778
|
+
c.lineWidth = 1;
|
|
3779
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
3780
|
+
}
|
|
3781
|
+
}));
|
|
3782
|
+
},
|
|
3141
3783
|
download: () => {
|
|
3142
3784
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
3143
3785
|
const url = URL.createObjectURL(blob);
|
|
@@ -3170,7 +3812,39 @@ var CsvPlugin = class {
|
|
|
3170
3812
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3171
3813
|
}
|
|
3172
3814
|
getToolbarActions(instance) {
|
|
3173
|
-
|
|
3815
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3816
|
+
const actions = [];
|
|
3817
|
+
actions.push({
|
|
3818
|
+
id: "thumbnails",
|
|
3819
|
+
icon: "thumbnails",
|
|
3820
|
+
label: "Page Thumbnails",
|
|
3821
|
+
type: "button",
|
|
3822
|
+
group: "navigation",
|
|
3823
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3824
|
+
});
|
|
3825
|
+
if (totalPages > 1) {
|
|
3826
|
+
actions.push({
|
|
3827
|
+
id: "page-nav",
|
|
3828
|
+
icon: "",
|
|
3829
|
+
label: "Page Navigation",
|
|
3830
|
+
type: "page-nav",
|
|
3831
|
+
group: "navigation",
|
|
3832
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3833
|
+
max: totalPages,
|
|
3834
|
+
execute: (action, page) => {
|
|
3835
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3836
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3837
|
+
if (action === "prev") {
|
|
3838
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3839
|
+
} else if (action === "next") {
|
|
3840
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3841
|
+
} else if (typeof page === "number") {
|
|
3842
|
+
instance.goToPage?.(page);
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
});
|
|
3846
|
+
}
|
|
3847
|
+
actions.push(
|
|
3174
3848
|
{
|
|
3175
3849
|
id: "zoom-out",
|
|
3176
3850
|
icon: "zoom-out",
|
|
@@ -3191,6 +3865,16 @@ var CsvPlugin = class {
|
|
|
3191
3865
|
instance.zoomIn?.();
|
|
3192
3866
|
}
|
|
3193
3867
|
},
|
|
3868
|
+
{
|
|
3869
|
+
id: "fit-page",
|
|
3870
|
+
icon: "fit-page",
|
|
3871
|
+
label: "Fit to View",
|
|
3872
|
+
type: "button",
|
|
3873
|
+
group: "zoom",
|
|
3874
|
+
execute: () => {
|
|
3875
|
+
instance.fitToPage?.();
|
|
3876
|
+
}
|
|
3877
|
+
},
|
|
3194
3878
|
{
|
|
3195
3879
|
id: "download",
|
|
3196
3880
|
icon: "download",
|
|
@@ -3210,8 +3894,19 @@ var CsvPlugin = class {
|
|
|
3210
3894
|
execute: () => {
|
|
3211
3895
|
instance.print?.();
|
|
3212
3896
|
}
|
|
3897
|
+
},
|
|
3898
|
+
{
|
|
3899
|
+
id: "open-window",
|
|
3900
|
+
icon: "open-window",
|
|
3901
|
+
label: "Open in Separate Full Window",
|
|
3902
|
+
type: "button",
|
|
3903
|
+
group: "actions",
|
|
3904
|
+
execute: () => {
|
|
3905
|
+
instance.openInSeparateWindow?.();
|
|
3906
|
+
}
|
|
3213
3907
|
}
|
|
3214
|
-
|
|
3908
|
+
);
|
|
3909
|
+
return actions;
|
|
3215
3910
|
}
|
|
3216
3911
|
async render(ctx) {
|
|
3217
3912
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -3223,33 +3918,62 @@ var CsvPlugin = class {
|
|
|
3223
3918
|
container.style.padding = "16px";
|
|
3224
3919
|
container.style.boxSizing = "border-box";
|
|
3225
3920
|
container.style.transformOrigin = "top left";
|
|
3921
|
+
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
3922
|
+
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
3923
|
+
const headerLine = allLines[0] || "";
|
|
3924
|
+
const headerCells = headerLine.split(delimiter);
|
|
3925
|
+
const dataLines = allLines.slice(1);
|
|
3926
|
+
const ROWS_PER_PAGE = 100;
|
|
3927
|
+
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
3928
|
+
let currentPage = 1;
|
|
3226
3929
|
const table = document.createElement("table");
|
|
3227
3930
|
table.style.borderCollapse = "collapse";
|
|
3228
3931
|
table.style.width = "100%";
|
|
3229
|
-
table.style.fontFamily = "monospace
|
|
3932
|
+
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3230
3933
|
table.style.fontSize = "13px";
|
|
3231
|
-
const
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
td.style.fontWeight = "bold";
|
|
3245
|
-
}
|
|
3246
|
-
tr.appendChild(td);
|
|
3934
|
+
const renderPage = (pageNum) => {
|
|
3935
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3936
|
+
table.innerHTML = "";
|
|
3937
|
+
const headerTr = document.createElement("tr");
|
|
3938
|
+
headerCells.forEach((cell) => {
|
|
3939
|
+
const th = document.createElement("th");
|
|
3940
|
+
th.textContent = cell.trim();
|
|
3941
|
+
th.style.border = "1px solid #d0d7de";
|
|
3942
|
+
th.style.padding = "8px 12px";
|
|
3943
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
3944
|
+
th.style.fontWeight = "600";
|
|
3945
|
+
th.style.whiteSpace = "nowrap";
|
|
3946
|
+
headerTr.appendChild(th);
|
|
3247
3947
|
});
|
|
3248
|
-
table.appendChild(
|
|
3249
|
-
|
|
3948
|
+
table.appendChild(headerTr);
|
|
3949
|
+
const start = (currentPage - 1) * ROWS_PER_PAGE;
|
|
3950
|
+
const end = Math.min(dataLines.length, start + ROWS_PER_PAGE);
|
|
3951
|
+
const pageRows = dataLines.slice(start, end);
|
|
3952
|
+
pageRows.forEach((row, idx) => {
|
|
3953
|
+
const tr = document.createElement("tr");
|
|
3954
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
3955
|
+
const cells = row.split(delimiter);
|
|
3956
|
+
cells.forEach((cell) => {
|
|
3957
|
+
const td = document.createElement("td");
|
|
3958
|
+
td.textContent = cell.trim();
|
|
3959
|
+
td.style.border = "1px solid #d0d7de";
|
|
3960
|
+
td.style.padding = "6px 12px";
|
|
3961
|
+
td.style.whiteSpace = "nowrap";
|
|
3962
|
+
tr.appendChild(td);
|
|
3963
|
+
});
|
|
3964
|
+
table.appendChild(tr);
|
|
3965
|
+
});
|
|
3966
|
+
container.scrollTop = 0;
|
|
3967
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3968
|
+
};
|
|
3969
|
+
renderPage(1);
|
|
3250
3970
|
container.appendChild(table);
|
|
3251
3971
|
ctx.container.appendChild(container);
|
|
3252
3972
|
let scale = 1;
|
|
3973
|
+
const applyScale = () => {
|
|
3974
|
+
container.style.transform = `scale(${scale})`;
|
|
3975
|
+
container.style.transformOrigin = "top left";
|
|
3976
|
+
};
|
|
3253
3977
|
const cleanup = () => {
|
|
3254
3978
|
container.remove();
|
|
3255
3979
|
ctx.container.innerHTML = "";
|
|
@@ -3257,22 +3981,86 @@ var CsvPlugin = class {
|
|
|
3257
3981
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3258
3982
|
return {
|
|
3259
3983
|
destroy: cleanup,
|
|
3984
|
+
getPageCount: () => totalPages,
|
|
3985
|
+
getCurrentPage: () => currentPage,
|
|
3986
|
+
goToPage: (page) => renderPage(page),
|
|
3987
|
+
getThumbnails: () => {
|
|
3988
|
+
const thumbnails = [];
|
|
3989
|
+
for (let i = 0; i < totalPages; i++) {
|
|
3990
|
+
const pageIdx = i;
|
|
3991
|
+
const startRow = pageIdx * ROWS_PER_PAGE + 1;
|
|
3992
|
+
const endRow = Math.min(dataLines.length, (pageIdx + 1) * ROWS_PER_PAGE);
|
|
3993
|
+
const label = totalPages === 1 ? "Table" : `Page ${pageIdx + 1} (${startRow}-${endRow})`;
|
|
3994
|
+
thumbnails.push({
|
|
3995
|
+
index: pageIdx,
|
|
3996
|
+
label,
|
|
3997
|
+
render: async (canvas) => {
|
|
3998
|
+
canvas.width = 140;
|
|
3999
|
+
canvas.height = 100;
|
|
4000
|
+
const c = canvas.getContext("2d");
|
|
4001
|
+
if (!c) return;
|
|
4002
|
+
c.fillStyle = "#ffffff";
|
|
4003
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4004
|
+
c.fillStyle = "#2563eb";
|
|
4005
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
4006
|
+
c.fillStyle = "#ffffff";
|
|
4007
|
+
c.font = "bold 8px sans-serif";
|
|
4008
|
+
c.fillText(`\u{1F4C8} ${label.slice(0, 18)}`, 6, 11);
|
|
4009
|
+
const startY = 17;
|
|
4010
|
+
const rowH = 13;
|
|
4011
|
+
const colW = 28;
|
|
4012
|
+
const cols = Math.min(4, headerCells.length || 4);
|
|
4013
|
+
c.fillStyle = "#f1f5f9";
|
|
4014
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
4015
|
+
c.strokeStyle = "#cbd5e1";
|
|
4016
|
+
c.lineWidth = 0.8;
|
|
4017
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
4018
|
+
c.fillStyle = "#64748b";
|
|
4019
|
+
c.font = "bold 7px sans-serif";
|
|
4020
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4021
|
+
const hName = headerCells[ci] || `Col ${ci + 1}`;
|
|
4022
|
+
c.fillText(hName.slice(0, 5), 8 + ci * colW, startY + 9);
|
|
4023
|
+
}
|
|
4024
|
+
const rowsToPreview = dataLines.slice(pageIdx * ROWS_PER_PAGE, pageIdx * ROWS_PER_PAGE + 5);
|
|
4025
|
+
for (let ri = 0; ri < rowsToPreview.length; ri++) {
|
|
4026
|
+
const y = startY + (ri + 1) * rowH;
|
|
4027
|
+
if (y > canvas.height - 2) break;
|
|
4028
|
+
c.strokeStyle = "#e2e8f0";
|
|
4029
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
4030
|
+
const cVals = rowsToPreview[ri].split(delimiter);
|
|
4031
|
+
c.fillStyle = "#334155";
|
|
4032
|
+
c.font = "6px sans-serif";
|
|
4033
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4034
|
+
const val = cVals[ci] || "";
|
|
4035
|
+
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
c.strokeStyle = "#cbd5e1";
|
|
4039
|
+
c.lineWidth = 1;
|
|
4040
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4041
|
+
}
|
|
4042
|
+
});
|
|
4043
|
+
}
|
|
4044
|
+
return thumbnails;
|
|
4045
|
+
},
|
|
3260
4046
|
zoomIn: () => {
|
|
3261
4047
|
scale += 0.1;
|
|
3262
|
-
|
|
4048
|
+
applyScale();
|
|
3263
4049
|
},
|
|
3264
4050
|
zoomOut: () => {
|
|
3265
4051
|
scale = Math.max(0.2, scale - 0.1);
|
|
3266
|
-
|
|
4052
|
+
applyScale();
|
|
3267
4053
|
},
|
|
3268
4054
|
getZoom: () => scale,
|
|
3269
4055
|
setZoom: (level) => {
|
|
3270
4056
|
scale = level;
|
|
3271
|
-
|
|
4057
|
+
applyScale();
|
|
3272
4058
|
},
|
|
3273
4059
|
fitToPage: () => {
|
|
3274
|
-
|
|
3275
|
-
|
|
4060
|
+
const availW = Math.max(280, (ctx.container.clientWidth || window.innerWidth) - 48);
|
|
4061
|
+
const tW = table.offsetWidth || 600;
|
|
4062
|
+
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4063
|
+
applyScale();
|
|
3276
4064
|
},
|
|
3277
4065
|
download: () => {
|
|
3278
4066
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
@@ -3336,28 +4124,34 @@ var CodePlugin = class {
|
|
|
3336
4124
|
getToolbarActions(instance) {
|
|
3337
4125
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3338
4126
|
const actions = [];
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
4127
|
+
actions.push({
|
|
4128
|
+
id: "thumbnails",
|
|
4129
|
+
icon: "thumbnails",
|
|
4130
|
+
label: "Page Thumbnails",
|
|
4131
|
+
type: "button",
|
|
4132
|
+
group: "navigation",
|
|
4133
|
+
execute: () => instance.toggleThumbnails?.()
|
|
4134
|
+
});
|
|
4135
|
+
actions.push({
|
|
4136
|
+
id: "page-nav",
|
|
4137
|
+
icon: "",
|
|
4138
|
+
label: "Page Navigation",
|
|
4139
|
+
type: "page-nav",
|
|
4140
|
+
group: "navigation",
|
|
4141
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4142
|
+
max: totalPages,
|
|
4143
|
+
execute: (action, page) => {
|
|
4144
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4145
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4146
|
+
if (action === "prev") {
|
|
4147
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4148
|
+
} else if (action === "next") {
|
|
4149
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4150
|
+
} else if (typeof page === "number") {
|
|
4151
|
+
instance.goToPage?.(page);
|
|
3358
4152
|
}
|
|
3359
|
-
}
|
|
3360
|
-
}
|
|
4153
|
+
}
|
|
4154
|
+
});
|
|
3361
4155
|
actions.push(
|
|
3362
4156
|
{
|
|
3363
4157
|
id: "zoom-out",
|
|
@@ -3501,16 +4295,19 @@ var CodePlugin = class {
|
|
|
3501
4295
|
let fontSize = 13;
|
|
3502
4296
|
let rotation = 0;
|
|
3503
4297
|
let zoomLevel = 1;
|
|
4298
|
+
let isUserZoomed = false;
|
|
3504
4299
|
const pre = document.createElement("pre");
|
|
3505
4300
|
const code = document.createElement("code");
|
|
3506
4301
|
if (isTxt) {
|
|
4302
|
+
container.style.overflowX = "hidden";
|
|
4303
|
+
container.style.overflowY = "auto";
|
|
3507
4304
|
container.style.backgroundColor = "#f1f5f9";
|
|
3508
|
-
container.style.padding = "
|
|
4305
|
+
container.style.padding = "16px 8px";
|
|
3509
4306
|
container.style.boxSizing = "border-box";
|
|
3510
4307
|
container.style.display = "flex";
|
|
3511
4308
|
container.style.flexDirection = "column";
|
|
3512
4309
|
container.style.alignItems = "center";
|
|
3513
|
-
pre.style.margin = "0";
|
|
4310
|
+
pre.style.margin = "0 auto";
|
|
3514
4311
|
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3515
4312
|
pre.style.fontSize = "13px";
|
|
3516
4313
|
pre.style.color = "#1e293b";
|
|
@@ -3522,10 +4319,12 @@ var CodePlugin = class {
|
|
|
3522
4319
|
pre.style.minHeight = "1056px";
|
|
3523
4320
|
pre.style.padding = "72px 56px";
|
|
3524
4321
|
pre.style.boxSizing = "border-box";
|
|
3525
|
-
pre.style.boxShadow = "0 4px
|
|
4322
|
+
pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
3526
4323
|
pre.style.borderRadius = "4px";
|
|
3527
4324
|
pre.style.transformOrigin = "top center";
|
|
4325
|
+
pre.style.transition = "transform 0.15s ease";
|
|
3528
4326
|
} else {
|
|
4327
|
+
container.style.overflow = "auto";
|
|
3529
4328
|
container.style.backgroundColor = "#1e1e1e";
|
|
3530
4329
|
container.style.color = "#d4d4d4";
|
|
3531
4330
|
container.style.padding = "16px";
|
|
@@ -3557,42 +4356,9 @@ var CodePlugin = class {
|
|
|
3557
4356
|
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3558
4357
|
pre.appendChild(code);
|
|
3559
4358
|
container.appendChild(pre);
|
|
3560
|
-
let indicator = null;
|
|
3561
|
-
if (totalPages > 1) {
|
|
3562
|
-
indicator = document.createElement("div");
|
|
3563
|
-
indicator.className = "fp-code-page-indicator";
|
|
3564
|
-
indicator.style.position = "sticky";
|
|
3565
|
-
indicator.style.bottom = "16px";
|
|
3566
|
-
if (isTxt) {
|
|
3567
|
-
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3568
|
-
indicator.style.color = "#334155";
|
|
3569
|
-
indicator.style.border = "1px solid #e2e8f0";
|
|
3570
|
-
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3571
|
-
} else {
|
|
3572
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3573
|
-
indicator.style.color = "#f8fafc";
|
|
3574
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3575
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3576
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
3577
|
-
}
|
|
3578
|
-
indicator.style.fontSize = "12px";
|
|
3579
|
-
indicator.style.fontWeight = "600";
|
|
3580
|
-
indicator.style.padding = "5px 14px";
|
|
3581
|
-
indicator.style.borderRadius = "20px";
|
|
3582
|
-
indicator.style.zIndex = "10";
|
|
3583
|
-
indicator.style.userSelect = "none";
|
|
3584
|
-
indicator.style.pointerEvents = "none";
|
|
3585
|
-
indicator.style.textAlign = "center";
|
|
3586
|
-
indicator.style.width = "fit-content";
|
|
3587
|
-
indicator.style.margin = "16px auto 0";
|
|
3588
|
-
container.appendChild(indicator);
|
|
3589
|
-
}
|
|
3590
4359
|
const showPage = (pageNum) => {
|
|
3591
4360
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3592
4361
|
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3593
|
-
if (indicator) {
|
|
3594
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3595
|
-
}
|
|
3596
4362
|
container.scrollTop = 0;
|
|
3597
4363
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3598
4364
|
};
|
|
@@ -3600,36 +4366,90 @@ var CodePlugin = class {
|
|
|
3600
4366
|
showPage(1);
|
|
3601
4367
|
}
|
|
3602
4368
|
ctx.container.appendChild(container);
|
|
3603
|
-
const
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
ctx.container.innerHTML = "";
|
|
4369
|
+
const calculateTxtFit = () => {
|
|
4370
|
+
const availW = Math.max(280, container.clientWidth - 32);
|
|
4371
|
+
return Math.max(0.4, Math.min(3, availW / 816));
|
|
3607
4372
|
};
|
|
3608
|
-
ctx.signal.addEventListener("abort", cleanup);
|
|
3609
4373
|
const updateTransform = () => {
|
|
3610
4374
|
if (isTxt) {
|
|
3611
4375
|
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
4376
|
+
const scaledH = 1056 * zoomLevel;
|
|
4377
|
+
const extraH = Math.max(0, scaledH - 1056);
|
|
4378
|
+
pre.style.marginBottom = `${extraH + 32}px`;
|
|
3612
4379
|
} else {
|
|
3613
4380
|
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3614
4381
|
pre.style.fontSize = `${fontSize}px`;
|
|
3615
4382
|
}
|
|
3616
4383
|
};
|
|
4384
|
+
let resizeObserver = null;
|
|
4385
|
+
if (isTxt) {
|
|
4386
|
+
setTimeout(() => {
|
|
4387
|
+
zoomLevel = calculateTxtFit();
|
|
4388
|
+
updateTransform();
|
|
4389
|
+
}, 60);
|
|
4390
|
+
resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
4391
|
+
if (!isUserZoomed) {
|
|
4392
|
+
zoomLevel = calculateTxtFit();
|
|
4393
|
+
updateTransform();
|
|
4394
|
+
}
|
|
4395
|
+
}) : null;
|
|
4396
|
+
resizeObserver?.observe(container);
|
|
4397
|
+
}
|
|
4398
|
+
const cleanup = () => {
|
|
4399
|
+
resizeObserver?.disconnect();
|
|
4400
|
+
container.remove();
|
|
4401
|
+
ctx.container.innerHTML = "";
|
|
4402
|
+
};
|
|
4403
|
+
ctx.signal.addEventListener("abort", cleanup);
|
|
3617
4404
|
return {
|
|
3618
4405
|
destroy: cleanup,
|
|
3619
4406
|
getPageCount: () => totalPages,
|
|
3620
4407
|
getCurrentPage: () => currentPage,
|
|
3621
4408
|
goToPage: (page) => showPage(page),
|
|
4409
|
+
getThumbnails: () => {
|
|
4410
|
+
return rawPages.map((pageText, idx) => ({
|
|
4411
|
+
index: idx,
|
|
4412
|
+
label: `Page ${idx + 1}`,
|
|
4413
|
+
render: async (canvas) => {
|
|
4414
|
+
canvas.width = 140;
|
|
4415
|
+
canvas.height = 180;
|
|
4416
|
+
const c = canvas.getContext("2d");
|
|
4417
|
+
if (!c) return;
|
|
4418
|
+
c.fillStyle = "#ffffff";
|
|
4419
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4420
|
+
c.strokeStyle = "#cbd5e1";
|
|
4421
|
+
c.lineWidth = 1;
|
|
4422
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4423
|
+
c.fillStyle = "#64748b";
|
|
4424
|
+
const lines = (pageText || "").split("\n").slice(0, 24);
|
|
4425
|
+
const lineH = 6;
|
|
4426
|
+
const startY = 14;
|
|
4427
|
+
const startX = 12;
|
|
4428
|
+
const maxW = canvas.width - 24;
|
|
4429
|
+
c.font = "5px monospace";
|
|
4430
|
+
for (let li = 0; li < lines.length; li++) {
|
|
4431
|
+
const l = lines[li].trim();
|
|
4432
|
+
if (!l) continue;
|
|
4433
|
+
const y = startY + li * lineH;
|
|
4434
|
+
if (y > canvas.height - 12) break;
|
|
4435
|
+
c.fillText(l.slice(0, 30), startX, y, maxW);
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
}));
|
|
4439
|
+
},
|
|
3622
4440
|
zoomIn: () => {
|
|
4441
|
+
isUserZoomed = true;
|
|
3623
4442
|
if (isTxt) {
|
|
3624
|
-
zoomLevel = Math.min(3, zoomLevel + 0.
|
|
4443
|
+
zoomLevel = Math.min(3.5, zoomLevel + 0.15);
|
|
3625
4444
|
} else {
|
|
3626
4445
|
fontSize = Math.min(32, fontSize + 2);
|
|
3627
4446
|
}
|
|
3628
4447
|
updateTransform();
|
|
3629
4448
|
},
|
|
3630
4449
|
zoomOut: () => {
|
|
4450
|
+
isUserZoomed = true;
|
|
3631
4451
|
if (isTxt) {
|
|
3632
|
-
zoomLevel = Math.max(0.1, zoomLevel - 0.
|
|
4452
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.15);
|
|
3633
4453
|
} else {
|
|
3634
4454
|
fontSize = Math.max(8, fontSize - 2);
|
|
3635
4455
|
}
|
|
@@ -3637,6 +4457,7 @@ var CodePlugin = class {
|
|
|
3637
4457
|
},
|
|
3638
4458
|
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3639
4459
|
setZoom: (level) => {
|
|
4460
|
+
isUserZoomed = true;
|
|
3640
4461
|
if (isTxt) {
|
|
3641
4462
|
zoomLevel = level;
|
|
3642
4463
|
} else {
|
|
@@ -3645,9 +4466,10 @@ var CodePlugin = class {
|
|
|
3645
4466
|
updateTransform();
|
|
3646
4467
|
},
|
|
3647
4468
|
fitToPage: () => {
|
|
4469
|
+
isUserZoomed = false;
|
|
3648
4470
|
fontSize = 13;
|
|
3649
4471
|
rotation = 0;
|
|
3650
|
-
zoomLevel = isTxt ?
|
|
4472
|
+
zoomLevel = isTxt ? calculateTxtFit() : 1;
|
|
3651
4473
|
updateTransform();
|
|
3652
4474
|
},
|
|
3653
4475
|
rotateCW: () => {
|
|
@@ -4528,28 +5350,26 @@ var RtfPlugin = class {
|
|
|
4528
5350
|
getToolbarActions(instance) {
|
|
4529
5351
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4530
5352
|
const actions = [];
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
if (
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
instance.goToPage?.(page);
|
|
4549
|
-
}
|
|
5353
|
+
actions.push({
|
|
5354
|
+
id: "page-nav",
|
|
5355
|
+
icon: "",
|
|
5356
|
+
label: "Page Navigation",
|
|
5357
|
+
type: "page-nav",
|
|
5358
|
+
group: "navigation",
|
|
5359
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5360
|
+
max: totalPages,
|
|
5361
|
+
execute: (action, page) => {
|
|
5362
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5363
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5364
|
+
if (action === "prev") {
|
|
5365
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5366
|
+
} else if (action === "next") {
|
|
5367
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5368
|
+
} else if (typeof page === "number") {
|
|
5369
|
+
instance.goToPage?.(page);
|
|
4550
5370
|
}
|
|
4551
|
-
}
|
|
4552
|
-
}
|
|
5371
|
+
}
|
|
5372
|
+
});
|
|
4553
5373
|
actions.push(
|
|
4554
5374
|
{
|
|
4555
5375
|
id: "zoom-out",
|
|
@@ -4621,43 +5441,57 @@ var RtfPlugin = class {
|
|
|
4621
5441
|
async render(ctx) {
|
|
4622
5442
|
const wrapper = document.createElement("div");
|
|
4623
5443
|
wrapper.className = "fp-rtf-wrapper";
|
|
4624
|
-
wrapper.style.padding = "
|
|
4625
|
-
wrapper.style.
|
|
5444
|
+
wrapper.style.padding = "0";
|
|
5445
|
+
wrapper.style.width = "816px";
|
|
4626
5446
|
wrapper.style.margin = "0 auto";
|
|
4627
|
-
wrapper.style.
|
|
4628
|
-
wrapper.style.
|
|
4629
|
-
wrapper.style.
|
|
4630
|
-
wrapper.style.
|
|
5447
|
+
wrapper.style.boxSizing = "border-box";
|
|
5448
|
+
wrapper.style.display = "flex";
|
|
5449
|
+
wrapper.style.flexDirection = "column";
|
|
5450
|
+
wrapper.style.alignItems = "center";
|
|
5451
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4631
5452
|
wrapper.style.transformOrigin = "top center";
|
|
4632
|
-
wrapper.style.transition = "transform 0.
|
|
4633
|
-
ctx.container.style.
|
|
4634
|
-
ctx.container.style.
|
|
5453
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5454
|
+
ctx.container.style.overflowX = "hidden";
|
|
5455
|
+
ctx.container.style.overflowY = "auto";
|
|
5456
|
+
ctx.container.style.padding = "16px 8px";
|
|
4635
5457
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
4636
5458
|
ctx.container.appendChild(wrapper);
|
|
4637
5459
|
let scale = 1;
|
|
4638
5460
|
let rotation = 0;
|
|
4639
5461
|
let pageElements = [];
|
|
4640
|
-
let
|
|
5462
|
+
let isUserZoomed = false;
|
|
5463
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
4641
5464
|
const calculateFitScale = (mode = fitMode) => {
|
|
4642
5465
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4643
|
-
const elW =
|
|
4644
|
-
const singlePageH =
|
|
4645
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
4646
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
5466
|
+
const elW = 816;
|
|
5467
|
+
const singlePageH = activeEl?.offsetHeight || 1056;
|
|
5468
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5469
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
4647
5470
|
const sW = availW / elW;
|
|
4648
5471
|
const sH = availH / singlePageH;
|
|
4649
5472
|
if (mode === "page") {
|
|
4650
|
-
return Math.max(0.
|
|
5473
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
4651
5474
|
}
|
|
4652
|
-
return Math.max(0.
|
|
5475
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
4653
5476
|
};
|
|
4654
5477
|
const applyTransform = () => {
|
|
4655
5478
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4656
5479
|
wrapper.style.transformOrigin = "top center";
|
|
5480
|
+
const activeEl = pageElements[currentPage - 1];
|
|
5481
|
+
const baseH = activeEl?.offsetHeight || 1056;
|
|
5482
|
+
const scaledH = baseH * scale;
|
|
5483
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5484
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
4657
5485
|
};
|
|
5486
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5487
|
+
if (!isUserZoomed) {
|
|
5488
|
+
scale = calculateFitScale(fitMode);
|
|
5489
|
+
applyTransform();
|
|
5490
|
+
}
|
|
5491
|
+
}) : null;
|
|
5492
|
+
resizeObserver?.observe(ctx.container);
|
|
4658
5493
|
setTimeout(() => {
|
|
4659
|
-
|
|
4660
|
-
scale = calculateFitScale("width");
|
|
5494
|
+
scale = calculateFitScale(fitMode);
|
|
4661
5495
|
applyTransform();
|
|
4662
5496
|
}, 60);
|
|
4663
5497
|
try {
|
|
@@ -4667,20 +5501,34 @@ var RtfPlugin = class {
|
|
|
4667
5501
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
4668
5502
|
const htmlElements = await doc.render();
|
|
4669
5503
|
const contentNodes = [];
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
5504
|
+
const extractBlocks = (nodes) => {
|
|
5505
|
+
for (const item of nodes) {
|
|
5506
|
+
if (!item || !(item instanceof HTMLElement)) continue;
|
|
5507
|
+
const tag = item.tagName.toLowerCase();
|
|
5508
|
+
const hasChildBlocks = Array.from(item.children).some((c) => {
|
|
5509
|
+
const ct = c.tagName.toLowerCase();
|
|
5510
|
+
return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
|
|
5511
|
+
});
|
|
5512
|
+
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5513
|
+
extractBlocks(Array.from(item.children));
|
|
5514
|
+
} else {
|
|
5515
|
+
if (tag === "p" || tag === "div") {
|
|
5516
|
+
item.style.display = "block";
|
|
5517
|
+
item.style.marginBottom = "12px";
|
|
5518
|
+
item.style.lineHeight = "1.6";
|
|
5519
|
+
}
|
|
5520
|
+
contentNodes.push(item);
|
|
5521
|
+
}
|
|
4675
5522
|
}
|
|
4676
|
-
}
|
|
5523
|
+
};
|
|
5524
|
+
extractBlocks(htmlElements);
|
|
4677
5525
|
wrapper.innerHTML = "";
|
|
4678
5526
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4679
5527
|
const childHeights = contentNodes.map((c) => {
|
|
4680
5528
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4681
5529
|
const offH = c.offsetHeight || 0;
|
|
4682
5530
|
const textLen = c.textContent?.trim().length || 0;
|
|
4683
|
-
const estH = Math.max(
|
|
5531
|
+
const estH = Math.max(28, Math.ceil(textLen / 75) * 24 + 16);
|
|
4684
5532
|
return Math.max(rectH, offH, estH);
|
|
4685
5533
|
});
|
|
4686
5534
|
wrapper.innerHTML = "";
|
|
@@ -4697,6 +5545,7 @@ var RtfPlugin = class {
|
|
|
4697
5545
|
card.style.marginBottom = "24px";
|
|
4698
5546
|
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4699
5547
|
card.style.lineHeight = "1.6";
|
|
5548
|
+
card.style.color = "#1e293b";
|
|
4700
5549
|
return card;
|
|
4701
5550
|
};
|
|
4702
5551
|
let curCard = createRtfCard();
|
|
@@ -4732,9 +5581,8 @@ var RtfPlugin = class {
|
|
|
4732
5581
|
pageCard.style.padding = "72px 56px";
|
|
4733
5582
|
pageCard.style.width = "816px";
|
|
4734
5583
|
pageCard.style.minHeight = "1056px";
|
|
4735
|
-
pageCard.style.maxWidth = "100%";
|
|
4736
5584
|
pageCard.style.boxSizing = "border-box";
|
|
4737
|
-
pageCard.style.fontFamily = "serif
|
|
5585
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4738
5586
|
pageCard.style.fontSize = "12pt";
|
|
4739
5587
|
pageCard.style.lineHeight = "1.6";
|
|
4740
5588
|
pageCard.style.color = "#1e293b";
|
|
@@ -4747,29 +5595,6 @@ var RtfPlugin = class {
|
|
|
4747
5595
|
}
|
|
4748
5596
|
const totalPages = Math.max(1, pageElements.length);
|
|
4749
5597
|
let currentPage = 1;
|
|
4750
|
-
let indicator = null;
|
|
4751
|
-
if (totalPages > 1) {
|
|
4752
|
-
indicator = document.createElement("div");
|
|
4753
|
-
indicator.className = "fp-rtf-page-indicator";
|
|
4754
|
-
indicator.style.position = "sticky";
|
|
4755
|
-
indicator.style.bottom = "16px";
|
|
4756
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4757
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
4758
|
-
indicator.style.color = "#f8fafc";
|
|
4759
|
-
indicator.style.fontSize = "12px";
|
|
4760
|
-
indicator.style.fontWeight = "600";
|
|
4761
|
-
indicator.style.padding = "5px 14px";
|
|
4762
|
-
indicator.style.borderRadius = "20px";
|
|
4763
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4764
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4765
|
-
indicator.style.zIndex = "10";
|
|
4766
|
-
indicator.style.userSelect = "none";
|
|
4767
|
-
indicator.style.pointerEvents = "none";
|
|
4768
|
-
indicator.style.textAlign = "center";
|
|
4769
|
-
indicator.style.width = "fit-content";
|
|
4770
|
-
indicator.style.margin = "16px auto 0";
|
|
4771
|
-
ctx.container.appendChild(indicator);
|
|
4772
|
-
}
|
|
4773
5598
|
const showPage = (pageNum) => {
|
|
4774
5599
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4775
5600
|
if (totalPages > 1) {
|
|
@@ -4777,9 +5602,6 @@ var RtfPlugin = class {
|
|
|
4777
5602
|
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4778
5603
|
});
|
|
4779
5604
|
}
|
|
4780
|
-
if (indicator) {
|
|
4781
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4782
|
-
}
|
|
4783
5605
|
ctx.container.scrollTop = 0;
|
|
4784
5606
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4785
5607
|
};
|
|
@@ -4787,7 +5609,7 @@ var RtfPlugin = class {
|
|
|
4787
5609
|
showPage(1);
|
|
4788
5610
|
}
|
|
4789
5611
|
const cleanup = () => {
|
|
4790
|
-
|
|
5612
|
+
resizeObserver?.disconnect();
|
|
4791
5613
|
wrapper.remove();
|
|
4792
5614
|
ctx.container.innerHTML = "";
|
|
4793
5615
|
};
|
|
@@ -4798,21 +5620,25 @@ var RtfPlugin = class {
|
|
|
4798
5620
|
getCurrentPage: () => currentPage,
|
|
4799
5621
|
goToPage: (page) => showPage(page),
|
|
4800
5622
|
zoomIn: () => {
|
|
5623
|
+
isUserZoomed = true;
|
|
4801
5624
|
scale += 0.15;
|
|
4802
5625
|
applyTransform();
|
|
4803
5626
|
},
|
|
4804
5627
|
zoomOut: () => {
|
|
5628
|
+
isUserZoomed = true;
|
|
4805
5629
|
scale = Math.max(0.2, scale - 0.15);
|
|
4806
5630
|
applyTransform();
|
|
4807
5631
|
},
|
|
4808
5632
|
getZoom: () => scale,
|
|
4809
5633
|
setZoom: (level) => {
|
|
5634
|
+
isUserZoomed = true;
|
|
4810
5635
|
scale = level;
|
|
4811
5636
|
applyTransform();
|
|
4812
5637
|
},
|
|
4813
5638
|
fitToPage: () => {
|
|
4814
|
-
|
|
4815
|
-
|
|
5639
|
+
isUserZoomed = false;
|
|
5640
|
+
fitMode = "width";
|
|
5641
|
+
scale = calculateFitScale("width");
|
|
4816
5642
|
rotation = 0;
|
|
4817
5643
|
applyTransform();
|
|
4818
5644
|
},
|
|
@@ -5000,40 +5826,36 @@ var OpenDocumentPlugin = class {
|
|
|
5000
5826
|
const isPresentation = instance.isPresentation;
|
|
5001
5827
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5002
5828
|
const actions = [];
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
max
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
if (
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
instance.goToPage?.(page);
|
|
5031
|
-
} else if (typeof action === "number") {
|
|
5032
|
-
instance.goToPage?.(action);
|
|
5033
|
-
}
|
|
5829
|
+
actions.push({
|
|
5830
|
+
id: "thumbnails",
|
|
5831
|
+
icon: "thumbnails",
|
|
5832
|
+
label: isPresentation ? "Slide Thumbnails" : "Page Thumbnails",
|
|
5833
|
+
type: "button",
|
|
5834
|
+
group: "navigation",
|
|
5835
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5836
|
+
});
|
|
5837
|
+
actions.push({
|
|
5838
|
+
id: "page-nav",
|
|
5839
|
+
icon: "",
|
|
5840
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
5841
|
+
type: "page-nav",
|
|
5842
|
+
group: "navigation",
|
|
5843
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5844
|
+
max: totalPages,
|
|
5845
|
+
execute: (action, page) => {
|
|
5846
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5847
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5848
|
+
if (action === "prev") {
|
|
5849
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5850
|
+
} else if (action === "next") {
|
|
5851
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5852
|
+
} else if (typeof page === "number") {
|
|
5853
|
+
instance.goToPage?.(page);
|
|
5854
|
+
} else if (typeof action === "number") {
|
|
5855
|
+
instance.goToPage?.(action);
|
|
5034
5856
|
}
|
|
5035
|
-
}
|
|
5036
|
-
}
|
|
5857
|
+
}
|
|
5858
|
+
});
|
|
5037
5859
|
actions.push(
|
|
5038
5860
|
{
|
|
5039
5861
|
id: "zoom-out",
|
|
@@ -5124,49 +5946,65 @@ var OpenDocumentPlugin = class {
|
|
|
5124
5946
|
container.className = "fp-odf-container";
|
|
5125
5947
|
container.style.width = "100%";
|
|
5126
5948
|
container.style.height = "100%";
|
|
5127
|
-
container.style.
|
|
5128
|
-
container.style.
|
|
5949
|
+
container.style.overflowX = "hidden";
|
|
5950
|
+
container.style.overflowY = "auto";
|
|
5951
|
+
container.style.padding = "16px 8px";
|
|
5129
5952
|
container.style.backgroundColor = "#f1f5f9";
|
|
5130
5953
|
const wrapper = document.createElement("div");
|
|
5131
5954
|
wrapper.className = "fp-odf-wrapper";
|
|
5132
5955
|
wrapper.style.margin = "0 auto";
|
|
5956
|
+
wrapper.style.width = isPresentation ? "960px" : "816px";
|
|
5957
|
+
wrapper.style.boxSizing = "border-box";
|
|
5133
5958
|
wrapper.style.backgroundColor = "#ffffff";
|
|
5134
5959
|
wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
5135
5960
|
wrapper.style.borderRadius = "4px";
|
|
5136
5961
|
wrapper.style.transformOrigin = "top center";
|
|
5137
|
-
wrapper.style.transition = "transform 0.
|
|
5962
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5138
5963
|
container.appendChild(wrapper);
|
|
5139
5964
|
ctx.container.appendChild(container);
|
|
5140
5965
|
let scale = 1;
|
|
5141
5966
|
let rotation = 0;
|
|
5142
|
-
let
|
|
5967
|
+
let isUserZoomed = false;
|
|
5968
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
5969
|
+
let currentPage = 1;
|
|
5970
|
+
let totalPages = 1;
|
|
5971
|
+
let slides = [];
|
|
5143
5972
|
const calculateFitScale = (mode = fitMode) => {
|
|
5144
|
-
const
|
|
5145
|
-
const
|
|
5146
|
-
const
|
|
5147
|
-
const
|
|
5973
|
+
const activeSlide = slides[currentPage - 1];
|
|
5974
|
+
const elW = isPresentation ? 960 : 816;
|
|
5975
|
+
const singlePageH = Math.min(activeSlide?.offsetHeight || wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
5976
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5977
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5148
5978
|
const sW = availW / elW;
|
|
5149
5979
|
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
5150
5980
|
if (isPresentation) {
|
|
5151
|
-
return Math.min(
|
|
5981
|
+
return Math.min(2.5, Math.min(sW, sH));
|
|
5152
5982
|
}
|
|
5153
5983
|
if (mode === "page") {
|
|
5154
|
-
return Math.max(0.
|
|
5984
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5155
5985
|
}
|
|
5156
|
-
return Math.max(0.
|
|
5986
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5157
5987
|
};
|
|
5158
5988
|
const applyTransform = () => {
|
|
5159
5989
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5160
5990
|
wrapper.style.transformOrigin = "top center";
|
|
5991
|
+
const activeSlide = slides[currentPage - 1];
|
|
5992
|
+
const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
|
|
5993
|
+
const scaledH = baseH * scale;
|
|
5994
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5995
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
5161
5996
|
};
|
|
5997
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5998
|
+
if (!isUserZoomed) {
|
|
5999
|
+
scale = calculateFitScale(fitMode);
|
|
6000
|
+
applyTransform();
|
|
6001
|
+
}
|
|
6002
|
+
}) : null;
|
|
6003
|
+
resizeObserver?.observe(ctx.container);
|
|
5162
6004
|
setTimeout(() => {
|
|
5163
|
-
|
|
5164
|
-
scale = calculateFitScale("width");
|
|
6005
|
+
scale = calculateFitScale(fitMode);
|
|
5165
6006
|
applyTransform();
|
|
5166
6007
|
}, 60);
|
|
5167
|
-
let currentPage = 1;
|
|
5168
|
-
let totalPages = 1;
|
|
5169
|
-
let slides = [];
|
|
5170
6008
|
if (isPresentation) {
|
|
5171
6009
|
wrapper.style.maxWidth = "960px";
|
|
5172
6010
|
wrapper.style.aspectRatio = "16 / 9";
|
|
@@ -5267,24 +6105,9 @@ var OpenDocumentPlugin = class {
|
|
|
5267
6105
|
wrapper.appendChild(page);
|
|
5268
6106
|
slides.push(page);
|
|
5269
6107
|
});
|
|
5270
|
-
const pageIndicator = document.createElement("div");
|
|
5271
|
-
pageIndicator.className = "fp-odt-page-indicator";
|
|
5272
|
-
pageIndicator.style.position = "sticky";
|
|
5273
|
-
pageIndicator.style.bottom = "16px";
|
|
5274
|
-
pageIndicator.style.left = "50%";
|
|
5275
|
-
pageIndicator.style.transform = "translateX(-50%)";
|
|
5276
|
-
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
5277
|
-
pageIndicator.style.color = "#fff";
|
|
5278
|
-
pageIndicator.style.padding = "6px 12px";
|
|
5279
|
-
pageIndicator.style.borderRadius = "16px";
|
|
5280
|
-
pageIndicator.style.fontSize = "12px";
|
|
5281
|
-
pageIndicator.style.zIndex = "100";
|
|
5282
|
-
pageIndicator.style.display = "inline-block";
|
|
5283
|
-
pageIndicator.style.width = "fit-content";
|
|
5284
|
-
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
5285
|
-
container.appendChild(pageIndicator);
|
|
5286
6108
|
}
|
|
5287
6109
|
const cleanup = () => {
|
|
6110
|
+
resizeObserver?.disconnect();
|
|
5288
6111
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
5289
6112
|
container.remove();
|
|
5290
6113
|
ctx.container.innerHTML = "";
|
|
@@ -5296,10 +6119,6 @@ var OpenDocumentPlugin = class {
|
|
|
5296
6119
|
slides.forEach((s, idx) => {
|
|
5297
6120
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
5298
6121
|
});
|
|
5299
|
-
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
5300
|
-
if (indicator) {
|
|
5301
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5302
|
-
}
|
|
5303
6122
|
container.scrollTop = 0;
|
|
5304
6123
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5305
6124
|
};
|
|
@@ -5307,21 +6126,25 @@ var OpenDocumentPlugin = class {
|
|
|
5307
6126
|
destroy: cleanup,
|
|
5308
6127
|
isPresentation,
|
|
5309
6128
|
zoomIn: () => {
|
|
6129
|
+
isUserZoomed = true;
|
|
5310
6130
|
scale += 0.15;
|
|
5311
6131
|
applyTransform();
|
|
5312
6132
|
},
|
|
5313
6133
|
zoomOut: () => {
|
|
6134
|
+
isUserZoomed = true;
|
|
5314
6135
|
scale = Math.max(0.2, scale - 0.15);
|
|
5315
6136
|
applyTransform();
|
|
5316
6137
|
},
|
|
5317
6138
|
getZoom: () => scale,
|
|
5318
6139
|
setZoom: (level) => {
|
|
6140
|
+
isUserZoomed = true;
|
|
5319
6141
|
scale = level;
|
|
5320
6142
|
applyTransform();
|
|
5321
6143
|
},
|
|
5322
6144
|
fitToPage: () => {
|
|
5323
|
-
|
|
5324
|
-
|
|
6145
|
+
isUserZoomed = false;
|
|
6146
|
+
fitMode = "width";
|
|
6147
|
+
scale = calculateFitScale("width");
|
|
5325
6148
|
rotation = 0;
|
|
5326
6149
|
applyTransform();
|
|
5327
6150
|
},
|
|
@@ -5337,23 +6160,45 @@ var OpenDocumentPlugin = class {
|
|
|
5337
6160
|
getPageCount: () => totalPages,
|
|
5338
6161
|
getCurrentPage: () => currentPage,
|
|
5339
6162
|
getThumbnails: async () => {
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
canvas
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
6163
|
+
const count = totalPages || slides.length || 1;
|
|
6164
|
+
const items = [];
|
|
6165
|
+
for (let idx = 0; idx < count; idx++) {
|
|
6166
|
+
const itemIdx = idx;
|
|
6167
|
+
items.push({
|
|
6168
|
+
index: itemIdx,
|
|
6169
|
+
label: isPresentation ? `Slide ${itemIdx + 1}` : `Page ${itemIdx + 1}`,
|
|
6170
|
+
render: async (canvas) => {
|
|
6171
|
+
const ctx2d = canvas.getContext("2d");
|
|
6172
|
+
if (!ctx2d) return;
|
|
6173
|
+
if (isPresentation) {
|
|
6174
|
+
canvas.width = 160;
|
|
6175
|
+
canvas.height = 90;
|
|
6176
|
+
ctx2d.fillStyle = "#f8fafc";
|
|
6177
|
+
ctx2d.fillRect(0, 0, 160, 90);
|
|
6178
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6179
|
+
ctx2d.lineWidth = 1;
|
|
6180
|
+
ctx2d.strokeRect(0.5, 0.5, 159, 89);
|
|
6181
|
+
ctx2d.fillStyle = "#334155";
|
|
6182
|
+
ctx2d.font = "bold 11px sans-serif";
|
|
6183
|
+
ctx2d.textAlign = "center";
|
|
6184
|
+
ctx2d.fillText(`Slide ${itemIdx + 1}`, 80, 50);
|
|
6185
|
+
} else {
|
|
6186
|
+
canvas.width = 140;
|
|
6187
|
+
canvas.height = 180;
|
|
6188
|
+
ctx2d.fillStyle = "#ffffff";
|
|
6189
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
6190
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6191
|
+
ctx2d.lineWidth = 1;
|
|
6192
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
6193
|
+
ctx2d.fillStyle = "#64748b";
|
|
6194
|
+
ctx2d.font = "bold 10px sans-serif";
|
|
6195
|
+
ctx2d.textAlign = "center";
|
|
6196
|
+
ctx2d.fillText(`Page ${itemIdx + 1}`, 70, 90);
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
});
|
|
6200
|
+
}
|
|
6201
|
+
return items;
|
|
5357
6202
|
},
|
|
5358
6203
|
download: () => {
|
|
5359
6204
|
const mimeType = this.mimeTypes.find((m) => m.includes(ext.replace(".", ""))) || "application/octet-stream";
|
|
@@ -5458,23 +6303,24 @@ var OpenDocumentPlugin = class {
|
|
|
5458
6303
|
case "h": {
|
|
5459
6304
|
const level = Math.min(6, Math.max(1, Number(node.getAttribute("text:outline-level") || 1)));
|
|
5460
6305
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5461
|
-
html += `<h${level} style="${style}; font-family:
|
|
6306
|
+
html += `<h${level} style="${style}; margin: 18px 0 8px; color: #1e3a8a; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${node.textContent || ""}</h${level}>`;
|
|
5462
6307
|
break;
|
|
5463
6308
|
}
|
|
5464
6309
|
case "p": {
|
|
5465
6310
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5466
6311
|
const inner = this.renderSpans(node, styles, images);
|
|
5467
|
-
|
|
6312
|
+
const isInsideLi = node.parentElement?.localName === "list-item" || node.parentElement?.tagName?.toLowerCase() === "list-item";
|
|
6313
|
+
html += `<p style="${style}; line-height: 1.5; margin: ${isInsideLi ? "0" : "8px 0 12px"}; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${inner}</p>`;
|
|
5468
6314
|
break;
|
|
5469
6315
|
}
|
|
5470
6316
|
case "list": {
|
|
5471
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
6317
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
5472
6318
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5473
6319
|
html += "</ul>";
|
|
5474
6320
|
break;
|
|
5475
6321
|
}
|
|
5476
6322
|
case "list-item": {
|
|
5477
|
-
html +=
|
|
6323
|
+
html += '<li style="margin: 4px 0; font-size: 11pt; line-height: 1.5; color: #1e293b;">';
|
|
5478
6324
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5479
6325
|
html += "</li>";
|
|
5480
6326
|
break;
|
|
@@ -5600,28 +6446,26 @@ var DocPlugin = class {
|
|
|
5600
6446
|
getToolbarActions(instance) {
|
|
5601
6447
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5602
6448
|
const actions = [];
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
if (
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
instance.goToPage?.(page);
|
|
5621
|
-
}
|
|
6449
|
+
actions.push({
|
|
6450
|
+
id: "page-nav",
|
|
6451
|
+
icon: "",
|
|
6452
|
+
label: "Page Navigation",
|
|
6453
|
+
type: "page-nav",
|
|
6454
|
+
group: "navigation",
|
|
6455
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
6456
|
+
max: totalPages,
|
|
6457
|
+
execute: (action, page) => {
|
|
6458
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
6459
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
6460
|
+
if (action === "prev") {
|
|
6461
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
6462
|
+
} else if (action === "next") {
|
|
6463
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
6464
|
+
} else if (typeof page === "number") {
|
|
6465
|
+
instance.goToPage?.(page);
|
|
5622
6466
|
}
|
|
5623
|
-
}
|
|
5624
|
-
}
|
|
6467
|
+
}
|
|
6468
|
+
});
|
|
5625
6469
|
actions.push(
|
|
5626
6470
|
{
|
|
5627
6471
|
id: "zoom-out",
|
|
@@ -5695,8 +6539,9 @@ var DocPlugin = class {
|
|
|
5695
6539
|
container.className = "fp-doc-container";
|
|
5696
6540
|
container.style.width = "100%";
|
|
5697
6541
|
container.style.height = "100%";
|
|
5698
|
-
container.style.
|
|
5699
|
-
container.style.
|
|
6542
|
+
container.style.overflowX = "hidden";
|
|
6543
|
+
container.style.overflowY = "auto";
|
|
6544
|
+
container.style.padding = "16px 8px";
|
|
5700
6545
|
container.style.backgroundColor = "#f1f5f9";
|
|
5701
6546
|
container.style.display = "flex";
|
|
5702
6547
|
container.style.justifyContent = "center";
|
|
@@ -5741,16 +6586,15 @@ var DocPlugin = class {
|
|
|
5741
6586
|
const pageCard = document.createElement("div");
|
|
5742
6587
|
pageCard.className = "fp-doc-page-card";
|
|
5743
6588
|
pageCard.style.width = "816px";
|
|
5744
|
-
pageCard.style.
|
|
6589
|
+
pageCard.style.minHeight = "1056px";
|
|
5745
6590
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5746
|
-
pageCard.style.boxShadow = "0
|
|
6591
|
+
pageCard.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5747
6592
|
pageCard.style.borderRadius = "4px";
|
|
5748
|
-
pageCard.style.padding = "
|
|
6593
|
+
pageCard.style.padding = "72px 56px";
|
|
5749
6594
|
pageCard.style.boxSizing = "border-box";
|
|
5750
|
-
pageCard.style.overflow = "hidden";
|
|
5751
6595
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5752
6596
|
pageCard.style.transformOrigin = "top center";
|
|
5753
|
-
pageCard.style.transition = "transform 0.
|
|
6597
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
5754
6598
|
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5755
6599
|
pageCard.style.color = "#1e293b";
|
|
5756
6600
|
if (isFallback && i === 0) {
|
|
@@ -5767,34 +6611,15 @@ var DocPlugin = class {
|
|
|
5767
6611
|
container.appendChild(pageCard);
|
|
5768
6612
|
pageCards.push(pageCard);
|
|
5769
6613
|
}
|
|
5770
|
-
let indicator = null;
|
|
5771
|
-
if (totalPages > 1) {
|
|
5772
|
-
indicator = document.createElement("div");
|
|
5773
|
-
indicator.className = "fp-doc-page-indicator";
|
|
5774
|
-
indicator.style.position = "fixed";
|
|
5775
|
-
indicator.style.bottom = "16px";
|
|
5776
|
-
indicator.style.left = "50%";
|
|
5777
|
-
indicator.style.transform = "translateX(-50%)";
|
|
5778
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
5779
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
5780
|
-
indicator.style.color = "#f8fafc";
|
|
5781
|
-
indicator.style.fontSize = "12px";
|
|
5782
|
-
indicator.style.fontWeight = "600";
|
|
5783
|
-
indicator.style.padding = "5px 14px";
|
|
5784
|
-
indicator.style.borderRadius = "20px";
|
|
5785
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
5786
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
5787
|
-
indicator.style.zIndex = "10";
|
|
5788
|
-
indicator.style.userSelect = "none";
|
|
5789
|
-
indicator.style.pointerEvents = "none";
|
|
5790
|
-
indicator.style.textAlign = "center";
|
|
5791
|
-
container.appendChild(indicator);
|
|
5792
|
-
}
|
|
5793
6614
|
let rotation = 0;
|
|
5794
6615
|
const applyTransform = () => {
|
|
5795
6616
|
const activeCard = pageCards[currentPage - 1];
|
|
5796
6617
|
if (activeCard) {
|
|
5797
6618
|
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
6619
|
+
const baseH = activeCard.offsetHeight || 1056;
|
|
6620
|
+
const scaledH = baseH * scale;
|
|
6621
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6622
|
+
activeCard.style.marginBottom = `${extraH + 32}px`;
|
|
5798
6623
|
}
|
|
5799
6624
|
};
|
|
5800
6625
|
const showPage = (pageNum) => {
|
|
@@ -5807,35 +6632,39 @@ var DocPlugin = class {
|
|
|
5807
6632
|
card.style.display = "none";
|
|
5808
6633
|
}
|
|
5809
6634
|
});
|
|
5810
|
-
if (indicator) {
|
|
5811
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5812
|
-
}
|
|
5813
6635
|
container.scrollTop = 0;
|
|
5814
6636
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5815
6637
|
};
|
|
5816
6638
|
if (totalPages > 1) {
|
|
5817
6639
|
showPage(1);
|
|
5818
6640
|
}
|
|
5819
|
-
let fitMode = "width";
|
|
6641
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6642
|
+
let isUserZoomed = false;
|
|
5820
6643
|
const calculateFitScale = (mode = fitMode) => {
|
|
5821
6644
|
const elW = 816;
|
|
5822
6645
|
const elH = 1056;
|
|
5823
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
5824
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
6646
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6647
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5825
6648
|
const sW = availW / elW;
|
|
5826
6649
|
const sH = availH / elH;
|
|
5827
6650
|
if (mode === "page") {
|
|
5828
|
-
return Math.max(0.
|
|
6651
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5829
6652
|
}
|
|
5830
|
-
return Math.max(0.
|
|
6653
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5831
6654
|
};
|
|
6655
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6656
|
+
if (!isUserZoomed) {
|
|
6657
|
+
scale = calculateFitScale(fitMode);
|
|
6658
|
+
applyTransform();
|
|
6659
|
+
}
|
|
6660
|
+
}) : null;
|
|
6661
|
+
resizeObserver?.observe(ctx.container);
|
|
5832
6662
|
setTimeout(() => {
|
|
5833
|
-
|
|
5834
|
-
scale = calculateFitScale("width");
|
|
6663
|
+
scale = calculateFitScale(fitMode);
|
|
5835
6664
|
applyTransform();
|
|
5836
6665
|
}, 60);
|
|
5837
6666
|
const cleanup = () => {
|
|
5838
|
-
|
|
6667
|
+
resizeObserver?.disconnect();
|
|
5839
6668
|
container.remove();
|
|
5840
6669
|
ctx.container.innerHTML = "";
|
|
5841
6670
|
};
|
|
@@ -5846,21 +6675,25 @@ var DocPlugin = class {
|
|
|
5846
6675
|
getCurrentPage: () => currentPage,
|
|
5847
6676
|
goToPage: (page) => showPage(page),
|
|
5848
6677
|
zoomIn: () => {
|
|
6678
|
+
isUserZoomed = true;
|
|
5849
6679
|
scale += 0.15;
|
|
5850
6680
|
applyTransform();
|
|
5851
6681
|
},
|
|
5852
6682
|
zoomOut: () => {
|
|
6683
|
+
isUserZoomed = true;
|
|
5853
6684
|
scale = Math.max(0.2, scale - 0.15);
|
|
5854
6685
|
applyTransform();
|
|
5855
6686
|
},
|
|
5856
6687
|
getZoom: () => scale,
|
|
5857
6688
|
setZoom: (level) => {
|
|
6689
|
+
isUserZoomed = true;
|
|
5858
6690
|
scale = level;
|
|
5859
6691
|
applyTransform();
|
|
5860
6692
|
},
|
|
5861
6693
|
fitToPage: () => {
|
|
5862
|
-
|
|
5863
|
-
|
|
6694
|
+
isUserZoomed = false;
|
|
6695
|
+
fitMode = "width";
|
|
6696
|
+
scale = calculateFitScale("width");
|
|
5864
6697
|
rotation = 0;
|
|
5865
6698
|
applyTransform();
|
|
5866
6699
|
},
|
|
@@ -6237,25 +7070,31 @@ ${chartSvg}
|
|
|
6237
7070
|
i++;
|
|
6238
7071
|
continue;
|
|
6239
7072
|
}
|
|
6240
|
-
if (
|
|
7073
|
+
if (/^\d{1,2}$/.test(line.trim())) {
|
|
7074
|
+
i++;
|
|
7075
|
+
continue;
|
|
7076
|
+
}
|
|
7077
|
+
const isShortLine = line.length < 60 && !line.endsWith(".") && !line.endsWith(",");
|
|
7078
|
+
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));
|
|
7079
|
+
if (isTitleLike) {
|
|
6241
7080
|
if (inList) {
|
|
6242
7081
|
html += "</ul>";
|
|
6243
7082
|
inList = false;
|
|
6244
7083
|
}
|
|
6245
|
-
html += `<h2 style="font-size:
|
|
7084
|
+
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>`;
|
|
6246
7085
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
6247
7086
|
if (!inList) {
|
|
6248
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
7087
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
6249
7088
|
inList = true;
|
|
6250
7089
|
}
|
|
6251
7090
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
6252
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
7091
|
+
html += `<li style="margin: 4px 0; line-height: 1.5; font-size: 11pt; color: #1e293b;">${DOMPurify6__default.default.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
6253
7092
|
} else {
|
|
6254
7093
|
if (inList) {
|
|
6255
7094
|
html += "</ul>";
|
|
6256
7095
|
inList = false;
|
|
6257
7096
|
}
|
|
6258
|
-
html += `<p style="line-height: 1.
|
|
7097
|
+
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>`;
|
|
6259
7098
|
}
|
|
6260
7099
|
i++;
|
|
6261
7100
|
}
|