@files-preview-app/preview-file 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/angular.cjs +1307 -468
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +1307 -468
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +1307 -468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d-B79v0jxi.d.cts +570 -0
- package/dist/index.d-B79v0jxi.d.ts +570 -0
- package/dist/index.d.cts +3227 -19
- package/dist/index.d.ts +3227 -19
- package/dist/index.js +1307 -468
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1307 -468
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -16
- package/dist/react.d.ts +1 -16
- package/dist/react.js +1307 -468
- package/dist/react.js.map +1 -1
- package/dist/styles.css +195 -14
- package/dist/vue.cjs +1307 -468
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1307 -468
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
package/dist/react.js
CHANGED
|
@@ -495,8 +495,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
495
495
|
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>`;
|
|
496
496
|
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>`;
|
|
497
497
|
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>`;
|
|
498
|
-
var
|
|
499
|
-
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>`;
|
|
498
|
+
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>`;
|
|
500
499
|
var ICON_MAP = {
|
|
501
500
|
"zoom-in": ICON_ZOOM_IN,
|
|
502
501
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -523,28 +522,177 @@ var ICON_MAP = {
|
|
|
523
522
|
"forward-10": ICON_FAST_FORWARD,
|
|
524
523
|
"rewind": ICON_REWIND,
|
|
525
524
|
"replay-10": ICON_REWIND,
|
|
526
|
-
"speed": ICON_SPEED,
|
|
527
525
|
"open-window": ICON_EXTERNAL_WINDOW,
|
|
528
|
-
"external-window": ICON_EXTERNAL_WINDOW
|
|
526
|
+
"external-window": ICON_EXTERNAL_WINDOW,
|
|
527
|
+
"openWindow": ICON_EXTERNAL_WINDOW,
|
|
528
|
+
"openSeparateWindow": ICON_EXTERNAL_WINDOW
|
|
529
529
|
};
|
|
530
530
|
var ToolbarController = class {
|
|
531
531
|
el;
|
|
532
532
|
toolbarEl;
|
|
533
533
|
actions = [];
|
|
534
|
+
config = {};
|
|
534
535
|
pageInputEl = null;
|
|
535
536
|
pageLabelEl = null;
|
|
536
|
-
|
|
537
|
+
prevPageBtn = null;
|
|
538
|
+
nextPageBtn = null;
|
|
539
|
+
constructor(container, config) {
|
|
537
540
|
this.el = container;
|
|
541
|
+
if (config) this.config = { ...config };
|
|
538
542
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
539
543
|
this.el.appendChild(this.toolbarEl);
|
|
540
544
|
}
|
|
545
|
+
setConfig(config) {
|
|
546
|
+
this.config = { ...config };
|
|
547
|
+
this.render();
|
|
548
|
+
}
|
|
549
|
+
getConfig() {
|
|
550
|
+
return { ...this.config };
|
|
551
|
+
}
|
|
552
|
+
hideAction(actionId) {
|
|
553
|
+
this.config[actionId] = false;
|
|
554
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = false;
|
|
555
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = false;
|
|
556
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
557
|
+
this.config.fitPage = false;
|
|
558
|
+
this.config.fitToPage = false;
|
|
559
|
+
this.config.fitWidth = false;
|
|
560
|
+
}
|
|
561
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
|
|
562
|
+
if (actionId === "fullscreen") this.config.fullscreen = false;
|
|
563
|
+
if (actionId === "download") this.config.download = false;
|
|
564
|
+
if (actionId === "print") this.config.print = false;
|
|
565
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
566
|
+
this.config.openWindow = false;
|
|
567
|
+
this.config.openSeparateWindow = false;
|
|
568
|
+
}
|
|
569
|
+
if (actionId === "copy") this.config.copy = false;
|
|
570
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
571
|
+
this.config.pageNav = false;
|
|
572
|
+
this.config.pagination = false;
|
|
573
|
+
}
|
|
574
|
+
this.render();
|
|
575
|
+
}
|
|
576
|
+
showAction(actionId) {
|
|
577
|
+
this.config[actionId] = true;
|
|
578
|
+
if (actionId === "zoom-in" || actionId === "zoomIn") this.config.zoomIn = true;
|
|
579
|
+
if (actionId === "zoom-out" || actionId === "zoomOut") this.config.zoomOut = true;
|
|
580
|
+
if (actionId === "fit-page" || actionId === "fitPage" || actionId === "fitToPage" || actionId === "fit-width") {
|
|
581
|
+
this.config.fitPage = true;
|
|
582
|
+
this.config.fitToPage = true;
|
|
583
|
+
this.config.fitWidth = true;
|
|
584
|
+
}
|
|
585
|
+
if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
|
|
586
|
+
if (actionId === "fullscreen") this.config.fullscreen = true;
|
|
587
|
+
if (actionId === "download") this.config.download = true;
|
|
588
|
+
if (actionId === "print") this.config.print = true;
|
|
589
|
+
if (actionId === "open-window" || actionId === "openWindow" || actionId === "openSeparateWindow") {
|
|
590
|
+
this.config.openWindow = true;
|
|
591
|
+
this.config.openSeparateWindow = true;
|
|
592
|
+
}
|
|
593
|
+
if (actionId === "copy") this.config.copy = true;
|
|
594
|
+
if (actionId === "page-nav" || actionId === "pageNav" || actionId === "pagination") {
|
|
595
|
+
this.config.pageNav = true;
|
|
596
|
+
this.config.pagination = true;
|
|
597
|
+
}
|
|
598
|
+
this.render();
|
|
599
|
+
}
|
|
600
|
+
normalizeActionId(actionId) {
|
|
601
|
+
if (actionId === "zoomIn") return "zoom-in";
|
|
602
|
+
if (actionId === "zoomOut") return "zoom-out";
|
|
603
|
+
if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
|
|
604
|
+
if (actionId === "rotateCW") return "rotate-cw";
|
|
605
|
+
if (actionId === "rotateCCW") return "rotate-ccw";
|
|
606
|
+
if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
|
|
607
|
+
if (actionId === "pageNav") return "page-nav";
|
|
608
|
+
return actionId;
|
|
609
|
+
}
|
|
610
|
+
enableAction(actionId) {
|
|
611
|
+
const norm = this.normalizeActionId(actionId);
|
|
612
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
613
|
+
if (btn) {
|
|
614
|
+
btn.disabled = false;
|
|
615
|
+
btn.classList.remove("disabled");
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
disableAction(actionId) {
|
|
619
|
+
const norm = this.normalizeActionId(actionId);
|
|
620
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
621
|
+
if (btn) {
|
|
622
|
+
btn.disabled = true;
|
|
623
|
+
btn.classList.add("disabled");
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
setActionActive(actionId, active) {
|
|
627
|
+
const norm = this.normalizeActionId(actionId);
|
|
628
|
+
const btn = this.toolbarEl.querySelector(`button[data-action-id="${actionId}"], button[data-action-id="${norm}"]`);
|
|
629
|
+
if (btn) {
|
|
630
|
+
if (active) {
|
|
631
|
+
btn.classList.add("active");
|
|
632
|
+
} else {
|
|
633
|
+
btn.classList.remove("active");
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
isActionEnabled(action) {
|
|
638
|
+
const c = this.config;
|
|
639
|
+
const id = action.id;
|
|
640
|
+
if (c[id] === false) return false;
|
|
641
|
+
if (id === "zoom-in" && (c.zoomIn === false || c["zoom-in"] === false)) return false;
|
|
642
|
+
if (id === "zoom-out" && (c.zoomOut === false || c["zoom-out"] === false)) return false;
|
|
643
|
+
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)) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
if (id === "fullscreen" && c.fullscreen === false) return false;
|
|
650
|
+
if (id === "download" && c.download === false) return false;
|
|
651
|
+
if (id === "print" && c.print === false) return false;
|
|
652
|
+
if ((id === "open-window" || id === "external-window") && (c.openWindow === false || c.openSeparateWindow === false || c["open-window"] === false)) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
if (id === "copy" && c.copy === false) return false;
|
|
656
|
+
if (id === "thumbnails" && c.thumbnails === false) return false;
|
|
657
|
+
if (id === "page-nav" && (c.pageNav === false || c.pagination === false || c["page-nav"] === false)) {
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
if ((id === "prev" || id === "page-prev") && (c.prevPage === false || c.prev === false || c["prev"] === false || c.pageNav === false || c.pagination === false)) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
if ((id === "next" || id === "page-next") && (c.nextPage === false || c.next === false || c["next"] === false || c.pageNav === false || c.pagination === false)) {
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
if (id === "play" && c.play === false) return false;
|
|
667
|
+
if (id === "pause" && c.pause === false) return false;
|
|
668
|
+
if ((id === "fast-forward" || id === "forward-10") && (c.fastForward === false || c["fast-forward"] === false)) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
if ((id === "rewind" || id === "replay-10") && (c.rewind === false || c["rewind"] === false)) {
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
if (id === "speed" && c.speed === false) return false;
|
|
675
|
+
return true;
|
|
676
|
+
}
|
|
541
677
|
setPage(page, max) {
|
|
542
678
|
if (this.pageInputEl) {
|
|
543
679
|
this.pageInputEl.value = page.toString();
|
|
680
|
+
if (max !== void 0) {
|
|
681
|
+
this.pageInputEl.max = max.toString();
|
|
682
|
+
}
|
|
544
683
|
}
|
|
545
684
|
if (max !== void 0 && this.pageLabelEl) {
|
|
546
685
|
this.pageLabelEl.textContent = ` / ${max}`;
|
|
547
686
|
}
|
|
687
|
+
const currentMax = max !== void 0 ? max : parseInt(this.pageInputEl?.max || "1", 10) || 1;
|
|
688
|
+
if (this.prevPageBtn) {
|
|
689
|
+
this.prevPageBtn.disabled = page <= 1;
|
|
690
|
+
this.prevPageBtn.style.opacity = page <= 1 ? "0.4" : "1";
|
|
691
|
+
}
|
|
692
|
+
if (this.nextPageBtn) {
|
|
693
|
+
this.nextPageBtn.disabled = page >= currentMax;
|
|
694
|
+
this.nextPageBtn.style.opacity = page >= currentMax ? "0.4" : "1";
|
|
695
|
+
}
|
|
548
696
|
}
|
|
549
697
|
update(actions) {
|
|
550
698
|
this.actions = actions;
|
|
@@ -567,8 +715,9 @@ var ToolbarController = class {
|
|
|
567
715
|
view: [],
|
|
568
716
|
actions: []
|
|
569
717
|
};
|
|
570
|
-
const
|
|
571
|
-
const
|
|
718
|
+
const enabledActions = this.actions.filter((a) => this.isActionEnabled(a));
|
|
719
|
+
const hasPageNav = enabledActions.some((a) => a.type === "page-nav");
|
|
720
|
+
const effectiveActions = hasPageNav ? enabledActions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : enabledActions;
|
|
572
721
|
for (const action of effectiveActions) {
|
|
573
722
|
if (groups[action.group]) {
|
|
574
723
|
groups[action.group].push(action);
|
|
@@ -628,6 +777,13 @@ var ToolbarController = class {
|
|
|
628
777
|
action.execute("go", val);
|
|
629
778
|
});
|
|
630
779
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
780
|
+
const curVal = action.value ?? 1;
|
|
781
|
+
prevBtn.disabled = curVal <= 1;
|
|
782
|
+
prevBtn.style.opacity = curVal <= 1 ? "0.4" : "1";
|
|
783
|
+
nextBtn.disabled = curVal >= max;
|
|
784
|
+
nextBtn.style.opacity = curVal >= max ? "0.4" : "1";
|
|
785
|
+
this.prevPageBtn = prevBtn;
|
|
786
|
+
this.nextPageBtn = nextBtn;
|
|
631
787
|
this.pageInputEl = input;
|
|
632
788
|
this.pageLabelEl = label;
|
|
633
789
|
groupEl.appendChild(prevBtn);
|
|
@@ -683,25 +839,63 @@ var ToolbarController = class {
|
|
|
683
839
|
var ThumbnailPanel = class {
|
|
684
840
|
el;
|
|
685
841
|
panelEl;
|
|
842
|
+
listEl;
|
|
843
|
+
headerEl;
|
|
686
844
|
thumbnails = [];
|
|
687
845
|
onSelect;
|
|
846
|
+
onToggleCallback;
|
|
688
847
|
activeIndex = 0;
|
|
689
|
-
|
|
848
|
+
observer;
|
|
849
|
+
renderedIndices = /* @__PURE__ */ new Set();
|
|
850
|
+
constructor(container, onToggle) {
|
|
690
851
|
this.el = container;
|
|
852
|
+
this.onToggleCallback = onToggle;
|
|
691
853
|
this.panelEl = createElement("div", { className: "fp-thumbnail-panel hidden" });
|
|
854
|
+
this.panelEl.style.width = "0px";
|
|
855
|
+
this.panelEl.style.minWidth = "0px";
|
|
856
|
+
this.panelEl.style.opacity = "0";
|
|
857
|
+
this.headerEl = createElement("div", { className: "fp-thumbnail-header" });
|
|
858
|
+
const title = createElement("span", { className: "fp-thumbnail-title" }, "Pages");
|
|
859
|
+
const closeBtn = createElement("button", {
|
|
860
|
+
className: "fp-thumbnail-close-btn",
|
|
861
|
+
title: "Close Thumbnails",
|
|
862
|
+
type: "button"
|
|
863
|
+
});
|
|
864
|
+
closeBtn.innerHTML = ICON_CLOSE;
|
|
865
|
+
closeBtn.addEventListener("click", (e) => {
|
|
866
|
+
e.stopPropagation();
|
|
867
|
+
this.hide();
|
|
868
|
+
});
|
|
869
|
+
this.headerEl.appendChild(title);
|
|
870
|
+
this.headerEl.appendChild(closeBtn);
|
|
871
|
+
this.listEl = createElement("div", { className: "fp-thumbnail-list" });
|
|
872
|
+
this.panelEl.appendChild(this.headerEl);
|
|
873
|
+
this.panelEl.appendChild(this.listEl);
|
|
692
874
|
this.el.appendChild(this.panelEl);
|
|
693
875
|
}
|
|
876
|
+
isOpen() {
|
|
877
|
+
return !this.panelEl.classList.contains("hidden") && this.panelEl.style.width !== "0px";
|
|
878
|
+
}
|
|
694
879
|
update(thumbnails, onSelect) {
|
|
695
880
|
this.thumbnails = thumbnails;
|
|
696
881
|
this.onSelect = onSelect;
|
|
882
|
+
this.renderedIndices.clear();
|
|
883
|
+
const titleEl = this.headerEl.querySelector(".fp-thumbnail-title");
|
|
884
|
+
if (titleEl) {
|
|
885
|
+
titleEl.textContent = `Pages (${thumbnails.length})`;
|
|
886
|
+
}
|
|
697
887
|
this.render();
|
|
888
|
+
if (this.isOpen()) {
|
|
889
|
+
this.renderAllVisible();
|
|
890
|
+
}
|
|
698
891
|
}
|
|
699
892
|
setActive(index) {
|
|
700
893
|
this.activeIndex = index;
|
|
701
|
-
const items = this.
|
|
894
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
702
895
|
items.forEach((item, i) => {
|
|
703
896
|
if (i === index) {
|
|
704
897
|
item.classList.add("active");
|
|
898
|
+
item.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
705
899
|
} else {
|
|
706
900
|
item.classList.remove("active");
|
|
707
901
|
}
|
|
@@ -709,37 +903,102 @@ var ThumbnailPanel = class {
|
|
|
709
903
|
}
|
|
710
904
|
show() {
|
|
711
905
|
this.panelEl.classList.remove("hidden");
|
|
906
|
+
this.panelEl.style.width = "200px";
|
|
907
|
+
this.panelEl.style.minWidth = "200px";
|
|
908
|
+
this.panelEl.style.opacity = "1";
|
|
909
|
+
this.panelEl.style.display = "flex";
|
|
910
|
+
this.onToggleCallback?.(true);
|
|
911
|
+
this.renderAllVisible();
|
|
712
912
|
}
|
|
713
913
|
hide() {
|
|
714
914
|
this.panelEl.classList.add("hidden");
|
|
915
|
+
this.panelEl.style.width = "0px";
|
|
916
|
+
this.panelEl.style.minWidth = "0px";
|
|
917
|
+
this.panelEl.style.opacity = "0";
|
|
918
|
+
this.onToggleCallback?.(false);
|
|
715
919
|
}
|
|
716
920
|
toggle() {
|
|
717
|
-
this.
|
|
921
|
+
if (this.isOpen()) {
|
|
922
|
+
this.hide();
|
|
923
|
+
} else {
|
|
924
|
+
this.show();
|
|
925
|
+
}
|
|
718
926
|
}
|
|
719
927
|
destroy() {
|
|
928
|
+
if (this.observer) {
|
|
929
|
+
this.observer.disconnect();
|
|
930
|
+
this.observer = void 0;
|
|
931
|
+
}
|
|
932
|
+
this.renderedIndices.clear();
|
|
720
933
|
this.el.innerHTML = "";
|
|
721
934
|
}
|
|
722
|
-
|
|
723
|
-
this.
|
|
935
|
+
renderAllVisible() {
|
|
936
|
+
const items = this.listEl.querySelectorAll(".fp-thumbnail-item");
|
|
937
|
+
items.forEach((item) => {
|
|
938
|
+
const idx = parseInt(item.dataset.thumbIndex || "-1", 10);
|
|
939
|
+
if (idx >= 0 && !this.renderedIndices.has(idx)) {
|
|
940
|
+
this.renderThumbnailItem(idx, item);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
renderThumbnailItem(idx, itemEl) {
|
|
945
|
+
if (this.renderedIndices.has(idx)) return;
|
|
946
|
+
this.renderedIndices.add(idx);
|
|
947
|
+
const canvas = itemEl.querySelector("canvas");
|
|
948
|
+
const thumb = this.thumbnails[idx];
|
|
949
|
+
if (canvas && thumb) {
|
|
950
|
+
Promise.resolve(thumb.render(canvas)).catch((err) => {
|
|
951
|
+
console.warn(`[FilePreview] Error rendering thumbnail ${idx}:`, err);
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
render() {
|
|
956
|
+
if (this.observer) {
|
|
957
|
+
this.observer.disconnect();
|
|
958
|
+
}
|
|
959
|
+
this.listEl.innerHTML = "";
|
|
960
|
+
const useObserver = typeof IntersectionObserver !== "undefined";
|
|
961
|
+
if (useObserver) {
|
|
962
|
+
this.observer = new IntersectionObserver(
|
|
963
|
+
(entries) => {
|
|
964
|
+
for (const entry of entries) {
|
|
965
|
+
if (entry.isIntersecting) {
|
|
966
|
+
const target = entry.target;
|
|
967
|
+
const idx = parseInt(target.dataset.thumbIndex || "-1", 10);
|
|
968
|
+
if (idx >= 0) {
|
|
969
|
+
this.renderThumbnailItem(idx, target);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
root: this.listEl,
|
|
976
|
+
rootMargin: "120px 0px 120px 0px"
|
|
977
|
+
}
|
|
978
|
+
);
|
|
979
|
+
}
|
|
724
980
|
for (let i = 0; i < this.thumbnails.length; i++) {
|
|
725
981
|
const thumb = this.thumbnails[i];
|
|
726
|
-
const itemEl = createElement("div", {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
982
|
+
const itemEl = createElement("div", {
|
|
983
|
+
className: "fp-thumbnail-item" + (i === this.activeIndex ? " active" : "")
|
|
984
|
+
});
|
|
985
|
+
itemEl.dataset.thumbIndex = i.toString();
|
|
730
986
|
itemEl.addEventListener("click", () => {
|
|
731
987
|
this.setActive(i);
|
|
732
988
|
this.onSelect?.(i);
|
|
733
989
|
});
|
|
734
|
-
const
|
|
735
|
-
const
|
|
736
|
-
|
|
990
|
+
const canvasWrapper = createElement("div", { className: "fp-thumbnail-canvas-wrapper" });
|
|
991
|
+
const canvas = createElement("canvas", { width: "130", height: "170" });
|
|
992
|
+
canvasWrapper.appendChild(canvas);
|
|
993
|
+
const label = createElement("span", { className: "fp-thumbnail-label" }, thumb.label || `Page ${i + 1}`);
|
|
994
|
+
itemEl.appendChild(canvasWrapper);
|
|
737
995
|
itemEl.appendChild(label);
|
|
738
|
-
this.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
742
|
-
|
|
996
|
+
this.listEl.appendChild(itemEl);
|
|
997
|
+
if (this.observer) {
|
|
998
|
+
this.observer.observe(itemEl);
|
|
999
|
+
}
|
|
1000
|
+
if (i < 4) {
|
|
1001
|
+
this.renderThumbnailItem(i, itemEl);
|
|
743
1002
|
}
|
|
744
1003
|
}
|
|
745
1004
|
}
|
|
@@ -760,6 +1019,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
760
1019
|
currentOptions = {};
|
|
761
1020
|
resizeObserver = null;
|
|
762
1021
|
fullscreenHandler = null;
|
|
1022
|
+
titleBarEl = null;
|
|
763
1023
|
/**
|
|
764
1024
|
* Register a preview plugin.
|
|
765
1025
|
*/
|
|
@@ -796,6 +1056,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
796
1056
|
}
|
|
797
1057
|
this.currentBuffer = buffer.slice(0);
|
|
798
1058
|
this.currentMetadata = metadata;
|
|
1059
|
+
this.updateTitleBar(options, metadata);
|
|
799
1060
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
800
1061
|
const fileInfo = { metadata, buffer };
|
|
801
1062
|
const matchedPlugin = await this.findPlugin(fileInfo);
|
|
@@ -819,15 +1080,21 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
819
1080
|
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
820
1081
|
const total = payload.total ?? payload.totalPages;
|
|
821
1082
|
this.toolbar?.setPage(payload.page, total);
|
|
1083
|
+
this.thumbnailPanel?.setActive(payload.page - 1);
|
|
822
1084
|
}
|
|
823
1085
|
this.eventEmitter.emit(event, payload);
|
|
824
|
-
}
|
|
1086
|
+
},
|
|
1087
|
+
toggleThumbnails: () => this.toggleThumbnails()
|
|
825
1088
|
});
|
|
826
1089
|
this.activeInstance = instance;
|
|
827
1090
|
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
1091
|
+
instance.toggleThumbnails = () => this.toggleThumbnails();
|
|
828
1092
|
this.hideLoading();
|
|
829
1093
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
830
|
-
|
|
1094
|
+
const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
|
|
1095
|
+
if (isToolbarVisible && this.toolbar) {
|
|
1096
|
+
const toolbarConfig = this.extractToolbarConfig(options);
|
|
1097
|
+
this.toolbar.setConfig(toolbarConfig);
|
|
831
1098
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
832
1099
|
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
833
1100
|
if (!hasFullscreen && this.wrapperEl) {
|
|
@@ -877,6 +1144,12 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
877
1144
|
}
|
|
878
1145
|
});
|
|
879
1146
|
}
|
|
1147
|
+
const thumbAction = actions.find((a) => a.id === "thumbnails");
|
|
1148
|
+
if (thumbAction) {
|
|
1149
|
+
thumbAction.execute = () => {
|
|
1150
|
+
this.toggleThumbnails();
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
880
1153
|
this.toolbar.update(actions);
|
|
881
1154
|
this.toolbar.show();
|
|
882
1155
|
}
|
|
@@ -961,7 +1234,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
961
1234
|
if (targetUrl) {
|
|
962
1235
|
const newWin2 = window.open(targetUrl, "_blank");
|
|
963
1236
|
if (!newWin2) {
|
|
964
|
-
|
|
1237
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
965
1238
|
return null;
|
|
966
1239
|
}
|
|
967
1240
|
return newWin2;
|
|
@@ -969,7 +1242,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
969
1242
|
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
970
1243
|
const newWin = window.open("", "_blank");
|
|
971
1244
|
if (!newWin) {
|
|
972
|
-
|
|
1245
|
+
console.warn("[FilePreviewViewer] Popup blocker prevented opening the preview in a separate window.");
|
|
973
1246
|
return null;
|
|
974
1247
|
}
|
|
975
1248
|
newWin.document.title = title;
|
|
@@ -1046,6 +1319,7 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1046
1319
|
this.currentBuffer = null;
|
|
1047
1320
|
this.currentMetadata = null;
|
|
1048
1321
|
this.currentContainer = null;
|
|
1322
|
+
this.titleBarEl = null;
|
|
1049
1323
|
}
|
|
1050
1324
|
/**
|
|
1051
1325
|
* Get the currently active preview instance.
|
|
@@ -1053,7 +1327,218 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1053
1327
|
getInstance() {
|
|
1054
1328
|
return this.activeInstance;
|
|
1055
1329
|
}
|
|
1330
|
+
// --- Toolbar Configuration & Feature Toggles ---
|
|
1331
|
+
/**
|
|
1332
|
+
* Configure toolbar features dynamically through options or methods.
|
|
1333
|
+
* e.g. viewer.setToolbarConfig({ zoomIn: false, print: false })
|
|
1334
|
+
*/
|
|
1335
|
+
setToolbarConfig(config) {
|
|
1336
|
+
this.toolbar?.setConfig(config);
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Get current toolbar configuration.
|
|
1340
|
+
*/
|
|
1341
|
+
getToolbarConfig() {
|
|
1342
|
+
return this.toolbar?.getConfig() ?? {};
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Hide a specific toolbar action by ID or alias (e.g. 'zoom-in', 'print', 'download').
|
|
1346
|
+
*/
|
|
1347
|
+
hideToolbarAction(actionId) {
|
|
1348
|
+
this.toolbar?.hideAction(actionId);
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Show a specific toolbar action by ID or alias.
|
|
1352
|
+
*/
|
|
1353
|
+
showToolbarAction(actionId) {
|
|
1354
|
+
this.toolbar?.showAction(actionId);
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Enable a specific toolbar action button.
|
|
1358
|
+
*/
|
|
1359
|
+
enableToolbarAction(actionId) {
|
|
1360
|
+
this.toolbar?.enableAction(actionId);
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Disable a specific toolbar action button.
|
|
1364
|
+
*/
|
|
1365
|
+
disableToolbarAction(actionId) {
|
|
1366
|
+
this.toolbar?.disableAction(actionId);
|
|
1367
|
+
}
|
|
1368
|
+
// --- Programmatic Toolbar Action Methods ---
|
|
1369
|
+
/**
|
|
1370
|
+
* Fit document to page so it fills the frame width with minimal margins.
|
|
1371
|
+
*/
|
|
1372
|
+
fitToPage() {
|
|
1373
|
+
this.activeInstance?.fitToPage?.();
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Zoom in.
|
|
1377
|
+
*/
|
|
1378
|
+
zoomIn() {
|
|
1379
|
+
this.activeInstance?.zoomIn?.();
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Zoom out.
|
|
1383
|
+
*/
|
|
1384
|
+
zoomOut() {
|
|
1385
|
+
this.activeInstance?.zoomOut?.();
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Set specific zoom level.
|
|
1389
|
+
*/
|
|
1390
|
+
setZoom(level) {
|
|
1391
|
+
this.activeInstance?.setZoom?.(level);
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Get current zoom level.
|
|
1395
|
+
*/
|
|
1396
|
+
getZoom() {
|
|
1397
|
+
return this.activeInstance?.getZoom?.() ?? 1;
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Rotate 90 degrees clockwise.
|
|
1401
|
+
*/
|
|
1402
|
+
rotateCW() {
|
|
1403
|
+
this.activeInstance?.rotateCW?.();
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Rotate 90 degrees counter-clockwise.
|
|
1407
|
+
*/
|
|
1408
|
+
rotateCCW() {
|
|
1409
|
+
this.activeInstance?.rotateCCW?.();
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Navigate to a specific page number.
|
|
1413
|
+
*/
|
|
1414
|
+
goToPage(page) {
|
|
1415
|
+
this.activeInstance?.goToPage?.(page);
|
|
1416
|
+
this.toolbar?.setPage(page);
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Navigate to next page.
|
|
1420
|
+
*/
|
|
1421
|
+
nextPage() {
|
|
1422
|
+
const cur = this.getCurrentPage();
|
|
1423
|
+
const max = this.getPageCount();
|
|
1424
|
+
if (cur < max) {
|
|
1425
|
+
this.goToPage(cur + 1);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Navigate to previous page.
|
|
1430
|
+
*/
|
|
1431
|
+
prevPage() {
|
|
1432
|
+
const cur = this.getCurrentPage();
|
|
1433
|
+
if (cur > 1) {
|
|
1434
|
+
this.goToPage(cur - 1);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Get total page count.
|
|
1439
|
+
*/
|
|
1440
|
+
getPageCount() {
|
|
1441
|
+
return this.activeInstance?.getPageCount?.() ?? 1;
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Get current page number.
|
|
1445
|
+
*/
|
|
1446
|
+
getCurrentPage() {
|
|
1447
|
+
return this.activeInstance?.getCurrentPage?.() ?? 1;
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Download the current document.
|
|
1451
|
+
*/
|
|
1452
|
+
download() {
|
|
1453
|
+
this.activeInstance?.download?.();
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Print the current document.
|
|
1457
|
+
*/
|
|
1458
|
+
print() {
|
|
1459
|
+
this.activeInstance?.print?.();
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Toggle fullscreen mode.
|
|
1463
|
+
*/
|
|
1464
|
+
toggleFullscreen() {
|
|
1465
|
+
try {
|
|
1466
|
+
if (!document.fullscreenElement) {
|
|
1467
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
1468
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
1469
|
+
} else {
|
|
1470
|
+
document.exitFullscreen?.();
|
|
1471
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
1472
|
+
}
|
|
1473
|
+
} catch {
|
|
1474
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
1475
|
+
}
|
|
1476
|
+
setTimeout(() => {
|
|
1477
|
+
this.activeInstance?.fitToPage?.();
|
|
1478
|
+
}, 120);
|
|
1479
|
+
}
|
|
1480
|
+
/**
|
|
1481
|
+
* Toggle thumbnails sidebar panel.
|
|
1482
|
+
*/
|
|
1483
|
+
toggleThumbnails() {
|
|
1484
|
+
if (!this.thumbnailPanel) return;
|
|
1485
|
+
this.thumbnailPanel.toggle();
|
|
1486
|
+
const isOpen = this.thumbnailPanel.isOpen();
|
|
1487
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1488
|
+
setTimeout(() => {
|
|
1489
|
+
this.activeInstance?.fitToPage?.();
|
|
1490
|
+
}, 260);
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Set whether to display the file name / title bar above the toolbar.
|
|
1494
|
+
*/
|
|
1495
|
+
setShowFileName(show) {
|
|
1496
|
+
if (this.currentOptions) {
|
|
1497
|
+
this.currentOptions.showFileName = show;
|
|
1498
|
+
}
|
|
1499
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Set or override the displayed file name in the preview panel.
|
|
1503
|
+
*/
|
|
1504
|
+
setFileName(name) {
|
|
1505
|
+
if (this.currentOptions) {
|
|
1506
|
+
this.currentOptions.fileName = name;
|
|
1507
|
+
}
|
|
1508
|
+
this.updateTitleBar(this.currentOptions, this.currentMetadata);
|
|
1509
|
+
}
|
|
1056
1510
|
// --- Private methods ---
|
|
1511
|
+
updateTitleBar(options, metadata) {
|
|
1512
|
+
if (!this.titleBarEl) return;
|
|
1513
|
+
const show = options?.showFileName !== false;
|
|
1514
|
+
if (!show) {
|
|
1515
|
+
this.titleBarEl.style.display = "none";
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const name = options?.fileName || metadata?.name || this.currentMetadata?.name || "";
|
|
1519
|
+
if (!name) {
|
|
1520
|
+
this.titleBarEl.style.display = "none";
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
this.titleBarEl.style.display = "flex";
|
|
1524
|
+
const ext = metadata?.extension || (name.includes(".") ? "." + name.split(".").pop() : "");
|
|
1525
|
+
const badge = ext ? ext.replace(".", "").toUpperCase() : "";
|
|
1526
|
+
this.titleBarEl.innerHTML = `
|
|
1527
|
+
<div class="fp-titlebar-info">
|
|
1528
|
+
<span class="fp-titlebar-icon">\u{1F4C4}</span>
|
|
1529
|
+
<span class="fp-titlebar-name" title="${name}">${name}</span>
|
|
1530
|
+
${badge ? `<span class="fp-titlebar-badge">${badge}</span>` : ""}
|
|
1531
|
+
</div>
|
|
1532
|
+
`;
|
|
1533
|
+
}
|
|
1534
|
+
extractToolbarConfig(options) {
|
|
1535
|
+
if (!options) return {};
|
|
1536
|
+
const nested = typeof options.toolbar === "object" ? options.toolbar : {};
|
|
1537
|
+
return {
|
|
1538
|
+
...options,
|
|
1539
|
+
...nested
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1057
1542
|
abort() {
|
|
1058
1543
|
if (this.abortController) {
|
|
1059
1544
|
this.abortController.abort();
|
|
@@ -1096,17 +1581,29 @@ var FilePreviewViewer = class _FilePreviewViewer {
|
|
|
1096
1581
|
bodyEl.className = "fp-body";
|
|
1097
1582
|
bodyEl.appendChild(thumbnailEl);
|
|
1098
1583
|
bodyEl.appendChild(this.contentEl);
|
|
1584
|
+
const titleBarEl = document.createElement("div");
|
|
1585
|
+
titleBarEl.className = "fp-titlebar";
|
|
1586
|
+
this.titleBarEl = titleBarEl;
|
|
1587
|
+
this.updateTitleBar(options, this.currentMetadata);
|
|
1099
1588
|
if (toolbarPos === "top") {
|
|
1589
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1100
1590
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1101
1591
|
this.wrapperEl.appendChild(bodyEl);
|
|
1102
1592
|
} else {
|
|
1593
|
+
this.wrapperEl.appendChild(titleBarEl);
|
|
1103
1594
|
this.wrapperEl.appendChild(bodyEl);
|
|
1104
1595
|
this.wrapperEl.appendChild(toolbarEl);
|
|
1105
1596
|
}
|
|
1106
1597
|
container.innerHTML = "";
|
|
1107
1598
|
container.appendChild(this.wrapperEl);
|
|
1108
|
-
|
|
1109
|
-
this.
|
|
1599
|
+
const initialToolbarConfig = this.extractToolbarConfig(options);
|
|
1600
|
+
this.toolbar = new ToolbarController(toolbarEl, initialToolbarConfig);
|
|
1601
|
+
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl, (isOpen) => {
|
|
1602
|
+
this.toolbar?.setActionActive("thumbnails", isOpen);
|
|
1603
|
+
setTimeout(() => {
|
|
1604
|
+
this.activeInstance?.fitToPage?.();
|
|
1605
|
+
}, 260);
|
|
1606
|
+
});
|
|
1110
1607
|
this.setupKeyboardShortcuts();
|
|
1111
1608
|
this.setupDragAndDrop(container, options);
|
|
1112
1609
|
this.setupResizeAndFullscreenListeners();
|
|
@@ -1496,6 +1993,14 @@ var PdfPlugin = class {
|
|
|
1496
1993
|
group: "zoom",
|
|
1497
1994
|
execute: () => instance.fitToPage?.()
|
|
1498
1995
|
},
|
|
1996
|
+
{
|
|
1997
|
+
id: "fit-width",
|
|
1998
|
+
icon: "fit-width",
|
|
1999
|
+
label: "Fit to Width",
|
|
2000
|
+
type: "button",
|
|
2001
|
+
group: "zoom",
|
|
2002
|
+
execute: () => instance.fitToWidth?.()
|
|
2003
|
+
},
|
|
1499
2004
|
{
|
|
1500
2005
|
id: "rotate-cw",
|
|
1501
2006
|
icon: "rotate-cw",
|
|
@@ -1504,6 +2009,14 @@ var PdfPlugin = class {
|
|
|
1504
2009
|
group: "view",
|
|
1505
2010
|
execute: () => instance.rotateCW?.()
|
|
1506
2011
|
},
|
|
2012
|
+
{
|
|
2013
|
+
id: "rotate-ccw",
|
|
2014
|
+
icon: "rotate-ccw",
|
|
2015
|
+
label: "Rotate Counter-Clockwise",
|
|
2016
|
+
type: "button",
|
|
2017
|
+
group: "view",
|
|
2018
|
+
execute: () => instance.rotateCCW?.()
|
|
2019
|
+
},
|
|
1507
2020
|
{
|
|
1508
2021
|
id: "download",
|
|
1509
2022
|
icon: "download",
|
|
@@ -1535,12 +2048,13 @@ var PdfPlugin = class {
|
|
|
1535
2048
|
container.className = "fp-pdf-container";
|
|
1536
2049
|
container.style.width = "100%";
|
|
1537
2050
|
container.style.height = "100%";
|
|
1538
|
-
container.style.
|
|
2051
|
+
container.style.overflowX = "hidden";
|
|
2052
|
+
container.style.overflowY = "auto";
|
|
1539
2053
|
container.style.display = "flex";
|
|
1540
2054
|
container.style.flexDirection = "column";
|
|
1541
2055
|
container.style.alignItems = "center";
|
|
1542
2056
|
container.style.justifyContent = "flex-start";
|
|
1543
|
-
container.style.padding = "
|
|
2057
|
+
container.style.padding = "16px 8px";
|
|
1544
2058
|
container.style.backgroundColor = "#0f172a";
|
|
1545
2059
|
container.style.boxSizing = "border-box";
|
|
1546
2060
|
container.style.position = "relative";
|
|
@@ -1551,30 +2065,12 @@ var PdfPlugin = class {
|
|
|
1551
2065
|
pageCard.style.borderRadius = "4px";
|
|
1552
2066
|
pageCard.style.overflow = "hidden";
|
|
1553
2067
|
pageCard.style.lineHeight = "0";
|
|
1554
|
-
pageCard.style.transition = "transform 0.15s ease";
|
|
1555
2068
|
pageCard.style.position = "relative";
|
|
1556
2069
|
pageCard.style.flexShrink = "0";
|
|
2070
|
+
pageCard.style.transition = "box-shadow 0.2s ease";
|
|
1557
2071
|
let canvas = document.createElement("canvas");
|
|
1558
2072
|
pageCard.appendChild(canvas);
|
|
1559
2073
|
container.appendChild(pageCard);
|
|
1560
|
-
const indicator = document.createElement("div");
|
|
1561
|
-
indicator.className = "fp-pdf-page-indicator";
|
|
1562
|
-
indicator.style.position = "sticky";
|
|
1563
|
-
indicator.style.bottom = "16px";
|
|
1564
|
-
indicator.style.marginTop = "16px";
|
|
1565
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1566
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
1567
|
-
indicator.style.color = "#f8fafc";
|
|
1568
|
-
indicator.style.fontSize = "12px";
|
|
1569
|
-
indicator.style.fontWeight = "600";
|
|
1570
|
-
indicator.style.padding = "5px 14px";
|
|
1571
|
-
indicator.style.borderRadius = "20px";
|
|
1572
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1573
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1574
|
-
indicator.style.zIndex = "10";
|
|
1575
|
-
indicator.style.userSelect = "none";
|
|
1576
|
-
indicator.style.pointerEvents = "none";
|
|
1577
|
-
container.appendChild(indicator);
|
|
1578
2074
|
ctx.container.appendChild(container);
|
|
1579
2075
|
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1580
2076
|
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
@@ -1590,8 +2086,9 @@ var PdfPlugin = class {
|
|
|
1590
2086
|
let currentPage = 1;
|
|
1591
2087
|
let zoomScale = 1;
|
|
1592
2088
|
let rotation = 0;
|
|
1593
|
-
let fitMode = "
|
|
2089
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
1594
2090
|
let currentRenderTask = null;
|
|
2091
|
+
let textLayerDiv = null;
|
|
1595
2092
|
const renderPage = async (pageNum) => {
|
|
1596
2093
|
if (currentRenderTask) {
|
|
1597
2094
|
try {
|
|
@@ -1603,30 +2100,37 @@ var PdfPlugin = class {
|
|
|
1603
2100
|
const newCanvas = document.createElement("canvas");
|
|
1604
2101
|
pageCard.replaceChild(newCanvas, canvas);
|
|
1605
2102
|
canvas = newCanvas;
|
|
2103
|
+
if (textLayerDiv) {
|
|
2104
|
+
textLayerDiv.remove();
|
|
2105
|
+
textLayerDiv = null;
|
|
2106
|
+
}
|
|
1606
2107
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1607
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1608
2108
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1609
2109
|
const page = await pdfDoc.getPage(currentPage);
|
|
1610
2110
|
const containerWidth = container.clientWidth || 900;
|
|
1611
2111
|
const containerHeight = container.clientHeight || 700;
|
|
1612
2112
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1613
|
-
const availWidth = Math.max(
|
|
1614
|
-
const availHeight = Math.max(
|
|
2113
|
+
const availWidth = Math.max(280, containerWidth - 36);
|
|
2114
|
+
const availHeight = Math.max(280, containerHeight - 32);
|
|
1615
2115
|
const scaleW = availWidth / unscaledVp.width;
|
|
1616
2116
|
const scaleH = availHeight / unscaledVp.height;
|
|
1617
2117
|
let fitScale;
|
|
1618
2118
|
if (fitMode === "page") {
|
|
1619
|
-
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
2119
|
+
fitScale = Math.max(0.2, Math.min(4, Math.min(scaleW, scaleH)));
|
|
1620
2120
|
} else {
|
|
1621
|
-
fitScale = Math.max(0.
|
|
2121
|
+
fitScale = Math.max(0.2, Math.min(4, scaleW));
|
|
1622
2122
|
}
|
|
1623
2123
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1624
2124
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1625
2125
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
2126
|
+
const displayWidth = Math.floor(viewport.width);
|
|
2127
|
+
const displayHeight = Math.floor(viewport.height);
|
|
1626
2128
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1627
2129
|
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1628
|
-
canvas.style.width = `${
|
|
1629
|
-
canvas.style.height = `${
|
|
2130
|
+
canvas.style.width = `${displayWidth}px`;
|
|
2131
|
+
canvas.style.height = `${displayHeight}px`;
|
|
2132
|
+
pageCard.style.width = `${displayWidth}px`;
|
|
2133
|
+
pageCard.style.height = `${displayHeight}px`;
|
|
1630
2134
|
const canvasCtx = canvas.getContext("2d");
|
|
1631
2135
|
if (!canvasCtx) return;
|
|
1632
2136
|
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
@@ -1640,9 +2144,31 @@ var PdfPlugin = class {
|
|
|
1640
2144
|
if (err?.name !== "RenderingCancelledException") {
|
|
1641
2145
|
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1642
2146
|
}
|
|
2147
|
+
return;
|
|
1643
2148
|
} finally {
|
|
1644
2149
|
currentRenderTask = null;
|
|
1645
2150
|
}
|
|
2151
|
+
try {
|
|
2152
|
+
textLayerDiv = document.createElement("div");
|
|
2153
|
+
textLayerDiv.className = "textLayer";
|
|
2154
|
+
textLayerDiv.style.width = `${displayWidth}px`;
|
|
2155
|
+
textLayerDiv.style.height = `${displayHeight}px`;
|
|
2156
|
+
textLayerDiv.style.position = "absolute";
|
|
2157
|
+
textLayerDiv.style.top = "0";
|
|
2158
|
+
textLayerDiv.style.left = "0";
|
|
2159
|
+
textLayerDiv.style.lineHeight = "1";
|
|
2160
|
+
pageCard.appendChild(textLayerDiv);
|
|
2161
|
+
if (pdfjsLib.TextLayer) {
|
|
2162
|
+
const textLayer = new pdfjsLib.TextLayer({
|
|
2163
|
+
textContentSource: page.streamTextContent(),
|
|
2164
|
+
container: textLayerDiv,
|
|
2165
|
+
viewport
|
|
2166
|
+
});
|
|
2167
|
+
await textLayer.render();
|
|
2168
|
+
}
|
|
2169
|
+
} catch (err) {
|
|
2170
|
+
console.debug("[PdfPlugin] TextLayer notice:", err);
|
|
2171
|
+
}
|
|
1646
2172
|
};
|
|
1647
2173
|
renderPage(1);
|
|
1648
2174
|
let resizeTimer = null;
|
|
@@ -1652,11 +2178,48 @@ var PdfPlugin = class {
|
|
|
1652
2178
|
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1653
2179
|
renderPage(currentPage);
|
|
1654
2180
|
}
|
|
1655
|
-
},
|
|
2181
|
+
}, 120);
|
|
1656
2182
|
});
|
|
1657
2183
|
resizeObserver.observe(container);
|
|
2184
|
+
const onWheel = (e) => {
|
|
2185
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2186
|
+
e.preventDefault();
|
|
2187
|
+
const delta = e.deltaY > 0 ? -0.15 : 0.15;
|
|
2188
|
+
zoomScale = Math.max(0.25, Math.min(4, Math.round((zoomScale + delta) * 100) / 100));
|
|
2189
|
+
renderPage(currentPage);
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
2193
|
+
const onKeyDown = (e) => {
|
|
2194
|
+
const tag = e.target?.tagName?.toLowerCase();
|
|
2195
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
2196
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
2197
|
+
if (currentPage < totalPages) {
|
|
2198
|
+
e.preventDefault();
|
|
2199
|
+
container.scrollTop = 0;
|
|
2200
|
+
renderPage(currentPage + 1);
|
|
2201
|
+
}
|
|
2202
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
2203
|
+
if (currentPage > 1) {
|
|
2204
|
+
e.preventDefault();
|
|
2205
|
+
container.scrollTop = 0;
|
|
2206
|
+
renderPage(currentPage - 1);
|
|
2207
|
+
}
|
|
2208
|
+
} else if (e.key === "Home") {
|
|
2209
|
+
e.preventDefault();
|
|
2210
|
+
container.scrollTop = 0;
|
|
2211
|
+
renderPage(1);
|
|
2212
|
+
} else if (e.key === "End") {
|
|
2213
|
+
e.preventDefault();
|
|
2214
|
+
container.scrollTop = 0;
|
|
2215
|
+
renderPage(totalPages);
|
|
2216
|
+
}
|
|
2217
|
+
};
|
|
2218
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1658
2219
|
const cleanup = () => {
|
|
1659
2220
|
resizeObserver.disconnect();
|
|
2221
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2222
|
+
container.removeEventListener("wheel", onWheel);
|
|
1660
2223
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1661
2224
|
if (currentRenderTask) {
|
|
1662
2225
|
try {
|
|
@@ -1675,22 +2238,26 @@ var PdfPlugin = class {
|
|
|
1675
2238
|
const instance = {
|
|
1676
2239
|
destroy: cleanup,
|
|
1677
2240
|
zoomIn: () => {
|
|
1678
|
-
zoomScale = Math.min(
|
|
2241
|
+
zoomScale = Math.min(4, Math.round((zoomScale + 0.2) * 10) / 10);
|
|
1679
2242
|
renderPage(currentPage);
|
|
1680
2243
|
},
|
|
1681
2244
|
zoomOut: () => {
|
|
1682
|
-
zoomScale = Math.max(0.
|
|
2245
|
+
zoomScale = Math.max(0.25, Math.round((zoomScale - 0.2) * 10) / 10);
|
|
1683
2246
|
renderPage(currentPage);
|
|
1684
2247
|
},
|
|
1685
2248
|
getZoom: () => zoomScale,
|
|
1686
2249
|
setZoom: (level) => {
|
|
1687
|
-
zoomScale = Math.max(0.
|
|
2250
|
+
zoomScale = Math.max(0.25, Math.min(4, level));
|
|
1688
2251
|
renderPage(currentPage);
|
|
1689
2252
|
},
|
|
1690
2253
|
fitToPage: () => {
|
|
1691
|
-
fitMode =
|
|
2254
|
+
fitMode = "page";
|
|
2255
|
+
zoomScale = 1;
|
|
2256
|
+
renderPage(currentPage);
|
|
2257
|
+
},
|
|
2258
|
+
fitToWidth: () => {
|
|
2259
|
+
fitMode = "width";
|
|
1692
2260
|
zoomScale = 1;
|
|
1693
|
-
rotation = 0;
|
|
1694
2261
|
renderPage(currentPage);
|
|
1695
2262
|
},
|
|
1696
2263
|
rotateCW: () => {
|
|
@@ -1708,6 +2275,9 @@ var PdfPlugin = class {
|
|
|
1708
2275
|
container.scrollTop = 0;
|
|
1709
2276
|
renderPage(page);
|
|
1710
2277
|
},
|
|
2278
|
+
toggleThumbnails: () => {
|
|
2279
|
+
ctx?.toggleThumbnails?.();
|
|
2280
|
+
},
|
|
1711
2281
|
download: () => {
|
|
1712
2282
|
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1713
2283
|
const url = URL.createObjectURL(blob);
|
|
@@ -1741,7 +2311,7 @@ var PdfPlugin = class {
|
|
|
1741
2311
|
},
|
|
1742
2312
|
getThumbnails: async () => {
|
|
1743
2313
|
const thumbnails = [];
|
|
1744
|
-
const count =
|
|
2314
|
+
const count = totalPages;
|
|
1745
2315
|
for (let i = 1; i <= count; i++) {
|
|
1746
2316
|
thumbnails.push({
|
|
1747
2317
|
index: i,
|
|
@@ -1749,9 +2319,10 @@ var PdfPlugin = class {
|
|
|
1749
2319
|
render: async (thumbCanvas) => {
|
|
1750
2320
|
try {
|
|
1751
2321
|
const p = await pdfDoc.getPage(i);
|
|
1752
|
-
const baseVp = p.getViewport({ scale: 1 });
|
|
1753
|
-
const
|
|
1754
|
-
const
|
|
2322
|
+
const baseVp = p.getViewport({ scale: 1, rotation });
|
|
2323
|
+
const targetW = thumbCanvas.width || 130;
|
|
2324
|
+
const thumbScale = targetW / baseVp.width;
|
|
2325
|
+
const thumbVp = p.getViewport({ scale: thumbScale, rotation });
|
|
1755
2326
|
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1756
2327
|
const tCtx = thumbCanvas.getContext("2d");
|
|
1757
2328
|
if (tCtx) {
|
|
@@ -2095,28 +2666,26 @@ var DocxPlugin = class {
|
|
|
2095
2666
|
getToolbarActions(instance) {
|
|
2096
2667
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2097
2668
|
const actions = [];
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
if (
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
instance.goToPage?.(page);
|
|
2116
|
-
}
|
|
2669
|
+
actions.push({
|
|
2670
|
+
id: "page-nav",
|
|
2671
|
+
icon: "",
|
|
2672
|
+
label: "Page Navigation",
|
|
2673
|
+
type: "page-nav",
|
|
2674
|
+
group: "navigation",
|
|
2675
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2676
|
+
max: totalPages,
|
|
2677
|
+
execute: (action, page) => {
|
|
2678
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2679
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2680
|
+
if (action === "prev") {
|
|
2681
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2682
|
+
} else if (action === "next") {
|
|
2683
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2684
|
+
} else if (typeof page === "number") {
|
|
2685
|
+
instance.goToPage?.(page);
|
|
2117
2686
|
}
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2687
|
+
}
|
|
2688
|
+
});
|
|
2120
2689
|
actions.push(
|
|
2121
2690
|
{
|
|
2122
2691
|
id: "zoom-out",
|
|
@@ -2182,11 +2751,17 @@ var DocxPlugin = class {
|
|
|
2182
2751
|
wrapper.className = "fp-docx-wrapper";
|
|
2183
2752
|
wrapper.style.transformOrigin = "top center";
|
|
2184
2753
|
wrapper.style.transition = "transform 0.2s ease";
|
|
2185
|
-
wrapper.style.padding = "
|
|
2186
|
-
wrapper.style.maxWidth = "
|
|
2754
|
+
wrapper.style.padding = "0";
|
|
2755
|
+
wrapper.style.maxWidth = "none";
|
|
2756
|
+
wrapper.style.width = "816px";
|
|
2187
2757
|
wrapper.style.margin = "0 auto";
|
|
2758
|
+
wrapper.style.display = "flex";
|
|
2759
|
+
wrapper.style.flexDirection = "column";
|
|
2760
|
+
wrapper.style.alignItems = "center";
|
|
2188
2761
|
wrapper.style.boxSizing = "border-box";
|
|
2189
|
-
ctx.container.style.
|
|
2762
|
+
ctx.container.style.overflowX = "hidden";
|
|
2763
|
+
ctx.container.style.overflowY = "auto";
|
|
2764
|
+
ctx.container.style.padding = "16px 8px";
|
|
2190
2765
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
2191
2766
|
ctx.container.appendChild(wrapper);
|
|
2192
2767
|
const styleOverride = document.createElement("style");
|
|
@@ -2360,39 +2935,13 @@ var DocxPlugin = class {
|
|
|
2360
2935
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2361
2936
|
const totalPages = Math.max(1, pageElements.length);
|
|
2362
2937
|
let currentPage = 1;
|
|
2363
|
-
let indicator = null;
|
|
2364
|
-
if (totalPages > 1) {
|
|
2365
|
-
indicator = document.createElement("div");
|
|
2366
|
-
indicator.className = "fp-docx-page-indicator";
|
|
2367
|
-
indicator.style.position = "sticky";
|
|
2368
|
-
indicator.style.bottom = "16px";
|
|
2369
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2370
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
2371
|
-
indicator.style.color = "#f8fafc";
|
|
2372
|
-
indicator.style.fontSize = "12px";
|
|
2373
|
-
indicator.style.fontWeight = "600";
|
|
2374
|
-
indicator.style.padding = "5px 14px";
|
|
2375
|
-
indicator.style.borderRadius = "20px";
|
|
2376
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2377
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2378
|
-
indicator.style.zIndex = "10";
|
|
2379
|
-
indicator.style.userSelect = "none";
|
|
2380
|
-
indicator.style.pointerEvents = "none";
|
|
2381
|
-
indicator.style.textAlign = "center";
|
|
2382
|
-
indicator.style.width = "fit-content";
|
|
2383
|
-
indicator.style.margin = "16px auto 0";
|
|
2384
|
-
ctx.container.appendChild(indicator);
|
|
2385
|
-
}
|
|
2386
2938
|
const showPage = (pageNum) => {
|
|
2387
2939
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2388
2940
|
if (pageElements.length > 1) {
|
|
2389
2941
|
pageElements.forEach((sec, idx) => {
|
|
2390
|
-
sec.style.display = idx + 1 === currentPage ? "
|
|
2942
|
+
sec.style.display = idx + 1 === currentPage ? "" : "none";
|
|
2391
2943
|
});
|
|
2392
2944
|
}
|
|
2393
|
-
if (indicator) {
|
|
2394
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2395
|
-
}
|
|
2396
2945
|
ctx.container.scrollTop = 0;
|
|
2397
2946
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2398
2947
|
};
|
|
@@ -2401,31 +2950,46 @@ var DocxPlugin = class {
|
|
|
2401
2950
|
}
|
|
2402
2951
|
scale = 1;
|
|
2403
2952
|
let rotation = 0;
|
|
2404
|
-
let fitMode = "
|
|
2405
|
-
|
|
2406
|
-
|
|
2953
|
+
let fitMode = "page";
|
|
2954
|
+
let isUserZoomed = false;
|
|
2955
|
+
const calculateFitScale = (_mode = fitMode) => {
|
|
2956
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2407
2957
|
const elW = activeEl.offsetWidth || 816;
|
|
2408
|
-
const
|
|
2409
|
-
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2410
|
-
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2958
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
2411
2959
|
const sW = availW / elW;
|
|
2412
|
-
|
|
2413
|
-
if (mode === "page") {
|
|
2414
|
-
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2415
|
-
}
|
|
2416
|
-
return Math.max(0.65, Math.min(1.05, sW));
|
|
2960
|
+
return Math.max(0.35, Math.min(3, sW));
|
|
2417
2961
|
};
|
|
2418
2962
|
const applyTransform = () => {
|
|
2419
2963
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2420
2964
|
wrapper.style.transformOrigin = "top center";
|
|
2965
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
|
|
2966
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
2967
|
+
if (scale > 1) {
|
|
2968
|
+
wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
|
|
2969
|
+
} else {
|
|
2970
|
+
wrapper.style.marginBottom = "32px";
|
|
2971
|
+
}
|
|
2421
2972
|
};
|
|
2973
|
+
let resizeObserver = null;
|
|
2974
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
2975
|
+
resizeObserver = new ResizeObserver(() => {
|
|
2976
|
+
if (!isUserZoomed) {
|
|
2977
|
+
const newFit = calculateFitScale("page");
|
|
2978
|
+
if (Math.abs(scale - newFit) > 0.015) {
|
|
2979
|
+
scale = newFit;
|
|
2980
|
+
applyTransform();
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
});
|
|
2984
|
+
resizeObserver.observe(ctx.container);
|
|
2985
|
+
}
|
|
2422
2986
|
setTimeout(() => {
|
|
2423
|
-
|
|
2424
|
-
scale = calculateFitScale("width");
|
|
2987
|
+
scale = calculateFitScale("page");
|
|
2425
2988
|
applyTransform();
|
|
2426
|
-
},
|
|
2989
|
+
}, 40);
|
|
2427
2990
|
const cleanup = () => {
|
|
2428
|
-
|
|
2991
|
+
resizeObserver?.disconnect();
|
|
2992
|
+
resizeObserver = null;
|
|
2429
2993
|
for (const url of createdBlobUrls) {
|
|
2430
2994
|
URL.revokeObjectURL(url);
|
|
2431
2995
|
}
|
|
@@ -2442,21 +3006,24 @@ var DocxPlugin = class {
|
|
|
2442
3006
|
showPage(page);
|
|
2443
3007
|
},
|
|
2444
3008
|
zoomIn: () => {
|
|
2445
|
-
|
|
3009
|
+
isUserZoomed = true;
|
|
3010
|
+
scale = Math.min(3.5, scale + 0.15);
|
|
2446
3011
|
applyTransform();
|
|
2447
3012
|
},
|
|
2448
3013
|
zoomOut: () => {
|
|
3014
|
+
isUserZoomed = true;
|
|
2449
3015
|
scale = Math.max(0.2, scale - 0.15);
|
|
2450
3016
|
applyTransform();
|
|
2451
3017
|
},
|
|
2452
3018
|
getZoom: () => scale,
|
|
2453
3019
|
setZoom: (level) => {
|
|
3020
|
+
isUserZoomed = true;
|
|
2454
3021
|
scale = level;
|
|
2455
3022
|
applyTransform();
|
|
2456
3023
|
},
|
|
2457
3024
|
fitToPage: () => {
|
|
2458
|
-
|
|
2459
|
-
scale = calculateFitScale(
|
|
3025
|
+
isUserZoomed = false;
|
|
3026
|
+
scale = calculateFitScale("page");
|
|
2460
3027
|
rotation = 0;
|
|
2461
3028
|
applyTransform();
|
|
2462
3029
|
},
|
|
@@ -2846,7 +3413,7 @@ var ExcelPlugin = class {
|
|
|
2846
3413
|
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
2847
3414
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
2848
3415
|
];
|
|
2849
|
-
weight =
|
|
3416
|
+
weight = 85;
|
|
2850
3417
|
supports(file) {
|
|
2851
3418
|
const ext = file.metadata.extension?.toLowerCase();
|
|
2852
3419
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
@@ -2858,6 +3425,14 @@ var ExcelPlugin = class {
|
|
|
2858
3425
|
getToolbarActions(instance) {
|
|
2859
3426
|
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2860
3427
|
const actions = [];
|
|
3428
|
+
actions.push({
|
|
3429
|
+
id: "thumbnails",
|
|
3430
|
+
icon: "thumbnails",
|
|
3431
|
+
label: "Sheet Thumbnails",
|
|
3432
|
+
type: "button",
|
|
3433
|
+
group: "navigation",
|
|
3434
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3435
|
+
});
|
|
2861
3436
|
if (totalSheets > 1) {
|
|
2862
3437
|
actions.push({
|
|
2863
3438
|
id: "page-nav",
|
|
@@ -2940,6 +3515,16 @@ var ExcelPlugin = class {
|
|
|
2940
3515
|
execute: () => {
|
|
2941
3516
|
instance.print?.();
|
|
2942
3517
|
}
|
|
3518
|
+
},
|
|
3519
|
+
{
|
|
3520
|
+
id: "open-window",
|
|
3521
|
+
icon: "open-window",
|
|
3522
|
+
label: "Open in Separate Full Window",
|
|
3523
|
+
type: "button",
|
|
3524
|
+
group: "actions",
|
|
3525
|
+
execute: () => {
|
|
3526
|
+
instance.openInSeparateWindow?.();
|
|
3527
|
+
}
|
|
2943
3528
|
}
|
|
2944
3529
|
);
|
|
2945
3530
|
return actions;
|
|
@@ -3105,6 +3690,63 @@ var ExcelPlugin = class {
|
|
|
3105
3690
|
},
|
|
3106
3691
|
getPageCount: () => sheetNames.length,
|
|
3107
3692
|
getCurrentPage: () => currentSheetIndex,
|
|
3693
|
+
getThumbnails: () => {
|
|
3694
|
+
return sheetNames.map((name, idx) => ({
|
|
3695
|
+
index: idx,
|
|
3696
|
+
label: name,
|
|
3697
|
+
render: async (canvas) => {
|
|
3698
|
+
canvas.width = 140;
|
|
3699
|
+
canvas.height = 100;
|
|
3700
|
+
const c = canvas.getContext("2d");
|
|
3701
|
+
if (!c) return;
|
|
3702
|
+
c.fillStyle = "#ffffff";
|
|
3703
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3704
|
+
c.fillStyle = "#107c41";
|
|
3705
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3706
|
+
c.fillStyle = "#ffffff";
|
|
3707
|
+
c.font = 'bold 8px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
3708
|
+
c.fillText(`\u{1F4CA} ${name.slice(0, 16)}`, 6, 11);
|
|
3709
|
+
const startY = 17;
|
|
3710
|
+
const rowH = 13;
|
|
3711
|
+
const colW = 30;
|
|
3712
|
+
const colHeaders = ["A", "B", "C", "D"];
|
|
3713
|
+
c.fillStyle = "#f1f5f9";
|
|
3714
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3715
|
+
c.strokeStyle = "#cbd5e1";
|
|
3716
|
+
c.lineWidth = 0.8;
|
|
3717
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3718
|
+
c.fillStyle = "#64748b";
|
|
3719
|
+
c.font = "bold 7px sans-serif";
|
|
3720
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3721
|
+
c.fillText(colHeaders[ci], 14 + ci * colW, startY + 9);
|
|
3722
|
+
}
|
|
3723
|
+
const ws = wb?.Sheets[name];
|
|
3724
|
+
for (let ri = 1; ri <= 5; ri++) {
|
|
3725
|
+
const y = startY + ri * rowH;
|
|
3726
|
+
if (y > canvas.height - 2) break;
|
|
3727
|
+
c.fillStyle = "#f8fafc";
|
|
3728
|
+
c.fillRect(0, y, 12, rowH);
|
|
3729
|
+
c.fillStyle = "#94a3b8";
|
|
3730
|
+
c.font = "6px sans-serif";
|
|
3731
|
+
c.fillText(String(ri), 3, y + 9);
|
|
3732
|
+
c.strokeStyle = "#e2e8f0";
|
|
3733
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3734
|
+
c.fillStyle = "#334155";
|
|
3735
|
+
c.font = "6px sans-serif";
|
|
3736
|
+
for (let ci = 0; ci < colHeaders.length; ci++) {
|
|
3737
|
+
const cellRef = `${colHeaders[ci]}${ri}`;
|
|
3738
|
+
const cellVal = ws?.[cellRef]?.w || ws?.[cellRef]?.v;
|
|
3739
|
+
if (cellVal !== void 0) {
|
|
3740
|
+
c.fillText(String(cellVal).slice(0, 6), 14 + ci * colW, y + 9);
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
c.strokeStyle = "#cbd5e1";
|
|
3745
|
+
c.lineWidth = 1;
|
|
3746
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
3747
|
+
}
|
|
3748
|
+
}));
|
|
3749
|
+
},
|
|
3108
3750
|
download: () => {
|
|
3109
3751
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
3110
3752
|
const url = URL.createObjectURL(blob);
|
|
@@ -3137,7 +3779,39 @@ var CsvPlugin = class {
|
|
|
3137
3779
|
return ext === ".csv" || ext === ".tsv" || mime === "text/csv" || mime === "text/tab-separated-values";
|
|
3138
3780
|
}
|
|
3139
3781
|
getToolbarActions(instance) {
|
|
3140
|
-
|
|
3782
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3783
|
+
const actions = [];
|
|
3784
|
+
actions.push({
|
|
3785
|
+
id: "thumbnails",
|
|
3786
|
+
icon: "thumbnails",
|
|
3787
|
+
label: "Page Thumbnails",
|
|
3788
|
+
type: "button",
|
|
3789
|
+
group: "navigation",
|
|
3790
|
+
execute: () => instance.toggleThumbnails?.()
|
|
3791
|
+
});
|
|
3792
|
+
if (totalPages > 1) {
|
|
3793
|
+
actions.push({
|
|
3794
|
+
id: "page-nav",
|
|
3795
|
+
icon: "",
|
|
3796
|
+
label: "Page Navigation",
|
|
3797
|
+
type: "page-nav",
|
|
3798
|
+
group: "navigation",
|
|
3799
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3800
|
+
max: totalPages,
|
|
3801
|
+
execute: (action, page) => {
|
|
3802
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3803
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3804
|
+
if (action === "prev") {
|
|
3805
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3806
|
+
} else if (action === "next") {
|
|
3807
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3808
|
+
} else if (typeof page === "number") {
|
|
3809
|
+
instance.goToPage?.(page);
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
});
|
|
3813
|
+
}
|
|
3814
|
+
actions.push(
|
|
3141
3815
|
{
|
|
3142
3816
|
id: "zoom-out",
|
|
3143
3817
|
icon: "zoom-out",
|
|
@@ -3158,6 +3832,16 @@ var CsvPlugin = class {
|
|
|
3158
3832
|
instance.zoomIn?.();
|
|
3159
3833
|
}
|
|
3160
3834
|
},
|
|
3835
|
+
{
|
|
3836
|
+
id: "fit-page",
|
|
3837
|
+
icon: "fit-page",
|
|
3838
|
+
label: "Fit to View",
|
|
3839
|
+
type: "button",
|
|
3840
|
+
group: "zoom",
|
|
3841
|
+
execute: () => {
|
|
3842
|
+
instance.fitToPage?.();
|
|
3843
|
+
}
|
|
3844
|
+
},
|
|
3161
3845
|
{
|
|
3162
3846
|
id: "download",
|
|
3163
3847
|
icon: "download",
|
|
@@ -3177,8 +3861,19 @@ var CsvPlugin = class {
|
|
|
3177
3861
|
execute: () => {
|
|
3178
3862
|
instance.print?.();
|
|
3179
3863
|
}
|
|
3864
|
+
},
|
|
3865
|
+
{
|
|
3866
|
+
id: "open-window",
|
|
3867
|
+
icon: "open-window",
|
|
3868
|
+
label: "Open in Separate Full Window",
|
|
3869
|
+
type: "button",
|
|
3870
|
+
group: "actions",
|
|
3871
|
+
execute: () => {
|
|
3872
|
+
instance.openInSeparateWindow?.();
|
|
3873
|
+
}
|
|
3180
3874
|
}
|
|
3181
|
-
|
|
3875
|
+
);
|
|
3876
|
+
return actions;
|
|
3182
3877
|
}
|
|
3183
3878
|
async render(ctx) {
|
|
3184
3879
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -3190,33 +3885,62 @@ var CsvPlugin = class {
|
|
|
3190
3885
|
container.style.padding = "16px";
|
|
3191
3886
|
container.style.boxSizing = "border-box";
|
|
3192
3887
|
container.style.transformOrigin = "top left";
|
|
3888
|
+
const delimiter = ctx.metadata.extension === ".tsv" ? " " : ",";
|
|
3889
|
+
const allLines = text.split(/\r?\n/).filter((r) => r.trim().length > 0);
|
|
3890
|
+
const headerLine = allLines[0] || "";
|
|
3891
|
+
const headerCells = headerLine.split(delimiter);
|
|
3892
|
+
const dataLines = allLines.slice(1);
|
|
3893
|
+
const ROWS_PER_PAGE = 100;
|
|
3894
|
+
const totalPages = Math.max(1, Math.ceil(dataLines.length / ROWS_PER_PAGE));
|
|
3895
|
+
let currentPage = 1;
|
|
3193
3896
|
const table = document.createElement("table");
|
|
3194
3897
|
table.style.borderCollapse = "collapse";
|
|
3195
3898
|
table.style.width = "100%";
|
|
3196
|
-
table.style.fontFamily = "monospace
|
|
3899
|
+
table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace';
|
|
3197
3900
|
table.style.fontSize = "13px";
|
|
3198
|
-
const
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
td.style.fontWeight = "bold";
|
|
3212
|
-
}
|
|
3213
|
-
tr.appendChild(td);
|
|
3901
|
+
const renderPage = (pageNum) => {
|
|
3902
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3903
|
+
table.innerHTML = "";
|
|
3904
|
+
const headerTr = document.createElement("tr");
|
|
3905
|
+
headerCells.forEach((cell) => {
|
|
3906
|
+
const th = document.createElement("th");
|
|
3907
|
+
th.textContent = cell.trim();
|
|
3908
|
+
th.style.border = "1px solid #d0d7de";
|
|
3909
|
+
th.style.padding = "8px 12px";
|
|
3910
|
+
th.style.backgroundColor = "#f6f8fa";
|
|
3911
|
+
th.style.fontWeight = "600";
|
|
3912
|
+
th.style.whiteSpace = "nowrap";
|
|
3913
|
+
headerTr.appendChild(th);
|
|
3214
3914
|
});
|
|
3215
|
-
table.appendChild(
|
|
3216
|
-
|
|
3915
|
+
table.appendChild(headerTr);
|
|
3916
|
+
const start = (currentPage - 1) * ROWS_PER_PAGE;
|
|
3917
|
+
const end = Math.min(dataLines.length, start + ROWS_PER_PAGE);
|
|
3918
|
+
const pageRows = dataLines.slice(start, end);
|
|
3919
|
+
pageRows.forEach((row, idx) => {
|
|
3920
|
+
const tr = document.createElement("tr");
|
|
3921
|
+
if (idx % 2 === 1) tr.style.backgroundColor = "#f8fafc";
|
|
3922
|
+
const cells = row.split(delimiter);
|
|
3923
|
+
cells.forEach((cell) => {
|
|
3924
|
+
const td = document.createElement("td");
|
|
3925
|
+
td.textContent = cell.trim();
|
|
3926
|
+
td.style.border = "1px solid #d0d7de";
|
|
3927
|
+
td.style.padding = "6px 12px";
|
|
3928
|
+
td.style.whiteSpace = "nowrap";
|
|
3929
|
+
tr.appendChild(td);
|
|
3930
|
+
});
|
|
3931
|
+
table.appendChild(tr);
|
|
3932
|
+
});
|
|
3933
|
+
container.scrollTop = 0;
|
|
3934
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3935
|
+
};
|
|
3936
|
+
renderPage(1);
|
|
3217
3937
|
container.appendChild(table);
|
|
3218
3938
|
ctx.container.appendChild(container);
|
|
3219
3939
|
let scale = 1;
|
|
3940
|
+
const applyScale = () => {
|
|
3941
|
+
container.style.transform = `scale(${scale})`;
|
|
3942
|
+
container.style.transformOrigin = "top left";
|
|
3943
|
+
};
|
|
3220
3944
|
const cleanup = () => {
|
|
3221
3945
|
container.remove();
|
|
3222
3946
|
ctx.container.innerHTML = "";
|
|
@@ -3224,22 +3948,86 @@ var CsvPlugin = class {
|
|
|
3224
3948
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3225
3949
|
return {
|
|
3226
3950
|
destroy: cleanup,
|
|
3951
|
+
getPageCount: () => totalPages,
|
|
3952
|
+
getCurrentPage: () => currentPage,
|
|
3953
|
+
goToPage: (page) => renderPage(page),
|
|
3954
|
+
getThumbnails: () => {
|
|
3955
|
+
const thumbnails = [];
|
|
3956
|
+
for (let i = 0; i < totalPages; i++) {
|
|
3957
|
+
const pageIdx = i;
|
|
3958
|
+
const startRow = pageIdx * ROWS_PER_PAGE + 1;
|
|
3959
|
+
const endRow = Math.min(dataLines.length, (pageIdx + 1) * ROWS_PER_PAGE);
|
|
3960
|
+
const label = totalPages === 1 ? "Table" : `Page ${pageIdx + 1} (${startRow}-${endRow})`;
|
|
3961
|
+
thumbnails.push({
|
|
3962
|
+
index: pageIdx,
|
|
3963
|
+
label,
|
|
3964
|
+
render: async (canvas) => {
|
|
3965
|
+
canvas.width = 140;
|
|
3966
|
+
canvas.height = 100;
|
|
3967
|
+
const c = canvas.getContext("2d");
|
|
3968
|
+
if (!c) return;
|
|
3969
|
+
c.fillStyle = "#ffffff";
|
|
3970
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
3971
|
+
c.fillStyle = "#2563eb";
|
|
3972
|
+
c.fillRect(0, 0, canvas.width, 16);
|
|
3973
|
+
c.fillStyle = "#ffffff";
|
|
3974
|
+
c.font = "bold 8px sans-serif";
|
|
3975
|
+
c.fillText(`\u{1F4C8} ${label.slice(0, 18)}`, 6, 11);
|
|
3976
|
+
const startY = 17;
|
|
3977
|
+
const rowH = 13;
|
|
3978
|
+
const colW = 28;
|
|
3979
|
+
const cols = Math.min(4, headerCells.length || 4);
|
|
3980
|
+
c.fillStyle = "#f1f5f9";
|
|
3981
|
+
c.fillRect(0, startY, canvas.width, rowH);
|
|
3982
|
+
c.strokeStyle = "#cbd5e1";
|
|
3983
|
+
c.lineWidth = 0.8;
|
|
3984
|
+
c.strokeRect(0, startY, canvas.width, rowH);
|
|
3985
|
+
c.fillStyle = "#64748b";
|
|
3986
|
+
c.font = "bold 7px sans-serif";
|
|
3987
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
3988
|
+
const hName = headerCells[ci] || `Col ${ci + 1}`;
|
|
3989
|
+
c.fillText(hName.slice(0, 5), 8 + ci * colW, startY + 9);
|
|
3990
|
+
}
|
|
3991
|
+
const rowsToPreview = dataLines.slice(pageIdx * ROWS_PER_PAGE, pageIdx * ROWS_PER_PAGE + 5);
|
|
3992
|
+
for (let ri = 0; ri < rowsToPreview.length; ri++) {
|
|
3993
|
+
const y = startY + (ri + 1) * rowH;
|
|
3994
|
+
if (y > canvas.height - 2) break;
|
|
3995
|
+
c.strokeStyle = "#e2e8f0";
|
|
3996
|
+
c.strokeRect(0, y, canvas.width, rowH);
|
|
3997
|
+
const cVals = rowsToPreview[ri].split(delimiter);
|
|
3998
|
+
c.fillStyle = "#334155";
|
|
3999
|
+
c.font = "6px sans-serif";
|
|
4000
|
+
for (let ci = 0; ci < cols; ci++) {
|
|
4001
|
+
const val = cVals[ci] || "";
|
|
4002
|
+
c.fillText(val.trim().slice(0, 6), 8 + ci * colW, y + 9);
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
c.strokeStyle = "#cbd5e1";
|
|
4006
|
+
c.lineWidth = 1;
|
|
4007
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4008
|
+
}
|
|
4009
|
+
});
|
|
4010
|
+
}
|
|
4011
|
+
return thumbnails;
|
|
4012
|
+
},
|
|
3227
4013
|
zoomIn: () => {
|
|
3228
4014
|
scale += 0.1;
|
|
3229
|
-
|
|
4015
|
+
applyScale();
|
|
3230
4016
|
},
|
|
3231
4017
|
zoomOut: () => {
|
|
3232
4018
|
scale = Math.max(0.2, scale - 0.1);
|
|
3233
|
-
|
|
4019
|
+
applyScale();
|
|
3234
4020
|
},
|
|
3235
4021
|
getZoom: () => scale,
|
|
3236
4022
|
setZoom: (level) => {
|
|
3237
4023
|
scale = level;
|
|
3238
|
-
|
|
4024
|
+
applyScale();
|
|
3239
4025
|
},
|
|
3240
4026
|
fitToPage: () => {
|
|
3241
|
-
|
|
3242
|
-
|
|
4027
|
+
const availW = Math.max(280, (ctx.container.clientWidth || window.innerWidth) - 48);
|
|
4028
|
+
const tW = table.offsetWidth || 600;
|
|
4029
|
+
scale = Math.max(0.35, Math.min(1, availW / tW));
|
|
4030
|
+
applyScale();
|
|
3243
4031
|
},
|
|
3244
4032
|
download: () => {
|
|
3245
4033
|
const blob = new Blob([ctx.buffer], { type: "text/csv" });
|
|
@@ -3303,28 +4091,34 @@ var CodePlugin = class {
|
|
|
3303
4091
|
getToolbarActions(instance) {
|
|
3304
4092
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3305
4093
|
const actions = [];
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
4094
|
+
actions.push({
|
|
4095
|
+
id: "thumbnails",
|
|
4096
|
+
icon: "thumbnails",
|
|
4097
|
+
label: "Page Thumbnails",
|
|
4098
|
+
type: "button",
|
|
4099
|
+
group: "navigation",
|
|
4100
|
+
execute: () => instance.toggleThumbnails?.()
|
|
4101
|
+
});
|
|
4102
|
+
actions.push({
|
|
4103
|
+
id: "page-nav",
|
|
4104
|
+
icon: "",
|
|
4105
|
+
label: "Page Navigation",
|
|
4106
|
+
type: "page-nav",
|
|
4107
|
+
group: "navigation",
|
|
4108
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4109
|
+
max: totalPages,
|
|
4110
|
+
execute: (action, page) => {
|
|
4111
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4112
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4113
|
+
if (action === "prev") {
|
|
4114
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4115
|
+
} else if (action === "next") {
|
|
4116
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4117
|
+
} else if (typeof page === "number") {
|
|
4118
|
+
instance.goToPage?.(page);
|
|
3325
4119
|
}
|
|
3326
|
-
}
|
|
3327
|
-
}
|
|
4120
|
+
}
|
|
4121
|
+
});
|
|
3328
4122
|
actions.push(
|
|
3329
4123
|
{
|
|
3330
4124
|
id: "zoom-out",
|
|
@@ -3468,16 +4262,19 @@ var CodePlugin = class {
|
|
|
3468
4262
|
let fontSize = 13;
|
|
3469
4263
|
let rotation = 0;
|
|
3470
4264
|
let zoomLevel = 1;
|
|
4265
|
+
let isUserZoomed = false;
|
|
3471
4266
|
const pre = document.createElement("pre");
|
|
3472
4267
|
const code = document.createElement("code");
|
|
3473
4268
|
if (isTxt) {
|
|
4269
|
+
container.style.overflowX = "hidden";
|
|
4270
|
+
container.style.overflowY = "auto";
|
|
3474
4271
|
container.style.backgroundColor = "#f1f5f9";
|
|
3475
|
-
container.style.padding = "
|
|
4272
|
+
container.style.padding = "16px 8px";
|
|
3476
4273
|
container.style.boxSizing = "border-box";
|
|
3477
4274
|
container.style.display = "flex";
|
|
3478
4275
|
container.style.flexDirection = "column";
|
|
3479
4276
|
container.style.alignItems = "center";
|
|
3480
|
-
pre.style.margin = "0";
|
|
4277
|
+
pre.style.margin = "0 auto";
|
|
3481
4278
|
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3482
4279
|
pre.style.fontSize = "13px";
|
|
3483
4280
|
pre.style.color = "#1e293b";
|
|
@@ -3489,10 +4286,12 @@ var CodePlugin = class {
|
|
|
3489
4286
|
pre.style.minHeight = "1056px";
|
|
3490
4287
|
pre.style.padding = "72px 56px";
|
|
3491
4288
|
pre.style.boxSizing = "border-box";
|
|
3492
|
-
pre.style.boxShadow = "0 4px
|
|
4289
|
+
pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
3493
4290
|
pre.style.borderRadius = "4px";
|
|
3494
4291
|
pre.style.transformOrigin = "top center";
|
|
4292
|
+
pre.style.transition = "transform 0.15s ease";
|
|
3495
4293
|
} else {
|
|
4294
|
+
container.style.overflow = "auto";
|
|
3496
4295
|
container.style.backgroundColor = "#1e1e1e";
|
|
3497
4296
|
container.style.color = "#d4d4d4";
|
|
3498
4297
|
container.style.padding = "16px";
|
|
@@ -3524,42 +4323,9 @@ var CodePlugin = class {
|
|
|
3524
4323
|
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3525
4324
|
pre.appendChild(code);
|
|
3526
4325
|
container.appendChild(pre);
|
|
3527
|
-
let indicator = null;
|
|
3528
|
-
if (totalPages > 1) {
|
|
3529
|
-
indicator = document.createElement("div");
|
|
3530
|
-
indicator.className = "fp-code-page-indicator";
|
|
3531
|
-
indicator.style.position = "sticky";
|
|
3532
|
-
indicator.style.bottom = "16px";
|
|
3533
|
-
if (isTxt) {
|
|
3534
|
-
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3535
|
-
indicator.style.color = "#334155";
|
|
3536
|
-
indicator.style.border = "1px solid #e2e8f0";
|
|
3537
|
-
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3538
|
-
} else {
|
|
3539
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3540
|
-
indicator.style.color = "#f8fafc";
|
|
3541
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3542
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3543
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
3544
|
-
}
|
|
3545
|
-
indicator.style.fontSize = "12px";
|
|
3546
|
-
indicator.style.fontWeight = "600";
|
|
3547
|
-
indicator.style.padding = "5px 14px";
|
|
3548
|
-
indicator.style.borderRadius = "20px";
|
|
3549
|
-
indicator.style.zIndex = "10";
|
|
3550
|
-
indicator.style.userSelect = "none";
|
|
3551
|
-
indicator.style.pointerEvents = "none";
|
|
3552
|
-
indicator.style.textAlign = "center";
|
|
3553
|
-
indicator.style.width = "fit-content";
|
|
3554
|
-
indicator.style.margin = "16px auto 0";
|
|
3555
|
-
container.appendChild(indicator);
|
|
3556
|
-
}
|
|
3557
4326
|
const showPage = (pageNum) => {
|
|
3558
4327
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3559
4328
|
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3560
|
-
if (indicator) {
|
|
3561
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3562
|
-
}
|
|
3563
4329
|
container.scrollTop = 0;
|
|
3564
4330
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3565
4331
|
};
|
|
@@ -3567,36 +4333,90 @@ var CodePlugin = class {
|
|
|
3567
4333
|
showPage(1);
|
|
3568
4334
|
}
|
|
3569
4335
|
ctx.container.appendChild(container);
|
|
3570
|
-
const
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
ctx.container.innerHTML = "";
|
|
4336
|
+
const calculateTxtFit = () => {
|
|
4337
|
+
const availW = Math.max(280, container.clientWidth - 32);
|
|
4338
|
+
return Math.max(0.4, Math.min(3, availW / 816));
|
|
3574
4339
|
};
|
|
3575
|
-
ctx.signal.addEventListener("abort", cleanup);
|
|
3576
4340
|
const updateTransform = () => {
|
|
3577
4341
|
if (isTxt) {
|
|
3578
4342
|
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
4343
|
+
const scaledH = 1056 * zoomLevel;
|
|
4344
|
+
const extraH = Math.max(0, scaledH - 1056);
|
|
4345
|
+
pre.style.marginBottom = `${extraH + 32}px`;
|
|
3579
4346
|
} else {
|
|
3580
4347
|
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3581
4348
|
pre.style.fontSize = `${fontSize}px`;
|
|
3582
4349
|
}
|
|
3583
4350
|
};
|
|
4351
|
+
let resizeObserver = null;
|
|
4352
|
+
if (isTxt) {
|
|
4353
|
+
setTimeout(() => {
|
|
4354
|
+
zoomLevel = calculateTxtFit();
|
|
4355
|
+
updateTransform();
|
|
4356
|
+
}, 60);
|
|
4357
|
+
resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
4358
|
+
if (!isUserZoomed) {
|
|
4359
|
+
zoomLevel = calculateTxtFit();
|
|
4360
|
+
updateTransform();
|
|
4361
|
+
}
|
|
4362
|
+
}) : null;
|
|
4363
|
+
resizeObserver?.observe(container);
|
|
4364
|
+
}
|
|
4365
|
+
const cleanup = () => {
|
|
4366
|
+
resizeObserver?.disconnect();
|
|
4367
|
+
container.remove();
|
|
4368
|
+
ctx.container.innerHTML = "";
|
|
4369
|
+
};
|
|
4370
|
+
ctx.signal.addEventListener("abort", cleanup);
|
|
3584
4371
|
return {
|
|
3585
4372
|
destroy: cleanup,
|
|
3586
4373
|
getPageCount: () => totalPages,
|
|
3587
4374
|
getCurrentPage: () => currentPage,
|
|
3588
4375
|
goToPage: (page) => showPage(page),
|
|
4376
|
+
getThumbnails: () => {
|
|
4377
|
+
return rawPages.map((pageText, idx) => ({
|
|
4378
|
+
index: idx,
|
|
4379
|
+
label: `Page ${idx + 1}`,
|
|
4380
|
+
render: async (canvas) => {
|
|
4381
|
+
canvas.width = 140;
|
|
4382
|
+
canvas.height = 180;
|
|
4383
|
+
const c = canvas.getContext("2d");
|
|
4384
|
+
if (!c) return;
|
|
4385
|
+
c.fillStyle = "#ffffff";
|
|
4386
|
+
c.fillRect(0, 0, canvas.width, canvas.height);
|
|
4387
|
+
c.strokeStyle = "#cbd5e1";
|
|
4388
|
+
c.lineWidth = 1;
|
|
4389
|
+
c.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
|
|
4390
|
+
c.fillStyle = "#64748b";
|
|
4391
|
+
const lines = (pageText || "").split("\n").slice(0, 24);
|
|
4392
|
+
const lineH = 6;
|
|
4393
|
+
const startY = 14;
|
|
4394
|
+
const startX = 12;
|
|
4395
|
+
const maxW = canvas.width - 24;
|
|
4396
|
+
c.font = "5px monospace";
|
|
4397
|
+
for (let li = 0; li < lines.length; li++) {
|
|
4398
|
+
const l = lines[li].trim();
|
|
4399
|
+
if (!l) continue;
|
|
4400
|
+
const y = startY + li * lineH;
|
|
4401
|
+
if (y > canvas.height - 12) break;
|
|
4402
|
+
c.fillText(l.slice(0, 30), startX, y, maxW);
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
}));
|
|
4406
|
+
},
|
|
3589
4407
|
zoomIn: () => {
|
|
4408
|
+
isUserZoomed = true;
|
|
3590
4409
|
if (isTxt) {
|
|
3591
|
-
zoomLevel = Math.min(3, zoomLevel + 0.
|
|
4410
|
+
zoomLevel = Math.min(3.5, zoomLevel + 0.15);
|
|
3592
4411
|
} else {
|
|
3593
4412
|
fontSize = Math.min(32, fontSize + 2);
|
|
3594
4413
|
}
|
|
3595
4414
|
updateTransform();
|
|
3596
4415
|
},
|
|
3597
4416
|
zoomOut: () => {
|
|
4417
|
+
isUserZoomed = true;
|
|
3598
4418
|
if (isTxt) {
|
|
3599
|
-
zoomLevel = Math.max(0.1, zoomLevel - 0.
|
|
4419
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.15);
|
|
3600
4420
|
} else {
|
|
3601
4421
|
fontSize = Math.max(8, fontSize - 2);
|
|
3602
4422
|
}
|
|
@@ -3604,6 +4424,7 @@ var CodePlugin = class {
|
|
|
3604
4424
|
},
|
|
3605
4425
|
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3606
4426
|
setZoom: (level) => {
|
|
4427
|
+
isUserZoomed = true;
|
|
3607
4428
|
if (isTxt) {
|
|
3608
4429
|
zoomLevel = level;
|
|
3609
4430
|
} else {
|
|
@@ -3612,9 +4433,10 @@ var CodePlugin = class {
|
|
|
3612
4433
|
updateTransform();
|
|
3613
4434
|
},
|
|
3614
4435
|
fitToPage: () => {
|
|
4436
|
+
isUserZoomed = false;
|
|
3615
4437
|
fontSize = 13;
|
|
3616
4438
|
rotation = 0;
|
|
3617
|
-
zoomLevel = isTxt ?
|
|
4439
|
+
zoomLevel = isTxt ? calculateTxtFit() : 1;
|
|
3618
4440
|
updateTransform();
|
|
3619
4441
|
},
|
|
3620
4442
|
rotateCW: () => {
|
|
@@ -4495,28 +5317,26 @@ var RtfPlugin = class {
|
|
|
4495
5317
|
getToolbarActions(instance) {
|
|
4496
5318
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4497
5319
|
const actions = [];
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
if (
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
instance.goToPage?.(page);
|
|
4516
|
-
}
|
|
5320
|
+
actions.push({
|
|
5321
|
+
id: "page-nav",
|
|
5322
|
+
icon: "",
|
|
5323
|
+
label: "Page Navigation",
|
|
5324
|
+
type: "page-nav",
|
|
5325
|
+
group: "navigation",
|
|
5326
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5327
|
+
max: totalPages,
|
|
5328
|
+
execute: (action, page) => {
|
|
5329
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5330
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5331
|
+
if (action === "prev") {
|
|
5332
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5333
|
+
} else if (action === "next") {
|
|
5334
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5335
|
+
} else if (typeof page === "number") {
|
|
5336
|
+
instance.goToPage?.(page);
|
|
4517
5337
|
}
|
|
4518
|
-
}
|
|
4519
|
-
}
|
|
5338
|
+
}
|
|
5339
|
+
});
|
|
4520
5340
|
actions.push(
|
|
4521
5341
|
{
|
|
4522
5342
|
id: "zoom-out",
|
|
@@ -4588,43 +5408,57 @@ var RtfPlugin = class {
|
|
|
4588
5408
|
async render(ctx) {
|
|
4589
5409
|
const wrapper = document.createElement("div");
|
|
4590
5410
|
wrapper.className = "fp-rtf-wrapper";
|
|
4591
|
-
wrapper.style.padding = "
|
|
4592
|
-
wrapper.style.
|
|
5411
|
+
wrapper.style.padding = "0";
|
|
5412
|
+
wrapper.style.width = "816px";
|
|
4593
5413
|
wrapper.style.margin = "0 auto";
|
|
4594
|
-
wrapper.style.
|
|
4595
|
-
wrapper.style.
|
|
4596
|
-
wrapper.style.
|
|
4597
|
-
wrapper.style.
|
|
5414
|
+
wrapper.style.boxSizing = "border-box";
|
|
5415
|
+
wrapper.style.display = "flex";
|
|
5416
|
+
wrapper.style.flexDirection = "column";
|
|
5417
|
+
wrapper.style.alignItems = "center";
|
|
5418
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4598
5419
|
wrapper.style.transformOrigin = "top center";
|
|
4599
|
-
wrapper.style.transition = "transform 0.
|
|
4600
|
-
ctx.container.style.
|
|
4601
|
-
ctx.container.style.
|
|
5420
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5421
|
+
ctx.container.style.overflowX = "hidden";
|
|
5422
|
+
ctx.container.style.overflowY = "auto";
|
|
5423
|
+
ctx.container.style.padding = "16px 8px";
|
|
4602
5424
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
4603
5425
|
ctx.container.appendChild(wrapper);
|
|
4604
5426
|
let scale = 1;
|
|
4605
5427
|
let rotation = 0;
|
|
4606
5428
|
let pageElements = [];
|
|
4607
|
-
let
|
|
5429
|
+
let isUserZoomed = false;
|
|
5430
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
4608
5431
|
const calculateFitScale = (mode = fitMode) => {
|
|
4609
5432
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4610
|
-
const elW =
|
|
4611
|
-
const singlePageH =
|
|
4612
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
4613
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
5433
|
+
const elW = 816;
|
|
5434
|
+
const singlePageH = activeEl?.offsetHeight || 1056;
|
|
5435
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5436
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
4614
5437
|
const sW = availW / elW;
|
|
4615
5438
|
const sH = availH / singlePageH;
|
|
4616
5439
|
if (mode === "page") {
|
|
4617
|
-
return Math.max(0.
|
|
5440
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
4618
5441
|
}
|
|
4619
|
-
return Math.max(0.
|
|
5442
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
4620
5443
|
};
|
|
4621
5444
|
const applyTransform = () => {
|
|
4622
5445
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4623
5446
|
wrapper.style.transformOrigin = "top center";
|
|
5447
|
+
const activeEl = pageElements[currentPage - 1];
|
|
5448
|
+
const baseH = activeEl?.offsetHeight || 1056;
|
|
5449
|
+
const scaledH = baseH * scale;
|
|
5450
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5451
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
4624
5452
|
};
|
|
5453
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5454
|
+
if (!isUserZoomed) {
|
|
5455
|
+
scale = calculateFitScale(fitMode);
|
|
5456
|
+
applyTransform();
|
|
5457
|
+
}
|
|
5458
|
+
}) : null;
|
|
5459
|
+
resizeObserver?.observe(ctx.container);
|
|
4625
5460
|
setTimeout(() => {
|
|
4626
|
-
|
|
4627
|
-
scale = calculateFitScale("width");
|
|
5461
|
+
scale = calculateFitScale(fitMode);
|
|
4628
5462
|
applyTransform();
|
|
4629
5463
|
}, 60);
|
|
4630
5464
|
try {
|
|
@@ -4634,20 +5468,34 @@ var RtfPlugin = class {
|
|
|
4634
5468
|
const doc = new RTFJS.Document(ctx.buffer, {});
|
|
4635
5469
|
const htmlElements = await doc.render();
|
|
4636
5470
|
const contentNodes = [];
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
5471
|
+
const extractBlocks = (nodes) => {
|
|
5472
|
+
for (const item of nodes) {
|
|
5473
|
+
if (!item || !(item instanceof HTMLElement)) continue;
|
|
5474
|
+
const tag = item.tagName.toLowerCase();
|
|
5475
|
+
const hasChildBlocks = Array.from(item.children).some((c) => {
|
|
5476
|
+
const ct = c.tagName.toLowerCase();
|
|
5477
|
+
return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
|
|
5478
|
+
});
|
|
5479
|
+
if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
|
|
5480
|
+
extractBlocks(Array.from(item.children));
|
|
5481
|
+
} else {
|
|
5482
|
+
if (tag === "p" || tag === "div") {
|
|
5483
|
+
item.style.display = "block";
|
|
5484
|
+
item.style.marginBottom = "12px";
|
|
5485
|
+
item.style.lineHeight = "1.6";
|
|
5486
|
+
}
|
|
5487
|
+
contentNodes.push(item);
|
|
5488
|
+
}
|
|
4642
5489
|
}
|
|
4643
|
-
}
|
|
5490
|
+
};
|
|
5491
|
+
extractBlocks(htmlElements);
|
|
4644
5492
|
wrapper.innerHTML = "";
|
|
4645
5493
|
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4646
5494
|
const childHeights = contentNodes.map((c) => {
|
|
4647
5495
|
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4648
5496
|
const offH = c.offsetHeight || 0;
|
|
4649
5497
|
const textLen = c.textContent?.trim().length || 0;
|
|
4650
|
-
const estH = Math.max(
|
|
5498
|
+
const estH = Math.max(28, Math.ceil(textLen / 75) * 24 + 16);
|
|
4651
5499
|
return Math.max(rectH, offH, estH);
|
|
4652
5500
|
});
|
|
4653
5501
|
wrapper.innerHTML = "";
|
|
@@ -4664,6 +5512,7 @@ var RtfPlugin = class {
|
|
|
4664
5512
|
card.style.marginBottom = "24px";
|
|
4665
5513
|
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4666
5514
|
card.style.lineHeight = "1.6";
|
|
5515
|
+
card.style.color = "#1e293b";
|
|
4667
5516
|
return card;
|
|
4668
5517
|
};
|
|
4669
5518
|
let curCard = createRtfCard();
|
|
@@ -4699,9 +5548,8 @@ var RtfPlugin = class {
|
|
|
4699
5548
|
pageCard.style.padding = "72px 56px";
|
|
4700
5549
|
pageCard.style.width = "816px";
|
|
4701
5550
|
pageCard.style.minHeight = "1056px";
|
|
4702
|
-
pageCard.style.maxWidth = "100%";
|
|
4703
5551
|
pageCard.style.boxSizing = "border-box";
|
|
4704
|
-
pageCard.style.fontFamily = "serif
|
|
5552
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4705
5553
|
pageCard.style.fontSize = "12pt";
|
|
4706
5554
|
pageCard.style.lineHeight = "1.6";
|
|
4707
5555
|
pageCard.style.color = "#1e293b";
|
|
@@ -4714,29 +5562,6 @@ var RtfPlugin = class {
|
|
|
4714
5562
|
}
|
|
4715
5563
|
const totalPages = Math.max(1, pageElements.length);
|
|
4716
5564
|
let currentPage = 1;
|
|
4717
|
-
let indicator = null;
|
|
4718
|
-
if (totalPages > 1) {
|
|
4719
|
-
indicator = document.createElement("div");
|
|
4720
|
-
indicator.className = "fp-rtf-page-indicator";
|
|
4721
|
-
indicator.style.position = "sticky";
|
|
4722
|
-
indicator.style.bottom = "16px";
|
|
4723
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4724
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
4725
|
-
indicator.style.color = "#f8fafc";
|
|
4726
|
-
indicator.style.fontSize = "12px";
|
|
4727
|
-
indicator.style.fontWeight = "600";
|
|
4728
|
-
indicator.style.padding = "5px 14px";
|
|
4729
|
-
indicator.style.borderRadius = "20px";
|
|
4730
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4731
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4732
|
-
indicator.style.zIndex = "10";
|
|
4733
|
-
indicator.style.userSelect = "none";
|
|
4734
|
-
indicator.style.pointerEvents = "none";
|
|
4735
|
-
indicator.style.textAlign = "center";
|
|
4736
|
-
indicator.style.width = "fit-content";
|
|
4737
|
-
indicator.style.margin = "16px auto 0";
|
|
4738
|
-
ctx.container.appendChild(indicator);
|
|
4739
|
-
}
|
|
4740
5565
|
const showPage = (pageNum) => {
|
|
4741
5566
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4742
5567
|
if (totalPages > 1) {
|
|
@@ -4744,9 +5569,6 @@ var RtfPlugin = class {
|
|
|
4744
5569
|
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4745
5570
|
});
|
|
4746
5571
|
}
|
|
4747
|
-
if (indicator) {
|
|
4748
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4749
|
-
}
|
|
4750
5572
|
ctx.container.scrollTop = 0;
|
|
4751
5573
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4752
5574
|
};
|
|
@@ -4754,7 +5576,7 @@ var RtfPlugin = class {
|
|
|
4754
5576
|
showPage(1);
|
|
4755
5577
|
}
|
|
4756
5578
|
const cleanup = () => {
|
|
4757
|
-
|
|
5579
|
+
resizeObserver?.disconnect();
|
|
4758
5580
|
wrapper.remove();
|
|
4759
5581
|
ctx.container.innerHTML = "";
|
|
4760
5582
|
};
|
|
@@ -4765,21 +5587,25 @@ var RtfPlugin = class {
|
|
|
4765
5587
|
getCurrentPage: () => currentPage,
|
|
4766
5588
|
goToPage: (page) => showPage(page),
|
|
4767
5589
|
zoomIn: () => {
|
|
5590
|
+
isUserZoomed = true;
|
|
4768
5591
|
scale += 0.15;
|
|
4769
5592
|
applyTransform();
|
|
4770
5593
|
},
|
|
4771
5594
|
zoomOut: () => {
|
|
5595
|
+
isUserZoomed = true;
|
|
4772
5596
|
scale = Math.max(0.2, scale - 0.15);
|
|
4773
5597
|
applyTransform();
|
|
4774
5598
|
},
|
|
4775
5599
|
getZoom: () => scale,
|
|
4776
5600
|
setZoom: (level) => {
|
|
5601
|
+
isUserZoomed = true;
|
|
4777
5602
|
scale = level;
|
|
4778
5603
|
applyTransform();
|
|
4779
5604
|
},
|
|
4780
5605
|
fitToPage: () => {
|
|
4781
|
-
|
|
4782
|
-
|
|
5606
|
+
isUserZoomed = false;
|
|
5607
|
+
fitMode = "width";
|
|
5608
|
+
scale = calculateFitScale("width");
|
|
4783
5609
|
rotation = 0;
|
|
4784
5610
|
applyTransform();
|
|
4785
5611
|
},
|
|
@@ -4967,40 +5793,36 @@ var OpenDocumentPlugin = class {
|
|
|
4967
5793
|
const isPresentation = instance.isPresentation;
|
|
4968
5794
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4969
5795
|
const actions = [];
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
max
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
if (
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
instance.goToPage?.(page);
|
|
4998
|
-
} else if (typeof action === "number") {
|
|
4999
|
-
instance.goToPage?.(action);
|
|
5000
|
-
}
|
|
5796
|
+
actions.push({
|
|
5797
|
+
id: "thumbnails",
|
|
5798
|
+
icon: "thumbnails",
|
|
5799
|
+
label: isPresentation ? "Slide Thumbnails" : "Page Thumbnails",
|
|
5800
|
+
type: "button",
|
|
5801
|
+
group: "navigation",
|
|
5802
|
+
execute: () => instance.toggleThumbnails?.()
|
|
5803
|
+
});
|
|
5804
|
+
actions.push({
|
|
5805
|
+
id: "page-nav",
|
|
5806
|
+
icon: "",
|
|
5807
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
5808
|
+
type: "page-nav",
|
|
5809
|
+
group: "navigation",
|
|
5810
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
5811
|
+
max: totalPages,
|
|
5812
|
+
execute: (action, page) => {
|
|
5813
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
5814
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
5815
|
+
if (action === "prev") {
|
|
5816
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
5817
|
+
} else if (action === "next") {
|
|
5818
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
5819
|
+
} else if (typeof page === "number") {
|
|
5820
|
+
instance.goToPage?.(page);
|
|
5821
|
+
} else if (typeof action === "number") {
|
|
5822
|
+
instance.goToPage?.(action);
|
|
5001
5823
|
}
|
|
5002
|
-
}
|
|
5003
|
-
}
|
|
5824
|
+
}
|
|
5825
|
+
});
|
|
5004
5826
|
actions.push(
|
|
5005
5827
|
{
|
|
5006
5828
|
id: "zoom-out",
|
|
@@ -5091,49 +5913,65 @@ var OpenDocumentPlugin = class {
|
|
|
5091
5913
|
container.className = "fp-odf-container";
|
|
5092
5914
|
container.style.width = "100%";
|
|
5093
5915
|
container.style.height = "100%";
|
|
5094
|
-
container.style.
|
|
5095
|
-
container.style.
|
|
5916
|
+
container.style.overflowX = "hidden";
|
|
5917
|
+
container.style.overflowY = "auto";
|
|
5918
|
+
container.style.padding = "16px 8px";
|
|
5096
5919
|
container.style.backgroundColor = "#f1f5f9";
|
|
5097
5920
|
const wrapper = document.createElement("div");
|
|
5098
5921
|
wrapper.className = "fp-odf-wrapper";
|
|
5099
5922
|
wrapper.style.margin = "0 auto";
|
|
5923
|
+
wrapper.style.width = isPresentation ? "960px" : "816px";
|
|
5924
|
+
wrapper.style.boxSizing = "border-box";
|
|
5100
5925
|
wrapper.style.backgroundColor = "#ffffff";
|
|
5101
5926
|
wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
5102
5927
|
wrapper.style.borderRadius = "4px";
|
|
5103
5928
|
wrapper.style.transformOrigin = "top center";
|
|
5104
|
-
wrapper.style.transition = "transform 0.
|
|
5929
|
+
wrapper.style.transition = "transform 0.15s ease";
|
|
5105
5930
|
container.appendChild(wrapper);
|
|
5106
5931
|
ctx.container.appendChild(container);
|
|
5107
5932
|
let scale = 1;
|
|
5108
5933
|
let rotation = 0;
|
|
5109
|
-
let
|
|
5934
|
+
let isUserZoomed = false;
|
|
5935
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
5936
|
+
let currentPage = 1;
|
|
5937
|
+
let totalPages = 1;
|
|
5938
|
+
let slides = [];
|
|
5110
5939
|
const calculateFitScale = (mode = fitMode) => {
|
|
5111
|
-
const
|
|
5112
|
-
const
|
|
5113
|
-
const
|
|
5114
|
-
const
|
|
5940
|
+
const activeSlide = slides[currentPage - 1];
|
|
5941
|
+
const elW = isPresentation ? 960 : 816;
|
|
5942
|
+
const singlePageH = Math.min(activeSlide?.offsetHeight || wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
5943
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
5944
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5115
5945
|
const sW = availW / elW;
|
|
5116
5946
|
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
5117
5947
|
if (isPresentation) {
|
|
5118
|
-
return Math.min(
|
|
5948
|
+
return Math.min(2.5, Math.min(sW, sH));
|
|
5119
5949
|
}
|
|
5120
5950
|
if (mode === "page") {
|
|
5121
|
-
return Math.max(0.
|
|
5951
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5122
5952
|
}
|
|
5123
|
-
return Math.max(0.
|
|
5953
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5124
5954
|
};
|
|
5125
5955
|
const applyTransform = () => {
|
|
5126
5956
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5127
5957
|
wrapper.style.transformOrigin = "top center";
|
|
5958
|
+
const activeSlide = slides[currentPage - 1];
|
|
5959
|
+
const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
|
|
5960
|
+
const scaledH = baseH * scale;
|
|
5961
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
5962
|
+
wrapper.style.marginBottom = `${extraH + 32}px`;
|
|
5128
5963
|
};
|
|
5964
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
5965
|
+
if (!isUserZoomed) {
|
|
5966
|
+
scale = calculateFitScale(fitMode);
|
|
5967
|
+
applyTransform();
|
|
5968
|
+
}
|
|
5969
|
+
}) : null;
|
|
5970
|
+
resizeObserver?.observe(ctx.container);
|
|
5129
5971
|
setTimeout(() => {
|
|
5130
|
-
|
|
5131
|
-
scale = calculateFitScale("width");
|
|
5972
|
+
scale = calculateFitScale(fitMode);
|
|
5132
5973
|
applyTransform();
|
|
5133
5974
|
}, 60);
|
|
5134
|
-
let currentPage = 1;
|
|
5135
|
-
let totalPages = 1;
|
|
5136
|
-
let slides = [];
|
|
5137
5975
|
if (isPresentation) {
|
|
5138
5976
|
wrapper.style.maxWidth = "960px";
|
|
5139
5977
|
wrapper.style.aspectRatio = "16 / 9";
|
|
@@ -5234,24 +6072,9 @@ var OpenDocumentPlugin = class {
|
|
|
5234
6072
|
wrapper.appendChild(page);
|
|
5235
6073
|
slides.push(page);
|
|
5236
6074
|
});
|
|
5237
|
-
const pageIndicator = document.createElement("div");
|
|
5238
|
-
pageIndicator.className = "fp-odt-page-indicator";
|
|
5239
|
-
pageIndicator.style.position = "sticky";
|
|
5240
|
-
pageIndicator.style.bottom = "16px";
|
|
5241
|
-
pageIndicator.style.left = "50%";
|
|
5242
|
-
pageIndicator.style.transform = "translateX(-50%)";
|
|
5243
|
-
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
5244
|
-
pageIndicator.style.color = "#fff";
|
|
5245
|
-
pageIndicator.style.padding = "6px 12px";
|
|
5246
|
-
pageIndicator.style.borderRadius = "16px";
|
|
5247
|
-
pageIndicator.style.fontSize = "12px";
|
|
5248
|
-
pageIndicator.style.zIndex = "100";
|
|
5249
|
-
pageIndicator.style.display = "inline-block";
|
|
5250
|
-
pageIndicator.style.width = "fit-content";
|
|
5251
|
-
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
5252
|
-
container.appendChild(pageIndicator);
|
|
5253
6075
|
}
|
|
5254
6076
|
const cleanup = () => {
|
|
6077
|
+
resizeObserver?.disconnect();
|
|
5255
6078
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
5256
6079
|
container.remove();
|
|
5257
6080
|
ctx.container.innerHTML = "";
|
|
@@ -5263,10 +6086,6 @@ var OpenDocumentPlugin = class {
|
|
|
5263
6086
|
slides.forEach((s, idx) => {
|
|
5264
6087
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
5265
6088
|
});
|
|
5266
|
-
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
5267
|
-
if (indicator) {
|
|
5268
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5269
|
-
}
|
|
5270
6089
|
container.scrollTop = 0;
|
|
5271
6090
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5272
6091
|
};
|
|
@@ -5274,21 +6093,25 @@ var OpenDocumentPlugin = class {
|
|
|
5274
6093
|
destroy: cleanup,
|
|
5275
6094
|
isPresentation,
|
|
5276
6095
|
zoomIn: () => {
|
|
6096
|
+
isUserZoomed = true;
|
|
5277
6097
|
scale += 0.15;
|
|
5278
6098
|
applyTransform();
|
|
5279
6099
|
},
|
|
5280
6100
|
zoomOut: () => {
|
|
6101
|
+
isUserZoomed = true;
|
|
5281
6102
|
scale = Math.max(0.2, scale - 0.15);
|
|
5282
6103
|
applyTransform();
|
|
5283
6104
|
},
|
|
5284
6105
|
getZoom: () => scale,
|
|
5285
6106
|
setZoom: (level) => {
|
|
6107
|
+
isUserZoomed = true;
|
|
5286
6108
|
scale = level;
|
|
5287
6109
|
applyTransform();
|
|
5288
6110
|
},
|
|
5289
6111
|
fitToPage: () => {
|
|
5290
|
-
|
|
5291
|
-
|
|
6112
|
+
isUserZoomed = false;
|
|
6113
|
+
fitMode = "width";
|
|
6114
|
+
scale = calculateFitScale("width");
|
|
5292
6115
|
rotation = 0;
|
|
5293
6116
|
applyTransform();
|
|
5294
6117
|
},
|
|
@@ -5304,23 +6127,45 @@ var OpenDocumentPlugin = class {
|
|
|
5304
6127
|
getPageCount: () => totalPages,
|
|
5305
6128
|
getCurrentPage: () => currentPage,
|
|
5306
6129
|
getThumbnails: async () => {
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
canvas
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
6130
|
+
const count = totalPages || slides.length || 1;
|
|
6131
|
+
const items = [];
|
|
6132
|
+
for (let idx = 0; idx < count; idx++) {
|
|
6133
|
+
const itemIdx = idx;
|
|
6134
|
+
items.push({
|
|
6135
|
+
index: itemIdx,
|
|
6136
|
+
label: isPresentation ? `Slide ${itemIdx + 1}` : `Page ${itemIdx + 1}`,
|
|
6137
|
+
render: async (canvas) => {
|
|
6138
|
+
const ctx2d = canvas.getContext("2d");
|
|
6139
|
+
if (!ctx2d) return;
|
|
6140
|
+
if (isPresentation) {
|
|
6141
|
+
canvas.width = 160;
|
|
6142
|
+
canvas.height = 90;
|
|
6143
|
+
ctx2d.fillStyle = "#f8fafc";
|
|
6144
|
+
ctx2d.fillRect(0, 0, 160, 90);
|
|
6145
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6146
|
+
ctx2d.lineWidth = 1;
|
|
6147
|
+
ctx2d.strokeRect(0.5, 0.5, 159, 89);
|
|
6148
|
+
ctx2d.fillStyle = "#334155";
|
|
6149
|
+
ctx2d.font = "bold 11px sans-serif";
|
|
6150
|
+
ctx2d.textAlign = "center";
|
|
6151
|
+
ctx2d.fillText(`Slide ${itemIdx + 1}`, 80, 50);
|
|
6152
|
+
} else {
|
|
6153
|
+
canvas.width = 140;
|
|
6154
|
+
canvas.height = 180;
|
|
6155
|
+
ctx2d.fillStyle = "#ffffff";
|
|
6156
|
+
ctx2d.fillRect(0, 0, 140, 180);
|
|
6157
|
+
ctx2d.strokeStyle = "#cbd5e1";
|
|
6158
|
+
ctx2d.lineWidth = 1;
|
|
6159
|
+
ctx2d.strokeRect(0.5, 0.5, 139, 179);
|
|
6160
|
+
ctx2d.fillStyle = "#64748b";
|
|
6161
|
+
ctx2d.font = "bold 10px sans-serif";
|
|
6162
|
+
ctx2d.textAlign = "center";
|
|
6163
|
+
ctx2d.fillText(`Page ${itemIdx + 1}`, 70, 90);
|
|
6164
|
+
}
|
|
6165
|
+
}
|
|
6166
|
+
});
|
|
6167
|
+
}
|
|
6168
|
+
return items;
|
|
5324
6169
|
},
|
|
5325
6170
|
download: () => {
|
|
5326
6171
|
const mimeType = this.mimeTypes.find((m) => m.includes(ext.replace(".", ""))) || "application/octet-stream";
|
|
@@ -5425,23 +6270,24 @@ var OpenDocumentPlugin = class {
|
|
|
5425
6270
|
case "h": {
|
|
5426
6271
|
const level = Math.min(6, Math.max(1, Number(node.getAttribute("text:outline-level") || 1)));
|
|
5427
6272
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5428
|
-
html += `<h${level} style="${style}; font-family:
|
|
6273
|
+
html += `<h${level} style="${style}; margin: 18px 0 8px; color: #1e3a8a; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${node.textContent || ""}</h${level}>`;
|
|
5429
6274
|
break;
|
|
5430
6275
|
}
|
|
5431
6276
|
case "p": {
|
|
5432
6277
|
const style = styles.get(node.getAttribute("text:style-name") || "") || "";
|
|
5433
6278
|
const inner = this.renderSpans(node, styles, images);
|
|
5434
|
-
|
|
6279
|
+
const isInsideLi = node.parentElement?.localName === "list-item" || node.parentElement?.tagName?.toLowerCase() === "list-item";
|
|
6280
|
+
html += `<p style="${style}; line-height: 1.5; margin: ${isInsideLi ? "0" : "8px 0 12px"}; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">${inner}</p>`;
|
|
5435
6281
|
break;
|
|
5436
6282
|
}
|
|
5437
6283
|
case "list": {
|
|
5438
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
6284
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
5439
6285
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5440
6286
|
html += "</ul>";
|
|
5441
6287
|
break;
|
|
5442
6288
|
}
|
|
5443
6289
|
case "list-item": {
|
|
5444
|
-
html +=
|
|
6290
|
+
html += '<li style="margin: 4px 0; font-size: 11pt; line-height: 1.5; color: #1e293b;">';
|
|
5445
6291
|
Array.from(node.children).forEach((c) => walk(c));
|
|
5446
6292
|
html += "</li>";
|
|
5447
6293
|
break;
|
|
@@ -5567,28 +6413,26 @@ var DocPlugin = class {
|
|
|
5567
6413
|
getToolbarActions(instance) {
|
|
5568
6414
|
const totalPages = instance.getPageCount?.() ?? 1;
|
|
5569
6415
|
const actions = [];
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
if (
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
instance.goToPage?.(page);
|
|
5588
|
-
}
|
|
6416
|
+
actions.push({
|
|
6417
|
+
id: "page-nav",
|
|
6418
|
+
icon: "",
|
|
6419
|
+
label: "Page Navigation",
|
|
6420
|
+
type: "page-nav",
|
|
6421
|
+
group: "navigation",
|
|
6422
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
6423
|
+
max: totalPages,
|
|
6424
|
+
execute: (action, page) => {
|
|
6425
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
6426
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
6427
|
+
if (action === "prev") {
|
|
6428
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
6429
|
+
} else if (action === "next") {
|
|
6430
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
6431
|
+
} else if (typeof page === "number") {
|
|
6432
|
+
instance.goToPage?.(page);
|
|
5589
6433
|
}
|
|
5590
|
-
}
|
|
5591
|
-
}
|
|
6434
|
+
}
|
|
6435
|
+
});
|
|
5592
6436
|
actions.push(
|
|
5593
6437
|
{
|
|
5594
6438
|
id: "zoom-out",
|
|
@@ -5662,8 +6506,9 @@ var DocPlugin = class {
|
|
|
5662
6506
|
container.className = "fp-doc-container";
|
|
5663
6507
|
container.style.width = "100%";
|
|
5664
6508
|
container.style.height = "100%";
|
|
5665
|
-
container.style.
|
|
5666
|
-
container.style.
|
|
6509
|
+
container.style.overflowX = "hidden";
|
|
6510
|
+
container.style.overflowY = "auto";
|
|
6511
|
+
container.style.padding = "16px 8px";
|
|
5667
6512
|
container.style.backgroundColor = "#f1f5f9";
|
|
5668
6513
|
container.style.display = "flex";
|
|
5669
6514
|
container.style.justifyContent = "center";
|
|
@@ -5708,16 +6553,15 @@ var DocPlugin = class {
|
|
|
5708
6553
|
const pageCard = document.createElement("div");
|
|
5709
6554
|
pageCard.className = "fp-doc-page-card";
|
|
5710
6555
|
pageCard.style.width = "816px";
|
|
5711
|
-
pageCard.style.
|
|
6556
|
+
pageCard.style.minHeight = "1056px";
|
|
5712
6557
|
pageCard.style.backgroundColor = "#ffffff";
|
|
5713
|
-
pageCard.style.boxShadow = "0
|
|
6558
|
+
pageCard.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
5714
6559
|
pageCard.style.borderRadius = "4px";
|
|
5715
|
-
pageCard.style.padding = "
|
|
6560
|
+
pageCard.style.padding = "72px 56px";
|
|
5716
6561
|
pageCard.style.boxSizing = "border-box";
|
|
5717
|
-
pageCard.style.overflow = "hidden";
|
|
5718
6562
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5719
6563
|
pageCard.style.transformOrigin = "top center";
|
|
5720
|
-
pageCard.style.transition = "transform 0.
|
|
6564
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
5721
6565
|
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5722
6566
|
pageCard.style.color = "#1e293b";
|
|
5723
6567
|
if (isFallback && i === 0) {
|
|
@@ -5734,34 +6578,15 @@ var DocPlugin = class {
|
|
|
5734
6578
|
container.appendChild(pageCard);
|
|
5735
6579
|
pageCards.push(pageCard);
|
|
5736
6580
|
}
|
|
5737
|
-
let indicator = null;
|
|
5738
|
-
if (totalPages > 1) {
|
|
5739
|
-
indicator = document.createElement("div");
|
|
5740
|
-
indicator.className = "fp-doc-page-indicator";
|
|
5741
|
-
indicator.style.position = "fixed";
|
|
5742
|
-
indicator.style.bottom = "16px";
|
|
5743
|
-
indicator.style.left = "50%";
|
|
5744
|
-
indicator.style.transform = "translateX(-50%)";
|
|
5745
|
-
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
5746
|
-
indicator.style.backdropFilter = "blur(8px)";
|
|
5747
|
-
indicator.style.color = "#f8fafc";
|
|
5748
|
-
indicator.style.fontSize = "12px";
|
|
5749
|
-
indicator.style.fontWeight = "600";
|
|
5750
|
-
indicator.style.padding = "5px 14px";
|
|
5751
|
-
indicator.style.borderRadius = "20px";
|
|
5752
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
5753
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
5754
|
-
indicator.style.zIndex = "10";
|
|
5755
|
-
indicator.style.userSelect = "none";
|
|
5756
|
-
indicator.style.pointerEvents = "none";
|
|
5757
|
-
indicator.style.textAlign = "center";
|
|
5758
|
-
container.appendChild(indicator);
|
|
5759
|
-
}
|
|
5760
6581
|
let rotation = 0;
|
|
5761
6582
|
const applyTransform = () => {
|
|
5762
6583
|
const activeCard = pageCards[currentPage - 1];
|
|
5763
6584
|
if (activeCard) {
|
|
5764
6585
|
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
6586
|
+
const baseH = activeCard.offsetHeight || 1056;
|
|
6587
|
+
const scaledH = baseH * scale;
|
|
6588
|
+
const extraH = Math.max(0, scaledH - baseH);
|
|
6589
|
+
activeCard.style.marginBottom = `${extraH + 32}px`;
|
|
5765
6590
|
}
|
|
5766
6591
|
};
|
|
5767
6592
|
const showPage = (pageNum) => {
|
|
@@ -5774,35 +6599,39 @@ var DocPlugin = class {
|
|
|
5774
6599
|
card.style.display = "none";
|
|
5775
6600
|
}
|
|
5776
6601
|
});
|
|
5777
|
-
if (indicator) {
|
|
5778
|
-
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5779
|
-
}
|
|
5780
6602
|
container.scrollTop = 0;
|
|
5781
6603
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5782
6604
|
};
|
|
5783
6605
|
if (totalPages > 1) {
|
|
5784
6606
|
showPage(1);
|
|
5785
6607
|
}
|
|
5786
|
-
let fitMode = "width";
|
|
6608
|
+
let fitMode = ctx?.options?.fitMode || "width";
|
|
6609
|
+
let isUserZoomed = false;
|
|
5787
6610
|
const calculateFitScale = (mode = fitMode) => {
|
|
5788
6611
|
const elW = 816;
|
|
5789
6612
|
const elH = 1056;
|
|
5790
|
-
const availW = Math.max(280, ctx.container.clientWidth -
|
|
5791
|
-
const availH = Math.max(280, ctx.container.clientHeight -
|
|
6613
|
+
const availW = Math.max(280, ctx.container.clientWidth - 32);
|
|
6614
|
+
const availH = Math.max(280, ctx.container.clientHeight - 32);
|
|
5792
6615
|
const sW = availW / elW;
|
|
5793
6616
|
const sH = availH / elH;
|
|
5794
6617
|
if (mode === "page") {
|
|
5795
|
-
return Math.max(0.
|
|
6618
|
+
return Math.max(0.35, Math.min(3, Math.min(sW, sH)));
|
|
5796
6619
|
}
|
|
5797
|
-
return Math.max(0.
|
|
6620
|
+
return Math.max(0.4, Math.min(3, sW));
|
|
5798
6621
|
};
|
|
6622
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
6623
|
+
if (!isUserZoomed) {
|
|
6624
|
+
scale = calculateFitScale(fitMode);
|
|
6625
|
+
applyTransform();
|
|
6626
|
+
}
|
|
6627
|
+
}) : null;
|
|
6628
|
+
resizeObserver?.observe(ctx.container);
|
|
5799
6629
|
setTimeout(() => {
|
|
5800
|
-
|
|
5801
|
-
scale = calculateFitScale("width");
|
|
6630
|
+
scale = calculateFitScale(fitMode);
|
|
5802
6631
|
applyTransform();
|
|
5803
6632
|
}, 60);
|
|
5804
6633
|
const cleanup = () => {
|
|
5805
|
-
|
|
6634
|
+
resizeObserver?.disconnect();
|
|
5806
6635
|
container.remove();
|
|
5807
6636
|
ctx.container.innerHTML = "";
|
|
5808
6637
|
};
|
|
@@ -5813,21 +6642,25 @@ var DocPlugin = class {
|
|
|
5813
6642
|
getCurrentPage: () => currentPage,
|
|
5814
6643
|
goToPage: (page) => showPage(page),
|
|
5815
6644
|
zoomIn: () => {
|
|
6645
|
+
isUserZoomed = true;
|
|
5816
6646
|
scale += 0.15;
|
|
5817
6647
|
applyTransform();
|
|
5818
6648
|
},
|
|
5819
6649
|
zoomOut: () => {
|
|
6650
|
+
isUserZoomed = true;
|
|
5820
6651
|
scale = Math.max(0.2, scale - 0.15);
|
|
5821
6652
|
applyTransform();
|
|
5822
6653
|
},
|
|
5823
6654
|
getZoom: () => scale,
|
|
5824
6655
|
setZoom: (level) => {
|
|
6656
|
+
isUserZoomed = true;
|
|
5825
6657
|
scale = level;
|
|
5826
6658
|
applyTransform();
|
|
5827
6659
|
},
|
|
5828
6660
|
fitToPage: () => {
|
|
5829
|
-
|
|
5830
|
-
|
|
6661
|
+
isUserZoomed = false;
|
|
6662
|
+
fitMode = "width";
|
|
6663
|
+
scale = calculateFitScale("width");
|
|
5831
6664
|
rotation = 0;
|
|
5832
6665
|
applyTransform();
|
|
5833
6666
|
},
|
|
@@ -6204,25 +7037,31 @@ ${chartSvg}
|
|
|
6204
7037
|
i++;
|
|
6205
7038
|
continue;
|
|
6206
7039
|
}
|
|
6207
|
-
if (
|
|
7040
|
+
if (/^\d{1,2}$/.test(line.trim())) {
|
|
7041
|
+
i++;
|
|
7042
|
+
continue;
|
|
7043
|
+
}
|
|
7044
|
+
const isShortLine = line.length < 60 && !line.endsWith(".") && !line.endsWith(",");
|
|
7045
|
+
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));
|
|
7046
|
+
if (isTitleLike) {
|
|
6208
7047
|
if (inList) {
|
|
6209
7048
|
html += "</ul>";
|
|
6210
7049
|
inList = false;
|
|
6211
7050
|
}
|
|
6212
|
-
html += `<h2 style="font-size:
|
|
7051
|
+
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>`;
|
|
6213
7052
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
6214
7053
|
if (!inList) {
|
|
6215
|
-
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
7054
|
+
html += '<ul style="margin: 8px 0 12px; padding-left: 24px;">';
|
|
6216
7055
|
inList = true;
|
|
6217
7056
|
}
|
|
6218
7057
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
6219
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
7058
|
+
html += `<li style="margin: 4px 0; line-height: 1.5; font-size: 11pt; color: #1e293b;">${DOMPurify6.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
6220
7059
|
} else {
|
|
6221
7060
|
if (inList) {
|
|
6222
7061
|
html += "</ul>";
|
|
6223
7062
|
inList = false;
|
|
6224
7063
|
}
|
|
6225
|
-
html += `<p style="line-height: 1.
|
|
7064
|
+
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>`;
|
|
6226
7065
|
}
|
|
6227
7066
|
i++;
|
|
6228
7067
|
}
|