import "./jszip-ChlR43oI.es.js";
import { A as openBlock, E as onBeforeUnmount, I as watch, K as ref, O as onMounted, U as markRaw, c as Fragment, d as createBaseVNode, et as normalizeStyle, f as createBlock, g as createVNode, j as renderList, m as createElementBlock, p as createCommentVNode, q as shallowRef, u as computed, w as mergeProps } from "./vue-DMgTaOx9.es.js";
import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-HmhZBO0u.es.js";
const floor = (val, precision) => {
	const multiplier = 10 ** (precision || 0);
	return Math.floor(val * multiplier) / multiplier;
};
const readFileAsArrayBuffer = (blob) => {
	return new Promise((resolve, reject) => {
		const reader = new FileReader();
		reader.onload = (event) => resolve(event.target.result);
		reader.onerror = reject;
		reader.readAsDataURL(blob);
	});
};
const PDF_TO_CSS_UNITS = 96 / 72;
const range = (start, end) => {
	const length = end - start;
	return Array.from({ length }, (_, i) => start + i);
};
const createPDFConfig = (config) => {
	return {
		adapter: "pdfjs",
		...config
	};
};
var PDFAdapter = class PDFAdapter {
	constructor() {
		if (Object.getPrototypeOf(this).constructor === PDFAdapter) throw new Error("Abstract class should not be instanciated");
	}
};
var PDFJSAdapter = class extends PDFAdapter {
	constructor(config) {
		super();
		this.pdfLib = config.pdfLib;
		this.workerSrc = config.workerSrc;
		if (config.setWorker) if (this.workerSrc) this.pdfLib.GlobalWorkerOptions.workerSrc = config.workerSrc;
		else this.pdfLib.GlobalWorkerOptions.workerSrc = getWorkerSrcFromCDN(this.pdfLib.version);
	}
	async getDocument(file) {
		return await this.pdfLib.getDocument(file).promise;
	}
	async getPages(pdf, firstPage, lastPage) {
		const pagesPromises = range(firstPage, lastPage + 1).map((num) => pdf.getPage(num));
		return await Promise.all(pagesPromises);
	}
};
var PDFAdapterFactory = class {
	static create(config) {
		const adapters = {
			pdfjs: () => {
				return new PDFJSAdapter(config);
			},
			default: () => {
				throw new Error("Unsupported adapter");
			}
		};
		return (adapters[config.adapter] ?? adapters.default)();
	}
};
function getWorkerSrcFromCDN(version) {
	return `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${version}/pdf.worker.min.mjs`;
}
var _hoisted_1$1 = ["data-page-id", "data-page-number"];
var _hoisted_2 = { class: "sd-pdf-viewer-page__canvas-wrapper" };
var PdfViewerPage_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
	__name: "PdfViewerPage",
	props: {
		config: {
			type: Object,
			required: true
		},
		page: {
			type: Object,
			required: true
		},
		pages: {
			type: Array,
			required: true
		},
		scale: {
			type: Number,
			required: true
		},
		hasTextLayer: {
			type: Boolean,
			default: false
		},
		outputScale: {
			type: Number,
			default: 2
		},
		documentEl: {
			type: [Object],
			default: null
		}
	},
	emits: [
		"page-rendered",
		"page-error",
		"text-layer-rendered",
		"text-layer-error",
		"selection-raw",
		"bypass-selection"
	],
	setup(__props, { emit: __emit }) {
		const emit = __emit;
		const props = __props;
		const viewport = shallowRef(null);
		const pageRef = ref(null);
		const canvasRef = ref(null);
		const textLayerRef = ref(null);
		let renderTask;
		const pageIdx = computed(() => props.pages.findIndex((page) => page.pageId === props.page.pageId));
		const pageNumber = computed(() => {
			if (pageIdx.value === -1) return 0;
			return pageIdx.value + 1;
		});
		function getSelectedTextBoundingBox(container) {
			const selection = window.getSelection();
			if (!selection || selection.rangeCount === 0) return null;
			const rects = selection.getRangeAt(0).getClientRects();
			if (!rects.length) return null;
			const containerRect = container.getBoundingClientRect();
			const scale = props.scale ?? 1;
			const firstRect = rects[0];
			let boundingBox = {
				top: firstRect.top,
				left: firstRect.left,
				bottom: firstRect.bottom,
				right: firstRect.right
			};
			for (let i = 1; i < rects.length; i += 1) {
				const rect = rects[i];
				if (rect.width === 0 || rect.height === 0) continue;
				boundingBox.top = Math.min(boundingBox.top, rect.top);
				boundingBox.left = Math.min(boundingBox.left, rect.left);
				boundingBox.bottom = Math.max(boundingBox.bottom, rect.bottom);
				boundingBox.right = Math.max(boundingBox.right, rect.right);
			}
			return {
				top: (boundingBox.top - containerRect.top) / scale + container.scrollTop,
				left: (boundingBox.left - containerRect.left) / scale + container.scrollLeft,
				bottom: (boundingBox.bottom - containerRect.top) / scale + container.scrollTop,
				right: (boundingBox.right - containerRect.left) / scale + container.scrollLeft
			};
		}
		const pageSize = computed(() => {
			let { width, height } = viewport.value;
			[width, height] = [width, height].map((dim) => Math.ceil(dim));
			return {
				width,
				height
			};
		});
		const canvasAttrs = computed(() => {
			const { width, height } = pageSize.value;
			return {
				width,
				height
			};
		});
		const pageStyle = computed(() => {
			const { width: widthPt, height: heightPt } = getPagePtSize();
			const scaleFactor = getScaleFactor();
			return {
				"--scale-factor": `${scaleFactor}`,
				width: `calc(var(--scale-factor) * ${widthPt}px)`,
				height: `calc(var(--scale-factor) * ${heightPt}px)`
			};
		});
		function onMouseUp() {
			const selection = window.getSelection();
			if (!selection || selection.toString().length === 0) return;
			const bounds = getSelectedTextBoundingBox(props.documentEl?.value ?? props.documentEl ?? pageRef.value);
			if (!bounds) return;
			emit("selection-raw", {
				selectionBounds: bounds,
				documentId: props.page.documentId,
				page: pageNumber.value,
				source: "pdf"
			});
		}
		function onMouseDown(event) {
			if (!event?.target) return;
			if (event.target.tagName !== "SPAN") emit("bypass-selection", event);
		}
		function getPagePtSize() {
			const factor = PDF_TO_CSS_UNITS * props.outputScale;
			let { width, height } = viewport.value;
			width = width / factor;
			height = height / factor;
			[width, height] = [width, height].map((dim) => Math.ceil(dim));
			return {
				width,
				height
			};
		}
		function getPageSize() {
			const { width: widthPt, height: heightPt } = getPagePtSize();
			const scaleFactor = getScaleFactor();
			return {
				width: widthPt * scaleFactor,
				height: heightPt * scaleFactor
			};
		}
		function getScaleFactor() {
			return (props.scale ?? 1) * PDF_TO_CSS_UNITS;
		}
		function setInitialViewport() {
			const { pdfjsPage } = props.page;
			viewport.value = pdfjsPage.getViewport({ scale: PDF_TO_CSS_UNITS * props.outputScale });
		}
		async function renderPage() {
			if (renderTask) return;
			const canvasElem = canvasRef.value;
			if (!canvasElem || !viewport.value) return;
			const renderContext = {
				canvasContext: canvasElem.getContext("2d"),
				viewport: viewport.value
			};
			try {
				const { pdfjsPage } = props.page;
				renderTask = pdfjsPage.render(renderContext);
				await renderTask.promise;
				const size = getPageSize();
				const originalPt = getPagePtSize();
				emit("page-rendered", {
					page: props.page,
					documentId: props.page.documentId,
					pageIndex: pageIdx.value,
					pageNumber: pageNumber.value,
					width: size.width,
					height: size.height,
					originalWidth: originalPt.width * PDF_TO_CSS_UNITS,
					originalHeight: originalPt.height * PDF_TO_CSS_UNITS
				});
			} catch (e) {
				destroyRenderTask();
				emit("page-error", props.page);
			}
		}
		async function renderTextLayer() {
			if (!props.hasTextLayer) return;
			const container = textLayerRef.value;
			if (!container) return;
			container.innerHTML = "";
			const TextLayer = props.config?.pdfLib?.TextLayer;
			if (!TextLayer) return;
			try {
				const scale = (props.scale ?? 1) * PDF_TO_CSS_UNITS;
				const textViewport = props.page.pdfjsPage.getViewport({ scale });
				await new TextLayer({
					textContentSource: await props.page.pdfjsPage.getTextContent(),
					container,
					viewport: textViewport
				}).render();
				emit("text-layer-rendered", props.page);
			} catch (e) {
				emit("text-layer-error", props.page);
				console.error(e);
			}
		}
		async function render() {
			await renderPage();
			await renderTextLayer();
		}
		function destroyPage(page) {
			if (page?.pdfjsPage) page.pdfjsPage.cleanup();
			destroyRenderTask();
		}
		function destroyRenderTask() {
			if (!renderTask) return;
			renderTask.cancel();
			renderTask = null;
		}
		watch(() => props.scale, () => {
			renderTextLayer();
		});
		setInitialViewport();
		onMounted(() => {
			render();
		});
		onBeforeUnmount(() => {
			destroyPage(props.page);
		});
		return (_ctx, _cache) => {
			return openBlock(), createElementBlock("div", {
				class: "sd-pdf-viewer-page",
				"data-page-id": __props.page.pageId,
				"data-page-number": pageNumber.value,
				style: normalizeStyle(pageStyle.value),
				"data-pdf-page": "",
				ref_key: "pageRef",
				ref: pageRef,
				onMousedown: onMouseDown,
				onMouseup: onMouseUp
			}, [createBaseVNode("div", _hoisted_2, [createBaseVNode("canvas", mergeProps({ class: "sd-pdf-viewer-page__canvas" }, canvasAttrs.value, {
				ref_key: "canvasRef",
				ref: canvasRef
			}), null, 16)]), __props.hasTextLayer ? (openBlock(), createElementBlock("div", {
				key: 0,
				class: "sd-pdf-viewer-page__text-layer",
				ref_key: "textLayerRef",
				ref: textLayerRef
			}, null, 512)) : createCommentVNode("", true)], 44, _hoisted_1$1);
		};
	}
}, [["__scopeId", "data-v-d7a9857d"]]);
var PdfViewerDocument_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
	__name: "PdfViewerDocument",
	props: {
		config: {
			type: Object,
			required: true
		},
		pdf: { type: Object },
		pages: {
			type: Array,
			required: true
		},
		scale: { type: Number },
		hasTextLayer: {
			type: Boolean,
			default: false
		},
		outputScale: { type: Number }
	},
	emits: [
		"page-focus",
		"page-rendered",
		"page-error",
		"selection-raw",
		"bypass-selection"
	],
	setup(__props, { emit: __emit }) {
		const emit = __emit;
		const documentRef = ref(null);
		const documentWrapper = ref(null);
		function onPageRendered(payload) {
			emit("page-rendered", payload);
		}
		function onPageError(page) {
			emit("page-error", page);
		}
		function onSelectionRaw(payload) {
			emit("selection-raw", payload);
		}
		function onBypassSelection(event) {
			emit("bypass-selection", event);
		}
		return (_ctx, _cache) => {
			return openBlock(), createElementBlock("div", {
				class: "sd-pdf-viewer-document",
				ref_key: "documentRef",
				ref: documentRef
			}, [createBaseVNode("div", {
				class: "sd-pdf-viewer-document__wrapper",
				ref_key: "documentWrapper",
				ref: documentWrapper
			}, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.pages, (page) => {
				return openBlock(), createBlock(PdfViewerPage_default, mergeProps({ key: page.pageId }, { ref_for: true }, {
					page,
					pages: __props.pages,
					scale: __props.scale,
					config: __props.config,
					hasTextLayer: __props.hasTextLayer,
					outputScale: __props.outputScale,
					documentEl: documentRef.value
				}, {
					onPageRendered,
					onPageError,
					onSelectionRaw,
					onBypassSelection
				}), null, 16);
			}), 128))], 512)], 512);
		};
	}
}, [["__scopeId", "data-v-2152178b"]]);
var _hoisted_1 = { class: "sd-pdf-viewer__main" };
var PdfViewer_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
	__name: "PdfViewer",
	props: {
		config: {
			type: Object,
			required: true
		},
		file: {
			type: Object,
			required: true
		},
		fileId: { type: String }
	},
	emits: [
		"page-rendered",
		"pages-loaded",
		"document-loaded",
		"document-ready",
		"document-error",
		"selection-raw",
		"bypass-selection"
	],
	setup(__props, { expose: __expose, emit: __emit }) {
		const emit = __emit;
		const props = __props;
		const pdfConfig = createPDFConfig({
			pdfLib: markRaw(props.config.pdfLib),
			workerSrc: props.config.workerSrc,
			setWorker: props.config.setWorker
		});
		const pdfAdapter = PDFAdapterFactory.create(pdfConfig);
		const rootRef = ref(null);
		const documentRef = ref(null);
		const pdf = ref(null);
		const pages = ref([]);
		const scale = ref(1);
		const totalPages = ref(0);
		const renderedPages = ref(0);
		const hasTextLayer = computed(() => props.config?.textLayer === true);
		const outputScale = computed(() => props.config?.outputScale ?? 2);
		function onPageRendered(payload) {
			const page = payload?.page;
			if (page) page.pageIsRendered = true;
			checkDocumentReady();
			emit("page-rendered", payload);
		}
		function onSelectionRaw(payload) {
			emit("selection-raw", payload);
		}
		function onBypassSelection(event) {
			emit("bypass-selection", event);
		}
		function checkDocumentReady() {
			if (totalPages.value <= 0) return;
			renderedPages.value += 1;
			if (renderedPages.value >= totalPages.value) emit("document-ready", {
				documentId: pdf.value?.documentId,
				viewerContainer: rootRef.value
			});
		}
		function updatePages(nextPages) {
			pages.value = nextPages;
			totalPages.value = nextPages.length;
			renderedPages.value = 0;
		}
		function updateScale(nextScale) {
			scale.value = floor(nextScale, 2);
		}
		__expose({ updateScale });
		async function getDocument(file) {
			if (!file) return;
			try {
				const result = await readFileAsArrayBuffer(file);
				pdf.value = {
					documentId: props.fileId || generateDocumentId("document"),
					pdfjsDocument: markRaw(await pdfAdapter.getDocument(result))
				};
				emit("document-loaded", file);
			} catch (e) {
				emit("document-error", e);
				console.error(e);
			}
		}
		async function getPages() {
			if (!pdf.value) return;
			const { pdfjsDocument } = pdf.value;
			const firstPageNum = 1;
			const lastPageNum = pdfjsDocument.numPages;
			try {
				const pdfjsPages = await pdfAdapter.getPages(pdfjsDocument, firstPageNum, lastPageNum);
				const mapPages = (pdfjsPage) => {
					return {
						documentId: pdf.value.documentId,
						pageId: generatePageId(pdf.value.documentId, pdfjsPage.pageNumber),
						pageNumber: pdfjsPage.pageNumber,
						pageIsRendered: false,
						pdfjsPage: markRaw(pdfjsPage)
					};
				};
				const pages$1 = pdfjsPages.map(mapPages);
				updatePages(pages$1);
				emit("pages-loaded", pages$1);
			} catch (e) {
				emit("document-error", e);
				console.error(e);
			}
		}
		function resetValues() {
			pages.value = [];
			scale.value = 1;
		}
		function generateDocumentId(fileName) {
			return `pdf-${fileName.replace(/\W/g, "")}-${Math.random().toString(36).slice(2)}-${Date.now()}`;
		}
		function generatePageId(documentId, pageNumber) {
			return `${documentId}-page-${pageNumber}`;
		}
		watch(() => props.file, (file) => {
			getDocument(file);
		}, { immediate: true });
		watch(pdf, (nextPdf, oldPdf) => {
			if (!nextPdf) return;
			if (oldPdf) resetValues();
			getPages();
		});
		return (_ctx, _cache) => {
			return openBlock(), createElementBlock("div", {
				class: "sd-pdf-viewer",
				ref_key: "rootRef",
				ref: rootRef
			}, [createBaseVNode("div", _hoisted_1, [createVNode(PdfViewerDocument_default, mergeProps({
				pdf: pdf.value,
				pages: pages.value,
				scale: scale.value,
				config: __props.config,
				hasTextLayer: hasTextLayer.value,
				outputScale: outputScale.value
			}, {
				onPageRendered,
				onSelectionRaw,
				onBypassSelection,
				ref_key: "documentRef",
				ref: documentRef
			}), null, 16)])], 512);
		};
	}
}, [["__scopeId", "data-v-c47c92bc"]]);
export { PdfViewer_default as default };
