@qrcommunication/gigapdf-lib 0.1.0 → 0.8.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/editor.ts","../src/viewer.ts"],"sourcesContent":["/**\n * `@qrcommunication/gigapdf-lib/editor` — an interactive **editing canvas** that\n * extends {@link GigaPdfViewer}. It overlays each rendered page with an SVG\n * surface for drawing/placing annotations and shapes (rectangle, ellipse, line,\n * freehand ink, text, image, highlight, redaction), supports select / move /\n * delete, and **bakes the edits into the real PDF** through the engine\n * (`addRectangle`/`addEllipse`/`addPolygon`/`addText`/`addImage`/`redact`) — then\n * re-renders. Zero external libraries; browser-only.\n *\n * ```ts\n * const ed = new GigaPdfEditor(giga, host, { defaultFont: { family: \"Roboto\", ttf } });\n * await ed.open({ kind: \"auto\", bytes });\n * ed.setTool(\"rect\"); ed.setStyle({ color: 0xcc0000 });\n * // …user draws…\n * ed.applyEdits(); // bake into the PDF\n * const pdf = ed.save(); // download the result\n * ```\n */\nimport { GigaPdfEngine } from \"./index\";\nimport { GigaPdfViewer, type ViewerOptions } from \"./viewer\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\" as const;\nconst PT_PER_MM = 72 / 25.4; // 1 mm in PDF points\n\n/** A page edge that carries an adjustable margin. */\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nexport type EditTool =\n | \"select\"\n | \"text\"\n | \"rect\"\n | \"ellipse\"\n | \"line\"\n | \"ink\"\n | \"image\"\n | \"highlight\"\n | \"redact\";\n\nexport interface EditStyle {\n /** Stroke (shapes / ink / line) and text colour, `0xRRGGBB`. */\n color: number;\n /** Shape fill colour, or `null` for no fill. */\n fill: number | null;\n lineWidth: number;\n fontSize: number;\n /** 0–1 fill/stroke alpha. */\n opacity: number;\n}\n\nexport interface EditorOptions extends ViewerOptions {\n /** A TrueType font for the text tool (required to add text). */\n defaultFont?: { family: string; ttf: Uint8Array };\n}\n\n// Element geometry is in **PDF points, top-left origin** (Y-down) so it maps 1:1\n// onto the overlay SVG (whose viewBox is the page in points) and flips to PDF's\n// bottom-left Y-up only when applied.\ntype El = {\n id: number;\n page: number;\n kind: EditTool;\n // bbox / endpoints / polyline, all in page points (top-left):\n x: number;\n y: number;\n w: number;\n h: number;\n pts?: number[];\n text?: string;\n imgUrl?: string;\n data?: Uint8Array;\n s: EditStyle;\n};\n\nconst hex = (n: number) => \"#\" + (n & 0xffffff).toString(16).padStart(6, \"0\");\n\nexport class GigaPdfEditor extends GigaPdfViewer {\n private tool: EditTool = \"select\";\n private style: EditStyle = { color: 0x1a1a1a, fill: null, lineWidth: 1.5, fontSize: 16, opacity: 1 };\n private els: El[] = [];\n private overlays: (SVGSVGElement | null)[] = [];\n private idSeq = 1;\n private selected: El | null = null;\n private fontObj: number | null = null;\n private editorOpts: EditorOptions;\n private palette: HTMLElement | null = null;\n\n // Rulers & margins. Margins are stored in **PDF points**, shared across pages.\n private margins: Record<Side, number> = { top: 56.7, right: 56.7, bottom: 56.7, left: 56.7 }; // ≈20 mm\n private guides: (SVGSVGElement | null)[] = [];\n private showGuides = true;\n private marginInputs: Record<Side, HTMLInputElement | null> = {\n top: null,\n right: null,\n bottom: null,\n left: null,\n };\n\n constructor(engine: GigaPdfEngine, container: HTMLElement, opts: EditorOptions = {}) {\n super(engine, container, opts);\n this.editorOpts = opts;\n this.buildPalette();\n }\n\n // ── public API ─────────────────────────────────────────────────────────────\n setTool(tool: EditTool) {\n this.tool = tool;\n for (const b of this.palette?.querySelectorAll(\"button[data-tool]\") ?? []) {\n b.classList.toggle(\"gpe-on\", b.getAttribute(\"data-tool\") === tool);\n }\n if (this.selected && tool !== \"select\") {\n this.selected = null;\n this.redrawAll();\n }\n }\n setStyle(patch: Partial<EditStyle>) {\n this.style = { ...this.style, ...patch };\n if (this.selected) {\n this.selected.s = { ...this.selected.s, ...patch };\n this.redraw(this.selected.page);\n }\n }\n /** Edits drawn but not yet baked into the PDF. */\n get pendingEdits(): number {\n return this.els.length;\n }\n\n /** Delete the currently selected element. */\n removeSelected() {\n if (!this.selected) return;\n const page = this.selected.page;\n this.els = this.els.filter((e) => e !== this.selected);\n this.selected = null;\n this.redraw(page);\n }\n /** Discard all un-applied edits. */\n clearEdits() {\n this.els = [];\n this.selected = null;\n this.redrawAll();\n }\n\n /** Bake every pending edit into the PDF, then re-render the affected pages. */\n applyEdits(): number {\n if (!this.doc || this.els.length === 0) return 0;\n const pages = new Set<number>();\n let applied = 0;\n for (const e of this.els) {\n if (this.bake(e)) {\n pages.add(e.page);\n applied++;\n }\n }\n this.els = [];\n this.selected = null;\n for (const p of pages) this.reRenderPage(p);\n this.redrawAll();\n return applied;\n }\n\n // ── apply one element to the PDF (flip Y: top-left points → PDF bottom-left) ──\n private bake(e: El): boolean {\n const doc = this.doc!;\n const H = this.pageHeightPt(e.page);\n const nx = Math.min(e.x, e.x + e.w);\n const ny = Math.min(e.y, e.y + e.h);\n const nw = Math.abs(e.w);\n const nh = Math.abs(e.h);\n const { color, fill, lineWidth, opacity } = e.s;\n switch (e.kind) {\n case \"rect\":\n return doc.addRectangle(e.page, nx, H - (ny + nh), nw, nh, color, fill, lineWidth, opacity);\n case \"ellipse\":\n return doc.addEllipse(e.page, nx + nw / 2, H - (ny + nh / 2), nw / 2, nh / 2, color, fill, lineWidth, opacity);\n case \"line\":\n return doc.addPolygon(e.page, [e.x, H - e.y, e.x + e.w, H - (e.y + e.h)], false, color, null, lineWidth, opacity);\n case \"ink\": {\n const flat: number[] = [];\n const pts = e.pts ?? [];\n for (let i = 0; i + 1 < pts.length; i += 2) {\n flat.push(pts[i]!, H - pts[i + 1]!);\n }\n return flat.length >= 4 ? doc.addPolygon(e.page, flat, false, color, null, lineWidth, opacity) : false;\n }\n case \"text\": {\n const id = this.ensureFont();\n if (id === null || !e.text) return false;\n return doc.addText(e.page, e.x, H - e.y, e.s.fontSize, e.text, id, color);\n }\n case \"image\":\n return e.data ? doc.addImage(e.page, e.data, nx, H - (ny + nh), nw, nh, opacity) : false;\n case \"highlight\":\n return doc.addRectangle(e.page, nx, H - (ny + nh), nw, nh, null, color, 0, 0.4);\n case \"redact\":\n return doc.redact(e.page, nx, H - (ny + nh), nw, nh, 0, false) >= 0;\n default:\n return false;\n }\n }\n\n private ensureFont(): number | null {\n if (this.fontObj !== null) return this.fontObj;\n const f = this.editorOpts.defaultFont;\n if (!f || !this.doc) return null;\n this.fontObj = this.doc.embedFont(f.family, f.ttf);\n return this.fontObj;\n }\n\n // ── overlays (rebuilt after each (re)render) ─────────────────────────────────\n protected override afterRender() {\n this.overlays = new Array(this.count + 1).fill(null);\n this.guides = new Array(this.count + 1).fill(null);\n const d = this.root.ownerDocument;\n for (let p = 1; p <= this.count; p++) {\n const box = this.pageEls[p];\n if (!box) continue;\n box.style.position = \"relative\";\n // 1) drawing surface — captures the editing tools.\n const svg = d.createElementNS(SVG_NS, \"svg\") as SVGSVGElement;\n svg.setAttribute(\"viewBox\", `0 0 ${this.pageWidthPt(p)} ${this.pageHeightPt(p)}`);\n svg.setAttribute(\"preserveAspectRatio\", \"none\");\n svg.style.cssText = \"position:absolute;inset:0;width:100%;height:100%;touch-action:none\";\n svg.dataset.page = String(p);\n box.appendChild(svg);\n this.overlays[p] = svg;\n this.bindOverlay(svg, p);\n // 2) rulers + margin guides — on top, click-through except the drag handles.\n const g = d.createElementNS(SVG_NS, \"svg\") as SVGSVGElement;\n g.setAttribute(\"viewBox\", `0 0 ${this.pageWidthPt(p)} ${this.pageHeightPt(p)}`);\n g.setAttribute(\"preserveAspectRatio\", \"none\");\n g.style.cssText = \"position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible\";\n g.dataset.page = String(p);\n box.appendChild(g);\n this.guides[p] = g;\n }\n this.redrawAll();\n this.redrawGuidesAll();\n }\n\n /** Keep ruler ticks / handles a constant on-screen size as the zoom changes. */\n protected override onZoomChange() {\n this.redrawGuidesAll();\n }\n\n // ── rulers & margins (public API) ────────────────────────────────────────────\n /** Set page margins (default unit: millimetres). */\n setMargins(m: Partial<Record<Side, number>>, unit: \"mm\" | \"pt\" = \"mm\") {\n const k = unit === \"mm\" ? PT_PER_MM : 1;\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as Side[]) {\n const v = m[side];\n if (typeof v === \"number\" && isFinite(v)) this.margins[side] = Math.max(0, v * k);\n }\n this.syncMarginInputs();\n this.redrawGuidesAll();\n }\n /** Current margins in the requested unit (millimetres by default). */\n getMargins(unit: \"mm\" | \"pt\" = \"mm\"): Record<Side, number> {\n const k = unit === \"mm\" ? PT_PER_MM : 1;\n return {\n top: this.margins.top / k,\n right: this.margins.right / k,\n bottom: this.margins.bottom / k,\n left: this.margins.left / k,\n };\n }\n /** Show or hide the rulers and margin guides. */\n showRulers(on: boolean) {\n this.showGuides = on;\n this.redrawGuidesAll();\n }\n\n private syncMarginInputs() {\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as Side[]) {\n const inp = this.marginInputs[side];\n if (inp) inp.value = String(Math.round(this.margins[side] / PT_PER_MM));\n }\n }\n\n // ── ruler / margin drawing ───────────────────────────────────────────────────\n private redrawGuidesAll() {\n for (let p = 1; p <= this.count; p++) this.redrawGuides(p);\n }\n\n private redrawGuides(page: number) {\n const g = this.guides[page];\n if (!g) return;\n g.replaceChildren();\n if (!this.showGuides) return;\n const W = this.pageWidthPt(page);\n const H = this.pageHeightPt(page);\n if (!W || !H) return;\n const d = this.root.ownerDocument;\n const z = this.zoom || 1;\n const band = 14 / z; // ruler thickness ≈14 px on screen\n const fs = 8 / z; // tick-label size ≈8 px\n\n const line = (x1: number, y1: number, x2: number, y2: number, stroke: string, dash?: string) => {\n const l = d.createElementNS(SVG_NS, \"line\");\n l.setAttribute(\"x1\", String(x1));\n l.setAttribute(\"y1\", String(y1));\n l.setAttribute(\"x2\", String(x2));\n l.setAttribute(\"y2\", String(y2));\n l.setAttribute(\"stroke\", stroke);\n l.setAttribute(\"stroke-width\", \"1\");\n l.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n if (dash) l.setAttribute(\"stroke-dasharray\", dash);\n g.appendChild(l);\n };\n const label = (x: number, y: number, text: string) => {\n const t = d.createElementNS(SVG_NS, \"text\");\n t.setAttribute(\"x\", String(x));\n t.setAttribute(\"y\", String(y));\n t.setAttribute(\"font-size\", String(fs));\n t.setAttribute(\"fill\", \"#c9ced2\");\n t.setAttribute(\"font-family\", \"system-ui,sans-serif\");\n t.textContent = text;\n g.appendChild(t);\n };\n const bandRect = (w: number, h: number) => {\n const r = d.createElementNS(SVG_NS, \"rect\");\n r.setAttribute(\"x\", \"0\");\n r.setAttribute(\"y\", \"0\");\n r.setAttribute(\"width\", String(w));\n r.setAttribute(\"height\", String(h));\n r.setAttribute(\"fill\", \"rgba(38,42,45,0.86)\");\n g.appendChild(r);\n };\n\n // ruler bands (top + left)\n bandRect(W, band);\n bandRect(band, H);\n\n // ticks every 5 mm (minor) / 10 mm (major + mm label)\n const step = PT_PER_MM * 5;\n for (let x = 0, m = 0; x <= W + 0.5; x += step, m += 5) {\n const major = m % 10 === 0;\n line(x, 0, x, major ? band : band * 0.55, \"#7a8085\");\n if (major && m > 0) label(x + 1 / z, band - 1.5 / z, String(m));\n }\n for (let y = 0, m = 0; y <= H + 0.5; y += step, m += 5) {\n const major = m % 10 === 0;\n line(0, y, major ? band : band * 0.55, y, \"#7a8085\");\n if (major && m > 0) label(1 / z, y - 1 / z, String(m));\n }\n\n // margin guides across the page (dashed blue)\n const ml = this.margins.left;\n const mr = W - this.margins.right;\n const mt = this.margins.top;\n const mb = H - this.margins.bottom;\n line(ml, 0, ml, H, \"#3b82f6\", \"5 3\");\n line(mr, 0, mr, H, \"#3b82f6\", \"5 3\");\n line(0, mt, W, mt, \"#3b82f6\", \"5 3\");\n line(0, mb, W, mb, \"#3b82f6\", \"5 3\");\n\n // draggable handles, sitting in the ruler bands\n const hs = 11 / z;\n this.marginHandle(g, page, \"left\", ml, band / 2, hs, \"ew-resize\", W, H);\n this.marginHandle(g, page, \"right\", mr, band / 2, hs, \"ew-resize\", W, H);\n this.marginHandle(g, page, \"top\", band / 2, mt, hs, \"ns-resize\", W, H);\n this.marginHandle(g, page, \"bottom\", band / 2, mb, hs, \"ns-resize\", W, H);\n }\n\n private marginHandle(\n g: SVGSVGElement,\n page: number,\n side: Side,\n cx: number,\n cy: number,\n size: number,\n cursor: string,\n W: number,\n H: number\n ) {\n const d = this.root.ownerDocument;\n const r = d.createElementNS(SVG_NS, \"rect\");\n r.setAttribute(\"x\", String(cx - size / 2));\n r.setAttribute(\"y\", String(cy - size / 2));\n r.setAttribute(\"width\", String(size));\n r.setAttribute(\"height\", String(size));\n r.setAttribute(\"rx\", String(size * 0.25));\n r.setAttribute(\"fill\", \"#3b82f6\");\n r.setAttribute(\"stroke\", \"#fff\");\n r.setAttribute(\"stroke-width\", \"1\");\n r.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n r.style.cssText = `pointer-events:all;cursor:${cursor}`;\n r.addEventListener(\"pointerdown\", (e: PointerEvent) => {\n // Capture on the *guide layer* (stable across redraws), not the handle —\n // each drag redraws and replaces this rect, which would drop its capture.\n e.stopPropagation();\n e.preventDefault();\n try {\n g.setPointerCapture(e.pointerId);\n } catch {\n /* capture is best-effort */\n }\n const move = (ev: PointerEvent) => {\n const pp = this.toPagePt(g, ev.clientX, ev.clientY);\n const val =\n side === \"left\" ? pp.x : side === \"right\" ? W - pp.x : side === \"top\" ? pp.y : H - pp.y;\n this.dragMargin(page, side, val);\n };\n const up = (ev: PointerEvent) => {\n try {\n g.releasePointerCapture(ev.pointerId);\n } catch {\n /* already released */\n }\n g.removeEventListener(\"pointermove\", move);\n g.removeEventListener(\"pointerup\", up);\n g.removeEventListener(\"pointercancel\", up);\n };\n g.addEventListener(\"pointermove\", move);\n g.addEventListener(\"pointerup\", up);\n g.addEventListener(\"pointercancel\", up);\n });\n g.appendChild(r);\n }\n\n private dragMargin(page: number, side: Side, val: number) {\n const W = this.pageWidthPt(page);\n const H = this.pageHeightPt(page);\n const lim = side === \"left\" || side === \"right\" ? W : H;\n const opp =\n side === \"left\"\n ? this.margins.right\n : side === \"right\"\n ? this.margins.left\n : side === \"top\"\n ? this.margins.bottom\n : this.margins.top;\n this.margins[side] = Math.max(0, Math.min(val, lim - opp - 8));\n this.syncMarginInputs();\n this.redrawGuidesAll();\n }\n\n private toPagePt(svg: SVGSVGElement, clientX: number, clientY: number): { x: number; y: number } {\n const m = svg.getScreenCTM();\n if (!m) return { x: 0, y: 0 };\n const pt = new DOMPoint(clientX, clientY).matrixTransform(m.inverse());\n return { x: pt.x, y: pt.y };\n }\n\n private bindOverlay(svg: SVGSVGElement, page: number) {\n let draft: El | null = null;\n let origin: { x: number; y: number } | null = null;\n let moving: { el: El; dx: number; dy: number } | null = null;\n\n svg.addEventListener(\"pointerdown\", (e: PointerEvent) => {\n svg.setPointerCapture(e.pointerId);\n const p = this.toPagePt(svg, e.clientX, e.clientY);\n if (this.tool === \"select\") {\n const hit = this.hitTest(page, p);\n this.selected = hit;\n if (hit) moving = { el: hit, dx: p.x - hit.x, dy: p.y - hit.y };\n this.redraw(page);\n return;\n }\n if (this.tool === \"text\") {\n this.placeText(page, p);\n return;\n }\n if (this.tool === \"image\") {\n void this.placeImage(page, p);\n return;\n }\n origin = p;\n draft = {\n id: this.idSeq++,\n page,\n kind: this.tool,\n x: p.x,\n y: p.y,\n w: 0,\n h: 0,\n s: { ...this.style },\n ...(this.tool === \"ink\" ? { pts: [p.x, p.y] } : {}),\n };\n this.els.push(draft);\n });\n\n svg.addEventListener(\"pointermove\", (e: PointerEvent) => {\n const p = this.toPagePt(svg, e.clientX, e.clientY);\n if (moving) {\n moving.el.x = p.x - moving.dx;\n moving.el.y = p.y - moving.dy;\n this.redraw(page);\n return;\n }\n if (!draft || !origin) return;\n if (draft.kind === \"ink\") {\n draft.pts!.push(p.x, p.y);\n } else {\n draft.x = origin.x;\n draft.y = origin.y;\n draft.w = p.x - origin.x;\n draft.h = p.y - origin.y;\n }\n this.redraw(page);\n });\n\n const end = () => {\n if (draft && !this.isMeaningful(draft)) {\n this.els = this.els.filter((x) => x !== draft);\n this.redraw(page);\n } else if (draft) {\n this.selected = draft;\n this.redraw(page);\n }\n draft = null;\n origin = null;\n moving = null;\n };\n svg.addEventListener(\"pointerup\", end);\n svg.addEventListener(\"pointercancel\", end);\n }\n\n private isMeaningful(e: El): boolean {\n if (e.kind === \"ink\") return (e.pts?.length ?? 0) >= 4;\n return Math.abs(e.w) > 1 || Math.abs(e.h) > 1;\n }\n\n private hitTest(page: number, p: { x: number; y: number }): El | null {\n // Topmost element whose bbox contains the point.\n for (let i = this.els.length - 1; i >= 0; i--) {\n const e = this.els[i]!;\n if (e.page !== page) continue;\n const nx = Math.min(e.x, e.x + e.w);\n const ny = Math.min(e.y, e.y + e.h);\n const nw = Math.abs(e.w) || 12;\n const nh = Math.abs(e.h) || 12;\n if (p.x >= nx - 4 && p.x <= nx + nw + 4 && p.y >= ny - 4 && p.y <= ny + nh + 4) return e;\n }\n return null;\n }\n\n private placeText(page: number, p: { x: number; y: number }) {\n const text = this.root.ownerDocument.defaultView?.prompt(\"Text:\") ?? \"\";\n if (!text.trim()) return;\n this.els.push({ id: this.idSeq++, page, kind: \"text\", x: p.x, y: p.y + this.style.fontSize, w: 0, h: 0, text, s: { ...this.style } });\n this.redraw(page);\n }\n\n private async placeImage(page: number, p: { x: number; y: number }) {\n const d = this.root.ownerDocument;\n const input = d.createElement(\"input\");\n input.type = \"file\";\n input.accept = \"image/png,image/jpeg\";\n input.addEventListener(\"change\", async () => {\n const file = input.files?.[0];\n if (!file) return;\n const data = new Uint8Array(await file.arrayBuffer());\n const url = URL.createObjectURL(file);\n this.els.push({ id: this.idSeq++, page, kind: \"image\", x: p.x, y: p.y, w: 120, h: 120, data, imgUrl: url, s: { ...this.style } });\n this.redraw(page);\n });\n input.click();\n }\n\n // ── overlay drawing ──────────────────────────────────────────────────────────\n private redrawAll() {\n for (let p = 1; p <= this.count; p++) this.redraw(p);\n }\n\n private redraw(page: number) {\n const svg = this.overlays[page];\n if (!svg) return;\n svg.replaceChildren();\n const d = this.root.ownerDocument;\n for (const e of this.els) {\n if (e.page !== page) continue;\n const node = this.elNode(d, e);\n if (node) svg.appendChild(node);\n }\n if (this.selected && this.selected.page === page) {\n const nx = Math.min(this.selected.x, this.selected.x + this.selected.w);\n const ny = Math.min(this.selected.y, this.selected.y + this.selected.h);\n const sel = d.createElementNS(SVG_NS, \"rect\");\n sel.setAttribute(\"x\", String(nx - 3));\n sel.setAttribute(\"y\", String(ny - 3));\n sel.setAttribute(\"width\", String((Math.abs(this.selected.w) || 12) + 6));\n sel.setAttribute(\"height\", String((Math.abs(this.selected.h) || 12) + 6));\n sel.setAttribute(\"fill\", \"none\");\n sel.setAttribute(\"stroke\", \"#3b82f6\");\n sel.setAttribute(\"stroke-dasharray\", \"4 3\");\n sel.setAttribute(\"stroke-width\", \"1\");\n svg.appendChild(sel);\n }\n }\n\n private elNode(d: Document, e: El): SVGElement | null {\n const stroke = hex(e.s.color);\n const fill = e.s.fill === null ? \"none\" : hex(e.s.fill);\n const nx = Math.min(e.x, e.x + e.w);\n const ny = Math.min(e.y, e.y + e.h);\n const nw = Math.abs(e.w);\n const nh = Math.abs(e.h);\n switch (e.kind) {\n case \"rect\":\n case \"highlight\":\n case \"redact\": {\n const r = d.createElementNS(SVG_NS, \"rect\");\n r.setAttribute(\"x\", String(nx));\n r.setAttribute(\"y\", String(ny));\n r.setAttribute(\"width\", String(nw));\n r.setAttribute(\"height\", String(nh));\n if (e.kind === \"rect\") {\n r.setAttribute(\"fill\", fill);\n r.setAttribute(\"stroke\", stroke);\n r.setAttribute(\"stroke-width\", String(e.s.lineWidth));\n r.setAttribute(\"opacity\", String(e.s.opacity));\n } else if (e.kind === \"highlight\") {\n r.setAttribute(\"fill\", stroke);\n r.setAttribute(\"opacity\", \"0.4\");\n } else {\n r.setAttribute(\"fill\", \"#000\");\n r.setAttribute(\"stroke\", \"#f00\");\n r.setAttribute(\"stroke-dasharray\", \"3 2\");\n r.setAttribute(\"stroke-width\", \"0.5\");\n }\n return r;\n }\n case \"ellipse\": {\n const el = d.createElementNS(SVG_NS, \"ellipse\");\n el.setAttribute(\"cx\", String(nx + nw / 2));\n el.setAttribute(\"cy\", String(ny + nh / 2));\n el.setAttribute(\"rx\", String(nw / 2));\n el.setAttribute(\"ry\", String(nh / 2));\n el.setAttribute(\"fill\", fill);\n el.setAttribute(\"stroke\", stroke);\n el.setAttribute(\"stroke-width\", String(e.s.lineWidth));\n el.setAttribute(\"opacity\", String(e.s.opacity));\n return el;\n }\n case \"line\": {\n const ln = d.createElementNS(SVG_NS, \"line\");\n ln.setAttribute(\"x1\", String(e.x));\n ln.setAttribute(\"y1\", String(e.y));\n ln.setAttribute(\"x2\", String(e.x + e.w));\n ln.setAttribute(\"y2\", String(e.y + e.h));\n ln.setAttribute(\"stroke\", stroke);\n ln.setAttribute(\"stroke-width\", String(e.s.lineWidth));\n return ln;\n }\n case \"ink\": {\n const pl = d.createElementNS(SVG_NS, \"polyline\");\n const pts = e.pts ?? [];\n let s = \"\";\n for (let i = 0; i + 1 < pts.length; i += 2) s += `${pts[i]},${pts[i + 1]} `;\n pl.setAttribute(\"points\", s.trim());\n pl.setAttribute(\"fill\", \"none\");\n pl.setAttribute(\"stroke\", stroke);\n pl.setAttribute(\"stroke-width\", String(e.s.lineWidth));\n pl.setAttribute(\"stroke-linejoin\", \"round\");\n pl.setAttribute(\"stroke-linecap\", \"round\");\n return pl;\n }\n case \"text\": {\n const t = d.createElementNS(SVG_NS, \"text\");\n t.setAttribute(\"x\", String(e.x));\n t.setAttribute(\"y\", String(e.y));\n t.setAttribute(\"font-size\", String(e.s.fontSize));\n t.setAttribute(\"fill\", stroke);\n t.setAttribute(\"font-family\", \"sans-serif\");\n t.textContent = e.text ?? \"\";\n return t;\n }\n case \"image\": {\n const im = d.createElementNS(SVG_NS, \"image\");\n im.setAttribute(\"x\", String(nx));\n im.setAttribute(\"y\", String(ny));\n im.setAttribute(\"width\", String(nw || 120));\n im.setAttribute(\"height\", String(nh || 120));\n if (e.imgUrl) im.setAttribute(\"href\", e.imgUrl);\n return im;\n }\n default:\n return null;\n }\n }\n\n // ── tool palette ─────────────────────────────────────────────────────────────\n private buildPalette() {\n const d = this.root.ownerDocument;\n const bar = d.createElement(\"div\");\n bar.className = \"gpe-bar\";\n bar.style.cssText =\n \"display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding:6px 10px;background:#3a3f42;border-bottom:1px solid #000;color:#eee;font:13px system-ui\";\n const tools: [EditTool, string][] = [\n [\"select\", \"▸\"],\n [\"text\", \"T\"],\n [\"rect\", \"▭\"],\n [\"ellipse\", \"◯\"],\n [\"line\", \"╱\"],\n [\"ink\", \"✎\"],\n [\"image\", \"🖼\"],\n [\"highlight\", \"▥\"],\n [\"redact\", \"█\"],\n ];\n for (const [t, label] of tools) {\n const b = d.createElement(\"button\");\n b.textContent = label;\n b.title = t;\n b.dataset.tool = t;\n b.style.cssText = \"background:#4a4f52;color:#eee;border:0;border-radius:4px;padding:4px 8px;cursor:pointer\";\n b.addEventListener(\"click\", () => this.setTool(t));\n bar.appendChild(b);\n }\n const color = d.createElement(\"input\");\n color.type = \"color\";\n color.value = hex(this.style.color);\n color.title = \"Colour\";\n color.addEventListener(\"input\", () => this.setStyle({ color: parseInt(color.value.slice(1), 16) }));\n bar.appendChild(color);\n\n // Margins group: ruler toggle + four live mm inputs (T / R / B / L).\n const mg = d.createElement(\"span\");\n mg.style.cssText = \"display:flex;align-items:center;gap:3px;margin-left:8px\";\n const mtog = d.createElement(\"input\");\n mtog.type = \"checkbox\";\n mtog.checked = this.showGuides;\n mtog.title = \"Show rulers & margins\";\n mtog.addEventListener(\"change\", () => this.showRulers(mtog.checked));\n const mlbl = d.createElement(\"span\");\n mlbl.textContent = \"Marges mm\";\n mlbl.style.color = \"#bbb\";\n mg.append(mtog, mlbl);\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as Side[]) {\n const inp = d.createElement(\"input\");\n inp.type = \"number\";\n inp.min = \"0\";\n inp.value = String(Math.round(this.margins[side] / PT_PER_MM));\n inp.title = side;\n inp.style.cssText =\n \"width:44px;background:#222;color:#eee;border:1px solid #000;border-radius:4px;padding:3px;text-align:center\";\n inp.addEventListener(\"change\", () => this.setMargins({ [side]: Number(inp.value) || 0 }, \"mm\"));\n this.marginInputs[side] = inp;\n mg.appendChild(inp);\n }\n bar.appendChild(mg);\n\n const sp = d.createElement(\"span\");\n sp.style.flex = \"1\";\n bar.appendChild(sp);\n\n const apply = d.createElement(\"button\");\n apply.textContent = \"Apply\";\n apply.style.cssText = \"background:#2563eb;color:#fff;border:0;border-radius:4px;padding:4px 12px;cursor:pointer\";\n apply.addEventListener(\"click\", () => this.applyEdits());\n bar.appendChild(apply);\n\n const del = d.createElement(\"button\");\n del.textContent = \"Delete\";\n del.style.cssText = \"background:#4a4f52;color:#eee;border:0;border-radius:4px;padding:4px 10px;cursor:pointer\";\n del.addEventListener(\"click\", () => this.removeSelected());\n bar.appendChild(del);\n\n // Insert below the viewer toolbar (first child) if present, else at the top.\n const style = d.createElement(\"style\");\n style.textContent = \".gpe-bar button.gpe-on{outline:2px solid #3b82f6}\";\n d.head.appendChild(style);\n this.root.insertBefore(bar, this.root.children[1] ?? null);\n this.palette = bar;\n this.setTool(\"select\");\n }\n}\n","/**\n * `@qrcommunication/gigapdf-lib/viewer` — a zero-dependency document **viewer**\n * built entirely on the WASM engine. It opens PDF, Office (docx/xlsx/pptx +\n * legacy/ODF) and HTML — converting non-PDF inputs to PDF in-engine — renders\n * pages with {@link GigaPdfDoc.renderPage}, detects each page's orientation and\n * adapts, and offers navigation, zoom, a thumbnail rail and a **fullscreen\n * presentation mode**. No third-party libraries (no pdf.js); browser-only (DOM).\n *\n * ```ts\n * const giga = await GigaPdfEngine.load(wasmUrl);\n * const viewer = new GigaPdfViewer(giga, document.getElementById(\"app\")!);\n * await viewer.open({ kind: \"auto\", bytes }); // pdf / office / html auto-detected\n * viewer.present(); // fullscreen slideshow\n * ```\n */\nimport { GigaPdfEngine, GigaPdfDoc, type HtmlFont } from \"./index\";\n\n/** A document to open. `auto` sniffs the format from magic bytes. */\nexport type ViewerSource =\n | { kind: \"pdf\"; bytes: Uint8Array }\n | { kind: \"office\"; bytes: Uint8Array }\n | { kind: \"html\"; html: string; fonts?: HtmlFont[] }\n | { kind: \"auto\"; bytes: Uint8Array };\n\nexport interface ViewerOptions {\n /** CSS zoom multiplier applied to the page boxes (default 1). */\n scale?: number;\n /** Raster scale for crisp rendering (default 2 ≈ retina). */\n renderScale?: number;\n /** Show the thumbnail rail (default true). */\n thumbnails?: boolean;\n /** Show the toolbar (default true). */\n toolbar?: boolean;\n /** Gutter background colour (default `#525659`). */\n background?: string;\n}\n\n/** Page orientation derived from the rendered raster. */\nexport type Orientation = \"portrait\" | \"landscape\";\n\nconst CSS = `\n.gpv{position:relative;display:flex;flex-direction:column;height:100%;width:100%;background:var(--gpv-bg,#525659);color:#eee;font:13px/1.4 system-ui,sans-serif;overflow:hidden}\n.gpv-bar{display:flex;align-items:center;gap:6px;padding:6px 10px;background:#323639;border-bottom:1px solid #000;flex:0 0 auto;user-select:none}\n.gpv-bar button{background:#4a4f52;color:#eee;border:0;border-radius:4px;padding:4px 9px;cursor:pointer;font:inherit}\n.gpv-bar button:hover{background:#5a6063}\n.gpv-bar .gpv-sp{flex:1}\n.gpv-bar input{width:46px;background:#222;color:#eee;border:1px solid #000;border-radius:4px;padding:3px;text-align:center;font:inherit}\n.gpv-bar select{background:#222;color:#eee;border:1px solid #000;border-radius:4px;padding:3px;font:inherit;cursor:pointer}\n.gpv-bar .gpv-zoom{min-width:44px;text-align:center;color:#ddd;font-variant-numeric:tabular-nums}\n.gpv-body{flex:1;display:flex;min-height:0}\n.gpv-thumbs{flex:0 0 132px;overflow-y:auto;background:#2a2d2f;padding:8px;display:flex;flex-direction:column;gap:8px}\n.gpv-thumbs img{width:100%;display:block;border:2px solid transparent;border-radius:2px;cursor:pointer;background:#fff}\n.gpv-thumbs .gpv-on img{border-color:#3b82f6}\n.gpv-thumbs span{display:block;text-align:center;color:#aaa;font-size:11px}\n.gpv-pages{flex:1;overflow:auto;padding:18px;display:flex;flex-direction:column;align-items:center;gap:18px;scroll-behavior:smooth}\n.gpv-page{position:relative;box-shadow:0 1px 6px rgba(0,0,0,.6);background:#fff}\n.gpv-page img{display:block;width:100%;height:auto}\n.gpv:fullscreen{--gpv-bg:#000}\n.gpv.gpv-present .gpv-thumbs,.gpv.gpv-present .gpv-bar{display:none}\n.gpv.gpv-present .gpv-pages{padding:0;justify-content:center;overflow:hidden}\n.gpv.gpv-present .gpv-page{box-shadow:none;max-height:100vh}\n.gpv.gpv-present .gpv-page img{width:auto;max-width:100vw;max-height:100vh}\n`;\n\nlet styleInjected = false;\nfunction injectStyle(doc: Document) {\n if (styleInjected) return;\n const el = doc.createElement(\"style\");\n el.textContent = CSS;\n doc.head.appendChild(el);\n styleInjected = true;\n}\n\n/** Read a PNG's pixel dimensions from its IHDR (bytes 16–23, big-endian). */\nfunction pngSize(b: Uint8Array): { w: number; h: number } {\n if (b.length < 24) return { w: 1, h: 1 };\n const dv = new DataView(b.buffer, b.byteOffset, b.byteLength);\n return { w: dv.getUint32(16) || 1, h: dv.getUint32(20) || 1 };\n}\n\nexport class GigaPdfViewer {\n // `protected` members are the surface the editor subclass builds on.\n protected doc: GigaPdfDoc | null = null;\n protected count = 0;\n protected current = 1;\n protected cssScale: number;\n protected renderScale: number;\n /** Active auto-fit mode; re-applied on resize and page change. */\n protected fitMode: \"none\" | \"width\" | \"page\" = \"none\";\n private presenting = false;\n private resizeObs: ResizeObserver | null = null;\n\n // Per-page caches (1-indexed; slot 0 unused).\n protected urls: (string | null)[] = [];\n protected sizes: ({ w: number; h: number } | null)[] = [];\n\n // DOM nodes.\n protected root: HTMLElement;\n private bar: HTMLElement | null = null;\n private body!: HTMLElement;\n private thumbs!: HTMLElement;\n protected pages!: HTMLElement;\n private pageInput: HTMLInputElement | null = null;\n private zoomReadout: HTMLElement | null = null;\n private zoomSelect: HTMLSelectElement | null = null;\n protected pageEls: (HTMLElement | null)[] = [];\n private onKey: (e: KeyboardEvent) => void;\n private onFsChange: () => void;\n\n constructor(\n protected engine: GigaPdfEngine,\n container: HTMLElement,\n private options: ViewerOptions = {}\n ) {\n this.cssScale = options.scale ?? 1;\n this.renderScale = options.renderScale ?? 2;\n this.root = container;\n injectStyle(container.ownerDocument);\n this.buildChrome();\n this.onKey = (e) => this.handleKey(e);\n this.onFsChange = () => this.syncPresentClass();\n container.ownerDocument.addEventListener(\"keydown\", this.onKey);\n container.ownerDocument.addEventListener(\"fullscreenchange\", this.onFsChange);\n }\n\n /** Number of pages currently open. */\n get pageCount(): number {\n return this.count;\n }\n /** The page currently in view (1-based). */\n get currentPage(): number {\n return this.current;\n }\n /** Orientation of `page` (after open). */\n orientation(page: number): Orientation {\n const s = this.sizes[page];\n return s && s.w > s.h ? \"landscape\" : \"portrait\";\n }\n\n /** The current document as PDF bytes (including any applied edits). */\n save(): Uint8Array {\n if (!this.doc) return new Uint8Array(0);\n return this.doc.save();\n }\n\n /** Open a document; Office/HTML are converted to PDF in-engine. Returns the page count. */\n async open(src: ViewerSource): Promise<number> {\n const pdf = this.toPdf(src);\n this.close();\n this.doc = this.engine.open(pdf);\n this.count = this.doc.pageCount();\n this.urls = new Array(this.count + 1).fill(null);\n this.sizes = new Array(this.count + 1).fill(null);\n this.pageEls = new Array(this.count + 1).fill(null);\n this.current = 1;\n this.renderAllPages();\n if (this.options.thumbnails !== false) this.buildThumbs();\n this.goTo(1);\n return this.count;\n }\n\n private toPdf(src: ViewerSource): Uint8Array {\n switch (src.kind) {\n case \"pdf\":\n return src.bytes;\n case \"office\":\n return this.engine.officeToPdf(src.bytes);\n case \"html\":\n return src.fonts?.length\n ? this.engine.htmlRender(src.html, src.fonts)\n : this.engine.htmlToPdf(src.html);\n case \"auto\":\n return this.detectAndConvert(src.bytes);\n }\n }\n\n private detectAndConvert(b: Uint8Array): Uint8Array {\n const is = (...sig: number[]) => sig.every((v, i) => b[i] === v);\n if (is(0x25, 0x50, 0x44, 0x46)) return b; // %PDF\n if (is(0x50, 0x4b)) return this.engine.officeToPdf(b); // PK zip (docx/xlsx/pptx/odf)\n if (is(0xd0, 0xcf, 0x11, 0xe0)) return this.engine.officeToPdf(b); // OLE2 (legacy doc/xls/ppt)\n return this.engine.htmlToPdf(new TextDecoder().decode(b)); // else: HTML/text\n }\n\n // ── rendering ────────────────────────────────────────────────────────────────\n protected renderPageRaster(page: number): { url: string; w: number; h: number } {\n const cachedUrl = this.urls[page];\n const cachedSize = this.sizes[page];\n if (cachedUrl && cachedSize) return { url: cachedUrl, ...cachedSize };\n const png = this.doc!.renderPage(page, this.renderScale);\n const size = pngSize(png);\n // Copy into a fresh ArrayBuffer (the wasm-backed view may sit on a\n // SharedArrayBuffer, which `Blob` rejects).\n const buf = new ArrayBuffer(png.byteLength);\n new Uint8Array(buf).set(png);\n const url = URL.createObjectURL(new Blob([buf], { type: \"image/png\" }));\n this.urls[page] = url;\n this.sizes[page] = size;\n return { url, ...size };\n }\n\n /** The page's width / height in PDF points (raster pixels ÷ render scale). */\n protected pageWidthPt(page: number): number {\n const s = this.sizes[page];\n return s ? s.w / this.renderScale : 0;\n }\n protected pageHeightPt(page: number): number {\n const s = this.sizes[page];\n return s ? s.h / this.renderScale : 0;\n }\n\n /** Re-raster a page after its content changed (drops the cached image). */\n protected reRenderPage(page: number) {\n const old = this.urls[page];\n if (old) URL.revokeObjectURL(old);\n this.urls[page] = null;\n this.sizes[page] = null;\n const { url, w } = this.renderPageRaster(page);\n const box = this.pageEls[page];\n if (!box) return;\n box.style.width = `${(w / this.renderScale) * this.cssScale}px`;\n const img = box.querySelector(\"img\");\n if (img) img.src = url;\n }\n\n /** Hook for subclasses (the editor) to attach per-page overlays. */\n protected afterRender() {}\n\n private renderAllPages() {\n this.pages.replaceChildren();\n for (let p = 1; p <= this.count; p++) {\n const { url, w, h } = this.renderPageRaster(p);\n const box = this.root.ownerDocument.createElement(\"div\");\n box.className = \"gpv-page\";\n box.dataset.page = String(p);\n // Size the box to the page's true aspect ratio (so landscape pages are\n // wide and portrait pages tall) at the current CSS zoom.\n box.style.width = `${(w / this.renderScale) * this.cssScale}px`;\n const img = this.root.ownerDocument.createElement(\"img\");\n img.src = url;\n img.alt = `Page ${p}`;\n img.loading = \"lazy\";\n box.appendChild(img);\n this.pages.appendChild(box);\n this.pageEls[p] = box;\n }\n this.afterRender();\n }\n\n private buildThumbs() {\n this.thumbs.replaceChildren();\n for (let p = 1; p <= this.count; p++) {\n const url = this.urls[p];\n const item = this.root.ownerDocument.createElement(\"div\");\n item.dataset.page = String(p);\n const img = this.root.ownerDocument.createElement(\"img\");\n if (url) img.src = url;\n img.addEventListener(\"click\", () => this.goTo(p));\n const label = this.root.ownerDocument.createElement(\"span\");\n label.textContent = String(p);\n item.append(img, label);\n this.thumbs.appendChild(item);\n }\n this.highlightThumb();\n }\n\n private highlightThumb() {\n for (const child of Array.from(this.thumbs.children)) {\n child.classList.toggle(\"gpv-on\", child.getAttribute(\"data-page\") === String(this.current));\n }\n }\n\n // ── navigation ───────────────────────────────────────────────────────────────\n /** Scroll/jump to `page` (clamped to range). */\n goTo(page: number) {\n if (this.count === 0) return;\n this.current = Math.min(Math.max(1, Math.round(page)), this.count);\n if (this.presenting) {\n // Single-page: show only the current page.\n for (let p = 1; p <= this.count; p++) {\n const el = this.pageEls[p];\n if (el) el.style.display = p === this.current ? \"\" : \"none\";\n }\n } else {\n this.pageEls[this.current]?.scrollIntoView({ block: \"start\" });\n }\n if (this.pageInput) this.pageInput.value = String(this.current);\n if (this.fitMode !== \"none\") this.applyFitMode();\n this.highlightThumb();\n }\n next() {\n this.goTo(this.current + 1);\n }\n prev() {\n this.goTo(this.current - 1);\n }\n\n // ── zoom ─────────────────────────────────────────────────────────────────────\n /** Current CSS zoom multiplier (1 = 100%). */\n get zoom(): number {\n return this.cssScale;\n }\n\n /** Resize the page boxes to the current `cssScale` (no re-raster). */\n private applyScale(scale: number) {\n this.cssScale = Math.min(Math.max(0.08, scale), 8);\n for (let p = 1; p <= this.count; p++) {\n const box = this.pageEls[p];\n const size = this.sizes[p];\n if (box && size) box.style.width = `${(size.w / this.renderScale) * this.cssScale}px`;\n }\n this.updateZoomReadout();\n this.onZoomChange();\n }\n\n /** Set an explicit zoom multiplier (cancels any auto-fit mode). */\n setZoom(scale: number) {\n this.fitMode = \"none\";\n this.applyScale(scale);\n }\n /** Set zoom as a percentage (e.g. `125`). */\n setZoomPercent(pct: number) {\n this.setZoom(pct / 100);\n }\n /** Reset to 100 % (actual size). */\n actualSize() {\n this.setZoom(1);\n }\n zoomIn() {\n this.setZoom(this.cssScale * 1.2);\n }\n zoomOut() {\n this.setZoom(this.cssScale / 1.2);\n }\n /** Fit the current page's **width** to the viewport (sticks across resizes). */\n fitWidth() {\n this.fitMode = \"width\";\n this.applyFitMode();\n }\n /** Fit the **whole** current page (width *and* height) to the viewport. */\n fitPage() {\n this.fitMode = \"page\";\n this.applyFitMode();\n }\n /** Recompute the zoom for the active fit mode against the current page. */\n protected applyFitMode() {\n if (this.fitMode === \"none\" || this.presenting || this.count === 0) return;\n const size = this.sizes[this.current];\n if (!size) return;\n const wPt = size.w / this.renderScale;\n const hPt = size.h / this.renderScale;\n if (this.fitMode === \"width\") {\n this.applyScale((this.pages.clientWidth - 36) / wPt || 1);\n } else {\n const availW = this.pages.clientWidth - 36;\n const availH = this.pages.clientHeight - 36;\n this.applyScale(Math.min(availW / wPt, availH / hPt) || 1);\n }\n }\n\n /** Hook for subclasses (the editor) to react to zoom changes. */\n protected onZoomChange() {}\n\n private updateZoomReadout() {\n if (this.zoomReadout) this.zoomReadout.textContent = `${Math.round(this.cssScale * 100)}%`;\n if (this.zoomSelect) {\n const v =\n this.fitMode === \"width\" ? \"width\" : this.fitMode === \"page\" ? \"page\" : String(this.cssScale);\n const has = Array.from(this.zoomSelect.options).some((o) => o.value === v);\n this.zoomSelect.value = has ? v : \"\";\n }\n }\n\n // ── presentation (fullscreen slideshow) ───────────────────────────────────────\n /** Enter fullscreen single-page presentation mode. */\n present() {\n this.presenting = true;\n this.root.classList.add(\"gpv-present\");\n this.goTo(this.current);\n void this.root.requestFullscreen?.();\n }\n /** Leave presentation mode. */\n exitPresent() {\n this.presenting = false;\n this.root.classList.remove(\"gpv-present\");\n if (this.root.ownerDocument.fullscreenElement) void this.root.ownerDocument.exitFullscreen?.();\n for (let p = 1; p <= this.count; p++) {\n const el = this.pageEls[p];\n if (el) el.style.display = \"\";\n }\n this.goTo(this.current);\n }\n private syncPresentClass() {\n // The user pressed Esc / left fullscreen via the browser chrome.\n if (this.presenting && !this.root.ownerDocument.fullscreenElement) this.exitPresent();\n }\n\n // ── keyboard ─────────────────────────────────────────────────────────────────\n private handleKey(e: KeyboardEvent) {\n if (!this.isActive()) return;\n switch (e.key) {\n case \"ArrowRight\":\n case \"PageDown\":\n case \" \":\n this.next();\n break;\n case \"ArrowLeft\":\n case \"PageUp\":\n this.prev();\n break;\n case \"Home\":\n this.goTo(1);\n break;\n case \"End\":\n this.goTo(this.count);\n break;\n case \"+\":\n case \"=\":\n this.zoomIn();\n break;\n case \"-\":\n this.zoomOut();\n break;\n case \"0\":\n this.actualSize();\n break;\n case \"f\":\n case \"F\":\n this.presenting ? this.exitPresent() : this.present();\n break;\n case \"Escape\":\n if (this.presenting) this.exitPresent();\n break;\n default:\n return;\n }\n e.preventDefault();\n }\n private isActive(): boolean {\n return this.presenting || this.root.contains(this.root.ownerDocument.activeElement) || this.root.matches(\":hover\");\n }\n\n // ── chrome ───────────────────────────────────────────────────────────────────\n private buildChrome() {\n const d = this.root.ownerDocument;\n this.root.classList.add(\"gpv\");\n if (this.options.background) this.root.style.setProperty(\"--gpv-bg\", this.options.background);\n this.root.replaceChildren();\n\n if (this.options.toolbar !== false) {\n const bar = d.createElement(\"div\");\n bar.className = \"gpv-bar\";\n const btn = (label: string, fn: () => void, title?: string) => {\n const b = d.createElement(\"button\");\n b.textContent = label;\n if (title) b.title = title;\n b.addEventListener(\"click\", fn);\n bar.appendChild(b);\n return b;\n };\n btn(\"‹\", () => this.prev(), \"Previous page\");\n btn(\"›\", () => this.next(), \"Next page\");\n const input = d.createElement(\"input\");\n input.value = \"1\";\n input.addEventListener(\"change\", () => this.goTo(Number(input.value) || 1));\n bar.appendChild(input);\n this.pageInput = input;\n btn(\"−\", () => this.zoomOut(), \"Zoom out\");\n const zr = d.createElement(\"span\");\n zr.className = \"gpv-zoom\";\n zr.textContent = \"100%\";\n bar.appendChild(zr);\n this.zoomReadout = zr;\n btn(\"+\", () => this.zoomIn(), \"Zoom in\");\n const zsel = d.createElement(\"select\");\n zsel.title = \"Zoom level\";\n const zopts: [string, string][] = [\n [\"width\", \"Fit width\"],\n [\"page\", \"Fit page\"],\n [\"0.5\", \"50%\"],\n [\"0.75\", \"75%\"],\n [\"1\", \"100%\"],\n [\"1.25\", \"125%\"],\n [\"1.5\", \"150%\"],\n [\"2\", \"200%\"],\n [\"4\", \"400%\"],\n ];\n for (const [val, label] of zopts) {\n const o = d.createElement(\"option\");\n o.value = val;\n o.textContent = label;\n zsel.appendChild(o);\n }\n zsel.value = \"1\";\n zsel.addEventListener(\"change\", () => {\n const v = zsel.value;\n if (v === \"width\") this.fitWidth();\n else if (v === \"page\") this.fitPage();\n else if (v) this.setZoom(Number(v));\n });\n bar.appendChild(zsel);\n this.zoomSelect = zsel;\n const sp = d.createElement(\"div\");\n sp.className = \"gpv-sp\";\n bar.appendChild(sp);\n btn(\"⛶ Present\", () => this.present(), \"Fullscreen presentation (F)\");\n this.root.appendChild(bar);\n this.bar = bar;\n }\n\n this.body = d.createElement(\"div\");\n this.body.className = \"gpv-body\";\n this.thumbs = d.createElement(\"div\");\n this.thumbs.className = \"gpv-thumbs\";\n if (this.options.thumbnails === false) this.thumbs.style.display = \"none\";\n this.pages = d.createElement(\"div\");\n this.pages.className = \"gpv-pages\";\n // Track which page is centred while scrolling (continuous mode).\n this.pages.addEventListener(\"scroll\", () => this.trackScroll());\n this.body.append(this.thumbs, this.pages);\n this.root.appendChild(this.body);\n\n // Re-apply the active fit mode when the viewport resizes.\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObs = new ResizeObserver(() => this.applyFitMode());\n this.resizeObs.observe(this.pages);\n }\n // Ctrl/⌘ + wheel zooms (like every PDF viewer).\n this.pages.addEventListener(\n \"wheel\",\n (e) => {\n if (!e.ctrlKey && !e.metaKey) return;\n e.preventDefault();\n this.setZoom(this.cssScale * (e.deltaY < 0 ? 1.1 : 1 / 1.1));\n },\n { passive: false }\n );\n }\n\n private trackScroll() {\n if (this.presenting || this.count === 0) return;\n const mid = this.pages.scrollTop + this.pages.clientHeight / 2;\n let best = this.current;\n for (let p = 1; p <= this.count; p++) {\n const el = this.pageEls[p];\n if (el && el.offsetTop <= mid) best = p;\n }\n if (best !== this.current) {\n this.current = best;\n if (this.pageInput) this.pageInput.value = String(best);\n if (this.fitMode !== \"none\") this.applyFitMode();\n this.highlightThumb();\n }\n }\n\n // ── lifecycle ────────────────────────────────────────────────────────────────\n /** Close the current document and free its rendered pages. */\n close() {\n for (const u of this.urls) if (u) URL.revokeObjectURL(u);\n this.urls = [];\n this.sizes = [];\n this.pageEls = [];\n this.doc?.close();\n this.doc = null;\n this.count = 0;\n this.pages?.replaceChildren();\n this.thumbs?.replaceChildren();\n }\n\n /** Destroy the viewer: close the document and detach listeners. */\n destroy() {\n this.close();\n this.resizeObs?.disconnect();\n this.resizeObs = null;\n this.root.ownerDocument.removeEventListener(\"keydown\", this.onKey);\n this.root.ownerDocument.removeEventListener(\"fullscreenchange\", this.onFsChange);\n this.root.classList.remove(\"gpv\", \"gpv-present\");\n this.root.replaceChildren();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,96 @@
1
+ import { GigaPdfEngine } from './index.cjs';
2
+ import { ViewerOptions, GigaPdfViewer } from './viewer.cjs';
3
+
4
+ /**
5
+ * `@qrcommunication/gigapdf-lib/editor` — an interactive **editing canvas** that
6
+ * extends {@link GigaPdfViewer}. It overlays each rendered page with an SVG
7
+ * surface for drawing/placing annotations and shapes (rectangle, ellipse, line,
8
+ * freehand ink, text, image, highlight, redaction), supports select / move /
9
+ * delete, and **bakes the edits into the real PDF** through the engine
10
+ * (`addRectangle`/`addEllipse`/`addPolygon`/`addText`/`addImage`/`redact`) — then
11
+ * re-renders. Zero external libraries; browser-only.
12
+ *
13
+ * ```ts
14
+ * const ed = new GigaPdfEditor(giga, host, { defaultFont: { family: "Roboto", ttf } });
15
+ * await ed.open({ kind: "auto", bytes });
16
+ * ed.setTool("rect"); ed.setStyle({ color: 0xcc0000 });
17
+ * // …user draws…
18
+ * ed.applyEdits(); // bake into the PDF
19
+ * const pdf = ed.save(); // download the result
20
+ * ```
21
+ */
22
+
23
+ /** A page edge that carries an adjustable margin. */
24
+ type Side = "top" | "right" | "bottom" | "left";
25
+ type EditTool = "select" | "text" | "rect" | "ellipse" | "line" | "ink" | "image" | "highlight" | "redact";
26
+ interface EditStyle {
27
+ /** Stroke (shapes / ink / line) and text colour, `0xRRGGBB`. */
28
+ color: number;
29
+ /** Shape fill colour, or `null` for no fill. */
30
+ fill: number | null;
31
+ lineWidth: number;
32
+ fontSize: number;
33
+ /** 0–1 fill/stroke alpha. */
34
+ opacity: number;
35
+ }
36
+ interface EditorOptions extends ViewerOptions {
37
+ /** A TrueType font for the text tool (required to add text). */
38
+ defaultFont?: {
39
+ family: string;
40
+ ttf: Uint8Array;
41
+ };
42
+ }
43
+ declare class GigaPdfEditor extends GigaPdfViewer {
44
+ private tool;
45
+ private style;
46
+ private els;
47
+ private overlays;
48
+ private idSeq;
49
+ private selected;
50
+ private fontObj;
51
+ private editorOpts;
52
+ private palette;
53
+ private margins;
54
+ private guides;
55
+ private showGuides;
56
+ private marginInputs;
57
+ constructor(engine: GigaPdfEngine, container: HTMLElement, opts?: EditorOptions);
58
+ setTool(tool: EditTool): void;
59
+ setStyle(patch: Partial<EditStyle>): void;
60
+ /** Edits drawn but not yet baked into the PDF. */
61
+ get pendingEdits(): number;
62
+ /** Delete the currently selected element. */
63
+ removeSelected(): void;
64
+ /** Discard all un-applied edits. */
65
+ clearEdits(): void;
66
+ /** Bake every pending edit into the PDF, then re-render the affected pages. */
67
+ applyEdits(): number;
68
+ private bake;
69
+ private ensureFont;
70
+ protected afterRender(): void;
71
+ /** Keep ruler ticks / handles a constant on-screen size as the zoom changes. */
72
+ protected onZoomChange(): void;
73
+ /** Set page margins (default unit: millimetres). */
74
+ setMargins(m: Partial<Record<Side, number>>, unit?: "mm" | "pt"): void;
75
+ /** Current margins in the requested unit (millimetres by default). */
76
+ getMargins(unit?: "mm" | "pt"): Record<Side, number>;
77
+ /** Show or hide the rulers and margin guides. */
78
+ showRulers(on: boolean): void;
79
+ private syncMarginInputs;
80
+ private redrawGuidesAll;
81
+ private redrawGuides;
82
+ private marginHandle;
83
+ private dragMargin;
84
+ private toPagePt;
85
+ private bindOverlay;
86
+ private isMeaningful;
87
+ private hitTest;
88
+ private placeText;
89
+ private placeImage;
90
+ private redrawAll;
91
+ private redraw;
92
+ private elNode;
93
+ private buildPalette;
94
+ }
95
+
96
+ export { type EditStyle, type EditTool, type EditorOptions, GigaPdfEditor };
@@ -0,0 +1,96 @@
1
+ import { GigaPdfEngine } from './index.js';
2
+ import { ViewerOptions, GigaPdfViewer } from './viewer.js';
3
+
4
+ /**
5
+ * `@qrcommunication/gigapdf-lib/editor` — an interactive **editing canvas** that
6
+ * extends {@link GigaPdfViewer}. It overlays each rendered page with an SVG
7
+ * surface for drawing/placing annotations and shapes (rectangle, ellipse, line,
8
+ * freehand ink, text, image, highlight, redaction), supports select / move /
9
+ * delete, and **bakes the edits into the real PDF** through the engine
10
+ * (`addRectangle`/`addEllipse`/`addPolygon`/`addText`/`addImage`/`redact`) — then
11
+ * re-renders. Zero external libraries; browser-only.
12
+ *
13
+ * ```ts
14
+ * const ed = new GigaPdfEditor(giga, host, { defaultFont: { family: "Roboto", ttf } });
15
+ * await ed.open({ kind: "auto", bytes });
16
+ * ed.setTool("rect"); ed.setStyle({ color: 0xcc0000 });
17
+ * // …user draws…
18
+ * ed.applyEdits(); // bake into the PDF
19
+ * const pdf = ed.save(); // download the result
20
+ * ```
21
+ */
22
+
23
+ /** A page edge that carries an adjustable margin. */
24
+ type Side = "top" | "right" | "bottom" | "left";
25
+ type EditTool = "select" | "text" | "rect" | "ellipse" | "line" | "ink" | "image" | "highlight" | "redact";
26
+ interface EditStyle {
27
+ /** Stroke (shapes / ink / line) and text colour, `0xRRGGBB`. */
28
+ color: number;
29
+ /** Shape fill colour, or `null` for no fill. */
30
+ fill: number | null;
31
+ lineWidth: number;
32
+ fontSize: number;
33
+ /** 0–1 fill/stroke alpha. */
34
+ opacity: number;
35
+ }
36
+ interface EditorOptions extends ViewerOptions {
37
+ /** A TrueType font for the text tool (required to add text). */
38
+ defaultFont?: {
39
+ family: string;
40
+ ttf: Uint8Array;
41
+ };
42
+ }
43
+ declare class GigaPdfEditor extends GigaPdfViewer {
44
+ private tool;
45
+ private style;
46
+ private els;
47
+ private overlays;
48
+ private idSeq;
49
+ private selected;
50
+ private fontObj;
51
+ private editorOpts;
52
+ private palette;
53
+ private margins;
54
+ private guides;
55
+ private showGuides;
56
+ private marginInputs;
57
+ constructor(engine: GigaPdfEngine, container: HTMLElement, opts?: EditorOptions);
58
+ setTool(tool: EditTool): void;
59
+ setStyle(patch: Partial<EditStyle>): void;
60
+ /** Edits drawn but not yet baked into the PDF. */
61
+ get pendingEdits(): number;
62
+ /** Delete the currently selected element. */
63
+ removeSelected(): void;
64
+ /** Discard all un-applied edits. */
65
+ clearEdits(): void;
66
+ /** Bake every pending edit into the PDF, then re-render the affected pages. */
67
+ applyEdits(): number;
68
+ private bake;
69
+ private ensureFont;
70
+ protected afterRender(): void;
71
+ /** Keep ruler ticks / handles a constant on-screen size as the zoom changes. */
72
+ protected onZoomChange(): void;
73
+ /** Set page margins (default unit: millimetres). */
74
+ setMargins(m: Partial<Record<Side, number>>, unit?: "mm" | "pt"): void;
75
+ /** Current margins in the requested unit (millimetres by default). */
76
+ getMargins(unit?: "mm" | "pt"): Record<Side, number>;
77
+ /** Show or hide the rulers and margin guides. */
78
+ showRulers(on: boolean): void;
79
+ private syncMarginInputs;
80
+ private redrawGuidesAll;
81
+ private redrawGuides;
82
+ private marginHandle;
83
+ private dragMargin;
84
+ private toPagePt;
85
+ private bindOverlay;
86
+ private isMeaningful;
87
+ private hitTest;
88
+ private placeText;
89
+ private placeImage;
90
+ private redrawAll;
91
+ private redraw;
92
+ private elNode;
93
+ private buildPalette;
94
+ }
95
+
96
+ export { type EditStyle, type EditTool, type EditorOptions, GigaPdfEditor };