@files-preview-app/preview-file 1.1.4 → 1.1.5
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/dist/angular.cjs +175 -15
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +175 -15
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +175 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +175 -15
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +175 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +175 -15
- package/dist/react.js.map +1 -1
- package/dist/styles.css +12 -0
- package/dist/vue.cjs +175 -15
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +175 -15
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -71,6 +71,13 @@
|
|
|
71
71
|
transition: all 0.2s;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
.fp-toolbar-btn svg {
|
|
75
|
+
width: 18px;
|
|
76
|
+
height: 18px;
|
|
77
|
+
display: block;
|
|
78
|
+
pointer-events: none;
|
|
79
|
+
}
|
|
80
|
+
|
|
74
81
|
.fp-toolbar-btn:hover {
|
|
75
82
|
background: var(--fp-btn-hover-bg);
|
|
76
83
|
}
|
|
@@ -80,6 +87,11 @@
|
|
|
80
87
|
color: var(--fp-accent);
|
|
81
88
|
}
|
|
82
89
|
|
|
90
|
+
.fp-viewer.fp-dragover {
|
|
91
|
+
outline: 2px dashed var(--fp-accent);
|
|
92
|
+
outline-offset: -4px;
|
|
93
|
+
}
|
|
94
|
+
|
|
83
95
|
.fp-toolbar-btn:disabled {
|
|
84
96
|
opacity: 0.5;
|
|
85
97
|
cursor: not-allowed;
|
package/dist/vue.cjs
CHANGED
|
@@ -371,8 +371,39 @@ function createElement(tag, attrs, ...children) {
|
|
|
371
371
|
}
|
|
372
372
|
return el;
|
|
373
373
|
}
|
|
374
|
+
var ICON_ZOOM_IN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
375
|
+
var ICON_ZOOM_OUT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
376
|
+
var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" y1="3" x2="14" y2="10"></line><line x1="3" y1="21" x2="10" y2="14"></line></svg>`;
|
|
377
|
+
var ICON_ROTATE_CW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>`;
|
|
378
|
+
var ICON_ROTATE_CCW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>`;
|
|
379
|
+
var ICON_DOWNLOAD = `<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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`;
|
|
380
|
+
var ICON_PRINT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>`;
|
|
374
381
|
var ICON_PAGE_PREV = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>`;
|
|
375
382
|
var ICON_PAGE_NEXT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>`;
|
|
383
|
+
var ICON_PLAY = `<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="5 3 19 12 5 21 5 3"></polygon></svg>`;
|
|
384
|
+
var ICON_PAUSE = `<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="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>`;
|
|
385
|
+
var ICON_THUMBNAILS = `<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="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>`;
|
|
386
|
+
var ICON_CLOSE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
|
|
387
|
+
var ICON_FULLSCREEN = `<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="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path></svg>`;
|
|
388
|
+
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>`;
|
|
389
|
+
var ICON_MAP = {
|
|
390
|
+
"zoom-in": ICON_ZOOM_IN,
|
|
391
|
+
"zoom-out": ICON_ZOOM_OUT,
|
|
392
|
+
"fit-page": ICON_FIT_PAGE,
|
|
393
|
+
"fit-slide": ICON_FIT_PAGE,
|
|
394
|
+
"rotate-cw": ICON_ROTATE_CW,
|
|
395
|
+
"rotate-ccw": ICON_ROTATE_CCW,
|
|
396
|
+
"download": ICON_DOWNLOAD,
|
|
397
|
+
"print": ICON_PRINT,
|
|
398
|
+
"thumbnails": ICON_THUMBNAILS,
|
|
399
|
+
"fullscreen": ICON_FULLSCREEN,
|
|
400
|
+
"play": ICON_PLAY,
|
|
401
|
+
"pause": ICON_PAUSE,
|
|
402
|
+
"close": ICON_CLOSE,
|
|
403
|
+
"copy": ICON_COPY,
|
|
404
|
+
"prev": ICON_PAGE_PREV,
|
|
405
|
+
"next": ICON_PAGE_NEXT
|
|
406
|
+
};
|
|
376
407
|
var ToolbarController = class {
|
|
377
408
|
el;
|
|
378
409
|
toolbarEl;
|
|
@@ -483,10 +514,11 @@ var ToolbarController = class {
|
|
|
483
514
|
type: "button",
|
|
484
515
|
"data-action-id": id
|
|
485
516
|
});
|
|
486
|
-
|
|
487
|
-
|
|
517
|
+
const svg = ICON_MAP[iconHtml] || iconHtml;
|
|
518
|
+
if (svg && svg.startsWith("<svg")) {
|
|
519
|
+
btn.innerHTML = sanitizeSVG(svg);
|
|
488
520
|
} else {
|
|
489
|
-
btn.textContent =
|
|
521
|
+
btn.textContent = svg || title;
|
|
490
522
|
}
|
|
491
523
|
btn.addEventListener("click", onClick);
|
|
492
524
|
return btn;
|
|
@@ -567,6 +599,9 @@ var FilePreviewViewer = class {
|
|
|
567
599
|
contentEl = null;
|
|
568
600
|
currentBuffer = null;
|
|
569
601
|
currentMetadata = null;
|
|
602
|
+
keyHandler = null;
|
|
603
|
+
currentContainer = null;
|
|
604
|
+
currentOptions = {};
|
|
570
605
|
/**
|
|
571
606
|
* Register a preview plugin.
|
|
572
607
|
*/
|
|
@@ -621,24 +656,47 @@ var FilePreviewViewer = class {
|
|
|
621
656
|
emit: (event, payload) => this.eventEmitter.emit(event, payload)
|
|
622
657
|
});
|
|
623
658
|
this.activeInstance = instance;
|
|
659
|
+
this.hideLoading();
|
|
660
|
+
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
624
661
|
if (options.showToolbar !== false && this.toolbar) {
|
|
625
662
|
const actions = matchedPlugin.getToolbarActions(instance);
|
|
663
|
+
const hasFullscreen = actions.some((a) => a.id === "fullscreen");
|
|
664
|
+
if (!hasFullscreen && this.wrapperEl) {
|
|
665
|
+
actions.push({
|
|
666
|
+
id: "fullscreen",
|
|
667
|
+
icon: "fullscreen",
|
|
668
|
+
label: "Toggle Fullscreen",
|
|
669
|
+
type: "button",
|
|
670
|
+
group: "view",
|
|
671
|
+
execute: () => {
|
|
672
|
+
if (!document.fullscreenElement) {
|
|
673
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
674
|
+
} else {
|
|
675
|
+
document.exitFullscreen?.();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
}
|
|
626
680
|
this.toolbar.update(actions);
|
|
627
681
|
this.toolbar.show();
|
|
628
682
|
}
|
|
629
683
|
if (instance.getThumbnails && this.thumbnailPanel) {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
684
|
+
Promise.resolve().then(async () => {
|
|
685
|
+
try {
|
|
686
|
+
const thumbnails = await Promise.resolve(instance.getThumbnails());
|
|
687
|
+
if (thumbnails && thumbnails.length > 0 && this.thumbnailPanel) {
|
|
688
|
+
this.thumbnailPanel.update(thumbnails, (index) => {
|
|
689
|
+
instance.goToPage?.(index + 1);
|
|
690
|
+
});
|
|
691
|
+
if (options.showThumbnails) {
|
|
692
|
+
this.thumbnailPanel.show();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
} catch (e) {
|
|
696
|
+
console.warn("[FilePreview] Non-critical thumbnail load error:", e);
|
|
637
697
|
}
|
|
638
|
-
}
|
|
698
|
+
});
|
|
639
699
|
}
|
|
640
|
-
this.hideLoading();
|
|
641
|
-
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
642
700
|
return instance;
|
|
643
701
|
} catch (error) {
|
|
644
702
|
this.hideLoading();
|
|
@@ -660,6 +718,10 @@ var FilePreviewViewer = class {
|
|
|
660
718
|
* Destroy the viewer and clean up all resources.
|
|
661
719
|
*/
|
|
662
720
|
destroy() {
|
|
721
|
+
if (this.keyHandler) {
|
|
722
|
+
window.removeEventListener("keydown", this.keyHandler);
|
|
723
|
+
this.keyHandler = null;
|
|
724
|
+
}
|
|
663
725
|
this.abort();
|
|
664
726
|
this.destroyInstance();
|
|
665
727
|
this.toolbar?.destroy();
|
|
@@ -675,6 +737,7 @@ var FilePreviewViewer = class {
|
|
|
675
737
|
this.thumbnailPanel = null;
|
|
676
738
|
this.currentBuffer = null;
|
|
677
739
|
this.currentMetadata = null;
|
|
740
|
+
this.currentContainer = null;
|
|
678
741
|
}
|
|
679
742
|
/**
|
|
680
743
|
* Get the currently active preview instance.
|
|
@@ -704,6 +767,8 @@ var FilePreviewViewer = class {
|
|
|
704
767
|
return null;
|
|
705
768
|
}
|
|
706
769
|
setupDOM(container, options) {
|
|
770
|
+
this.currentContainer = container;
|
|
771
|
+
this.currentOptions = options;
|
|
707
772
|
if (this.wrapperEl?.parentNode === container) return;
|
|
708
773
|
if (this.wrapperEl?.parentNode) {
|
|
709
774
|
this.wrapperEl.parentNode.removeChild(this.wrapperEl);
|
|
@@ -712,6 +777,7 @@ var FilePreviewViewer = class {
|
|
|
712
777
|
const toolbarPos = options.toolbarPosition ?? "top";
|
|
713
778
|
this.wrapperEl = document.createElement("div");
|
|
714
779
|
this.wrapperEl.className = `fp-viewer ${themeClass} ${options.className ?? ""}`.trim();
|
|
780
|
+
this.wrapperEl.tabIndex = 0;
|
|
715
781
|
const toolbarEl = document.createElement("div");
|
|
716
782
|
toolbarEl.className = "fp-toolbar-container";
|
|
717
783
|
this.contentEl = document.createElement("div");
|
|
@@ -733,6 +799,59 @@ var FilePreviewViewer = class {
|
|
|
733
799
|
container.appendChild(this.wrapperEl);
|
|
734
800
|
this.toolbar = new ToolbarController(toolbarEl);
|
|
735
801
|
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl);
|
|
802
|
+
this.setupKeyboardShortcuts();
|
|
803
|
+
this.setupDragAndDrop(container, options);
|
|
804
|
+
}
|
|
805
|
+
setupKeyboardShortcuts() {
|
|
806
|
+
if (this.keyHandler) return;
|
|
807
|
+
this.keyHandler = (e) => {
|
|
808
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || e.target?.isContentEditable) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
if (!this.activeInstance) return;
|
|
812
|
+
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
813
|
+
const cur = this.activeInstance.getCurrentPage?.() ?? 1;
|
|
814
|
+
this.activeInstance.goToPage?.(cur + 1);
|
|
815
|
+
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
816
|
+
const cur = this.activeInstance.getCurrentPage?.() ?? 1;
|
|
817
|
+
this.activeInstance.goToPage?.(Math.max(1, cur - 1));
|
|
818
|
+
} else if (e.key === "+" || e.key === "=") {
|
|
819
|
+
this.activeInstance.zoomIn?.();
|
|
820
|
+
} else if (e.key === "-" || e.key === "_") {
|
|
821
|
+
this.activeInstance.zoomOut?.();
|
|
822
|
+
} else if (e.key === "0") {
|
|
823
|
+
this.activeInstance.fitToPage?.();
|
|
824
|
+
} else if (e.key === "r" || e.key === "R") {
|
|
825
|
+
this.activeInstance.rotateCW?.();
|
|
826
|
+
} else if (e.key === "f" || e.key === "F") {
|
|
827
|
+
if (!document.fullscreenElement) {
|
|
828
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
829
|
+
} else {
|
|
830
|
+
document.exitFullscreen?.();
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
window.addEventListener("keydown", this.keyHandler);
|
|
835
|
+
}
|
|
836
|
+
setupDragAndDrop(container, options) {
|
|
837
|
+
if (!this.wrapperEl) return;
|
|
838
|
+
this.wrapperEl.addEventListener("dragover", (e) => {
|
|
839
|
+
e.preventDefault();
|
|
840
|
+
this.wrapperEl?.classList.add("fp-dragover");
|
|
841
|
+
});
|
|
842
|
+
this.wrapperEl.addEventListener("dragleave", (e) => {
|
|
843
|
+
if (e.relatedTarget === null || !this.wrapperEl?.contains(e.relatedTarget)) {
|
|
844
|
+
this.wrapperEl?.classList.remove("fp-dragover");
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
this.wrapperEl.addEventListener("drop", (e) => {
|
|
848
|
+
e.preventDefault();
|
|
849
|
+
this.wrapperEl?.classList.remove("fp-dragover");
|
|
850
|
+
const file = e.dataTransfer?.files?.[0];
|
|
851
|
+
if (file) {
|
|
852
|
+
this.preview(container, file, options);
|
|
853
|
+
}
|
|
854
|
+
});
|
|
736
855
|
}
|
|
737
856
|
showLoading() {
|
|
738
857
|
if (!this.contentEl) return;
|
|
@@ -751,10 +870,27 @@ var FilePreviewViewer = class {
|
|
|
751
870
|
this.contentEl.innerHTML = "";
|
|
752
871
|
const errorEl = document.createElement("div");
|
|
753
872
|
errorEl.className = "fp-error";
|
|
873
|
+
errorEl.style.display = "flex";
|
|
874
|
+
errorEl.style.flexDirection = "column";
|
|
875
|
+
errorEl.style.alignItems = "center";
|
|
876
|
+
errorEl.style.justifyContent = "center";
|
|
877
|
+
errorEl.style.padding = "32px";
|
|
878
|
+
errorEl.style.textAlign = "center";
|
|
879
|
+
const hasDownload = !!(this.currentBuffer && this.currentMetadata);
|
|
754
880
|
errorEl.innerHTML = `
|
|
755
|
-
<div class="fp-error-icon">\u26A0\uFE0F</div>
|
|
756
|
-
<div class="fp-error-message"
|
|
881
|
+
<div class="fp-error-icon" style="font-size:36px;margin-bottom:8px;">\u26A0\uFE0F</div>
|
|
882
|
+
<div class="fp-error-message" style="font-size:16px;font-weight:600;margin-bottom:6px;">Cannot preview file</div>
|
|
883
|
+
<div class="fp-error-sub" style="font-size:13px;color:#64748b;max-width:420px;line-height:1.5;margin-bottom:16px;">${message}</div>
|
|
884
|
+
${hasDownload ? '<button class="fp-error-download-btn" style="padding:8px 16px;background:#3b82f6;color:#ffffff;border:none;border-radius:6px;cursor:pointer;font-weight:500;font-size:13px;transition:background 0.2s;">Download Original File</button>' : ""}
|
|
757
885
|
`;
|
|
886
|
+
if (hasDownload && this.currentBuffer) {
|
|
887
|
+
const btn = errorEl.querySelector(".fp-error-download-btn");
|
|
888
|
+
if (btn) {
|
|
889
|
+
btn.addEventListener("click", () => {
|
|
890
|
+
downloadFile(this.currentBuffer, this.currentMetadata?.name || "download", this.currentMetadata?.mimeType);
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
}
|
|
758
894
|
this.contentEl.appendChild(errorEl);
|
|
759
895
|
}
|
|
760
896
|
};
|
|
@@ -1675,6 +1811,16 @@ var CodePlugin = class {
|
|
|
1675
1811
|
instance.zoomIn?.();
|
|
1676
1812
|
}
|
|
1677
1813
|
},
|
|
1814
|
+
{
|
|
1815
|
+
id: "copy",
|
|
1816
|
+
icon: "copy",
|
|
1817
|
+
label: "Copy Content",
|
|
1818
|
+
type: "button",
|
|
1819
|
+
group: "actions",
|
|
1820
|
+
execute: () => {
|
|
1821
|
+
instance.copy?.();
|
|
1822
|
+
}
|
|
1823
|
+
},
|
|
1678
1824
|
{
|
|
1679
1825
|
id: "download",
|
|
1680
1826
|
icon: "download",
|
|
@@ -1762,6 +1908,9 @@ var CodePlugin = class {
|
|
|
1762
1908
|
},
|
|
1763
1909
|
print: () => {
|
|
1764
1910
|
window.print();
|
|
1911
|
+
},
|
|
1912
|
+
copy: () => {
|
|
1913
|
+
navigator.clipboard?.writeText(text);
|
|
1765
1914
|
}
|
|
1766
1915
|
};
|
|
1767
1916
|
}
|
|
@@ -2012,6 +2161,14 @@ var MarkdownPlugin = class {
|
|
|
2012
2161
|
group: "zoom",
|
|
2013
2162
|
execute: () => instance.fitToPage?.()
|
|
2014
2163
|
},
|
|
2164
|
+
{
|
|
2165
|
+
id: "copy",
|
|
2166
|
+
icon: "copy",
|
|
2167
|
+
label: "Copy Markdown",
|
|
2168
|
+
type: "button",
|
|
2169
|
+
group: "actions",
|
|
2170
|
+
execute: () => instance.copy?.()
|
|
2171
|
+
},
|
|
2015
2172
|
{
|
|
2016
2173
|
id: "download",
|
|
2017
2174
|
icon: "download",
|
|
@@ -2162,6 +2319,9 @@ var MarkdownPlugin = class {
|
|
|
2162
2319
|
},
|
|
2163
2320
|
print: () => {
|
|
2164
2321
|
window.print();
|
|
2322
|
+
},
|
|
2323
|
+
copy: () => {
|
|
2324
|
+
navigator.clipboard?.writeText(text);
|
|
2165
2325
|
}
|
|
2166
2326
|
};
|
|
2167
2327
|
}
|