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