@files-preview-app/preview-file 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/angular.cjs +1307 -468
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +1307 -468
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +1307 -468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d-B79v0jxi.d.cts +570 -0
- package/dist/index.d-B79v0jxi.d.ts +570 -0
- package/dist/index.d.cts +3227 -19
- package/dist/index.d.ts +3227 -19
- package/dist/index.js +1307 -468
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1307 -468
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -16
- package/dist/react.d.ts +1 -16
- package/dist/react.js +1307 -468
- package/dist/react.js.map +1 -1
- package/dist/styles.css +195 -14
- package/dist/vue.cjs +1307 -468
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1307 -468
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
package/dist/angular.js
CHANGED
|
@@ -542,8 +542,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
542
542
|
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>`;
|
|
543
543
|
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>`;
|
|
544
544
|
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>`;
|
|
545
|
-
var
|
|
546
|
-
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>`;
|
|
545
|
+
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>`;
|
|
547
546
|
var ICON_MAP = {
|
|
548
547
|
"zoom-in": ICON_ZOOM_IN,
|
|
549
548
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -570,28 +569,177 @@ var ICON_MAP = {
|
|
|
570
569
|
"forward-10": ICON_FAST_FORWARD,
|
|
571
570
|
"rewind": ICON_REWIND,
|
|
572
571
|
"replay-10": ICON_REWIND,
|
|
573
|
-
"speed": ICON_SPEED,
|
|
574
572
|
"open-window": ICON_EXTERNAL_WINDOW,
|
|
575
|
-
"external-window": ICON_EXTERNAL_WINDOW
|
|
573
|
+
"external-window": ICON_EXTERNAL_WINDOW,
|
|
574
|
+
"openWindow": ICON_EXTERNAL_WINDOW,
|
|
575
|
+
"openSeparateWindow": ICON_EXTERNAL_WINDOW
|
|
576
576
|
};
|
|
577
577
|
var ToolbarController = class {
|
|
578
578
|
el;
|
|
579
579
|
toolbarEl;
|
|
580
580
|
actions = [];
|
|
581
|
+
config = {};
|
|
581
582
|
pageInputEl = null;
|
|
582
583
|
pageLabelEl = null;
|
|
583
|
-
|
|
584
|
+
prevPageBtn = null;
|
|
585
|
+
nextPageBtn = null;
|
|
586
|
+
constructor(container, config) {
|
|
584
587
|
this.el = container;
|
|
588
|
+
if (config) this.config = { ...config };
|
|
585
589
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
586
590
|
this.el.appendChild(this.toolbarEl);
|
|
587
591
|
}
|
|
592
|
+
setConfig(config) {
|
|
593
|
+
this.config = { ...config };
|
|
594
|
+
this.render();
|
|
595
|
+
}
|
|
596
|
+
getConfig() {
|
|
597
|
+
return { ...this.config };
|
|
598
|
+
}
|
|
599
|
+
hideAction(actionId) {
|
|
600
|
+
this.config[actionId] = false;
|
|
601
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = false;
|
|
602
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = false;
|
|
603
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
604
|
+
this.config.fitPage = false;
|
|
605
|
+
this.config.fitToPage = false;
|
|
606
|
+
this.config.fitWidth = false;
|
|
607
|
+
}
|
|
608
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
|
|
609
|
+
if (actionId === "fullscreen") this.config.fullscreen = false;
|
|
610
|
+
if (actionId === "download") this.config.download = false;
|
|
611
|
+
if (actionId === "print") this.config.print = false;
|
|
612
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
613
|
+
this.config.openWindow = false;
|
|
614
|
+
this.config.openSeparateWindow = false;
|
|
615
|
+
}
|
|
616
|
+
if (actionId === "copy") this.config.copy = false;
|
|
617
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
618
|
+
this.config.pageNav = false;
|
|
619
|
+
this.config.pagination = false;
|
|
620
|
+
}
|
|
621
|
+
this.render();
|
|
622
|
+
}
|
|
623
|
+
showAction(actionId) {
|
|
624
|
+
this.config[actionId] = true;
|
|
625
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = true;
|
|
626
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = true;
|
|
627
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
628
|
+
this.config.fitPage = true;
|
|
629
|
+
this.config.fitToPage = true;
|
|
630
|
+
this.config.fitWidth = true;
|
|
631
|
+
}
|
|
632
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
|
|
633
|
+
if (actionId === "fullscreen") this.config.fullscreen = true;
|
|
634
|
+
if (actionId === "download") this.config.download = true;
|
|
635
|
+
if (actionId === "print") this.config.print = true;
|
|
636
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
637
|
+
this.config.openWindow = true;
|
|
638
|
+
this.config.openSeparateWindow = true;
|
|
639
|
+
}
|
|
640
|
+
if (actionId === "copy") this.config.copy = true;
|
|
641
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
642
|
+
this.config.pageNav = true;
|
|
643
|
+
this.config.pagination = true;
|
|
644
|
+
}
|
|
645
|
+
this.render();
|
|
646
|
+
}
|
|
647
|
+
normalizeActionId(actionId) {
|
|
648
|
+
if (actionId === "zoomIn") return "zoom-in";
|
|
649
|
+
if (actionId === "zoomOut") return "zoom-out";
|
|
650
|
+
if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
|
|
651
|
+
if (actionId === "rotateCW") return "rotate-cw";
|
|
652
|
+
if (actionId === "rotateCCW") return "rotate-ccw";
|
|
653
|
+
if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
|
|
654
|
+
if (actionId === "pageNav") return "page-nav";
|
|
655
|
+
return actionId;
|
|
656
|
+
}
|
|
657
|
+
enableAction(actionId) {
|
|
658
|
+
const norm = this.normalizeActionId(actionId);
|
|
659
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
660
|
+
if (btn) {
|
|
661
|
+
btn.disabled = false;
|
|
662
|
+
btn.classList.remove("disabled");
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
disableAction(actionId) {
|
|
666
|
+
const norm = this.normalizeActionId(actionId);
|
|
667
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
668
|
+
if (btn) {
|
|
669
|
+
btn.disabled = true;
|
|
670
|
+
btn.classList.add("disabled");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
setActionActive(actionId, active) {
|
|
674
|
+
const norm = this.normalizeActionId(actionId);
|
|
675
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
676
|
+
if (btn) {
|
|
677
|
+
if (active) {
|
|
678
|
+
btn.classList.add("active");
|
|
679
|
+
} else {
|
|
680
|
+
btn.classList.remove("active");
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
isActionEnabled(action) {
|
|
685
|
+
const c = this.config;
|
|
686
|
+
const id = action.id;
|
|
687
|
+
if (c[id] === false) return false;
|
|
688
|
+
if (id === "zoom-in" && (c.zoomIn === false || c["zoom-in"] === false)) return false;
|
|
689
|
+
if (id === "zoom-out" && (c.zoomOut === false || c["zoom-out"] === false)) return false;
|
|
690
|
+
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)) {
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
if (id === "fullscreen" && c.fullscreen === false) return false;
|
|
697
|
+
if (id === "download" && c.download === false) return false;
|
|
698
|
+
if (id === "print" && c.print === false) return false;
|
|
699
|
+
if ((id === "open-window" || id === "external-window") && (c.openWindow === false || c.openSeparateWindow === false || c["open-window"] === false)) {
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
if (id === "copy" && c.copy === false) return false;
|
|
703
|
+
if (id === "thumbnails" && c.thumbnails === false) return false;
|
|
704
|
+
if (id === "page-nav" && (c.pageNav === false || c.pagination === false || c["page-nav"] === false)) {
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
if ((id === "prev" || id === "page-prev") && (c.prevPage === false || c.prev === false || c["prev"] === false || c.pageNav === false || c.pagination === false)) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
if ((id === "next" || id === "page-next") && (c.nextPage === false || c.next === false || c["next"] === false || c.pageNav === false || c.pagination === false)) {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
if (id === "play" && c.play === false) return false;
|
|
714
|
+
if (id === "pause" && c.pause === false) return false;
|
|
715
|
+
if ((id === "fast-forward" || id === "forward-10") && (c.fastForward === false || c["fast-forward"] === false)) {
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
if ((id === "rewind" || id === "replay-10") && (c.rewind === false || c["rewind"] === false)) {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
if (id === "speed" && c.speed === false) return false;
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
588
724
|
setPage(page, max) {
|
|
589
725
|
if (this.pageInputEl) {
|
|
590
726
|
this.pageInputEl.value = page.toString();
|
|
727
|
+
if (max !== void 0) {
|
|
728
|
+
this.pageInputEl.max = max.toString();
|
|
729
|
+
}
|
|
591
730
|
}
|
|
592
731
|
if (max !== void 0 && this.pageLabelEl) {
|
|
593
732
|
this.pageLabelEl.textContent = ` / ${max}`;
|
|
594
733
|
}
|
|
734
|
+
const currentMax = max !== void 0 ? max : parseInt(this.pageInputEl?.max || "1", 10) || 1;
|
|
735
|
+
if (this.prevPageBtn) {
|
|
736
|
+
this.prevPageBtn.disabled = page <= 1;
|
|
737
|
+
this.prevPageBtn.style.opacity = page <= 1 ? "0.4" : "1";
|
|
738
|
+
}
|
|
739
|
+
if (this.nextPageBtn) {
|
|
740
|
+
this.nextPageBtn.disabled = page >= currentMax;
|
|
741
|
+
this.nextPageBtn.style.opacity = page >= currentMax ? "0.4" : "1";
|
|
742
|
+
}
|
|
595
743
|
}
|
|
596
744
|
update(actions) {
|
|
597
745
|
this.actions = actions;
|
|
@@ -614,8 +762,9 @@ var ToolbarController = class {
|
|
|
614
762
|
view: [],
|
|
615
763
|
actions: []
|
|
616
764
|
};
|
|
617
|
-
const
|
|
618
|
-
const
|
|
765
|
+
const enabledActions = this.actions.filter((a) => this.isActionEnabled(a));
|
|
766
|
+
const hasPageNav = enabledActions.some((a) => a.type === "page-nav");
|
|
767
|
+
const effectiveActions = hasPageNav ? enabledActions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : enabledActions;
|
|
619
768
|
for (const action of effectiveActions) {
|
|
620
769
|
if (groups[action.group]) {
|
|
621
770
|
groups[action.group].push(action);
|
|
@@ -675,6 +824,13 @@ var ToolbarController = class {
|
|
|
675
824
|
action.execute("go", val);
|
|
676
825
|
});
|
|
677
826
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
827
|
+
const curVal = action.value ?? 1;
|
|
828
|
+
prevBtn.disabled = curVal <= 1;
|
|
829
|
+
prevBtn.style.opacity = curVal <= 1 ? "0.4" : "1";
|
|
830
|
+
nextBtn.disabled = curVal >= max;
|
|
831
|
+
nextBtn.style.opacity = curVal >= max ? "0.4" : "1";
|
|
832
|
+
this.prevPageBtn = prevBtn;
|
|
833
|
+
this.nextPageBtn = nextBtn;
|
|
678
834
|
this.pageInputEl = input;
|
|
679
835
|
this.pageLabelEl = label;
|
|
680
836
|
groupEl.appendChild(prevBtn);
|
|
@@ -730,25 +886,63 @@ var ToolbarController = class {
|
|
|
730
886
|
var ThumbnailPanel = class {
|
|
731
887
|
el;
|
|
732
888
|
panelEl;
|
|
889
|
+
listEl;
|
|
890
|
+
headerEl;
|
|
733
891
|
thumbnails = [];
|
|
734
892
|
onSelect;
|
|
893
|
+
onToggleCallback;
|
|
735
894
|
activeIndex = 0;
|
|
736
|
-
|
|
895
|
+
observer;
|
|
896
|
+
renderedIndices = /* @__PURE__ */ new Set();
|
|
897
|
+
constructor(container, onToggle) {
|
|
737
898
|
this.el = container;
|
|
899
|
+
this.onToggleCallback = onToggle;
|
|
738
900
|
this.panelEl = createElement("div", { className: "fp-thumbnail-panel hidden" });
|
|
901
|
+
this.panelEl.style.width = "0px";
|
|
902
|
+
this.panelEl.style.minWidth = "0px";
|
|
903
|
+
this.panelEl.style.opacity = "0";
|
|
904
|
+
this.headerEl = createElement("div", { className: "fp-thumbnail-header" });
|
|
905
|
+
const title = createElement("span", { className: "fp-thumbnail-title" }, "Pages");
|
|
906
|
+
const closeBtn = createElement("button", {
|
|
907
|
+
className: "fp-thumbnail-close-btn",
|
|
908
|
+
title: "Close Thumbnails",
|
|
909
|
+
type: "button"
|
|
910
|
+
});
|
|
911
|
+
closeBtn.innerHTML = ICON_CLOSE;
|
|
912
|
+
closeBtn.addEventListener("click", (e) => {
|
|
913
|
+
e.stopPropagation();
|
|
914
|
+
this.hide();
|
|
915
|
+
});
|
|
916
|
+
this.headerEl.appendChild(title);
|
|
917
|
+
this.headerEl.appendChild(closeBtn);
|
|
918
|
+
this.listEl = createElement("div", { className: "fp-thumbnail-list" });
|
|
919
|
+
this.panelEl.appendChild(this.headerEl);
|
|
920
|
+
this.panelEl.appendChild(this.listEl);
|
|
739
921
|
this.el.appendChild(this.panelEl);
|
|
740
922
|
}
|
|
923
|
+
isOpen() {
|
|
924
|
+
return !this.panelEl.classList.contains("hidden") && this.panelEl.style.width !== "0px";
|
|
925
|
+
}
|
|
741
926
|
update(thumbnails, onSelect) {
|
|
742
927
|
this.thumbnails = thumbnails;
|
|
743
928
|
this.onSelect = onSelect;
|
|
929
|
+
this.renderedIndices.clear();
|
|
930
|
+
const titleEl = this.headerEl.querySelector(".fp-thumbnail-title");
|
|
931
|
+
if (titleEl) {
|
|
932
|
+
titleEl.textContent = `Pages (${thumbnails.length})`;
|
|
933
|
+
}
|
|
744
934
|
this.render();
|
|
935
|
+
if (this.isOpen()) {
|
|
936
|
+
this.renderAllVisible();
|
|
937
|
+
}
|
|
745
938
|
}
|
|
746
939
|
setActive(index) {
|
|
747
940
|
this.activeIndex = index;
|
|
748
|
-
const items = this.
|
|
941
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
749
942
|
items.forEach((item, i) => {
|
|
750
943
|
if (i === index) {
|
|
751
944
|
item.classList.add("active");
|
|
945
|
+
item.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
752
946
|
} else {
|
|
753
947
|
item.classList.remove("active");
|
|
754
948
|
}
|
|
@@ -756,37 +950,102 @@ var ThumbnailPanel = class {
|
|
|
756
950
|
}
|
|
757
951
|
show() {
|
|
758
952
|
this.panelEl.classList.remove("hidden");
|
|
953
|
+
this.panelEl.style.width = "200px";
|
|
954
|
+
this.panelEl.style.minWidth = "200px";
|
|
955
|
+
this.panelEl.style.opacity = "1";
|
|
956
|
+
this.panelEl.style.display = "flex";
|
|
957
|
+
this.onToggleCallback?.(true);
|
|
958
|
+
this.renderAllVisible();
|
|
759
959
|
}
|
|
760
960
|
hide() {
|
|
761
961
|
this.panelEl.classList.add("hidden");
|
|
962
|
+
this.panelEl.style.width = "0px";
|
|
963
|
+
this.panelEl.style.minWidth = "0px";
|
|
964
|
+
this.panelEl.style.opacity = "0";
|
|
965
|
+
this.onToggleCallback?.(false);
|
|
762
966
|
}
|
|
763
967
|
toggle() {
|
|
764
|
-
this.
|
|
968
|
+
if (this.isOpen()) {
|
|
969
|
+
this.hide();
|
|
970
|
+
} else {
|
|
971
|
+
this.show();
|
|
972
|
+
}
|
|
765
973
|
}
|
|
766
974
|
destroy() {
|
|
975
|
+
if (this.observer) {
|
|
976
|
+
this.observer.disconnect();
|
|
977
|
+
this.observer = void 0;
|
|
978
|
+
}
|
|
979
|
+
this.renderedIndices.clear();
|
|
767
980
|
this.el.innerHTML = "";
|
|
768
981
|
}
|
|
769
|
-
|
|
770
|
-
this.
|
|
982
|
+
renderAllVisible() {
|
|
983
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
984
|
+
items.forEach((item) => {
|
|
985
|
+
const idx = parseInt(item.dataset.thumbIndex || "-1", 10);
|
|
986
|
+
if (idx >= 0 && !this.renderedIndices.has(idx)) {
|
|
987
|
+
this.renderThumbnailItem(idx, item);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
renderThumbnailItem(idx, itemEl) {
|
|
992
|
+
if (this.renderedIndices.has(idx)) return;
|
|
993
|
+
this.renderedIndices.add(idx);
|
|
994
|
+
const canvas = itemEl.querySelector("canvas");
|
|
995
|
+
const thumb = this.thumbnails[idx];
|
|
996
|
+
if (canvas && thumb) {
|
|
997
|
+
Promise.resolve(thumb.render(canvas)).catch((err) => {
|
|
998
|
+
console.warn(`[FilePreview] Error rendering thumbnail ${idx}:`, err);
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
render() {
|
|
1003
|
+
if (this.observer) {
|
|
1004
|
+
this.observer.disconnect();
|
|
1005
|
+
}
|
|
1006
|
+
this.listEl.innerHTML = "";
|
|
1007
|
+
const useObserver = typeof IntersectionObserver !== "undefined";
|
|
1008
|
+
if (useObserver) {
|
|
1009
|
+
this.observer = new IntersectionObserver(
|
|
1010
|
+
(entries) => {
|
|
1011
|
+
for (const entry of entries) {
|
|
1012
|
+
if (entry.isIntersecting) {
|
|
1013
|
+
const target = entry.target;
|
|
1014
|
+
const idx = parseInt(target.dataset.thumbIndex || "-1", 10);
|
|
1015
|
+
if (idx >= 0) {
|
|
1016
|
+
this.renderThumbnailItem(idx, target);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
root: this.listEl,
|
|
1023
|
+
rootMargin: "120px 0px 120px 0px"
|
|
1024
|
+
}
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
771
1027
|
for (let i = 0; i < this.thumbnails.length; i++) {
|
|
772
1028
|
const thumb = this.thumbnails[i];
|
|
773
|
-
const itemEl = createElement("div", {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
1029
|
+
const itemEl = createElement("div", {
|
|
1030
|
+
className: "fp-thumbnail-item" + (i === this.activeIndex ? " active" : "")
|
|
1031
|
+
});
|
|
1032
|
+
itemEl.dataset.thumbIndex = i.toString();
|
|
777
1033
|
itemEl.addEventListener("click", () => {
|
|
778
1034
|
this.setActive(i);
|
|
779
1035
|
this.onSelect?.(i);
|
|
780
1036
|
});
|
|
781
|
-
const
|
|
782
|
-
const
|
|
783
|
-
|
|
1037
|
+
const canvasWrapper = createElement("div", { className: "fp-thumbnail-canvas-wrapper" });
|
|
1038
|
+
const canvas = createElement("canvas", { width: "130", height: "170" });
|
|
1039
|
+
canvasWrapper.appendChild(canvas);
|
|
1040
|
+
const label = createElement("span", { className: "fp-thumbnail-label" }, thumb.label || `Page ${i + 1}`);
|
|
1041
|
+
itemEl.appendChild(canvasWrapper);
|
|
784
1042
|
itemEl.appendChild(label);
|
|
785
|
-
this.
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
1043
|
+
this.listEl.appendChild(itemEl);
|
|
1044
|
+
if (this.observer) {
|
|
1045
|
+
this.observer.observe(itemEl);
|
|
1046
|
+
}
|
|
1047
|
+
if (i < 4) {
|
|
1048
|
+
this.renderThumbnailItem(i, itemEl);
|
|
790
1049
|
}
|
|
791
1050
|
}
|
|
792
1051
|
}
|
|
@@ -807,6 +1066,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
807
1066
|
currentOptions = {};
|
|
808
1067
|
resizeObserver = null;
|
|
809
1068
|
fullscreenHandler = null;
|
|
1069
|
+
titleBarEl = null;
|
|
810
1070
|
/**
|
|
811
1071
|
* Register a preview plugin.
|
|
812
1072
|
*/
|
|
@@ -843,6 +1103,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
843
1103
|
}
|
|
844
1104
|
this.currentBuffer = buffer.slice(0);
|
|
845
1105
|
this.currentMetadata = metadata;
|
|
1106
|
+
this.updateTitleBar(options, metadata);
|
|
846
1107
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
847
1108
|
const fileInfo = { metadata, buffer };
|
|
848
1109
|
const matchedPlugin = await this.findPlugin(fileInfo);
|
|
@@ -866,15 +1127,21 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
866
1127
|
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
867
1128
|
const total = payload.total ?? payload.totalPages;
|
|
868
1129
|
this.toolbar?.setPage(payload.page, total);
|
|
1130
|
+
this.thumbnailPanel?.setActive(payload.page - 1);
|
|
869
1131
|
}
|
|
870
1132
|
this.eventEmitter.emit(event, payload);
|
|
871
|
-
}
|
|
1133
|
+
},
|
|
1134
|
+
toggleThumbnails: () => this.toggleThumbnails()
|
|
872
1135
|
});
|
|
873
1136
|
this.activeInstance = instance;
|
|
874
1137
|
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
1138
|
+
instance.toggleThumbnails = () => this.toggleThumbnails();
|
|
875
1139
|
this.hideLoading();
|
|
876
1140
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
877
|
-
|
|
1141
|
+
const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
|
|
1142
|
+
if (isToolbarVisible && this.toolbar) {
|
|
1143
|
+
const toolbarConfig = this.extractToolbarConfig(options);
|
|
1144
|
+
this.toolbar.setConfig(toolbarConfig);
|
|
878
1145
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
879
1146
|
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
880
1147
|
if (!hasFullscreen && this.wrapperEl) {
|
|
@@ -924,6 +1191,12 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
924
1191
|
}
|
|
925
1192
|
});
|
|
926
1193
|
}
|
|
1194
|
+
const thumbAction = actions.find((a) => a.id === "thumbnails");
|
|
1195
|
+
if (thumbAction) {
|
|
1196
|
+
thumbAction.execute = () => {
|
|
1197
|
+
this.toggleThumbnails();
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
927
1200
|
this.toolbar.update(actions);
|
|
928
1201
|
this.toolbar.show();
|
|
929
1202
|
}
|
|
@@ -1008,7 +1281,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1008
1281
|
if (targetUrl) {
|
|
1009
1282
|
const newWin2 = window.open(targetUrl, "_blank");
|
|
1010
1283
|
if (!newWin2) {
|
|
1011
|
-
|
|
1284
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1012
1285
|
return null;
|
|
1013
1286
|
}
|
|
1014
1287
|
return newWin2;
|
|
@@ -1016,7 +1289,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1016
1289
|
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1017
1290
|
const newWin = window.open("", "_blank");
|
|
1018
1291
|
if (!newWin) {
|
|
1019
|
-
|
|
1292
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
1020
1293
|
return null;
|
|
1021
1294
|
}
|
|
1022
1295
|
newWin.document.title = title;
|
|
@@ -1093,6 +1366,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1093
1366
|
this.currentBuffer = null;
|
|
1094
1367
|
this.currentMetadata = null;
|
|
1095
1368
|
this.currentContainer = null;
|
|
1369
|
+
this.titleBarEl = null;
|
|
1096
1370
|
}
|
|
1097
1371
|
/**
|
|
1098
1372
|
* Get the currently active preview instance.
|
|
@@ -1100,7 +1374,218 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1100
1374
|
getInstance() {
|
|
1101
1375
|
return this.activeInstance;
|
|
1102
1376
|
}
|
|
1377
|
+
// --- Toolbar Configuration & Feature Toggles ---
|
|
1378
|
+
/**
|
|
1379
|
+
* Configure toolbar features dynamically through options or methods.
|
|
1380
|
+
* e.g. viewer.setToolbarConfig({ zoomIn: false, print: false })
|
|
1381
|
+
*/
|
|
1382
|
+
setToolbarConfig(config) {
|
|
1383
|
+
this.toolbar?.setConfig(config);
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Get current toolbar configuration.
|
|
1387
|
+
*/
|
|
1388
|
+
getToolbarConfig() {
|
|
1389
|
+
return this.toolbar?.getConfig() ?? {};
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Hide a specific toolbar action by ID or alias (e.g. 'zoom-in', 'print', 'download').
|
|
1393
|
+
*/
|
|
1394
|
+
hideToolbarAction(actionId) {
|
|
1395
|
+
this.toolbar?.hideAction(actionId);
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Show a specific toolbar action by ID or alias.
|
|
1399
|
+
*/
|
|
1400
|
+
showToolbarAction(actionId) {
|
|
1401
|
+
this.toolbar?.showAction(actionId);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Enable a specific toolbar action button.
|
|
1405
|
+
*/
|
|
1406
|
+
enableToolbarAction(actionId) {
|
|
1407
|
+
this.toolbar?.enableAction(actionId);
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Disable a specific toolbar action button.
|
|
1411
|
+
*/
|
|
1412
|
+
disableToolbarAction(actionId) {
|
|
1413
|
+
this.toolbar?.disableAction(actionId);
|
|
1414
|
+
}
|
|
1415
|
+
// --- Programmatic Toolbar Action Methods ---
|
|
1416
|
+
/**
|
|
1417
|
+
* Fit document to page so it fills the frame width with minimal margins.
|
|
1418
|
+
*/
|
|
1419
|
+
fitToPage() {
|
|
1420
|
+
this.activeInstance?.fitToPage?.();
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Zoom in.
|
|
1424
|
+
*/
|
|
1425
|
+
zoomIn() {
|
|
1426
|
+
this.activeInstance?.zoomIn?.();
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Zoom out.
|
|
1430
|
+
*/
|
|
1431
|
+
zoomOut() {
|
|
1432
|
+
this.activeInstance?.zoomOut?.();
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Set specific zoom level.
|
|
1436
|
+
*/
|
|
1437
|
+
setZoom(level) {
|
|
1438
|
+
this.activeInstance?.setZoom?.(level);
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Get current zoom level.
|
|
1442
|
+
*/
|
|
1443
|
+
getZoom() {
|
|
1444
|
+
return this.activeInstance?.getZoom?.() ?? 1;
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Rotate 90 degrees clockwise.
|
|
1448
|
+
*/
|
|
1449
|
+
rotateCW() {
|
|
1450
|
+
this.activeInstance?.rotateCW?.();
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Rotate 90 degrees counter-clockwise.
|
|
1454
|
+
*/
|
|
1455
|
+
rotateCCW() {
|
|
1456
|
+
this.activeInstance?.rotateCCW?.();
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Navigate to a specific page number.
|
|
1460
|
+
*/
|
|
1461
|
+
goToPage(page) {
|
|
1462
|
+
this.activeInstance?.goToPage?.(page);
|
|
1463
|
+
this.toolbar?.setPage(page);
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Navigate to next page.
|
|
1467
|
+
*/
|
|
1468
|
+
nextPage() {
|
|
1469
|
+
const cur = this.getCurrentPage();
|
|
1470
|
+
const max = this.getPageCount();
|
|
1471
|
+
if (cur < max) {
|
|
1472
|
+
this.goToPage(cur + 1);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Navigate to previous page.
|
|
1477
|
+
*/
|
|
1478
|
+
prevPage() {
|
|
1479
|
+
const cur = this.getCurrentPage();
|
|
1480
|
+
if (cur > 1) {
|
|
1481
|
+
this.goToPage(cur - 1);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Get total page count.
|
|
1486
|
+
*/
|
|
1487
|
+
getPageCount() {
|
|
1488
|
+
return this.activeInstance?.getPageCount?.() ?? 1;
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Get current page number.
|
|
1492
|
+
*/
|
|
1493
|
+
getCurrentPage() {
|
|
1494
|
+
return this.activeInstance?.getCurrentPage?.() ?? 1;
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Download the current document.
|
|
1498
|
+
*/
|
|
1499
|
+
download() {
|
|
1500
|
+
this.activeInstance?.download?.();
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Print the current document.
|
|
1504
|
+
*/
|
|
1505
|
+
print() {
|
|
1506
|
+
this.activeInstance?.print?.();
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Toggle fullscreen mode.
|
|
1510
|
+
*/
|
|
1511
|
+
toggleFullscreen() {
|
|
1512
|
+
try {
|
|
1513
|
+
if (!document.fullscreenElement) {
|
|
1514
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
1515
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
1516
|
+
} else {
|
|
1517
|
+
document.exitFullscreen?.();
|
|
1518
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
1519
|
+
}
|
|
1520
|
+
} catch {
|
|
1521
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
1522
|
+
}
|
|
1523
|
+
setTimeout(() => {
|
|
1524
|
+
this.activeInstance?.fitToPage?.();
|
|
1525
|
+
}, 120);
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Toggle thumbnails sidebar panel.
|
|
1529
|
+
*/
|
|
1530
|
+
toggleThumbnails() {
|
|
1531
|
+
if (!this.thumbnailPanel) return;
|
|
1532
|
+
this.thumbnailPanel.toggle();
|
|
1533
|
+
const isOpen = this.thumbnailPanel.isOpen();
|
|
1534
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1535
|
+
setTimeout(() => {
|
|
1536
|
+
this.activeInstance?.fitToPage?.();
|
|
1537
|
+
}, 260);
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Set whether to display the file name / title bar above the toolbar.
|
|
1541
|
+
*/
|
|
1542
|
+
setShowFileName(show) {
|
|
1543
|
+
if (this.currentOptions) {
|
|
1544
|
+
this.currentOptions.showFileName = show;
|
|
1545
|
+
}
|
|
1546
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1547
|
+
}
|
|
1548
|
+
/**
|
|
1549
|
+
* Set or override the displayed file name in the preview panel.
|
|
1550
|
+
*/
|
|
1551
|
+
setFileName(name) {
|
|
1552
|
+
if (this.currentOptions) {
|
|
1553
|
+
this.currentOptions.fileName = name;
|
|
1554
|
+
}
|
|
1555
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1556
|
+
}
|
|
1103
1557
|
// --- Private methods ---
|
|
1558
|
+
updateTitleBar(options, metadata) {
|
|
1559
|
+
if (!this.titleBarEl) return;
|
|
1560
|
+
const show = options?.showFileName !== false;
|
|
1561
|
+
if (!show) {
|
|
1562
|
+
this.titleBarEl.style.display = "none";
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
const name = options?.fileName || metadata?.name || this.currentMetadata?.name || "";
|
|
1566
|
+
if (!name) {
|
|
1567
|
+
this.titleBarEl.style.display = "none";
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
this.titleBarEl.style.display = "flex";
|
|
1571
|
+
const ext = metadata?.extension || (name.includes(".") ? "." + name.split(".").pop() : "");
|
|
1572
|
+
const badge = ext ? ext.replace(".", "").toUpperCase() : "";
|
|
1573
|
+
this.titleBarEl.innerHTML = `
|
|
1574
|
+
<div class="fp-titlebar-info">
|
|
1575
|
+
<span class="fp-titlebar-icon">\u{1F4C4}</span>
|
|
1576
|
+
<span class="fp-titlebar-name" title="${name}">${name}</span>
|
|
1577
|
+
${badge ? `<span class="fp-titlebar-badge">${badge}</span>` : ""}
|
|
1578
|
+
</div>
|
|
1579
|
+
`;
|
|
1580
|
+
}
|
|
1581
|
+
extractToolbarConfig(options) {
|
|
1582
|
+
if (!options) return {};
|
|
1583
|
+
const nested = typeof options.toolbar === "object" ? options.toolbar : {};
|
|
1584
|
+
return {
|
|
1585
|
+
...options,
|
|
1586
|
+
...nested
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1104
1589
|
abort() {
|
|
1105
1590
|
if (this.abortController) {
|
|
1106
1591
|
this.abortController.abort();
|
|
@@ -1143,17 +1628,29 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1143
1628
|
bodyEl.className = "fp-body";
|
|
1144
1629
|
bodyEl.appendChild(thumbnailEl);
|
|
1145
1630
|
bodyEl.appendChild(this.contentEl);
|
|
1631
|
+
const titleBarEl = document.createElement("div");
|
|
1632
|
+
titleBarEl.className = "fp-titlebar";
|
|
1633
|
+
this.titleBarEl = titleBarEl;
|
|
1634
|
+
this.updateTitleBar(options, this.currentMetadata);
|
|
1146
1635
|
if (toolbarPos === "top") {
|
|
1636
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1147
1637
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1148
1638
|
this.wrapperEl.appendChild(bodyEl);
|
|
1149
1639
|
} else {
|
|
1640
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1150
1641
|
this.wrapperEl.appendChild(bodyEl);
|
|
1151
1642
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1152
1643
|
}
|
|
1153
1644
|
container.innerHTML = "";
|
|
1154
1645
|
container.appendChild(this.wrapperEl);
|
|
1155
|
-
|
|
1156
|
-
this.
|
|
1646
|
+
const initialToolbarConfig = this.extractToolbarConfig(options);
|
|
1647
|
+
this.toolbar = new ToolbarController(toolbarEl, initialToolbarConfig);
|
|
1648
|
+
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl, (isOpen) => {
|
|
1649
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1650
|
+
setTimeout(() => {
|
|
1651
|
+
this.activeInstance?.fitToPage?.();
|
|
1652
|
+
}, 260);
|
|
1653
|
+
});
|
|
1157
1654
|
this.setupKeyboardShortcuts();
|
|
1158
1655
|
this.setupDragAndDrop(container, options);
|
|
1159
1656
|
this.setupResizeAndFullscreenListeners();
|
|
@@ -1543,6 +2040,14 @@ var PdfPlugin = class {
|
|
|
1543
2040
|
group: "zoom",
|
|
1544
2041
|
execute: () => instance.fitToPage?.()
|
|
1545
2042
|
},
|
|
2043
|
+
{
|
|
2044
|
+
id: "fit-width",
|
|
2045
|
+
icon: "fit-width",
|
|
2046
|
+
label: "Fit to Width",
|
|
2047
|
+
type: "button",
|
|
2048
|
+
group: "zoom",
|
|
2049
|
+
execute: () => instance.fitToWidth?.()
|
|
2050
|
+
},
|
|
1546
2051
|
{
|
|
1547
2052
|
id: "rotate-cw",
|
|
1548
2053
|
icon: "rotate-cw",
|
|
@@ -1551,6 +2056,14 @@ var PdfPlugin = class {
|
|
|
1551
2056
|
group: "view",
|
|
1552
2057
|
execute: () => instance.rotateCW?.()
|
|
1553
2058
|
},
|
|
2059
|
+
{
|
|
2060
|
+
id: "rotate-ccw",
|
|
2061
|
+
icon: "rotate-ccw",
|
|
2062
|
+
label: "Rotate Counter-Clockwise",
|
|
2063
|
+
type: "button",
|
|
2064
|
+
group: "view",
|
|
2065
|
+
execute: () => instance.rotateCCW?.()
|
|
2066
|
+
},
|
|
1554
2067
|
{
|
|
1555
2068
|
id: "download",
|
|
1556
2069
|
icon: "download",
|
|
@@ -1582,12 +2095,13 @@ var PdfPlugin = class {
|
|
|
1582
2095
|
container.className = "fp-pdf-container";
|
|
1583
2096
|
container.style.width = "100%";
|
|
1584
2097
|
container.style.height = "100%";
|
|
1585
|
-
container.style.
|
|
2098
|
+
container.style.overflowX = "hidden";
|
|
2099
|
+
container.style.overflowY = "auto";
|
|
1586
2100
|
container.style.display = "flex";
|
|
1587
2101
|
container.style.flexDirection = "column";
|
|
1588
2102
|
container.style.alignItems = "center";
|
|
1589
2103
|
container.style.justifyContent = "flex-start";
|
|
1590
|
-
container.style.padding = "
|
|
2104
|
+
container.style.padding = "16px 8px";
|
|
1591
2105
|
container.style.backgroundColor = "#0f172a";
|
|
1592
2106
|
container.style.boxSizing = "border-box";
|
|
1593
2107
|
container.style.position = "relative";
|
|
@@ -1598,30 +2112,12 @@ var PdfPlugin = class {
|
|
|
1598
2112
|
pageCard.style.borderRadius = "4px";
|
|
1599
2113
|
pageCard.style.overflow = "hidden";
|
|
1600
2114
|
pageCard.style.lineHeight = "0";
|
|
1601
|
-
pageCard.style.transition = "transform 0.15s ease";
|
|
1602
2115
|
pageCard.style.position = "relative";
|
|
1603
2116
|
pageCard.style.flexShrink = "0";
|
|
2117
|
+
pageCard.style.transition = "box-shadow 0.2s ease";
|
|
1604
2118
|
let canvas = document.createElement("canvas");
|
|
1605
2119
|
pageCard.appendChild(canvas);
|
|
1606
2120
|
container.appendChild(pageCard);
|
|
1607
|
-
const indicator = document.createElement("div");
|
|
1608
|
-
indicator.className = "fp-pdf-page-indicator";
|
|
1609
|
-
indicator.style.position = "sticky";
|
|
1610
|
-
indicator.style.bottom = "16px";
|
|
1611
|
-
indicator.style.marginTop = "16px";
|
|
1612
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1613
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
1614
|
-
indicator.style.color = "#f8fafc";
|
|
1615
|
-
indicator.style.fontSize = "12px";
|
|
1616
|
-
indicator.style.fontWeight = "600";
|
|
1617
|
-
indicator.style.padding = "5px 14px";
|
|
1618
|
-
indicator.style.borderRadius = "20px";
|
|
1619
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1620
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1621
|
-
indicator.style.zIndex = "10";
|
|
1622
|
-
indicator.style.userSelect = "none";
|
|
1623
|
-
indicator.style.pointerEvents = "none";
|
|
1624
|
-
container.appendChild(indicator);
|
|
1625
2121
|
ctx.container.appendChild(container);
|
|
1626
2122
|
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1627
2123
|
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
@@ -1637,8 +2133,9 @@ var PdfPlugin = class {
|
|
|
1637
2133
|
let currentPage = 1;
|
|
1638
2134
|
let zoomScale = 1;
|
|
1639
2135
|
let rotation = 0;
|
|
1640
|
-
let fitMode = "
|
|
2136
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
1641
2137
|
let currentRenderTask = null;
|
|
2138
|
+
let textLayerDiv = null;
|
|
1642
2139
|
const renderPage = async (pageNum) => {
|
|
1643
2140
|
if (currentRenderTask) {
|
|
1644
2141
|
try {
|
|
@@ -1650,30 +2147,37 @@ var PdfPlugin = class {
|
|
|
1650
2147
|
const newCanvas = document.createElement("canvas");
|
|
1651
2148
|
pageCard.replaceChild(newCanvas, canvas);
|
|
1652
2149
|
canvas = newCanvas;
|
|
2150
|
+
if (textLayerDiv) {
|
|
2151
|
+
textLayerDiv.remove();
|
|
2152
|
+
textLayerDiv = null;
|
|
2153
|
+
}
|
|
1653
2154
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1654
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1655
2155
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1656
2156
|
const page = await pdfDoc.getPage(currentPage);
|
|
1657
2157
|
const containerWidth = container.clientWidth || 900;
|
|
1658
2158
|
const containerHeight = container.clientHeight || 700;
|
|
1659
2159
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1660
|
-
const availWidth = Math.max(
|
|
1661
|
-
const availHeight = Math.max(
|
|
2160
|
+
const availWidth = Math.max(280, containerWidth - 36);
|
|
2161
|
+
const availHeight = Math.max(280, containerHeight - 32);
|
|
1662
2162
|
const scaleW = availWidth / unscaledVp.width;
|
|
1663
2163
|
const scaleH = availHeight / unscaledVp.height;
|
|
1664
2164
|
let fitScale;
|
|
1665
2165
|
if (fitMode === "page") {
|
|
1666
|
-
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
2166
|
+
fitScale = Math.max(0.2, Math.min(4, Math.min(scaleW, scaleH)));
|
|
1667
2167
|
} else {
|
|
1668
|
-
fitScale = Math.max(0.
|
|
2168
|
+
fitScale = Math.max(0.2, Math.min(4, scaleW));
|
|
1669
2169
|
}
|
|
1670
2170
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1671
2171
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1672
2172
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
2173
|
+
const displayWidth = Math.floor(viewport.width);
|
|
2174
|
+
const displayHeight = Math.floor(viewport.height);
|
|
1673
2175
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1674
2176
|
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1675
|
-
canvas.style.width = `${
|
|
1676
|
-
canvas.style.height = `${
|
|
2177
|
+
canvas.style.width = `${displayWidth}px`;
|
|
2178
|
+
canvas.style.height = `${displayHeight}px`;
|
|
2179
|
+
pageCard.style.width = `${displayWidth}px`;
|
|
2180
|
+
pageCard.style.height = `${displayHeight}px`;
|
|
1677
2181
|
const canvasCtx = canvas.getContext("2d");
|
|
1678
2182
|
if (!canvasCtx) return;
|
|
1679
2183
|
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
@@ -1687,9 +2191,31 @@ var PdfPlugin = class {
|
|
|
1687
2191
|
if (err?.name !== "RenderingCancelledException") {
|
|
1688
2192
|
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1689
2193
|
}
|
|
2194
|
+
return;
|
|
1690
2195
|
} finally {
|
|
1691
2196
|
currentRenderTask = null;
|
|
1692
2197
|
}
|
|
2198
|
+
try {
|
|
2199
|
+
textLayerDiv = document.createElement("div");
|
|
2200
|
+
textLayerDiv.className = "textLayer";
|
|
2201
|
+
textLayerDiv.style.width = `${displayWidth}px`;
|
|
2202
|
+
textLayerDiv.style.height = `${displayHeight}px`;
|
|
2203
|
+
textLayerDiv.style.position = "absolute";
|
|
2204
|
+
textLayerDiv.style.top = "0";
|
|
2205
|
+
textLayerDiv.style.left = "0";
|
|
2206
|
+
textLayerDiv.style.lineHeight = "1";
|
|
2207
|
+
pageCard.appendChild(textLayerDiv);
|
|
2208
|
+
if (pdfjsLib.TextLayer) {
|
|
2209
|
+
const textLayer = new pdfjsLib.TextLayer({
|
|
2210
|
+
textContentSource: page.streamTextContent(),
|
|
2211
|
+
container: textLayerDiv,
|
|
2212
|
+
viewport
|
|
2213
|
+
});
|
|
2214
|
+
await textLayer.render();
|
|
2215
|
+
}
|
|
2216
|
+
} catch (err) {
|
|
2217
|
+
console.debug("[PdfPlugin] TextLayer notice:", err);
|
|
2218
|
+
}
|
|
1693
2219
|
};
|
|
1694
2220
|
renderPage(1);
|
|
1695
2221
|
let resizeTimer = null;
|
|
@@ -1699,11 +2225,48 @@ var PdfPlugin = class {
|
|
|
1699
2225
|
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1700
2226
|
renderPage(currentPage);
|
|
1701
2227
|
}
|
|
1702
|
-
},
|
|
2228
|
+
}, 120);
|
|
1703
2229
|
});
|
|
1704
2230
|
resizeObserver.observe(container);
|
|
2231
|
+
const onWheel = (e) => {
|
|
2232
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2233
|
+
e.preventDefault();
|
|
2234
|
+
const delta = e.deltaY > 0 ? -0.15 : 0.15;
|
|
2235
|
+
zoomScale = Math.max(0.25, Math.min(4, Math.round((zoomScale + delta) * 100) / 100));
|
|
2236
|
+
renderPage(currentPage);
|
|
2237
|
+
}
|
|
2238
|
+
};
|
|
2239
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
2240
|
+
const onKeyDown = (e) => {
|
|
2241
|
+
const tag = e.target?.tagName?.toLowerCase();
|
|
2242
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
2243
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
2244
|
+
if (currentPage < totalPages) {
|
|
2245
|
+
e.preventDefault();
|
|
2246
|
+
container.scrollTop = 0;
|
|
2247
|
+
renderPage(currentPage + 1);
|
|
2248
|
+
}
|
|
2249
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
2250
|
+
if (currentPage > 1) {
|
|
2251
|
+
e.preventDefault();
|
|
2252
|
+
container.scrollTop = 0;
|
|
2253
|
+
renderPage(currentPage - 1);
|
|
2254
|
+
}
|
|
2255
|
+
} else if (e.key === "Home") {
|
|
2256
|
+
e.preventDefault();
|
|
2257
|
+
container.scrollTop = 0;
|
|
2258
|
+
renderPage(1);
|
|
2259
|
+
} else if (e.key === "End") {
|
|
2260
|
+
e.preventDefault();
|
|
2261
|
+
container.scrollTop = 0;
|
|
2262
|
+
renderPage(totalPages);
|
|
2263
|
+
}
|
|
2264
|
+
};
|
|
2265
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1705
2266
|
const cleanup = () => {
|
|
1706
2267
|
resizeObserver.disconnect();
|
|
2268
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2269
|
+
container.removeEventListener("wheel", onWheel);
|
|
1707
2270
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1708
2271
|
if (currentRenderTask) {
|
|
1709
2272
|
try {
|
|
@@ -1722,22 +2285,26 @@ var PdfPlugin = class {
|
|
|
1722
2285
|
const instance = {
|
|
1723
2286
|
destroy: cleanup,
|
|
1724
2287
|
zoomIn: () => {
|
|
1725
|
-
zoomScale = Math.min(
|
|
2288
|
+
zoomScale = Math.min(4, Math.round((zoomScale + 0.2) * 10) / 10);
|
|
1726
2289
|
renderPage(currentPage);
|
|
1727
2290
|
},
|
|
1728
2291
|
zoomOut: () => {
|
|
1729
|
-
zoomScale = Math.max(0.
|
|
2292
|
+
zoomScale = Math.max(0.25, Math.round((zoomScale - 0.2) * 10) / 10);
|
|
1730
2293
|
renderPage(currentPage);
|
|
1731
2294
|
},
|
|
1732
2295
|
getZoom: () => zoomScale,
|
|
1733
2296
|
setZoom: (level) => {
|
|
1734
|
-
zoomScale = Math.max(0.
|
|
2297
|
+
zoomScale = Math.max(0.25, Math.min(4, level));
|
|
1735
2298
|
renderPage(currentPage);
|
|
1736
2299
|
},
|
|
1737
2300
|
fitToPage: () => {
|
|
1738
|
-
fitMode =
|
|
2301
|
+
fitMode = "page";
|
|
2302
|
+
zoomScale = 1;
|
|
2303
|
+
renderPage(currentPage);
|
|
2304
|
+
},
|
|
2305
|
+
fitToWidth: () => {
|
|
2306
|
+
fitMode = "width";
|
|
1739
2307
|
zoomScale = 1;
|
|
1740
|
-
rotation = 0;
|
|
1741
2308
|
renderPage(currentPage);
|
|
1742
2309
|
},
|
|
1743
2310
|
rotateCW: () => {
|
|
@@ -1755,6 +2322,9 @@ var PdfPlugin = class {
|
|
|
1755
2322
|
container.scrollTop = 0;
|
|
1756
2323
|
renderPage(page);
|
|
1757
2324
|
},
|
|
2325
|
+
toggleThumbnails: () => {
|
|
2326
|
+
ctx?.toggleThumbnails?.();
|
|
2327
|
+
},
|
|
1758
2328
|
download: () => {
|
|
1759
2329
|
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1760
2330
|
const url = URL.createObjectURL(blob);
|
|
@@ -1788,7 +2358,7 @@ var PdfPlugin = class {
|
|
|
1788
2358
|
},
|
|
1789
2359
|
getThumbnails: async () => {
|
|
1790
2360
|
const thumbnails = [];
|
|
1791
|
-
const count =
|
|
2361
|
+
const count = totalPages;
|
|
1792
2362
|
for (let i = 1; i <= count; i++) {
|
|
1793
2363
|
thumbnails.push({
|
|
1794
2364
|
index: i,
|
|
@@ -1796,9 +2366,10 @@ var PdfPlugin = class {
|
|
|
1796
2366
|
render: async (thumbCanvas) => {
|
|
1797
2367
|
try {
|
|
1798
2368
|
const p = await pdfDoc.getPage(i);
|
|
1799
|
-
const baseVp = p.getViewport({ scale: 1 });
|
|
1800
|
-
const
|
|
1801
|
-
const
|
|
2369
|
+
const baseVp = p.getViewport({ scale: 1, rotation });
|
|
2370
|
+
const targetW = thumbCanvas.width || 130;
|
|
2371
|
+
const thumbScale = targetW / baseVp.width;
|
|
2372
|
+
const thumbVp = p.getViewport({ scale: thumbScale, rotation });
|
|
1802
2373
|
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1803
2374
|
const tCtx = thumbCanvas.getContext("2d");
|
|
1804
2375
|
if (tCtx) {
|
|
@@ -2142,28 +2713,26 @@ var DocxPlugin = class {
|
|
|
2142
2713
|
getToolbarActions(instance) {
|
|
2143
2714
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2144
2715
|
const actions = [];
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
if (
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
instance.goToPage?.(page);
|
|
2163
|
-
}
|
|
2716
|
+
actions.push({
|
|
2717
|
+
id: "page-nav",
|
|
2718
|
+
icon: "",
|
|
2719
|
+
label: "Page Navigation",
|
|
2720
|
+
type: "page-nav",
|
|
2721
|
+
group: "navigation",
|
|
2722
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2723
|
+
max: totalPages,
|
|
2724
|
+
execute: (action, page) => {
|
|
2725
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2726
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2727
|
+
if (action === "prev") {
|
|
2728
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2729
|
+
} else if (action === "next") {
|
|
2730
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2731
|
+
} else if (typeof page === "number") {
|
|
2732
|
+
instance.goToPage?.(page);
|
|
2164
2733
|
}
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2734
|
+
}
|
|
2735
|
+
});
|
|
2167
2736
|
actions.push(
|
|
2168
2737
|
{
|
|
2169
2738
|
id: "zoom-out",
|
|
@@ -2229,11 +2798,17 @@ var DocxPlugin = class {
|
|
|
2229
2798
|
wrapper.className = "fp-docx-wrapper";
|
|
2230
2799
|
wrapper.style.transformOrigin = "top center";
|
|
2231
2800
|
wrapper.style.transition = "transform 0.2s ease";
|
|
2232
|
-
wrapper.style.padding = "
|
|
2233
|
-
wrapper.style.maxWidth = "
|
|
2801
|
+
wrapper.style.padding = "0";
|
|
2802
|
+
wrapper.style.maxWidth = "none";
|
|
2803
|
+
wrapper.style.width = "816px";
|
|
2234
2804
|
wrapper.style.margin = "0 auto";
|
|
2805
|
+
wrapper.style.display = "flex";
|
|
2806
|
+
wrapper.style.flexDirection = "column";
|
|
2807
|
+
wrapper.style.alignItems = "center";
|
|
2235
2808
|
wrapper.style.boxSizing = "border-box";
|
|
2236
|
-
ctx.container.style.
|
|
2809
|
+
ctx.container.style.overflowX = "hidden";
|
|
2810
|
+
ctx.container.style.overflowY = "auto";
|
|
2811
|
+
ctx.container.style.padding = "16px 8px";
|
|
2237
2812
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
2238
2813
|
ctx.container.appendChild(wrapper);
|
|
2239
2814
|
const styleOverride = document.createElement("style");
|
|
@@ -2407,39 +2982,13 @@ var DocxPlugin = class {
|
|
|
2407
2982
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2408
2983
|
const totalPages = Math.max(1, pageElements.length);
|
|
2409
2984
|
let currentPage = 1;
|
|
2410
|
-
let indicator = null;
|
|
2411
|
-
if (totalPages > 1) {
|
|
2412
|
-
indicator = document.createElement("div");
|
|
2413
|
-
indicator.className = "fp-docx-page-indicator";
|
|
2414
|
-
indicator.style.position = "sticky";
|
|
2415
|
-
indicator.style.bottom = "16px";
|
|
2416
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2417
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
2418
|
-
indicator.style.color = "#f8fafc";
|
|
2419
|
-
indicator.style.fontSize = "12px";
|
|
2420
|
-
indicator.style.fontWeight = "600";
|
|
2421
|
-
indicator.style.padding = "5px 14px";
|
|
2422
|
-
indicator.style.borderRadius = "20px";
|
|
2423
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2424
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2425
|
-
indicator.style.zIndex = "10";
|
|
2426
|
-
indicator.style.userSelect = "none";
|
|
2427
|
-
indicator.style.pointerEvents = "none";
|
|
2428
|
-
indicator.style.textAlign = "center";
|
|
2429
|
-
indicator.style.width = "fit-content";
|
|
2430
|
-
indicator.style.margin = "16px auto 0";
|
|
2431
|
-
ctx.container.appendChild(indicator);
|
|
2432
|
-
}
|
|
2433
2985
|
const showPage = (pageNum) => {
|
|
2434
2986
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2435
2987
|
if (pageElements.length > 1) {
|
|
2436
2988
|
pageElements.forEach((sec, idx) => {
|
|
2437
|
-
sec.style.display = idx + 1 === currentPage ? "
|
|
2989
|
+
sec.style.display = idx + 1 === currentPage ? "" : "none";
|
|
2438
2990
|
});
|
|
2439
2991
|
}
|
|
2440
|
-
if (indicator) {
|
|
2441
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2442
|
-
}
|
|
2443
2992
|
ctx.container.scrollTop = 0;
|
|
2444
2993
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2445
2994
|
};
|
|
@@ -2448,31 +2997,46 @@ var DocxPlugin = class {
|
|
|
2448
2997
|
}
|
|
2449
2998
|
scale = 1;
|
|
2450
2999
|
let rotation = 0;
|
|
2451
|
-
let fitMode = "
|
|
2452
|
-
|
|
2453
|
-
|
|
3000
|
+
let fitMode = "page";
|
|
3001
|
+
let isUserZoomed = false;
|
|
3002
|
+
const calculateFitScale = (_mode = fitMode) => {
|
|
3003
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2454
3004
|
const elW = activeEl.offsetWidth || 816;
|
|
2455
|
-
const
|
|
2456
|
-
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2457
|
-
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
3005
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
2458
3006
|
const sW = availW / elW;
|
|
2459
|
-
|
|
2460
|
-
if (mode === "page") {
|
|
2461
|
-
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2462
|
-
}
|
|
2463
|
-
return Math.max(0.65, Math.min(1.05, sW));
|
|
3007
|
+
return Math.max(0.35, Math.min(3, sW));
|
|
2464
3008
|
};
|
|
2465
3009
|
const applyTransform = () => {
|
|
2466
3010
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2467
3011
|
wrapper.style.transformOrigin = "top center";
|
|
3012
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
3013
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
3014
|
+
if (scale > 1) {
|
|
3015
|
+
wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
|
|
3016
|
+
} else {
|
|
3017
|
+
wrapper.style.marginBottom = "32px";
|
|
3018
|
+
}
|
|
2468
3019
|
};
|
|
3020
|
+
let resizeObserver = null;
|
|
3021
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
3022
|
+
resizeObserver = new ResizeObserver(() => {
|
|
3023
|
+
if (!isUserZoomed) {
|
|
3024
|
+
const newFit = calculateFitScale("page");
|
|
3025
|
+
if (Math.abs(scale - newFit) > 0.015) {
|
|
3026
|
+
scale = newFit;
|
|
3027
|
+
applyTransform();
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
});
|
|
3031
|
+
resizeObserver.observe(ctx.container);
|
|
3032
|
+
}
|
|
2469
3033
|
setTimeout(() => {
|
|
2470
|
-
|
|
2471
|
-
scale = calculateFitScale("width");
|
|
3034
|
+
scale = calculateFitScale("page");
|
|
2472
3035
|
applyTransform();
|
|
2473
|
-
},
|
|
3036
|
+
}, 40);
|
|
2474
3037
|
const cleanup = () => {
|
|
2475
|
-
|
|
3038
|
+
resizeObserver?.disconnect();
|
|
3039
|
+
resizeObserver = null;
|
|
2476
3040
|
for (const url of createdBlobUrls) {
|
|
2477
3041
|
URL.revokeObjectURL(url);
|
|
2478
3042
|
}
|
|
@@ -2489,21 +3053,24 @@ var DocxPlugin = class {
|
|
|
2489
3053
|
showPage(page);
|
|
2490
3054
|
},
|
|
2491
3055
|
zoomIn: () => {
|
|
2492
|
-
|
|
3056
|
+
isUserZoomed = true;
|
|
3057
|
+
scale = Math.min(3.5, scale + 0.15);
|
|
2493
3058
|
applyTransform();
|
|
2494
3059
|
},
|
|
2495
3060
|
zoomOut: () => {
|
|
3061
|
+
isUserZoomed = true;
|
|
2496
3062
|
scale = Math.max(0.2, scale - 0.15);
|
|
2497
3063
|
applyTransform();
|
|
2498
3064
|
},
|
|
2499
3065
|
getZoom: () => scale,
|
|
2500
3066
|
setZoom: (level) => {
|
|
3067
|
+
isUserZoomed = true;
|
|
2501
3068
|
scale = level;
|
|
2502
3069
|
applyTransform();
|
|
2503
3070
|
},
|
|
2504
3071
|
fitToPage: () => {
|
|
2505
|
-
|
|
2506
|
-
scale = calculateFitScale(
|
|
3072
|
+
isUserZoomed = false;
|
|
3073
|
+
scale = calculateFitScale("page");
|
|
2507
3074
|
rotation = 0;
|
|
2508
3075
|
applyTransform();
|
|
2509
3076
|
},
|
|
@@ -2893,7 +3460,7 @@ var ExcelPlugin = class {
|
|
|
2893
3460
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
2894
3461
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
2895
3462
|
];
|
|
2896
|
-
weight =
|
|
3463
|
+
weight = 85;
|
|
2897
3464
|
supports(file) {
|
|
2898
3465
|
const ext = file.metadata.extension?.toLowerCase();
|
|
2899
3466
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
@@ -2905,6 +3472,14 @@ var ExcelPlugin = class {
|
|
|
2905
3472
|
getToolbarActions(instance) {
|
|
2906
3473
|
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2907
3474
|
const actions = [];
|
|
3475
|
+
actions.push({
|
|
3476
|
+
id: "thumbnails",
|
|
3477
|
+
icon: "thumbnails",
|
|
3478
|
+
label: "Sheet Thumbnails",
|
|
3479
|
+
type: "button",
|
|
3480
|
+
group: "navigation",
|
|
3481
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3482
|
+
});
|
|
2908
3483
|
if (totalSheets > 1) {
|
|
2909
3484
|
actions.push({
|
|
2910
3485
|
id: "page-nav",
|
|
@@ -2987,6 +3562,16 @@ var ExcelPlugin = class {
|
|
|
2987
3562
|
execute: () => {
|
|
2988
3563
|
instance.print?.();
|
|
2989
3564
|
}
|
|
3565
|
+
},
|
|
3566
|
+
{
|
|
3567
|
+
id: "open-window",
|
|
3568
|
+
icon: "open-window",
|
|
3569
|
+
label: "Open in Separate Full Window",
|
|
3570
|
+
type: "button",
|
|
3571
|
+
group: "actions",
|
|
3572
|
+
execute: () => {
|
|
3573
|
+
instance.openInSeparateWindow?.();
|
|
3574
|
+
}
|
|
2990
3575
|
}
|
|
2991
3576
|
);
|
|
2992
3577
|
return actions;
|
|
@@ -3152,6 +3737,63 @@ var ExcelPlugin = class {
|
|
|
3152
3737
|
},
|
|
3153
3738
|
getPageCount: () => sheetNames.length,
|
|
3154
3739
|
getCurrentPage: () => currentSheetIndex,
|
|
3740
|
+
getThumbnails: () => {
|
|
3741
|
+
return sheetNames.map((name, idx) => ({
|
|
3742
|
+
index: idx,
|
|
3743
|
+
label: name,
|
|
3744
|
+
render: async (canvas) => {
|
|
3745
|
+
canvas.width = 140;
|
|
3746
|
+
canvas.height = 100;
|
|
3747
|
+
const c = canvas.getContext("2d");
|
|
3748
|
+
if (!c) return;
|
|
3749
|
+
c.fillStyle = "#ffffff";
|
|
3750
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3751
|
+
c.fillStyle = "#107c41";
|
|
3752
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3753
|
+
c.fillStyle = "#ffffff";
|
|
3754
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
3755
|
+
c.fillText(`\u{1F4CA} ${name.slice(0, 16)}`, 6, 11);
|
|
3756
|
+
const startY = 17;
|
|
3757
|
+
const rowH = 13;
|
|
3758
|
+
const colW = 30;
|
|
3759
|
+
const colHeaders = ["A", "B", "C", "D"];
|
|
3760
|
+
c.fillStyle = "#f1f5f9";
|
|
3761
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3762
|
+
c.strokeStyle = "#cbd5e1";
|
|
3763
|
+
c.lineWidth = 0.8;
|
|
3764
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3765
|
+
c.fillStyle = "#64748b";
|
|
3766
|
+
c.font = "bold 7px sans-serif";
|
|
3767
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3768
|
+
c.fillText(colHeaders[ci], 14 + ci * colW, startY + 9);
|
|
3769
|
+
}
|
|
3770
|
+
const ws = wb?.Sheets[name];
|
|
3771
|
+
for (let ri = 1; ri <= 5; ri++) {
|
|
3772
|
+
const y = startY + ri * rowH;
|
|
3773
|
+
if (y > canvas.height - 2) break;
|
|
3774
|
+
c.fillStyle = "#f8fafc";
|
|
3775
|
+
c.fillRect(0, y, 12, rowH);
|
|
3776
|
+
c.fillStyle = "#94a3b8";
|
|
3777
|
+
c.font = "6px sans-serif";
|
|
3778
|
+
c.fillText(String(ri), 3, y + 9);
|
|
3779
|
+
c.strokeStyle = "#e2e8f0";
|
|
3780
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3781
|
+
c.fillStyle = "#334155";
|
|
3782
|
+
c.font = "6px sans-serif";
|
|
3783
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3784
|
+
const cellRef = `${colHeaders[ci]}${ri}`;
|
|
3785
|
+
const cellVal = ws?.[cellRef]?.w || ws?.[cellRef]?.v;
|
|
3786
|
+
if (cellVal !== void 0) {
|
|
3787
|
+
c.fillText(String(cellVal).slice(0, 6), 14 + ci * colW, y + 9);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
c.strokeStyle = "#cbd5e1";
|
|
3792
|
+
c.lineWidth = 1;
|
|
3793
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
3794
|
+
}
|
|
3795
|
+
}));
|
|
3796
|
+
},
|
|
3155
3797
|
download: () => {
|
|
3156
3798
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
3157
3799
|
const url = URL.createObjectURL(blob);
|
|
@@ -3184,7 +3826,39 @@ var CsvPlugin = class {
|
|
|
3184
3826
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3185
3827
|
}
|
|
3186
3828
|
getToolbarActions(instance) {
|
|
3187
|
-
|
|
3829
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3830
|
+
const actions = [];
|
|
3831
|
+
actions.push({
|
|
3832
|
+
id: "thumbnails",
|
|
3833
|
+
icon: "thumbnails",
|
|
3834
|
+
label: "Page Thumbnails",
|
|
3835
|
+
type: "button",
|
|
3836
|
+
group: "navigation",
|
|
3837
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3838
|
+
});
|
|
3839
|
+
if (totalPages > 1) {
|
|
3840
|
+
actions.push({
|
|
3841
|
+
id: "page-nav",
|
|
3842
|
+
icon: "",
|
|
3843
|
+
label: "Page Navigation",
|
|
3844
|
+
type: "page-nav",
|
|
3845
|
+
group: "navigation",
|
|
3846
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3847
|
+
max: totalPages,
|
|
3848
|
+
execute: (action, page) => {
|
|
3849
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3850
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3851
|
+
if (action === "prev") {
|
|
3852
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3853
|
+
} else if (action === "next") {
|
|
3854
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3855
|
+
} else if (typeof page === "number") {
|
|
3856
|
+
instance.goToPage?.(page);
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
});
|
|
3860
|
+
}
|
|
3861
|
+
actions.push(
|
|
3188
3862
|
{
|
|
3189
3863
|
id: "zoom-out",
|
|
3190
3864
|
icon: "zoom-out",
|
|
@@ -3205,6 +3879,16 @@ var CsvPlugin = class {
|
|
|
3205
3879
|
instance.zoomIn?.();
|
|
3206
3880
|
}
|
|
3207
3881
|
},
|
|
3882
|
+
{
|
|
3883
|
+
id: "fit-page",
|
|
3884
|
+
icon: "fit-page",
|
|
3885
|
+
label: "Fit to View",
|
|
3886
|
+
type: "button",
|
|
3887
|
+
group: "zoom",
|
|
3888
|
+
execute: () => {
|
|
3889
|
+
instance.fitToPage?.();
|
|
3890
|
+
}
|
|
3891
|
+
},
|
|
3208
3892
|
{
|
|
3209
3893
|
id: "download",
|
|
3210
3894
|
icon: "download",
|
|
@@ -3224,8 +3908,19 @@ var CsvPlugin = class {
|
|
|
3224
3908
|
execute: () => {
|
|
3225
3909
|
instance.print?.();
|
|
3226
3910
|
}
|
|
3911
|
+
},
|
|
3912
|
+
{
|
|
3913
|
+
id: "open-window",
|
|
3914
|
+
icon: "open-window",
|
|
3915
|
+
label: "Open in Separate Full Window",
|
|
3916
|
+
type: "button",
|
|
3917
|
+
group: "actions",
|
|
3918
|
+
execute: () => {
|
|
3919
|
+
instance.openInSeparateWindow?.();
|
|
3920
|
+
}
|
|
3227
3921
|
}
|
|
3228
|
-
|
|
3922
|
+
);
|
|
3923
|
+
return actions;
|
|
3229
3924
|
}
|
|
3230
3925
|
async render(ctx) {
|
|
3231
3926
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -3237,33 +3932,62 @@ var CsvPlugin = class {
|
|
|
3237
3932
|
container.style.padding = "16px";
|
|
3238
3933
|
container.style.boxSizing = "border-box";
|
|
3239
3934
|
container.style.transformOrigin = "top left";
|
|
3935
|
+
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
3936
|
+
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
3937
|
+
const headerLine = allLines[0] || "";
|
|
3938
|
+
const headerCells = headerLine.split(delimiter);
|
|
3939
|
+
const dataLines = allLines.slice(1);
|
|
3940
|
+
const ROWS_PER_PAGE = 100;
|
|
3941
|
+
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
3942
|
+
let currentPage = 1;
|
|
3240
3943
|
const table = document.createElement("table");
|
|
3241
3944
|
table.style.borderCollapse = "collapse";
|
|
3242
3945
|
table.style.width = "100%";
|
|
3243
|
-
table.style.fontFamily = "monospace
|
|
3946
|
+
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3244
3947
|
table.style.fontSize = "13px";
|
|
3245
|
-
const
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
td.style.fontWeight = "bold";
|
|
3259
|
-
}
|
|
3260
|
-
tr.appendChild(td);
|
|
3948
|
+
const renderPage = (pageNum) => {
|
|
3949
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3950
|
+
table.innerHTML = "";
|
|
3951
|
+
const headerTr = document.createElement("tr");
|
|
3952
|
+
headerCells.forEach((cell) => {
|
|
3953
|
+
const th = document.createElement("th");
|
|
3954
|
+
th.textContent = cell.trim();
|
|
3955
|
+
th.style.border = "1px solid #d0d7de";
|
|
3956
|
+
th.style.padding = "8px 12px";
|
|
3957
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
3958
|
+
th.style.fontWeight = "600";
|
|
3959
|
+
th.style.whiteSpace = "nowrap";
|
|
3960
|
+
headerTr.appendChild(th);
|
|
3261
3961
|
});
|
|
3262
|
-
table.appendChild(
|
|
3263
|
-
|
|
3962
|
+
table.appendChild(headerTr);
|
|
3963
|
+
const start = (currentPage - 1) * ROWS_PER_PAGE;
|
|
3964
|
+
const end = Math.min(dataLines.length, start + ROWS_PER_PAGE);
|
|
3965
|
+
const pageRows = dataLines.slice(start, end);
|
|
3966
|
+
pageRows.forEach((row, idx) => {
|
|
3967
|
+
const tr = document.createElement("tr");
|
|
3968
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
3969
|
+
const cells = row.split(delimiter);
|
|
3970
|
+
cells.forEach((cell) => {
|
|
3971
|
+
const td = document.createElement("td");
|
|
3972
|
+
td.textContent = cell.trim();
|
|
3973
|
+
td.style.border = "1px solid #d0d7de";
|
|
3974
|
+
td.style.padding = "6px 12px";
|
|
3975
|
+
td.style.whiteSpace = "nowrap";
|
|
3976
|
+
tr.appendChild(td);
|
|
3977
|
+
});
|
|
3978
|
+
table.appendChild(tr);
|
|
3979
|
+
});
|
|
3980
|
+
container.scrollTop = 0;
|
|
3981
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3982
|
+
};
|
|
3983
|
+
renderPage(1);
|
|
3264
3984
|
container.appendChild(table);
|
|
3265
3985
|
ctx.container.appendChild(container);
|
|
3266
3986
|
let scale = 1;
|
|
3987
|
+
const applyScale = () => {
|
|
3988
|
+
container.style.transform = `scale(${scale})`;
|
|
3989
|
+
container.style.transformOrigin = "top left";
|
|
3990
|
+
};
|
|
3267
3991
|
const cleanup = () => {
|
|
3268
3992
|
container.remove();
|
|
3269
3993
|
ctx.container.innerHTML = "";
|
|
@@ -3271,22 +3995,86 @@ var CsvPlugin = class {
|
|
|
3271
3995
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3272
3996
|
return {
|
|
3273
3997
|
destroy: cleanup,
|
|
3998
|
+
getPageCount: () => totalPages,
|
|
3999
|
+
getCurrentPage: () => currentPage,
|
|
4000
|
+
goToPage: (page) => renderPage(page),
|
|
4001
|
+
getThumbnails: () => {
|
|
4002
|
+
const thumbnails = [];
|
|
4003
|
+
for (let i = 0; i < totalPages; i++) {
|
|
4004
|
+
const pageIdx = i;
|
|
4005
|
+
const startRow = pageIdx * ROWS_PER_PAGE + 1;
|
|
4006
|
+
const endRow = Math.min(dataLines.length, (pageIdx + 1) * ROWS_PER_PAGE);
|
|
4007
|
+
const label = totalPages === 1 ? "Table" : `Page ${pageIdx + 1} (${startRow}-${endRow})`;
|
|
4008
|
+
thumbnails.push({
|
|
4009
|
+
index: pageIdx,
|
|
4010
|
+
label,
|
|
4011
|
+
render: async (canvas) => {
|
|
4012
|
+
canvas.width = 140;
|
|
4013
|
+
canvas.height = 100;
|
|
4014
|
+
const c = canvas.getContext("2d");
|
|
4015
|
+
if (!c) return;
|
|
4016
|
+
c.fillStyle = "#ffffff";
|
|
4017
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4018
|
+
c.fillStyle = "#2563eb";
|
|
4019
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
4020
|
+
c.fillStyle = "#ffffff";
|
|
4021
|
+
c.font = "bold 8px sans-serif";
|
|
4022
|
+
c.fillText(`\u{1F4C8} ${label.slice(0, 18)}`, 6, 11);
|
|
4023
|
+
const startY = 17;
|
|
4024
|
+
const rowH = 13;
|
|
4025
|
+
const colW = 28;
|
|
4026
|
+
const cols = Math.min(4, headerCells.length || 4);
|
|
4027
|
+
c.fillStyle = "#f1f5f9";
|
|
4028
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
4029
|
+
c.strokeStyle = "#cbd5e1";
|
|
4030
|
+
c.lineWidth = 0.8;
|
|
4031
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
4032
|
+
c.fillStyle = "#64748b";
|
|
4033
|
+
c.font = "bold 7px sans-serif";
|
|
4034
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4035
|
+
const hName = headerCells[ci] || `Col ${ci + 1}`;
|
|
4036
|
+
c.fillText(hName.slice(0, 5), 8 + ci * colW, startY + 9);
|
|
4037
|
+
}
|
|
4038
|
+
const rowsToPreview = dataLines.slice(pageIdx * ROWS_PER_PAGE, pageIdx * ROWS_PER_PAGE + 5);
|
|
4039
|
+
for (let ri = 0; ri < rowsToPreview.length; ri++) {
|
|
4040
|
+
const y = startY + (ri + 1) * rowH;
|
|
4041
|
+
if (y > canvas.height - 2) break;
|
|
4042
|
+
c.strokeStyle = "#e2e8f0";
|
|
4043
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
4044
|
+
const cVals = rowsToPreview[ri].split(delimiter);
|
|
4045
|
+
c.fillStyle = "#334155";
|
|
4046
|
+
c.font = "6px sans-serif";
|
|
4047
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4048
|
+
const val = cVals[ci] || "";
|
|
4049
|
+
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
c.strokeStyle = "#cbd5e1";
|
|
4053
|
+
c.lineWidth = 1;
|
|
4054
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4055
|
+
}
|
|
4056
|
+
});
|
|
4057
|
+
}
|
|
4058
|
+
return thumbnails;
|
|
4059
|
+
},
|
|
3274
4060
|
zoomIn: () => {
|
|
3275
4061
|
scale += 0.1;
|
|
3276
|
-
|
|
4062
|
+
applyScale();
|
|
3277
4063
|
},
|
|
3278
4064
|
zoomOut: () => {
|
|
3279
4065
|
scale = Math.max(0.2, scale - 0.1);
|
|
3280
|
-
|
|
4066
|
+
applyScale();
|
|
3281
4067
|
},
|
|
3282
4068
|
getZoom: () => scale,
|
|
3283
4069
|
setZoom: (level) => {
|
|
3284
4070
|
scale = level;
|
|
3285
|
-
|
|
4071
|
+
applyScale();
|
|
3286
4072
|
},
|
|
3287
4073
|
fitToPage: () => {
|
|
3288
|
-
|
|
3289
|
-
|
|
4074
|
+
const availW = Math.max(280, (ctx.container.clientWidth || window.innerWidth) - 48);
|
|
4075
|
+
const tW = table.offsetWidth || 600;
|
|
4076
|
+
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4077
|
+
applyScale();
|
|
3290
4078
|
},
|
|
3291
4079
|
download: () => {
|
|
3292
4080
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
@@ -3350,28 +4138,34 @@ var CodePlugin = class {
|
|
|
3350
4138
|
getToolbarActions(instance) {
|
|
3351
4139
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3352
4140
|
const actions = [];
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
4141
|
+
actions.push({
|
|
4142
|
+
id: "thumbnails",
|
|
4143
|
+
icon: "thumbnails",
|
|
4144
|
+
label: "Page Thumbnails",
|
|
4145
|
+
type: "button",
|
|
4146
|
+
group: "navigation",
|
|
4147
|
+
execute: () => instance.toggleThumbnails?.()
|
|
4148
|
+
});
|
|
4149
|
+
actions.push({
|
|
4150
|
+
id: "page-nav",
|
|
4151
|
+
icon: "",
|
|
4152
|
+
label: "Page Navigation",
|
|
4153
|
+
type: "page-nav",
|
|
4154
|
+
group: "navigation",
|
|
4155
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4156
|
+
max: totalPages,
|
|
4157
|
+
execute: (action, page) => {
|
|
4158
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4159
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4160
|
+
if (action === "prev") {
|
|
4161
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4162
|
+
} else if (action === "next") {
|
|
4163
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4164
|
+
} else if (typeof page === "number") {
|
|
4165
|
+
instance.goToPage?.(page);
|
|
3372
4166
|
}
|
|
3373
|
-
}
|
|
3374
|
-
}
|
|
4167
|
+
}
|
|
4168
|
+
});
|
|
3375
4169
|
actions.push(
|
|
3376
4170
|
{
|
|
3377
4171
|
id: "zoom-out",
|
|
@@ -3515,16 +4309,19 @@ var CodePlugin = class {
|
|
|
3515
4309
|
let fontSize = 13;
|
|
3516
4310
|
let rotation = 0;
|
|
3517
4311
|
let zoomLevel = 1;
|
|
4312
|
+
let isUserZoomed = false;
|
|
3518
4313
|
const pre = document.createElement("pre");
|
|
3519
4314
|
const code = document.createElement("code");
|
|
3520
4315
|
if (isTxt) {
|
|
4316
|
+
container.style.overflowX = "hidden";
|
|
4317
|
+
container.style.overflowY = "auto";
|
|
3521
4318
|
container.style.backgroundColor = "#f1f5f9";
|
|
3522
|
-
container.style.padding = "
|
|
4319
|
+
container.style.padding = "16px 8px";
|
|
3523
4320
|
container.style.boxSizing = "border-box";
|
|
3524
4321
|
container.style.display = "flex";
|
|
3525
4322
|
container.style.flexDirection = "column";
|
|
3526
4323
|
container.style.alignItems = "center";
|
|
3527
|
-
pre.style.margin = "0";
|
|
4324
|
+
pre.style.margin = "0 auto";
|
|
3528
4325
|
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3529
4326
|
pre.style.fontSize = "13px";
|
|
3530
4327
|
pre.style.color = "#1e293b";
|
|
@@ -3536,10 +4333,12 @@ var CodePlugin = class {
|
|
|
3536
4333
|
pre.style.minHeight = "1056px";
|
|
3537
4334
|
pre.style.padding = "72px 56px";
|
|
3538
4335
|
pre.style.boxSizing = "border-box";
|
|
3539
|
-
pre.style.boxShadow = "0 4px
|
|
4336
|
+
pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
3540
4337
|
pre.style.borderRadius = "4px";
|
|
3541
4338
|
pre.style.transformOrigin = "top center";
|
|
4339
|
+
pre.style.transition = "transform 0.15s ease";
|
|
3542
4340
|
} else {
|
|
4341
|
+
container.style.overflow = "auto";
|
|
3543
4342
|
container.style.backgroundColor = "#1e1e1e";
|
|
3544
4343
|
container.style.color = "#d4d4d4";
|
|
3545
4344
|
container.style.padding = "16px";
|
|
@@ -3571,42 +4370,9 @@ var CodePlugin = class {
|
|
|
3571
4370
|
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3572
4371
|
pre.appendChild(code);
|
|
3573
4372
|
container.appendChild(pre);
|
|
3574
|
-
let indicator = null;
|
|
3575
|
-
if (totalPages > 1) {
|
|
3576
|
-
indicator = document.createElement("div");
|
|
3577
|
-
indicator.className = "fp-code-page-indicator";
|
|
3578
|
-
indicator.style.position = "sticky";
|
|
3579
|
-
indicator.style.bottom = "16px";
|
|
3580
|
-
if (isTxt) {
|
|
3581
|
-
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3582
|
-
indicator.style.color = "#334155";
|
|
3583
|
-
indicator.style.border = "1px solid #e2e8f0";
|
|
3584
|
-
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3585
|
-
} else {
|
|
3586
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3587
|
-
indicator.style.color = "#f8fafc";
|
|
3588
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3589
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3590
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
3591
|
-
}
|
|
3592
|
-
indicator.style.fontSize = "12px";
|
|
3593
|
-
indicator.style.fontWeight = "600";
|
|
3594
|
-
indicator.style.padding = "5px 14px";
|
|
3595
|
-
indicator.style.borderRadius = "20px";
|
|
3596
|
-
indicator.style.zIndex = "10";
|
|
3597
|
-
indicator.style.userSelect = "none";
|
|
3598
|
-
indicator.style.pointerEvents = "none";
|
|
3599
|
-
indicator.style.textAlign = "center";
|
|
3600
|
-
indicator.style.width = "fit-content";
|
|
3601
|
-
indicator.style.margin = "16px auto 0";
|
|
3602
|
-
container.appendChild(indicator);
|
|
3603
|
-
}
|
|
3604
4373
|
const showPage = (pageNum) => {
|
|
3605
4374
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3606
4375
|
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3607
|
-
if (indicator) {
|
|
3608
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3609
|
-
}
|
|
3610
4376
|
container.scrollTop = 0;
|
|
3611
4377
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3612
4378
|
};
|
|
@@ -3614,36 +4380,90 @@ var CodePlugin = class {
|
|
|
3614
4380
|
showPage(1);
|
|
3615
4381
|
}
|
|
3616
4382
|
ctx.container.appendChild(container);
|
|
3617
|
-
const
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
ctx.container.innerHTML = "";
|
|
4383
|
+
const calculateTxtFit = () => {
|
|
4384
|
+
const availW = Math.max(280, container.clientWidth - 32);
|
|
4385
|
+
return Math.max(0.4, Math.min(3, availW / 816));
|
|
3621
4386
|
};
|
|
3622
|
-
ctx.signal.addEventListener("abort", cleanup);
|
|
3623
4387
|
const updateTransform = () => {
|
|
3624
4388
|
if (isTxt) {
|
|
3625
4389
|
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
4390
|
+
const scaledH = 1056 * zoomLevel;
|
|
4391
|
+
const extraH = Math.max(0, scaledH - 1056);
|
|
4392
|
+
pre.style.marginBottom = `${extraH + 32}px`;
|
|
3626
4393
|
} else {
|
|
3627
4394
|
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3628
4395
|
pre.style.fontSize = `${fontSize}px`;
|
|
3629
4396
|
}
|
|
3630
4397
|
};
|
|
4398
|
+
let resizeObserver = null;
|
|
4399
|
+
if (isTxt) {
|
|
4400
|
+
setTimeout(() => {
|
|
4401
|
+
zoomLevel = calculateTxtFit();
|
|
4402
|
+
updateTransform();
|
|
4403
|
+
}, 60);
|
|
4404
|
+
resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
4405
|
+
if (!isUserZoomed) {
|
|
4406
|
+
zoomLevel = calculateTxtFit();
|
|
4407
|
+
updateTransform();
|
|
4408
|
+
}
|
|
4409
|
+
}) : null;
|
|
4410
|
+
resizeObserver?.observe(container);
|
|
4411
|
+
}
|
|
4412
|
+
const cleanup = () => {
|
|
4413
|
+
resizeObserver?.disconnect();
|
|
4414
|
+
container.remove();
|
|
4415
|
+
ctx.container.innerHTML = "";
|
|
4416
|
+
};
|
|
4417
|
+
ctx.signal.addEventListener("abort", cleanup);
|
|
3631
4418
|
return {
|
|
3632
4419
|
destroy: cleanup,
|
|
3633
4420
|
getPageCount: () => totalPages,
|
|
3634
4421
|
getCurrentPage: () => currentPage,
|
|
3635
4422
|
goToPage: (page) => showPage(page),
|
|
4423
|
+
getThumbnails: () => {
|
|
4424
|
+
return rawPages.map((pageText, idx) => ({
|
|
4425
|
+
index: idx,
|
|
4426
|
+
label: `Page ${idx + 1}`,
|
|
4427
|
+
render: async (canvas) => {
|
|
4428
|
+
canvas.width = 140;
|
|
4429
|
+
canvas.height = 180;
|
|
4430
|
+
const c = canvas.getContext("2d");
|
|
4431
|
+
if (!c) return;
|
|
4432
|
+
c.fillStyle = "#ffffff";
|
|
4433
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4434
|
+
c.strokeStyle = "#cbd5e1";
|
|
4435
|
+
c.lineWidth = 1;
|
|
4436
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4437
|
+
c.fillStyle = "#64748b";
|
|
4438
|
+
const lines = (pageText || "").split("\n").slice(0, 24);
|
|
4439
|
+
const lineH = 6;
|
|
4440
|
+
const startY = 14;
|
|
4441
|
+
const startX = 12;
|
|
4442
|
+
const maxW = canvas.width - 24;
|
|
4443
|
+
c.font = "5px monospace";
|
|
4444
|
+
for (let li = 0; li < lines.length; li++) {
|
|
4445
|
+
const l = lines[li].trim();
|
|
4446
|
+
if (!l) continue;
|
|
4447
|
+
const y = startY + li * lineH;
|
|
4448
|
+
if (y > canvas.height - 12) break;
|
|
4449
|
+
c.fillText(l.slice(0, 30), startX, y, maxW);
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
}));
|
|
4453
|
+
},
|
|
3636
4454
|
zoomIn: () => {
|
|
4455
|
+
isUserZoomed = true;
|
|
3637
4456
|
if (isTxt) {
|
|
3638
|
-
zoomLevel = Math.min(3, zoomLevel + 0.
|
|
4457
|
+
zoomLevel = Math.min(3.5, zoomLevel + 0.15);
|
|
3639
4458
|
} else {
|
|
3640
4459
|
fontSize = Math.min(32, fontSize + 2);
|
|
3641
4460
|
}
|
|
3642
4461
|
updateTransform();
|
|
3643
4462
|
},
|
|
3644
4463
|
zoomOut: () => {
|
|
4464
|
+
isUserZoomed = true;
|
|
3645
4465
|
if (isTxt) {
|
|
3646
|
-
zoomLevel = Math.max(0.1, zoomLevel - 0.
|
|
4466
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.15);
|
|
3647
4467
|
} else {
|
|
3648
4468
|
fontSize = Math.max(8, fontSize - 2);
|
|
3649
4469
|
}
|
|
@@ -3651,6 +4471,7 @@ var CodePlugin = class {
|
|
|
3651
4471
|
},
|
|
3652
4472
|
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3653
4473
|
setZoom: (level) => {
|
|
4474
|
+
isUserZoomed = true;
|
|
3654
4475
|
if (isTxt) {
|
|
3655
4476
|
zoomLevel = level;
|
|
3656
4477
|
} else {
|
|
@@ -3659,9 +4480,10 @@ var CodePlugin = class {
|
|
|
3659
4480
|
updateTransform();
|
|
3660
4481
|
},
|
|
3661
4482
|
fitToPage: () => {
|
|
4483
|
+
isUserZoomed = false;
|
|
3662
4484
|
fontSize = 13;
|
|
3663
4485
|
rotation = 0;
|
|
3664
|
-
zoomLevel = isTxt ?
|
|
4486
|
+
zoomLevel = isTxt ? calculateTxtFit() : 1;
|
|
3665
4487
|
updateTransform();
|
|
3666
4488
|
},
|
|
3667
4489
|
rotateCW: () => {
|
|
@@ -4542,28 +5364,26 @@ var RtfPlugin = class {
|
|
|
4542
5364
|
getToolbarActions(instance) {
|
|
4543
5365
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4544
5366
|
const actions = [];
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
if (
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
instance.goToPage?.(page);
|
|
4563
|
-
}
|
|
5367
|
+
actions.push({
|
|
5368
|
+
id: "page-nav",
|
|
5369
|
+
icon: "",
|
|
5370
|
+
label: "Page Navigation",
|
|
5371
|
+
type: "page-nav",
|
|
5372
|
+
group: "navigation",
|
|
5373
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5374
|
+
max: totalPages,
|
|
5375
|
+
execute: (action, page) => {
|
|
5376
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5377
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5378
|
+
if (action === "prev") {
|
|
5379
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5380
|
+
} else if (action === "next") {
|
|
5381
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5382
|
+
} else if (typeof page === "number") {
|
|
5383
|
+
instance.goToPage?.(page);
|
|
4564
5384
|
}
|
|
4565
|
-
}
|
|
4566
|
-
}
|
|
5385
|
+
}
|
|
5386
|
+
});
|
|
4567
5387
|
actions.push(
|
|
4568
5388
|
{
|
|
4569
5389
|
id: "zoom-out",
|
|
@@ -4635,43 +5455,57 @@ var RtfPlugin = class {
|
|
|
4635
5455
|
async render(ctx) {
|
|
4636
5456
|
const wrapper = document.createElement("div");
|
|
4637
5457
|
wrapper.className = "fp-rtf-wrapper";
|
|
4638
|
-
wrapper.style.padding = "
|
|
4639
|
-
wrapper.style.
|
|
5458
|
+
wrapper.style.padding = "0";
|
|
5459
|
+
wrapper.style.width = "816px";
|
|
4640
5460
|
wrapper.style.margin = "0 auto";
|
|
4641
|
-
wrapper.style.
|
|
4642
|
-
wrapper.style.
|
|
4643
|
-
wrapper.style.
|
|
4644
|
-
wrapper.style.
|
|
5461
|
+
wrapper.style.boxSizing = "border-box";
|
|
5462
|
+
wrapper.style.display = "flex";
|
|
5463
|
+
wrapper.style.flexDirection = "column";
|
|
5464
|
+
wrapper.style.alignItems = "center";
|
|
5465
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4645
5466
|
wrapper.style.transformOrigin = "top center";
|
|
4646
|
-
wrapper.style.transition = "transform 0.
|
|
4647
|
-
ctx.container.style.
|
|
4648
|
-
ctx.container.style.
|
|
5467
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5468
|
+
ctx.container.style.overflowX = "hidden";
|
|
5469
|
+
ctx.container.style.overflowY = "auto";
|
|
5470
|
+
ctx.container.style.padding = "16px 8px";
|
|
4649
5471
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
4650
5472
|
ctx.container.appendChild(wrapper);
|
|
4651
5473
|
let scale = 1;
|
|
4652
5474
|
let rotation = 0;
|
|
4653
5475
|
let pageElements = [];
|
|
4654
|
-
let
|
|
5476
|
+
let isUserZoomed = false;
|
|
5477
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
4655
5478
|
const calculateFitScale = (mode = fitMode) => {
|
|
4656
5479
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4657
|
-
const elW =
|
|
4658
|
-
const singlePageH =
|
|
4659
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
4660
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
5480
|
+
const elW = 816;
|
|
5481
|
+
const singlePageH = activeEl?.offsetHeight || 1056;
|
|
5482
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5483
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
4661
5484
|
const sW = availW / elW;
|
|
4662
5485
|
const sH = availH / singlePageH;
|
|
4663
5486
|
if (mode === "page") {
|
|
4664
|
-
return Math.max(0.
|
|
5487
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
4665
5488
|
}
|
|
4666
|
-
return Math.max(0.
|
|
5489
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
4667
5490
|
};
|
|
4668
5491
|
const applyTransform = () => {
|
|
4669
5492
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4670
5493
|
wrapper.style.transformOrigin = "top center";
|
|
5494
|
+
const activeEl = pageElements[currentPage - 1];
|
|
5495
|
+
const baseH = activeEl?.offsetHeight || 1056;
|
|
5496
|
+
const scaledH = baseH * scale;
|
|
5497
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5498
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
4671
5499
|
};
|
|
5500
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5501
|
+
if (!isUserZoomed) {
|
|
5502
|
+
scale = calculateFitScale(fitMode);
|
|
5503
|
+
applyTransform();
|
|
5504
|
+
}
|
|
5505
|
+
}) : null;
|
|
5506
|
+
resizeObserver?.observe(ctx.container);
|
|
4672
5507
|
setTimeout(() => {
|
|
4673
|
-
|
|
4674
|
-
scale = calculateFitScale("width");
|
|
5508
|
+
scale = calculateFitScale(fitMode);
|
|
4675
5509
|
applyTransform();
|
|
4676
5510
|
}, 60);
|
|
4677
5511
|
try {
|
|
@@ -4681,20 +5515,34 @@ var RtfPlugin = class {
|
|
|
4681
5515
|
const doc = new RTFJS.Document(ctx.buffer, {});
|
|
4682
5516
|
const htmlElements = await doc.render();
|
|
4683
5517
|
const contentNodes = [];
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
5518
|
+
const extractBlocks = (nodes) => {
|
|
5519
|
+
for (const item of nodes) {
|
|
5520
|
+
if (!item || !(item instanceof HTMLElement)) continue;
|
|
5521
|
+
const tag = item.tagName.toLowerCase();
|
|
5522
|
+
const hasChildBlocks = Array.from(item.children).some((c) => {
|
|
5523
|
+
const ct = c.tagName.toLowerCase();
|
|
5524
|
+
return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
|
|
5525
|
+
});
|
|
5526
|
+
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5527
|
+
extractBlocks(Array.from(item.children));
|
|
5528
|
+
} else {
|
|
5529
|
+
if (tag === "p" || tag === "div") {
|
|
5530
|
+
item.style.display = "block";
|
|
5531
|
+
item.style.marginBottom = "12px";
|
|
5532
|
+
item.style.lineHeight = "1.6";
|
|
5533
|
+
}
|
|
5534
|
+
contentNodes.push(item);
|
|
5535
|
+
}
|
|
4689
5536
|
}
|
|
4690
|
-
}
|
|
5537
|
+
};
|
|
5538
|
+
extractBlocks(htmlElements);
|
|
4691
5539
|
wrapper.innerHTML = "";
|
|
4692
5540
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4693
5541
|
const childHeights = contentNodes.map((c) => {
|
|
4694
5542
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4695
5543
|
const offH = c.offsetHeight || 0;
|
|
4696
5544
|
const textLen = c.textContent?.trim().length || 0;
|
|
4697
|
-
const estH = Math.max(
|
|
5545
|
+
const estH = Math.max(28, Math.ceil(textLen / 75) * 24 + 16);
|
|
4698
5546
|
return Math.max(rectH, offH, estH);
|
|
4699
5547
|
});
|
|
4700
5548
|
wrapper.innerHTML = "";
|
|
@@ -4711,6 +5559,7 @@ var RtfPlugin = class {
|
|
|
4711
5559
|
card.style.marginBottom = "24px";
|
|
4712
5560
|
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4713
5561
|
card.style.lineHeight = "1.6";
|
|
5562
|
+
card.style.color = "#1e293b";
|
|
4714
5563
|
return card;
|
|
4715
5564
|
};
|
|
4716
5565
|
let curCard = createRtfCard();
|
|
@@ -4746,9 +5595,8 @@ var RtfPlugin = class {
|
|
|
4746
5595
|
pageCard.style.padding = "72px 56px";
|
|
4747
5596
|
pageCard.style.width = "816px";
|
|
4748
5597
|
pageCard.style.minHeight = "1056px";
|
|
4749
|
-
pageCard.style.maxWidth = "100%";
|
|
4750
5598
|
pageCard.style.boxSizing = "border-box";
|
|
4751
|
-
pageCard.style.fontFamily = "serif
|
|
5599
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4752
5600
|
pageCard.style.fontSize = "12pt";
|
|
4753
5601
|
pageCard.style.lineHeight = "1.6";
|
|
4754
5602
|
pageCard.style.color = "#1e293b";
|
|
@@ -4761,29 +5609,6 @@ var RtfPlugin = class {
|
|
|
4761
5609
|
}
|
|
4762
5610
|
const totalPages = Math.max(1, pageElements.length);
|
|
4763
5611
|
let currentPage = 1;
|
|
4764
|
-
let indicator = null;
|
|
4765
|
-
if (totalPages > 1) {
|
|
4766
|
-
indicator = document.createElement("div");
|
|
4767
|
-
indicator.className = "fp-rtf-page-indicator";
|
|
4768
|
-
indicator.style.position = "sticky";
|
|
4769
|
-
indicator.style.bottom = "16px";
|
|
4770
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4771
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
4772
|
-
indicator.style.color = "#f8fafc";
|
|
4773
|
-
indicator.style.fontSize = "12px";
|
|
4774
|
-
indicator.style.fontWeight = "600";
|
|
4775
|
-
indicator.style.padding = "5px 14px";
|
|
4776
|
-
indicator.style.borderRadius = "20px";
|
|
4777
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4778
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4779
|
-
indicator.style.zIndex = "10";
|
|
4780
|
-
indicator.style.userSelect = "none";
|
|
4781
|
-
indicator.style.pointerEvents = "none";
|
|
4782
|
-
indicator.style.textAlign = "center";
|
|
4783
|
-
indicator.style.width = "fit-content";
|
|
4784
|
-
indicator.style.margin = "16px auto 0";
|
|
4785
|
-
ctx.container.appendChild(indicator);
|
|
4786
|
-
}
|
|
4787
5612
|
const showPage = (pageNum) => {
|
|
4788
5613
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4789
5614
|
if (totalPages > 1) {
|
|
@@ -4791,9 +5616,6 @@ var RtfPlugin = class {
|
|
|
4791
5616
|
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4792
5617
|
});
|
|
4793
5618
|
}
|
|
4794
|
-
if (indicator) {
|
|
4795
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4796
|
-
}
|
|
4797
5619
|
ctx.container.scrollTop = 0;
|
|
4798
5620
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4799
5621
|
};
|
|
@@ -4801,7 +5623,7 @@ var RtfPlugin = class {
|
|
|
4801
5623
|
showPage(1);
|
|
4802
5624
|
}
|
|
4803
5625
|
const cleanup = () => {
|
|
4804
|
-
|
|
5626
|
+
resizeObserver?.disconnect();
|
|
4805
5627
|
wrapper.remove();
|
|
4806
5628
|
ctx.container.innerHTML = "";
|
|
4807
5629
|
};
|
|
@@ -4812,21 +5634,25 @@ var RtfPlugin = class {
|
|
|
4812
5634
|
getCurrentPage: () => currentPage,
|
|
4813
5635
|
goToPage: (page) => showPage(page),
|
|
4814
5636
|
zoomIn: () => {
|
|
5637
|
+
isUserZoomed = true;
|
|
4815
5638
|
scale += 0.15;
|
|
4816
5639
|
applyTransform();
|
|
4817
5640
|
},
|
|
4818
5641
|
zoomOut: () => {
|
|
5642
|
+
isUserZoomed = true;
|
|
4819
5643
|
scale = Math.max(0.2, scale - 0.15);
|
|
4820
5644
|
applyTransform();
|
|
4821
5645
|
},
|
|
4822
5646
|
getZoom: () => scale,
|
|
4823
5647
|
setZoom: (level) => {
|
|
5648
|
+
isUserZoomed = true;
|
|
4824
5649
|
scale = level;
|
|
4825
5650
|
applyTransform();
|
|
4826
5651
|
},
|
|
4827
5652
|
fitToPage: () => {
|
|
4828
|
-
|
|
4829
|
-
|
|
5653
|
+
isUserZoomed = false;
|
|
5654
|
+
fitMode = "width";
|
|
5655
|
+
scale = calculateFitScale("width");
|
|
4830
5656
|
rotation = 0;
|
|
4831
5657
|
applyTransform();
|
|
4832
5658
|
},
|
|
@@ -5014,40 +5840,36 @@ var OpenDocumentPlugin = class {
|
|
|
5014
5840
|
const isPresentation = instance.isPresentation;
|
|
5015
5841
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5016
5842
|
const actions = [];
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
max
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
if (
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
instance.goToPage?.(page);
|
|
5045
|
-
} else if (typeof action === "number") {
|
|
5046
|
-
instance.goToPage?.(action);
|
|
5047
|
-
}
|
|
5843
|
+
actions.push({
|
|
5844
|
+
id: "thumbnails",
|
|
5845
|
+
icon: "thumbnails",
|
|
5846
|
+
label: isPresentation ? "Slide Thumbnails" : "Page Thumbnails",
|
|
5847
|
+
type: "button",
|
|
5848
|
+
group: "navigation",
|
|
5849
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5850
|
+
});
|
|
5851
|
+
actions.push({
|
|
5852
|
+
id: "page-nav",
|
|
5853
|
+
icon: "",
|
|
5854
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
5855
|
+
type: "page-nav",
|
|
5856
|
+
group: "navigation",
|
|
5857
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5858
|
+
max: totalPages,
|
|
5859
|
+
execute: (action, page) => {
|
|
5860
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5861
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5862
|
+
if (action === "prev") {
|
|
5863
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5864
|
+
} else if (action === "next") {
|
|
5865
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5866
|
+
} else if (typeof page === "number") {
|
|
5867
|
+
instance.goToPage?.(page);
|
|
5868
|
+
} else if (typeof action === "number") {
|
|
5869
|
+
instance.goToPage?.(action);
|
|
5048
5870
|
}
|
|
5049
|
-
}
|
|
5050
|
-
}
|
|
5871
|
+
}
|
|
5872
|
+
});
|
|
5051
5873
|
actions.push(
|
|
5052
5874
|
{
|
|
5053
5875
|
id: "zoom-out",
|
|
@@ -5138,49 +5960,65 @@ var OpenDocumentPlugin = class {
|
|
|
5138
5960
|
container.className = "fp-odf-container";
|
|
5139
5961
|
container.style.width = "100%";
|
|
5140
5962
|
container.style.height = "100%";
|
|
5141
|
-
container.style.
|
|
5142
|
-
container.style.
|
|
5963
|
+
container.style.overflowX = "hidden";
|
|
5964
|
+
container.style.overflowY = "auto";
|
|
5965
|
+
container.style.padding = "16px 8px";
|
|
5143
5966
|
container.style.backgroundColor = "#f1f5f9";
|
|
5144
5967
|
const wrapper = document.createElement("div");
|
|
5145
5968
|
wrapper.className = "fp-odf-wrapper";
|
|
5146
5969
|
wrapper.style.margin = "0 auto";
|
|
5970
|
+
wrapper.style.width = isPresentation ? "960px" : "816px";
|
|
5971
|
+
wrapper.style.boxSizing = "border-box";
|
|
5147
5972
|
wrapper.style.backgroundColor = "#ffffff";
|
|
5148
5973
|
wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
5149
5974
|
wrapper.style.borderRadius = "4px";
|
|
5150
5975
|
wrapper.style.transformOrigin = "top center";
|
|
5151
|
-
wrapper.style.transition = "transform 0.
|
|
5976
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5152
5977
|
container.appendChild(wrapper);
|
|
5153
5978
|
ctx.container.appendChild(container);
|
|
5154
5979
|
let scale = 1;
|
|
5155
5980
|
let rotation = 0;
|
|
5156
|
-
let
|
|
5981
|
+
let isUserZoomed = false;
|
|
5982
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
5983
|
+
let currentPage = 1;
|
|
5984
|
+
let totalPages = 1;
|
|
5985
|
+
let slides = [];
|
|
5157
5986
|
const calculateFitScale = (mode = fitMode) => {
|
|
5158
|
-
const
|
|
5159
|
-
const
|
|
5160
|
-
const
|
|
5161
|
-
const
|
|
5987
|
+
const activeSlide = slides[currentPage - 1];
|
|
5988
|
+
const elW = isPresentation ? 960 : 816;
|
|
5989
|
+
const singlePageH = Math.min(activeSlide?.offsetHeight || wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
5990
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5991
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5162
5992
|
const sW = availW / elW;
|
|
5163
5993
|
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
5164
5994
|
if (isPresentation) {
|
|
5165
|
-
return Math.min(
|
|
5995
|
+
return Math.min(2.5, Math.min(sW, sH));
|
|
5166
5996
|
}
|
|
5167
5997
|
if (mode === "page") {
|
|
5168
|
-
return Math.max(0.
|
|
5998
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5169
5999
|
}
|
|
5170
|
-
return Math.max(0.
|
|
6000
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5171
6001
|
};
|
|
5172
6002
|
const applyTransform = () => {
|
|
5173
6003
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5174
6004
|
wrapper.style.transformOrigin = "top center";
|
|
6005
|
+
const activeSlide = slides[currentPage - 1];
|
|
6006
|
+
const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
|
|
6007
|
+
const scaledH = baseH * scale;
|
|
6008
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6009
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
5175
6010
|
};
|
|
6011
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6012
|
+
if (!isUserZoomed) {
|
|
6013
|
+
scale = calculateFitScale(fitMode);
|
|
6014
|
+
applyTransform();
|
|
6015
|
+
}
|
|
6016
|
+
}) : null;
|
|
6017
|
+
resizeObserver?.observe(ctx.container);
|
|
5176
6018
|
setTimeout(() => {
|
|
5177
|
-
|
|
5178
|
-
scale = calculateFitScale("width");
|
|
6019
|
+
scale = calculateFitScale(fitMode);
|
|
5179
6020
|
applyTransform();
|
|
5180
6021
|
}, 60);
|
|
5181
|
-
let currentPage = 1;
|
|
5182
|
-
let totalPages = 1;
|
|
5183
|
-
let slides = [];
|
|
5184
6022
|
if (isPresentation) {
|
|
5185
6023
|
wrapper.style.maxWidth = "960px";
|
|
5186
6024
|
wrapper.style.aspectRatio = "16 / 9";
|
|
@@ -5281,24 +6119,9 @@ var OpenDocumentPlugin = class {
|
|
|
5281
6119
|
wrapper.appendChild(page);
|
|
5282
6120
|
slides.push(page);
|
|
5283
6121
|
});
|
|
5284
|
-
const pageIndicator = document.createElement("div");
|
|
5285
|
-
pageIndicator.className = "fp-odt-page-indicator";
|
|
5286
|
-
pageIndicator.style.position = "sticky";
|
|
5287
|
-
pageIndicator.style.bottom = "16px";
|
|
5288
|
-
pageIndicator.style.left = "50%";
|
|
5289
|
-
pageIndicator.style.transform = "translateX(-50%)";
|
|
5290
|
-
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
5291
|
-
pageIndicator.style.color = "#fff";
|
|
5292
|
-
pageIndicator.style.padding = "6px 12px";
|
|
5293
|
-
pageIndicator.style.borderRadius = "16px";
|
|
5294
|
-
pageIndicator.style.fontSize = "12px";
|
|
5295
|
-
pageIndicator.style.zIndex = "100";
|
|
5296
|
-
pageIndicator.style.display = "inline-block";
|
|
5297
|
-
pageIndicator.style.width = "fit-content";
|
|
5298
|
-
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
5299
|
-
container.appendChild(pageIndicator);
|
|
5300
6122
|
}
|
|
5301
6123
|
const cleanup = () => {
|
|
6124
|
+
resizeObserver?.disconnect();
|
|
5302
6125
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
5303
6126
|
container.remove();
|
|
5304
6127
|
ctx.container.innerHTML = "";
|
|
@@ -5310,10 +6133,6 @@ var OpenDocumentPlugin = class {
|
|
|
5310
6133
|
slides.forEach((s, idx) => {
|
|
5311
6134
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
5312
6135
|
});
|
|
5313
|
-
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
5314
|
-
if (indicator) {
|
|
5315
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5316
|
-
}
|
|
5317
6136
|
container.scrollTop = 0;
|
|
5318
6137
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5319
6138
|
};
|
|
@@ -5321,21 +6140,25 @@ var OpenDocumentPlugin = class {
|
|
|
5321
6140
|
destroy: cleanup,
|
|
5322
6141
|
isPresentation,
|
|
5323
6142
|
zoomIn: () => {
|
|
6143
|
+
isUserZoomed = true;
|
|
5324
6144
|
scale += 0.15;
|
|
5325
6145
|
applyTransform();
|
|
5326
6146
|
},
|
|
5327
6147
|
zoomOut: () => {
|
|
6148
|
+
isUserZoomed = true;
|
|
5328
6149
|
scale = Math.max(0.2, scale - 0.15);
|
|
5329
6150
|
applyTransform();
|
|
5330
6151
|
},
|
|
5331
6152
|
getZoom: () => scale,
|
|
5332
6153
|
setZoom: (level) => {
|
|
6154
|
+
isUserZoomed = true;
|
|
5333
6155
|
scale = level;
|
|
5334
6156
|
applyTransform();
|
|
5335
6157
|
},
|
|
5336
6158
|
fitToPage: () => {
|
|
5337
|
-
|
|
5338
|
-
|
|
6159
|
+
isUserZoomed = false;
|
|
6160
|
+
fitMode = "width";
|
|
6161
|
+
scale = calculateFitScale("width");
|
|
5339
6162
|
rotation = 0;
|
|
5340
6163
|
applyTransform();
|
|
5341
6164
|
},
|
|
@@ -5351,23 +6174,45 @@ var OpenDocumentPlugin = class {
|
|
|
5351
6174
|
getPageCount: () => totalPages,
|
|
5352
6175
|
getCurrentPage: () => currentPage,
|
|
5353
6176
|
getThumbnails: async () => {
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
canvas
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
6177
|
+
const count = totalPages || slides.length || 1;
|
|
6178
|
+
const items = [];
|
|
6179
|
+
for (let idx = 0; idx < count; idx++) {
|
|
6180
|
+
const itemIdx = idx;
|
|
6181
|
+
items.push({
|
|
6182
|
+
index: itemIdx,
|
|
6183
|
+
label: isPresentation ? `Slide ${itemIdx + 1}` : `Page ${itemIdx + 1}`,
|
|
6184
|
+
render: async (canvas) => {
|
|
6185
|
+
const ctx2d = canvas.getContext("2d");
|
|
6186
|
+
if (!ctx2d) return;
|
|
6187
|
+
if (isPresentation) {
|
|
6188
|
+
canvas.width = 160;
|
|
6189
|
+
canvas.height = 90;
|
|
6190
|
+
ctx2d.fillStyle = "#f8fafc";
|
|
6191
|
+
ctx2d.fillRect(0, 0, 160, 90);
|
|
6192
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6193
|
+
ctx2d.lineWidth = 1;
|
|
6194
|
+
ctx2d.strokeRect(0.5, 0.5, 159, 89);
|
|
6195
|
+
ctx2d.fillStyle = "#334155";
|
|
6196
|
+
ctx2d.font = "bold 11px sans-serif";
|
|
6197
|
+
ctx2d.textAlign = "center";
|
|
6198
|
+
ctx2d.fillText(`Slide ${itemIdx + 1}`, 80, 50);
|
|
6199
|
+
} else {
|
|
6200
|
+
canvas.width = 140;
|
|
6201
|
+
canvas.height = 180;
|
|
6202
|
+
ctx2d.fillStyle = "#ffffff";
|
|
6203
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
6204
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6205
|
+
ctx2d.lineWidth = 1;
|
|
6206
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
6207
|
+
ctx2d.fillStyle = "#64748b";
|
|
6208
|
+
ctx2d.font = "bold 10px sans-serif";
|
|
6209
|
+
ctx2d.textAlign = "center";
|
|
6210
|
+
ctx2d.fillText(`Page ${itemIdx + 1}`, 70, 90);
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
});
|
|
6214
|
+
}
|
|
6215
|
+
return items;
|
|
5371
6216
|
},
|
|
5372
6217
|
download: () => {
|
|
5373
6218
|
const mimeType = this.mimeTypes.find((m) => m.includes(ext.replace(".", ""))) || "application/octet-stream";
|
|
@@ -5472,23 +6317,24 @@ var OpenDocumentPlugin = class {
|
|
|
5472
6317
|
case "h": {
|
|
5473
6318
|
const level = Math.min(6, Math.max(1, Number(node.getAttribute("text:outline-level") || 1)));
|
|
5474
6319
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5475
|
-
html += `<h${level} style="${style}; font-family:
|
|
6320
|
+
html += `<h${level} style="${style}; margin: 18px 0 8px; color: #1e3a8a; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${node.textContent || ""}</h${level}>`;
|
|
5476
6321
|
break;
|
|
5477
6322
|
}
|
|
5478
6323
|
case "p": {
|
|
5479
6324
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5480
6325
|
const inner = this.renderSpans(node, styles, images);
|
|
5481
|
-
|
|
6326
|
+
const isInsideLi = node.parentElement?.localName === "list-item" || node.parentElement?.tagName?.toLowerCase() === "list-item";
|
|
6327
|
+
html += `<p style="${style}; line-height: 1.5; margin: ${isInsideLi ? "0" : "8px 0 12px"}; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${inner}</p>`;
|
|
5482
6328
|
break;
|
|
5483
6329
|
}
|
|
5484
6330
|
case "list": {
|
|
5485
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
6331
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
5486
6332
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5487
6333
|
html += "</ul>";
|
|
5488
6334
|
break;
|
|
5489
6335
|
}
|
|
5490
6336
|
case "list-item": {
|
|
5491
|
-
html +=
|
|
6337
|
+
html += '<li style="margin: 4px 0; font-size: 11pt; line-height: 1.5; color: #1e293b;">';
|
|
5492
6338
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5493
6339
|
html += "</li>";
|
|
5494
6340
|
break;
|
|
@@ -5614,28 +6460,26 @@ var DocPlugin = class {
|
|
|
5614
6460
|
getToolbarActions(instance) {
|
|
5615
6461
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5616
6462
|
const actions = [];
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
if (
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
instance.goToPage?.(page);
|
|
5635
|
-
}
|
|
6463
|
+
actions.push({
|
|
6464
|
+
id: "page-nav",
|
|
6465
|
+
icon: "",
|
|
6466
|
+
label: "Page Navigation",
|
|
6467
|
+
type: "page-nav",
|
|
6468
|
+
group: "navigation",
|
|
6469
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
6470
|
+
max: totalPages,
|
|
6471
|
+
execute: (action, page) => {
|
|
6472
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
6473
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
6474
|
+
if (action === "prev") {
|
|
6475
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
6476
|
+
} else if (action === "next") {
|
|
6477
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
6478
|
+
} else if (typeof page === "number") {
|
|
6479
|
+
instance.goToPage?.(page);
|
|
5636
6480
|
}
|
|
5637
|
-
}
|
|
5638
|
-
}
|
|
6481
|
+
}
|
|
6482
|
+
});
|
|
5639
6483
|
actions.push(
|
|
5640
6484
|
{
|
|
5641
6485
|
id: "zoom-out",
|
|
@@ -5709,8 +6553,9 @@ var DocPlugin = class {
|
|
|
5709
6553
|
container.className = "fp-doc-container";
|
|
5710
6554
|
container.style.width = "100%";
|
|
5711
6555
|
container.style.height = "100%";
|
|
5712
|
-
container.style.
|
|
5713
|
-
container.style.
|
|
6556
|
+
container.style.overflowX = "hidden";
|
|
6557
|
+
container.style.overflowY = "auto";
|
|
6558
|
+
container.style.padding = "16px 8px";
|
|
5714
6559
|
container.style.backgroundColor = "#f1f5f9";
|
|
5715
6560
|
container.style.display = "flex";
|
|
5716
6561
|
container.style.justifyContent = "center";
|
|
@@ -5755,16 +6600,15 @@ var DocPlugin = class {
|
|
|
5755
6600
|
const pageCard = document.createElement("div");
|
|
5756
6601
|
pageCard.className = "fp-doc-page-card";
|
|
5757
6602
|
pageCard.style.width = "816px";
|
|
5758
|
-
pageCard.style.
|
|
6603
|
+
pageCard.style.minHeight = "1056px";
|
|
5759
6604
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5760
|
-
pageCard.style.boxShadow = "0
|
|
6605
|
+
pageCard.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5761
6606
|
pageCard.style.borderRadius = "4px";
|
|
5762
|
-
pageCard.style.padding = "
|
|
6607
|
+
pageCard.style.padding = "72px 56px";
|
|
5763
6608
|
pageCard.style.boxSizing = "border-box";
|
|
5764
|
-
pageCard.style.overflow = "hidden";
|
|
5765
6609
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5766
6610
|
pageCard.style.transformOrigin = "top center";
|
|
5767
|
-
pageCard.style.transition = "transform 0.
|
|
6611
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
5768
6612
|
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5769
6613
|
pageCard.style.color = "#1e293b";
|
|
5770
6614
|
if (isFallback && i === 0) {
|
|
@@ -5781,34 +6625,15 @@ var DocPlugin = class {
|
|
|
5781
6625
|
container.appendChild(pageCard);
|
|
5782
6626
|
pageCards.push(pageCard);
|
|
5783
6627
|
}
|
|
5784
|
-
let indicator = null;
|
|
5785
|
-
if (totalPages > 1) {
|
|
5786
|
-
indicator = document.createElement("div");
|
|
5787
|
-
indicator.className = "fp-doc-page-indicator";
|
|
5788
|
-
indicator.style.position = "fixed";
|
|
5789
|
-
indicator.style.bottom = "16px";
|
|
5790
|
-
indicator.style.left = "50%";
|
|
5791
|
-
indicator.style.transform = "translateX(-50%)";
|
|
5792
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
5793
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
5794
|
-
indicator.style.color = "#f8fafc";
|
|
5795
|
-
indicator.style.fontSize = "12px";
|
|
5796
|
-
indicator.style.fontWeight = "600";
|
|
5797
|
-
indicator.style.padding = "5px 14px";
|
|
5798
|
-
indicator.style.borderRadius = "20px";
|
|
5799
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
5800
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
5801
|
-
indicator.style.zIndex = "10";
|
|
5802
|
-
indicator.style.userSelect = "none";
|
|
5803
|
-
indicator.style.pointerEvents = "none";
|
|
5804
|
-
indicator.style.textAlign = "center";
|
|
5805
|
-
container.appendChild(indicator);
|
|
5806
|
-
}
|
|
5807
6628
|
let rotation = 0;
|
|
5808
6629
|
const applyTransform = () => {
|
|
5809
6630
|
const activeCard = pageCards[currentPage - 1];
|
|
5810
6631
|
if (activeCard) {
|
|
5811
6632
|
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
6633
|
+
const baseH = activeCard.offsetHeight || 1056;
|
|
6634
|
+
const scaledH = baseH * scale;
|
|
6635
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6636
|
+
activeCard.style.marginBottom = `${extraH + 32}px`;
|
|
5812
6637
|
}
|
|
5813
6638
|
};
|
|
5814
6639
|
const showPage = (pageNum) => {
|
|
@@ -5821,35 +6646,39 @@ var DocPlugin = class {
|
|
|
5821
6646
|
card.style.display = "none";
|
|
5822
6647
|
}
|
|
5823
6648
|
});
|
|
5824
|
-
if (indicator) {
|
|
5825
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5826
|
-
}
|
|
5827
6649
|
container.scrollTop = 0;
|
|
5828
6650
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5829
6651
|
};
|
|
5830
6652
|
if (totalPages > 1) {
|
|
5831
6653
|
showPage(1);
|
|
5832
6654
|
}
|
|
5833
|
-
let fitMode = "width";
|
|
6655
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6656
|
+
let isUserZoomed = false;
|
|
5834
6657
|
const calculateFitScale = (mode = fitMode) => {
|
|
5835
6658
|
const elW = 816;
|
|
5836
6659
|
const elH = 1056;
|
|
5837
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
5838
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
6660
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6661
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5839
6662
|
const sW = availW / elW;
|
|
5840
6663
|
const sH = availH / elH;
|
|
5841
6664
|
if (mode === "page") {
|
|
5842
|
-
return Math.max(0.
|
|
6665
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5843
6666
|
}
|
|
5844
|
-
return Math.max(0.
|
|
6667
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5845
6668
|
};
|
|
6669
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6670
|
+
if (!isUserZoomed) {
|
|
6671
|
+
scale = calculateFitScale(fitMode);
|
|
6672
|
+
applyTransform();
|
|
6673
|
+
}
|
|
6674
|
+
}) : null;
|
|
6675
|
+
resizeObserver?.observe(ctx.container);
|
|
5846
6676
|
setTimeout(() => {
|
|
5847
|
-
|
|
5848
|
-
scale = calculateFitScale("width");
|
|
6677
|
+
scale = calculateFitScale(fitMode);
|
|
5849
6678
|
applyTransform();
|
|
5850
6679
|
}, 60);
|
|
5851
6680
|
const cleanup = () => {
|
|
5852
|
-
|
|
6681
|
+
resizeObserver?.disconnect();
|
|
5853
6682
|
container.remove();
|
|
5854
6683
|
ctx.container.innerHTML = "";
|
|
5855
6684
|
};
|
|
@@ -5860,21 +6689,25 @@ var DocPlugin = class {
|
|
|
5860
6689
|
getCurrentPage: () => currentPage,
|
|
5861
6690
|
goToPage: (page) => showPage(page),
|
|
5862
6691
|
zoomIn: () => {
|
|
6692
|
+
isUserZoomed = true;
|
|
5863
6693
|
scale += 0.15;
|
|
5864
6694
|
applyTransform();
|
|
5865
6695
|
},
|
|
5866
6696
|
zoomOut: () => {
|
|
6697
|
+
isUserZoomed = true;
|
|
5867
6698
|
scale = Math.max(0.2, scale - 0.15);
|
|
5868
6699
|
applyTransform();
|
|
5869
6700
|
},
|
|
5870
6701
|
getZoom: () => scale,
|
|
5871
6702
|
setZoom: (level) => {
|
|
6703
|
+
isUserZoomed = true;
|
|
5872
6704
|
scale = level;
|
|
5873
6705
|
applyTransform();
|
|
5874
6706
|
},
|
|
5875
6707
|
fitToPage: () => {
|
|
5876
|
-
|
|
5877
|
-
|
|
6708
|
+
isUserZoomed = false;
|
|
6709
|
+
fitMode = "width";
|
|
6710
|
+
scale = calculateFitScale("width");
|
|
5878
6711
|
rotation = 0;
|
|
5879
6712
|
applyTransform();
|
|
5880
6713
|
},
|
|
@@ -6251,25 +7084,31 @@ ${chartSvg}
|
|
|
6251
7084
|
i++;
|
|
6252
7085
|
continue;
|
|
6253
7086
|
}
|
|
6254
|
-
if (
|
|
7087
|
+
if (/^\d{1,2}$/.test(line.trim())) {
|
|
7088
|
+
i++;
|
|
7089
|
+
continue;
|
|
7090
|
+
}
|
|
7091
|
+
const isShortLine = line.length < 60 && !line.endsWith(".") && !line.endsWith(",");
|
|
7092
|
+
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));
|
|
7093
|
+
if (isTitleLike) {
|
|
6255
7094
|
if (inList) {
|
|
6256
7095
|
html += "</ul>";
|
|
6257
7096
|
inList = false;
|
|
6258
7097
|
}
|
|
6259
|
-
html += `<h2 style="font-size:
|
|
7098
|
+
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 18px 0 10px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line, sanitizeOptions)}</h2>`;
|
|
6260
7099
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
6261
7100
|
if (!inList) {
|
|
6262
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
7101
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
6263
7102
|
inList = true;
|
|
6264
7103
|
}
|
|
6265
7104
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
6266
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
7105
|
+
html += `<li style="margin: 4px 0; line-height: 1.5; font-size: 11pt; color: #1e293b;">${DOMPurify6.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
6267
7106
|
} else {
|
|
6268
7107
|
if (inList) {
|
|
6269
7108
|
html += "</ul>";
|
|
6270
7109
|
inList = false;
|
|
6271
7110
|
}
|
|
6272
|
-
html += `<p style="line-height: 1.
|
|
7111
|
+
html += `<p style="line-height: 1.5; margin: 0 0 12px 0; font-size: 11pt; color: #1e293b; text-align: justify;">${DOMPurify6.sanitize(line, sanitizeOptions)}</p>`;
|
|
6273
7112
|
}
|
|
6274
7113
|
i++;
|
|
6275
7114
|
}
|