@inkbar/core 0.1.1 → 0.3.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.
- package/LICENSE +0 -49
- package/README.md +37 -9
- package/dist/{document-Cywnv8Sz.d.mts → document-BftlPZKU.d.mts} +343 -71
- package/dist/document-BftlPZKU.d.mts.map +1 -0
- package/dist/dom.d.mts +48 -5
- package/dist/dom.d.mts.map +1 -1
- package/dist/dom.mjs +339 -339
- package/dist/dom.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/{threads-BtvtrAhL.mjs → threads-2USvyGpX.mjs} +70 -47
- package/dist/threads-2USvyGpX.mjs.map +1 -0
- package/package.json +2 -1
- package/schema.json +122 -91
- package/dist/document-Cywnv8Sz.d.mts.map +0 -1
- package/dist/threads-BtvtrAhL.mjs.map +0 -1
package/dist/dom.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.mjs","names":["SVG","createToolController","createWith"],"sources":["../src/dom/transform.ts","../src/dom/layout.ts","../src/dom/viewport.ts","../src/dom/viewport-keys.ts","../src/dom/page-renderer.ts","../src/pdfjs/text-layer.ts","../src/dom/text-layer.ts","../src/dom/selection.ts","../src/model/annotations/edit.ts","../src/dom/overlay-render.ts","../src/dom/overlay.ts","../src/dom/page-mount.ts","../src/dom/tools/controller.ts","../src/dom/tools/highlight.ts","../src/dom/tools/note.ts","../src/dom/tools/redact-area.ts","../src/dom/tools/select.ts","../src/dom/tools/view.ts","../src/dom/tools/index.ts","../src/dom/ui.ts","../src/dom/annotation-element.ts","../src/dom/popover-focus.ts","../src/dom/viewer-engine.ts","../src/dom/viewer/dom.ts","../src/dom/viewer/popover.ts","../src/dom/viewer/note-popover.ts","../src/dom/viewer/suggestion-card.ts","../src/dom/viewer/icons.ts","../src/dom/viewer/toolbar.ts","../src/dom/viewer/create-viewer.ts"],"sourcesContent":["import {\n applyMatrix,\n invertMatrix,\n type Matrix,\n type Point,\n type Quad,\n type Rect,\n} from '../model/geometry'\n\nimport type { PageInfo } from '../model/pages'\n\nexport type ViewRotation = 0 | 90 | 180 | 270\n\n/** CSS box: `left`,`top` from the rendered page's top-left corner, in CSS pixels. */\nexport interface CssRect {\n left: number\n top: number\n width: number\n height: number\n}\n\nexport interface PageTransform {\n readonly page: PageInfo\n /** The viewer zoom the transform was built for. 1 is one CSS pixel per user-space unit at /UserUnit 1. */\n readonly zoom: number\n /**\n * CSS pixels per user-space unit: `zoom × page.userUnit`. This is PDF.js `PageViewport.scale`\n * and the value its text and annotation layers read from `--total-scale-factor`.\n */\n readonly scale: number\n /** Rotation the viewer applied on top of the page's own /Rotate. */\n readonly rotation: ViewRotation\n /** The page's /Rotate plus the viewer rotation. */\n readonly totalRotation: ViewRotation\n /** Rendered page width in CSS pixels at this zoom and total rotation. */\n readonly cssWidth: number\n /** Rendered page height in CSS pixels at this zoom and total rotation. */\n readonly cssHeight: number\n /** User space to CSS pixels. Same matrix PDF.js builds for `getViewport`. */\n readonly matrix: Matrix\n toCss(p: Point): Point\n toCssRect(r: Rect): CssRect\n toCssQuad(q: Quad): Quad\n /** Converts a length in user-space units (stroke width, font size) to CSS pixels: zoom times `/UserUnit`. */\n toCssLength(points: number): number\n fromCss(p: Point): Point\n fromCssRect(r: CssRect): Rect\n /** Converts a length in CSS pixels to user-space units. */\n fromCssLength(px: number): number\n}\n\n/** Folds any integer multiple of 90 onto 0, 90, 180 or 270. Throws `RangeError` otherwise. */\nexport function normalizeRotation(deg: number): ViewRotation {\n if (!Number.isFinite(deg) || deg % 90 !== 0) {\n throw new RangeError(`rotation must be a multiple of 90, got ${deg}`)\n }\n return (((deg % 360) + 360) % 360) as ViewRotation\n}\n\n/**\n * Port of PDF.js `PageViewport` (display/page_viewport.js) with offsetX = offsetY = 0 and\n * dontFlip = false. Using the same maths keeps the canvas, text layer and overlay aligned.\n */\nexport function createPageTransform(\n page: PageInfo,\n zoom: number,\n viewRotation: ViewRotation = 0\n): PageTransform {\n const rotation = normalizeRotation(viewRotation)\n const totalRotation = normalizeRotation(page.rotate + rotation)\n // PDF.js PageViewport does `scale *= userUnit`; zoom 1 is one user-space unit, so 1 point only when userUnit is 1.\n const scale = zoom * page.userUnit\n const x0 = page.box.x\n const y0 = page.box.y\n const x1 = page.box.x + page.box.width\n const y1 = page.box.y + page.box.height\n const centerX = (x1 + x0) / 2\n const centerY = (y1 + y0) / 2\n let rotateA: number\n let rotateB: number\n let rotateC: number\n let rotateD: number\n switch (totalRotation) {\n case 180:\n rotateA = -1\n rotateB = 0\n rotateC = 0\n rotateD = 1\n break\n case 90:\n rotateA = 0\n rotateB = 1\n rotateC = 1\n rotateD = 0\n break\n case 270:\n rotateA = 0\n rotateB = -1\n rotateC = -1\n rotateD = 0\n break\n default:\n rotateA = 1\n rotateB = 0\n rotateC = 0\n rotateD = -1\n }\n let offsetCanvasX: number\n let offsetCanvasY: number\n let cssWidth: number\n let cssHeight: number\n if (rotateA === 0) {\n offsetCanvasX = Math.abs(centerY - y0) * scale\n offsetCanvasY = Math.abs(centerX - x0) * scale\n cssWidth = Math.abs(y1 - y0) * scale\n cssHeight = Math.abs(x1 - x0) * scale\n } else {\n offsetCanvasX = Math.abs(centerX - x0) * scale\n offsetCanvasY = Math.abs(centerY - y0) * scale\n cssWidth = Math.abs(x1 - x0) * scale\n cssHeight = Math.abs(y1 - y0) * scale\n }\n const matrix: Matrix = [\n rotateA * scale,\n rotateB * scale,\n rotateC * scale,\n rotateD * scale,\n offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,\n offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY,\n ]\n const inverse = invertMatrix(matrix)\n const toCss = (p: Point): Point => applyMatrix(matrix, p)\n const fromCss = (p: Point): Point => applyMatrix(inverse, p)\n\n const bounds = (\n points: Point[]\n ): { x: number; y: number; width: number; height: number } => {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y }\n }\n\n return {\n page,\n zoom,\n scale,\n rotation,\n totalRotation,\n cssWidth,\n cssHeight,\n matrix,\n toCss,\n fromCss,\n toCssRect(r) {\n const b = bounds([\n toCss({ x: r.x, y: r.y }),\n toCss({ x: r.x + r.width, y: r.y }),\n toCss({ x: r.x, y: r.y + r.height }),\n toCss({ x: r.x + r.width, y: r.y + r.height }),\n ])\n return { left: b.x, top: b.y, width: b.width, height: b.height }\n },\n toCssQuad(q) {\n return { p1: toCss(q.p1), p2: toCss(q.p2), p3: toCss(q.p3), p4: toCss(q.p4) }\n },\n toCssLength: (points) => points * scale,\n fromCssRect(r) {\n return bounds([\n fromCss({ x: r.left, y: r.top }),\n fromCss({ x: r.left + r.width, y: r.top }),\n fromCss({ x: r.left, y: r.top + r.height }),\n fromCss({ x: r.left + r.width, y: r.top + r.height }),\n ])\n },\n fromCssLength: (px) => px / scale,\n }\n}\n","import { createPageTransform, type ViewRotation } from './transform'\n\nimport type { PageInfo } from '../model/pages'\n\nexport type LayoutMode = 'single' | 'continuous'\n\n/** Where one page sits inside the pages element, in CSS pixels. */\nexport interface CssPageBox {\n index: number\n left: number\n top: number\n width: number\n height: number\n}\n\n/** Every laid-out page plus the size of the pages element, in CSS pixels. */\nexport interface CssLayout {\n boxes: CssPageBox[]\n width: number\n height: number\n}\n\nexport interface CssLayoutInput {\n pages: readonly PageInfo[]\n zoom: number\n rotation: ViewRotation\n /** Gap above, between and below pages, CSS px. */\n gap: number\n mode: LayoutMode\n /** The page shown in `single` mode. */\n current: number\n /** The container's content width (client width less padding), CSS px. Narrower pages are centred. */\n containerWidth: number\n}\n\nfunction cssSize(page: PageInfo, zoom: number, rotation: ViewRotation) {\n const t = createPageTransform(page, zoom, rotation)\n return { width: t.cssWidth, height: t.cssHeight }\n}\n\n/** Stacks pages vertically, centred horizontally, with `gap` around each. */\nexport function computeCssLayout(input: CssLayoutInput): CssLayout {\n const pages =\n input.mode === 'single'\n ? input.pages.filter((p) => p.index === input.current)\n : input.pages\n const sizes = pages.map((p) => cssSize(p, input.zoom, input.rotation))\n // A reduce, not Math.max(...spread): spreading hundreds of thousands of pages overflows the stack.\n const width = sizes.reduce((max, s) => Math.max(max, s.width), input.containerWidth)\n let top = input.gap\n const boxes = pages.map((p, i): CssPageBox => {\n const s = sizes[i]!\n const box = {\n index: p.index,\n left: (width - s.width) / 2,\n top,\n width: s.width,\n height: s.height,\n }\n top += s.height + input.gap\n return box\n })\n return { boxes, width, height: top }\n}\n\n/** The zoom at which `page` fits a container of the given CSS size, less `padding` on each side. */\nexport function fitZoomCss(\n page: PageInfo,\n rotation: ViewRotation,\n container: { width: number; height: number },\n mode: 'fit-width' | 'fit-page',\n padding: number\n): number {\n const size = cssSize(page, 1, rotation)\n const byWidth = (container.width - padding * 2) / size.width\n if (mode === 'fit-width') return Math.max(0.05, byWidth)\n const byHeight = (container.height - padding * 2) / size.height\n return Math.max(0.05, Math.min(byWidth, byHeight))\n}\n\n/**\n * Indexes of pages intersecting [scrollTop, scrollTop + viewportHeight], extended by\n * `buffer` pages each side. Past the end it returns the last page plus its buffer.\n */\nexport function visibleRangeCss(\n layout: CssLayout,\n scrollTop: number,\n viewportHeight: number,\n buffer: number\n): number[] {\n const boxes = layout.boxes\n if (boxes.length === 0) return []\n const bottom = scrollTop + viewportHeight\n let first = boxes.findIndex((b) => b.top + b.height >= scrollTop)\n if (first === -1) first = boxes.length - 1\n let last = first\n while (last + 1 < boxes.length && boxes[last + 1]!.top <= bottom) last++\n const from = Math.max(0, first - buffer)\n const to = Math.min(boxes.length - 1, last + buffer)\n return boxes.slice(from, to + 1).map((b) => b.index)\n}\n\n/** The page with the most visible height in the viewport; the first page on a tie. */\nexport function mostVisiblePageCss(\n layout: CssLayout,\n scrollTop: number,\n viewportHeight: number\n): number {\n let best = layout.boxes[0]?.index ?? 0\n let bestArea = -1\n const bottom = scrollTop + viewportHeight\n for (const b of layout.boxes) {\n const visible = Math.max(\n 0,\n Math.min(b.top + b.height, bottom) - Math.max(b.top, scrollTop)\n )\n if (visible > bestArea) {\n bestArea = visible\n best = b.index\n }\n }\n return best\n}\n","/*\n * Inline styles. The headless DOM layer sets only what it cannot work without:\n * - container: `overflow: auto`, and `position: relative` when its computed position is static;\n * - pages element: `position: relative`, plus `width`/`height` from the layout;\n * - page hosts: `position: absolute` and `left`/`top`/`width`/`height` from the layout;\n * - page hosts: the `--scale-factor` (zoom) and `--total-scale-factor` (zoom × /UserUnit)\n * custom properties.\n * Nothing cosmetic (colours, borders, backgrounds, fonts) is ever set inline; that belongs to\n * the stylesheet. `destroy()` restores the container's overflow and position.\n */\nimport { readonly, writable, type Readable } from '../model/readable'\n\nimport {\n computeCssLayout,\n fitZoomCss,\n mostVisiblePageCss,\n visibleRangeCss,\n type CssLayout,\n type CssPageBox,\n type LayoutMode,\n} from './layout'\nimport { createPageTransform, type PageTransform, type ViewRotation } from './transform'\n\nimport type { InkDocument } from '../model/document'\nimport type { Point, Rect } from '../model/geometry'\n\nexport type ZoomValue = number | 'fit-width' | 'fit-page'\n\nexport interface ViewportOptions {\n container: HTMLElement\n document: InkDocument\n /** Default `'fit-width'`. */\n zoom?: ZoomValue\n /** Default `'continuous'`. */\n mode?: LayoutMode\n /** Default 0. */\n rotation?: ViewRotation\n /** Gap between pages, and the page padding used by fit modes, CSS px. Default 16. */\n gap?: number\n /** Pages to keep mounted either side of the visible range. Default 2. */\n buffer?: number\n /** Default 0.1. */\n minZoom?: number\n /** Default 8. */\n maxZoom?: number\n onMount(page: number, host: HTMLElement, transform: PageTransform): void\n onUpdate(page: number, host: HTMLElement, transform: PageTransform): void\n onUnmount(page: number, host: HTMLElement): void\n}\n\n/** The mounted page under a client point. The tools layer adds `user` and `css` (`PageHit`). */\nexport interface ViewportHit {\n page: number\n host: HTMLElement\n transform: PageTransform\n}\n\nexport interface Viewport {\n readonly zoom: Readable<ZoomValue>\n /** Effective numeric zoom, with fit modes resolved. */\n readonly scale: Readable<number>\n readonly currentPage: Readable<number>\n readonly mounted: Readable<readonly number[]>\n readonly layout: Readable<CssLayout>\n readonly rotation: Readable<ViewRotation>\n readonly mode: Readable<LayoutMode>\n /** `anchorCss` is relative to the container's top-left inside its border, CSS px; defaults to its centre. */\n setZoom(zoom: ZoomValue, anchorCss?: Point): void\n zoomBy(factor: number, anchorCss?: Point): void\n setMode(mode: LayoutMode): void\n setRotation(rotation: ViewRotation): void\n scrollToPage(index: number, opts?: { behavior?: ScrollBehavior }): void\n /** Scrolls so `rect` (user space on `page`) is visible, centring it when it was not. */\n scrollToRect(page: number, rect: Rect): void\n transformFor(page: number): PageTransform\n hostFor(page: number): HTMLElement | undefined\n /** The mounted page under a viewport (client) point, if any. */\n pageAtCss(clientX: number, clientY: number): ViewportHit | undefined\n destroy(): void\n}\n\nfunction sameList(a: readonly number[], b: readonly number[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i])\n}\n\nexport function createViewport(opts: ViewportOptions): Viewport {\n const { container, document: doc } = opts\n const gap = opts.gap ?? 16\n const buffer = opts.buffer ?? 2\n const minZoom = opts.minZoom ?? 0.1\n const maxZoom = opts.maxZoom ?? 8\n const clamp = (z: number): number => Math.min(maxZoom, Math.max(minZoom, z))\n\n const zoom = writable<ZoomValue>(\n typeof opts.zoom === 'number' ? clamp(opts.zoom) : (opts.zoom ?? 'fit-width')\n )\n const scale = writable(1)\n const rotation = writable<ViewRotation>(opts.rotation ?? 0)\n const mode = writable<LayoutMode>(opts.mode ?? 'continuous')\n const currentPage = writable(0)\n const mounted = writable<readonly number[]>([])\n const layout = writable<CssLayout>({ boxes: [], width: 0, height: 0 })\n\n const previousStyle = {\n overflow: container.style.overflow,\n position: container.style.position,\n }\n container.dataset.inkViewport = ''\n container.style.overflow = 'auto'\n if (getComputedStyle(container).position === 'static')\n container.style.position = 'relative'\n\n const pagesEl = container.ownerDocument.createElement('div')\n pagesEl.className = 'ink-pages'\n pagesEl.dataset.inkPages = ''\n pagesEl.style.position = 'relative'\n container.append(pagesEl)\n\n const hosts = new Map<number, HTMLElement>()\n const transforms = new Map<number, PageTransform>()\n let lastSize = { width: -1, height: -1 }\n let destroyed = false\n\n function boxFor(page: number, l = layout.get()): CssPageBox | undefined {\n return l.boxes.find((b) => b.index === page)\n }\n\n /** Where the pages element starts inside the container's scrollable content (its padding). */\n function origin(): Point {\n return { x: pagesEl.offsetLeft, y: pagesEl.offsetTop }\n }\n\n /** The container's content box, CSS px: client size less padding. The pages element sits inside it. */\n function innerSize(): { width: number; height: number } {\n const cs = getComputedStyle(container)\n const px = (v: string): number => Number.parseFloat(v) || 0\n return {\n width: container.clientWidth - px(cs.paddingLeft) - px(cs.paddingRight),\n height: container.clientHeight - px(cs.paddingTop) - px(cs.paddingBottom),\n }\n }\n\n function resolveScale(): number {\n const z = zoom.get()\n if (typeof z === 'number') return clamp(z)\n const page = doc.pages[currentPage.get()] ?? doc.pages[0]\n if (!page) return 1\n return clamp(fitZoomCss(page, rotation.get(), innerSize(), z, gap))\n }\n\n function transformFor(page: number): PageTransform {\n let t = transforms.get(page)\n if (!t) {\n const info = doc.pages[page]\n if (!info) throw new RangeError(`page ${page} out of range`)\n t = createPageTransform(info, scale.get(), rotation.get())\n transforms.set(page, t)\n }\n return t\n }\n\n function layoutOnce(): void {\n scale.set(resolveScale())\n transforms.clear()\n const l = computeCssLayout({\n pages: doc.pages,\n zoom: scale.get(),\n rotation: rotation.get(),\n gap,\n mode: mode.get(),\n current: currentPage.get(),\n containerWidth: innerSize().width,\n })\n pagesEl.style.width = `${l.width}px`\n pagesEl.style.height = `${l.height}px`\n layout.set(l)\n }\n\n /**\n * Recomputes the layout. Sizing the pages element can add or remove a scrollbar, which\n * changes the client width the layout (and a fit zoom) was based on, so it runs again\n * once when that happens.\n */\n function relayout(): void {\n const width = container.clientWidth\n layoutOnce()\n if (container.clientWidth !== width) layoutOnce()\n lastSize = { width: container.clientWidth, height: container.clientHeight }\n const l = layout.get()\n for (const [page, host] of hosts) {\n if (!boxFor(page, l)) continue\n place(page, host, l)\n opts.onUpdate(page, host, transformFor(page))\n }\n sync()\n }\n\n function place(page: number, host: HTMLElement, l: CssLayout): void {\n const box = boxFor(page, l)\n if (!box) return\n const t = transformFor(page)\n host.style.left = `${box.left}px`\n host.style.top = `${box.top}px`\n host.style.width = `${t.cssWidth}px`\n host.style.height = `${t.cssHeight}px`\n // As in PDF.js's viewer: --scale-factor is the zoom, --total-scale-factor also folds in\n // /UserUnit (pdf_viewer.css: calc(var(--scale-factor) * var(--user-unit))).\n host.style.setProperty('--scale-factor', String(t.zoom))\n host.style.setProperty('--total-scale-factor', String(t.scale))\n host.dataset.rotation = String(t.totalRotation)\n }\n\n /** Mounts and unmounts hosts for the scroll position, and updates the current page. */\n function sync(): void {\n if (destroyed) return\n const l = layout.get()\n const top = container.scrollTop - origin().y\n const wanted = visibleRangeCss(l, top, container.clientHeight, buffer)\n const wantedSet = new Set(wanted)\n for (const [page, host] of [...hosts]) {\n if (wantedSet.has(page)) continue\n hosts.delete(page)\n opts.onUnmount(page, host)\n host.remove()\n }\n for (const page of wanted) {\n if (hosts.has(page)) continue\n const host = container.ownerDocument.createElement('div')\n host.className = 'ink-page'\n host.dataset.page = String(page)\n host.style.position = 'absolute'\n place(page, host, l)\n hosts.set(page, host)\n pagesEl.append(host)\n opts.onMount(page, host, transformFor(page))\n }\n if (!sameList(mounted.get(), wanted)) mounted.set(wanted)\n if (mode.get() === 'continuous') {\n currentPage.set(mostVisiblePageCss(l, top, container.clientHeight))\n }\n }\n\n let scrollFrame = 0\n const onScroll = (): void => {\n if (scrollFrame) return\n scrollFrame = requestAnimationFrame(() => {\n scrollFrame = 0\n sync()\n })\n }\n container.addEventListener('scroll', onScroll, { passive: true })\n\n const ro = new ResizeObserver(() => {\n if (destroyed) return\n if (\n container.clientWidth === lastSize.width &&\n container.clientHeight === lastSize.height\n ) {\n return\n }\n withAnchor(undefined, () => undefined)\n })\n ro.observe(container)\n\n function pageAtCss(clientX: number, clientY: number): ViewportHit | undefined {\n for (const [page, host] of hosts) {\n const r = host.getBoundingClientRect()\n if (\n clientX >= r.left &&\n clientX <= r.right &&\n clientY >= r.top &&\n clientY <= r.bottom\n ) {\n return { page, host, transform: transformFor(page) }\n }\n }\n return undefined\n }\n\n /**\n * The page box an anchor at layout-space `y` belongs to: the one whose vertical span\n * contains it, otherwise the nearest one (an anchor in a gap or past either end).\n */\n function anchorBox(l: CssLayout, y: number): CssPageBox | undefined {\n let best: CssPageBox | undefined\n let bestDistance = Infinity\n for (const b of l.boxes) {\n const distance =\n y < b.top ? b.top - y : y > b.top + b.height ? y - b.top - b.height : 0\n if (distance < bestDistance) {\n best = b\n bestDistance = distance\n }\n }\n return best\n }\n\n /**\n * Keeps the user-space point under `anchorCss` still while `change` alters the layout.\n * The anchor is taken in layout space, so it holds in the margins and gaps too: there it\n * is extrapolated from the nearest page's transform, which is affine, so the point maps\n * back exactly. The browser may still clamp the scroll at the content edges.\n */\n function withAnchor(anchorCss: Point | undefined, change: () => void): void {\n const anchor = anchorCss ?? {\n x: container.clientWidth / 2,\n y: container.clientHeight / 2,\n }\n // Read everything from the old layout before relayout() clears the cached transforms.\n const o = origin()\n const x = container.scrollLeft + anchor.x - o.x\n const y = container.scrollTop + anchor.y - o.y\n const old = anchorBox(layout.get(), y)\n const user = old\n ? transformFor(old.index).fromCss({ x: x - old.left, y: y - old.top })\n : undefined\n change()\n relayout()\n if (!old || !user) return\n const box = boxFor(old.index)\n if (!box) return\n const after = transformFor(old.index).toCss(user)\n const o2 = origin()\n container.scrollLeft = o2.x + box.left + after.x - anchor.x\n container.scrollTop = o2.y + box.top + after.y - anchor.y\n sync()\n }\n\n const viewport: Viewport = {\n zoom: readonly(zoom),\n scale: readonly(scale),\n currentPage: readonly(currentPage),\n mounted: readonly(mounted),\n layout: readonly(layout),\n rotation: readonly(rotation),\n mode: readonly(mode),\n setZoom(z, anchorCss) {\n withAnchor(anchorCss, () => zoom.set(typeof z === 'number' ? clamp(z) : z))\n },\n zoomBy(factor, anchorCss) {\n viewport.setZoom(clamp(scale.get() * factor), anchorCss)\n },\n setMode(m) {\n if (m === mode.get()) return\n // Catch up with a scroll whose frame has not run yet, then keep that page: relayout()\n // re-derives the current page from the scroll position, which the new mode changes.\n if (mode.get() === 'continuous') sync()\n const page = currentPage.get()\n mode.set(m)\n relayout()\n viewport.scrollToPage(page)\n },\n setRotation(r) {\n withAnchor(undefined, () => rotation.set(r))\n },\n scrollToPage(index, o) {\n const page = Math.max(0, Math.min(doc.pages.length - 1, index))\n const behavior = o?.behavior ?? 'auto'\n if (mode.get() === 'single') {\n // Also relayout when the layout shows another page, even if currentPage already matches.\n if (page !== currentPage.get() || layout.get().boxes[0]?.index !== page) {\n currentPage.set(page)\n relayout()\n }\n container.scrollTo({ top: 0, behavior })\n sync()\n return\n }\n const box = boxFor(page)\n if (!box) return\n container.scrollTo({ top: Math.max(0, origin().y + box.top - gap), behavior })\n sync()\n },\n scrollToRect(page, rect) {\n if (mode.get() === 'single' && currentPage.get() !== page) {\n currentPage.set(page)\n relayout()\n }\n const box = boxFor(page)\n if (!box) return\n const css = transformFor(page).toCssRect(rect)\n const o = origin()\n const top = o.y + box.top + css.top\n if (\n top < container.scrollTop ||\n top + css.height > container.scrollTop + container.clientHeight\n ) {\n container.scrollTop = Math.max(0, top - (container.clientHeight - css.height) / 2)\n }\n const left = o.x + box.left + css.left\n if (\n left < container.scrollLeft ||\n left + css.width > container.scrollLeft + container.clientWidth\n ) {\n container.scrollLeft = Math.max(0, left - (container.clientWidth - css.width) / 2)\n }\n sync()\n },\n transformFor,\n hostFor: (page) => hosts.get(page),\n pageAtCss,\n destroy() {\n if (destroyed) return\n destroyed = true\n ro.disconnect()\n container.removeEventListener('scroll', onScroll)\n if (scrollFrame) cancelAnimationFrame(scrollFrame)\n for (const [page, host] of hosts) {\n opts.onUnmount(page, host)\n host.remove()\n }\n hosts.clear()\n transforms.clear()\n pagesEl.remove()\n delete container.dataset.inkViewport\n container.style.overflow = previousStyle.overflow\n container.style.position = previousStyle.position\n },\n }\n\n relayout()\n return viewport\n}\n","import type { Viewport } from './viewport'\n\nexport interface ViewportKeysOptions {\n viewport: Viewport\n /** Read on every key, so it follows the open document. */\n pageCount: () => number\n}\n\n/** Factor `+`/`=` zoom in by; `-` zooms out by its inverse. */\nconst ZOOM_STEP = 1.25\n\n/** Keys typed here belong to the element, not the viewport. */\nconst IGNORE =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [data-annotation]'\n\n/**\n * Keyboard shortcuts for a focused viewport container: `+` or `=` and `-` zoom, `Home` and\n * `End` go to the first and last page, `PageDown` and `PageUp` to the next and previous.\n * Events from inputs, editable content and annotation elements, chords with Ctrl, Meta or\n * Alt (browser zoom stays the browser's), and events already handled are left alone. Only\n * handled keys are prevented. Returns a function that removes the listener.\n */\nexport function attachViewportKeys(\n el: HTMLElement,\n opts: ViewportKeysOptions\n): () => void {\n const { viewport } = opts\n const onKeydown = (e: KeyboardEvent): void => {\n if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey) return\n if (e.target instanceof Element && e.target.closest(IGNORE)) return\n switch (e.key) {\n case '+':\n case '=':\n viewport.zoomBy(ZOOM_STEP)\n break\n case '-':\n viewport.zoomBy(1 / ZOOM_STEP)\n break\n case 'Home':\n viewport.scrollToPage(0)\n break\n case 'End':\n viewport.scrollToPage(opts.pageCount() - 1)\n break\n case 'PageDown':\n viewport.scrollToPage(viewport.currentPage.get() + 1)\n break\n case 'PageUp':\n viewport.scrollToPage(viewport.currentPage.get() - 1)\n break\n default:\n return\n }\n e.preventDefault()\n }\n el.addEventListener('keydown', onKeydown)\n return () => el.removeEventListener('keydown', onKeydown)\n}\n","// Inline styles here are structural only: the wrapper fills the page host and clips\n// (`position:absolute; inset:0; overflow:hidden`), and each canvas is pinned to the top-left\n// with its CSS size set from the transform (`position:absolute; left:0; top:0; width; height`).\n// Everything cosmetic (background, shadow, border) belongs to the theme.\nimport type { PageTransform } from './transform'\nimport type { InkDocument } from '../model/document'\nimport type { PdfjsRenderTask } from '../pdfjs/types'\n\nexport interface PageRendererOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`); the renderer appends its canvas layer to it. */\n host: HTMLElement\n transform: PageTransform\n /**\n * Fixed device pixel ratio. When omitted, `window.devicePixelRatio` is read at every render\n * and the page re-renders when it changes (browser zoom, moving to another screen).\n */\n devicePixelRatio?: number\n onRendered?(): void\n /** Called for any render failure other than a superseded render's cancellation. */\n onError?(error: unknown): void\n}\n\nexport interface PageRenderer {\n readonly element: HTMLElement\n /**\n * Resolves once the most recent `update` has painted, failed (see `onError`) or the\n * renderer was destroyed. Never rejects. A promise read before a later `update` resolves\n * together with that later render, so every promise handed out settles.\n */\n readonly rendered: Promise<void>\n update(transform: PageTransform): void\n destroy(): void\n}\n\nconst isCancellation = (error: unknown): boolean =>\n (error as { name?: unknown } | null)?.name === 'RenderingCancelledException'\n\nexport function createPageRenderer(opts: PageRendererOptions): PageRenderer {\n const { document: doc, page, host } = opts\n const view = host.ownerDocument.defaultView\n const currentDpr = (): number =>\n opts.devicePixelRatio ??\n (view && view.devicePixelRatio > 0 ? view.devicePixelRatio : 1)\n const wrapper = host.ownerDocument.createElement('div')\n wrapper.className = 'ink-canvas-layer'\n wrapper.dataset.inkCanvasLayer = ''\n wrapper.style.cssText = 'position:absolute;inset:0;overflow:hidden;'\n host.append(wrapper)\n\n let current: HTMLCanvasElement | undefined\n let latest = opts.transform\n let task: PdfjsRenderTask | undefined\n let destroyed = false\n let generation = 0\n\n // One deferred per busy period: renders that supersede each other share it, and it\n // resolves when the newest one settles.\n let resolvePending: (() => void) | undefined\n let rendered: Promise<void> = Promise.resolve()\n\n function settle() {\n resolvePending?.()\n resolvePending = undefined\n }\n\n /**\n * Drops a canvas for good. Zeroing it frees its bitmap now rather than at garbage\n * collection; Safari caps the total canvas memory, which a long scroll would otherwise hit.\n */\n function release(canvas: HTMLCanvasElement): void {\n canvas.width = 0\n canvas.height = 0\n canvas.remove()\n }\n\n function sizeCanvas(canvas: HTMLCanvasElement, transform: PageTransform) {\n canvas.style.width = `${transform.cssWidth}px`\n canvas.style.height = `${transform.cssHeight}px`\n }\n\n async function render(transform: PageTransform): Promise<void> {\n const gen = ++generation\n latest = transform\n const dpr = currentDpr()\n watchDpr(dpr)\n task?.cancel()\n task = undefined\n if (!resolvePending) {\n rendered = new Promise<void>((resolve) => (resolvePending = resolve))\n }\n // The previous bitmap stays visible, stretched to the new size, until the new one lands.\n if (current) sizeCanvas(current, transform)\n let canvas: HTMLCanvasElement | undefined\n try {\n const pdfPage = await doc._pdfjs.getPage(page)\n if (destroyed || gen !== generation) return\n const { AnnotationMode } = doc._pdfjs.module\n const viewport = pdfPage.getViewport({\n scale: transform.zoom,\n rotation: transform.totalRotation,\n })\n canvas = host.ownerDocument.createElement('canvas')\n canvas.dataset.inkCanvas = ''\n canvas.setAttribute('aria-hidden', 'true')\n canvas.width = Math.round(transform.cssWidth * dpr)\n canvas.height = Math.round(transform.cssHeight * dpr)\n canvas.style.cssText = 'position:absolute;left:0;top:0;'\n sizeCanvas(canvas, transform)\n const ownTask = pdfPage.render({\n canvas,\n viewport,\n // Pages are paper: an opaque white canvas, whatever the theme puts behind it.\n background: '#ffffff',\n annotationMode: AnnotationMode.ENABLE,\n ...(dpr === 1 ? {} : { transform: [dpr, 0, 0, dpr, 0, 0] }),\n })\n task = ownTask\n await ownTask.promise\n if (task === ownTask) task = undefined\n if (destroyed || gen !== generation) {\n release(canvas)\n return\n }\n if (current) release(current)\n current = canvas\n wrapper.append(canvas)\n opts.onRendered?.()\n } catch (error) {\n if (canvas && canvas !== current) release(canvas)\n const superseded = destroyed || gen !== generation\n if (!(superseded && isCancellation(error)) && !destroyed) opts.onError?.(error)\n } finally {\n if (gen === generation) settle()\n }\n }\n\n // Re-render when the device pixel ratio changes, unless the caller fixed it. The media\n // query matches only the ratio it was built for, so it is rebuilt after every change.\n // During a browser-zoom or screen transition the query can fire while devicePixelRatio\n // still reports the old value, so each change also schedules follow-up checks.\n const RECHECK_MS = [100, 500]\n let dprQuery: MediaQueryList | undefined\n let watchedDpr: number | undefined\n let rechecks: ReturnType<typeof setTimeout>[] = []\n const clearRechecks = (): void => {\n rechecks.forEach(clearTimeout)\n rechecks = []\n }\n const onDprChange = (): void => {\n if (destroyed) return\n const seen = currentDpr()\n watchDpr(seen, true)\n void render(latest)\n clearRechecks()\n rechecks = RECHECK_MS.map((ms) =>\n setTimeout(() => {\n if (!destroyed && currentDpr() !== watchedDpr) onDprChange()\n }, ms)\n )\n }\n function watchDpr(dpr: number, force = false): void {\n if (opts.devicePixelRatio !== undefined || !view?.matchMedia) return\n if (dpr === watchedDpr && !force) return\n watchedDpr = dpr\n dprQuery?.removeEventListener('change', onDprChange)\n dprQuery = view.matchMedia(`(resolution: ${dpr}dppx)`)\n dprQuery.addEventListener('change', onDprChange)\n }\n\n void render(opts.transform)\n\n return {\n element: wrapper,\n get rendered() {\n return rendered\n },\n update(transform) {\n if (destroyed) return\n void render(transform)\n },\n destroy() {\n if (destroyed) return\n destroyed = true\n dprQuery?.removeEventListener('change', onDprChange)\n dprQuery = undefined\n clearRechecks()\n task?.cancel()\n task = undefined\n if (current) release(current)\n current = undefined\n wrapper.remove()\n settle()\n },\n }\n}\n","// The only file that touches PDF.js's `TextLayer`. It takes the already-loaded PDF.js module\n// instead of importing `#pdfjs`, so `@inkbar/core/dom` can re-export the text layer without\n// evaluating PDF.js at import time.\nimport type { PdfjsModule, PdfjsPage, PdfjsViewport } from './types'\n\nexport interface MountedTextLayer {\n update(viewport: PdfjsViewport): void\n cancel(): void\n}\n\nexport interface MountPdfjsTextLayerOptions {\n /** The loaded PDF.js module, i.e. `InkDocument._pdfjs.module`. */\n module: PdfjsModule\n pdfPage: PdfjsPage\n container: HTMLElement\n viewport: PdfjsViewport\n /** Aborting cancels the render (and any later use of the layer). */\n signal?: AbortSignal\n}\n\n/**\n * Renders the page's text into `container` as positioned spans. The constructor sizes the\n * container from `--total-scale-factor` and sets `data-main-rotation`; CSS (the theme) turns\n * those into the final layout. Rejects with PDF.js's `AbortException` if `signal` aborts first.\n * On any rejection the layer is cancelled and detached from `signal`.\n */\nexport async function mountPdfjsTextLayer(\n opts: MountPdfjsTextLayerOptions\n): Promise<MountedTextLayer> {\n const layer = new opts.module.TextLayer({\n textContentSource: opts.pdfPage.streamTextContent({\n includeMarkedContent: false,\n disableNormalization: true,\n }),\n container: opts.container,\n viewport: opts.viewport,\n })\n const mounted: MountedTextLayer = {\n update(viewport) {\n layer.update({ viewport })\n },\n cancel() {\n layer.cancel()\n },\n }\n const onAbort = (): void => layer.cancel()\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n if (opts.signal?.aborted) layer.cancel()\n try {\n await layer.render()\n } catch (error) {\n // A failed layer is dropped here: cancelled, and no longer held by the caller's signal, so\n // a retry on the same signal does not keep every failed attempt alive.\n opts.signal?.removeEventListener('abort', onAbort)\n layer.cancel()\n throw error\n }\n return mounted\n}\n","// Inline styles here are structural only: the layer covers the page host\n// (`position:absolute; inset:0`) and its text must stay selectable whatever the page around it\n// sets (`user-select:text`). PDF.js sets the layer's width/height from `--total-scale-factor`.\n// Span styling (transparent colour, absolute positioning, font sizing, rotation transforms)\n// is the theme's job.\nimport { mountPdfjsTextLayer, type MountedTextLayer } from '../pdfjs/text-layer'\n\nimport type { PageTransform } from './transform'\nimport type { InkDocument } from '../model/document'\n\nexport interface TextLayerOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`), which must carry `--total-scale-factor`. */\n host: HTMLElement\n transform: PageTransform\n /**\n * Mount or update failures. Cancellation by `destroy` is not reported. If it throws, the\n * exception is rethrown asynchronously; `ready` still resolves.\n */\n onError?(error: unknown): void\n /** The layer mounted, or applied an `update`, without error. */\n onRendered?(): void\n}\n\nexport interface TextLayerHandle {\n readonly element: HTMLElement\n /** Resolves once the latest mount or `update` has applied. Never rejects. */\n readonly ready: Promise<void>\n update(transform: PageTransform): void\n destroy(): void\n}\n\nexport function createTextLayer(opts: TextLayerOptions): TextLayerHandle {\n const { document: doc, page } = opts\n const el = opts.host.ownerDocument.createElement('div')\n el.className = 'ink-text-layer'\n el.dataset.inkTextLayer = ''\n el.style.cssText = 'position:absolute;inset:0;user-select:text;'\n opts.host.append(el)\n\n const abort = new AbortController()\n let mounted: MountedTextLayer | undefined\n\n const viewportFor = async (transform: PageTransform) => {\n const pdfPage = await doc._pdfjs.getPage(page)\n return {\n pdfPage,\n viewport: pdfPage.getViewport({\n scale: transform.zoom,\n rotation: transform.totalRotation,\n }),\n }\n }\n\n // A throwing `onError` must not reject `ready`: its exception is rethrown from a microtask,\n // so it still surfaces as an uncaught error.\n const report = (error: unknown) => {\n if (abort.signal.aborted || !opts.onError) return\n try {\n opts.onError(error)\n } catch (thrown) {\n queueMicrotask(() => {\n throw thrown\n })\n }\n }\n\n const mount = async (transform: PageTransform): Promise<void> => {\n const { pdfPage, viewport } = await viewportFor(transform)\n if (abort.signal.aborted) return\n mounted = await mountPdfjsTextLayer({\n module: doc._pdfjs.module,\n pdfPage,\n container: el,\n viewport,\n signal: abort.signal,\n })\n if (!abort.signal.aborted) opts.onRendered?.()\n }\n\n let ready: Promise<void> = mount(opts.transform).catch(report)\n\n return {\n element: el,\n get ready() {\n return ready\n },\n update(transform) {\n if (abort.signal.aborted) return\n ready = ready\n .then(async () => {\n if (abort.signal.aborted) return\n // A mount that failed is tried again, so the layer can recover with the page.\n if (!mounted) {\n el.replaceChildren()\n await mount(transform)\n return\n }\n const { viewport } = await viewportFor(transform)\n if (abort.signal.aborted) return\n mounted.update(viewport)\n opts.onRendered?.()\n })\n .catch(report)\n },\n destroy() {\n if (abort.signal.aborted) return\n abort.abort()\n el.remove()\n },\n }\n}\n","import { mergeLineRects } from '../model/selection'\n\nimport type { PageTransform } from './transform'\nimport type { Quad, Rect } from '../model/geometry'\n\nexport interface SelectionQuads {\n /** Zero-based page index. */\n page: number\n /** One user-space quad per selected line, top to bottom. */\n quads: Quad[]\n text: string\n}\n\n/**\n * Converts viewport-relative CSS-pixel rects (from `getClientRects()`) to user-space rects on\n * the page rendered in `host`. Empty rects are skipped.\n */\nexport function cssRectsToUserRects(\n rects: Iterable<DOMRect>,\n host: HTMLElement,\n transform: PageTransform\n): Rect[] {\n const h = host.getBoundingClientRect()\n const out: Rect[] = []\n for (const r of rects) {\n if (r.width === 0 || r.height === 0) continue\n out.push(\n transform.fromCssRect({\n left: r.left - h.left,\n top: r.top - h.top,\n width: r.width,\n height: r.height,\n })\n )\n }\n return out\n}\n\n/**\n * Reads the live DOM selection and returns one entry per page it touches, with line-merged\n * user-space quads. Only text inside `[data-ink-text-layer]` under a `[data-page]` host counts;\n * `pageFor` maps a host to its page index and current transform.\n */\nexport function getSelectionQuads(\n root: HTMLElement,\n pageFor: (host: HTMLElement) => { page: number; transform: PageTransform } | undefined\n): SelectionQuads[] {\n const sel = root.ownerDocument.defaultView?.getSelection()\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return []\n const results = new Map<number, { rects: Rect[]; text: string[] }>()\n const layers = [...root.querySelectorAll<HTMLElement>('[data-ink-text-layer]')]\n if (root.matches('[data-ink-text-layer]')) layers.unshift(root)\n for (let i = 0; i < sel.rangeCount; i++) {\n const range = sel.getRangeAt(i)\n for (const layer of layers) {\n if (!range.intersectsNode(layer)) continue\n const host = layer.closest<HTMLElement>('[data-page]')\n if (!host) continue\n const info = pageFor(host)\n if (!info) continue\n const sub = range.cloneRange()\n if (!layer.contains(range.startContainer)) sub.setStart(layer, 0)\n if (!layer.contains(range.endContainer)) sub.setEnd(layer, layer.childNodes.length)\n const entry = results.get(info.page) ?? { rects: [], text: [] }\n entry.rects.push(...cssRectsToUserRects(sub.getClientRects(), host, info.transform))\n entry.text.push(rangeText(sub))\n results.set(info.page, entry)\n }\n }\n return [...results.entries()]\n .sort(([a], [b]) => a - b)\n .map(([page, { rects, text }]) => ({\n page,\n quads: mergeLineRects(rects),\n text: normaliseText(text.join('\\n')),\n }))\n .filter((r) => r.quads.length > 0)\n}\n\n/**\n * The range's text with each PDF.js `<br>` (an end of line) kept as a newline.\n * `Range.toString()` would run the lines together.\n */\nfunction rangeText(range: Range): string {\n const fragment = range.cloneContents()\n for (const br of fragment.querySelectorAll('br')) br.replaceWith('\\n')\n return fragment.textContent ?? ''\n}\n\n/**\n * Collapses runs of horizontal whitespace to one space and drops the spaces around a line\n * break. Breaks themselves are all kept, so a blank line (two breaks) survives.\n */\nfunction normaliseText(text: string): string {\n return text\n .replace(/[^\\S\\n]+/g, ' ')\n .replace(/ ?\\n ?/g, '\\n')\n .trim()\n}\n","// Geometry edits in user space, shared by the pointer (select tool) and keyboard (overlay)\n// paths so both produce the same patch for the same change.\nimport { translateQuad, translateRect, type Point, type Rect } from '../geometry'\n\nimport type { Annotation } from './types'\n\n/** Smallest width or height a resize leaves, user-space points. */\nexport const MIN_SIZE = 1\n\nconst shift = (p: Point, dx: number, dy: number): Point => ({ x: p.x + dx, y: p.y + dy })\n\n/** The geometry patch that translates `a` by (dx, dy) in user space. */\nexport function translated(a: Annotation, dx: number, dy: number): Partial<Annotation> {\n const patch: Record<string, unknown> = { rect: translateRect(a.rect, dx, dy) }\n if ('quads' in a && a.quads) patch.quads = a.quads.map((q) => translateQuad(q, dx, dy))\n if ('callout' in a && a.callout) patch.callout = a.callout.map((p) => shift(p, dx, dy))\n switch (a.type) {\n case 'line':\n patch.start = shift(a.start, dx, dy)\n patch.end = shift(a.end, dx, dy)\n break\n case 'polyline':\n case 'polygon':\n patch.vertices = a.vertices.map((p) => shift(p, dx, dy))\n break\n case 'ink':\n patch.paths = a.paths.map((path) => path.map((p) => shift(p, dx, dy)))\n break\n default:\n }\n return patch\n}\n\n/**\n * True when `rect` is the annotation's whole shape, so resizing means changing `rect`: area\n * redactions, free text, squares and circles. Text-derived marks (quads), note icons and\n * point-based shapes are not.\n */\nexport function hasRectGeometry(a: Annotation): boolean {\n switch (a.type) {\n case 'redact':\n return a.quads === undefined || a.quads.length === 0\n case 'freeText':\n case 'square':\n case 'circle':\n return true\n default:\n return false\n }\n}\n\n/**\n * Grows (positive) or shrinks (negative) a rect by `dw` and `dh` points, keeping its top-left\n * corner (user space: left edge and top edge, `y + height`) where it is. Neither side goes\n * below `MIN_SIZE`.\n */\nexport function resizedRect(r: Rect, dw: number, dh: number): Rect {\n const width = Math.max(MIN_SIZE, r.width + dw)\n const height = Math.max(MIN_SIZE, r.height + dh)\n const top = r.y + r.height\n return { x: r.x, y: top - height, width, height }\n}\n","import type { CssRect, PageTransform } from './transform'\nimport type { Annotation } from '../model/annotations/types'\nimport type { Point, Quad } from '../model/geometry'\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\n/**\n * The CSS box an annotation's default visual occupies. Usually `toCssRect(a.rect)`. Stroked\n * paths (lines, polylines, polygons, ink) use the bounds of their own points instead of\n * `rect` (which may already carry stroke padding, as a derived ink rect does), padded once by\n * half their stroke width on every side, at least 1px in all, so a horizontal or vertical\n * line still has a box to draw and hit-test in. Custom elements do not use this: they sit on\n * `toCssRect(a.rect)`.\n */\nexport function annotationBox(a: Annotation, t: PageTransform): CssRect {\n const points =\n a.type === 'line'\n ? [a.start, a.end]\n : a.type === 'polyline' || a.type === 'polygon'\n ? a.vertices\n : a.type === 'ink'\n ? a.paths.flat()\n : undefined\n if (!points || points.length === 0 || !('strokeWidth' in a)) return t.toCssRect(a.rect)\n const box = t.toCssRect(pointBounds(points))\n const pad = Math.max(t.toCssLength(a.strokeWidth), 1) / 2\n return {\n left: box.left - pad,\n top: box.top - pad,\n width: box.width + pad * 2,\n height: box.height + pad * 2,\n }\n}\n\nfunction pointBounds(points: readonly Point[]): {\n x: number\n y: number\n width: number\n height: number\n} {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y }\n}\n\n/**\n * Draws the default visual for an annotation inside its positioned element. Coordinates are\n * relative to the element. Colour, opacity and stroke are SVG attributes, never inline style,\n * so a theme can override them with CSS.\n */\nexport function renderAnnotationContent(\n el: HTMLElement,\n a: Annotation,\n t: PageTransform\n): void {\n const doc = el.ownerDocument\n el.replaceChildren()\n const box = annotationBox(a, t)\n const local = (p: Point): string => {\n const c = t.toCss(p)\n return `${c.x - box.left},${c.y - box.top}`\n }\n const node = (name: string, attrs: Record<string, string | number>): SVGElement => {\n const n = doc.createElementNS(SVG, name)\n for (const [k, v] of Object.entries(attrs)) n.setAttribute(k, String(v))\n return n\n }\n\n if (a.type === 'note') {\n // The note's box is its shape: a transparent rect takes the hits, the icon is theme art.\n const svg = boxSvg(doc, box.width, box.height)\n const hit = node('rect', {\n x: 0,\n y: 0,\n width: box.width,\n height: box.height,\n fill: 'transparent',\n stroke: 'none',\n 'pointer-events': 'all',\n })\n hit.classList.add('ink-note-box')\n svg.append(hit)\n const icon = doc.createElement('span')\n icon.className = 'ink-note-icon'\n icon.dataset.icon = a.icon\n el.append(svg, icon)\n return\n }\n if (a.type === 'freeText') {\n // HTML rather than SVG <text>: a text box must wrap, and SVG text does not. Font size,\n // colour and opacity travel as custom properties the theme reads; alignment as an attribute.\n const text = doc.createElement('div')\n text.className = 'ink-free-text'\n text.textContent = a.text\n text.dataset.align = a.align\n text.style.setProperty('--ink-font-size', `${t.toCssLength(a.fontSize)}px`)\n text.style.setProperty('--ink-text-color', a.color)\n text.style.setProperty('--ink-opacity', String(a.opacity))\n text.style.setProperty('--ink-font-family', cssString(a.fontFamily))\n // Structural: the element itself ignores the pointer, the text box takes it.\n text.style.pointerEvents = 'auto'\n el.append(text)\n return\n }\n\n const svg = boxSvg(doc, box.width, box.height)\n svg.classList.add('ink-annotation-shape')\n\n switch (a.type) {\n case 'highlight':\n for (const q of a.quads) {\n svg.append(\n node('polygon', {\n points: quadPoints(q).map(local).join(' '),\n fill: a.color,\n 'fill-opacity': a.opacity,\n })\n )\n }\n break\n case 'underline':\n case 'strikeout':\n case 'squiggly':\n svg.setAttribute('opacity', String(a.opacity))\n for (const q of a.quads) {\n const pts = markupLine(a.type, q)\n svg.append(\n node('polyline', {\n points: pts.map(local).join(' '),\n fill: 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(markupStroke(q)),\n })\n )\n }\n break\n case 'redact': {\n const shapes = a.quads\n ? a.quads.map((q) =>\n node('polygon', { points: quadPoints(q).map(local).join(' ') })\n )\n : [node('rect', { x: 0, y: 0, width: box.width, height: box.height })]\n for (const s of shapes) {\n s.setAttribute('fill', a.fill)\n s.setAttribute('fill-opacity', '0.15')\n s.setAttribute('stroke', a.color)\n s.setAttribute('stroke-width', String(t.toCssLength(1)))\n svg.append(s)\n }\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'square':\n case 'circle': {\n const sw = t.toCssLength(a.strokeWidth)\n const shape =\n a.type === 'square'\n ? node('rect', {\n x: sw / 2,\n y: sw / 2,\n width: Math.max(0, box.width - sw),\n height: Math.max(0, box.height - sw),\n })\n : node('ellipse', {\n cx: box.width / 2,\n cy: box.height / 2,\n rx: Math.max(0, box.width / 2 - sw / 2),\n ry: Math.max(0, box.height / 2 - sw / 2),\n })\n shape.setAttribute('fill', a.fill ?? 'none')\n shape.setAttribute('stroke', a.color)\n shape.setAttribute('stroke-width', String(sw))\n svg.append(shape)\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'line':\n case 'polyline':\n case 'polygon': {\n const pts = a.type === 'line' ? [a.start, a.end] : a.vertices\n svg.append(\n node(a.type === 'polygon' ? 'polygon' : 'polyline', {\n points: pts.map(local).join(' '),\n fill: a.type === 'polygon' ? (a.fill ?? 'none') : 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(a.strokeWidth),\n 'stroke-linejoin': 'round',\n })\n )\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'ink':\n for (const path of a.paths) {\n svg.append(\n node('polyline', {\n points: path.map(local).join(' '),\n fill: 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(a.strokeWidth),\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n })\n )\n }\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n // Hits follow the painted shape, so a press beside it reaches the text layer underneath.\n for (const shape of svg.children) shape.setAttribute('pointer-events', 'visiblePainted')\n el.append(svg)\n}\n\n/**\n * An invisible hit area for an annotation the overlay does not draw (embedded ones, which\n * PDF.js paints on the canvas): polygons over its quads, or its rect. Selection chrome only.\n */\nexport function renderHitArea(el: HTMLElement, a: Annotation, t: PageTransform): void {\n const doc = el.ownerDocument\n el.replaceChildren()\n const box = annotationBox(a, t)\n const svg = boxSvg(doc, box.width, box.height)\n svg.dataset.inkHit = ''\n const quads = 'quads' in a && a.quads ? a.quads : undefined\n const shapes = quads\n ? quads.map((q) => {\n const poly = doc.createElementNS(SVG, 'polygon')\n poly.setAttribute(\n 'points',\n quadPoints(q)\n .map((p) => {\n const c = t.toCss(p)\n return `${c.x - box.left},${c.y - box.top}`\n })\n .join(' ')\n )\n return poly\n })\n : [doc.createElementNS(SVG, 'rect')]\n for (const shape of shapes) {\n if (shape.tagName === 'rect') {\n shape.setAttribute('width', String(box.width))\n shape.setAttribute('height', String(box.height))\n }\n shape.setAttribute('fill', 'transparent')\n shape.setAttribute('stroke', 'none')\n shape.setAttribute('pointer-events', 'all')\n svg.append(shape)\n }\n el.append(svg)\n}\n\nfunction boxSvg(doc: Document, width: number, height: number): SVGSVGElement {\n const svg = doc.createElementNS(SVG, 'svg')\n svg.setAttribute('width', String(width))\n svg.setAttribute('height', String(height))\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`)\n svg.setAttribute('overflow', 'visible')\n // Block, not inline: an inline SVG sits on the text baseline and drifts below a short box.\n // The theme positions it absolutely as well.\n svg.setAttribute('display', 'block')\n svg.setAttribute('aria-hidden', 'true')\n return svg\n}\n\n/** Quad corners in drawing order: p1 top-left, p2 top-right, p4 bottom-right, p3 bottom-left. */\nfunction quadPoints(q: Quad): Point[] {\n return [q.p1, q.p2, q.p4, q.p3]\n}\n\nconst lerp = (a: Point, b: Point, f: number): Point => ({\n x: a.x + (b.x - a.x) * f,\n y: a.y + (b.y - a.y) * f,\n})\nconst dist = (a: Point, b: Point): number => Math.hypot(b.x - a.x, b.y - a.y)\n\n/** Line thickness in points for a text markup: a fraction of the quad's height. */\nfunction markupStroke(q: Quad): number {\n return Math.max(0.5, dist(q.p1, q.p3) / 14)\n}\n\n/** The stroke for an underline, strikeout or squiggly, in user space. */\nfunction markupLine(type: 'underline' | 'strikeout' | 'squiggly', q: Quad): Point[] {\n if (type === 'strikeout') return [lerp(q.p1, q.p3, 0.5), lerp(q.p2, q.p4, 0.5)]\n const height = dist(q.p1, q.p3)\n // The baseline sits a little above the quad's bottom edge.\n const start = lerp(q.p3, q.p1, 0.1)\n const end = lerp(q.p4, q.p2, 0.1)\n if (type === 'underline') return [start, end]\n const length = dist(start, end)\n const amp = Math.max(0.5, height / 16)\n const step = amp * 2\n const steps = Math.max(1, Math.round(length / step))\n // Unit normal pointing from the bottom edge towards the top edge.\n const up = {\n x: (q.p1.x - q.p3.x) / (height || 1),\n y: (q.p1.y - q.p3.y) / (height || 1),\n }\n const pts: Point[] = []\n for (let i = 0; i <= steps; i++) {\n const p = lerp(start, end, i / steps)\n const s = i % 2 === 0 ? -amp : amp\n pts.push({ x: p.x + up.x * s, y: p.y + up.y * s })\n }\n return pts\n}\n\n/** A CSS string literal, so any PDF font name is a single family name. */\nfunction cssString(value: string): string {\n return `\"${value.replace(/[\"\\\\]/g, '\\\\$&').replace(/\\n/g, '\\\\a ')}\"`\n}\n","// Inline styles here are structural or geometric only: the container is\n// `position:absolute; inset:0; pointer-events:none` so it covers the page without eating\n// events, and each annotation element is `position:absolute` with `left/top/width/height`\n// from `annotationBox` (stroked paths padded once by their stroke), or from\n// `PageTransform.toCssRect(a.rect)` for custom elements. Hit-testing\n// follows the drawn shape, not the box: elements are `pointer-events:none` and their shapes\n// opt back in (overlay-render.ts), so a press beside a shape still reaches the text layer.\n// Resize handles (`.ink-handle[data-handle]`) are 8px `position:absolute;\n// pointer-events:auto` boxes on the element's corners; their look is the theme's.\n// Custom elements are the exception and stay `pointer-events:auto`: the host draws them and\n// only it knows their shape. Every visual (colour, opacity, stroke, fill) is an SVG\n// attribute or a theme hook.\nimport { hasRectGeometry, resizedRect, translated } from '../model/annotations/edit'\nimport { confidenceBucket, type Annotation } from '../model/annotations/types'\n\nimport { annotationBox, renderAnnotationContent, renderHitArea } from './overlay-render'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\n\nexport interface OverlayOptions {\n host: HTMLElement\n /** 0-based page index this overlay shows. */\n page: number\n store: AnnotationStore\n transform: PageTransform\n /** Called when an annotation is clicked, or activated with Enter or Space. */\n onActivate?(id: string): void\n /** Return true to render only the positioned shell; the host (e.g. a Vue slot) fills it. */\n isCustom?(annotation: Annotation): boolean\n}\n\nexport interface Overlay {\n readonly element: HTMLElement\n /** Repositions every element and redraws content for a new zoom or rotation. */\n update(transform: PageTransform): void\n elementFor(id: string): HTMLElement | undefined\n destroy(): void\n}\n\ntype State = 'idle' | 'hover' | 'selected'\n\n/** Resize handles, by the CSS corner they sit on. */\nconst HANDLES = ['nw', 'ne', 'sw', 'se'] as const\n/** Side of a resize handle, CSS px. */\nconst HANDLE_PX = 8\n\n/** Arrow keys as user-space unit steps (y grows upwards). */\nconst ARROW_STEPS: Record<string, { x: number; y: number }> = {\n ArrowRight: { x: 1, y: 0 },\n ArrowLeft: { x: -1, y: 0 },\n ArrowUp: { x: 0, y: 1 },\n ArrowDown: { x: 0, y: -1 },\n}\n\nconst LABELS: Record<Annotation['type'], string> = {\n highlight: 'Highlight',\n underline: 'Underline',\n strikeout: 'Strikeout',\n squiggly: 'Squiggly underline',\n note: 'Note',\n freeText: 'Text box',\n square: 'Rectangle',\n circle: 'Ellipse',\n line: 'Line',\n polyline: 'Polyline',\n polygon: 'Polygon',\n ink: 'Drawing',\n redact: 'Redaction',\n}\n\n/** The `data-confidence` bucket for a suggested redaction; undefined for everything else. */\nexport function confidenceAttr(a: Annotation): 'low' | 'medium' | 'high' | undefined {\n return a.type === 'redact' && a.suggestion\n ? confidenceBucket(a.suggestion.confidence)\n : undefined\n}\n\nfunction ariaLabel(a: Annotation): string {\n const base =\n a.type === 'redact' && a.origin === 'suggested'\n ? 'Suggested redaction'\n : LABELS[a.type]\n return a.author ? `${base} by ${a.author}` : base\n}\n\n/** Reading order in user space: top edge first (y grows upwards), then left edge. */\nfunction readingOrder(a: Annotation, b: Annotation): number {\n return b.rect.y + b.rect.height - (a.rect.y + a.rect.height) || a.rect.x - b.rect.x\n}\n\nfunction setFlag(node: HTMLElement, key: string, on: boolean): void {\n if (on) node.dataset[key] = ''\n else delete node.dataset[key]\n}\n\nfunction setData(node: HTMLElement, key: string, value: string | undefined): void {\n if (value === undefined) delete node.dataset[key]\n else node.dataset[key] = value\n}\n\nexport function createOverlay(opts: OverlayOptions): Overlay {\n const { store, page } = opts\n const doc = opts.host.ownerDocument\n let transform = opts.transform\n const root = doc.createElement('div')\n root.className = 'ink-overlay'\n root.dataset.inkOverlay = ''\n root.style.cssText = 'position:absolute;inset:0;pointer-events:none;'\n opts.host.append(root)\n\n const elements = new Map<string, HTMLElement>()\n /** What each element's content was last drawn from; absent when it has none of ours. */\n const drawn = new Map<string, { a: Annotation; t: PageTransform }>()\n const hovered = new Set<string>()\n let order: string[] = []\n let destroyed = false\n\n function stateOf(id: string, selected: ReadonlySet<string>): State {\n if (selected.has(id)) return 'selected'\n return hovered.has(id) ? 'hover' : 'idle'\n }\n\n function applyState(node: HTMLElement, id: string): void {\n const selected = new Set(store.selection.get())\n const anyHere = order.some((x) => selected.has(x))\n const state = stateOf(id, selected)\n node.dataset.state = state\n node.setAttribute('aria-pressed', String(state === 'selected'))\n node.tabIndex = !anyHere || state === 'selected' ? 0 : -1\n const a = store.get(id)\n syncHandles(\n node,\n selectToolActive() &&\n state === 'selected' &&\n a !== undefined &&\n !a.locked &&\n hasRectGeometry(a)\n )\n }\n\n /** True while the tool controller marks the tool root (an ancestor) `data-ink-tool=\"select\"`. */\n function selectToolActive(): boolean {\n return (\n opts.host.closest('[data-ink-tool]')?.getAttribute('data-ink-tool') === 'select'\n )\n }\n // Re-sync handles on a tool switch. The controller's root is normally the viewport\n // container; pages can mount before the controller marks it, so fall back to that.\n const toolRoot =\n opts.host.closest('[data-ink-tool]') ?? opts.host.closest('[data-ink-viewport]')\n const Observer = doc.defaultView?.MutationObserver\n let toolObserver: MutationObserver | undefined\n if (toolRoot && Observer) {\n toolObserver = new Observer(() => {\n if (destroyed) return\n for (const [id, node] of elements) applyState(node, id)\n })\n toolObserver.observe(toolRoot, {\n attributes: true,\n attributeFilter: ['data-ink-tool'],\n })\n }\n\n /**\n * Corner handles for a selected, unlocked rect-shaped annotation, drawn only while the select\n * tool is active (`data-ink-tool=\"select\"` on the tool root). The select tool drags them\n * (`data-handle` names the CSS corner). The theme also hides them outside the select tool.\n */\n function syncHandles(node: HTMLElement, want: boolean): void {\n const existing = node.querySelectorAll(':scope > [data-handle]')\n if (!want) {\n existing.forEach((h) => h.remove())\n return\n }\n if (existing.length === HANDLES.length) return\n existing.forEach((h) => h.remove())\n for (const corner of HANDLES) {\n const h = doc.createElement('div')\n h.className = 'ink-handle'\n h.dataset.handle = corner\n h.setAttribute('aria-hidden', 'true')\n const off = `${-HANDLE_PX / 2}px`\n h.style.cssText =\n `position:absolute;width:${HANDLE_PX}px;height:${HANDLE_PX}px;pointer-events:auto;` +\n `${corner[0] === 'n' ? 'top' : 'bottom'}:${off};` +\n `${corner[1] === 'w' ? 'left' : 'right'}:${off};`\n node.append(h)\n }\n }\n\n function applyAttributes(node: HTMLElement, a: Annotation): void {\n node.dataset.type = a.type\n node.dataset.source = a.source\n setFlag(node, 'locked', a.locked === true)\n setData(node, 'origin', a.type === 'redact' ? a.origin : undefined)\n setData(node, 'confidence', confidenceAttr(a))\n node.setAttribute('aria-label', ariaLabel(a))\n }\n\n function applyGeometry(node: HTMLElement, a: Annotation): void {\n // Custom elements hold host content laid out against the annotation's own rect.\n const box =\n opts.isCustom?.(a) === true\n ? transform.toCssRect(a.rect)\n : annotationBox(a, transform)\n node.style.left = `${box.left}px`\n node.style.top = `${box.top}px`\n node.style.width = `${box.width}px`\n node.style.height = `${box.height}px`\n }\n\n function applyContent(node: HTMLElement, a: Annotation): void {\n const custom = opts.isCustom?.(a) === true\n setFlag(node, 'custom', custom)\n node.style.pointerEvents = custom ? 'auto' : 'none'\n // Custom elements are the host's to fill: draw nothing.\n if (custom) {\n if (drawn.delete(a.id)) node.replaceChildren()\n return\n }\n const last = drawn.get(a.id)\n if (last?.a === a && last.t === transform) return\n // Embedded annotations are already painted on the canvas by PDF.js, so they get only an\n // invisible hit area.\n if (a.source === 'pdf') renderHitArea(node, a, transform)\n else renderAnnotationContent(node, a, transform)\n drawn.set(a.id, { a, t: transform })\n }\n\n function activate(id: string): void {\n store.select([id])\n opts.onActivate?.(id)\n }\n\n function focusAt(index: number): void {\n const id = order[Math.max(0, Math.min(order.length - 1, index))]\n if (id !== undefined) elements.get(id)?.focus()\n }\n\n /**\n * `Shift+Arrow` moves the annotation 1 pt in user space (`Shift+Alt+Arrow` 10 pt; up is +y).\n * `Ctrl+Shift+Arrow` or `Meta+Shift+Arrow` resizes a rect-shaped one by 1 pt: Right and Down\n * grow it, Left and Up shrink it, keeping its top-left corner. Locked items ignore both.\n * Returns true when the key was one of these chords.\n */\n function onEditKey(e: KeyboardEvent, id: string): boolean {\n const step = ARROW_STEPS[e.key]\n if (!step || !e.shiftKey) return false\n e.preventDefault()\n const a = store.get(id)\n if (!a || a.locked) return true\n if (e.ctrlKey || e.metaKey) {\n if (hasRectGeometry(a))\n store.update(id, { rect: resizedRect(a.rect, step.x, -step.y) })\n return true\n }\n const by = e.altKey ? 10 : 1\n store.update(id, translated(a, step.x * by, step.y * by))\n return true\n }\n\n function onKey(e: KeyboardEvent, id: string): void {\n if (onEditKey(e, id)) return\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n activate(id)\n break\n case 'Delete':\n case 'Backspace': {\n // The overlay owns deletion from a focused annotation: it removes that one only, never\n // the rest of the selection. `preventDefault` tells the select tool to stand down.\n e.preventDefault()\n const a = store.get(id)\n if (a && !a.locked) store.remove(id)\n break\n }\n case 'Escape':\n e.preventDefault()\n store.select([])\n break\n case 'ArrowDown':\n case 'ArrowUp':\n e.preventDefault()\n focusAt(order.indexOf(id) + (e.key === 'ArrowDown' ? 1 : -1))\n break\n default:\n }\n }\n\n function create(id: string): HTMLElement {\n const node = doc.createElement('div')\n node.className = 'ink-annotation'\n node.dataset.annotation = id\n node.setAttribute('role', 'button')\n node.style.position = 'absolute'\n node.addEventListener('pointerenter', () => {\n hovered.add(id)\n applyState(node, id)\n })\n node.addEventListener('pointerleave', () => {\n hovered.delete(id)\n applyState(node, id)\n })\n node.addEventListener('pointerdown', (e) => {\n if (e.button !== 0) return\n // A press on a custom element's own content (a host's button, say) is that content's:\n // no selection, and it bubbles on to the host's delegated handlers.\n if (\n e.target !== node &&\n node.hasAttribute('data-custom') &&\n !(e.target instanceof Element && e.target.closest('[data-handle]'))\n )\n return\n // A tool listening on the page root must not start a drag from this press.\n e.stopPropagation()\n activate(id)\n })\n node.addEventListener('keydown', (e) => {\n // Keys typed in descendants (a custom element's buttons and inputs) are theirs.\n if (e.target !== node) return\n onKey(e, id)\n })\n return node\n }\n\n function render(): void {\n if (destroyed) return\n const current = store.byPage(page).sort(readingOrder)\n const ids = new Set(current.map((a) => a.id))\n const active = doc.activeElement\n let focusId = [...elements].find(([, n]) => n === active)?.[0]\n /** The focused element is going away with nothing on this page to take over. */\n let focusRoot = false\n\n if (focusId !== undefined && !ids.has(focusId)) {\n // The focused element is going away: hand focus to the next survivor, else the previous.\n const i = order.indexOf(focusId)\n focusId =\n order.slice(i + 1).find((x) => ids.has(x)) ??\n order\n .slice(0, i)\n .reverse()\n .find((x) => ids.has(x))\n focusRoot = focusId === undefined\n }\n for (const [id, node] of elements) {\n if (ids.has(id)) continue\n node.remove()\n elements.delete(id)\n drawn.delete(id)\n hovered.delete(id)\n }\n\n order = current.map((a) => a.id)\n for (const a of current) {\n let node = elements.get(a.id)\n if (!node) {\n node = create(a.id)\n elements.set(a.id, node)\n }\n applyAttributes(node, a)\n applyGeometry(node, a)\n applyContent(node, a)\n applyState(node, a.id)\n }\n\n // DOM order is tab order: keep it in reading order. Moving nodes blurs them, so only\n // re-append when the order actually changed.\n const inDom = [...root.children]\n if (\n inDom.length !== order.length ||\n order.some((id, i) => inDom[i] !== elements.get(id))\n ) {\n for (const id of order) root.append(elements.get(id)!)\n }\n if (focusId !== undefined) {\n const target = elements.get(focusId)\n if (target && doc.activeElement !== target) target.focus({ preventScroll: true })\n } else if (focusRoot) {\n // Last one on the page: back to the scroll element (as the popovers do), not <body>.\n const scroll = opts.host.closest<HTMLElement>('[data-ink-viewport]')\n if (scroll) {\n // A container the host did not make focusable still takes focus from script.\n if (!scroll.hasAttribute('tabindex')) scroll.tabIndex = -1\n scroll.focus({ preventScroll: true })\n }\n }\n }\n\n const offList = store.list.subscribe(render)\n const offSelection = store.selection.subscribe(() => {\n for (const [id, node] of elements) applyState(node, id)\n })\n render()\n\n return {\n element: root,\n update(next) {\n transform = next\n render()\n },\n elementFor: (id) => elements.get(id),\n destroy() {\n if (destroyed) return\n destroyed = true\n offList()\n offSelection()\n toolObserver?.disconnect()\n root.remove()\n elements.clear()\n drawn.clear()\n hovered.clear()\n order = []\n },\n }\n}\n","import { createOverlay, type Overlay } from './overlay'\nimport { createPageRenderer, type PageRenderer } from './page-renderer'\nimport { createTextLayer, type TextLayerHandle } from './text-layer'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\nimport type { Annotation } from '../model/annotations/types'\nimport type { InkDocument } from '../model/document'\n\nexport interface PageMountOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`) from the viewport's `onMount`. */\n host: HTMLElement\n transform: PageTransform\n store: AnnotationStore\n onActivate?(id: string): void\n isCustom?(a: Annotation): boolean\n /** Defaults to `window.devicePixelRatio`. */\n devicePixelRatio?: number\n /**\n * Canvas and text layer failures, with the layer that failed (cancellations are not\n * reported).\n */\n onError?(error: unknown, layer: PageLayer): void\n /**\n * A layer finished without error: the canvas painted, or the text layer mounted or applied\n * an update. Pair it with `onError` to tell when a failed layer has recovered.\n */\n onRendered?(layer: PageLayer): void\n}\n\n/** The page layers that can fail and recover: the canvas and the text layer. */\nexport type PageLayer = 'canvas' | 'text'\n\nexport interface PageMount {\n readonly renderer: PageRenderer\n readonly textLayer: TextLayerHandle\n readonly overlay: Overlay\n update(transform: PageTransform): void\n destroy(): void\n}\n\n/** Canvas, text layer and annotation overlay for one page, stacked in that order. */\nexport function createPageMount(opts: PageMountOptions): PageMount {\n const { document, page, host, transform } = opts\n const callbacks = (layer: PageLayer) => ({\n ...(opts.onError\n ? { onError: (error: unknown) => opts.onError?.(error, layer) }\n : {}),\n ...(opts.onRendered ? { onRendered: () => opts.onRendered?.(layer) } : {}),\n })\n const renderer = createPageRenderer({\n document,\n page,\n host,\n transform,\n ...(opts.devicePixelRatio === undefined\n ? {}\n : { devicePixelRatio: opts.devicePixelRatio }),\n ...callbacks('canvas'),\n })\n const textLayer = createTextLayer({\n document,\n page,\n host,\n transform,\n ...callbacks('text'),\n })\n const overlay = createOverlay({\n host,\n page,\n store: opts.store,\n transform,\n ...(opts.onActivate ? { onActivate: (id: string) => opts.onActivate?.(id) } : {}),\n ...(opts.isCustom\n ? { isCustom: (a: Annotation) => opts.isCustom?.(a) === true }\n : {}),\n })\n return {\n renderer,\n textLayer,\n overlay,\n update(next) {\n renderer.update(next)\n textLayer.update(next)\n overlay.update(next)\n },\n destroy() {\n overlay.destroy()\n textLayer.destroy()\n renderer.destroy()\n },\n }\n}\n","// The controller writes two things to the root: `data-ink-tool=\"<id>\"` (a marker for themes\n// and tests; `data-tool` belongs to toolbar buttons) and `style.cursor` from the active tool.\n// Both are structural, and both are removed on destroy.\n//\n// `pointerdown` is listened for in the capture phase. The overlay stops propagation of presses\n// on annotation shapes (so a creation tool never starts a drag from one), but a capture\n// listener on the root runs before that, so the controller can pass the pressed annotation's\n// id to the tool. Move, up and key events bubble normally.\n//\n// When a tool starts a gesture (its `onPointerDown` returns true) the controller captures the\n// pointer on the root, so the release still arrives when it happens outside. `pointercancel`\n// and `lostpointercapture` reach the tool as `onPointerCancel`. `touch-action` is left to the\n// theme or host: touch gestures are theirs to arbitrate.\n//\n// The controller tracks the pressed pointer. Switching tools mid-press cancels the old tool's\n// gesture and swallows that pointer's release, so the new tool never sees half a gesture.\n// `lostpointercapture` after a completed release is not a cancel. Only primary-button presses\n// and releases reach tools. The root's own inline cursor is restored on destroy.\nimport { readonly, writable, type Readable } from '../../model/readable'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Point } from '../../model/geometry'\nimport type { SelectionQuads } from '../selection'\nimport type { Viewport, ViewportHit } from '../viewport'\n\nexport type ToolId = 'view' | 'select' | 'highlight' | 'redact-area' | 'note'\n\nexport interface PageHit extends ViewportHit {\n /** Pointer position in user space. */\n user: Point\n /** Pointer position relative to the page host's top-left, CSS px. */\n css: Point\n}\n\nexport interface ToolContext {\n store: AnnotationStore\n viewport: Viewport\n /** The element pointer and key events are listened on (the viewport container). */\n root: HTMLElement\n /** The live text selection as user-space quads, one entry per page. */\n selectionQuads(): SelectionQuads[]\n clearSelection(): void\n onActivate?(id: string): void\n}\n\nexport interface Tool {\n id: ToolId\n cursor: string\n activate(ctx: ToolContext): void\n deactivate(): void\n /**\n * Runs in the capture phase, before the overlay sees the press. `annotationId` is set when\n * the press landed on an annotation; the overlay then selects and activates it, so tools\n * other than `select` should ignore such presses. Calling `e.stopPropagation()` here keeps\n * the overlay from handling it. Return true when the press starts a gesture: the controller\n * then captures the pointer until it is released or cancelled.\n */\n onPointerDown?(\n e: PointerEvent,\n hit: PageHit | undefined,\n annotationId?: string\n ): boolean | void\n /**\n * A move with `e.buttons === 0` during a gesture means the release was missed (it happened\n * where no listener saw it): tools treat it as a cancel.\n */\n onPointerMove?(e: PointerEvent, hit: PageHit | undefined): void\n onPointerUp?(e: PointerEvent, hit: PageHit | undefined): void\n /** `pointercancel` or `lostpointercapture`: drop any gesture in progress without writing. */\n onPointerCancel?(e: PointerEvent): void\n onKeyDown?(e: KeyboardEvent): void\n}\n\nexport interface ToolController {\n readonly active: Readable<ToolId>\n set(id: ToolId): void\n destroy(): void\n}\n\nexport interface ToolControllerOptions {\n ctx: ToolContext\n /** Default `'view'`. */\n initial?: ToolId\n tools: Tool[]\n}\n\n/** Host-relative CSS point for a client point. */\nexport function cssIn(host: HTMLElement, e: { clientX: number; clientY: number }): Point {\n const r = host.getBoundingClientRect()\n return { x: e.clientX - r.left, y: e.clientY - r.top }\n}\n\n/** Like `cssIn`, clamped to the host's box, so a drag past the page edge stops at the edge. */\nexport function clampedCssIn(\n host: HTMLElement,\n e: { clientX: number; clientY: number }\n): Point {\n const r = host.getBoundingClientRect()\n return {\n x: Math.min(Math.max(e.clientX - r.left, 0), r.width),\n y: Math.min(Math.max(e.clientY - r.top, 0), r.height),\n }\n}\n\n/** The mounted page under a client point, with the point in CSS px and user space. */\nexport function hitFor(\n ctx: ToolContext,\n e: { clientX: number; clientY: number }\n): PageHit | undefined {\n const hit = ctx.viewport.pageAtCss(e.clientX, e.clientY)\n if (!hit) return undefined\n const css = cssIn(hit.host, e)\n return { ...hit, css, user: hit.transform.fromCss(css) }\n}\n\nexport function createToolController(opts: ToolControllerOptions): ToolController {\n const { ctx } = opts\n const byId = new Map(opts.tools.map((t) => [t.id, t]))\n const active = writable<ToolId>(opts.initial ?? 'view')\n let current: Tool | undefined\n const originalCursor = ctx.root.style.cursor\n /** The pointer between a primary press and its release or cancel. */\n let pressed: number | undefined\n /** Pointers whose release belongs to a tool that is no longer active. */\n const swallow = new Set<number>()\n\n /** True for events from a pointer other than the one whose press is live. */\n const foreign = (e: PointerEvent): boolean =>\n pressed !== undefined && pressed !== e.pointerId\n\n const onDown = (e: PointerEvent): void => {\n if (!e.isPrimary || e.button !== 0 || inCustomContent(e.target)) return\n // One gesture at a time: a second pointer pressing mid-gesture is ignored.\n if (foreign(e)) return\n swallow.delete(e.pointerId)\n pressed = e.pointerId\n const target = e.target instanceof Element ? e.target : null\n const annotationId =\n target?.closest('[data-annotation]')?.getAttribute('data-annotation') ?? undefined\n if (current?.onPointerDown?.(e, hitFor(ctx, e), annotationId) === true)\n capture(e.pointerId)\n }\n const onMove = (e: PointerEvent): void => {\n if (!e.isPrimary || foreign(e)) return\n // A buttonless move means the release was missed: the press is over (tools drop their\n // own gesture on the same signal), so another pointer may press again.\n if (pressed === e.pointerId && e.buttons === 0) pressed = undefined\n current?.onPointerMove?.(e, hitFor(ctx, e))\n }\n const onUp = (e: PointerEvent): void => {\n if (!e.isPrimary || e.button !== 0 || foreign(e)) return\n if (pressed === e.pointerId) pressed = undefined\n if (swallow.delete(e.pointerId)) {\n release(e.pointerId)\n return\n }\n current?.onPointerUp?.(e, hitFor(ctx, e))\n release(e.pointerId)\n }\n const onCancel = (e: PointerEvent): void => {\n if (!e.isPrimary || foreign(e)) return\n // Capture is also lost when a completed release frees it: only a live press cancels.\n if (e.type === 'lostpointercapture' && pressed !== e.pointerId) return\n if (pressed === e.pointerId) pressed = undefined\n swallow.delete(e.pointerId)\n current?.onPointerCancel?.(e)\n }\n const onKey = (e: KeyboardEvent): void => {\n if (!inCustomContent(e.target)) current?.onKeyDown?.(e)\n }\n\n // Capture is best effort: synthetic events may carry a pointer id the browser does not know.\n function capture(id: number): void {\n try {\n ctx.root.setPointerCapture?.(id)\n } catch {\n // Not an active pointer: the gesture still works while the pointer stays over the root.\n }\n }\n function release(id: number): void {\n try {\n if (ctx.root.hasPointerCapture?.(id)) ctx.root.releasePointerCapture(id)\n } catch {\n // Already released.\n }\n }\n ctx.root.addEventListener('pointerdown', onDown, { capture: true })\n ctx.root.addEventListener('pointermove', onMove)\n ctx.root.addEventListener('pointerup', onUp)\n ctx.root.addEventListener('pointercancel', onCancel)\n ctx.root.addEventListener('lostpointercapture', onCancel)\n ctx.root.addEventListener('keydown', onKey)\n\n function set(id: ToolId): void {\n const next = byId.get(id)\n if (!next) throw new RangeError(`Unknown tool ${id}`)\n if (pressed !== undefined) {\n // Mid-press: end the old tool's gesture here and keep its release from the new tool.\n current?.onPointerCancel?.(\n new PointerEvent('pointercancel', { pointerId: pressed, isPrimary: true })\n )\n swallow.add(pressed)\n pressed = undefined\n }\n current?.deactivate()\n current = next\n next.activate(ctx)\n ctx.root.dataset.inkTool = id\n ctx.root.style.cursor = next.cursor\n active.set(id)\n }\n set(opts.initial ?? 'view')\n\n return {\n active: readonly(active),\n set,\n destroy() {\n current?.deactivate()\n current = undefined\n ctx.root.removeEventListener('pointerdown', onDown, { capture: true })\n ctx.root.removeEventListener('pointermove', onMove)\n ctx.root.removeEventListener('pointerup', onUp)\n ctx.root.removeEventListener('pointercancel', onCancel)\n ctx.root.removeEventListener('lostpointercapture', onCancel)\n ctx.root.removeEventListener('keydown', onKey)\n delete ctx.root.dataset.inkTool\n ctx.root.style.cursor = originalCursor\n },\n }\n}\n\n/**\n * True for an unmodified, unhandled Enter on the viewport's own elements: the scroll element\n * (`root`), a page host, or content of a page's text layer or canvas layer. Every other target\n * (annotations, custom slot content, any control a host puts in the page) keeps its Enter.\n * This is the keyboard trigger for the creation tools.\n */\nexport function isViewportEnter(e: KeyboardEvent, root: HTMLElement): boolean {\n if (e.key !== 'Enter' || e.defaultPrevented) return false\n if (e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.isComposing) return false\n const target = e.target\n if (target === root) return true\n if (!(target instanceof Element) || !root.contains(target)) return false\n if (target.matches('.ink-page[data-page]')) return true\n return target.closest('[data-ink-text-layer], [data-ink-canvas-layer]') !== null\n}\n\n/**\n * True for a target inside a custom annotation element (`data-custom`) but not that element\n * itself: the host's buttons and inputs there own their presses and keys, as in the overlay.\n */\nfunction inCustomContent(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n const el = target.closest('[data-annotation]')\n return (\n el !== null &&\n el !== target &&\n el.hasAttribute('data-custom') &&\n // Resize handles are the overlay's, not the host's content.\n target.closest('[data-handle]') === null\n )\n}\n","import { isViewportEnter, type Tool, type ToolContext } from './controller'\n\n/**\n * Turns the text selection into one highlight per page when the pointer is released, or on\n * Enter in the viewport (a keyboard selection). Without a selection both do nothing.\n */\nexport function highlightTool(): Tool {\n let ctx: ToolContext | undefined\n const convert = (): boolean => {\n if (!ctx) return false\n const selections = ctx.selectionQuads()\n if (selections.length === 0) return false\n for (const s of selections) {\n ctx.store.add({\n type: 'highlight',\n page: s.page,\n quads: s.quads,\n contents: s.text,\n })\n }\n ctx.clearSelection()\n return true\n }\n return {\n id: 'highlight',\n cursor: 'text',\n activate(c) {\n ctx = c\n },\n deactivate() {\n ctx = undefined\n },\n onPointerUp() {\n convert()\n },\n onKeyDown(e) {\n if (!!ctx && isViewportEnter(e, ctx.root) && convert()) e.preventDefault()\n },\n }\n}\n","import { isViewportEnter, type PageHit, type Tool, type ToolContext } from './controller'\n\nimport type { Point } from '../../model/geometry'\n\n/** Side of a new note's icon box, user-space points. */\nconst SIZE = 20\n\n/** Frames to wait for a controlled host to apply a new note before giving up on focusing it. */\nconst FOCUS_FRAMES = 10\n\n/**\n * Click places a note centred on the press. Enter in the viewport places one at the centre of\n * the current page and focuses it. Either way the note is selected and activated.\n */\nexport function noteTool(): Tool {\n let ctx: ToolContext | undefined\n let down: PageHit | undefined\n\n const place = (c: ToolContext, page: number, at: Point): string => {\n const a = c.store.add({\n type: 'note',\n page,\n rect: { x: at.x - SIZE / 2, y: at.y - SIZE / 2, width: SIZE, height: SIZE },\n })\n c.store.select([a.id])\n return a.id\n }\n\n return {\n id: 'note',\n cursor: 'copy',\n activate(c) {\n ctx = c\n },\n deactivate() {\n ctx = undefined\n down = undefined\n },\n onPointerDown(_e, hit, annotationId) {\n down = annotationId === undefined ? hit : undefined\n return down !== undefined\n },\n onPointerCancel() {\n down = undefined\n },\n onPointerUp(_e, hit) {\n const pressed = down\n down = undefined\n if (!ctx || !pressed || !hit || hit.page !== pressed.page) return\n const id = place(ctx, hit.page, hit.user)\n ctx.onActivate?.(id)\n },\n onKeyDown(e) {\n if (!ctx || !isViewportEnter(e, ctx.root)) return\n e.preventDefault()\n const c = ctx\n const page = c.viewport.currentPage.get()\n const { box } = c.viewport.transformFor(page).page\n const id = place(c, page, { x: box.x + box.width / 2, y: box.y + box.height / 2 })\n focusWhenDrawn(c, id)\n c.onActivate?.(id)\n },\n }\n}\n\n/**\n * Focuses the note's overlay element. An uncontrolled store draws it synchronously; a\n * controlled host applies the change later, so wait a few frames, and give up if focus has\n * meanwhile moved off the viewport (a popover took it).\n */\nfunction focusWhenDrawn(ctx: ToolContext, id: string): void {\n const doc = ctx.root.ownerDocument\n const find = (): HTMLElement | null =>\n ctx.root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`)\n const now = find()\n if (now) {\n now.focus({ preventScroll: true })\n return\n }\n let frames = 0\n const view = doc.defaultView\n const tick = (): void => {\n if (doc.activeElement !== ctx.root) return\n const el = find()\n if (el) el.focus({ preventScroll: true })\n else if (++frames < FOCUS_FRAMES) view?.requestAnimationFrame(tick)\n }\n view?.requestAnimationFrame(tick)\n}\n","// The live draft is `position:absolute; pointer-events:none` with left/top/width/height from\n// the drag: geometry only. Its look comes from the theme (`.ink-draft[data-ink-draft]`).\nimport {\n clampedCssIn,\n isViewportEnter,\n type PageHit,\n type Tool,\n type ToolContext,\n} from './controller'\n\n/** Smallest drag, in CSS px on each axis, that draws a box rather than counting as a click. */\nconst MIN_CSS = 3\n\nexport function redactAreaTool(): Tool {\n let ctx: ToolContext | undefined\n let start: PageHit | undefined\n let draft: HTMLElement | undefined\n\n /** Text redactions from the live selection, one per page. False when nothing is selected. */\n const fromSelection = (): boolean => {\n if (!ctx) return false\n const selections = ctx.selectionQuads()\n if (selections.length === 0) return false\n for (const s of selections)\n ctx.store.add({ type: 'redact', page: s.page, quads: s.quads })\n ctx.clearSelection()\n return true\n }\n\n const clear = (): void => {\n draft?.remove()\n draft = undefined\n start = undefined\n }\n\n return {\n id: 'redact-area',\n cursor: 'crosshair',\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n if (!hit || annotationId !== undefined) return\n start = hit\n // Keeps the press from starting a text selection; an existing one survives for the\n // text-derived mode on pointerup.\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!start) return\n // No button down: the release was missed, so drop the draft. A host scrolled out of\n // the mounted range is gone with it.\n if (e.buttons === 0 || !start.host.isConnected) {\n clear()\n return\n }\n const css = clampedCssIn(start.host, e)\n if (!draft) {\n draft = start.host.ownerDocument.createElement('div')\n draft.className = 'ink-draft'\n draft.dataset.inkDraft = 'redact'\n draft.style.position = 'absolute'\n draft.style.pointerEvents = 'none'\n start.host.append(draft)\n }\n draft.style.left = `${Math.min(start.css.x, css.x)}px`\n draft.style.top = `${Math.min(start.css.y, css.y)}px`\n draft.style.width = `${Math.abs(css.x - start.css.x)}px`\n draft.style.height = `${Math.abs(css.y - start.css.y)}px`\n },\n onPointerCancel() {\n clear()\n },\n onPointerUp(e) {\n if (!ctx || !start) return\n if (!start.host.isConnected) {\n clear()\n return\n }\n const css = clampedCssIn(start.host, e)\n const width = Math.abs(css.x - start.css.x)\n const height = Math.abs(css.y - start.css.y)\n if (width >= MIN_CSS && height >= MIN_CSS) {\n const rect = start.transform.fromCssRect({\n left: Math.min(start.css.x, css.x),\n top: Math.min(start.css.y, css.y),\n width,\n height,\n })\n ctx.store.add({ type: 'redact', page: start.page, rect })\n } else {\n fromSelection()\n }\n clear()\n },\n onKeyDown(e) {\n // The keyboard path for text marks: select text, then Enter.\n if (!!ctx && isViewportEnter(e, ctx.root) && fromSelection()) e.preventDefault()\n },\n }\n}\n","// The marquee is `position:absolute; pointer-events:none` with left/top/width/height from the\n// drag, and a moving annotation is shown with a temporary `transform: translate(...)` on its\n// overlay element; a resizing one with `translate(...) scale(...)` from a `0 0` origin. All\n// are geometry; the marquee's look comes from the theme.\n//\n// Resize: a press on one of the overlay's corner handles (`[data-handle]`, drawn on a\n// selected, unlocked rect-shaped annotation) drags that CSS corner while the opposite one\n// stays put. The new box is converted back to user space once, on release, as one\n// `store.update` of `rect`. Neither side goes below 1 pt.\nimport { MIN_SIZE, hasRectGeometry, translated } from '../../model/annotations/edit'\nimport { rectFromPoints, rectsIntersect } from '../../model/geometry'\n\nimport { cssIn, type PageHit, type Tool, type ToolContext } from './controller'\n\nimport type { Point } from '../../model/geometry'\nimport type { CssRect } from '../transform'\n\ntype Corner = 'nw' | 'ne' | 'sw' | 'se'\nconst CORNERS: readonly string[] = ['nw', 'ne', 'sw', 'se']\n\n/** Pointer travel, CSS px, before a press on an annotation becomes a move. */\nconst DRAG_THRESHOLD = 3\n\ntype Mode =\n | { kind: 'idle' }\n | { kind: 'press'; id: string; start: PageHit }\n | { kind: 'move'; id: string; start: PageHit; el: HTMLElement | undefined }\n | { kind: 'marquee'; start: PageHit; el: HTMLElement; additive: boolean }\n | {\n kind: 'resize'\n id: string\n start: PageHit\n corner: Corner\n /** The annotation's CSS box when the press began. */\n box: CssRect\n el: HTMLElement | undefined\n }\n\nexport function selectTool(): Tool {\n let ctx: ToolContext | undefined\n let mode: Mode = { kind: 'idle' }\n\n const reset = (): void => {\n if (mode.kind === 'marquee') mode.el.remove()\n if ((mode.kind === 'move' || mode.kind === 'resize') && mode.el) {\n mode.el.style.transform = ''\n mode.el.style.transformOrigin = ''\n }\n mode = { kind: 'idle' }\n }\n\n return {\n id: 'select',\n cursor: 'default',\n activate(c) {\n ctx = c\n },\n deactivate() {\n reset()\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n if (!ctx || !hit) return\n reset()\n if (annotationId !== undefined) {\n const corner = handleOf(e.target)\n const a = corner === undefined ? undefined : ctx.store.get(annotationId)\n if (corner !== undefined && a && !a.locked && hasRectGeometry(a)) {\n // The annotation is already selected (it has handles): keep the overlay from\n // re-activating it.\n e.stopPropagation()\n e.preventDefault()\n const el =\n hit.host.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(annotationId)}\"]`\n ) ?? undefined\n mode = {\n kind: 'resize',\n id: annotationId,\n start: hit,\n corner,\n box: hit.transform.toCssRect(a.rect),\n el,\n }\n return true\n }\n if (e.shiftKey) {\n // Toggle membership ourselves; the overlay would replace the selection.\n e.stopPropagation()\n const selected = ctx.store.selection.get()\n ctx.store.select(\n selected.includes(annotationId)\n ? selected.filter((s) => s !== annotationId)\n : [...selected, annotationId]\n )\n return\n }\n // The overlay selects and activates it once this capture-phase handler returns.\n mode = { kind: 'press', id: annotationId, start: hit }\n e.preventDefault()\n return true\n }\n const el = hit.host.ownerDocument.createElement('div')\n el.className = 'ink-marquee'\n el.dataset.inkMarquee = ''\n el.style.cssText = `position:absolute;pointer-events:none;left:${hit.css.x}px;top:${hit.css.y}px;width:0;height:0;`\n hit.host.append(el)\n mode = { kind: 'marquee', start: hit, el, additive: e.shiftKey }\n if (!e.shiftKey) ctx.store.select([])\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!ctx || mode.kind === 'idle') return\n // No button down: the release was missed, so drop the gesture. So does a start host\n // that scrolling has unmounted.\n if (e.buttons === 0 || !mode.start.host.isConnected) {\n reset()\n return\n }\n const { start } = mode\n if (mode.kind === 'resize') {\n const { box, el } = mode\n const next = resizeCss(box, mode.corner, cornerAt(mode, e), minCss(start))\n if (el) {\n el.style.transformOrigin = '0 0'\n el.style.transform =\n `translate(${next.left - box.left}px, ${next.top - box.top}px) ` +\n `scale(${next.width / box.width}, ${next.height / box.height})`\n }\n return\n }\n const css = cssIn(start.host, e)\n const dx = css.x - start.css.x\n const dy = css.y - start.css.y\n if (mode.kind === 'press') {\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return\n const a = ctx.store.get(mode.id)\n if (!a || a.locked) {\n mode = { kind: 'idle' }\n return\n }\n const el =\n start.host.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(mode.id)}\"]`\n ) ?? undefined\n mode = { kind: 'move', id: mode.id, start, el }\n }\n if (mode.kind === 'move') {\n if (mode.el) mode.el.style.transform = `translate(${dx}px, ${dy}px)`\n return\n }\n mode.el.style.left = `${Math.min(start.css.x, css.x)}px`\n mode.el.style.top = `${Math.min(start.css.y, css.y)}px`\n mode.el.style.width = `${Math.abs(dx)}px`\n mode.el.style.height = `${Math.abs(dy)}px`\n },\n onPointerCancel() {\n reset()\n },\n onPointerUp(e) {\n if (!ctx) return\n const current = mode\n reset()\n if (current.kind !== 'idle' && !current.start.host.isConnected) return\n if (current.kind === 'move') {\n const { start } = current\n const end = start.transform.fromCss(cssIn(start.host, e))\n const a = ctx.store.get(current.id)\n if (a && !a.locked)\n ctx.store.update(\n a.id,\n translated(a, end.x - start.user.x, end.y - start.user.y)\n )\n } else if (current.kind === 'resize') {\n const { start, box } = current\n const next = resizeCss(box, current.corner, cornerAt(current, e), minCss(start))\n if (\n next.left === box.left &&\n next.top === box.top &&\n next.width === box.width &&\n next.height === box.height\n )\n return\n const a = ctx.store.get(current.id)\n if (!a || a.locked) return\n const r = start.transform.fromCssRect(next)\n ctx.store.update(a.id, {\n rect: {\n ...r,\n width: Math.max(MIN_SIZE, r.width),\n height: Math.max(MIN_SIZE, r.height),\n },\n })\n } else if (current.kind === 'marquee') {\n const { start } = current\n const box = rectFromPoints(\n start.user,\n start.transform.fromCss(cssIn(start.host, e))\n )\n if (box.width === 0 && box.height === 0) return\n const ids = ctx.store\n .byPage(start.page)\n .filter((a) => rectsIntersect(a.rect, box))\n .map((a) => a.id)\n ctx.store.select(\n current.additive ? [...new Set([...ctx.store.selection.get(), ...ids])] : ids\n )\n }\n },\n onKeyDown(e) {\n if (!ctx) return\n if (e.key === 'Escape') {\n reset()\n ctx.store.select([])\n return\n }\n if (e.key !== 'Delete' && e.key !== 'Backspace') return\n // A focused annotation's overlay element owns the key (it removes that one annotation\n // and prevents the default); deleting the selection too would double-handle it.\n if (e.defaultPrevented) return\n const target = e.target instanceof Element ? e.target : null\n if (\n target?.closest(\n '[data-annotation], input, textarea, [contenteditable]:not([contenteditable=\"false\"])'\n )\n )\n return\n for (const id of ctx.store.selection.get()) {\n if (ctx.store.get(id)?.locked !== true) ctx.store.remove(id)\n }\n },\n }\n}\n\n/** The corner of the resize handle a press landed on, if it landed on one. */\nfunction handleOf(target: EventTarget | null): Corner | undefined {\n if (!(target instanceof Element)) return undefined\n const corner = target.closest('[data-handle]')?.getAttribute('data-handle')\n return corner && CORNERS.includes(corner) ? (corner as Corner) : undefined\n}\n\n/**\n * Where the dragged corner is now: where it started plus the pointer's travel since the\n * press, kept on the page. Keeping the press's offset from the corner means a click on a\n * handle, with no drag, leaves the box as it was.\n */\nfunction cornerAt(\n mode: { start: PageHit; box: CssRect; corner: Corner },\n e: { clientX: number; clientY: number }\n): Point {\n const { start, box, corner } = mode\n const css = cssIn(start.host, e)\n const x = (corner[1] === 'w' ? box.left : box.left + box.width) + css.x - start.css.x\n const y = (corner[0] === 'n' ? box.top : box.top + box.height) + css.y - start.css.y\n const { cssWidth, cssHeight } = start.transform\n return {\n x: Math.min(Math.max(x, 0), cssWidth),\n y: Math.min(Math.max(y, 0), cssHeight),\n }\n}\n\n/** `MIN_SIZE` points as CSS px on the press's page. */\nfunction minCss(start: PageHit): number {\n return start.transform.toCssLength(MIN_SIZE)\n}\n\n/** `box` with its `corner` dragged to `p` and the opposite corner fixed, at least `min` a side. */\nfunction resizeCss(box: CssRect, corner: Corner, p: Point, min: number): CssRect {\n let left = box.left\n let top = box.top\n let right = box.left + box.width\n let bottom = box.top + box.height\n if (corner[1] === 'w') left = Math.min(p.x, right - min)\n else right = Math.max(p.x, left + min)\n if (corner[0] === 'n') top = Math.min(p.y, bottom - min)\n else bottom = Math.max(p.y, top + min)\n return { left, top, width: right - left, height: bottom - top }\n}\n","import type { Tool } from './controller'\n\n/** Reading only: text selection stays native and the overlay still selects annotations. */\nexport function viewTool(): Tool {\n return { id: 'view', cursor: 'auto', activate() {}, deactivate() {} }\n}\n","import {\n createToolController as createWith,\n type Tool,\n type ToolControllerOptions,\n type ToolController,\n} from './controller'\nimport { highlightTool } from './highlight'\nimport { noteTool } from './note'\nimport { redactAreaTool } from './redact-area'\nimport { selectTool } from './select'\nimport { viewTool } from './view'\n\nexport type {\n PageHit,\n Tool,\n ToolContext,\n ToolController,\n ToolControllerOptions,\n ToolId,\n} from './controller'\nexport { hitFor } from './controller'\nexport { highlightTool, noteTool, redactAreaTool, selectTool, viewTool }\n\n/** Fresh instances of every built-in tool. */\nexport function builtinTools(): Tool[] {\n return [viewTool(), selectTool(), highlightTool(), redactAreaTool(), noteTool()]\n}\n\n/** Listens on `ctx.root` and routes pointer and key events to the active tool. */\nexport function createToolController(\n opts: Omit<ToolControllerOptions, 'tools'> & { tools?: Tool[] }\n): ToolController {\n return createWith({ ...opts, tools: opts.tools ?? builtinTools() })\n}\n","// Vocabulary the framework packages share: labels, zoom levels and the props they hand to\n// host-rendered content. Core owns these so Vue and React cannot drift apart.\nimport type { ToolId } from './tools'\nimport type {\n Annotation,\n ConfidenceBucket,\n NoteAnnotation,\n RedactAnnotation,\n Suggestion,\n} from '../model/annotations/types'\n\n/** Accessible names of the built-in tools, as the toolbar buttons announce them. */\nexport const TOOL_LABELS: Readonly<Record<ToolId, string>> = {\n view: 'View',\n select: 'Select',\n highlight: 'Highlight',\n 'redact-area': 'Mark for redaction',\n note: 'Add note',\n}\n\n/** Zoom levels the zoom select offers, as scale factors. */\nexport const ZOOM_LEVELS: readonly number[] = [0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4]\n\n/** The overlay's per-annotation state, as on its `data-state` attribute. */\nexport type AnnotationState = 'idle' | 'hover' | 'selected'\n\n/**\n * What a host-rendered annotation receives: Vue's `annotation` slot and React's\n * `renderAnnotation`.\n */\nexport interface AnnotationSlotProps {\n annotation: Annotation\n state: AnnotationState\n locked: boolean\n select: () => void\n remove: () => void\n /** Turns a suggested redaction into the user's own. No-op for anything else. */\n accept: () => void\n /** Removes a suggested redaction. No-op for anything else. */\n dismiss: () => void\n}\n\n/** What a host-rendered note thread receives. */\nexport interface NotePopoverSlotProps {\n note: NoteAnnotation\n replies: Annotation[]\n reply: (text: string) => void\n update: (contents: string) => void\n remove: () => void\n close: () => void\n}\n\n/** What a host-rendered suggestion card receives. */\nexport interface SuggestionCardSlotProps {\n annotation: RedactAnnotation\n suggestion: Suggestion | undefined\n bucket: ConfidenceBucket | undefined\n accept: () => void\n dismiss: () => void\n close: () => void\n}\n","/** The overlay element drawn for annotation `id` under `root`, if it is in the DOM. */\nexport function annotationElementFor(root: ParentNode, id: string): HTMLElement | null {\n return root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`)\n}\n\n/**\n * Resolves the overlay element for `id` and keeps resolving while `root`'s subtree changes:\n * the overlay creates and removes these elements outside any framework (a page mounts as it\n * scrolls into view), so a popover anchored to one has to follow. Calls `onChange` once now\n * and again whenever the answer changes. The returned function stops observing.\n */\nexport function observeAnnotationElement(\n root: HTMLElement,\n id: string,\n onChange: (el: HTMLElement | null) => void\n): () => void {\n let last: HTMLElement | null | undefined\n const resolve = (): void => {\n const found = annotationElementFor(root, id)\n if (found === last) return\n last = found\n onChange(found)\n }\n resolve()\n const observer = new MutationObserver(resolve)\n observer.observe(root, { childList: true, subtree: true })\n return () => observer.disconnect()\n}\n","/*\n * Shared behaviour for popovers anchored to an overlay annotation element. There is no popover\n * trigger, so the primitive library's own focus return has nothing to return to.\n */\nimport { annotationElementFor } from './annotation-element'\n\n/**\n * A press that will activate an annotation is not a dismissal: the popover follows the\n * activation. Mirrors the overlay's rule: a press on the annotation element or on its drawn\n * shape activates; a press on a custom element's own content belongs to that content.\n */\nexport function shouldKeepOpenOnAnnotation(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n const annotation = target.closest('[data-annotation]')\n if (!annotation) return false\n return target === annotation || !annotation.hasAttribute('data-custom')\n}\n\nexport interface FocusReturnOptions {\n root: () => HTMLElement | null\n /** The activated annotation id when the popover closes. */\n activated: () => string | null\n}\n\nexport interface FocusReturn {\n /**\n * Call just before removing the anchor's annotation: remembers where focus goes instead,\n * the next annotation on the page in reading order (the next one matching `prefer`\n * first), else the previous one, else the scroll element.\n */\n beforeRemove(anchor: HTMLElement | null, prefer?: string): void\n /** The popover's close-auto-focus handler. Prevents the default and places focus itself. */\n onCloseAutoFocus(event: Event, anchor: HTMLElement | null): void\n}\n\nexport function createFocusReturn(opts: FocusReturnOptions): FocusReturn {\n let fallbacks: HTMLElement[] = []\n /** Set by `beforeRemove`: the close comes from removing the anchor's annotation. */\n let removing = false\n\n return {\n beforeRemove(anchor, prefer) {\n fallbacks = []\n removing = true\n // The overlay keeps its elements in reading order, so DOM order is reading order.\n const siblings = anchor?.parentElement\n ? [...anchor.parentElement.children].filter(\n (el): el is HTMLElement =>\n el instanceof HTMLElement && el.hasAttribute('data-annotation')\n )\n : []\n const i = anchor ? siblings.indexOf(anchor) : -1\n if (i >= 0) {\n const after = siblings.slice(i + 1)\n const preferred = prefer ? after.filter((el) => el.matches(prefer)) : []\n fallbacks.push(...preferred, ...after, ...siblings.slice(0, i).reverse())\n }\n },\n onCloseAutoFocus(event, anchor) {\n event.preventDefault()\n const plan = fallbacks\n const removed = removing\n fallbacks = []\n removing = false\n const root = opts.root()\n if (!root) return\n // Activation moved to another annotation that is on screen: its popover takes focus. An\n // id whose element is gone (the host removed it) does not count.\n const activated = opts.activated()\n if (activated !== null && annotationElementFor(root, activated)) return\n // The close can be reported more than once; focus already returned to the document stays.\n const active = root.ownerDocument.activeElement\n if (active && active !== root && root.contains(active)) return\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n // After a removal the anchor may still be connected (a controlled host has not applied\n // the change yet), but it is on its way out: go straight to what follows it.\n const candidates = removed ? [...plan, scroll] : [anchor, ...plan, scroll]\n candidates.find((el) => el?.isConnected)?.focus({ preventScroll: true })\n },\n }\n}\n","/*\n * The wiring every viewer needs: a viewport over the scroll element, page layers in each page\n * host it creates, page-error tracking, the tool controller and keyboard shortcuts. Framework\n * bindings and `createViewer` sit on top: they render their own chrome and get pages and\n * errors back through the callbacks.\n */\nimport { InkError, isInkError } from '../model/errors'\n\nimport { createPageMount, type PageLayer, type PageMount } from './page-mount'\nimport { getSelectionQuads } from './selection'\nimport { createToolController, type ToolController, type ToolId } from './tools'\nimport { createViewport, type Viewport, type ZoomValue } from './viewport'\nimport { attachViewportKeys } from './viewport-keys'\n\nimport type { LayoutMode } from './layout'\nimport type { PageTransform, ViewRotation } from './transform'\nimport type { InkDocument } from '../model/document'\nimport type { Point } from '../model/geometry'\n\n/** A user-space point on a page, used to put the scroll position back after a rebuild. */\ninterface ScrollAnchor {\n page: number\n user: Point\n /** Whether the vertical position is restored too, not only the horizontal one. */\n vertical: boolean\n}\n\nexport interface MountViewerOptions {\n container: HTMLElement\n document: InkDocument\n zoom?: ZoomValue\n page?: number\n mode?: LayoutMode\n rotation?: ViewRotation\n gap?: number\n buffer?: number\n tool?: ToolId\n /** Annotation content is rendered by the host (custom slots). Changing it needs `rebuild`. */\n customAnnotations?: boolean\n onActivate?(id: string): void\n /**\n * After every (re)build: subscribe to the new viewport and controller here. It fires inside\n * `mountViewer` before it returns, and after the build's `onPageMount` calls.\n */\n onBuild?(viewport: Viewport, tools: ToolController): void\n /**\n * The viewport mounts pages synchronously, so a build's `onPageMount` calls fire before its\n * `onBuild` (on the first build, before `mountViewer` returns). Do not read `engine.viewport`\n * or `engine.tools` here: during a rebuild they still point at the destroyed objects. Use\n * the arguments, or wait for `onBuild`.\n */\n onPageMount?(page: number, mount: PageMount, host: HTMLElement): void\n /** Same ordering rule as `onPageMount`: do not read `engine.viewport` or `engine.tools`. */\n onPageUnmount?(page: number): void\n /**\n * `error` when a page's canvas or text layer fails; `null` once every failed layer recovers.\n * Unmounting a failed page does not emit `null`: hosts that track errors by page must clear\n * them in `onPageUnmount`. Same ordering rule as `onPageMount`: do not read `engine.viewport`\n * or `engine.tools`.\n */\n onPageError?(page: number, error: InkError | null): void\n}\n\nexport interface ViewerEngine {\n readonly viewport: Viewport\n readonly tools: ToolController\n readonly pages: ReadonlyMap<number, PageMount>\n /**\n * Recreates the viewport for construction-only options, keeping zoom, page, mode, rotation\n * and tool. The scroll position is kept too: the user-space point at the top-left of the\n * visible area stays there. When that corner is in a gap rather than on a page, the page below\n * the gap lands where `scrollToPage` puts it, with the new gap above it.\n */\n rebuild(opts: { gap?: number; buffer?: number; customAnnotations?: boolean }): void\n destroy(): void\n}\n\nexport function mountViewer(opts: MountViewerOptions): ViewerEngine {\n const { container: el, document: doc } = opts\n const pages = new Map<number, PageMount>()\n let gap = opts.gap\n let buffer = opts.buffer\n let custom = opts.customAnnotations ?? false\n let viewport: Viewport\n let tools: ToolController\n let stopKeys: () => void = () => undefined\n let destroyed = false\n\n function mountPage(page: number, host: HTMLElement, transform: PageTransform): void {\n /** Layers that failed and have not rendered since; the error clears when this empties. */\n const failed = new Set<PageLayer>()\n let error: InkError | null = null\n const isCustom = custom\n const mount = createPageMount({\n document: doc,\n page,\n host,\n transform,\n store: doc.annotations,\n onActivate: (id) => opts.onActivate?.(id),\n isCustom: () => isCustom,\n onError: (cause, layer) => {\n failed.add(layer)\n // The first failure wins: a canvas and a text layer failing together report once.\n if (error) return\n error = isInkError(cause)\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n { page },\n cause\n )\n host.setAttribute('data-state', 'error')\n opts.onPageError?.(page, error)\n },\n onRendered: (layer) => {\n failed.delete(layer)\n if (!error || failed.size > 0) return\n error = null\n host.removeAttribute('data-state')\n opts.onPageError?.(page, null)\n },\n })\n pages.set(page, mount)\n opts.onPageMount?.(page, mount, host)\n }\n\n function unmountPage(page: number): void {\n const mount = pages.get(page)\n if (!mount) return\n pages.delete(page)\n opts.onPageUnmount?.(page)\n mount.destroy()\n }\n\n /** The client point at the top-left of the container's visible content area. */\n function viewTopLeft(): Point {\n const r = el.getBoundingClientRect()\n return { x: r.left + el.clientLeft, y: r.top + el.clientTop }\n }\n\n /** The client point of the pages element's top-left: the origin of the layout's page boxes. */\n function layoutOrigin(): Point | undefined {\n const pagesEl = el.querySelector<HTMLElement>(':scope > [data-ink-pages]')\n if (!pagesEl) return undefined\n const r = pagesEl.getBoundingClientRect()\n return { x: r.left, y: r.top }\n }\n\n /**\n * Where the view sits before a rebuild: the user-space point under the top-left of the\n * visible area, on the page whose box contains it. When the top of the view is in a gap or a\n * margin, only the horizontal position is kept, and the page lands where `scrollToPage` puts\n * it, the new gap above it (a view resting at a page boundary stays at that boundary).\n */\n function scrollAnchor(vp: Viewport): ScrollAnchor | undefined {\n const o = layoutOrigin()\n if (!o) return undefined\n const corner = viewTopLeft()\n const x = corner.x - o.x\n const y = corner.y - o.y\n const boxes = vp.layout.get().boxes\n const inside = boxes.find((b) => y >= b.top && y < b.top + b.height)\n // In a gap or margin: the page just below it, which the view reaches first. Past the\n // last page there is none, so the current page stands in.\n const box =\n inside ??\n boxes.find((b) => b.top > y) ??\n boxes.find((b) => b.index === vp.currentPage.get())\n if (!box) return undefined\n // Transforms are affine, so a point left or right of the page maps back exactly too.\n const user = vp.transformFor(box.index).fromCss({ x: x - box.left, y: y - box.top })\n return { page: box.index, user, vertical: inside !== undefined }\n }\n\n /** Scrolls so the anchor's point sits under the top-left of the visible area again. */\n function restoreScroll(vp: Viewport, anchor: ScrollAnchor): void {\n const o = layoutOrigin()\n const box = vp.layout.get().boxes.find((b) => b.index === anchor.page)\n if (!o || !box) return\n const css = vp.transformFor(anchor.page).toCss(anchor.user)\n const corner = viewTopLeft()\n el.scrollLeft += o.x + box.left + css.x - corner.x\n if (anchor.vertical) el.scrollTop += o.y + box.top + css.y - corner.y\n }\n\n function build(state: {\n zoom: ZoomValue\n page: number | undefined\n mode: LayoutMode | undefined\n rotation: ViewRotation | undefined\n tool: ToolId | undefined\n anchor?: ScrollAnchor | undefined\n }): void {\n const vp = createViewport({\n container: el,\n document: doc,\n zoom: state.zoom,\n ...(state.mode === undefined ? {} : { mode: state.mode }),\n ...(state.rotation === undefined ? {} : { rotation: state.rotation }),\n ...(gap === undefined ? {} : { gap }),\n ...(buffer === undefined ? {} : { buffer }),\n onMount: mountPage,\n onUpdate: (page, _host, transform) => pages.get(page)?.update(transform),\n onUnmount: unmountPage,\n })\n const tc = createToolController({\n ...(state.tool === undefined ? {} : { initial: state.tool }),\n ctx: {\n store: doc.annotations,\n viewport: vp,\n root: el,\n selectionQuads: () =>\n getSelectionQuads(el, (host) => {\n const page = Number(host.dataset.page)\n return { page, transform: vp.transformFor(page) }\n }),\n clearSelection: () =>\n el.ownerDocument.defaultView?.getSelection()?.removeAllRanges(),\n onActivate: (id) => opts.onActivate?.(id),\n },\n })\n viewport = vp\n tools = tc\n stopKeys = attachViewportKeys(el, { viewport: vp, pageCount: () => doc.pages.length })\n // A view resting in a gap lands on the page below it, not on the most visible page.\n // The scroll position resets on teardown, so the guard below must not skip a gap anchor.\n if (state.anchor && !state.anchor.vertical) vp.scrollToPage(state.anchor.page)\n else if (state.page !== undefined && state.page !== vp.currentPage.get())\n vp.scrollToPage(state.page)\n if (state.anchor) restoreScroll(vp, state.anchor)\n opts.onBuild?.(vp, tc)\n }\n\n function teardown(): void {\n stopKeys()\n tools.destroy()\n // The viewport unmounts every page it mounted, which destroys the page mounts.\n viewport.destroy()\n for (const page of [...pages.keys()]) unmountPage(page)\n }\n\n build({\n zoom: opts.zoom ?? 'fit-width',\n page: opts.page,\n mode: opts.mode,\n rotation: opts.rotation,\n tool: opts.tool,\n })\n\n return {\n get viewport() {\n return viewport\n },\n get tools() {\n return tools\n },\n pages,\n rebuild(next) {\n if (destroyed) return\n const state = {\n zoom: viewport.zoom.get(),\n page: viewport.currentPage.get(),\n mode: viewport.mode.get(),\n rotation: viewport.rotation.get(),\n tool: tools.active.get(),\n anchor: scrollAnchor(viewport),\n }\n teardown()\n if (next.gap !== undefined) gap = next.gap\n if (next.buffer !== undefined) buffer = next.buffer\n if (next.customAnnotations !== undefined) custom = next.customAnnotations\n build(state)\n },\n destroy() {\n if (destroyed) return\n destroyed = true\n teardown()\n },\n }\n}\n","/** `document.createElement` with attributes and children. */\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n ...children: (Node | string)[]\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag)\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value)\n el.append(...children)\n return el\n}\n\nexport function button(label: string, onClick: () => void): HTMLButtonElement {\n const b = h('button', { type: 'button' }, label)\n b.addEventListener('click', onClick)\n return b\n}\n","/*\n * A panel anchored to an annotation's overlay element, shared by the note thread and the\n * suggestion card. The overlay creates and removes those elements as pages mount and unmount,\n * so the panel follows the element by id: a replaced element re-anchors it, and while the\n * element is gone (its page scrolled out) the panel hides but stays logically open.\n */\nimport { observeAnnotationElement } from '../annotation-element'\nimport { shouldKeepOpenOnAnnotation, type FocusReturn } from '../popover-focus'\n\nimport { h } from './dom'\n\n/** Space between the anchor and the panel, and between the panel and the window edge. */\nconst GAP = 6\nconst MARGIN = 8\nconst TABBABLE = 'button, input, select, textarea, a[href], [tabindex]'\n\nexport interface PopoverOptions {\n /** The viewer root: anchors are looked up and focus returns inside it. */\n root: HTMLElement\n attrs: Record<string, string>\n focusReturn: FocusReturn\n /** Escape, or a press outside that will not activate an annotation. */\n onDismiss(): void\n}\n\nexport interface Popover {\n readonly panel: HTMLElement\n /** The anchor element, or null while it is not in the DOM. */\n readonly anchor: HTMLElement | null\n /** Anchors to annotation `id`. The panel shows whenever its element is in the DOM. */\n show(id: string): void\n /** Hides the panel and returns focus the way the bindings do. */\n hide(): void\n destroy(): void\n}\n\nexport function createPopover(opts: PopoverOptions): Popover {\n const { root, focusReturn } = opts\n const panel = h('div', { ...opts.attrs, role: 'dialog', hidden: '' })\n document.body.append(panel)\n let anchoredId: string | null = null\n let anchor: HTMLElement | null = null\n let stopObserving: () => void = () => undefined\n /** The element that had focus in the panel when the anchor went away. */\n let stranded: HTMLElement | null = null\n\n const place = (): void => {\n if (!anchor || panel.hidden) return\n const r = anchor.getBoundingClientRect()\n const { innerWidth: vw, innerHeight: vh } = window\n const w = panel.offsetWidth\n const ht = panel.offsetHeight\n // Below the anchor; above it when only that fits; clamped to the window either way.\n let top = r.bottom + GAP\n if (top + ht > vh - MARGIN && r.top - GAP - ht >= MARGIN) top = r.top - GAP - ht\n top = Math.max(MARGIN, Math.min(top, vh - ht - MARGIN))\n const left = Math.max(MARGIN, Math.min(r.left, vw - w - MARGIN))\n panel.style.position = 'fixed'\n panel.style.left = `${left}px`\n panel.style.top = `${top}px`\n }\n\n // The anchor changes size on zoom; the panel when its content changes.\n const resizes = new ResizeObserver(place)\n resizes.observe(panel)\n\n const onAnchor = (el: HTMLElement | null, closing = false): void => {\n if (anchor) resizes.unobserve(anchor)\n anchor = el\n if (!el) {\n const active = document.activeElement\n if (\n !closing &&\n !panel.hidden &&\n active instanceof HTMLElement &&\n panel.contains(active)\n ) {\n // Hiding the panel would drop focus to the body: keep the keyboard in the viewer.\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n if (scroll) {\n stranded = active\n scroll.focus({ preventScroll: true })\n }\n }\n panel.hidden = true\n return\n }\n resizes.observe(el)\n const wasHidden = panel.hidden\n panel.hidden = false\n place()\n if (wasHidden && stranded) {\n const back = stranded\n stranded = null\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n if (panel.contains(back) && document.activeElement === scroll)\n back.focus({ preventScroll: true })\n }\n }\n\n const onKey = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape' || panel.hidden || e.defaultPrevented) return\n // An Escape meant for a host's own dialog elsewhere on the page is not ours.\n const target = e.target\n if (!(target instanceof Node) || !(panel.contains(target) || root.contains(target)))\n return\n e.preventDefault()\n opts.onDismiss()\n }\n const onPress = (e: PointerEvent): void => {\n if (panel.hidden || panel.contains(e.target as Node)) return\n // A press that will activate an annotation hands over to it instead of closing.\n if (shouldKeepOpenOnAnnotation(e.target)) return\n opts.onDismiss()\n }\n // Focus loops inside the panel, as the bindings' non-modal popovers do.\n const onTab = (e: KeyboardEvent): void => {\n if (e.key !== 'Tab' || e.altKey || e.ctrlKey || e.metaKey) return\n const tabbable = [...panel.querySelectorAll<HTMLElement>(TABBABLE)].filter(\n (el) => !(el as HTMLButtonElement).disabled && el.tabIndex >= 0\n )\n const first = tabbable[0]\n const last = tabbable.at(-1)\n if (!first || !last) return\n const active = document.activeElement\n if (e.shiftKey ? active !== first : active !== last) return\n e.preventDefault()\n ;(e.shiftKey ? last : first).focus()\n }\n panel.addEventListener('keydown', onTab)\n document.addEventListener('keydown', onKey)\n document.addEventListener('pointerdown', onPress, true)\n // The viewer's scroll element and any scrolling ancestor in the host page.\n document.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n\n return {\n panel,\n get anchor() {\n return anchor\n },\n show(id) {\n if (id === anchoredId) return\n stopObserving()\n anchoredId = id\n stopObserving = observeAnnotationElement(root, id, onAnchor)\n },\n hide() {\n if (anchoredId === null) return\n stopObserving()\n stopObserving = () => undefined\n anchoredId = null\n const back = anchor\n stranded = null\n onAnchor(null, true)\n // After the change that closed the popover has settled (a removed anchor is out of the\n // DOM, a cleared activation is cleared), as the bindings' close-auto-focus runs after\n // their render. A popover reopened meanwhile keeps focus where it is.\n queueMicrotask(() => {\n if (anchoredId !== null || !panel.isConnected) return\n focusReturn.onCloseAutoFocus(\n new Event('closeautofocus', { cancelable: true }),\n back\n )\n })\n },\n destroy() {\n stopObserving()\n resizes.disconnect()\n document.removeEventListener('keydown', onKey)\n document.removeEventListener('pointerdown', onPress, true)\n panel.removeEventListener('keydown', onTab)\n document.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n panel.remove()\n },\n }\n}\n","/*\n * The thread for the activated note, anchored to the note's overlay element. Activating a\n * reply opens the whole thread from its root. Closing (Close, Escape, a press outside) clears\n * the activation.\n *\n * A new note has no text. While its root is empty (and unlocked) the form writes the root's\n * own `contents`, labelled \"Comment\", and the thread list stays hidden until there is\n * something in it; after that the form adds replies. A root closed, or left for another\n * annotation, while still empty and without replies is removed. The thread list re-renders on\n * every store change; the form, and the draft in it, stays until the popover moves to another\n * note or the note is gone.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '../../model/annotations/threads'\n\nimport { button, h } from './dom'\nimport { createPopover } from './popover'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Annotation, NoteAnnotation } from '../../model/annotations/types'\nimport type { Writable } from '../../model/readable'\nimport type { FocusReturn } from '../popover-focus'\n\nexport interface NotePopoverOptions {\n root: HTMLElement\n store: AnnotationStore\n activated: Writable<string | null>\n focusReturn: FocusReturn\n}\n\nexport function createNotePopover(opts: NotePopoverOptions): { destroy(): void } {\n const { root, store, activated, focusReturn } = opts\n const popover = createPopover({\n root,\n attrs: {\n class: 'ink-note-popover',\n 'data-ink-note-popover': '',\n 'aria-label': 'Note thread',\n },\n focusReturn,\n onDismiss: close,\n })\n const thread = h('ol', { class: 'ink-thread', 'data-ink-thread': '' })\n let form: ThreadForm | null = null\n /** The root note shown now. */\n let current: string | null = null\n /** Notes given text or a reply here: never dropped as abandoned. */\n const written = new Set<string>()\n /** Notes already removed from here, so they are not removed twice. */\n const dropped = new Set<string>()\n\n function shown(): NoteAnnotation | null {\n const a = current ? store.get(current) : undefined\n return a?.type === 'note' ? a : null\n }\n\n function target(): NoteAnnotation | null {\n const list = store.list.get()\n const id = activated.get()\n const a = id === null ? undefined : list.find((x) => x.id === id)\n return a?.type === 'note' ? threadRoot(list, a) : null\n }\n\n const editingRoot = (n: NoteAnnotation): boolean => !n.locked && !n.contents?.trim()\n\n function isEmptyRoot(n: NoteAnnotation): boolean {\n return (\n !written.has(n.id) && editingRoot(n) && threadOf(store.list.get(), n).length === 1\n )\n }\n\n function dropIfEmpty(id: string): void {\n if (dropped.has(id) || written.has(id) || !isAbandonedNote(store.list.get(), id))\n return\n dropped.add(id)\n store.remove(id)\n }\n\n function renderThread(n: NoteAnnotation): void {\n const items = threadOf(store.list.get(), n)\n if (editingRoot(n) && items.length === 1) {\n thread.remove()\n return\n }\n thread.replaceChildren(...items.map(threadItem))\n if (!thread.isConnected) popover.panel.prepend(thread)\n }\n\n function update(): void {\n const n = target()\n const id = n?.id ?? null\n if (id === current) {\n if (n && form) {\n renderThread(n)\n form.sync(n)\n }\n return\n }\n const previous = current\n current = id\n if (n) {\n const hadFocus = popover.panel.contains(document.activeElement)\n const opening = popover.panel.hidden\n form = createThreadForm(n, { submit, remove: removeThread, close })\n popover.panel.replaceChildren(form.element)\n renderThread(n)\n popover.show(n.id)\n if ((opening || hadFocus) && !popover.panel.hidden) form.textarea.focus()\n } else {\n form = null\n popover.hide()\n }\n // Activation moved on from a note that never got any text: drop it. This can re-enter\n // `update`, which finds `current` already settled.\n if (previous !== null) dropIfEmpty(previous)\n }\n\n function submit(text: string): void {\n const n = shown()\n if (!n) return\n written.add(n.id)\n if (editingRoot(n)) store.update(n.id, { contents: text })\n else\n store.add({\n type: 'note',\n page: n.page,\n rect: n.rect,\n contents: text,\n inReplyTo: n.id,\n })\n }\n\n /** Locked notes cannot be removed: Delete is not offered for them. */\n function removeThread(): void {\n const n = shown()\n if (!n || n.locked) return\n focusReturn.beforeRemove(popover.anchor)\n dropped.add(n.id)\n store.remove(n.id)\n activated.set(null)\n }\n\n function close(): void {\n const n = shown()\n if (n && isEmptyRoot(n)) focusReturn.beforeRemove(popover.anchor)\n // `update` hides the popover and drops the note if it is still empty.\n activated.set(null)\n }\n\n const stops = [store.list.subscribe(update), activated.subscribe(update)]\n update()\n\n return {\n destroy() {\n for (const stop of stops) stop()\n popover.destroy()\n },\n }\n}\n\nfunction threadItem(a: Annotation): HTMLLIElement {\n return h(\n 'li',\n {\n class: 'ink-thread-item',\n 'data-ink-thread-item': '',\n ...(a.inReplyTo ? { 'data-reply': '' } : {}),\n },\n h('span', { class: 'ink-thread-author' }, a.author ?? 'Anonymous'),\n h(\n 'time',\n { class: 'ink-thread-time', datetime: a.createdAt },\n new Date(a.createdAt).toLocaleString()\n ),\n h('p', { class: 'ink-thread-text' }, a.contents ?? '')\n )\n}\n\ninterface ThreadForm {\n readonly element: HTMLFormElement\n readonly textarea: HTMLTextAreaElement\n /** Follows the note's state: \"Comment\" while its own text is empty, \"Reply\" after. */\n sync(n: NoteAnnotation): void\n}\n\nfunction createThreadForm(\n n: NoteAnnotation,\n actions: { submit: (text: string) => void; remove: () => void; close: () => void }\n): ThreadForm {\n const textarea = h('textarea', { rows: '2' })\n const send = h('button', { type: 'submit' })\n const remove = button('Delete', actions.remove)\n const actionRow = h(\n 'div',\n { class: 'ink-thread-actions' },\n send,\n remove,\n button('Close', actions.close)\n )\n const element = h(\n 'form',\n { class: 'ink-thread-reply', 'data-ink-thread-reply': '' },\n textarea,\n actionRow\n )\n const syncSend = (): void => {\n send.disabled = !textarea.value.trim()\n }\n textarea.addEventListener('input', syncSend)\n element.addEventListener('submit', (e) => {\n e.preventDefault()\n const text = textarea.value.trim()\n if (!text) return\n // Cleared first: the store change re-renders the thread straight away.\n textarea.value = ''\n syncSend()\n actions.submit(text)\n })\n\n function sync(note: NoteAnnotation): void {\n const label = !note.locked && !note.contents?.trim() ? 'Comment' : 'Reply'\n textarea.setAttribute('aria-label', label)\n textarea.placeholder = label\n send.textContent = label\n if (note.locked) remove.remove()\n else if (!remove.isConnected) send.after(remove)\n }\n sync(n)\n syncSend()\n return { element, textarea, sync }\n}\n","/*\n * Review card for a suggested redaction: opens when the activated annotation, or the only\n * selected one (a marquee selects without activating), is a redaction with\n * `origin: 'suggested'`. It closes when that stops being true: accepted, dismissed, or removed\n * some other way (an undo). Locked suggestions cannot be dismissed, so they get no Dismiss\n * button. Closing clears the activation and the selection.\n */\nimport { acceptSuggestion } from '../../model/annotations/suggestions'\nimport { confidenceBucket } from '../../model/annotations/types'\n\nimport { button, h } from './dom'\nimport { createPopover } from './popover'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { RedactAnnotation } from '../../model/annotations/types'\nimport type { Writable } from '../../model/readable'\nimport type { FocusReturn } from '../popover-focus'\n\nexport interface SuggestionCardOptions {\n root: HTMLElement\n store: AnnotationStore\n activated: Writable<string | null>\n focusReturn: FocusReturn\n}\n\nexport function createSuggestionCard(opts: SuggestionCardOptions): { destroy(): void } {\n const { root, store, activated, focusReturn } = opts\n const popover = createPopover({\n root,\n attrs: {\n class: 'ink-suggestion-card',\n 'data-ink-suggestion-card': '',\n 'aria-label': 'Suggested redaction',\n },\n focusReturn,\n onDismiss: close,\n })\n /** The suggestion as last rendered. */\n let shown: RedactAnnotation | null = null\n\n function suggestion(id: string | null | undefined): RedactAnnotation | null {\n const a = id ? store.get(id) : undefined\n return a?.type === 'redact' && a.origin === 'suggested' ? a : null\n }\n\n function target(): RedactAnnotation | null {\n const selection = store.selection.get()\n return (\n suggestion(activated.get()) ??\n (selection.length === 1 ? suggestion(selection[0]) : null)\n )\n }\n\n function update(): void {\n const t = target()\n if (t === shown) return\n const previous = shown\n shown = t\n if (!t) {\n popover.hide()\n return\n }\n const hadFocus = popover.panel.contains(document.activeElement)\n const opening = previous === null || previous.id !== t.id\n render(t)\n popover.show(t.id)\n if ((opening || hadFocus) && !popover.panel.hidden)\n popover.panel.querySelector('button')?.focus()\n }\n\n function render(a: RedactAnnotation): void {\n const { suggestion: s } = a\n const bucket = s ? confidenceBucket(s.confidence) : undefined\n popover.panel.replaceChildren(\n h(\n 'p',\n { class: 'ink-suggestion-reason' },\n h('strong', {}, s?.reason ?? 'Suggested redaction'),\n ...(bucket\n ? [\n h(\n 'span',\n { class: 'ink-suggestion-confidence', 'data-confidence': bucket },\n `${bucket} confidence`\n ),\n ]\n : [])\n ),\n ...(s?.explanation\n ? [h('p', { class: 'ink-suggestion-explanation' }, s.explanation)]\n : []),\n h(\n 'div',\n { class: 'ink-suggestion-actions' },\n button('Accept', accept),\n ...(a.locked ? [] : [button('Dismiss', dismiss)])\n )\n )\n }\n\n function close(): void {\n activated.set(null)\n store.select([])\n }\n\n function accept(): void {\n if (shown) acceptSuggestion(store, shown.id)\n close()\n }\n\n /** Locked annotations cannot be removed: Dismiss is not offered for them. */\n function dismiss(): void {\n if (!shown || shown.locked) return\n focusReturn.beforeRemove(popover.anchor, '[data-origin=\"suggested\"]')\n store.remove(shown.id)\n close()\n }\n\n const stops = [\n store.list.subscribe(update),\n store.selection.subscribe(update),\n activated.subscribe(update),\n ]\n update()\n\n return {\n destroy() {\n for (const stop of stops) stop()\n popover.destroy()\n },\n }\n}\n","/*\n * The toolbar's icons, inlined from Lucide (https://lucide.dev, ISC licence; Square, ZoomIn\n * and ZoomOut derive from Feather, MIT). The notices are in this package's LICENSE. Inlined so\n * core has no runtime dependency.\n */\ntype IconNode = readonly (readonly [\n tag: string,\n attrs: Readonly<Record<string, string>>,\n])[]\n\nconst ICONS = {\n hand: [\n ['path', { d: 'M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2' }],\n ['path', { d: 'M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2' }],\n ['path', { d: 'M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8' }],\n [\n 'path',\n {\n d: 'M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15',\n },\n ],\n ],\n 'mouse-pointer-2': [\n [\n 'path',\n {\n d: 'M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z',\n },\n ],\n ],\n highlighter: [\n ['path', { d: 'm9 11-6 6v3h9l3-3' }],\n ['path', { d: 'm22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4' }],\n ],\n square: [['rect', { width: '18', height: '18', x: '3', y: '3', rx: '2' }]],\n 'message-square': [\n [\n 'path',\n {\n d: 'M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z',\n },\n ],\n ],\n 'zoom-in': [\n ['circle', { cx: '11', cy: '11', r: '8' }],\n ['line', { x1: '21', x2: '16.65', y1: '21', y2: '16.65' }],\n ['line', { x1: '11', x2: '11', y1: '8', y2: '14' }],\n ['line', { x1: '8', x2: '14', y1: '11', y2: '11' }],\n ],\n 'zoom-out': [\n ['circle', { cx: '11', cy: '11', r: '8' }],\n ['line', { x1: '21', x2: '16.65', y1: '21', y2: '16.65' }],\n ['line', { x1: '8', x2: '14', y1: '11', y2: '11' }],\n ],\n} satisfies Record<string, IconNode>\n\nexport type IconName = keyof typeof ICONS\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\n/** An 18px Lucide icon, hidden from assistive technology: its button carries the name. */\nexport function icon(name: IconName): SVGElement {\n const svg = document.createElementNS(SVG, 'svg')\n const attrs: Record<string, string> = {\n xmlns: SVG,\n width: '18',\n height: '18',\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-width': '2',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n 'aria-hidden': 'true',\n }\n for (const [k, v] of Object.entries(attrs)) svg.setAttribute(k, v)\n for (const [tag, shape] of ICONS[name] as IconNode) {\n const child = document.createElementNS(SVG, tag)\n for (const [k, v] of Object.entries(shape)) child.setAttribute(k, v)\n svg.append(child)\n }\n return svg\n}\n","/*\n * The default toolbar: tools, zoom and page, with the classes and data attributes of the\n * bindings' DefaultToolbar so the theme styles it. It follows the WAI-ARIA toolbar pattern:\n * the buttons share one Tab stop with arrow keys, Home and End (host-added buttons included),\n * and the zoom select and page input are Tab stops of their own, as in the bindings.\n *\n * The element outlives any one document, so a host can add controls once: `bind` points the\n * controls at a document's viewport and tool controller (again after every engine rebuild),\n * and `unbind` disables them while nothing is open.\n */\nimport { TOOL_LABELS, ZOOM_LEVELS } from '../ui'\n\nimport { h } from './dom'\nimport { icon, type IconName } from './icons'\n\nimport type { InkDocument } from '../../model/document'\nimport type { Readable } from '../../model/readable'\nimport type { ToolController, ToolId } from '../tools'\nimport type { Viewport } from '../viewport'\n\nconst TOOLS: [ToolId, IconName][] = [\n ['view', 'hand'],\n ['select', 'mouse-pointer-2'],\n ['highlight', 'highlighter'],\n ['redact-area', 'square'],\n ['note', 'message-square'],\n]\n\nexport interface DefaultToolbar {\n readonly element: HTMLElement\n /** Drives `viewport` and `tools` for `doc`. Call again after every rebuild. */\n bind(doc: InkDocument, viewport: Viewport, tools: ToolController): void\n /** No document: the controls are disabled. */\n unbind(): void\n destroy(): void\n}\n\n/** A toolbar button with an icon; the label is its accessible name and tooltip. */\nfunction iconButton(\n label: string,\n attrs: Record<string, string>,\n name: IconName,\n onClick: () => void\n): HTMLButtonElement {\n const b = h('button', { type: 'button', ...attrs, 'aria-label': label, title: label })\n b.append(icon(name))\n b.addEventListener('click', onClick)\n return b\n}\n\nconst group = (name: string, label: string, ...children: Node[]): HTMLElement =>\n h(\n 'div',\n {\n class: 'ink-toolbar-group',\n 'data-ink-toolbar-group': name,\n role: 'group',\n 'aria-label': label,\n },\n ...children\n )\n\nexport function createToolbar(): DefaultToolbar {\n let stops: (() => void)[] = []\n let bound: { doc: InkDocument; viewport: Viewport; tools: ToolController } | null = null\n const watch = <T>(r: Readable<T>, fn: (value: T) => void): void => {\n fn(r.get())\n stops.push(r.subscribe(fn))\n }\n\n const toolButtons = TOOLS.map(([id, name]) =>\n iconButton(\n TOOL_LABELS[id],\n { class: 'ink-tool-button', 'data-ink-tool-button': '', 'data-tool': id },\n name,\n () => bound?.tools.set(id)\n )\n )\n const showTool = (active: ToolId | null): void => {\n for (const b of toolButtons) {\n const on = b.dataset.tool === active\n b.dataset.state = on ? 'on' : 'off'\n b.setAttribute('aria-pressed', String(on))\n }\n }\n\n const zoomOut = iconButton(\n 'Zoom out',\n { class: 'ink-zoom-out', 'data-ink-zoom-out': '' },\n 'zoom-out',\n () => bound?.viewport.zoomBy(0.8)\n )\n const zoomIn = iconButton(\n 'Zoom in',\n { class: 'ink-zoom-in', 'data-ink-zoom-in': '' },\n 'zoom-in',\n () => bound?.viewport.zoomBy(1.25)\n )\n\n // A zoom that is not one of the levels (the buttons multiply) gets an option of its own.\n const custom = h('option', { value: 'custom' })\n const zoomSelect = h(\n 'select',\n { class: 'ink-zoom-select', 'data-ink-zoom-select': '', 'aria-label': 'Zoom' },\n h('option', { value: 'fit-width' }, 'Fit width'),\n h('option', { value: 'fit-page' }, 'Fit page'),\n ...ZOOM_LEVELS.map((l) =>\n h('option', { value: String(l) }, `${Math.round(l * 100)}%`)\n )\n )\n zoomSelect.addEventListener('change', () => {\n const v = zoomSelect.value\n if (v === 'fit-width' || v === 'fit-page') bound?.viewport.setZoom(v)\n else if (v !== 'custom') bound?.viewport.setZoom(Number(v))\n })\n\n // 1-based in the input, 0-based in the viewport. Out of range resets to the current page.\n const pageInput = h('input', {\n class: 'ink-page-input',\n 'data-ink-page-input': '',\n type: 'number',\n inputmode: 'numeric',\n 'aria-label': 'Page',\n min: '1',\n })\n const commitPage = (): void => {\n if (!bound) return\n const { viewport } = bound\n const n = Number(pageInput.value)\n const current = viewport.currentPage.get()\n if (Number.isInteger(n) && n >= 1 && n <= bound.doc.pages.length) {\n if (n - 1 !== current) viewport.scrollToPage(n - 1)\n } else pageInput.value = String(current + 1)\n }\n // `change` fires on blur after typing and on each arrow-key or spinner step.\n pageInput.addEventListener('change', commitPage)\n pageInput.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' || e.defaultPrevented) return\n e.preventDefault()\n commitPage()\n })\n const pageCount = h('span', {\n class: 'ink-page-count',\n 'data-ink-page-count': '',\n 'aria-live': 'polite',\n })\n\n const controls = [...toolButtons, zoomOut, zoomSelect, zoomIn, pageInput]\n const element = h(\n 'div',\n {\n class: 'ink-toolbar ink-default-toolbar',\n 'data-ink-toolbar': '',\n 'data-ink-default-toolbar': '',\n role: 'toolbar',\n 'aria-label': 'Document tools',\n 'aria-orientation': 'horizontal',\n },\n group('tools', 'Tools', ...toolButtons),\n group('zoom', 'Zoom', zoomOut, zoomSelect, zoomIn),\n group('page', 'Page', pageInput, pageCount)\n )\n const roving = rovingTabindex(element)\n\n function stop(): void {\n for (const s of stops) s()\n stops = []\n bound = null\n }\n\n function unbind(): void {\n stop()\n for (const c of controls) c.disabled = true\n showTool(null)\n custom.remove()\n zoomSelect.value = 'fit-width'\n pageInput.value = ''\n pageCount.textContent = ''\n roving.sync()\n }\n\n unbind()\n\n return {\n element,\n bind(doc, viewport, tools) {\n // Not `unbind`: disabling the focused control would drop focus during a rebuild.\n stop()\n bound = { doc, viewport, tools }\n for (const c of controls) c.disabled = false\n watch(tools.active, showTool)\n watch(viewport.zoom, (z) => {\n const level =\n typeof z === 'number'\n ? ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\n : undefined\n if (typeof z === 'number' && level === undefined) {\n custom.textContent = `${Math.round(z * 100)}%`\n zoomSelect.append(custom)\n zoomSelect.value = 'custom'\n } else {\n custom.remove()\n zoomSelect.value = typeof z === 'number' ? String(level) : z\n }\n })\n const count = doc.pages.length\n pageInput.max = String(count)\n pageCount.textContent = `of ${count}`\n watch(viewport.currentPage, (p) => {\n pageInput.value = String(p + 1)\n })\n roving.sync()\n },\n unbind,\n destroy() {\n stop()\n roving.destroy()\n element.remove()\n },\n }\n}\n\n/** Roving items, as in the bindings' Radix toolbar: buttons only. */\nconst ITEMS = 'button'\n\n/**\n * One Tab stop across the enabled buttons in `bar`: the current one has `tabindex=\"0\"`, the\n * rest `-1`. ArrowLeft and ArrowRight move between them and wrap, Home and End go to the ends.\n * Inputs, selects and textareas, built in or added by the host, keep their own tabindex (a\n * Tab stop of their own by default) and their own arrow, Home and End keys.\n */\nfunction rovingTabindex(bar: HTMLElement): { sync(): void; destroy(): void } {\n let current: HTMLElement | null = null\n const items = (): HTMLElement[] =>\n [...bar.querySelectorAll<HTMLButtonElement>(ITEMS)].filter(\n (el) => !el.disabled && !el.closest('[hidden]')\n )\n const sync = (): void => {\n const list = items()\n if (!current || !list.includes(current)) current = list[0] ?? null\n for (const el of bar.querySelectorAll<HTMLElement>(ITEMS))\n el.tabIndex = el === current ? 0 : -1\n // Fields are left alone: they are Tab stops by default, and a host's tabindex on one stays.\n }\n const onFocusIn = (e: FocusEvent): void => {\n const target = e.target as HTMLElement\n if (!items().includes(target)) return\n current = target\n sync()\n }\n const onKeyDown = (e: KeyboardEvent): void => {\n if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey) return\n const list = items()\n const i = list.indexOf(e.target as HTMLElement)\n if (i < 0) return\n const last = list.length - 1\n const next =\n e.key === 'ArrowRight'\n ? i === last\n ? 0\n : i + 1\n : e.key === 'ArrowLeft'\n ? i === 0\n ? last\n : i - 1\n : e.key === 'Home'\n ? 0\n : e.key === 'End'\n ? last\n : -1\n if (next < 0) return\n e.preventDefault()\n list[next]!.focus()\n }\n // Host-added buttons, and buttons a host enables or disables, join the rotation.\n const observer = new MutationObserver(sync)\n observer.observe(bar, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['disabled', 'hidden'],\n })\n bar.addEventListener('focusin', onFocusIn)\n bar.addEventListener('keydown', onKeyDown)\n sync()\n return {\n sync,\n destroy() {\n observer.disconnect()\n bar.removeEventListener('focusin', onFocusIn)\n bar.removeEventListener('keydown', onKeyDown)\n },\n }\n}\n","/*\n * A complete viewer without a framework: opens a document, mounts the engine and renders a\n * default toolbar, note thread and suggestion card around it, with the bindings' markup so\n * `@inkbar/theme` styles it unchanged. Each piece of UI can be left out.\n */\nimport {\n cssVariableDefaults,\n type AnnotationDefaults,\n} from '../../model/annotations/defaults'\nimport {\n openDocument,\n type InkDocument,\n type InkStatus,\n type OpenOptions,\n} from '../../model/document'\nimport { InkError, isInkError } from '../../model/errors'\nimport { readonly, writable, type Readable } from '../../model/readable'\nimport { createFocusReturn } from '../popover-focus'\nimport { mountViewer, type MountViewerOptions, type ViewerEngine } from '../viewer-engine'\n\nimport { h } from './dom'\nimport { createNotePopover } from './note-popover'\nimport { createSuggestionCard } from './suggestion-card'\nimport { createToolbar } from './toolbar'\n\nimport type { DocumentSource } from '../../model/source'\nimport type { PdfAssets } from '../../pdfjs/types'\n\nexport interface CreateViewerOptions extends Omit<\n MountViewerOptions,\n 'container' | 'document'\n> {\n source: DocumentSource\n assets: PdfAssets\n /** User password for encrypted files. `open` can pass its own for one load. */\n password?: string\n /** Default: read from the theme's CSS variables on the viewer root. */\n defaults?: AnnotationDefaults\n history?: OpenOptions['history']\n /** Default toolbar: tools, zoom, page. `false` leaves it out. */\n toolbar?: boolean\n /** Note thread popover. Default true. */\n notes?: boolean\n /** Suggested-redaction card. Default true. */\n suggestions?: boolean\n onReady?(this: void, doc: InkDocument): void\n onError?(this: void, error: InkError): void\n}\n\nexport interface Viewer {\n /** The root element (`[data-ink-root]`) the viewer rendered into the host element. */\n readonly element: HTMLElement\n readonly status: Readable<InkStatus>\n readonly document: Readable<InkDocument | null>\n /** Set while a document is ready; `null` otherwise. */\n readonly engine: Readable<ViewerEngine | null>\n /** The toolbar element, for adding controls. `null` when `toolbar: false`. */\n readonly toolbar: HTMLElement | null\n /**\n * Opens another document in place; the previous one is destroyed. Latest call wins.\n * `password` is used for this load only; without it, the constructor's `password` applies.\n */\n open(source: DocumentSource, opts?: { password?: string }): void\n destroy(): void\n}\n\nexport function createViewer(el: HTMLElement, opts: CreateViewerOptions): Viewer {\n const {\n source: initial,\n assets,\n password,\n defaults,\n history,\n toolbar: withToolbar = true,\n notes: withNotes = true,\n suggestions: withSuggestions = true,\n onReady,\n onError,\n onActivate,\n onBuild,\n onPageMount,\n onPageUnmount,\n onPageError,\n ...view\n } = opts\n const status = writable<InkStatus>({ state: 'idle' })\n const current = writable<InkDocument | null>(null)\n const engine = writable<ViewerEngine | null>(null)\n /** The activated annotation: the note thread and the suggestion card open from it. */\n const activated = writable<string | null>(null)\n\n const root = h('div', { 'data-ink-root': '', 'data-state': 'idle' })\n const scroll = h('div', {\n class: 'ink-scroll',\n 'data-ink-scroll': '',\n tabindex: '0',\n role: 'document',\n 'aria-label': 'Document',\n })\n const viewportRoot = h(\n 'div',\n { class: 'ink-viewport-root', 'data-ink-viewport-root': '', 'data-state': 'idle' },\n scroll\n )\n const toolbar = withToolbar ? createToolbar() : null\n if (toolbar) root.append(toolbar.element)\n root.append(viewportRoot)\n el.append(root)\n\n const focusReturn = createFocusReturn({\n root: () => root,\n activated: () => activated.get(),\n })\n\n let statusEl: HTMLElement | null = null\n function renderStatus(s: InkStatus): void {\n root.dataset.state = s.state\n viewportRoot.dataset.state = s.state\n statusEl?.remove()\n statusEl = null\n if (s.state === 'loading') {\n statusEl = h(\n 'div',\n { class: 'ink-status', role: 'status', 'aria-live': 'polite' },\n 'Loading document…'\n )\n } else if (s.state === 'error') {\n // The engine's message is not written for readers: it stays on the code's tooltip.\n statusEl = h(\n 'div',\n { class: 'ink-status ink-error', role: 'alert' },\n h('p', { class: 'ink-error-title' }, 'This document could not be opened.'),\n h(\n 'p',\n {},\n h('code', { class: 'ink-error-code', title: s.error.message }, s.error.code)\n )\n )\n }\n if (statusEl) viewportRoot.prepend(statusEl)\n }\n function setStatus(s: InkStatus): void {\n renderStatus(s)\n status.set(s)\n }\n\n /** Mounts the engine and the popovers for a ready document; returns their teardown. */\n function start(doc: InkDocument): () => void {\n const store = doc.annotations\n const popovers = [\n withNotes ? createNotePopover({ root, store, activated, focusReturn }) : null,\n withSuggestions\n ? createSuggestionCard({ root, store, activated, focusReturn })\n : null,\n ]\n // An activated annotation that has gone (removed, undone) is no longer activated, so it\n // does not reopen its popover if it comes back.\n const stopList = store.list.subscribe(() => {\n const id = activated.get()\n if (id !== null && !store.get(id)) activated.set(null)\n })\n const hosts = new Map<number, HTMLElement>()\n const errors = new Map<number, HTMLElement>()\n const clearError = (page: number): void => {\n errors.get(page)?.remove()\n errors.delete(page)\n }\n const mounted = mountViewer({\n ...view,\n container: scroll,\n document: doc,\n onActivate: (id) => {\n activated.set(id)\n onActivate?.(id)\n },\n onBuild: (viewport, tools) => {\n toolbar?.bind(doc, viewport, tools)\n onBuild?.(viewport, tools)\n },\n onPageMount: (page, mount, host) => {\n hosts.set(page, host)\n onPageMount?.(page, mount, host)\n },\n // A failed page that unmounts reports no recovery: its error goes with it.\n onPageUnmount: (page) => {\n hosts.delete(page)\n clearError(page)\n onPageUnmount?.(page)\n },\n onPageError: (page, error) => {\n clearError(page)\n const host = hosts.get(page)\n if (error && host) {\n const shown = h(\n 'div',\n { class: 'ink-page-error', 'data-ink-page-error': '', role: 'alert' },\n h('p', {}, `Page ${page + 1} could not be shown.`),\n h('code', { class: 'ink-error-code' }, error.code)\n )\n host.append(shown)\n errors.set(page, shown)\n }\n onPageError?.(page, error)\n },\n })\n engine.set(mounted)\n return () => {\n stopList()\n for (const p of popovers) p?.destroy()\n activated.set(null)\n engine.set(null)\n mounted.destroy()\n toolbar?.unbind()\n }\n }\n\n let loads = 0\n let destroyed = false\n let stop: () => void = () => undefined\n\n /** Tears down the open document, if any, and destroys it. */\n function close(): void {\n stop()\n stop = () => undefined\n const doc = current.get()\n current.set(null)\n doc?.destroy()\n }\n\n function open(source: DocumentSource, openOpts?: { password?: string }): void {\n if (destroyed) return\n const load = ++loads\n close()\n setStatus({ state: 'loading' })\n // The theme's colour variables are read from the root, which is in the page by now.\n openDocument(source, {\n assets,\n password: openOpts?.password ?? password,\n defaults: defaults ?? cssVariableDefaults(root),\n history,\n }).then(\n (doc) => {\n // A later `open` or `destroy` superseded this load.\n if (load !== loads) {\n doc.destroy()\n return\n }\n current.set(doc)\n const s = doc.status.get()\n if (s.state === 'error') {\n setStatus(s)\n onError?.(s.error)\n return\n }\n // The status leaves the layout before the engine measures the scroll element, and the\n // engine is set before anyone hears `ready`.\n renderStatus({ state: 'ready' })\n stop = start(doc)\n status.set({ state: 'ready' })\n // A status subscriber may have opened another document already.\n if (load === loads) onReady?.(doc)\n },\n (cause: unknown) => {\n // Only a programmer error (missing assets) rejects; it gets the error state too.\n if (load !== loads) return\n const error = isInkError(cause)\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n setStatus({ state: 'error', error })\n onError?.(error)\n }\n )\n }\n\n open(initial)\n\n return {\n element: root,\n status: readonly(status),\n document: readonly(current),\n engine: readonly(engine),\n toolbar: toolbar?.element ?? null,\n open,\n destroy() {\n if (destroyed) return\n destroyed = true\n loads++\n close()\n toolbar?.destroy()\n root.remove()\n },\n }\n}\n"],"mappings":";;;AAoDA,SAAgB,kBAAkB,KAA2B;CAC3D,IAAI,CAAC,OAAO,SAAS,GAAG,KAAK,MAAM,OAAO,GACxC,MAAM,IAAI,WAAW,0CAA0C,KAAK;CAEtE,QAAU,MAAM,MAAO,OAAO;AAChC;;;;;AAMA,SAAgB,oBACd,MACA,MACA,eAA6B,GACd;CACf,MAAM,WAAW,kBAAkB,YAAY;CAC/C,MAAM,gBAAgB,kBAAkB,KAAK,SAAS,QAAQ;CAE9D,MAAM,QAAQ,OAAO,KAAK;CAC1B,MAAM,KAAK,KAAK,IAAI;CACpB,MAAM,KAAK,KAAK,IAAI;CACpB,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI;CACjC,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI;CACjC,MAAM,WAAW,KAAK,MAAM;CAC5B,MAAM,WAAW,KAAK,MAAM;CAC5B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,QAAQ,eAAR;EACE,KAAK;GACH,UAAU;GACV,UAAU;GACV,UAAU;GACV,UAAU;GACV;EACF,KAAK;GACH,UAAU;GACV,UAAU;GACV,UAAU;GACV,UAAU;GACV;EACF,KAAK;GACH,UAAU;GACV,UAAU;GACV,UAAU;GACV,UAAU;GACV;EACF;GACE,UAAU;GACV,UAAU;GACV,UAAU;GACV,UAAU;CACd;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,YAAY,GAAG;EACjB,gBAAgB,KAAK,IAAI,UAAU,EAAE,IAAI;EACzC,gBAAgB,KAAK,IAAI,UAAU,EAAE,IAAI;EACzC,WAAW,KAAK,IAAI,KAAK,EAAE,IAAI;EAC/B,YAAY,KAAK,IAAI,KAAK,EAAE,IAAI;CAClC,OAAO;EACL,gBAAgB,KAAK,IAAI,UAAU,EAAE,IAAI;EACzC,gBAAgB,KAAK,IAAI,UAAU,EAAE,IAAI;EACzC,WAAW,KAAK,IAAI,KAAK,EAAE,IAAI;EAC/B,YAAY,KAAK,IAAI,KAAK,EAAE,IAAI;CAClC;CACA,MAAM,SAAiB;EACrB,UAAU;EACV,UAAU;EACV,UAAU;EACV,UAAU;EACV,gBAAgB,UAAU,QAAQ,UAAU,UAAU,QAAQ;EAC9D,gBAAgB,UAAU,QAAQ,UAAU,UAAU,QAAQ;CAChE;CACA,MAAM,UAAU,aAAa,MAAM;CACnC,MAAM,SAAS,MAAoB,YAAY,QAAQ,CAAC;CACxD,MAAM,WAAW,MAAoB,YAAY,SAAS,CAAC;CAE3D,MAAM,UACJ,WAC4D;EAC5D,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;EAChC,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;EAChC,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE;EACxB,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE;EACxB,OAAO;GAAE;GAAG;GAAG,OAAO,KAAK,IAAI,GAAG,EAAE,IAAI;GAAG,QAAQ,KAAK,IAAI,GAAG,EAAE,IAAI;EAAE;CACzE;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,GAAG;GACX,MAAM,IAAI,OAAO;IACf,MAAM;KAAE,GAAG,EAAE;KAAG,GAAG,EAAE;IAAE,CAAC;IACxB,MAAM;KAAE,GAAG,EAAE,IAAI,EAAE;KAAO,GAAG,EAAE;IAAE,CAAC;IAClC,MAAM;KAAE,GAAG,EAAE;KAAG,GAAG,EAAE,IAAI,EAAE;IAAO,CAAC;IACnC,MAAM;KAAE,GAAG,EAAE,IAAI,EAAE;KAAO,GAAG,EAAE,IAAI,EAAE;IAAO,CAAC;GAC/C,CAAC;GACD,OAAO;IAAE,MAAM,EAAE;IAAG,KAAK,EAAE;IAAG,OAAO,EAAE;IAAO,QAAQ,EAAE;GAAO;EACjE;EACA,UAAU,GAAG;GACX,OAAO;IAAE,IAAI,MAAM,EAAE,EAAE;IAAG,IAAI,MAAM,EAAE,EAAE;IAAG,IAAI,MAAM,EAAE,EAAE;IAAG,IAAI,MAAM,EAAE,EAAE;GAAE;EAC9E;EACA,cAAc,WAAW,SAAS;EAClC,YAAY,GAAG;GACb,OAAO,OAAO;IACZ,QAAQ;KAAE,GAAG,EAAE;KAAM,GAAG,EAAE;IAAI,CAAC;IAC/B,QAAQ;KAAE,GAAG,EAAE,OAAO,EAAE;KAAO,GAAG,EAAE;IAAI,CAAC;IACzC,QAAQ;KAAE,GAAG,EAAE;KAAM,GAAG,EAAE,MAAM,EAAE;IAAO,CAAC;IAC1C,QAAQ;KAAE,GAAG,EAAE,OAAO,EAAE;KAAO,GAAG,EAAE,MAAM,EAAE;IAAO,CAAC;GACtD,CAAC;EACH;EACA,gBAAgB,OAAO,KAAK;CAC9B;AACF;;;AC/IA,SAAS,QAAQ,MAAgB,MAAc,UAAwB;CACrE,MAAM,IAAI,oBAAoB,MAAM,MAAM,QAAQ;CAClD,OAAO;EAAE,OAAO,EAAE;EAAU,QAAQ,EAAE;CAAU;AAClD;;AAGA,SAAgB,iBAAiB,OAAkC;CACjE,MAAM,QACJ,MAAM,SAAS,WACX,MAAM,MAAM,QAAQ,MAAM,EAAE,UAAU,MAAM,OAAO,IACnD,MAAM;CACZ,MAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC;CAErE,MAAM,QAAQ,MAAM,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,KAAK,GAAG,MAAM,cAAc;CACnF,IAAI,MAAM,MAAM;CAahB,OAAO;EAAE,OAZK,MAAM,KAAK,GAAG,MAAkB;GAC5C,MAAM,IAAI,MAAM;GAChB,MAAM,MAAM;IACV,OAAO,EAAE;IACT,OAAO,QAAQ,EAAE,SAAS;IAC1B;IACA,OAAO,EAAE;IACT,QAAQ,EAAE;GACZ;GACA,OAAO,EAAE,SAAS,MAAM;GACxB,OAAO;EACT,CACa;EAAG;EAAO,QAAQ;CAAI;AACrC;;AAGA,SAAgB,WACd,MACA,UACA,WACA,MACA,SACQ;CACR,MAAM,OAAO,QAAQ,MAAM,GAAG,QAAQ;CACtC,MAAM,WAAW,UAAU,QAAQ,UAAU,KAAK,KAAK;CACvD,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,KAAM,OAAO;CACvD,MAAM,YAAY,UAAU,SAAS,UAAU,KAAK,KAAK;CACzD,OAAO,KAAK,IAAI,KAAM,KAAK,IAAI,SAAS,QAAQ,CAAC;AACnD;;;;;AAMA,SAAgB,gBACd,QACA,WACA,gBACA,QACU;CACV,MAAM,QAAQ,OAAO;CACrB,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC;CAChC,MAAM,SAAS,YAAY;CAC3B,IAAI,QAAQ,MAAM,WAAW,MAAM,EAAE,MAAM,EAAE,UAAU,SAAS;CAChE,IAAI,UAAU,IAAI,QAAQ,MAAM,SAAS;CACzC,IAAI,OAAO;CACX,OAAO,OAAO,IAAI,MAAM,UAAU,MAAM,OAAO,EAAE,CAAE,OAAO,QAAQ;CAClE,MAAM,OAAO,KAAK,IAAI,GAAG,QAAQ,MAAM;CACvC,MAAM,KAAK,KAAK,IAAI,MAAM,SAAS,GAAG,OAAO,MAAM;CACnD,OAAO,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK;AACrD;;AAGA,SAAgB,mBACd,QACA,WACA,gBACQ;CACR,IAAI,OAAO,OAAO,MAAM,EAAE,EAAE,SAAS;CACrC,IAAI,WAAW;CACf,MAAM,SAAS,YAAY;CAC3B,KAAK,MAAM,KAAK,OAAO,OAAO;EAC5B,MAAM,UAAU,KAAK,IACnB,GACA,KAAK,IAAI,EAAE,MAAM,EAAE,QAAQ,MAAM,IAAI,KAAK,IAAI,EAAE,KAAK,SAAS,CAChE;EACA,IAAI,UAAU,UAAU;GACtB,WAAW;GACX,OAAO,EAAE;EACX;CACF;CACA,OAAO;AACT;;;ACzCA,SAAS,SAAS,GAAsB,GAA+B;CACrE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,MAAM,EAAE,EAAE;AAC9D;AAEA,SAAgB,eAAe,MAAiC;CAC9D,MAAM,EAAE,WAAW,UAAU,QAAQ;CACrC,MAAM,MAAM,KAAK,OAAO;CACxB,MAAM,SAAS,KAAK,UAAU;CAC9B,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,SAAS,MAAsB,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,CAAC,CAAC;CAE3E,MAAM,OAAO,SACX,OAAO,KAAK,SAAS,WAAW,MAAM,KAAK,IAAI,IAAK,KAAK,QAAQ,WACnE;CACA,MAAM,QAAQ,SAAS,CAAC;CACxB,MAAM,WAAW,SAAuB,KAAK,YAAY,CAAC;CAC1D,MAAM,OAAO,SAAqB,KAAK,QAAQ,YAAY;CAC3D,MAAM,cAAc,SAAS,CAAC;CAC9B,MAAM,UAAU,SAA4B,CAAC,CAAC;CAC9C,MAAM,SAAS,SAAoB;EAAE,OAAO,CAAC;EAAG,OAAO;EAAG,QAAQ;CAAE,CAAC;CAErE,MAAM,gBAAgB;EACpB,UAAU,UAAU,MAAM;EAC1B,UAAU,UAAU,MAAM;CAC5B;CACA,UAAU,QAAQ,cAAc;CAChC,UAAU,MAAM,WAAW;CAC3B,IAAI,iBAAiB,SAAS,CAAC,CAAC,aAAa,UAC3C,UAAU,MAAM,WAAW;CAE7B,MAAM,UAAU,UAAU,cAAc,cAAc,KAAK;CAC3D,QAAQ,YAAY;CACpB,QAAQ,QAAQ,WAAW;CAC3B,QAAQ,MAAM,WAAW;CACzB,UAAU,OAAO,OAAO;CAExB,MAAM,wBAAQ,IAAI,IAAyB;CAC3C,MAAM,6BAAa,IAAI,IAA2B;CAClD,IAAI,WAAW;EAAE,OAAO;EAAI,QAAQ;CAAG;CACvC,IAAI,YAAY;CAEhB,SAAS,OAAO,MAAc,IAAI,OAAO,IAAI,GAA2B;EACtE,OAAO,EAAE,MAAM,MAAM,MAAM,EAAE,UAAU,IAAI;CAC7C;;CAGA,SAAS,SAAgB;EACvB,OAAO;GAAE,GAAG,QAAQ;GAAY,GAAG,QAAQ;EAAU;CACvD;;CAGA,SAAS,YAA+C;EACtD,MAAM,KAAK,iBAAiB,SAAS;EACrC,MAAM,MAAM,MAAsB,OAAO,WAAW,CAAC,KAAK;EAC1D,OAAO;GACL,OAAO,UAAU,cAAc,GAAG,GAAG,WAAW,IAAI,GAAG,GAAG,YAAY;GACtE,QAAQ,UAAU,eAAe,GAAG,GAAG,UAAU,IAAI,GAAG,GAAG,aAAa;EAC1E;CACF;CAEA,SAAS,eAAuB;EAC9B,MAAM,IAAI,KAAK,IAAI;EACnB,IAAI,OAAO,MAAM,UAAU,OAAO,MAAM,CAAC;EACzC,MAAM,OAAO,IAAI,MAAM,YAAY,IAAI,MAAM,IAAI,MAAM;EACvD,IAAI,CAAC,MAAM,OAAO;EAClB,OAAO,MAAM,WAAW,MAAM,SAAS,IAAI,GAAG,UAAU,GAAG,GAAG,GAAG,CAAC;CACpE;CAEA,SAAS,aAAa,MAA6B;EACjD,IAAI,IAAI,WAAW,IAAI,IAAI;EAC3B,IAAI,CAAC,GAAG;GACN,MAAM,OAAO,IAAI,MAAM;GACvB,IAAI,CAAC,MAAM,MAAM,IAAI,WAAW,QAAQ,KAAK,cAAc;GAC3D,IAAI,oBAAoB,MAAM,MAAM,IAAI,GAAG,SAAS,IAAI,CAAC;GACzD,WAAW,IAAI,MAAM,CAAC;EACxB;EACA,OAAO;CACT;CAEA,SAAS,aAAmB;EAC1B,MAAM,IAAI,aAAa,CAAC;EACxB,WAAW,MAAM;EACjB,MAAM,IAAI,iBAAiB;GACzB,OAAO,IAAI;GACX,MAAM,MAAM,IAAI;GAChB,UAAU,SAAS,IAAI;GACvB;GACA,MAAM,KAAK,IAAI;GACf,SAAS,YAAY,IAAI;GACzB,gBAAgB,UAAU,CAAC,CAAC;EAC9B,CAAC;EACD,QAAQ,MAAM,QAAQ,GAAG,EAAE,MAAM;EACjC,QAAQ,MAAM,SAAS,GAAG,EAAE,OAAO;EACnC,OAAO,IAAI,CAAC;CACd;;;;;;CAOA,SAAS,WAAiB;EACxB,MAAM,QAAQ,UAAU;EACxB,WAAW;EACX,IAAI,UAAU,gBAAgB,OAAO,WAAW;EAChD,WAAW;GAAE,OAAO,UAAU;GAAa,QAAQ,UAAU;EAAa;EAC1E,MAAM,IAAI,OAAO,IAAI;EACrB,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO;GAChC,IAAI,CAAC,OAAO,MAAM,CAAC,GAAG;GACtB,MAAM,MAAM,MAAM,CAAC;GACnB,KAAK,SAAS,MAAM,MAAM,aAAa,IAAI,CAAC;EAC9C;EACA,KAAK;CACP;CAEA,SAAS,MAAM,MAAc,MAAmB,GAAoB;EAClE,MAAM,MAAM,OAAO,MAAM,CAAC;EAC1B,IAAI,CAAC,KAAK;EACV,MAAM,IAAI,aAAa,IAAI;EAC3B,KAAK,MAAM,OAAO,GAAG,IAAI,KAAK;EAC9B,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI;EAC5B,KAAK,MAAM,QAAQ,GAAG,EAAE,SAAS;EACjC,KAAK,MAAM,SAAS,GAAG,EAAE,UAAU;EAGnC,KAAK,MAAM,YAAY,kBAAkB,OAAO,EAAE,IAAI,CAAC;EACvD,KAAK,MAAM,YAAY,wBAAwB,OAAO,EAAE,KAAK,CAAC;EAC9D,KAAK,QAAQ,WAAW,OAAO,EAAE,aAAa;CAChD;;CAGA,SAAS,OAAa;EACpB,IAAI,WAAW;EACf,MAAM,IAAI,OAAO,IAAI;EACrB,MAAM,MAAM,UAAU,YAAY,OAAO,CAAC,CAAC;EAC3C,MAAM,SAAS,gBAAgB,GAAG,KAAK,UAAU,cAAc,MAAM;EACrE,MAAM,YAAY,IAAI,IAAI,MAAM;EAChC,KAAK,MAAM,CAAC,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG;GACrC,IAAI,UAAU,IAAI,IAAI,GAAG;GACzB,MAAM,OAAO,IAAI;GACjB,KAAK,UAAU,MAAM,IAAI;GACzB,KAAK,OAAO;EACd;EACA,KAAK,MAAM,QAAQ,QAAQ;GACzB,IAAI,MAAM,IAAI,IAAI,GAAG;GACrB,MAAM,OAAO,UAAU,cAAc,cAAc,KAAK;GACxD,KAAK,YAAY;GACjB,KAAK,QAAQ,OAAO,OAAO,IAAI;GAC/B,KAAK,MAAM,WAAW;GACtB,MAAM,MAAM,MAAM,CAAC;GACnB,MAAM,IAAI,MAAM,IAAI;GACpB,QAAQ,OAAO,IAAI;GACnB,KAAK,QAAQ,MAAM,MAAM,aAAa,IAAI,CAAC;EAC7C;EACA,IAAI,CAAC,SAAS,QAAQ,IAAI,GAAG,MAAM,GAAG,QAAQ,IAAI,MAAM;EACxD,IAAI,KAAK,IAAI,MAAM,cACjB,YAAY,IAAI,mBAAmB,GAAG,KAAK,UAAU,YAAY,CAAC;CAEtE;CAEA,IAAI,cAAc;CAClB,MAAM,iBAAuB;EAC3B,IAAI,aAAa;EACjB,cAAc,4BAA4B;GACxC,cAAc;GACd,KAAK;EACP,CAAC;CACH;CACA,UAAU,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;CAEhE,MAAM,KAAK,IAAI,qBAAqB;EAClC,IAAI,WAAW;EACf,IACE,UAAU,gBAAgB,SAAS,SACnC,UAAU,iBAAiB,SAAS,QAEpC;EAEF,WAAW,KAAA,SAAiB,KAAA,CAAS;CACvC,CAAC;CACD,GAAG,QAAQ,SAAS;CAEpB,SAAS,UAAU,SAAiB,SAA0C;EAC5E,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO;GAChC,MAAM,IAAI,KAAK,sBAAsB;GACrC,IACE,WAAW,EAAE,QACb,WAAW,EAAE,SACb,WAAW,EAAE,OACb,WAAW,EAAE,QAEb,OAAO;IAAE;IAAM;IAAM,WAAW,aAAa,IAAI;GAAE;EAEvD;CAEF;;;;;CAMA,SAAS,UAAU,GAAc,GAAmC;EAClE,IAAI;EACJ,IAAI,eAAe;EACnB,KAAK,MAAM,KAAK,EAAE,OAAO;GACvB,MAAM,WACJ,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,MAAM,EAAE,SAAS;GACxE,IAAI,WAAW,cAAc;IAC3B,OAAO;IACP,eAAe;GACjB;EACF;EACA,OAAO;CACT;;;;;;;CAQA,SAAS,WAAW,WAA8B,QAA0B;EAC1E,MAAM,SAAS,aAAa;GAC1B,GAAG,UAAU,cAAc;GAC3B,GAAG,UAAU,eAAe;EAC9B;EAEA,MAAM,IAAI,OAAO;EACjB,MAAM,IAAI,UAAU,aAAa,OAAO,IAAI,EAAE;EAC9C,MAAM,IAAI,UAAU,YAAY,OAAO,IAAI,EAAE;EAC7C,MAAM,MAAM,UAAU,OAAO,IAAI,GAAG,CAAC;EACrC,MAAM,OAAO,MACT,aAAa,IAAI,KAAK,CAAC,CAAC,QAAQ;GAAE,GAAG,IAAI,IAAI;GAAM,GAAG,IAAI,IAAI;EAAI,CAAC,IACnE,KAAA;EACJ,OAAO;EACP,SAAS;EACT,IAAI,CAAC,OAAO,CAAC,MAAM;EACnB,MAAM,MAAM,OAAO,IAAI,KAAK;EAC5B,IAAI,CAAC,KAAK;EACV,MAAM,QAAQ,aAAa,IAAI,KAAK,CAAC,CAAC,MAAM,IAAI;EAChD,MAAM,KAAK,OAAO;EAClB,UAAU,aAAa,GAAG,IAAI,IAAI,OAAO,MAAM,IAAI,OAAO;EAC1D,UAAU,YAAY,GAAG,IAAI,IAAI,MAAM,MAAM,IAAI,OAAO;EACxD,KAAK;CACP;CAEA,MAAM,WAAqB;EACzB,MAAM,SAAS,IAAI;EACnB,OAAO,SAAS,KAAK;EACrB,aAAa,SAAS,WAAW;EACjC,SAAS,SAAS,OAAO;EACzB,QAAQ,SAAS,MAAM;EACvB,UAAU,SAAS,QAAQ;EAC3B,MAAM,SAAS,IAAI;EACnB,QAAQ,GAAG,WAAW;GACpB,WAAW,iBAAiB,KAAK,IAAI,OAAO,MAAM,WAAW,MAAM,CAAC,IAAI,CAAC,CAAC;EAC5E;EACA,OAAO,QAAQ,WAAW;GACxB,SAAS,QAAQ,MAAM,MAAM,IAAI,IAAI,MAAM,GAAG,SAAS;EACzD;EACA,QAAQ,GAAG;GACT,IAAI,MAAM,KAAK,IAAI,GAAG;GAGtB,IAAI,KAAK,IAAI,MAAM,cAAc,KAAK;GACtC,MAAM,OAAO,YAAY,IAAI;GAC7B,KAAK,IAAI,CAAC;GACV,SAAS;GACT,SAAS,aAAa,IAAI;EAC5B;EACA,YAAY,GAAG;GACb,WAAW,KAAA,SAAiB,SAAS,IAAI,CAAC,CAAC;EAC7C;EACA,aAAa,OAAO,GAAG;GACrB,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,CAAC;GAC9D,MAAM,WAAW,GAAG,YAAY;GAChC,IAAI,KAAK,IAAI,MAAM,UAAU;IAE3B,IAAI,SAAS,YAAY,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,UAAU,MAAM;KACvE,YAAY,IAAI,IAAI;KACpB,SAAS;IACX;IACA,UAAU,SAAS;KAAE,KAAK;KAAG;IAAS,CAAC;IACvC,KAAK;IACL;GACF;GACA,MAAM,MAAM,OAAO,IAAI;GACvB,IAAI,CAAC,KAAK;GACV,UAAU,SAAS;IAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG;IAAG;GAAS,CAAC;GAC7E,KAAK;EACP;EACA,aAAa,MAAM,MAAM;GACvB,IAAI,KAAK,IAAI,MAAM,YAAY,YAAY,IAAI,MAAM,MAAM;IACzD,YAAY,IAAI,IAAI;IACpB,SAAS;GACX;GACA,MAAM,MAAM,OAAO,IAAI;GACvB,IAAI,CAAC,KAAK;GACV,MAAM,MAAM,aAAa,IAAI,CAAC,CAAC,UAAU,IAAI;GAC7C,MAAM,IAAI,OAAO;GACjB,MAAM,MAAM,EAAE,IAAI,IAAI,MAAM,IAAI;GAChC,IACE,MAAM,UAAU,aAChB,MAAM,IAAI,SAAS,UAAU,YAAY,UAAU,cAEnD,UAAU,YAAY,KAAK,IAAI,GAAG,OAAO,UAAU,eAAe,IAAI,UAAU,CAAC;GAEnF,MAAM,OAAO,EAAE,IAAI,IAAI,OAAO,IAAI;GAClC,IACE,OAAO,UAAU,cACjB,OAAO,IAAI,QAAQ,UAAU,aAAa,UAAU,aAEpD,UAAU,aAAa,KAAK,IAAI,GAAG,QAAQ,UAAU,cAAc,IAAI,SAAS,CAAC;GAEnF,KAAK;EACP;EACA;EACA,UAAU,SAAS,MAAM,IAAI,IAAI;EACjC;EACA,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ,GAAG,WAAW;GACd,UAAU,oBAAoB,UAAU,QAAQ;GAChD,IAAI,aAAa,qBAAqB,WAAW;GACjD,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO;IAChC,KAAK,UAAU,MAAM,IAAI;IACzB,KAAK,OAAO;GACd;GACA,MAAM,MAAM;GACZ,WAAW,MAAM;GACjB,QAAQ,OAAO;GACf,OAAO,UAAU,QAAQ;GACzB,UAAU,MAAM,WAAW,cAAc;GACzC,UAAU,MAAM,WAAW,cAAc;EAC3C;CACF;CAEA,SAAS;CACT,OAAO;AACT;;;;AC7ZA,MAAM,YAAY;;AAGlB,MAAM,SACJ;;;;;;;;AASF,SAAgB,mBACd,IACA,MACY;CACZ,MAAM,EAAE,aAAa;CACrB,MAAM,aAAa,MAA2B;EAC5C,IAAI,EAAE,oBAAoB,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ;EAC9D,IAAI,EAAE,kBAAkB,WAAW,EAAE,OAAO,QAAQ,MAAM,GAAG;EAC7D,QAAQ,EAAE,KAAV;GACE,KAAK;GACL,KAAK;IACH,SAAS,OAAO,SAAS;IACzB;GACF,KAAK;IACH,SAAS,OAAO,IAAI,SAAS;IAC7B;GACF,KAAK;IACH,SAAS,aAAa,CAAC;IACvB;GACF,KAAK;IACH,SAAS,aAAa,KAAK,UAAU,IAAI,CAAC;IAC1C;GACF,KAAK;IACH,SAAS,aAAa,SAAS,YAAY,IAAI,IAAI,CAAC;IACpD;GACF,KAAK;IACH,SAAS,aAAa,SAAS,YAAY,IAAI,IAAI,CAAC;IACpD;GACF,SACE;EACJ;EACA,EAAE,eAAe;CACnB;CACA,GAAG,iBAAiB,WAAW,SAAS;CACxC,aAAa,GAAG,oBAAoB,WAAW,SAAS;AAC1D;;;ACpBA,MAAM,kBAAkB,UACrB,OAAqC,SAAS;AAEjD,SAAgB,mBAAmB,MAAyC;CAC1E,MAAM,EAAE,UAAU,KAAK,MAAM,SAAS;CACtC,MAAM,OAAO,KAAK,cAAc;CAChC,MAAM,mBACJ,KAAK,qBACJ,QAAQ,KAAK,mBAAmB,IAAI,KAAK,mBAAmB;CAC/D,MAAM,UAAU,KAAK,cAAc,cAAc,KAAK;CACtD,QAAQ,YAAY;CACpB,QAAQ,QAAQ,iBAAiB;CACjC,QAAQ,MAAM,UAAU;CACxB,KAAK,OAAO,OAAO;CAEnB,IAAI;CACJ,IAAI,SAAS,KAAK;CAClB,IAAI;CACJ,IAAI,YAAY;CAChB,IAAI,aAAa;CAIjB,IAAI;CACJ,IAAI,WAA0B,QAAQ,QAAQ;CAE9C,SAAS,SAAS;EAChB,iBAAiB;EACjB,iBAAiB,KAAA;CACnB;;;;;CAMA,SAAS,QAAQ,QAAiC;EAChD,OAAO,QAAQ;EACf,OAAO,SAAS;EAChB,OAAO,OAAO;CAChB;CAEA,SAAS,WAAW,QAA2B,WAA0B;EACvE,OAAO,MAAM,QAAQ,GAAG,UAAU,SAAS;EAC3C,OAAO,MAAM,SAAS,GAAG,UAAU,UAAU;CAC/C;CAEA,eAAe,OAAO,WAAyC;EAC7D,MAAM,MAAM,EAAE;EACd,SAAS;EACT,MAAM,MAAM,WAAW;EACvB,SAAS,GAAG;EACZ,MAAM,OAAO;EACb,OAAO,KAAA;EACP,IAAI,CAAC,gBACH,WAAW,IAAI,SAAe,YAAa,iBAAiB,OAAQ;EAGtE,IAAI,SAAS,WAAW,SAAS,SAAS;EAC1C,IAAI;EACJ,IAAI;GACF,MAAM,UAAU,MAAM,IAAI,OAAO,QAAQ,IAAI;GAC7C,IAAI,aAAa,QAAQ,YAAY;GACrC,MAAM,EAAE,mBAAmB,IAAI,OAAO;GACtC,MAAM,WAAW,QAAQ,YAAY;IACnC,OAAO,UAAU;IACjB,UAAU,UAAU;GACtB,CAAC;GACD,SAAS,KAAK,cAAc,cAAc,QAAQ;GAClD,OAAO,QAAQ,YAAY;GAC3B,OAAO,aAAa,eAAe,MAAM;GACzC,OAAO,QAAQ,KAAK,MAAM,UAAU,WAAW,GAAG;GAClD,OAAO,SAAS,KAAK,MAAM,UAAU,YAAY,GAAG;GACpD,OAAO,MAAM,UAAU;GACvB,WAAW,QAAQ,SAAS;GAC5B,MAAM,UAAU,QAAQ,OAAO;IAC7B;IACA;IAEA,YAAY;IACZ,gBAAgB,eAAe;IAC/B,GAAI,QAAQ,IAAI,CAAC,IAAI,EAAE,WAAW;KAAC;KAAK;KAAG;KAAG;KAAK;KAAG;IAAC,EAAE;GAC3D,CAAC;GACD,OAAO;GACP,MAAM,QAAQ;GACd,IAAI,SAAS,SAAS,OAAO,KAAA;GAC7B,IAAI,aAAa,QAAQ,YAAY;IACnC,QAAQ,MAAM;IACd;GACF;GACA,IAAI,SAAS,QAAQ,OAAO;GAC5B,UAAU;GACV,QAAQ,OAAO,MAAM;GACrB,KAAK,aAAa;EACpB,SAAS,OAAO;GACd,IAAI,UAAU,WAAW,SAAS,QAAQ,MAAM;GAEhD,IAAI,GADe,aAAa,QAAQ,eACpB,eAAe,KAAK,MAAM,CAAC,WAAW,KAAK,UAAU,KAAK;EAChF,UAAU;GACR,IAAI,QAAQ,YAAY,OAAO;EACjC;CACF;CAMA,MAAM,aAAa,CAAC,KAAK,GAAG;CAC5B,IAAI;CACJ,IAAI;CACJ,IAAI,WAA4C,CAAC;CACjD,MAAM,sBAA4B;EAChC,SAAS,QAAQ,YAAY;EAC7B,WAAW,CAAC;CACd;CACA,MAAM,oBAA0B;EAC9B,IAAI,WAAW;EAEf,SADa,WACD,GAAG,IAAI;EACnB,OAAY,MAAM;EAClB,cAAc;EACd,WAAW,WAAW,KAAK,OACzB,iBAAiB;GACf,IAAI,CAAC,aAAa,WAAW,MAAM,YAAY,YAAY;EAC7D,GAAG,EAAE,CACP;CACF;CACA,SAAS,SAAS,KAAa,QAAQ,OAAa;EAClD,IAAI,KAAK,qBAAqB,KAAA,KAAa,CAAC,MAAM,YAAY;EAC9D,IAAI,QAAQ,cAAc,CAAC,OAAO;EAClC,aAAa;EACb,UAAU,oBAAoB,UAAU,WAAW;EACnD,WAAW,KAAK,WAAW,gBAAgB,IAAI,MAAM;EACrD,SAAS,iBAAiB,UAAU,WAAW;CACjD;CAEA,OAAY,KAAK,SAAS;CAE1B,OAAO;EACL,SAAS;EACT,IAAI,WAAW;GACb,OAAO;EACT;EACA,OAAO,WAAW;GAChB,IAAI,WAAW;GACf,OAAY,SAAS;EACvB;EACA,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ,UAAU,oBAAoB,UAAU,WAAW;GACnD,WAAW,KAAA;GACX,cAAc;GACd,MAAM,OAAO;GACb,OAAO,KAAA;GACP,IAAI,SAAS,QAAQ,OAAO;GAC5B,UAAU,KAAA;GACV,QAAQ,OAAO;GACf,OAAO;EACT;CACF;AACF;;;;;;;;;AC3KA,eAAsB,oBACpB,MAC2B;CAC3B,MAAM,QAAQ,IAAI,KAAK,OAAO,UAAU;EACtC,mBAAmB,KAAK,QAAQ,kBAAkB;GAChD,sBAAsB;GACtB,sBAAsB;EACxB,CAAC;EACD,WAAW,KAAK;EAChB,UAAU,KAAK;CACjB,CAAC;CACD,MAAM,UAA4B;EAChC,OAAO,UAAU;GACf,MAAM,OAAO,EAAE,SAAS,CAAC;EAC3B;EACA,SAAS;GACP,MAAM,OAAO;EACf;CACF;CACA,MAAM,gBAAsB,MAAM,OAAO;CACzC,KAAK,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC9D,IAAI,KAAK,QAAQ,SAAS,MAAM,OAAO;CACvC,IAAI;EACF,MAAM,MAAM,OAAO;CACrB,SAAS,OAAO;EAGd,KAAK,QAAQ,oBAAoB,SAAS,OAAO;EACjD,MAAM,OAAO;EACb,MAAM;CACR;CACA,OAAO;AACT;;;ACxBA,SAAgB,gBAAgB,MAAyC;CACvE,MAAM,EAAE,UAAU,KAAK,SAAS;CAChC,MAAM,KAAK,KAAK,KAAK,cAAc,cAAc,KAAK;CACtD,GAAG,YAAY;CACf,GAAG,QAAQ,eAAe;CAC1B,GAAG,MAAM,UAAU;CACnB,KAAK,KAAK,OAAO,EAAE;CAEnB,MAAM,QAAQ,IAAI,gBAAgB;CAClC,IAAI;CAEJ,MAAM,cAAc,OAAO,cAA6B;EACtD,MAAM,UAAU,MAAM,IAAI,OAAO,QAAQ,IAAI;EAC7C,OAAO;GACL;GACA,UAAU,QAAQ,YAAY;IAC5B,OAAO,UAAU;IACjB,UAAU,UAAU;GACtB,CAAC;EACH;CACF;CAIA,MAAM,UAAU,UAAmB;EACjC,IAAI,MAAM,OAAO,WAAW,CAAC,KAAK,SAAS;EAC3C,IAAI;GACF,KAAK,QAAQ,KAAK;EACpB,SAAS,QAAQ;GACf,qBAAqB;IACnB,MAAM;GACR,CAAC;EACH;CACF;CAEA,MAAM,QAAQ,OAAO,cAA4C;EAC/D,MAAM,EAAE,SAAS,aAAa,MAAM,YAAY,SAAS;EACzD,IAAI,MAAM,OAAO,SAAS;EAC1B,UAAU,MAAM,oBAAoB;GAClC,QAAQ,IAAI,OAAO;GACnB;GACA,WAAW;GACX;GACA,QAAQ,MAAM;EAChB,CAAC;EACD,IAAI,CAAC,MAAM,OAAO,SAAS,KAAK,aAAa;CAC/C;CAEA,IAAI,QAAuB,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,MAAM;CAE7D,OAAO;EACL,SAAS;EACT,IAAI,QAAQ;GACV,OAAO;EACT;EACA,OAAO,WAAW;GAChB,IAAI,MAAM,OAAO,SAAS;GAC1B,QAAQ,MACL,KAAK,YAAY;IAChB,IAAI,MAAM,OAAO,SAAS;IAE1B,IAAI,CAAC,SAAS;KACZ,GAAG,gBAAgB;KACnB,MAAM,MAAM,SAAS;KACrB;IACF;IACA,MAAM,EAAE,aAAa,MAAM,YAAY,SAAS;IAChD,IAAI,MAAM,OAAO,SAAS;IAC1B,QAAQ,OAAO,QAAQ;IACvB,KAAK,aAAa;GACpB,CAAC,CAAC,CACD,MAAM,MAAM;EACjB;EACA,UAAU;GACR,IAAI,MAAM,OAAO,SAAS;GAC1B,MAAM,MAAM;GACZ,GAAG,OAAO;EACZ;CACF;AACF;;;;;;;AChGA,SAAgB,oBACd,OACA,MACA,WACQ;CACR,MAAM,IAAI,KAAK,sBAAsB;CACrC,MAAM,MAAc,CAAC;CACrB,KAAK,MAAM,KAAK,OAAO;EACrB,IAAI,EAAE,UAAU,KAAK,EAAE,WAAW,GAAG;EACrC,IAAI,KACF,UAAU,YAAY;GACpB,MAAM,EAAE,OAAO,EAAE;GACjB,KAAK,EAAE,MAAM,EAAE;GACf,OAAO,EAAE;GACT,QAAQ,EAAE;EACZ,CAAC,CACH;CACF;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,kBACd,MACA,SACkB;CAClB,MAAM,MAAM,KAAK,cAAc,aAAa,aAAa;CACzD,IAAI,CAAC,OAAO,IAAI,eAAe,KAAK,IAAI,aAAa,OAAO,CAAC;CAC7D,MAAM,0BAAU,IAAI,IAA+C;CACnE,MAAM,SAAS,CAAC,GAAG,KAAK,iBAA8B,uBAAuB,CAAC;CAC9E,IAAI,KAAK,QAAQ,uBAAuB,GAAG,OAAO,QAAQ,IAAI;CAC9D,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,YAAY,KAAK;EACvC,MAAM,QAAQ,IAAI,WAAW,CAAC;EAC9B,KAAK,MAAM,SAAS,QAAQ;GAC1B,IAAI,CAAC,MAAM,eAAe,KAAK,GAAG;GAClC,MAAM,OAAO,MAAM,QAAqB,aAAa;GACrD,IAAI,CAAC,MAAM;GACX,MAAM,OAAO,QAAQ,IAAI;GACzB,IAAI,CAAC,MAAM;GACX,MAAM,MAAM,MAAM,WAAW;GAC7B,IAAI,CAAC,MAAM,SAAS,MAAM,cAAc,GAAG,IAAI,SAAS,OAAO,CAAC;GAChE,IAAI,CAAC,MAAM,SAAS,MAAM,YAAY,GAAG,IAAI,OAAO,OAAO,MAAM,WAAW,MAAM;GAClF,MAAM,QAAQ,QAAQ,IAAI,KAAK,IAAI,KAAK;IAAE,OAAO,CAAC;IAAG,MAAM,CAAC;GAAE;GAC9D,MAAM,MAAM,KAAK,GAAG,oBAAoB,IAAI,eAAe,GAAG,MAAM,KAAK,SAAS,CAAC;GACnF,MAAM,KAAK,KAAK,UAAU,GAAG,CAAC;GAC9B,QAAQ,IAAI,KAAK,MAAM,KAAK;EAC9B;CACF;CACA,OAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC,CAC1B,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CACzB,KAAK,CAAC,MAAM,EAAE,OAAO,aAAa;EACjC;EACA,OAAO,eAAe,KAAK;EAC3B,MAAM,cAAc,KAAK,KAAK,IAAI,CAAC;CACrC,EAAE,CAAC,CACF,QAAQ,MAAM,EAAE,MAAM,SAAS,CAAC;AACrC;;;;;AAMA,SAAS,UAAU,OAAsB;CACvC,MAAM,WAAW,MAAM,cAAc;CACrC,KAAK,MAAM,MAAM,SAAS,iBAAiB,IAAI,GAAG,GAAG,YAAY,IAAI;CACrE,OAAO,SAAS,eAAe;AACjC;;;;;AAMA,SAAS,cAAc,MAAsB;CAC3C,OAAO,KACJ,QAAQ,aAAa,GAAG,CAAC,CACzB,QAAQ,WAAW,IAAI,CAAC,CACxB,KAAK;AACV;ACzFA,MAAM,SAAS,GAAU,IAAY,QAAuB;CAAE,GAAG,EAAE,IAAI;CAAI,GAAG,EAAE,IAAI;AAAG;;AAGvF,SAAgB,WAAW,GAAe,IAAY,IAAiC;CACrF,MAAM,QAAiC,EAAE,MAAM,cAAc,EAAE,MAAM,IAAI,EAAE,EAAE;CAC7E,IAAI,WAAW,KAAK,EAAE,OAAO,MAAM,QAAQ,EAAE,MAAM,KAAK,MAAM,cAAc,GAAG,IAAI,EAAE,CAAC;CACtF,IAAI,aAAa,KAAK,EAAE,SAAS,MAAM,UAAU,EAAE,QAAQ,KAAK,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;CACtF,QAAQ,EAAE,MAAV;EACE,KAAK;GACH,MAAM,QAAQ,MAAM,EAAE,OAAO,IAAI,EAAE;GACnC,MAAM,MAAM,MAAM,EAAE,KAAK,IAAI,EAAE;GAC/B;EACF,KAAK;EACL,KAAK;GACH,MAAM,WAAW,EAAE,SAAS,KAAK,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;GACvD;EACF,KAAK,OACH,MAAM,QAAQ,EAAE,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC;CAGzE;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,gBAAgB,GAAwB;CACtD,QAAQ,EAAE,MAAV;EACE,KAAK,UACH,OAAO,EAAE,UAAU,KAAA,KAAa,EAAE,MAAM,WAAW;EACrD,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;AAOA,SAAgB,YAAY,GAAS,IAAY,IAAkB;CACjE,MAAM,QAAQ,KAAK,IAAA,GAAc,EAAE,QAAQ,EAAE;CAC7C,MAAM,SAAS,KAAK,IAAA,GAAc,EAAE,SAAS,EAAE;CAC/C,MAAM,MAAM,EAAE,IAAI,EAAE;CACpB,OAAO;EAAE,GAAG,EAAE;EAAG,GAAG,MAAM;EAAQ;EAAO;CAAO;AAClD;;;ACzDA,MAAMA,QAAM;;;;;;;;;AAUZ,SAAgB,cAAc,GAAe,GAA2B;CACtE,MAAM,SACJ,EAAE,SAAS,SACP,CAAC,EAAE,OAAO,EAAE,GAAG,IACf,EAAE,SAAS,cAAc,EAAE,SAAS,YAClC,EAAE,WACF,EAAE,SAAS,QACT,EAAE,MAAM,KAAK,IACb,KAAA;CACV,IAAI,CAAC,UAAU,OAAO,WAAW,KAAK,EAAE,iBAAiB,IAAI,OAAO,EAAE,UAAU,EAAE,IAAI;CACtF,MAAM,MAAM,EAAE,UAAU,YAAY,MAAM,CAAC;CAC3C,MAAM,MAAM,KAAK,IAAI,EAAE,YAAY,EAAE,WAAW,GAAG,CAAC,IAAI;CACxD,OAAO;EACL,MAAM,IAAI,OAAO;EACjB,KAAK,IAAI,MAAM;EACf,OAAO,IAAI,QAAQ,MAAM;EACzB,QAAQ,IAAI,SAAS,MAAM;CAC7B;AACF;AAEA,SAAS,YAAY,QAKnB;CACA,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;CAChC,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE;CACxB,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE;CACxB,OAAO;EAAE;EAAG;EAAG,OAAO,KAAK,IAAI,GAAG,EAAE,IAAI;EAAG,QAAQ,KAAK,IAAI,GAAG,EAAE,IAAI;CAAE;AACzE;;;;;;AAOA,SAAgB,wBACd,IACA,GACA,GACM;CACN,MAAM,MAAM,GAAG;CACf,GAAG,gBAAgB;CACnB,MAAM,MAAM,cAAc,GAAG,CAAC;CAC9B,MAAM,SAAS,MAAqB;EAClC,MAAM,IAAI,EAAE,MAAM,CAAC;EACnB,OAAO,GAAG,EAAE,IAAI,IAAI,KAAK,GAAG,EAAE,IAAI,IAAI;CACxC;CACA,MAAM,QAAQ,MAAc,UAAuD;EACjF,MAAM,IAAI,IAAI,gBAAgBA,OAAK,IAAI;EACvC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC;EACvE,OAAO;CACT;CAEA,IAAI,EAAE,SAAS,QAAQ;EAErB,MAAM,MAAM,OAAO,KAAK,IAAI,OAAO,IAAI,MAAM;EAC7C,MAAM,MAAM,KAAK,QAAQ;GACvB,GAAG;GACH,GAAG;GACH,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,MAAM;GACN,QAAQ;GACR,kBAAkB;EACpB,CAAC;EACD,IAAI,UAAU,IAAI,cAAc;EAChC,IAAI,OAAO,GAAG;EACd,MAAM,OAAO,IAAI,cAAc,MAAM;EACrC,KAAK,YAAY;EACjB,KAAK,QAAQ,OAAO,EAAE;EACtB,GAAG,OAAO,KAAK,IAAI;EACnB;CACF;CACA,IAAI,EAAE,SAAS,YAAY;EAGzB,MAAM,OAAO,IAAI,cAAc,KAAK;EACpC,KAAK,YAAY;EACjB,KAAK,cAAc,EAAE;EACrB,KAAK,QAAQ,QAAQ,EAAE;EACvB,KAAK,MAAM,YAAY,mBAAmB,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG;EAC1E,KAAK,MAAM,YAAY,oBAAoB,EAAE,KAAK;EAClD,KAAK,MAAM,YAAY,iBAAiB,OAAO,EAAE,OAAO,CAAC;EACzD,KAAK,MAAM,YAAY,qBAAqB,UAAU,EAAE,UAAU,CAAC;EAEnE,KAAK,MAAM,gBAAgB;EAC3B,GAAG,OAAO,IAAI;EACd;CACF;CAEA,MAAM,MAAM,OAAO,KAAK,IAAI,OAAO,IAAI,MAAM;CAC7C,IAAI,UAAU,IAAI,sBAAsB;CAExC,QAAQ,EAAE,MAAV;EACE,KAAK;GACH,KAAK,MAAM,KAAK,EAAE,OAChB,IAAI,OACF,KAAK,WAAW;IACd,QAAQ,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;IACzC,MAAM,EAAE;IACR,gBAAgB,EAAE;GACpB,CAAC,CACH;GAEF;EACF,KAAK;EACL,KAAK;EACL,KAAK;GACH,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C,KAAK,MAAM,KAAK,EAAE,OAAO;IACvB,MAAM,MAAM,WAAW,EAAE,MAAM,CAAC;IAChC,IAAI,OACF,KAAK,YAAY;KACf,QAAQ,IAAI,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;KAC/B,MAAM;KACN,QAAQ,EAAE;KACV,gBAAgB,EAAE,YAAY,aAAa,CAAC,CAAC;IAC/C,CAAC,CACH;GACF;GACA;EACF,KAAK,UAAU;GACb,MAAM,SAAS,EAAE,QACb,EAAE,MAAM,KAAK,MACX,KAAK,WAAW,EAAE,QAAQ,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAChE,IACA,CAAC,KAAK,QAAQ;IAAE,GAAG;IAAG,GAAG;IAAG,OAAO,IAAI;IAAO,QAAQ,IAAI;GAAO,CAAC,CAAC;GACvE,KAAK,MAAM,KAAK,QAAQ;IACtB,EAAE,aAAa,QAAQ,EAAE,IAAI;IAC7B,EAAE,aAAa,gBAAgB,MAAM;IACrC,EAAE,aAAa,UAAU,EAAE,KAAK;IAChC,EAAE,aAAa,gBAAgB,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC;GACd;GACA,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK;EACL,KAAK,UAAU;GACb,MAAM,KAAK,EAAE,YAAY,EAAE,WAAW;GACtC,MAAM,QACJ,EAAE,SAAS,WACP,KAAK,QAAQ;IACX,GAAG,KAAK;IACR,GAAG,KAAK;IACR,OAAO,KAAK,IAAI,GAAG,IAAI,QAAQ,EAAE;IACjC,QAAQ,KAAK,IAAI,GAAG,IAAI,SAAS,EAAE;GACrC,CAAC,IACD,KAAK,WAAW;IACd,IAAI,IAAI,QAAQ;IAChB,IAAI,IAAI,SAAS;IACjB,IAAI,KAAK,IAAI,GAAG,IAAI,QAAQ,IAAI,KAAK,CAAC;IACtC,IAAI,KAAK,IAAI,GAAG,IAAI,SAAS,IAAI,KAAK,CAAC;GACzC,CAAC;GACP,MAAM,aAAa,QAAQ,EAAE,QAAQ,MAAM;GAC3C,MAAM,aAAa,UAAU,EAAE,KAAK;GACpC,MAAM,aAAa,gBAAgB,OAAO,EAAE,CAAC;GAC7C,IAAI,OAAO,KAAK;GAChB,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK;EACL,KAAK;EACL,KAAK,WAAW;GACd,MAAM,MAAM,EAAE,SAAS,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE;GACrD,IAAI,OACF,KAAK,EAAE,SAAS,YAAY,YAAY,YAAY;IAClD,QAAQ,IAAI,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;IAC/B,MAAM,EAAE,SAAS,YAAa,EAAE,QAAQ,SAAU;IAClD,QAAQ,EAAE;IACV,gBAAgB,EAAE,YAAY,EAAE,WAAW;IAC3C,mBAAmB;GACrB,CAAC,CACH;GACA,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK;GACH,KAAK,MAAM,QAAQ,EAAE,OACnB,IAAI,OACF,KAAK,YAAY;IACf,QAAQ,KAAK,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;IAChC,MAAM;IACN,QAAQ,EAAE;IACV,gBAAgB,EAAE,YAAY,EAAE,WAAW;IAC3C,kBAAkB;IAClB,mBAAmB;GACrB,CAAC,CACH;GAEF,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;CAEjD;CAEA,KAAK,MAAM,SAAS,IAAI,UAAU,MAAM,aAAa,kBAAkB,gBAAgB;CACvF,GAAG,OAAO,GAAG;AACf;;;;;AAMA,SAAgB,cAAc,IAAiB,GAAe,GAAwB;CACpF,MAAM,MAAM,GAAG;CACf,GAAG,gBAAgB;CACnB,MAAM,MAAM,cAAc,GAAG,CAAC;CAC9B,MAAM,MAAM,OAAO,KAAK,IAAI,OAAO,IAAI,MAAM;CAC7C,IAAI,QAAQ,SAAS;CACrB,MAAM,QAAQ,WAAW,KAAK,EAAE,QAAQ,EAAE,QAAQ,KAAA;CAClD,MAAM,SAAS,QACX,MAAM,KAAK,MAAM;EACf,MAAM,OAAO,IAAI,gBAAgBA,OAAK,SAAS;EAC/C,KAAK,aACH,UACA,WAAW,CAAC,CAAC,CACV,KAAK,MAAM;GACV,MAAM,IAAI,EAAE,MAAM,CAAC;GACnB,OAAO,GAAG,EAAE,IAAI,IAAI,KAAK,GAAG,EAAE,IAAI,IAAI;EACxC,CAAC,CAAC,CACD,KAAK,GAAG,CACb;EACA,OAAO;CACT,CAAC,IACD,CAAC,IAAI,gBAAgBA,OAAK,MAAM,CAAC;CACrC,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,YAAY,QAAQ;GAC5B,MAAM,aAAa,SAAS,OAAO,IAAI,KAAK,CAAC;GAC7C,MAAM,aAAa,UAAU,OAAO,IAAI,MAAM,CAAC;EACjD;EACA,MAAM,aAAa,QAAQ,aAAa;EACxC,MAAM,aAAa,UAAU,MAAM;EACnC,MAAM,aAAa,kBAAkB,KAAK;EAC1C,IAAI,OAAO,KAAK;CAClB;CACA,GAAG,OAAO,GAAG;AACf;AAEA,SAAS,OAAO,KAAe,OAAe,QAA+B;CAC3E,MAAM,MAAM,IAAI,gBAAgBA,OAAK,KAAK;CAC1C,IAAI,aAAa,SAAS,OAAO,KAAK,CAAC;CACvC,IAAI,aAAa,UAAU,OAAO,MAAM,CAAC;CACzC,IAAI,aAAa,WAAW,OAAO,MAAM,GAAG,QAAQ;CACpD,IAAI,aAAa,YAAY,SAAS;CAGtC,IAAI,aAAa,WAAW,OAAO;CACnC,IAAI,aAAa,eAAe,MAAM;CACtC,OAAO;AACT;;AAGA,SAAS,WAAW,GAAkB;CACpC,OAAO;EAAC,EAAE;EAAI,EAAE;EAAI,EAAE;EAAI,EAAE;CAAE;AAChC;AAEA,MAAM,QAAQ,GAAU,GAAU,OAAsB;CACtD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;CACvB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;AACzB;AACA,MAAM,QAAQ,GAAU,MAAqB,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;;AAG5E,SAAS,aAAa,GAAiB;CACrC,OAAO,KAAK,IAAI,IAAK,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE;AAC5C;;AAGA,SAAS,WAAW,MAA8C,GAAkB;CAClF,IAAI,SAAS,aAAa,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAG,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAG,CAAC;CAC9E,MAAM,SAAS,KAAK,EAAE,IAAI,EAAE,EAAE;CAE9B,MAAM,QAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,EAAG;CAClC,MAAM,MAAM,KAAK,EAAE,IAAI,EAAE,IAAI,EAAG;CAChC,IAAI,SAAS,aAAa,OAAO,CAAC,OAAO,GAAG;CAC5C,MAAM,SAAS,KAAK,OAAO,GAAG;CAC9B,MAAM,MAAM,KAAK,IAAI,IAAK,SAAS,EAAE;CACrC,MAAM,OAAO,MAAM;CACnB,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,CAAC;CAEnD,MAAM,KAAK;EACT,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,UAAU;EAClC,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,UAAU;CACpC;CACA,MAAM,MAAe,CAAC;CACtB,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAAK;EAC/B,MAAM,IAAI,KAAK,OAAO,KAAK,IAAI,KAAK;EACpC,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM;EAC/B,IAAI,KAAK;GAAE,GAAG,EAAE,IAAI,GAAG,IAAI;GAAG,GAAG,EAAE,IAAI,GAAG,IAAI;EAAE,CAAC;CACnD;CACA,OAAO;AACT;;AAGA,SAAS,UAAU,OAAuB;CACxC,OAAO,IAAI,MAAM,QAAQ,UAAU,MAAM,CAAC,CAAC,QAAQ,OAAO,MAAM,EAAE;AACpE;;;;AC7QA,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;AAAI;;AAEvC,MAAM,YAAY;;AAGlB,MAAM,cAAwD;CAC5D,YAAY;EAAE,GAAG;EAAG,GAAG;CAAE;CACzB,WAAW;EAAE,GAAG;EAAI,GAAG;CAAE;CACzB,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE;CACtB,WAAW;EAAE,GAAG;EAAG,GAAG;CAAG;AAC3B;AAEA,MAAM,SAA6C;CACjD,WAAW;CACX,WAAW;CACX,WAAW;CACX,UAAU;CACV,MAAM;CACN,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,MAAM;CACN,UAAU;CACV,SAAS;CACT,KAAK;CACL,QAAQ;AACV;;AAGA,SAAgB,eAAe,GAAsD;CACnF,OAAO,EAAE,SAAS,YAAY,EAAE,aAC5B,iBAAiB,EAAE,WAAW,UAAU,IACxC,KAAA;AACN;AAEA,SAAS,UAAU,GAAuB;CACxC,MAAM,OACJ,EAAE,SAAS,YAAY,EAAE,WAAW,cAChC,wBACA,OAAO,EAAE;CACf,OAAO,EAAE,SAAS,GAAG,KAAK,MAAM,EAAE,WAAW;AAC/C;;AAGA,SAAS,aAAa,GAAe,GAAuB;CAC1D,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,KAAK;AACpF;AAEA,SAAS,QAAQ,MAAmB,KAAa,IAAmB;CAClE,IAAI,IAAI,KAAK,QAAQ,OAAO;MACvB,OAAO,KAAK,QAAQ;AAC3B;AAEA,SAAS,QAAQ,MAAmB,KAAa,OAAiC;CAChF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAK,QAAQ;MACxC,KAAK,QAAQ,OAAO;AAC3B;AAEA,SAAgB,cAAc,MAA+B;CAC3D,MAAM,EAAE,OAAO,SAAS;CACxB,MAAM,MAAM,KAAK,KAAK;CACtB,IAAI,YAAY,KAAK;CACrB,MAAM,OAAO,IAAI,cAAc,KAAK;CACpC,KAAK,YAAY;CACjB,KAAK,QAAQ,aAAa;CAC1B,KAAK,MAAM,UAAU;CACrB,KAAK,KAAK,OAAO,IAAI;CAErB,MAAM,2BAAW,IAAI,IAAyB;;CAE9C,MAAM,wBAAQ,IAAI,IAAiD;CACnE,MAAM,0BAAU,IAAI,IAAY;CAChC,IAAI,QAAkB,CAAC;CACvB,IAAI,YAAY;CAEhB,SAAS,QAAQ,IAAY,UAAsC;EACjE,IAAI,SAAS,IAAI,EAAE,GAAG,OAAO;EAC7B,OAAO,QAAQ,IAAI,EAAE,IAAI,UAAU;CACrC;CAEA,SAAS,WAAW,MAAmB,IAAkB;EACvD,MAAM,WAAW,IAAI,IAAI,MAAM,UAAU,IAAI,CAAC;EAC9C,MAAM,UAAU,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,CAAC;EACjD,MAAM,QAAQ,QAAQ,IAAI,QAAQ;EAClC,KAAK,QAAQ,QAAQ;EACrB,KAAK,aAAa,gBAAgB,OAAO,UAAU,UAAU,CAAC;EAC9D,KAAK,WAAW,CAAC,WAAW,UAAU,aAAa,IAAI;EACvD,MAAM,IAAI,MAAM,IAAI,EAAE;EACtB,YACE,MACA,iBAAiB,KACf,UAAU,cACV,MAAM,KAAA,KACN,CAAC,EAAE,UACH,gBAAgB,CAAC,CACrB;CACF;;CAGA,SAAS,mBAA4B;EACnC,OACE,KAAK,KAAK,QAAQ,iBAAiB,CAAC,EAAE,aAAa,eAAe,MAAM;CAE5E;CAGA,MAAM,WACJ,KAAK,KAAK,QAAQ,iBAAiB,KAAK,KAAK,KAAK,QAAQ,qBAAqB;CACjF,MAAM,WAAW,IAAI,aAAa;CAClC,IAAI;CACJ,IAAI,YAAY,UAAU;EACxB,eAAe,IAAI,eAAe;GAChC,IAAI,WAAW;GACf,KAAK,MAAM,CAAC,IAAI,SAAS,UAAU,WAAW,MAAM,EAAE;EACxD,CAAC;EACD,aAAa,QAAQ,UAAU;GAC7B,YAAY;GACZ,iBAAiB,CAAC,eAAe;EACnC,CAAC;CACH;;;;;;CAOA,SAAS,YAAY,MAAmB,MAAqB;EAC3D,MAAM,WAAW,KAAK,iBAAiB,wBAAwB;EAC/D,IAAI,CAAC,MAAM;GACT,SAAS,SAAS,MAAM,EAAE,OAAO,CAAC;GAClC;EACF;EACA,IAAI,SAAS,WAAW,QAAQ,QAAQ;EACxC,SAAS,SAAS,MAAM,EAAE,OAAO,CAAC;EAClC,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,IAAI,IAAI,cAAc,KAAK;GACjC,EAAE,YAAY;GACd,EAAE,QAAQ,SAAS;GACnB,EAAE,aAAa,eAAe,MAAM;GACpC,MAAM,MAAM;GACZ,EAAE,MAAM,UACN,2BAA2B,UAAU,YAAY,UAAU,yBACxD,OAAO,OAAO,MAAM,QAAQ,SAAS,GAAG,IAAI,GAC5C,OAAO,OAAO,MAAM,SAAS,QAAQ,GAAG,IAAI;GACjD,KAAK,OAAO,CAAC;EACf;CACF;CAEA,SAAS,gBAAgB,MAAmB,GAAqB;EAC/D,KAAK,QAAQ,OAAO,EAAE;EACtB,KAAK,QAAQ,SAAS,EAAE;EACxB,QAAQ,MAAM,UAAU,EAAE,WAAW,IAAI;EACzC,QAAQ,MAAM,UAAU,EAAE,SAAS,WAAW,EAAE,SAAS,KAAA,CAAS;EAClE,QAAQ,MAAM,cAAc,eAAe,CAAC,CAAC;EAC7C,KAAK,aAAa,cAAc,UAAU,CAAC,CAAC;CAC9C;CAEA,SAAS,cAAc,MAAmB,GAAqB;EAE7D,MAAM,MACJ,KAAK,WAAW,CAAC,MAAM,OACnB,UAAU,UAAU,EAAE,IAAI,IAC1B,cAAc,GAAG,SAAS;EAChC,KAAK,MAAM,OAAO,GAAG,IAAI,KAAK;EAC9B,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI;EAC5B,KAAK,MAAM,QAAQ,GAAG,IAAI,MAAM;EAChC,KAAK,MAAM,SAAS,GAAG,IAAI,OAAO;CACpC;CAEA,SAAS,aAAa,MAAmB,GAAqB;EAC5D,MAAM,SAAS,KAAK,WAAW,CAAC,MAAM;EACtC,QAAQ,MAAM,UAAU,MAAM;EAC9B,KAAK,MAAM,gBAAgB,SAAS,SAAS;EAE7C,IAAI,QAAQ;GACV,IAAI,MAAM,OAAO,EAAE,EAAE,GAAG,KAAK,gBAAgB;GAC7C;EACF;EACA,MAAM,OAAO,MAAM,IAAI,EAAE,EAAE;EAC3B,IAAI,MAAM,MAAM,KAAK,KAAK,MAAM,WAAW;EAG3C,IAAI,EAAE,WAAW,OAAO,cAAc,MAAM,GAAG,SAAS;OACnD,wBAAwB,MAAM,GAAG,SAAS;EAC/C,MAAM,IAAI,EAAE,IAAI;GAAE;GAAG,GAAG;EAAU,CAAC;CACrC;CAEA,SAAS,SAAS,IAAkB;EAClC,MAAM,OAAO,CAAC,EAAE,CAAC;EACjB,KAAK,aAAa,EAAE;CACtB;CAEA,SAAS,QAAQ,OAAqB;EACpC,MAAM,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,SAAS,GAAG,KAAK,CAAC;EAC9D,IAAI,OAAO,KAAA,GAAW,SAAS,IAAI,EAAE,CAAC,EAAE,MAAM;CAChD;;;;;;;CAQA,SAAS,UAAU,GAAkB,IAAqB;EACxD,MAAM,OAAO,YAAY,EAAE;EAC3B,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,OAAO;EACjC,EAAE,eAAe;EACjB,MAAM,IAAI,MAAM,IAAI,EAAE;EACtB,IAAI,CAAC,KAAK,EAAE,QAAQ,OAAO;EAC3B,IAAI,EAAE,WAAW,EAAE,SAAS;GAC1B,IAAI,gBAAgB,CAAC,GACnB,MAAM,OAAO,IAAI,EAAE,MAAM,YAAY,EAAE,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;GACjE,OAAO;EACT;EACA,MAAM,KAAK,EAAE,SAAS,KAAK;EAC3B,MAAM,OAAO,IAAI,WAAW,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;EACxD,OAAO;CACT;CAEA,SAAS,MAAM,GAAkB,IAAkB;EACjD,IAAI,UAAU,GAAG,EAAE,GAAG;EACtB,QAAQ,EAAE,KAAV;GACE,KAAK;GACL,KAAK;IACH,EAAE,eAAe;IACjB,SAAS,EAAE;IACX;GACF,KAAK;GACL,KAAK,aAAa;IAGhB,EAAE,eAAe;IACjB,MAAM,IAAI,MAAM,IAAI,EAAE;IACtB,IAAI,KAAK,CAAC,EAAE,QAAQ,MAAM,OAAO,EAAE;IACnC;GACF;GACA,KAAK;IACH,EAAE,eAAe;IACjB,MAAM,OAAO,CAAC,CAAC;IACf;GACF,KAAK;GACL,KAAK;IACH,EAAE,eAAe;IACjB,QAAQ,MAAM,QAAQ,EAAE,KAAK,EAAE,QAAQ,cAAc,IAAI,GAAG;EAGhE;CACF;CAEA,SAAS,OAAO,IAAyB;EACvC,MAAM,OAAO,IAAI,cAAc,KAAK;EACpC,KAAK,YAAY;EACjB,KAAK,QAAQ,aAAa;EAC1B,KAAK,aAAa,QAAQ,QAAQ;EAClC,KAAK,MAAM,WAAW;EACtB,KAAK,iBAAiB,sBAAsB;GAC1C,QAAQ,IAAI,EAAE;GACd,WAAW,MAAM,EAAE;EACrB,CAAC;EACD,KAAK,iBAAiB,sBAAsB;GAC1C,QAAQ,OAAO,EAAE;GACjB,WAAW,MAAM,EAAE;EACrB,CAAC;EACD,KAAK,iBAAiB,gBAAgB,MAAM;GAC1C,IAAI,EAAE,WAAW,GAAG;GAGpB,IACE,EAAE,WAAW,QACb,KAAK,aAAa,aAAa,KAC/B,EAAE,EAAE,kBAAkB,WAAW,EAAE,OAAO,QAAQ,eAAe,IAEjE;GAEF,EAAE,gBAAgB;GAClB,SAAS,EAAE;EACb,CAAC;EACD,KAAK,iBAAiB,YAAY,MAAM;GAEtC,IAAI,EAAE,WAAW,MAAM;GACvB,MAAM,GAAG,EAAE;EACb,CAAC;EACD,OAAO;CACT;CAEA,SAAS,SAAe;EACtB,IAAI,WAAW;EACf,MAAM,UAAU,MAAM,OAAO,IAAI,CAAC,CAAC,KAAK,YAAY;EACpD,MAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,EAAE,CAAC;EAC5C,MAAM,SAAS,IAAI;EACnB,IAAI,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,GAAG,OAAO,MAAM,MAAM,CAAC,GAAG;;EAE5D,IAAI,YAAY;EAEhB,IAAI,YAAY,KAAA,KAAa,CAAC,IAAI,IAAI,OAAO,GAAG;GAE9C,MAAM,IAAI,MAAM,QAAQ,OAAO;GAC/B,UACE,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM,MAAM,IAAI,IAAI,CAAC,CAAC,KACzC,MACG,MAAM,GAAG,CAAC,CAAC,CACX,QAAQ,CAAC,CACT,MAAM,MAAM,IAAI,IAAI,CAAC,CAAC;GAC3B,YAAY,YAAY,KAAA;EAC1B;EACA,KAAK,MAAM,CAAC,IAAI,SAAS,UAAU;GACjC,IAAI,IAAI,IAAI,EAAE,GAAG;GACjB,KAAK,OAAO;GACZ,SAAS,OAAO,EAAE;GAClB,MAAM,OAAO,EAAE;GACf,QAAQ,OAAO,EAAE;EACnB;EAEA,QAAQ,QAAQ,KAAK,MAAM,EAAE,EAAE;EAC/B,KAAK,MAAM,KAAK,SAAS;GACvB,IAAI,OAAO,SAAS,IAAI,EAAE,EAAE;GAC5B,IAAI,CAAC,MAAM;IACT,OAAO,OAAO,EAAE,EAAE;IAClB,SAAS,IAAI,EAAE,IAAI,IAAI;GACzB;GACA,gBAAgB,MAAM,CAAC;GACvB,cAAc,MAAM,CAAC;GACrB,aAAa,MAAM,CAAC;GACpB,WAAW,MAAM,EAAE,EAAE;EACvB;EAIA,MAAM,QAAQ,CAAC,GAAG,KAAK,QAAQ;EAC/B,IACE,MAAM,WAAW,MAAM,UACvB,MAAM,MAAM,IAAI,MAAM,MAAM,OAAO,SAAS,IAAI,EAAE,CAAC,GAEnD,KAAK,MAAM,MAAM,OAAO,KAAK,OAAO,SAAS,IAAI,EAAE,CAAE;EAEvD,IAAI,YAAY,KAAA,GAAW;GACzB,MAAM,SAAS,SAAS,IAAI,OAAO;GACnC,IAAI,UAAU,IAAI,kBAAkB,QAAQ,OAAO,MAAM,EAAE,eAAe,KAAK,CAAC;EAClF,OAAO,IAAI,WAAW;GAEpB,MAAM,SAAS,KAAK,KAAK,QAAqB,qBAAqB;GACnE,IAAI,QAAQ;IAEV,IAAI,CAAC,OAAO,aAAa,UAAU,GAAG,OAAO,WAAW;IACxD,OAAO,MAAM,EAAE,eAAe,KAAK,CAAC;GACtC;EACF;CACF;CAEA,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;CAC3C,MAAM,eAAe,MAAM,UAAU,gBAAgB;EACnD,KAAK,MAAM,CAAC,IAAI,SAAS,UAAU,WAAW,MAAM,EAAE;CACxD,CAAC;CACD,OAAO;CAEP,OAAO;EACL,SAAS;EACT,OAAO,MAAM;GACX,YAAY;GACZ,OAAO;EACT;EACA,aAAa,OAAO,SAAS,IAAI,EAAE;EACnC,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ,QAAQ;GACR,aAAa;GACb,cAAc,WAAW;GACzB,KAAK,OAAO;GACZ,SAAS,MAAM;GACf,MAAM,MAAM;GACZ,QAAQ,MAAM;GACd,QAAQ,CAAC;EACX;CACF;AACF;;;;ACrXA,SAAgB,gBAAgB,MAAmC;CACjE,MAAM,EAAE,UAAU,MAAM,MAAM,cAAc;CAC5C,MAAM,aAAa,WAAsB;EACvC,GAAI,KAAK,UACL,EAAE,UAAU,UAAmB,KAAK,UAAU,OAAO,KAAK,EAAE,IAC5D,CAAC;EACL,GAAI,KAAK,aAAa,EAAE,kBAAkB,KAAK,aAAa,KAAK,EAAE,IAAI,CAAC;CAC1E;CACA,MAAM,WAAW,mBAAmB;EAClC;EACA;EACA;EACA;EACA,GAAI,KAAK,qBAAqB,KAAA,IAC1B,CAAC,IACD,EAAE,kBAAkB,KAAK,iBAAiB;EAC9C,GAAG,UAAU,QAAQ;CACvB,CAAC;CACD,MAAM,YAAY,gBAAgB;EAChC;EACA;EACA;EACA;EACA,GAAG,UAAU,MAAM;CACrB,CAAC;CACD,MAAM,UAAU,cAAc;EAC5B;EACA;EACA,OAAO,KAAK;EACZ;EACA,GAAI,KAAK,aAAa,EAAE,aAAa,OAAe,KAAK,aAAa,EAAE,EAAE,IAAI,CAAC;EAC/E,GAAI,KAAK,WACL,EAAE,WAAW,MAAkB,KAAK,WAAW,CAAC,MAAM,KAAK,IAC3D,CAAC;CACP,CAAC;CACD,OAAO;EACL;EACA;EACA;EACA,OAAO,MAAM;GACX,SAAS,OAAO,IAAI;GACpB,UAAU,OAAO,IAAI;GACrB,QAAQ,OAAO,IAAI;EACrB;EACA,UAAU;GACR,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,SAAS,QAAQ;EACnB;CACF;AACF;;;;ACRA,SAAgB,MAAM,MAAmB,GAAgD;CACvF,MAAM,IAAI,KAAK,sBAAsB;CACrC,OAAO;EAAE,GAAG,EAAE,UAAU,EAAE;EAAM,GAAG,EAAE,UAAU,EAAE;CAAI;AACvD;;AAGA,SAAgB,aACd,MACA,GACO;CACP,MAAM,IAAI,KAAK,sBAAsB;CACrC,OAAO;EACL,GAAG,KAAK,IAAI,KAAK,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK;EACpD,GAAG,KAAK,IAAI,KAAK,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM;CACtD;AACF;;AAGA,SAAgB,OACd,KACA,GACqB;CACrB,MAAM,MAAM,IAAI,SAAS,UAAU,EAAE,SAAS,EAAE,OAAO;CACvD,IAAI,CAAC,KAAK,OAAO,KAAA;CACjB,MAAM,MAAM,MAAM,IAAI,MAAM,CAAC;CAC7B,OAAO;EAAE,GAAG;EAAK;EAAK,MAAM,IAAI,UAAU,QAAQ,GAAG;CAAE;AACzD;AAEA,SAAgBC,uBAAqB,MAA6C;CAChF,MAAM,EAAE,QAAQ;CAChB,MAAM,OAAO,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CACrD,MAAM,SAAS,SAAiB,KAAK,WAAW,MAAM;CACtD,IAAI;CACJ,MAAM,iBAAiB,IAAI,KAAK,MAAM;;CAEtC,IAAI;;CAEJ,MAAM,0BAAU,IAAI,IAAY;;CAGhC,MAAM,WAAW,MACf,YAAY,KAAA,KAAa,YAAY,EAAE;CAEzC,MAAM,UAAU,MAA0B;EACxC,IAAI,CAAC,EAAE,aAAa,EAAE,WAAW,KAAK,gBAAgB,EAAE,MAAM,GAAG;EAEjE,IAAI,QAAQ,CAAC,GAAG;EAChB,QAAQ,OAAO,EAAE,SAAS;EAC1B,UAAU,EAAE;EAEZ,MAAM,gBADS,EAAE,kBAAkB,UAAU,EAAE,SAAS,KAAA,EAE9C,QAAQ,mBAAmB,CAAC,EAAE,aAAa,iBAAiB,KAAK,KAAA;EAC3E,IAAI,SAAS,gBAAgB,GAAG,OAAO,KAAK,CAAC,GAAG,YAAY,MAAM,MAChE,QAAQ,EAAE,SAAS;CACvB;CACA,MAAM,UAAU,MAA0B;EACxC,IAAI,CAAC,EAAE,aAAa,QAAQ,CAAC,GAAG;EAGhC,IAAI,YAAY,EAAE,aAAa,EAAE,YAAY,GAAG,UAAU,KAAA;EAC1D,SAAS,gBAAgB,GAAG,OAAO,KAAK,CAAC,CAAC;CAC5C;CACA,MAAM,QAAQ,MAA0B;EACtC,IAAI,CAAC,EAAE,aAAa,EAAE,WAAW,KAAK,QAAQ,CAAC,GAAG;EAClD,IAAI,YAAY,EAAE,WAAW,UAAU,KAAA;EACvC,IAAI,QAAQ,OAAO,EAAE,SAAS,GAAG;GAC/B,QAAQ,EAAE,SAAS;GACnB;EACF;EACA,SAAS,cAAc,GAAG,OAAO,KAAK,CAAC,CAAC;EACxC,QAAQ,EAAE,SAAS;CACrB;CACA,MAAM,YAAY,MAA0B;EAC1C,IAAI,CAAC,EAAE,aAAa,QAAQ,CAAC,GAAG;EAEhC,IAAI,EAAE,SAAS,wBAAwB,YAAY,EAAE,WAAW;EAChE,IAAI,YAAY,EAAE,WAAW,UAAU,KAAA;EACvC,QAAQ,OAAO,EAAE,SAAS;EAC1B,SAAS,kBAAkB,CAAC;CAC9B;CACA,MAAM,SAAS,MAA2B;EACxC,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,YAAY,CAAC;CACxD;CAGA,SAAS,QAAQ,IAAkB;EACjC,IAAI;GACF,IAAI,KAAK,oBAAoB,EAAE;EACjC,QAAQ,CAER;CACF;CACA,SAAS,QAAQ,IAAkB;EACjC,IAAI;GACF,IAAI,IAAI,KAAK,oBAAoB,EAAE,GAAG,IAAI,KAAK,sBAAsB,EAAE;EACzE,QAAQ,CAER;CACF;CACA,IAAI,KAAK,iBAAiB,eAAe,QAAQ,EAAE,SAAS,KAAK,CAAC;CAClE,IAAI,KAAK,iBAAiB,eAAe,MAAM;CAC/C,IAAI,KAAK,iBAAiB,aAAa,IAAI;CAC3C,IAAI,KAAK,iBAAiB,iBAAiB,QAAQ;CACnD,IAAI,KAAK,iBAAiB,sBAAsB,QAAQ;CACxD,IAAI,KAAK,iBAAiB,WAAW,KAAK;CAE1C,SAAS,IAAI,IAAkB;EAC7B,MAAM,OAAO,KAAK,IAAI,EAAE;EACxB,IAAI,CAAC,MAAM,MAAM,IAAI,WAAW,gBAAgB,IAAI;EACpD,IAAI,YAAY,KAAA,GAAW;GAEzB,SAAS,kBACP,IAAI,aAAa,iBAAiB;IAAE,WAAW;IAAS,WAAW;GAAK,CAAC,CAC3E;GACA,QAAQ,IAAI,OAAO;GACnB,UAAU,KAAA;EACZ;EACA,SAAS,WAAW;EACpB,UAAU;EACV,KAAK,SAAS,GAAG;EACjB,IAAI,KAAK,QAAQ,UAAU;EAC3B,IAAI,KAAK,MAAM,SAAS,KAAK;EAC7B,OAAO,IAAI,EAAE;CACf;CACA,IAAI,KAAK,WAAW,MAAM;CAE1B,OAAO;EACL,QAAQ,SAAS,MAAM;EACvB;EACA,UAAU;GACR,SAAS,WAAW;GACpB,UAAU,KAAA;GACV,IAAI,KAAK,oBAAoB,eAAe,QAAQ,EAAE,SAAS,KAAK,CAAC;GACrE,IAAI,KAAK,oBAAoB,eAAe,MAAM;GAClD,IAAI,KAAK,oBAAoB,aAAa,IAAI;GAC9C,IAAI,KAAK,oBAAoB,iBAAiB,QAAQ;GACtD,IAAI,KAAK,oBAAoB,sBAAsB,QAAQ;GAC3D,IAAI,KAAK,oBAAoB,WAAW,KAAK;GAC7C,OAAO,IAAI,KAAK,QAAQ;GACxB,IAAI,KAAK,MAAM,SAAS;EAC1B;CACF;AACF;;;;;;;AAQA,SAAgB,gBAAgB,GAAkB,MAA4B;CAC5E,IAAI,EAAE,QAAQ,WAAW,EAAE,kBAAkB,OAAO;CACpD,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,OAAO;CAC9E,MAAM,SAAS,EAAE;CACjB,IAAI,WAAW,MAAM,OAAO;CAC5B,IAAI,EAAE,kBAAkB,YAAY,CAAC,KAAK,SAAS,MAAM,GAAG,OAAO;CACnE,IAAI,OAAO,QAAQ,sBAAsB,GAAG,OAAO;CACnD,OAAO,OAAO,QAAQ,gDAAgD,MAAM;AAC9E;;;;;AAMA,SAAS,gBAAgB,QAAqC;CAC5D,IAAI,EAAE,kBAAkB,UAAU,OAAO;CACzC,MAAM,KAAK,OAAO,QAAQ,mBAAmB;CAC7C,OACE,OAAO,QACP,OAAO,UACP,GAAG,aAAa,aAAa,KAE7B,OAAO,QAAQ,eAAe,MAAM;AAExC;;;;;;;AC/PA,SAAgB,gBAAsB;CACpC,IAAI;CACJ,MAAM,gBAAyB;EAC7B,IAAI,CAAC,KAAK,OAAO;EACjB,MAAM,aAAa,IAAI,eAAe;EACtC,IAAI,WAAW,WAAW,GAAG,OAAO;EACpC,KAAK,MAAM,KAAK,YACd,IAAI,MAAM,IAAI;GACZ,MAAM;GACN,MAAM,EAAE;GACR,OAAO,EAAE;GACT,UAAU,EAAE;EACd,CAAC;EAEH,IAAI,eAAe;EACnB,OAAO;CACT;CACA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM,KAAA;EACR;EACA,cAAc;GACZ,QAAQ;EACV;EACA,UAAU,GAAG;GACX,IAAI,CAAC,CAAC,OAAO,gBAAgB,GAAG,IAAI,IAAI,KAAK,QAAQ,GAAG,EAAE,eAAe;EAC3E;CACF;AACF;;;;AClCA,MAAM,OAAO;;AAGb,MAAM,eAAe;;;;;AAMrB,SAAgB,WAAiB;CAC/B,IAAI;CACJ,IAAI;CAEJ,MAAM,SAAS,GAAgB,MAAc,OAAsB;EACjE,MAAM,IAAI,EAAE,MAAM,IAAI;GACpB,MAAM;GACN;GACA,MAAM;IAAE,GAAG,GAAG,IAAI,OAAO;IAAG,GAAG,GAAG,IAAI,OAAO;IAAG,OAAO;IAAM,QAAQ;GAAK;EAC5E,CAAC;EACD,EAAE,MAAM,OAAO,CAAC,EAAE,EAAE,CAAC;EACrB,OAAO,EAAE;CACX;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM,KAAA;GACN,OAAO,KAAA;EACT;EACA,cAAc,IAAI,KAAK,cAAc;GACnC,OAAO,iBAAiB,KAAA,IAAY,MAAM,KAAA;GAC1C,OAAO,SAAS,KAAA;EAClB;EACA,kBAAkB;GAChB,OAAO,KAAA;EACT;EACA,YAAY,IAAI,KAAK;GACnB,MAAM,UAAU;GAChB,OAAO,KAAA;GACP,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,IAAI,SAAS,QAAQ,MAAM;GAC3D,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,IAAI;GACxC,IAAI,aAAa,EAAE;EACrB;EACA,UAAU,GAAG;GACX,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,IAAI,IAAI,GAAG;GAC3C,EAAE,eAAe;GACjB,MAAM,IAAI;GACV,MAAM,OAAO,EAAE,SAAS,YAAY,IAAI;GACxC,MAAM,EAAE,QAAQ,EAAE,SAAS,aAAa,IAAI,CAAC,CAAC;GAC9C,MAAM,KAAK,MAAM,GAAG,MAAM;IAAE,GAAG,IAAI,IAAI,IAAI,QAAQ;IAAG,GAAG,IAAI,IAAI,IAAI,SAAS;GAAE,CAAC;GACjF,eAAe,GAAG,EAAE;GACpB,EAAE,aAAa,EAAE;EACnB;CACF;AACF;;;;;;AAOA,SAAS,eAAe,KAAkB,IAAkB;CAC1D,MAAM,MAAM,IAAI,KAAK;CACrB,MAAM,aACJ,IAAI,KAAK,cAA2B,qBAAqB,IAAI,OAAO,EAAE,EAAE,GAAG;CAC7E,MAAM,MAAM,KAAK;CACjB,IAAI,KAAK;EACP,IAAI,MAAM,EAAE,eAAe,KAAK,CAAC;EACjC;CACF;CACA,IAAI,SAAS;CACb,MAAM,OAAO,IAAI;CACjB,MAAM,aAAmB;EACvB,IAAI,IAAI,kBAAkB,IAAI,MAAM;EACpC,MAAM,KAAK,KAAK;EAChB,IAAI,IAAI,GAAG,MAAM,EAAE,eAAe,KAAK,CAAC;OACnC,IAAI,EAAE,SAAS,cAAc,MAAM,sBAAsB,IAAI;CACpE;CACA,MAAM,sBAAsB,IAAI;AAClC;;;;AC7EA,MAAM,UAAU;AAEhB,SAAgB,iBAAuB;CACrC,IAAI;CACJ,IAAI;CACJ,IAAI;;CAGJ,MAAM,sBAA+B;EACnC,IAAI,CAAC,KAAK,OAAO;EACjB,MAAM,aAAa,IAAI,eAAe;EACtC,IAAI,WAAW,WAAW,GAAG,OAAO;EACpC,KAAK,MAAM,KAAK,YACd,IAAI,MAAM,IAAI;GAAE,MAAM;GAAU,MAAM,EAAE;GAAM,OAAO,EAAE;EAAM,CAAC;EAChE,IAAI,eAAe;EACnB,OAAO;CACT;CAEA,MAAM,cAAoB;EACxB,OAAO,OAAO;EACd,QAAQ,KAAA;EACR,QAAQ,KAAA;CACV;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK,cAAc;GAClC,IAAI,CAAC,OAAO,iBAAiB,KAAA,GAAW;GACxC,QAAQ;GAGR,EAAE,eAAe;GACjB,OAAO;EACT;EACA,cAAc,GAAG;GACf,IAAI,CAAC,OAAO;GAGZ,IAAI,EAAE,YAAY,KAAK,CAAC,MAAM,KAAK,aAAa;IAC9C,MAAM;IACN;GACF;GACA,MAAM,MAAM,aAAa,MAAM,MAAM,CAAC;GACtC,IAAI,CAAC,OAAO;IACV,QAAQ,MAAM,KAAK,cAAc,cAAc,KAAK;IACpD,MAAM,YAAY;IAClB,MAAM,QAAQ,WAAW;IACzB,MAAM,MAAM,WAAW;IACvB,MAAM,MAAM,gBAAgB;IAC5B,MAAM,KAAK,OAAO,KAAK;GACzB;GACA,MAAM,MAAM,OAAO,GAAG,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;GACnD,MAAM,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;GAClD,MAAM,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,EAAE;GACrD,MAAM,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,EAAE;EACxD;EACA,kBAAkB;GAChB,MAAM;EACR;EACA,YAAY,GAAG;GACb,IAAI,CAAC,OAAO,CAAC,OAAO;GACpB,IAAI,CAAC,MAAM,KAAK,aAAa;IAC3B,MAAM;IACN;GACF;GACA,MAAM,MAAM,aAAa,MAAM,MAAM,CAAC;GACtC,MAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC;GAC1C,MAAM,SAAS,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC;GAC3C,IAAI,SAAS,WAAW,UAAU,SAAS;IACzC,MAAM,OAAO,MAAM,UAAU,YAAY;KACvC,MAAM,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC;KACjC,KAAK,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC;KAChC;KACA;IACF,CAAC;IACD,IAAI,MAAM,IAAI;KAAE,MAAM;KAAU,MAAM,MAAM;KAAM;IAAK,CAAC;GAC1D,OACE,cAAc;GAEhB,MAAM;EACR;EACA,UAAU,GAAG;GAEX,IAAI,CAAC,CAAC,OAAO,gBAAgB,GAAG,IAAI,IAAI,KAAK,cAAc,GAAG,EAAE,eAAe;EACjF;CACF;AACF;;;ACvFA,MAAM,UAA6B;CAAC;CAAM;CAAM;CAAM;AAAI;;AAG1D,MAAM,iBAAiB;AAiBvB,SAAgB,aAAmB;CACjC,IAAI;CACJ,IAAI,OAAa,EAAE,MAAM,OAAO;CAEhC,MAAM,cAAoB;EACxB,IAAI,KAAK,SAAS,WAAW,KAAK,GAAG,OAAO;EAC5C,KAAK,KAAK,SAAS,UAAU,KAAK,SAAS,aAAa,KAAK,IAAI;GAC/D,KAAK,GAAG,MAAM,YAAY;GAC1B,KAAK,GAAG,MAAM,kBAAkB;EAClC;EACA,OAAO,EAAE,MAAM,OAAO;CACxB;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK,cAAc;GAClC,IAAI,CAAC,OAAO,CAAC,KAAK;GAClB,MAAM;GACN,IAAI,iBAAiB,KAAA,GAAW;IAC9B,MAAM,SAAS,SAAS,EAAE,MAAM;IAChC,MAAM,IAAI,WAAW,KAAA,IAAY,KAAA,IAAY,IAAI,MAAM,IAAI,YAAY;IACvE,IAAI,WAAW,KAAA,KAAa,KAAK,CAAC,EAAE,UAAU,gBAAgB,CAAC,GAAG;KAGhE,EAAE,gBAAgB;KAClB,EAAE,eAAe;KACjB,MAAM,KACJ,IAAI,KAAK,cACP,qBAAqB,IAAI,OAAO,YAAY,EAAE,GAChD,KAAK,KAAA;KACP,OAAO;MACL,MAAM;MACN,IAAI;MACJ,OAAO;MACP;MACA,KAAK,IAAI,UAAU,UAAU,EAAE,IAAI;MACnC;KACF;KACA,OAAO;IACT;IACA,IAAI,EAAE,UAAU;KAEd,EAAE,gBAAgB;KAClB,MAAM,WAAW,IAAI,MAAM,UAAU,IAAI;KACzC,IAAI,MAAM,OACR,SAAS,SAAS,YAAY,IAC1B,SAAS,QAAQ,MAAM,MAAM,YAAY,IACzC,CAAC,GAAG,UAAU,YAAY,CAChC;KACA;IACF;IAEA,OAAO;KAAE,MAAM;KAAS,IAAI;KAAc,OAAO;IAAI;IACrD,EAAE,eAAe;IACjB,OAAO;GACT;GACA,MAAM,KAAK,IAAI,KAAK,cAAc,cAAc,KAAK;GACrD,GAAG,YAAY;GACf,GAAG,QAAQ,aAAa;GACxB,GAAG,MAAM,UAAU,8CAA8C,IAAI,IAAI,EAAE,SAAS,IAAI,IAAI,EAAE;GAC9F,IAAI,KAAK,OAAO,EAAE;GAClB,OAAO;IAAE,MAAM;IAAW,OAAO;IAAK;IAAI,UAAU,EAAE;GAAS;GAC/D,IAAI,CAAC,EAAE,UAAU,IAAI,MAAM,OAAO,CAAC,CAAC;GACpC,EAAE,eAAe;GACjB,OAAO;EACT;EACA,cAAc,GAAG;GACf,IAAI,CAAC,OAAO,KAAK,SAAS,QAAQ;GAGlC,IAAI,EAAE,YAAY,KAAK,CAAC,KAAK,MAAM,KAAK,aAAa;IACnD,MAAM;IACN;GACF;GACA,MAAM,EAAE,UAAU;GAClB,IAAI,KAAK,SAAS,UAAU;IAC1B,MAAM,EAAE,KAAK,OAAO;IACpB,MAAM,OAAO,UAAU,KAAK,KAAK,QAAQ,SAAS,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC;IACzE,IAAI,IAAI;KACN,GAAG,MAAM,kBAAkB;KAC3B,GAAG,MAAM,YACP,aAAa,KAAK,OAAO,IAAI,KAAK,MAAM,KAAK,MAAM,IAAI,IAAI,YAClD,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,SAAS,IAAI,OAAO;IACjE;IACA;GACF;GACA,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC;GAC/B,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI;GAC7B,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI;GAC7B,IAAI,KAAK,SAAS,SAAS;IACzB,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI,gBAAgB;IACzC,MAAM,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE;IAC/B,IAAI,CAAC,KAAK,EAAE,QAAQ;KAClB,OAAO,EAAE,MAAM,OAAO;KACtB;IACF;IACA,MAAM,KACJ,MAAM,KAAK,cACT,qBAAqB,IAAI,OAAO,KAAK,EAAE,EAAE,GAC3C,KAAK,KAAA;IACP,OAAO;KAAE,MAAM;KAAQ,IAAI,KAAK;KAAI;KAAO;IAAG;GAChD;GACA,IAAI,KAAK,SAAS,QAAQ;IACxB,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,YAAY,aAAa,GAAG,MAAM,GAAG;IAChE;GACF;GACA,KAAK,GAAG,MAAM,OAAO,GAAG,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;GACrD,KAAK,GAAG,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;GACpD,KAAK,GAAG,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE,EAAE;GACtC,KAAK,GAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,EAAE;EACzC;EACA,kBAAkB;GAChB,MAAM;EACR;EACA,YAAY,GAAG;GACb,IAAI,CAAC,KAAK;GACV,MAAM,UAAU;GAChB,MAAM;GACN,IAAI,QAAQ,SAAS,UAAU,CAAC,QAAQ,MAAM,KAAK,aAAa;GAChE,IAAI,QAAQ,SAAS,QAAQ;IAC3B,MAAM,EAAE,UAAU;IAClB,MAAM,MAAM,MAAM,UAAU,QAAQ,MAAM,MAAM,MAAM,CAAC,CAAC;IACxD,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE;IAClC,IAAI,KAAK,CAAC,EAAE,QACV,IAAI,MAAM,OACR,EAAE,IACF,WAAW,GAAG,IAAI,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,MAAM,KAAK,CAAC,CAC1D;GACJ,OAAO,IAAI,QAAQ,SAAS,UAAU;IACpC,MAAM,EAAE,OAAO,QAAQ;IACvB,MAAM,OAAO,UAAU,KAAK,QAAQ,QAAQ,SAAS,SAAS,CAAC,GAAG,OAAO,KAAK,CAAC;IAC/E,IACE,KAAK,SAAS,IAAI,QAClB,KAAK,QAAQ,IAAI,OACjB,KAAK,UAAU,IAAI,SACnB,KAAK,WAAW,IAAI,QAEpB;IACF,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE;IAClC,IAAI,CAAC,KAAK,EAAE,QAAQ;IACpB,MAAM,IAAI,MAAM,UAAU,YAAY,IAAI;IAC1C,IAAI,MAAM,OAAO,EAAE,IAAI,EACrB,MAAM;KACJ,GAAG;KACH,OAAO,KAAK,IAAA,GAAc,EAAE,KAAK;KACjC,QAAQ,KAAK,IAAA,GAAc,EAAE,MAAM;IACrC,EACF,CAAC;GACH,OAAO,IAAI,QAAQ,SAAS,WAAW;IACrC,MAAM,EAAE,UAAU;IAClB,MAAM,MAAM,eACV,MAAM,MACN,MAAM,UAAU,QAAQ,MAAM,MAAM,MAAM,CAAC,CAAC,CAC9C;IACA,IAAI,IAAI,UAAU,KAAK,IAAI,WAAW,GAAG;IACzC,MAAM,MAAM,IAAI,MACb,OAAO,MAAM,IAAI,CAAC,CAClB,QAAQ,MAAM,eAAe,EAAE,MAAM,GAAG,CAAC,CAAC,CAC1C,KAAK,MAAM,EAAE,EAAE;IAClB,IAAI,MAAM,OACR,QAAQ,WAAW,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,IAAI,MAAM,UAAU,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,GAC5E;GACF;EACF;EACA,UAAU,GAAG;GACX,IAAI,CAAC,KAAK;GACV,IAAI,EAAE,QAAQ,UAAU;IACtB,MAAM;IACN,IAAI,MAAM,OAAO,CAAC,CAAC;IACnB;GACF;GACA,IAAI,EAAE,QAAQ,YAAY,EAAE,QAAQ,aAAa;GAGjD,IAAI,EAAE,kBAAkB;GAExB,KADe,EAAE,kBAAkB,UAAU,EAAE,SAAS,KAAA,EAE9C,QACN,wFACF,GAEA;GACF,KAAK,MAAM,MAAM,IAAI,MAAM,UAAU,IAAI,GACvC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,EAAE,WAAW,MAAM,IAAI,MAAM,OAAO,EAAE;EAE/D;CACF;AACF;;AAGA,SAAS,SAAS,QAAgD;CAChE,IAAI,EAAE,kBAAkB,UAAU,OAAO,KAAA;CACzC,MAAM,SAAS,OAAO,QAAQ,eAAe,CAAC,EAAE,aAAa,aAAa;CAC1E,OAAO,UAAU,QAAQ,SAAS,MAAM,IAAK,SAAoB,KAAA;AACnE;;;;;;AAOA,SAAS,SACP,MACA,GACO;CACP,MAAM,EAAE,OAAO,KAAK,WAAW;CAC/B,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC;CAC/B,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI;CACpF,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,UAAU,IAAI,IAAI,MAAM,IAAI;CACnF,MAAM,EAAE,UAAU,cAAc,MAAM;CACtC,OAAO;EACL,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,QAAQ;EACpC,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,SAAS;CACvC;AACF;;AAGA,SAAS,OAAO,OAAwB;CACtC,OAAO,MAAM,UAAU,YAAA,CAAoB;AAC7C;;AAGA,SAAS,UAAU,KAAc,QAAgB,GAAU,KAAsB;CAC/E,IAAI,OAAO,IAAI;CACf,IAAI,MAAM,IAAI;CACd,IAAI,QAAQ,IAAI,OAAO,IAAI;CAC3B,IAAI,SAAS,IAAI,MAAM,IAAI;CAC3B,IAAI,OAAO,OAAO,KAAK,OAAO,KAAK,IAAI,EAAE,GAAG,QAAQ,GAAG;MAClD,QAAQ,KAAK,IAAI,EAAE,GAAG,OAAO,GAAG;CACrC,IAAI,OAAO,OAAO,KAAK,MAAM,KAAK,IAAI,EAAE,GAAG,SAAS,GAAG;MAClD,SAAS,KAAK,IAAI,EAAE,GAAG,MAAM,GAAG;CACrC,OAAO;EAAE;EAAM;EAAK,OAAO,QAAQ;EAAM,QAAQ,SAAS;CAAI;AAChE;;;;ACnRA,SAAgB,WAAiB;CAC/B,OAAO;EAAE,IAAI;EAAQ,QAAQ;EAAQ,WAAW,CAAC;EAAG,aAAa,CAAC;CAAE;AACtE;;;;ACmBA,SAAgB,eAAuB;CACrC,OAAO;EAAC,SAAS;EAAG,WAAW;EAAG,cAAc;EAAG,eAAe;EAAG,SAAS;CAAC;AACjF;;AAGA,SAAgB,qBACd,MACgB;CAChB,OAAOC,uBAAW;EAAE,GAAG;EAAM,OAAO,KAAK,SAAS,aAAa;CAAE,CAAC;AACpE;;;;ACrBA,MAAa,cAAgD;CAC3D,MAAM;CACN,QAAQ;CACR,WAAW;CACX,eAAe;CACf,MAAM;AACR;;AAGA,MAAa,cAAiC;CAAC;CAAK;CAAM;CAAG;CAAM;CAAK;CAAG;CAAG;AAAC;;;;ACpB/E,SAAgB,qBAAqB,MAAkB,IAAgC;CACrF,OAAO,KAAK,cAA2B,qBAAqB,IAAI,OAAO,EAAE,EAAE,GAAG;AAChF;;;;;;;AAQA,SAAgB,yBACd,MACA,IACA,UACY;CACZ,IAAI;CACJ,MAAM,gBAAsB;EAC1B,MAAM,QAAQ,qBAAqB,MAAM,EAAE;EAC3C,IAAI,UAAU,MAAM;EACpB,OAAO;EACP,SAAS,KAAK;CAChB;CACA,QAAQ;CACR,MAAM,WAAW,IAAI,iBAAiB,OAAO;CAC7C,SAAS,QAAQ,MAAM;EAAE,WAAW;EAAM,SAAS;CAAK,CAAC;CACzD,aAAa,SAAS,WAAW;AACnC;;;;;;;;AChBA,SAAgB,2BAA2B,QAAqC;CAC9E,IAAI,EAAE,kBAAkB,UAAU,OAAO;CACzC,MAAM,aAAa,OAAO,QAAQ,mBAAmB;CACrD,IAAI,CAAC,YAAY,OAAO;CACxB,OAAO,WAAW,cAAc,CAAC,WAAW,aAAa,aAAa;AACxE;AAmBA,SAAgB,kBAAkB,MAAuC;CACvE,IAAI,YAA2B,CAAC;;CAEhC,IAAI,WAAW;CAEf,OAAO;EACL,aAAa,QAAQ,QAAQ;GAC3B,YAAY,CAAC;GACb,WAAW;GAEX,MAAM,WAAW,QAAQ,gBACrB,CAAC,GAAG,OAAO,cAAc,QAAQ,CAAC,CAAC,QAChC,OACC,cAAc,eAAe,GAAG,aAAa,iBAAiB,CAClE,IACA,CAAC;GACL,MAAM,IAAI,SAAS,SAAS,QAAQ,MAAM,IAAI;GAC9C,IAAI,KAAK,GAAG;IACV,MAAM,QAAQ,SAAS,MAAM,IAAI,CAAC;IAClC,MAAM,YAAY,SAAS,MAAM,QAAQ,OAAO,GAAG,QAAQ,MAAM,CAAC,IAAI,CAAC;IACvE,UAAU,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;GAC1E;EACF;EACA,iBAAiB,OAAO,QAAQ;GAC9B,MAAM,eAAe;GACrB,MAAM,OAAO;GACb,MAAM,UAAU;GAChB,YAAY,CAAC;GACb,WAAW;GACX,MAAM,OAAO,KAAK,KAAK;GACvB,IAAI,CAAC,MAAM;GAGX,MAAM,YAAY,KAAK,UAAU;GACjC,IAAI,cAAc,QAAQ,qBAAqB,MAAM,SAAS,GAAG;GAEjE,MAAM,SAAS,KAAK,cAAc;GAClC,IAAI,UAAU,WAAW,QAAQ,KAAK,SAAS,MAAM,GAAG;GACxD,MAAM,SAAS,KAAK,cAA2B,mBAAmB;GAIlE,CADmB,UAAU,CAAC,GAAG,MAAM,MAAM,IAAI;IAAC;IAAQ,GAAG;IAAM;GAAM,EAAA,CAC9D,MAAM,OAAO,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;EACzE;CACF;AACF;;;ACHA,SAAgB,YAAY,MAAwC;CAClE,MAAM,EAAE,WAAW,IAAI,UAAU,QAAQ;CACzC,MAAM,wBAAQ,IAAI,IAAuB;CACzC,IAAI,MAAM,KAAK;CACf,IAAI,SAAS,KAAK;CAClB,IAAI,SAAS,KAAK,qBAAqB;CACvC,IAAI;CACJ,IAAI;CACJ,IAAI,iBAA6B,KAAA;CACjC,IAAI,YAAY;CAEhB,SAAS,UAAU,MAAc,MAAmB,WAAgC;;EAElF,MAAM,yBAAS,IAAI,IAAe;EAClC,IAAI,QAAyB;EAC7B,MAAM,WAAW;EACjB,MAAM,QAAQ,gBAAgB;GAC5B,UAAU;GACV;GACA;GACA;GACA,OAAO,IAAI;GACX,aAAa,OAAO,KAAK,aAAa,EAAE;GACxC,gBAAgB;GAChB,UAAU,OAAO,UAAU;IACzB,OAAO,IAAI,KAAK;IAEhB,IAAI,OAAO;IACX,QAAQ,WAAW,KAAK,IACpB,QACA,IAAI,SACF,cACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACrD,EAAE,KAAK,GACP,KACF;IACJ,KAAK,aAAa,cAAc,OAAO;IACvC,KAAK,cAAc,MAAM,KAAK;GAChC;GACA,aAAa,UAAU;IACrB,OAAO,OAAO,KAAK;IACnB,IAAI,CAAC,SAAS,OAAO,OAAO,GAAG;IAC/B,QAAQ;IACR,KAAK,gBAAgB,YAAY;IACjC,KAAK,cAAc,MAAM,IAAI;GAC/B;EACF,CAAC;EACD,MAAM,IAAI,MAAM,KAAK;EACrB,KAAK,cAAc,MAAM,OAAO,IAAI;CACtC;CAEA,SAAS,YAAY,MAAoB;EACvC,MAAM,QAAQ,MAAM,IAAI,IAAI;EAC5B,IAAI,CAAC,OAAO;EACZ,MAAM,OAAO,IAAI;EACjB,KAAK,gBAAgB,IAAI;EACzB,MAAM,QAAQ;CAChB;;CAGA,SAAS,cAAqB;EAC5B,MAAM,IAAI,GAAG,sBAAsB;EACnC,OAAO;GAAE,GAAG,EAAE,OAAO,GAAG;GAAY,GAAG,EAAE,MAAM,GAAG;EAAU;CAC9D;;CAGA,SAAS,eAAkC;EACzC,MAAM,UAAU,GAAG,cAA2B,2BAA2B;EACzE,IAAI,CAAC,SAAS,OAAO,KAAA;EACrB,MAAM,IAAI,QAAQ,sBAAsB;EACxC,OAAO;GAAE,GAAG,EAAE;GAAM,GAAG,EAAE;EAAI;CAC/B;;;;;;;CAQA,SAAS,aAAa,IAAwC;EAC5D,MAAM,IAAI,aAAa;EACvB,IAAI,CAAC,GAAG,OAAO,KAAA;EACf,MAAM,SAAS,YAAY;EAC3B,MAAM,IAAI,OAAO,IAAI,EAAE;EACvB,MAAM,IAAI,OAAO,IAAI,EAAE;EACvB,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,CAAC;EAC9B,MAAM,SAAS,MAAM,MAAM,MAAM,KAAK,EAAE,OAAO,IAAI,EAAE,MAAM,EAAE,MAAM;EAGnE,MAAM,MACJ,UACA,MAAM,MAAM,MAAM,EAAE,MAAM,CAAC,KAC3B,MAAM,MAAM,MAAM,EAAE,UAAU,GAAG,YAAY,IAAI,CAAC;EACpD,IAAI,CAAC,KAAK,OAAO,KAAA;EAEjB,MAAM,OAAO,GAAG,aAAa,IAAI,KAAK,CAAC,CAAC,QAAQ;GAAE,GAAG,IAAI,IAAI;GAAM,GAAG,IAAI,IAAI;EAAI,CAAC;EACnF,OAAO;GAAE,MAAM,IAAI;GAAO;GAAM,UAAU,WAAW,KAAA;EAAU;CACjE;;CAGA,SAAS,cAAc,IAAc,QAA4B;EAC/D,MAAM,IAAI,aAAa;EACvB,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM,EAAE,UAAU,OAAO,IAAI;EACrE,IAAI,CAAC,KAAK,CAAC,KAAK;EAChB,MAAM,MAAM,GAAG,aAAa,OAAO,IAAI,CAAC,CAAC,MAAM,OAAO,IAAI;EAC1D,MAAM,SAAS,YAAY;EAC3B,GAAG,cAAc,EAAE,IAAI,IAAI,OAAO,IAAI,IAAI,OAAO;EACjD,IAAI,OAAO,UAAU,GAAG,aAAa,EAAE,IAAI,IAAI,MAAM,IAAI,IAAI,OAAO;CACtE;CAEA,SAAS,MAAM,OAON;EACP,MAAM,KAAK,eAAe;GACxB,WAAW;GACX,UAAU;GACV,MAAM,MAAM;GACZ,GAAI,MAAM,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,MAAM,KAAK;GACvD,GAAI,MAAM,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;GACnE,GAAI,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,IAAI;GACnC,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO;GACzC,SAAS;GACT,WAAW,MAAM,OAAO,cAAc,MAAM,IAAI,IAAI,CAAC,EAAE,OAAO,SAAS;GACvE,WAAW;EACb,CAAC;EACD,MAAM,KAAK,qBAAqB;GAC9B,GAAI,MAAM,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,KAAK;GAC1D,KAAK;IACH,OAAO,IAAI;IACX,UAAU;IACV,MAAM;IACN,sBACE,kBAAkB,KAAK,SAAS;KAC9B,MAAM,OAAO,OAAO,KAAK,QAAQ,IAAI;KACrC,OAAO;MAAE;MAAM,WAAW,GAAG,aAAa,IAAI;KAAE;IAClD,CAAC;IACH,sBACE,GAAG,cAAc,aAAa,aAAa,CAAC,EAAE,gBAAgB;IAChE,aAAa,OAAO,KAAK,aAAa,EAAE;GAC1C;EACF,CAAC;EACD,WAAW;EACX,QAAQ;EACR,WAAW,mBAAmB,IAAI;GAAE,UAAU;GAAI,iBAAiB,IAAI,MAAM;EAAO,CAAC;EAGrF,IAAI,MAAM,UAAU,CAAC,MAAM,OAAO,UAAU,GAAG,aAAa,MAAM,OAAO,IAAI;OACxE,IAAI,MAAM,SAAS,KAAA,KAAa,MAAM,SAAS,GAAG,YAAY,IAAI,GACrE,GAAG,aAAa,MAAM,IAAI;EAC5B,IAAI,MAAM,QAAQ,cAAc,IAAI,MAAM,MAAM;EAChD,KAAK,UAAU,IAAI,EAAE;CACvB;CAEA,SAAS,WAAiB;EACxB,SAAS;EACT,MAAM,QAAQ;EAEd,SAAS,QAAQ;EACjB,KAAK,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,IAAI;CACxD;CAEA,MAAM;EACJ,MAAM,KAAK,QAAQ;EACnB,MAAM,KAAK;EACX,MAAM,KAAK;EACX,UAAU,KAAK;EACf,MAAM,KAAK;CACb,CAAC;CAED,OAAO;EACL,IAAI,WAAW;GACb,OAAO;EACT;EACA,IAAI,QAAQ;GACV,OAAO;EACT;EACA;EACA,QAAQ,MAAM;GACZ,IAAI,WAAW;GACf,MAAM,QAAQ;IACZ,MAAM,SAAS,KAAK,IAAI;IACxB,MAAM,SAAS,YAAY,IAAI;IAC/B,MAAM,SAAS,KAAK,IAAI;IACxB,UAAU,SAAS,SAAS,IAAI;IAChC,MAAM,MAAM,OAAO,IAAI;IACvB,QAAQ,aAAa,QAAQ;GAC/B;GACA,SAAS;GACT,IAAI,KAAK,QAAQ,KAAA,GAAW,MAAM,KAAK;GACvC,IAAI,KAAK,WAAW,KAAA,GAAW,SAAS,KAAK;GAC7C,IAAI,KAAK,sBAAsB,KAAA,GAAW,SAAS,KAAK;GACxD,MAAM,KAAK;EACb;EACA,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ,SAAS;EACX;CACF;AACF;;;;ACxRA,SAAgB,EACd,KACA,QAAgC,CAAC,GACjC,GAAG,UACuB;CAC1B,MAAM,KAAK,SAAS,cAAc,GAAG;CACrC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,GAAG,GAAG,aAAa,MAAM,KAAK;CAC9E,GAAG,OAAO,GAAG,QAAQ;CACrB,OAAO;AACT;AAEA,SAAgB,OAAO,OAAe,SAAwC;CAC5E,MAAM,IAAI,EAAE,UAAU,EAAE,MAAM,SAAS,GAAG,KAAK;CAC/C,EAAE,iBAAiB,SAAS,OAAO;CACnC,OAAO;AACT;;;;ACJA,MAAM,MAAM;AACZ,MAAM,SAAS;AACf,MAAM,WAAW;AAsBjB,SAAgB,cAAc,MAA+B;CAC3D,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,QAAQ,EAAE,OAAO;EAAE,GAAG,KAAK;EAAO,MAAM;EAAU,QAAQ;CAAG,CAAC;CACpE,SAAS,KAAK,OAAO,KAAK;CAC1B,IAAI,aAA4B;CAChC,IAAI,SAA6B;CACjC,IAAI,sBAAkC,KAAA;;CAEtC,IAAI,WAA+B;CAEnC,MAAM,cAAoB;EACxB,IAAI,CAAC,UAAU,MAAM,QAAQ;EAC7B,MAAM,IAAI,OAAO,sBAAsB;EACvC,MAAM,EAAE,YAAY,IAAI,aAAa,OAAO;EAC5C,MAAM,IAAI,MAAM;EAChB,MAAM,KAAK,MAAM;EAEjB,IAAI,MAAM,EAAE,SAAS;EACrB,IAAI,MAAM,KAAK,KAAK,UAAU,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,EAAE,MAAM,MAAM;EAC9E,MAAM,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,MAAM,CAAC;EACtD,MAAM,OAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC;EAC/D,MAAM,MAAM,WAAW;EACvB,MAAM,MAAM,OAAO,GAAG,KAAK;EAC3B,MAAM,MAAM,MAAM,GAAG,IAAI;CAC3B;CAGA,MAAM,UAAU,IAAI,eAAe,KAAK;CACxC,QAAQ,QAAQ,KAAK;CAErB,MAAM,YAAY,IAAwB,UAAU,UAAgB;EAClE,IAAI,QAAQ,QAAQ,UAAU,MAAM;EACpC,SAAS;EACT,IAAI,CAAC,IAAI;GACP,MAAM,SAAS,SAAS;GACxB,IACE,CAAC,WACD,CAAC,MAAM,UACP,kBAAkB,eAClB,MAAM,SAAS,MAAM,GACrB;IAEA,MAAM,SAAS,KAAK,cAA2B,mBAAmB;IAClE,IAAI,QAAQ;KACV,WAAW;KACX,OAAO,MAAM,EAAE,eAAe,KAAK,CAAC;IACtC;GACF;GACA,MAAM,SAAS;GACf;EACF;EACA,QAAQ,QAAQ,EAAE;EAClB,MAAM,YAAY,MAAM;EACxB,MAAM,SAAS;EACf,MAAM;EACN,IAAI,aAAa,UAAU;GACzB,MAAM,OAAO;GACb,WAAW;GACX,MAAM,SAAS,KAAK,cAA2B,mBAAmB;GAClE,IAAI,MAAM,SAAS,IAAI,KAAK,SAAS,kBAAkB,QACrD,KAAK,MAAM,EAAE,eAAe,KAAK,CAAC;EACtC;CACF;CAEA,MAAM,SAAS,MAA2B;EACxC,IAAI,EAAE,QAAQ,YAAY,MAAM,UAAU,EAAE,kBAAkB;EAE9D,MAAM,SAAS,EAAE;EACjB,IAAI,EAAE,kBAAkB,SAAS,EAAE,MAAM,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,IAC/E;EACF,EAAE,eAAe;EACjB,KAAK,UAAU;CACjB;CACA,MAAM,WAAW,MAA0B;EACzC,IAAI,MAAM,UAAU,MAAM,SAAS,EAAE,MAAc,GAAG;EAEtD,IAAI,2BAA2B,EAAE,MAAM,GAAG;EAC1C,KAAK,UAAU;CACjB;CAEA,MAAM,SAAS,MAA2B;EACxC,IAAI,EAAE,QAAQ,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS;EAC3D,MAAM,WAAW,CAAC,GAAG,MAAM,iBAA8B,QAAQ,CAAC,CAAC,CAAC,QACjE,OAAO,CAAE,GAAyB,YAAY,GAAG,YAAY,CAChE;EACA,MAAM,QAAQ,SAAS;EACvB,MAAM,OAAO,SAAS,GAAG,EAAE;EAC3B,IAAI,CAAC,SAAS,CAAC,MAAM;EACrB,MAAM,SAAS,SAAS;EACxB,IAAI,EAAE,WAAW,WAAW,QAAQ,WAAW,MAAM;EACrD,EAAE,eAAe;EAChB,CAAC,EAAE,WAAW,OAAO,MAAA,CAAO,MAAM;CACrC;CACA,MAAM,iBAAiB,WAAW,KAAK;CACvC,SAAS,iBAAiB,WAAW,KAAK;CAC1C,SAAS,iBAAiB,eAAe,SAAS,IAAI;CAEtD,SAAS,iBAAiB,UAAU,OAAO,IAAI;CAC/C,OAAO,iBAAiB,UAAU,KAAK;CAEvC,OAAO;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA,KAAK,IAAI;GACP,IAAI,OAAO,YAAY;GACvB,cAAc;GACd,aAAa;GACb,gBAAgB,yBAAyB,MAAM,IAAI,QAAQ;EAC7D;EACA,OAAO;GACL,IAAI,eAAe,MAAM;GACzB,cAAc;GACd,sBAAsB,KAAA;GACtB,aAAa;GACb,MAAM,OAAO;GACb,WAAW;GACX,SAAS,MAAM,IAAI;GAInB,qBAAqB;IACnB,IAAI,eAAe,QAAQ,CAAC,MAAM,aAAa;IAC/C,YAAY,iBACV,IAAI,MAAM,kBAAkB,EAAE,YAAY,KAAK,CAAC,GAChD,IACF;GACF,CAAC;EACH;EACA,UAAU;GACR,cAAc;GACd,QAAQ,WAAW;GACnB,SAAS,oBAAoB,WAAW,KAAK;GAC7C,SAAS,oBAAoB,eAAe,SAAS,IAAI;GACzD,MAAM,oBAAoB,WAAW,KAAK;GAC1C,SAAS,oBAAoB,UAAU,OAAO,IAAI;GAClD,OAAO,oBAAoB,UAAU,KAAK;GAC1C,MAAM,OAAO;EACf;CACF;AACF;;;ACpJA,SAAgB,kBAAkB,MAA+C;CAC/E,MAAM,EAAE,MAAM,OAAO,WAAW,gBAAgB;CAChD,MAAM,UAAU,cAAc;EAC5B;EACA,OAAO;GACL,OAAO;GACP,yBAAyB;GACzB,cAAc;EAChB;EACA;EACA,WAAW;CACb,CAAC;CACD,MAAM,SAAS,EAAE,MAAM;EAAE,OAAO;EAAc,mBAAmB;CAAG,CAAC;CACrE,IAAI,OAA0B;;CAE9B,IAAI,UAAyB;;CAE7B,MAAM,0BAAU,IAAI,IAAY;;CAEhC,MAAM,0BAAU,IAAI,IAAY;CAEhC,SAAS,QAA+B;EACtC,MAAM,IAAI,UAAU,MAAM,IAAI,OAAO,IAAI,KAAA;EACzC,OAAO,GAAG,SAAS,SAAS,IAAI;CAClC;CAEA,SAAS,SAAgC;EACvC,MAAM,OAAO,MAAM,KAAK,IAAI;EAC5B,MAAM,KAAK,UAAU,IAAI;EACzB,MAAM,IAAI,OAAO,OAAO,KAAA,IAAY,KAAK,MAAM,MAAM,EAAE,OAAO,EAAE;EAChE,OAAO,GAAG,SAAS,SAAS,WAAW,MAAM,CAAC,IAAI;CACpD;CAEA,MAAM,eAAe,MAA+B,CAAC,EAAE,UAAU,CAAC,EAAE,UAAU,KAAK;CAEnF,SAAS,YAAY,GAA4B;EAC/C,OACE,CAAC,QAAQ,IAAI,EAAE,EAAE,KAAK,YAAY,CAAC,KAAK,SAAS,MAAM,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW;CAErF;CAEA,SAAS,YAAY,IAAkB;EACrC,IAAI,QAAQ,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,CAAC,gBAAgB,MAAM,KAAK,IAAI,GAAG,EAAE,GAC7E;EACF,QAAQ,IAAI,EAAE;EACd,MAAM,OAAO,EAAE;CACjB;CAEA,SAAS,aAAa,GAAyB;EAC7C,MAAM,QAAQ,SAAS,MAAM,KAAK,IAAI,GAAG,CAAC;EAC1C,IAAI,YAAY,CAAC,KAAK,MAAM,WAAW,GAAG;GACxC,OAAO,OAAO;GACd;EACF;EACA,OAAO,gBAAgB,GAAG,MAAM,IAAI,UAAU,CAAC;EAC/C,IAAI,CAAC,OAAO,aAAa,QAAQ,MAAM,QAAQ,MAAM;CACvD;CAEA,SAAS,SAAe;EACtB,MAAM,IAAI,OAAO;EACjB,MAAM,KAAK,GAAG,MAAM;EACpB,IAAI,OAAO,SAAS;GAClB,IAAI,KAAK,MAAM;IACb,aAAa,CAAC;IACd,KAAK,KAAK,CAAC;GACb;GACA;EACF;EACA,MAAM,WAAW;EACjB,UAAU;EACV,IAAI,GAAG;GACL,MAAM,WAAW,QAAQ,MAAM,SAAS,SAAS,aAAa;GAC9D,MAAM,UAAU,QAAQ,MAAM;GAC9B,OAAO,iBAAiB,GAAG;IAAE;IAAQ,QAAQ;IAAc;GAAM,CAAC;GAClE,QAAQ,MAAM,gBAAgB,KAAK,OAAO;GAC1C,aAAa,CAAC;GACd,QAAQ,KAAK,EAAE,EAAE;GACjB,KAAK,WAAW,aAAa,CAAC,QAAQ,MAAM,QAAQ,KAAK,SAAS,MAAM;EAC1E,OAAO;GACL,OAAO;GACP,QAAQ,KAAK;EACf;EAGA,IAAI,aAAa,MAAM,YAAY,QAAQ;CAC7C;CAEA,SAAS,OAAO,MAAoB;EAClC,MAAM,IAAI,MAAM;EAChB,IAAI,CAAC,GAAG;EACR,QAAQ,IAAI,EAAE,EAAE;EAChB,IAAI,YAAY,CAAC,GAAG,MAAM,OAAO,EAAE,IAAI,EAAE,UAAU,KAAK,CAAC;OAEvD,MAAM,IAAI;GACR,MAAM;GACN,MAAM,EAAE;GACR,MAAM,EAAE;GACR,UAAU;GACV,WAAW,EAAE;EACf,CAAC;CACL;;CAGA,SAAS,eAAqB;EAC5B,MAAM,IAAI,MAAM;EAChB,IAAI,CAAC,KAAK,EAAE,QAAQ;EACpB,YAAY,aAAa,QAAQ,MAAM;EACvC,QAAQ,IAAI,EAAE,EAAE;EAChB,MAAM,OAAO,EAAE,EAAE;EACjB,UAAU,IAAI,IAAI;CACpB;CAEA,SAAS,QAAc;EACrB,MAAM,IAAI,MAAM;EAChB,IAAI,KAAK,YAAY,CAAC,GAAG,YAAY,aAAa,QAAQ,MAAM;EAEhE,UAAU,IAAI,IAAI;CACpB;CAEA,MAAM,QAAQ,CAAC,MAAM,KAAK,UAAU,MAAM,GAAG,UAAU,UAAU,MAAM,CAAC;CACxE,OAAO;CAEP,OAAO,EACL,UAAU;EACR,KAAK,MAAM,QAAQ,OAAO,KAAK;EAC/B,QAAQ,QAAQ;CAClB,EACF;AACF;AAEA,SAAS,WAAW,GAA8B;CAChD,OAAO,EACL,MACA;EACE,OAAO;EACP,wBAAwB;EACxB,GAAI,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,CAAC;CAC5C,GACA,EAAE,QAAQ,EAAE,OAAO,oBAAoB,GAAG,EAAE,UAAU,WAAW,GACjE,EACE,QACA;EAAE,OAAO;EAAmB,UAAU,EAAE;CAAU,GAClD,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC,eAAe,CACvC,GACA,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,EAAE,YAAY,EAAE,CACvD;AACF;AASA,SAAS,iBACP,GACA,SACY;CACZ,MAAM,WAAW,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;CAC5C,MAAM,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;CAC3C,MAAM,SAAS,OAAO,UAAU,QAAQ,MAAM;CAQ9C,MAAM,UAAU,EACd,QACA;EAAE,OAAO;EAAoB,yBAAyB;CAAG,GACzD,UAVgB,EAChB,OACA,EAAE,OAAO,qBAAqB,GAC9B,MACA,QACA,OAAO,SAAS,QAAQ,KAAK,CAM7B,CACF;CACA,MAAM,iBAAuB;EAC3B,KAAK,WAAW,CAAC,SAAS,MAAM,KAAK;CACvC;CACA,SAAS,iBAAiB,SAAS,QAAQ;CAC3C,QAAQ,iBAAiB,WAAW,MAAM;EACxC,EAAE,eAAe;EACjB,MAAM,OAAO,SAAS,MAAM,KAAK;EACjC,IAAI,CAAC,MAAM;EAEX,SAAS,QAAQ;EACjB,SAAS;EACT,QAAQ,OAAO,IAAI;CACrB,CAAC;CAED,SAAS,KAAK,MAA4B;EACxC,MAAM,QAAQ,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU,KAAK,IAAI,YAAY;EACnE,SAAS,aAAa,cAAc,KAAK;EACzC,SAAS,cAAc;EACvB,KAAK,cAAc;EACnB,IAAI,KAAK,QAAQ,OAAO,OAAO;OAC1B,IAAI,CAAC,OAAO,aAAa,KAAK,MAAM,MAAM;CACjD;CACA,KAAK,CAAC;CACN,SAAS;CACT,OAAO;EAAE;EAAS;EAAU;CAAK;AACnC;;;AC5MA,SAAgB,qBAAqB,MAAkD;CACrF,MAAM,EAAE,MAAM,OAAO,WAAW,gBAAgB;CAChD,MAAM,UAAU,cAAc;EAC5B;EACA,OAAO;GACL,OAAO;GACP,4BAA4B;GAC5B,cAAc;EAChB;EACA;EACA,WAAW;CACb,CAAC;;CAED,IAAI,QAAiC;CAErC,SAAS,WAAW,IAAwD;EAC1E,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI,KAAA;EAC/B,OAAO,GAAG,SAAS,YAAY,EAAE,WAAW,cAAc,IAAI;CAChE;CAEA,SAAS,SAAkC;EACzC,MAAM,YAAY,MAAM,UAAU,IAAI;EACtC,OACE,WAAW,UAAU,IAAI,CAAC,MACzB,UAAU,WAAW,IAAI,WAAW,UAAU,EAAE,IAAI;CAEzD;CAEA,SAAS,SAAe;EACtB,MAAM,IAAI,OAAO;EACjB,IAAI,MAAM,OAAO;EACjB,MAAM,WAAW;EACjB,QAAQ;EACR,IAAI,CAAC,GAAG;GACN,QAAQ,KAAK;GACb;EACF;EACA,MAAM,WAAW,QAAQ,MAAM,SAAS,SAAS,aAAa;EAC9D,MAAM,UAAU,aAAa,QAAQ,SAAS,OAAO,EAAE;EACvD,OAAO,CAAC;EACR,QAAQ,KAAK,EAAE,EAAE;EACjB,KAAK,WAAW,aAAa,CAAC,QAAQ,MAAM,QAC1C,QAAQ,MAAM,cAAc,QAAQ,CAAC,EAAE,MAAM;CACjD;CAEA,SAAS,OAAO,GAA2B;EACzC,MAAM,EAAE,YAAY,MAAM;EAC1B,MAAM,SAAS,IAAI,iBAAiB,EAAE,UAAU,IAAI,KAAA;EACpD,QAAQ,MAAM,gBACZ,EACE,KACA,EAAE,OAAO,wBAAwB,GACjC,EAAE,UAAU,CAAC,GAAG,GAAG,UAAU,qBAAqB,GAClD,GAAI,SACA,CACE,EACE,QACA;GAAE,OAAO;GAA6B,mBAAmB;EAAO,GAChE,GAAG,OAAO,YACZ,CACF,IACA,CAAC,CACP,GACA,GAAI,GAAG,cACH,CAAC,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,EAAE,WAAW,CAAC,IAC/D,CAAC,GACL,EACE,OACA,EAAE,OAAO,yBAAyB,GAClC,OAAO,UAAU,MAAM,GACvB,GAAI,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,WAAW,OAAO,CAAC,CACjD,CACF;CACF;CAEA,SAAS,QAAc;EACrB,UAAU,IAAI,IAAI;EAClB,MAAM,OAAO,CAAC,CAAC;CACjB;CAEA,SAAS,SAAe;EACtB,IAAI,OAAO,iBAAiB,OAAO,MAAM,EAAE;EAC3C,MAAM;CACR;;CAGA,SAAS,UAAgB;EACvB,IAAI,CAAC,SAAS,MAAM,QAAQ;EAC5B,YAAY,aAAa,QAAQ,QAAQ,6BAA2B;EACpE,MAAM,OAAO,MAAM,EAAE;EACrB,MAAM;CACR;CAEA,MAAM,QAAQ;EACZ,MAAM,KAAK,UAAU,MAAM;EAC3B,MAAM,UAAU,UAAU,MAAM;EAChC,UAAU,UAAU,MAAM;CAC5B;CACA,OAAO;CAEP,OAAO,EACL,UAAU;EACR,KAAK,MAAM,QAAQ,OAAO,KAAK;EAC/B,QAAQ,QAAQ;CAClB,EACF;AACF;;;ACzHA,MAAM,QAAQ;CACZ,MAAM;EACJ,CAAC,QAAQ,EAAE,GAAG,uCAAuC,CAAC;EACtD,CAAC,QAAQ,EAAE,GAAG,yCAAyC,CAAC;EACxD,CAAC,QAAQ,EAAE,GAAG,2CAA2C,CAAC;EAC1D,CACE,QACA,EACE,GAAG,oGACL,CACF;CACF;CACA,mBAAmB,CACjB,CACE,QACA,EACE,GAAG,uIACL,CACF,CACF;CACA,aAAa,CACX,CAAC,QAAQ,EAAE,GAAG,oBAAoB,CAAC,GACnC,CAAC,QAAQ,EAAE,GAAG,+DAA+D,CAAC,CAChF;CACA,QAAQ,CAAC,CAAC,QAAQ;EAAE,OAAO;EAAM,QAAQ;EAAM,GAAG;EAAK,GAAG;EAAK,IAAI;CAAI,CAAC,CAAC;CACzE,kBAAkB,CAChB,CACE,QACA,EACE,GAAG,sHACL,CACF,CACF;CACA,WAAW;EACT,CAAC,UAAU;GAAE,IAAI;GAAM,IAAI;GAAM,GAAG;EAAI,CAAC;EACzC,CAAC,QAAQ;GAAE,IAAI;GAAM,IAAI;GAAS,IAAI;GAAM,IAAI;EAAQ,CAAC;EACzD,CAAC,QAAQ;GAAE,IAAI;GAAM,IAAI;GAAM,IAAI;GAAK,IAAI;EAAK,CAAC;EAClD,CAAC,QAAQ;GAAE,IAAI;GAAK,IAAI;GAAM,IAAI;GAAM,IAAI;EAAK,CAAC;CACpD;CACA,YAAY;EACV,CAAC,UAAU;GAAE,IAAI;GAAM,IAAI;GAAM,GAAG;EAAI,CAAC;EACzC,CAAC,QAAQ;GAAE,IAAI;GAAM,IAAI;GAAS,IAAI;GAAM,IAAI;EAAQ,CAAC;EACzD,CAAC,QAAQ;GAAE,IAAI;GAAK,IAAI;GAAM,IAAI;GAAM,IAAI;EAAK,CAAC;CACpD;AACF;AAIA,MAAM,MAAM;;AAGZ,SAAgB,KAAK,MAA4B;CAC/C,MAAM,MAAM,SAAS,gBAAgB,KAAK,KAAK;CAC/C,MAAM,QAAgC;EACpC,OAAO;EACP,OAAO;EACP,QAAQ;EACR,SAAS;EACT,MAAM;EACN,QAAQ;EACR,gBAAgB;EAChB,kBAAkB;EAClB,mBAAmB;EACnB,eAAe;CACjB;CACA,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG,IAAI,aAAa,GAAG,CAAC;CACjE,KAAK,MAAM,CAAC,KAAK,UAAU,MAAM,OAAmB;EAClD,MAAM,QAAQ,SAAS,gBAAgB,KAAK,GAAG;EAC/C,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG,MAAM,aAAa,GAAG,CAAC;EACnE,IAAI,OAAO,KAAK;CAClB;CACA,OAAO;AACT;;;AC9DA,MAAM,QAA8B;CAClC,CAAC,QAAQ,MAAM;CACf,CAAC,UAAU,iBAAiB;CAC5B,CAAC,aAAa,aAAa;CAC3B,CAAC,eAAe,QAAQ;CACxB,CAAC,QAAQ,gBAAgB;AAC3B;;AAYA,SAAS,WACP,OACA,OACA,MACA,SACmB;CACnB,MAAM,IAAI,EAAE,UAAU;EAAE,MAAM;EAAU,GAAG;EAAO,cAAc;EAAO,OAAO;CAAM,CAAC;CACrF,EAAE,OAAO,KAAK,IAAI,CAAC;CACnB,EAAE,iBAAiB,SAAS,OAAO;CACnC,OAAO;AACT;AAEA,MAAM,SAAS,MAAc,OAAe,GAAG,aAC7C,EACE,OACA;CACE,OAAO;CACP,0BAA0B;CAC1B,MAAM;CACN,cAAc;AAChB,GACA,GAAG,QACL;AAEF,SAAgB,gBAAgC;CAC9C,IAAI,QAAwB,CAAC;CAC7B,IAAI,QAAgF;CACpF,MAAM,SAAY,GAAgB,OAAiC;EACjE,GAAG,EAAE,IAAI,CAAC;EACV,MAAM,KAAK,EAAE,UAAU,EAAE,CAAC;CAC5B;CAEA,MAAM,cAAc,MAAM,KAAK,CAAC,IAAI,UAClC,WACE,YAAY,KACZ;EAAE,OAAO;EAAmB,wBAAwB;EAAI,aAAa;CAAG,GACxE,YACM,OAAO,MAAM,IAAI,EAAE,CAC3B,CACF;CACA,MAAM,YAAY,WAAgC;EAChD,KAAK,MAAM,KAAK,aAAa;GAC3B,MAAM,KAAK,EAAE,QAAQ,SAAS;GAC9B,EAAE,QAAQ,QAAQ,KAAK,OAAO;GAC9B,EAAE,aAAa,gBAAgB,OAAO,EAAE,CAAC;EAC3C;CACF;CAEA,MAAM,UAAU,WACd,YACA;EAAE,OAAO;EAAgB,qBAAqB;CAAG,GACjD,kBACM,OAAO,SAAS,OAAO,EAAG,CAClC;CACA,MAAM,SAAS,WACb,WACA;EAAE,OAAO;EAAe,oBAAoB;CAAG,GAC/C,iBACM,OAAO,SAAS,OAAO,IAAI,CACnC;CAGA,MAAM,SAAS,EAAE,UAAU,EAAE,OAAO,SAAS,CAAC;CAC9C,MAAM,aAAa,EACjB,UACA;EAAE,OAAO;EAAmB,wBAAwB;EAAI,cAAc;CAAO,GAC7E,EAAE,UAAU,EAAE,OAAO,YAAY,GAAG,WAAW,GAC/C,EAAE,UAAU,EAAE,OAAO,WAAW,GAAG,UAAU,GAC7C,GAAG,YAAY,KAAK,MAClB,EAAE,UAAU,EAAE,OAAO,OAAO,CAAC,EAAE,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,EAAE,EAAE,CAC7D,CACF;CACA,WAAW,iBAAiB,gBAAgB;EAC1C,MAAM,IAAI,WAAW;EACrB,IAAI,MAAM,eAAe,MAAM,YAAY,OAAO,SAAS,QAAQ,CAAC;OAC/D,IAAI,MAAM,UAAU,OAAO,SAAS,QAAQ,OAAO,CAAC,CAAC;CAC5D,CAAC;CAGD,MAAM,YAAY,EAAE,SAAS;EAC3B,OAAO;EACP,uBAAuB;EACvB,MAAM;EACN,WAAW;EACX,cAAc;EACd,KAAK;CACP,CAAC;CACD,MAAM,mBAAyB;EAC7B,IAAI,CAAC,OAAO;EACZ,MAAM,EAAE,aAAa;EACrB,MAAM,IAAI,OAAO,UAAU,KAAK;EAChC,MAAM,UAAU,SAAS,YAAY,IAAI;EACzC,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,QACpD;OAAA,IAAI,MAAM,SAAS,SAAS,aAAa,IAAI,CAAC;EAAA,OAC7C,UAAU,QAAQ,OAAO,UAAU,CAAC;CAC7C;CAEA,UAAU,iBAAiB,UAAU,UAAU;CAC/C,UAAU,iBAAiB,YAAY,MAAM;EAC3C,IAAI,EAAE,QAAQ,WAAW,EAAE,kBAAkB;EAC7C,EAAE,eAAe;EACjB,WAAW;CACb,CAAC;CACD,MAAM,YAAY,EAAE,QAAQ;EAC1B,OAAO;EACP,uBAAuB;EACvB,aAAa;CACf,CAAC;CAED,MAAM,WAAW;EAAC,GAAG;EAAa;EAAS;EAAY;EAAQ;CAAS;CACxE,MAAM,UAAU,EACd,OACA;EACE,OAAO;EACP,oBAAoB;EACpB,4BAA4B;EAC5B,MAAM;EACN,cAAc;EACd,oBAAoB;CACtB,GACA,MAAM,SAAS,SAAS,GAAG,WAAW,GACtC,MAAM,QAAQ,QAAQ,SAAS,YAAY,MAAM,GACjD,MAAM,QAAQ,QAAQ,WAAW,SAAS,CAC5C;CACA,MAAM,SAAS,eAAe,OAAO;CAErC,SAAS,OAAa;EACpB,KAAK,MAAM,KAAK,OAAO,EAAE;EACzB,QAAQ,CAAC;EACT,QAAQ;CACV;CAEA,SAAS,SAAe;EACtB,KAAK;EACL,KAAK,MAAM,KAAK,UAAU,EAAE,WAAW;EACvC,SAAS,IAAI;EACb,OAAO,OAAO;EACd,WAAW,QAAQ;EACnB,UAAU,QAAQ;EAClB,UAAU,cAAc;EACxB,OAAO,KAAK;CACd;CAEA,OAAO;CAEP,OAAO;EACL;EACA,KAAK,KAAK,UAAU,OAAO;GAEzB,KAAK;GACL,QAAQ;IAAE;IAAK;IAAU;GAAM;GAC/B,KAAK,MAAM,KAAK,UAAU,EAAE,WAAW;GACvC,MAAM,MAAM,QAAQ,QAAQ;GAC5B,MAAM,SAAS,OAAO,MAAM;IAC1B,MAAM,QACJ,OAAO,MAAM,WACT,YAAY,MAAM,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,IAAK,IAC/C,KAAA;IACN,IAAI,OAAO,MAAM,YAAY,UAAU,KAAA,GAAW;KAChD,OAAO,cAAc,GAAG,KAAK,MAAM,IAAI,GAAG,EAAE;KAC5C,WAAW,OAAO,MAAM;KACxB,WAAW,QAAQ;IACrB,OAAO;KACL,OAAO,OAAO;KACd,WAAW,QAAQ,OAAO,MAAM,WAAW,OAAO,KAAK,IAAI;IAC7D;GACF,CAAC;GACD,MAAM,QAAQ,IAAI,MAAM;GACxB,UAAU,MAAM,OAAO,KAAK;GAC5B,UAAU,cAAc,MAAM;GAC9B,MAAM,SAAS,cAAc,MAAM;IACjC,UAAU,QAAQ,OAAO,IAAI,CAAC;GAChC,CAAC;GACD,OAAO,KAAK;EACd;EACA;EACA,UAAU;GACR,KAAK;GACL,OAAO,QAAQ;GACf,QAAQ,OAAO;EACjB;CACF;AACF;;AAGA,MAAM,QAAQ;;;;;;;AAQd,SAAS,eAAe,KAAqD;CAC3E,IAAI,UAA8B;CAClC,MAAM,cACJ,CAAC,GAAG,IAAI,iBAAoC,KAAK,CAAC,CAAC,CAAC,QACjD,OAAO,CAAC,GAAG,YAAY,CAAC,GAAG,QAAQ,UAAU,CAChD;CACF,MAAM,aAAmB;EACvB,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,WAAW,CAAC,KAAK,SAAS,OAAO,GAAG,UAAU,KAAK,MAAM;EAC9D,KAAK,MAAM,MAAM,IAAI,iBAA8B,KAAK,GACtD,GAAG,WAAW,OAAO,UAAU,IAAI;CAEvC;CACA,MAAM,aAAa,MAAwB;EACzC,MAAM,SAAS,EAAE;EACjB,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG;EAC/B,UAAU;EACV,KAAK;CACP;CACA,MAAM,aAAa,MAA2B;EAC5C,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS;EAC9D,MAAM,OAAO,MAAM;EACnB,MAAM,IAAI,KAAK,QAAQ,EAAE,MAAqB;EAC9C,IAAI,IAAI,GAAG;EACX,MAAM,OAAO,KAAK,SAAS;EAC3B,MAAM,OACJ,EAAE,QAAQ,eACN,MAAM,OACJ,IACA,IAAI,IACN,EAAE,QAAQ,cACR,MAAM,IACJ,OACA,IAAI,IACN,EAAE,QAAQ,SACR,IACA,EAAE,QAAQ,QACR,OACA;EACZ,IAAI,OAAO,GAAG;EACd,EAAE,eAAe;EACjB,KAAK,KAAK,CAAE,MAAM;CACpB;CAEA,MAAM,WAAW,IAAI,iBAAiB,IAAI;CAC1C,SAAS,QAAQ,KAAK;EACpB,WAAW;EACX,SAAS;EACT,YAAY;EACZ,iBAAiB,CAAC,YAAY,QAAQ;CACxC,CAAC;CACD,IAAI,iBAAiB,WAAW,SAAS;CACzC,IAAI,iBAAiB,WAAW,SAAS;CACzC,KAAK;CACL,OAAO;EACL;EACA,UAAU;GACR,SAAS,WAAW;GACpB,IAAI,oBAAoB,WAAW,SAAS;GAC5C,IAAI,oBAAoB,WAAW,SAAS;EAC9C;CACF;AACF;;;ACnOA,SAAgB,aAAa,IAAiB,MAAmC;CAC/E,MAAM,EACJ,QAAQ,SACR,QACA,UACA,UACA,SACA,SAAS,cAAc,MACvB,OAAO,YAAY,MACnB,aAAa,kBAAkB,MAC/B,SACA,SACA,YACA,SACA,aACA,eACA,aACA,GAAG,SACD;CACJ,MAAM,SAAS,SAAoB,EAAE,OAAO,OAAO,CAAC;CACpD,MAAM,UAAU,SAA6B,IAAI;CACjD,MAAM,SAAS,SAA8B,IAAI;;CAEjD,MAAM,YAAY,SAAwB,IAAI;CAE9C,MAAM,OAAO,EAAE,OAAO;EAAE,iBAAiB;EAAI,cAAc;CAAO,CAAC;CACnE,MAAM,SAAS,EAAE,OAAO;EACtB,OAAO;EACP,mBAAmB;EACnB,UAAU;EACV,MAAM;EACN,cAAc;CAChB,CAAC;CACD,MAAM,eAAe,EACnB,OACA;EAAE,OAAO;EAAqB,0BAA0B;EAAI,cAAc;CAAO,GACjF,MACF;CACA,MAAM,UAAU,cAAc,cAAc,IAAI;CAChD,IAAI,SAAS,KAAK,OAAO,QAAQ,OAAO;CACxC,KAAK,OAAO,YAAY;CACxB,GAAG,OAAO,IAAI;CAEd,MAAM,cAAc,kBAAkB;EACpC,YAAY;EACZ,iBAAiB,UAAU,IAAI;CACjC,CAAC;CAED,IAAI,WAA+B;CACnC,SAAS,aAAa,GAAoB;EACxC,KAAK,QAAQ,QAAQ,EAAE;EACvB,aAAa,QAAQ,QAAQ,EAAE;EAC/B,UAAU,OAAO;EACjB,WAAW;EACX,IAAI,EAAE,UAAU,WACd,WAAW,EACT,OACA;GAAE,OAAO;GAAc,MAAM;GAAU,aAAa;EAAS,GAC7D,mBACF;OACK,IAAI,EAAE,UAAU,SAErB,WAAW,EACT,OACA;GAAE,OAAO;GAAwB,MAAM;EAAQ,GAC/C,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,oCAAoC,GACzE,EACE,KACA,CAAC,GACD,EAAE,QAAQ;GAAE,OAAO;GAAkB,OAAO,EAAE,MAAM;EAAQ,GAAG,EAAE,MAAM,IAAI,CAC7E,CACF;EAEF,IAAI,UAAU,aAAa,QAAQ,QAAQ;CAC7C;CACA,SAAS,UAAU,GAAoB;EACrC,aAAa,CAAC;EACd,OAAO,IAAI,CAAC;CACd;;CAGA,SAAS,MAAM,KAA8B;EAC3C,MAAM,QAAQ,IAAI;EAClB,MAAM,WAAW,CACf,YAAY,kBAAkB;GAAE;GAAM;GAAO;GAAW;EAAY,CAAC,IAAI,MACzE,kBACI,qBAAqB;GAAE;GAAM;GAAO;GAAW;EAAY,CAAC,IAC5D,IACN;EAGA,MAAM,WAAW,MAAM,KAAK,gBAAgB;GAC1C,MAAM,KAAK,UAAU,IAAI;GACzB,IAAI,OAAO,QAAQ,CAAC,MAAM,IAAI,EAAE,GAAG,UAAU,IAAI,IAAI;EACvD,CAAC;EACD,MAAM,wBAAQ,IAAI,IAAyB;EAC3C,MAAM,yBAAS,IAAI,IAAyB;EAC5C,MAAM,cAAc,SAAuB;GACzC,OAAO,IAAI,IAAI,CAAC,EAAE,OAAO;GACzB,OAAO,OAAO,IAAI;EACpB;EACA,MAAM,UAAU,YAAY;GAC1B,GAAG;GACH,WAAW;GACX,UAAU;GACV,aAAa,OAAO;IAClB,UAAU,IAAI,EAAE;IAChB,aAAa,EAAE;GACjB;GACA,UAAU,UAAU,UAAU;IAC5B,SAAS,KAAK,KAAK,UAAU,KAAK;IAClC,UAAU,UAAU,KAAK;GAC3B;GACA,cAAc,MAAM,OAAO,SAAS;IAClC,MAAM,IAAI,MAAM,IAAI;IACpB,cAAc,MAAM,OAAO,IAAI;GACjC;GAEA,gBAAgB,SAAS;IACvB,MAAM,OAAO,IAAI;IACjB,WAAW,IAAI;IACf,gBAAgB,IAAI;GACtB;GACA,cAAc,MAAM,UAAU;IAC5B,WAAW,IAAI;IACf,MAAM,OAAO,MAAM,IAAI,IAAI;IAC3B,IAAI,SAAS,MAAM;KACjB,MAAM,QAAQ,EACZ,OACA;MAAE,OAAO;MAAkB,uBAAuB;MAAI,MAAM;KAAQ,GACpE,EAAE,KAAK,CAAC,GAAG,QAAQ,OAAO,EAAE,qBAAqB,GACjD,EAAE,QAAQ,EAAE,OAAO,iBAAiB,GAAG,MAAM,IAAI,CACnD;KACA,KAAK,OAAO,KAAK;KACjB,OAAO,IAAI,MAAM,KAAK;IACxB;IACA,cAAc,MAAM,KAAK;GAC3B;EACF,CAAC;EACD,OAAO,IAAI,OAAO;EAClB,aAAa;GACX,SAAS;GACT,KAAK,MAAM,KAAK,UAAU,GAAG,QAAQ;GACrC,UAAU,IAAI,IAAI;GAClB,OAAO,IAAI,IAAI;GACf,QAAQ,QAAQ;GAChB,SAAS,OAAO;EAClB;CACF;CAEA,IAAI,QAAQ;CACZ,IAAI,YAAY;CAChB,IAAI,aAAyB,KAAA;;CAG7B,SAAS,QAAc;EACrB,KAAK;EACL,aAAa,KAAA;EACb,MAAM,MAAM,QAAQ,IAAI;EACxB,QAAQ,IAAI,IAAI;EAChB,KAAK,QAAQ;CACf;CAEA,SAAS,KAAK,QAAwB,UAAwC;EAC5E,IAAI,WAAW;EACf,MAAM,OAAO,EAAE;EACf,MAAM;EACN,UAAU,EAAE,OAAO,UAAU,CAAC;EAE9B,aAAa,QAAQ;GACnB;GACA,UAAU,UAAU,YAAY;GAChC,UAAU,YAAY,oBAAoB,IAAI;GAC9C;EACF,CAAC,CAAC,CAAC,MACA,QAAQ;GAEP,IAAI,SAAS,OAAO;IAClB,IAAI,QAAQ;IACZ;GACF;GACA,QAAQ,IAAI,GAAG;GACf,MAAM,IAAI,IAAI,OAAO,IAAI;GACzB,IAAI,EAAE,UAAU,SAAS;IACvB,UAAU,CAAC;IACX,UAAU,EAAE,KAAK;IACjB;GACF;GAGA,aAAa,EAAE,OAAO,QAAQ,CAAC;GAC/B,OAAO,MAAM,GAAG;GAChB,OAAO,IAAI,EAAE,OAAO,QAAQ,CAAC;GAE7B,IAAI,SAAS,OAAO,UAAU,GAAG;EACnC,IACC,UAAmB;GAElB,IAAI,SAAS,OAAO;GACpB,MAAM,QAAQ,WAAW,KAAK,IAC1B,QACA,IAAI,SACF,cACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACrD,CAAC,GACD,KACF;GACJ,UAAU;IAAE,OAAO;IAAS;GAAM,CAAC;GACnC,UAAU,KAAK;EACjB,CACF;CACF;CAEA,KAAK,OAAO;CAEZ,OAAO;EACL,SAAS;EACT,QAAQ,SAAS,MAAM;EACvB,UAAU,SAAS,OAAO;EAC1B,QAAQ,SAAS,MAAM;EACvB,SAAS,SAAS,WAAW;EAC7B;EACA,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ;GACA,MAAM;GACN,SAAS,QAAQ;GACjB,KAAK,OAAO;EACd;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"dom.mjs","names":["SVG","createToolController","createWith","button","button","button"],"sources":["../src/dom/transform.ts","../src/dom/layout.ts","../src/dom/viewport.ts","../src/dom/viewport-keys.ts","../src/dom/page-renderer.ts","../src/pdfjs/text-layer.ts","../src/dom/text-layer.ts","../src/dom/selection.ts","../src/model/annotations/edit.ts","../src/dom/overlay-render.ts","../src/dom/overlay.ts","../src/dom/page-mount.ts","../src/dom/tools/controller.ts","../src/dom/tools/highlight.ts","../src/dom/tools/note.ts","../src/dom/tools/redact-area.ts","../src/dom/tools/select.ts","../src/dom/tools/view.ts","../src/dom/tools/index.ts","../src/dom/ui.ts","../src/dom/annotation-element.ts","../src/dom/popover-focus.ts","../src/dom/viewer-engine.ts","../src/dom/viewer/dom.ts","../src/dom/viewer/popover.ts","../src/dom/viewer/note-popover.ts","../src/dom/viewer/suggestion-card.ts","../src/dom/viewer/create-viewer.ts","../src/dom/viewer/controls.ts"],"sourcesContent":["import {\n applyMatrix,\n invertMatrix,\n type Matrix,\n type Point,\n type Quad,\n type Rect,\n} from '../model/geometry'\n\nimport type { PageInfo } from '../model/pages'\n\nexport type ViewRotation = 0 | 90 | 180 | 270\n\n/** CSS box: `left`,`top` from the rendered page's top-left corner, in CSS pixels. */\nexport interface CssRect {\n left: number\n top: number\n width: number\n height: number\n}\n\nexport interface PageTransform {\n readonly page: PageInfo\n /** The viewer zoom the transform was built for. 1 is one CSS pixel per user-space unit at /UserUnit 1. */\n readonly zoom: number\n /**\n * CSS pixels per user-space unit: `zoom × page.userUnit`. This is PDF.js `PageViewport.scale`\n * and the value its text and annotation layers read from `--total-scale-factor`.\n */\n readonly scale: number\n /** Rotation the viewer applied on top of the page's own /Rotate. */\n readonly rotation: ViewRotation\n /** The page's /Rotate plus the viewer rotation. */\n readonly totalRotation: ViewRotation\n /** Rendered page width in CSS pixels at this zoom and total rotation. */\n readonly cssWidth: number\n /** Rendered page height in CSS pixels at this zoom and total rotation. */\n readonly cssHeight: number\n /** User space to CSS pixels. Same matrix PDF.js builds for `getViewport`. */\n readonly matrix: Matrix\n toCss(p: Point): Point\n toCssRect(r: Rect): CssRect\n toCssQuad(q: Quad): Quad\n /** Converts a length in user-space units (stroke width, font size) to CSS pixels: zoom times `/UserUnit`. */\n toCssLength(points: number): number\n fromCss(p: Point): Point\n fromCssRect(r: CssRect): Rect\n /** Converts a length in CSS pixels to user-space units. */\n fromCssLength(px: number): number\n}\n\n/** Folds any integer multiple of 90 onto 0, 90, 180 or 270. Throws `RangeError` otherwise. */\nexport function normalizeRotation(deg: number): ViewRotation {\n if (!Number.isFinite(deg) || deg % 90 !== 0) {\n throw new RangeError(`rotation must be a multiple of 90, got ${deg}`)\n }\n return (((deg % 360) + 360) % 360) as ViewRotation\n}\n\n/**\n * Port of PDF.js `PageViewport` (display/page_viewport.js) with offsetX = offsetY = 0 and\n * dontFlip = false. Using the same maths keeps the canvas, text layer and overlay aligned.\n */\nexport function createPageTransform(\n page: PageInfo,\n zoom: number,\n viewRotation: ViewRotation = 0\n): PageTransform {\n const rotation = normalizeRotation(viewRotation)\n const totalRotation = normalizeRotation(page.rotate + rotation)\n // PDF.js PageViewport does `scale *= userUnit`; zoom 1 is one user-space unit, so 1 point only when userUnit is 1.\n const scale = zoom * page.userUnit\n const x0 = page.box.x\n const y0 = page.box.y\n const x1 = page.box.x + page.box.width\n const y1 = page.box.y + page.box.height\n const centerX = (x1 + x0) / 2\n const centerY = (y1 + y0) / 2\n let rotateA: number\n let rotateB: number\n let rotateC: number\n let rotateD: number\n switch (totalRotation) {\n case 180:\n rotateA = -1\n rotateB = 0\n rotateC = 0\n rotateD = 1\n break\n case 90:\n rotateA = 0\n rotateB = 1\n rotateC = 1\n rotateD = 0\n break\n case 270:\n rotateA = 0\n rotateB = -1\n rotateC = -1\n rotateD = 0\n break\n default:\n rotateA = 1\n rotateB = 0\n rotateC = 0\n rotateD = -1\n }\n let offsetCanvasX: number\n let offsetCanvasY: number\n let cssWidth: number\n let cssHeight: number\n if (rotateA === 0) {\n offsetCanvasX = Math.abs(centerY - y0) * scale\n offsetCanvasY = Math.abs(centerX - x0) * scale\n cssWidth = Math.abs(y1 - y0) * scale\n cssHeight = Math.abs(x1 - x0) * scale\n } else {\n offsetCanvasX = Math.abs(centerX - x0) * scale\n offsetCanvasY = Math.abs(centerY - y0) * scale\n cssWidth = Math.abs(x1 - x0) * scale\n cssHeight = Math.abs(y1 - y0) * scale\n }\n const matrix: Matrix = [\n rotateA * scale,\n rotateB * scale,\n rotateC * scale,\n rotateD * scale,\n offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,\n offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY,\n ]\n const inverse = invertMatrix(matrix)\n const toCss = (p: Point): Point => applyMatrix(matrix, p)\n const fromCss = (p: Point): Point => applyMatrix(inverse, p)\n\n const bounds = (\n points: Point[]\n ): { x: number; y: number; width: number; height: number } => {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y }\n }\n\n return {\n page,\n zoom,\n scale,\n rotation,\n totalRotation,\n cssWidth,\n cssHeight,\n matrix,\n toCss,\n fromCss,\n toCssRect(r) {\n const b = bounds([\n toCss({ x: r.x, y: r.y }),\n toCss({ x: r.x + r.width, y: r.y }),\n toCss({ x: r.x, y: r.y + r.height }),\n toCss({ x: r.x + r.width, y: r.y + r.height }),\n ])\n return { left: b.x, top: b.y, width: b.width, height: b.height }\n },\n toCssQuad(q) {\n return { p1: toCss(q.p1), p2: toCss(q.p2), p3: toCss(q.p3), p4: toCss(q.p4) }\n },\n toCssLength: (points) => points * scale,\n fromCssRect(r) {\n return bounds([\n fromCss({ x: r.left, y: r.top }),\n fromCss({ x: r.left + r.width, y: r.top }),\n fromCss({ x: r.left, y: r.top + r.height }),\n fromCss({ x: r.left + r.width, y: r.top + r.height }),\n ])\n },\n fromCssLength: (px) => px / scale,\n }\n}\n","import { createPageTransform, type ViewRotation } from './transform'\n\nimport type { PageInfo } from '../model/pages'\n\nexport type LayoutMode = 'single' | 'continuous'\n\n/** Where one page sits inside the pages element, in CSS pixels. */\nexport interface CssPageBox {\n index: number\n left: number\n top: number\n width: number\n height: number\n}\n\n/** Every laid-out page plus the size of the pages element, in CSS pixels. */\nexport interface CssLayout {\n boxes: CssPageBox[]\n width: number\n height: number\n}\n\nexport interface CssLayoutInput {\n pages: readonly PageInfo[]\n zoom: number\n rotation: ViewRotation\n /** Gap above, between and below pages, CSS px. */\n gap: number\n mode: LayoutMode\n /** The page shown in `single` mode. */\n current: number\n /** The container's content width (client width less padding), CSS px. Narrower pages are centred. */\n containerWidth: number\n}\n\nfunction cssSize(page: PageInfo, zoom: number, rotation: ViewRotation) {\n const t = createPageTransform(page, zoom, rotation)\n return { width: t.cssWidth, height: t.cssHeight }\n}\n\n/** Stacks pages vertically, centred horizontally, with `gap` around each. */\nexport function computeCssLayout(input: CssLayoutInput): CssLayout {\n const pages =\n input.mode === 'single'\n ? input.pages.filter((p) => p.index === input.current)\n : input.pages\n const sizes = pages.map((p) => cssSize(p, input.zoom, input.rotation))\n // A reduce, not Math.max(...spread): spreading hundreds of thousands of pages overflows the stack.\n const width = sizes.reduce((max, s) => Math.max(max, s.width), input.containerWidth)\n let top = input.gap\n const boxes = pages.map((p, i): CssPageBox => {\n const s = sizes[i]!\n const box = {\n index: p.index,\n left: (width - s.width) / 2,\n top,\n width: s.width,\n height: s.height,\n }\n top += s.height + input.gap\n return box\n })\n return { boxes, width, height: top }\n}\n\n/** The zoom at which `page` fits a container of the given CSS size, less `padding` on each side. */\nexport function fitZoomCss(\n page: PageInfo,\n rotation: ViewRotation,\n container: { width: number; height: number },\n mode: 'fit-width' | 'fit-page',\n padding: number\n): number {\n const size = cssSize(page, 1, rotation)\n const byWidth = (container.width - padding * 2) / size.width\n if (mode === 'fit-width') return Math.max(0.05, byWidth)\n const byHeight = (container.height - padding * 2) / size.height\n return Math.max(0.05, Math.min(byWidth, byHeight))\n}\n\n/**\n * Indexes of pages intersecting [scrollTop, scrollTop + viewportHeight], extended by\n * `buffer` pages each side. Past the end it returns the last page plus its buffer.\n */\nexport function visibleRangeCss(\n layout: CssLayout,\n scrollTop: number,\n viewportHeight: number,\n buffer: number\n): number[] {\n const boxes = layout.boxes\n if (boxes.length === 0) return []\n const bottom = scrollTop + viewportHeight\n let first = boxes.findIndex((b) => b.top + b.height >= scrollTop)\n if (first === -1) first = boxes.length - 1\n let last = first\n while (last + 1 < boxes.length && boxes[last + 1]!.top <= bottom) last++\n const from = Math.max(0, first - buffer)\n const to = Math.min(boxes.length - 1, last + buffer)\n return boxes.slice(from, to + 1).map((b) => b.index)\n}\n\n/** The page with the most visible height in the viewport; the first page on a tie. */\nexport function mostVisiblePageCss(\n layout: CssLayout,\n scrollTop: number,\n viewportHeight: number\n): number {\n let best = layout.boxes[0]?.index ?? 0\n let bestArea = -1\n const bottom = scrollTop + viewportHeight\n for (const b of layout.boxes) {\n const visible = Math.max(\n 0,\n Math.min(b.top + b.height, bottom) - Math.max(b.top, scrollTop)\n )\n if (visible > bestArea) {\n bestArea = visible\n best = b.index\n }\n }\n return best\n}\n","/*\n * Inline styles. The headless DOM layer sets only what it cannot work without:\n * - container: `overflow: auto`, and `position: relative` when its computed position is static;\n * - pages element: `position: relative`, plus `width`/`height` from the layout;\n * - page hosts: `position: absolute` and `left`/`top`/`width`/`height` from the layout;\n * - page hosts: the `--scale-factor` (zoom) and `--total-scale-factor` (zoom × /UserUnit)\n * custom properties.\n * Nothing cosmetic (colours, borders, backgrounds, fonts) is ever set inline; that belongs to\n * the stylesheet. `destroy()` restores the container's overflow and position.\n */\nimport { readonly, writable, type Readable } from '../model/readable'\n\nimport {\n computeCssLayout,\n fitZoomCss,\n mostVisiblePageCss,\n visibleRangeCss,\n type CssLayout,\n type CssPageBox,\n type LayoutMode,\n} from './layout'\nimport { createPageTransform, type PageTransform, type ViewRotation } from './transform'\n\nimport type { InkDocument } from '../model/document'\nimport type { Point, Rect } from '../model/geometry'\n\nexport type ZoomValue = number | 'fit-width' | 'fit-page'\n\nexport interface ViewportOptions {\n container: HTMLElement\n document: InkDocument\n /** Default `'fit-width'`. */\n zoom?: ZoomValue\n /** Default `'continuous'`. */\n mode?: LayoutMode\n /** Default 0. */\n rotation?: ViewRotation\n /** Gap between pages, and the page padding used by fit modes, CSS px. Default 16. */\n gap?: number\n /** Pages to keep mounted either side of the visible range. Default 2. */\n buffer?: number\n /** Default 0.1. */\n minZoom?: number\n /** Default 8. */\n maxZoom?: number\n onMount(page: number, host: HTMLElement, transform: PageTransform): void\n onUpdate(page: number, host: HTMLElement, transform: PageTransform): void\n onUnmount(page: number, host: HTMLElement): void\n}\n\n/** The mounted page under a client point. The tools layer adds `user` and `css` (`PageHit`). */\nexport interface ViewportHit {\n page: number\n host: HTMLElement\n transform: PageTransform\n}\n\nexport interface Viewport {\n readonly zoom: Readable<ZoomValue>\n /** Effective numeric zoom, with fit modes resolved. */\n readonly scale: Readable<number>\n readonly currentPage: Readable<number>\n readonly mounted: Readable<readonly number[]>\n readonly layout: Readable<CssLayout>\n readonly rotation: Readable<ViewRotation>\n readonly mode: Readable<LayoutMode>\n /** `anchorCss` is relative to the container's top-left inside its border, CSS px; defaults to its centre. */\n setZoom(zoom: ZoomValue, anchorCss?: Point): void\n zoomBy(factor: number, anchorCss?: Point): void\n setMode(mode: LayoutMode): void\n setRotation(rotation: ViewRotation): void\n scrollToPage(index: number, opts?: { behavior?: ScrollBehavior }): void\n /** Scrolls so `rect` (user space on `page`) is visible, centring it when it was not. */\n scrollToRect(page: number, rect: Rect): void\n transformFor(page: number): PageTransform\n hostFor(page: number): HTMLElement | undefined\n /** The mounted page under a viewport (client) point, if any. */\n pageAtCss(clientX: number, clientY: number): ViewportHit | undefined\n destroy(): void\n}\n\nfunction sameList(a: readonly number[], b: readonly number[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i])\n}\n\nexport function createViewport(opts: ViewportOptions): Viewport {\n const { container, document: doc } = opts\n const gap = opts.gap ?? 16\n const buffer = opts.buffer ?? 2\n const minZoom = opts.minZoom ?? 0.1\n const maxZoom = opts.maxZoom ?? 8\n const clamp = (z: number): number => Math.min(maxZoom, Math.max(minZoom, z))\n\n const zoom = writable<ZoomValue>(\n typeof opts.zoom === 'number' ? clamp(opts.zoom) : (opts.zoom ?? 'fit-width')\n )\n const scale = writable(1)\n const rotation = writable<ViewRotation>(opts.rotation ?? 0)\n const mode = writable<LayoutMode>(opts.mode ?? 'continuous')\n const currentPage = writable(0)\n const mounted = writable<readonly number[]>([])\n const layout = writable<CssLayout>({ boxes: [], width: 0, height: 0 })\n\n const previousStyle = {\n overflow: container.style.overflow,\n position: container.style.position,\n }\n container.dataset.inkViewport = ''\n container.style.overflow = 'auto'\n if (getComputedStyle(container).position === 'static')\n container.style.position = 'relative'\n\n const pagesEl = container.ownerDocument.createElement('div')\n pagesEl.className = 'ink-pages'\n pagesEl.dataset.inkPages = ''\n pagesEl.style.position = 'relative'\n container.append(pagesEl)\n\n const hosts = new Map<number, HTMLElement>()\n const transforms = new Map<number, PageTransform>()\n let lastSize = { width: -1, height: -1 }\n let destroyed = false\n\n function boxFor(page: number, l = layout.get()): CssPageBox | undefined {\n return l.boxes.find((b) => b.index === page)\n }\n\n /** Where the pages element starts inside the container's scrollable content (its padding). */\n function origin(): Point {\n return { x: pagesEl.offsetLeft, y: pagesEl.offsetTop }\n }\n\n /** The container's content box, CSS px: client size less padding. The pages element sits inside it. */\n function innerSize(): { width: number; height: number } {\n const cs = getComputedStyle(container)\n const px = (v: string): number => Number.parseFloat(v) || 0\n return {\n width: container.clientWidth - px(cs.paddingLeft) - px(cs.paddingRight),\n height: container.clientHeight - px(cs.paddingTop) - px(cs.paddingBottom),\n }\n }\n\n function resolveScale(): number {\n const z = zoom.get()\n if (typeof z === 'number') return clamp(z)\n const page = doc.pages[currentPage.get()] ?? doc.pages[0]\n if (!page) return 1\n return clamp(fitZoomCss(page, rotation.get(), innerSize(), z, gap))\n }\n\n function transformFor(page: number): PageTransform {\n let t = transforms.get(page)\n if (!t) {\n const info = doc.pages[page]\n if (!info) throw new RangeError(`page ${page} out of range`)\n t = createPageTransform(info, scale.get(), rotation.get())\n transforms.set(page, t)\n }\n return t\n }\n\n function layoutOnce(): void {\n scale.set(resolveScale())\n transforms.clear()\n const l = computeCssLayout({\n pages: doc.pages,\n zoom: scale.get(),\n rotation: rotation.get(),\n gap,\n mode: mode.get(),\n current: currentPage.get(),\n containerWidth: innerSize().width,\n })\n pagesEl.style.width = `${l.width}px`\n pagesEl.style.height = `${l.height}px`\n layout.set(l)\n }\n\n /**\n * Recomputes the layout. Sizing the pages element can add or remove a scrollbar, which\n * changes the client width the layout (and a fit zoom) was based on, so it runs again\n * once when that happens.\n */\n function relayout(): void {\n const width = container.clientWidth\n layoutOnce()\n if (container.clientWidth !== width) layoutOnce()\n lastSize = { width: container.clientWidth, height: container.clientHeight }\n const l = layout.get()\n for (const [page, host] of hosts) {\n if (!boxFor(page, l)) continue\n place(page, host, l)\n opts.onUpdate(page, host, transformFor(page))\n }\n sync()\n }\n\n function place(page: number, host: HTMLElement, l: CssLayout): void {\n const box = boxFor(page, l)\n if (!box) return\n const t = transformFor(page)\n host.style.left = `${box.left}px`\n host.style.top = `${box.top}px`\n host.style.width = `${t.cssWidth}px`\n host.style.height = `${t.cssHeight}px`\n // As in PDF.js's viewer: --scale-factor is the zoom, --total-scale-factor also folds in\n // /UserUnit (pdf_viewer.css: calc(var(--scale-factor) * var(--user-unit))).\n host.style.setProperty('--scale-factor', String(t.zoom))\n host.style.setProperty('--total-scale-factor', String(t.scale))\n host.dataset.rotation = String(t.totalRotation)\n }\n\n /** Mounts and unmounts hosts for the scroll position, and updates the current page. */\n function sync(): void {\n if (destroyed) return\n const l = layout.get()\n const top = container.scrollTop - origin().y\n const wanted = visibleRangeCss(l, top, container.clientHeight, buffer)\n const wantedSet = new Set(wanted)\n for (const [page, host] of [...hosts]) {\n if (wantedSet.has(page)) continue\n hosts.delete(page)\n opts.onUnmount(page, host)\n host.remove()\n }\n for (const page of wanted) {\n if (hosts.has(page)) continue\n const host = container.ownerDocument.createElement('div')\n host.className = 'ink-page'\n host.dataset.page = String(page)\n host.style.position = 'absolute'\n place(page, host, l)\n hosts.set(page, host)\n pagesEl.append(host)\n opts.onMount(page, host, transformFor(page))\n }\n if (!sameList(mounted.get(), wanted)) mounted.set(wanted)\n if (mode.get() === 'continuous') {\n currentPage.set(mostVisiblePageCss(l, top, container.clientHeight))\n }\n }\n\n let scrollFrame = 0\n const onScroll = (): void => {\n if (scrollFrame) return\n scrollFrame = requestAnimationFrame(() => {\n scrollFrame = 0\n sync()\n })\n }\n container.addEventListener('scroll', onScroll, { passive: true })\n\n const ro = new ResizeObserver(() => {\n if (destroyed) return\n if (\n container.clientWidth === lastSize.width &&\n container.clientHeight === lastSize.height\n ) {\n return\n }\n withAnchor(undefined, () => undefined)\n })\n ro.observe(container)\n\n function pageAtCss(clientX: number, clientY: number): ViewportHit | undefined {\n for (const [page, host] of hosts) {\n const r = host.getBoundingClientRect()\n if (\n clientX >= r.left &&\n clientX <= r.right &&\n clientY >= r.top &&\n clientY <= r.bottom\n ) {\n return { page, host, transform: transformFor(page) }\n }\n }\n return undefined\n }\n\n /**\n * The page box an anchor at layout-space `y` belongs to: the one whose vertical span\n * contains it, otherwise the nearest one (an anchor in a gap or past either end).\n */\n function anchorBox(l: CssLayout, y: number): CssPageBox | undefined {\n let best: CssPageBox | undefined\n let bestDistance = Infinity\n for (const b of l.boxes) {\n const distance =\n y < b.top ? b.top - y : y > b.top + b.height ? y - b.top - b.height : 0\n if (distance < bestDistance) {\n best = b\n bestDistance = distance\n }\n }\n return best\n }\n\n /**\n * Keeps the user-space point under `anchorCss` still while `change` alters the layout.\n * The anchor is taken in layout space, so it holds in the margins and gaps too: there it\n * is extrapolated from the nearest page's transform, which is affine, so the point maps\n * back exactly. The browser may still clamp the scroll at the content edges.\n */\n function withAnchor(anchorCss: Point | undefined, change: () => void): void {\n const anchor = anchorCss ?? {\n x: container.clientWidth / 2,\n y: container.clientHeight / 2,\n }\n // Read everything from the old layout before relayout() clears the cached transforms.\n const o = origin()\n const x = container.scrollLeft + anchor.x - o.x\n const y = container.scrollTop + anchor.y - o.y\n const old = anchorBox(layout.get(), y)\n const user = old\n ? transformFor(old.index).fromCss({ x: x - old.left, y: y - old.top })\n : undefined\n change()\n relayout()\n if (!old || !user) return\n const box = boxFor(old.index)\n if (!box) return\n const after = transformFor(old.index).toCss(user)\n const o2 = origin()\n container.scrollLeft = o2.x + box.left + after.x - anchor.x\n container.scrollTop = o2.y + box.top + after.y - anchor.y\n sync()\n }\n\n const viewport: Viewport = {\n zoom: readonly(zoom),\n scale: readonly(scale),\n currentPage: readonly(currentPage),\n mounted: readonly(mounted),\n layout: readonly(layout),\n rotation: readonly(rotation),\n mode: readonly(mode),\n setZoom(z, anchorCss) {\n withAnchor(anchorCss, () => zoom.set(typeof z === 'number' ? clamp(z) : z))\n },\n zoomBy(factor, anchorCss) {\n viewport.setZoom(clamp(scale.get() * factor), anchorCss)\n },\n setMode(m) {\n if (m === mode.get()) return\n // Catch up with a scroll whose frame has not run yet, then keep that page: relayout()\n // re-derives the current page from the scroll position, which the new mode changes.\n if (mode.get() === 'continuous') sync()\n const page = currentPage.get()\n mode.set(m)\n relayout()\n viewport.scrollToPage(page)\n },\n setRotation(r) {\n withAnchor(undefined, () => rotation.set(r))\n },\n scrollToPage(index, o) {\n const page = Math.max(0, Math.min(doc.pages.length - 1, index))\n const behavior = o?.behavior ?? 'auto'\n if (mode.get() === 'single') {\n // Also relayout when the layout shows another page, even if currentPage already matches.\n if (page !== currentPage.get() || layout.get().boxes[0]?.index !== page) {\n currentPage.set(page)\n relayout()\n }\n container.scrollTo({ top: 0, behavior })\n sync()\n return\n }\n const box = boxFor(page)\n if (!box) return\n container.scrollTo({ top: Math.max(0, origin().y + box.top - gap), behavior })\n sync()\n },\n scrollToRect(page, rect) {\n if (mode.get() === 'single' && currentPage.get() !== page) {\n currentPage.set(page)\n relayout()\n }\n const box = boxFor(page)\n if (!box) return\n const css = transformFor(page).toCssRect(rect)\n const o = origin()\n const top = o.y + box.top + css.top\n if (\n top < container.scrollTop ||\n top + css.height > container.scrollTop + container.clientHeight\n ) {\n container.scrollTop = Math.max(0, top - (container.clientHeight - css.height) / 2)\n }\n const left = o.x + box.left + css.left\n if (\n left < container.scrollLeft ||\n left + css.width > container.scrollLeft + container.clientWidth\n ) {\n container.scrollLeft = Math.max(0, left - (container.clientWidth - css.width) / 2)\n }\n sync()\n },\n transformFor,\n hostFor: (page) => hosts.get(page),\n pageAtCss,\n destroy() {\n if (destroyed) return\n destroyed = true\n ro.disconnect()\n container.removeEventListener('scroll', onScroll)\n if (scrollFrame) cancelAnimationFrame(scrollFrame)\n for (const [page, host] of hosts) {\n opts.onUnmount(page, host)\n host.remove()\n }\n hosts.clear()\n transforms.clear()\n pagesEl.remove()\n delete container.dataset.inkViewport\n container.style.overflow = previousStyle.overflow\n container.style.position = previousStyle.position\n },\n }\n\n relayout()\n return viewport\n}\n","import type { Viewport } from './viewport'\n\nexport interface ViewportKeysOptions {\n viewport: Viewport\n /** Read on every key, so it follows the open document. */\n pageCount: () => number\n}\n\n/** Factor `+`/`=` zoom in by; `-` zooms out by its inverse. */\nconst ZOOM_STEP = 1.25\n\n/** Keys typed here belong to the element, not the viewport. */\nconst IGNORE =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [data-annotation]'\n\n/**\n * Keyboard shortcuts for a focused viewport container: `+` or `=` and `-` zoom, `Home` and\n * `End` go to the first and last page, `PageDown` and `PageUp` to the next and previous.\n * Events from inputs, editable content and annotation elements, chords with Ctrl, Meta or\n * Alt (browser zoom stays the browser's), and events already handled are left alone. Only\n * handled keys are prevented. Returns a function that removes the listener.\n */\nexport function attachViewportKeys(\n el: HTMLElement,\n opts: ViewportKeysOptions\n): () => void {\n const { viewport } = opts\n const onKeydown = (e: KeyboardEvent): void => {\n if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey) return\n if (e.target instanceof Element && e.target.closest(IGNORE)) return\n switch (e.key) {\n case '+':\n case '=':\n viewport.zoomBy(ZOOM_STEP)\n break\n case '-':\n viewport.zoomBy(1 / ZOOM_STEP)\n break\n case 'Home':\n viewport.scrollToPage(0)\n break\n case 'End':\n viewport.scrollToPage(opts.pageCount() - 1)\n break\n case 'PageDown':\n viewport.scrollToPage(viewport.currentPage.get() + 1)\n break\n case 'PageUp':\n viewport.scrollToPage(viewport.currentPage.get() - 1)\n break\n default:\n return\n }\n e.preventDefault()\n }\n el.addEventListener('keydown', onKeydown)\n return () => el.removeEventListener('keydown', onKeydown)\n}\n","// Inline styles here are structural only: the wrapper fills the page host and clips\n// (`position:absolute; inset:0; overflow:hidden`), and each canvas is pinned to the top-left\n// with its CSS size set from the transform (`position:absolute; left:0; top:0; width; height`).\n// Everything cosmetic (background, shadow, border) belongs to the theme.\nimport type { PageTransform } from './transform'\nimport type { InkDocument } from '../model/document'\nimport type { PdfjsRenderTask } from '../pdfjs/types'\n\nexport interface PageRendererOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`); the renderer appends its canvas layer to it. */\n host: HTMLElement\n transform: PageTransform\n /**\n * Fixed device pixel ratio. When omitted, `window.devicePixelRatio` is read at every render\n * and the page re-renders when it changes (browser zoom, moving to another screen).\n */\n devicePixelRatio?: number\n onRendered?(): void\n /** Called for any render failure other than a superseded render's cancellation. */\n onError?(error: unknown): void\n}\n\nexport interface PageRenderer {\n readonly element: HTMLElement\n /**\n * Resolves once the most recent `update` has painted, failed (see `onError`) or the\n * renderer was destroyed. Never rejects. A promise read before a later `update` resolves\n * together with that later render, so every promise handed out settles.\n */\n readonly rendered: Promise<void>\n update(transform: PageTransform): void\n destroy(): void\n}\n\nconst isCancellation = (error: unknown): boolean =>\n (error as { name?: unknown } | null)?.name === 'RenderingCancelledException'\n\nexport function createPageRenderer(opts: PageRendererOptions): PageRenderer {\n const { document: doc, page, host } = opts\n const view = host.ownerDocument.defaultView\n const currentDpr = (): number =>\n opts.devicePixelRatio ??\n (view && view.devicePixelRatio > 0 ? view.devicePixelRatio : 1)\n const wrapper = host.ownerDocument.createElement('div')\n wrapper.className = 'ink-canvas-layer'\n wrapper.dataset.inkCanvasLayer = ''\n wrapper.style.cssText = 'position:absolute;inset:0;overflow:hidden;'\n host.append(wrapper)\n\n let current: HTMLCanvasElement | undefined\n let latest = opts.transform\n let task: PdfjsRenderTask | undefined\n let destroyed = false\n let generation = 0\n\n // One deferred per busy period: renders that supersede each other share it, and it\n // resolves when the newest one settles.\n let resolvePending: (() => void) | undefined\n let rendered: Promise<void> = Promise.resolve()\n\n function settle() {\n resolvePending?.()\n resolvePending = undefined\n }\n\n /**\n * Drops a canvas for good. Zeroing it frees its bitmap now rather than at garbage\n * collection; Safari caps the total canvas memory, which a long scroll would otherwise hit.\n */\n function release(canvas: HTMLCanvasElement): void {\n canvas.width = 0\n canvas.height = 0\n canvas.remove()\n }\n\n function sizeCanvas(canvas: HTMLCanvasElement, transform: PageTransform) {\n canvas.style.width = `${transform.cssWidth}px`\n canvas.style.height = `${transform.cssHeight}px`\n }\n\n async function render(transform: PageTransform): Promise<void> {\n const gen = ++generation\n latest = transform\n const dpr = currentDpr()\n watchDpr(dpr)\n task?.cancel()\n task = undefined\n if (!resolvePending) {\n rendered = new Promise<void>((resolve) => (resolvePending = resolve))\n }\n // The previous bitmap stays visible, stretched to the new size, until the new one lands.\n if (current) sizeCanvas(current, transform)\n let canvas: HTMLCanvasElement | undefined\n try {\n const pdfPage = await doc._pdfjs.getPage(page)\n if (destroyed || gen !== generation) return\n const { AnnotationMode } = doc._pdfjs.module\n const viewport = pdfPage.getViewport({\n scale: transform.zoom,\n rotation: transform.totalRotation,\n })\n canvas = host.ownerDocument.createElement('canvas')\n canvas.dataset.inkCanvas = ''\n canvas.setAttribute('aria-hidden', 'true')\n canvas.width = Math.round(transform.cssWidth * dpr)\n canvas.height = Math.round(transform.cssHeight * dpr)\n canvas.style.cssText = 'position:absolute;left:0;top:0;'\n sizeCanvas(canvas, transform)\n const ownTask = pdfPage.render({\n canvas,\n viewport,\n // Pages are paper: an opaque white canvas, whatever the theme puts behind it.\n background: '#ffffff',\n annotationMode: AnnotationMode.ENABLE,\n ...(dpr === 1 ? {} : { transform: [dpr, 0, 0, dpr, 0, 0] }),\n })\n task = ownTask\n await ownTask.promise\n if (task === ownTask) task = undefined\n if (destroyed || gen !== generation) {\n release(canvas)\n return\n }\n if (current) release(current)\n current = canvas\n wrapper.append(canvas)\n opts.onRendered?.()\n } catch (error) {\n if (canvas && canvas !== current) release(canvas)\n const superseded = destroyed || gen !== generation\n if (!(superseded && isCancellation(error)) && !destroyed) opts.onError?.(error)\n } finally {\n if (gen === generation) settle()\n }\n }\n\n // Re-render when the device pixel ratio changes, unless the caller fixed it. The media\n // query matches only the ratio it was built for, so it is rebuilt after every change.\n // During a browser-zoom or screen transition the query can fire while devicePixelRatio\n // still reports the old value, so each change also schedules follow-up checks.\n const RECHECK_MS = [100, 500]\n let dprQuery: MediaQueryList | undefined\n let watchedDpr: number | undefined\n let rechecks: ReturnType<typeof setTimeout>[] = []\n const clearRechecks = (): void => {\n rechecks.forEach(clearTimeout)\n rechecks = []\n }\n const onDprChange = (): void => {\n if (destroyed) return\n const seen = currentDpr()\n watchDpr(seen, true)\n void render(latest)\n clearRechecks()\n rechecks = RECHECK_MS.map((ms) =>\n setTimeout(() => {\n if (!destroyed && currentDpr() !== watchedDpr) onDprChange()\n }, ms)\n )\n }\n function watchDpr(dpr: number, force = false): void {\n if (opts.devicePixelRatio !== undefined || !view?.matchMedia) return\n if (dpr === watchedDpr && !force) return\n watchedDpr = dpr\n dprQuery?.removeEventListener('change', onDprChange)\n dprQuery = view.matchMedia(`(resolution: ${dpr}dppx)`)\n dprQuery.addEventListener('change', onDprChange)\n }\n\n void render(opts.transform)\n\n return {\n element: wrapper,\n get rendered() {\n return rendered\n },\n update(transform) {\n if (destroyed) return\n void render(transform)\n },\n destroy() {\n if (destroyed) return\n destroyed = true\n dprQuery?.removeEventListener('change', onDprChange)\n dprQuery = undefined\n clearRechecks()\n task?.cancel()\n task = undefined\n if (current) release(current)\n current = undefined\n wrapper.remove()\n settle()\n },\n }\n}\n","// The only file that touches PDF.js's `TextLayer`. It takes the already-loaded PDF.js module\n// instead of importing `#pdfjs`, so `@inkbar/core/dom` can re-export the text layer without\n// evaluating PDF.js at import time.\nimport type { PdfjsModule, PdfjsPage, PdfjsViewport } from './types'\n\nexport interface MountedTextLayer {\n update(viewport: PdfjsViewport): void\n cancel(): void\n}\n\nexport interface MountPdfjsTextLayerOptions {\n /** The loaded PDF.js module, i.e. `InkDocument._pdfjs.module`. */\n module: PdfjsModule\n pdfPage: PdfjsPage\n container: HTMLElement\n viewport: PdfjsViewport\n /** Aborting cancels the render (and any later use of the layer). */\n signal?: AbortSignal\n}\n\n/**\n * Renders the page's text into `container` as positioned spans. The constructor sizes the\n * container from `--total-scale-factor` and sets `data-main-rotation`; CSS (the theme) turns\n * those into the final layout. Rejects with PDF.js's `AbortException` if `signal` aborts first.\n * On any rejection the layer is cancelled and detached from `signal`.\n */\nexport async function mountPdfjsTextLayer(\n opts: MountPdfjsTextLayerOptions\n): Promise<MountedTextLayer> {\n const layer = new opts.module.TextLayer({\n textContentSource: opts.pdfPage.streamTextContent({\n includeMarkedContent: false,\n disableNormalization: true,\n }),\n container: opts.container,\n viewport: opts.viewport,\n })\n const mounted: MountedTextLayer = {\n update(viewport) {\n layer.update({ viewport })\n },\n cancel() {\n layer.cancel()\n },\n }\n const onAbort = (): void => layer.cancel()\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n if (opts.signal?.aborted) layer.cancel()\n try {\n await layer.render()\n } catch (error) {\n // A failed layer is dropped here: cancelled, and no longer held by the caller's signal, so\n // a retry on the same signal does not keep every failed attempt alive.\n opts.signal?.removeEventListener('abort', onAbort)\n layer.cancel()\n throw error\n }\n return mounted\n}\n","// Inline styles here are structural only: the layer covers the page host\n// (`position:absolute; inset:0`) and its text must stay selectable whatever the page around it\n// sets (`user-select:text`). PDF.js sets the layer's width/height from `--total-scale-factor`.\n// Span styling (transparent colour, absolute positioning, font sizing, rotation transforms)\n// is the theme's job.\nimport { mountPdfjsTextLayer, type MountedTextLayer } from '../pdfjs/text-layer'\n\nimport type { PageTransform } from './transform'\nimport type { InkDocument } from '../model/document'\n\nexport interface TextLayerOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`), which must carry `--total-scale-factor`. */\n host: HTMLElement\n transform: PageTransform\n /**\n * Mount or update failures. Cancellation by `destroy` is not reported. If it throws, the\n * exception is rethrown asynchronously; `ready` still resolves.\n */\n onError?(error: unknown): void\n /** The layer mounted, or applied an `update`, without error. */\n onRendered?(): void\n}\n\nexport interface TextLayerHandle {\n readonly element: HTMLElement\n /** Resolves once the latest mount or `update` has applied. Never rejects. */\n readonly ready: Promise<void>\n update(transform: PageTransform): void\n destroy(): void\n}\n\nexport function createTextLayer(opts: TextLayerOptions): TextLayerHandle {\n const { document: doc, page } = opts\n const el = opts.host.ownerDocument.createElement('div')\n el.className = 'ink-text-layer'\n el.dataset.inkTextLayer = ''\n el.style.cssText = 'position:absolute;inset:0;user-select:text;'\n opts.host.append(el)\n\n const abort = new AbortController()\n let mounted: MountedTextLayer | undefined\n\n const viewportFor = async (transform: PageTransform) => {\n const pdfPage = await doc._pdfjs.getPage(page)\n return {\n pdfPage,\n viewport: pdfPage.getViewport({\n scale: transform.zoom,\n rotation: transform.totalRotation,\n }),\n }\n }\n\n // A throwing `onError` must not reject `ready`: its exception is rethrown from a microtask,\n // so it still surfaces as an uncaught error.\n const report = (error: unknown) => {\n if (abort.signal.aborted || !opts.onError) return\n try {\n opts.onError(error)\n } catch (thrown) {\n queueMicrotask(() => {\n throw thrown\n })\n }\n }\n\n const mount = async (transform: PageTransform): Promise<void> => {\n const { pdfPage, viewport } = await viewportFor(transform)\n if (abort.signal.aborted) return\n mounted = await mountPdfjsTextLayer({\n module: doc._pdfjs.module,\n pdfPage,\n container: el,\n viewport,\n signal: abort.signal,\n })\n if (!abort.signal.aborted) opts.onRendered?.()\n }\n\n let ready: Promise<void> = mount(opts.transform).catch(report)\n\n return {\n element: el,\n get ready() {\n return ready\n },\n update(transform) {\n if (abort.signal.aborted) return\n ready = ready\n .then(async () => {\n if (abort.signal.aborted) return\n // A mount that failed is tried again, so the layer can recover with the page.\n if (!mounted) {\n el.replaceChildren()\n await mount(transform)\n return\n }\n const { viewport } = await viewportFor(transform)\n if (abort.signal.aborted) return\n mounted.update(viewport)\n opts.onRendered?.()\n })\n .catch(report)\n },\n destroy() {\n if (abort.signal.aborted) return\n abort.abort()\n el.remove()\n },\n }\n}\n","import { mergeLineRects } from '../model/selection'\n\nimport type { PageTransform } from './transform'\nimport type { Quad, Rect } from '../model/geometry'\n\nexport interface SelectionQuads {\n /** Zero-based page index. */\n page: number\n /** One user-space quad per selected line, top to bottom. */\n quads: Quad[]\n text: string\n}\n\n/**\n * Converts viewport-relative CSS-pixel rects (from `getClientRects()`) to user-space rects on\n * the page rendered in `host`. Empty rects are skipped.\n */\nexport function cssRectsToUserRects(\n rects: Iterable<DOMRect>,\n host: HTMLElement,\n transform: PageTransform\n): Rect[] {\n const h = host.getBoundingClientRect()\n const out: Rect[] = []\n for (const r of rects) {\n if (r.width === 0 || r.height === 0) continue\n out.push(\n transform.fromCssRect({\n left: r.left - h.left,\n top: r.top - h.top,\n width: r.width,\n height: r.height,\n })\n )\n }\n return out\n}\n\n/**\n * Reads the live DOM selection and returns one entry per page it touches, with line-merged\n * user-space quads. Only text inside `[data-ink-text-layer]` under a `[data-page]` host counts;\n * `pageFor` maps a host to its page index and current transform.\n */\nexport function getSelectionQuads(\n root: HTMLElement,\n pageFor: (host: HTMLElement) => { page: number; transform: PageTransform } | undefined\n): SelectionQuads[] {\n const sel = root.ownerDocument.defaultView?.getSelection()\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return []\n const results = new Map<number, { rects: Rect[]; text: string[] }>()\n const layers = [...root.querySelectorAll<HTMLElement>('[data-ink-text-layer]')]\n if (root.matches('[data-ink-text-layer]')) layers.unshift(root)\n for (let i = 0; i < sel.rangeCount; i++) {\n const range = sel.getRangeAt(i)\n for (const layer of layers) {\n if (!range.intersectsNode(layer)) continue\n const host = layer.closest<HTMLElement>('[data-page]')\n if (!host) continue\n const info = pageFor(host)\n if (!info) continue\n const sub = range.cloneRange()\n if (!layer.contains(range.startContainer)) sub.setStart(layer, 0)\n if (!layer.contains(range.endContainer)) sub.setEnd(layer, layer.childNodes.length)\n const entry = results.get(info.page) ?? { rects: [], text: [] }\n entry.rects.push(...cssRectsToUserRects(sub.getClientRects(), host, info.transform))\n entry.text.push(rangeText(sub))\n results.set(info.page, entry)\n }\n }\n return [...results.entries()]\n .sort(([a], [b]) => a - b)\n .map(([page, { rects, text }]) => ({\n page,\n quads: mergeLineRects(rects),\n text: normaliseText(text.join('\\n')),\n }))\n .filter((r) => r.quads.length > 0)\n}\n\n/**\n * The range's text with each PDF.js `<br>` (an end of line) kept as a newline.\n * `Range.toString()` would run the lines together.\n */\nfunction rangeText(range: Range): string {\n const fragment = range.cloneContents()\n for (const br of fragment.querySelectorAll('br')) br.replaceWith('\\n')\n return fragment.textContent ?? ''\n}\n\n/**\n * Collapses runs of horizontal whitespace to one space and drops the spaces around a line\n * break. Breaks themselves are all kept, so a blank line (two breaks) survives.\n */\nfunction normaliseText(text: string): string {\n return text\n .replace(/[^\\S\\n]+/g, ' ')\n .replace(/ ?\\n ?/g, '\\n')\n .trim()\n}\n","// Geometry edits in user space, shared by the pointer (select tool) and keyboard (overlay)\n// paths so both produce the same patch for the same change.\nimport { translateQuad, translateRect, type Point, type Rect } from '../geometry'\n\nimport type { Annotation } from './types'\n\n/** Smallest width or height a resize leaves, user-space points. */\nexport const MIN_SIZE = 1\n\nconst shift = (p: Point, dx: number, dy: number): Point => ({ x: p.x + dx, y: p.y + dy })\n\n/** The geometry patch that translates `a` by (dx, dy) in user space. */\nexport function translated(a: Annotation, dx: number, dy: number): Partial<Annotation> {\n const patch: Record<string, unknown> = { rect: translateRect(a.rect, dx, dy) }\n if ('quads' in a && a.quads) patch.quads = a.quads.map((q) => translateQuad(q, dx, dy))\n if ('callout' in a && a.callout) patch.callout = a.callout.map((p) => shift(p, dx, dy))\n switch (a.type) {\n case 'line':\n patch.start = shift(a.start, dx, dy)\n patch.end = shift(a.end, dx, dy)\n break\n case 'polyline':\n case 'polygon':\n patch.vertices = a.vertices.map((p) => shift(p, dx, dy))\n break\n case 'ink':\n patch.inklist = a.inklist.map((path) => path.map((p) => shift(p, dx, dy)))\n break\n default:\n }\n return patch\n}\n\n/**\n * True when `rect` is the annotation's whole shape, so resizing means changing `rect`: area\n * redactions, free text, squares and circles. Text-derived marks (quads), note icons and\n * point-based shapes are not.\n */\nexport function hasRectGeometry(a: Annotation): boolean {\n switch (a.type) {\n case 'redact':\n return a.quads === undefined || a.quads.length === 0\n case 'freetext':\n case 'square':\n case 'circle':\n return true\n default:\n return false\n }\n}\n\n/**\n * Grows (positive) or shrinks (negative) a rect by `dw` and `dh` points, keeping its top-left\n * corner (user space: left edge and top edge, `y + height`) where it is. Neither side goes\n * below `MIN_SIZE`.\n */\nexport function resizedRect(r: Rect, dw: number, dh: number): Rect {\n const width = Math.max(MIN_SIZE, r.width + dw)\n const height = Math.max(MIN_SIZE, r.height + dh)\n const top = r.y + r.height\n return { x: r.x, y: top - height, width, height }\n}\n","import type { CssRect, PageTransform } from './transform'\nimport type { Annotation } from '../model/annotations/types'\nimport type { Point, Quad } from '../model/geometry'\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\n/**\n * The CSS box an annotation's default visual occupies. Usually `toCssRect(a.rect)`. Stroked\n * paths (lines, polylines, polygons, ink) use the bounds of their own points instead of\n * `rect` (which may already carry stroke padding, as a derived ink rect does), padded once by\n * half their stroke width on every side, at least 1px in all, so a horizontal or vertical\n * line still has a box to draw and hit-test in. Custom elements do not use this: they sit on\n * `toCssRect(a.rect)`.\n */\nexport function annotationBox(a: Annotation, t: PageTransform): CssRect {\n const points =\n a.type === 'line'\n ? [a.start, a.end]\n : a.type === 'polyline' || a.type === 'polygon'\n ? a.vertices\n : a.type === 'ink'\n ? a.inklist.flat()\n : undefined\n if (!points || points.length === 0 || !('width' in a)) return t.toCssRect(a.rect)\n const box = t.toCssRect(pointBounds(points))\n const pad = Math.max(t.toCssLength(a.width), 1) / 2\n return {\n left: box.left - pad,\n top: box.top - pad,\n width: box.width + pad * 2,\n height: box.height + pad * 2,\n }\n}\n\nfunction pointBounds(points: readonly Point[]): {\n x: number\n y: number\n width: number\n height: number\n} {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y }\n}\n\n/**\n * Draws the default visual for an annotation inside its positioned element. Coordinates are\n * relative to the element. Colour, opacity and stroke are SVG attributes, never inline style,\n * so a theme can override them with CSS.\n */\nexport function renderAnnotationContent(\n el: HTMLElement,\n a: Annotation,\n t: PageTransform\n): void {\n const doc = el.ownerDocument\n el.replaceChildren()\n const box = annotationBox(a, t)\n const local = (p: Point): string => {\n const c = t.toCss(p)\n return `${c.x - box.left},${c.y - box.top}`\n }\n const node = (name: string, attrs: Record<string, string | number>): SVGElement => {\n const n = doc.createElementNS(SVG, name)\n for (const [k, v] of Object.entries(attrs)) n.setAttribute(k, String(v))\n return n\n }\n\n if (a.type === 'text') {\n // The note's box is its shape: a transparent rect takes the hits, the icon is theme art.\n const svg = boxSvg(doc, box.width, box.height)\n const hit = node('rect', {\n x: 0,\n y: 0,\n width: box.width,\n height: box.height,\n fill: 'transparent',\n stroke: 'none',\n 'pointer-events': 'all',\n })\n hit.classList.add('ink-note-box')\n svg.append(hit)\n const icon = doc.createElement('span')\n icon.className = 'ink-note-icon'\n icon.dataset.icon = a.icon\n el.append(svg, icon)\n return\n }\n if (a.type === 'freetext') {\n // HTML rather than SVG <text>: a text box must wrap, and SVG text does not. Font size,\n // colour and opacity travel as custom properties the theme reads; alignment as an attribute.\n const text = doc.createElement('div')\n text.className = 'ink-free-text'\n text.textContent = a.contents\n text.dataset.align = a.align\n text.style.setProperty('--ink-font-size', `${t.toCssLength(a.fontSize)}px`)\n text.style.setProperty('--ink-text-color', a.color)\n text.style.setProperty('--ink-opacity', String(a.opacity))\n text.style.setProperty('--ink-font-family', cssString(a.fontFamily))\n // Structural: the element itself ignores the pointer, the text box takes it.\n text.style.pointerEvents = 'auto'\n el.append(text)\n return\n }\n\n const svg = boxSvg(doc, box.width, box.height)\n svg.classList.add('ink-annotation-shape')\n\n switch (a.type) {\n case 'highlight':\n for (const q of a.quads) {\n svg.append(\n node('polygon', {\n points: quadPoints(q).map(local).join(' '),\n fill: a.color,\n 'fill-opacity': a.opacity,\n })\n )\n }\n break\n case 'underline':\n case 'strikeout':\n case 'squiggly':\n svg.setAttribute('opacity', String(a.opacity))\n for (const q of a.quads) {\n const pts = markupLine(a.type, q)\n svg.append(\n node('polyline', {\n points: pts.map(local).join(' '),\n fill: 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(markupStroke(q)),\n })\n )\n }\n break\n case 'redact': {\n const shapes = a.quads\n ? a.quads.map((q) =>\n node('polygon', { points: quadPoints(q).map(local).join(' ') })\n )\n : [node('rect', { x: 0, y: 0, width: box.width, height: box.height })]\n for (const s of shapes) {\n s.setAttribute('fill', a.interiorColor)\n s.setAttribute('fill-opacity', '0.15')\n s.setAttribute('stroke', a.color)\n s.setAttribute('stroke-width', String(t.toCssLength(1)))\n svg.append(s)\n }\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'square':\n case 'circle': {\n const sw = t.toCssLength(a.width)\n const shape =\n a.type === 'square'\n ? node('rect', {\n x: sw / 2,\n y: sw / 2,\n width: Math.max(0, box.width - sw),\n height: Math.max(0, box.height - sw),\n })\n : node('ellipse', {\n cx: box.width / 2,\n cy: box.height / 2,\n rx: Math.max(0, box.width / 2 - sw / 2),\n ry: Math.max(0, box.height / 2 - sw / 2),\n })\n shape.setAttribute('fill', a.interiorColor ?? 'none')\n shape.setAttribute('stroke', a.color)\n shape.setAttribute('stroke-width', String(sw))\n svg.append(shape)\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'line':\n case 'polyline':\n case 'polygon': {\n const pts = a.type === 'line' ? [a.start, a.end] : a.vertices\n svg.append(\n node(a.type === 'polygon' ? 'polygon' : 'polyline', {\n points: pts.map(local).join(' '),\n fill: a.type === 'polygon' ? (a.interiorColor ?? 'none') : 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(a.width),\n 'stroke-linejoin': 'round',\n })\n )\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'ink':\n for (const path of a.inklist) {\n svg.append(\n node('polyline', {\n points: path.map(local).join(' '),\n fill: 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(a.width),\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n })\n )\n }\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n // Hits follow the painted shape, so a press beside it reaches the text layer underneath.\n for (const shape of svg.children) shape.setAttribute('pointer-events', 'visiblePainted')\n el.append(svg)\n}\n\n/**\n * An invisible hit area for an annotation the overlay does not draw (embedded ones, which\n * PDF.js paints on the canvas): polygons over its quads, or its rect. Selection chrome only.\n */\nexport function renderHitArea(el: HTMLElement, a: Annotation, t: PageTransform): void {\n const doc = el.ownerDocument\n el.replaceChildren()\n const box = annotationBox(a, t)\n const svg = boxSvg(doc, box.width, box.height)\n svg.dataset.inkHit = ''\n const quads = 'quads' in a && a.quads ? a.quads : undefined\n const shapes = quads\n ? quads.map((q) => {\n const poly = doc.createElementNS(SVG, 'polygon')\n poly.setAttribute(\n 'points',\n quadPoints(q)\n .map((p) => {\n const c = t.toCss(p)\n return `${c.x - box.left},${c.y - box.top}`\n })\n .join(' ')\n )\n return poly\n })\n : [doc.createElementNS(SVG, 'rect')]\n for (const shape of shapes) {\n if (shape.tagName === 'rect') {\n shape.setAttribute('width', String(box.width))\n shape.setAttribute('height', String(box.height))\n }\n shape.setAttribute('fill', 'transparent')\n shape.setAttribute('stroke', 'none')\n shape.setAttribute('pointer-events', 'all')\n svg.append(shape)\n }\n el.append(svg)\n}\n\nfunction boxSvg(doc: Document, width: number, height: number): SVGSVGElement {\n const svg = doc.createElementNS(SVG, 'svg')\n svg.setAttribute('width', String(width))\n svg.setAttribute('height', String(height))\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`)\n svg.setAttribute('overflow', 'visible')\n // Block, not inline: an inline SVG sits on the text baseline and drifts below a short box.\n // The theme positions it absolutely as well.\n svg.setAttribute('display', 'block')\n svg.setAttribute('aria-hidden', 'true')\n return svg\n}\n\n/** Quad corners in drawing order: p1 top-left, p2 top-right, p4 bottom-right, p3 bottom-left. */\nfunction quadPoints(q: Quad): Point[] {\n return [q.p1, q.p2, q.p4, q.p3]\n}\n\nconst lerp = (a: Point, b: Point, f: number): Point => ({\n x: a.x + (b.x - a.x) * f,\n y: a.y + (b.y - a.y) * f,\n})\nconst dist = (a: Point, b: Point): number => Math.hypot(b.x - a.x, b.y - a.y)\n\n/** Line thickness in points for a text markup: a fraction of the quad's height. */\nfunction markupStroke(q: Quad): number {\n return Math.max(0.5, dist(q.p1, q.p3) / 14)\n}\n\n/** The stroke for an underline, strikeout or squiggly, in user space. */\nfunction markupLine(type: 'underline' | 'strikeout' | 'squiggly', q: Quad): Point[] {\n if (type === 'strikeout') return [lerp(q.p1, q.p3, 0.5), lerp(q.p2, q.p4, 0.5)]\n const height = dist(q.p1, q.p3)\n // The baseline sits a little above the quad's bottom edge.\n const start = lerp(q.p3, q.p1, 0.1)\n const end = lerp(q.p4, q.p2, 0.1)\n if (type === 'underline') return [start, end]\n const length = dist(start, end)\n const amp = Math.max(0.5, height / 16)\n const step = amp * 2\n const steps = Math.max(1, Math.round(length / step))\n // Unit normal pointing from the bottom edge towards the top edge.\n const up = {\n x: (q.p1.x - q.p3.x) / (height || 1),\n y: (q.p1.y - q.p3.y) / (height || 1),\n }\n const pts: Point[] = []\n for (let i = 0; i <= steps; i++) {\n const p = lerp(start, end, i / steps)\n const s = i % 2 === 0 ? -amp : amp\n pts.push({ x: p.x + up.x * s, y: p.y + up.y * s })\n }\n return pts\n}\n\n/** A CSS string literal, so any PDF font name is a single family name. */\nfunction cssString(value: string): string {\n return `\"${value.replace(/[\"\\\\]/g, '\\\\$&').replace(/\\n/g, '\\\\a ')}\"`\n}\n","// Inline styles here are structural or geometric only: the container is\n// `position:absolute; inset:0; pointer-events:none` so it covers the page without eating\n// events, and each annotation element is `position:absolute` with `left/top/width/height`\n// from `annotationBox` (stroked paths padded once by their stroke), or from\n// `PageTransform.toCssRect(a.rect)` for custom elements. Hit-testing\n// follows the drawn shape, not the box: elements are `pointer-events:none` and their shapes\n// opt back in (overlay-render.ts), so a press beside a shape still reaches the text layer.\n// Resize handles (`.ink-handle[data-handle]`) are 8px `position:absolute;\n// pointer-events:auto` boxes on the element's corners; their look is the theme's.\n// Custom elements are the exception and stay `pointer-events:auto`: the host draws them and\n// only it knows their shape. Every visual (colour, opacity, stroke, fill) is an SVG\n// attribute or a theme hook.\nimport { hasRectGeometry, resizedRect, translated } from '../model/annotations/edit'\nimport { confidenceBucket, type Annotation } from '../model/annotations/types'\n\nimport { annotationBox, renderAnnotationContent, renderHitArea } from './overlay-render'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\n\nexport interface OverlayOptions {\n host: HTMLElement\n /** 0-based page index this overlay shows. */\n page: number\n store: AnnotationStore\n transform: PageTransform\n /** Called when an annotation is clicked, or activated with Enter or Space. */\n onActivate?(id: string): void\n /** Return true to render only the positioned shell; the host (e.g. a Vue slot) fills it. */\n isCustom?(annotation: Annotation): boolean\n}\n\nexport interface Overlay {\n readonly element: HTMLElement\n /** Repositions every element and redraws content for a new zoom or rotation. */\n update(transform: PageTransform): void\n elementFor(id: string): HTMLElement | undefined\n destroy(): void\n}\n\ntype State = 'idle' | 'hover' | 'selected'\n\n/** Resize handles, by the CSS corner they sit on. */\nconst HANDLES = ['nw', 'ne', 'sw', 'se'] as const\n/** Side of a resize handle, CSS px. */\nconst HANDLE_PX = 8\n\n/** Arrow keys as user-space unit steps (y grows upwards). */\nconst ARROW_STEPS: Record<string, { x: number; y: number }> = {\n ArrowRight: { x: 1, y: 0 },\n ArrowLeft: { x: -1, y: 0 },\n ArrowUp: { x: 0, y: 1 },\n ArrowDown: { x: 0, y: -1 },\n}\n\nconst LABELS: Record<Annotation['type'], string> = {\n highlight: 'Highlight',\n underline: 'Underline',\n strikeout: 'Strikeout',\n squiggly: 'Squiggly underline',\n text: 'Note',\n freetext: 'Text box',\n square: 'Rectangle',\n circle: 'Ellipse',\n line: 'Line',\n polyline: 'Polyline',\n polygon: 'Polygon',\n ink: 'Drawing',\n redact: 'Redaction',\n}\n\n/** The `data-confidence` bucket for a suggested redaction; undefined for everything else. */\nexport function confidenceAttr(a: Annotation): 'low' | 'medium' | 'high' | undefined {\n return a.type === 'redact' && a.suggestion\n ? confidenceBucket(a.suggestion.confidence)\n : undefined\n}\n\nfunction ariaLabel(a: Annotation): string {\n const base =\n a.type === 'redact' && a.origin === 'suggested'\n ? 'Suggested redaction'\n : LABELS[a.type]\n return a.author ? `${base} by ${a.author}` : base\n}\n\n/** Reading order in user space: top edge first (y grows upwards), then left edge. */\nfunction readingOrder(a: Annotation, b: Annotation): number {\n return b.rect.y + b.rect.height - (a.rect.y + a.rect.height) || a.rect.x - b.rect.x\n}\n\nfunction setFlag(node: HTMLElement, key: string, on: boolean): void {\n if (on) node.dataset[key] = ''\n else delete node.dataset[key]\n}\n\nfunction setData(node: HTMLElement, key: string, value: string | undefined): void {\n if (value === undefined) delete node.dataset[key]\n else node.dataset[key] = value\n}\n\nexport function createOverlay(opts: OverlayOptions): Overlay {\n const { store, page } = opts\n const doc = opts.host.ownerDocument\n let transform = opts.transform\n const root = doc.createElement('div')\n root.className = 'ink-overlay'\n root.dataset.inkOverlay = ''\n root.style.cssText = 'position:absolute;inset:0;pointer-events:none;'\n opts.host.append(root)\n\n const elements = new Map<string, HTMLElement>()\n /** What each element's content was last drawn from; absent when it has none of ours. */\n const drawn = new Map<string, { a: Annotation; t: PageTransform }>()\n const hovered = new Set<string>()\n let order: string[] = []\n let destroyed = false\n\n function stateOf(id: string, selected: ReadonlySet<string>): State {\n if (selected.has(id)) return 'selected'\n return hovered.has(id) ? 'hover' : 'idle'\n }\n\n function applyState(node: HTMLElement, id: string): void {\n const selected = new Set(store.selection.get())\n const anyHere = order.some((x) => selected.has(x))\n const state = stateOf(id, selected)\n node.dataset.state = state\n node.setAttribute('aria-pressed', String(state === 'selected'))\n node.tabIndex = !anyHere || state === 'selected' ? 0 : -1\n const a = store.get(id)\n syncHandles(\n node,\n selectToolActive() &&\n state === 'selected' &&\n a !== undefined &&\n !a.locked &&\n hasRectGeometry(a)\n )\n }\n\n /** True while the tool controller marks the tool root (an ancestor) `data-ink-tool=\"select\"`. */\n function selectToolActive(): boolean {\n return (\n opts.host.closest('[data-ink-tool]')?.getAttribute('data-ink-tool') === 'select'\n )\n }\n // Re-sync handles on a tool switch. The controller's root is normally the viewport\n // container; pages can mount before the controller marks it, so fall back to that.\n const toolRoot =\n opts.host.closest('[data-ink-tool]') ?? opts.host.closest('[data-ink-viewport]')\n const Observer = doc.defaultView?.MutationObserver\n let toolObserver: MutationObserver | undefined\n if (toolRoot && Observer) {\n toolObserver = new Observer(() => {\n if (destroyed) return\n for (const [id, node] of elements) applyState(node, id)\n })\n toolObserver.observe(toolRoot, {\n attributes: true,\n attributeFilter: ['data-ink-tool'],\n })\n }\n\n /**\n * Corner handles for a selected, unlocked rect-shaped annotation, drawn only while the select\n * tool is active (`data-ink-tool=\"select\"` on the tool root). The select tool drags them\n * (`data-handle` names the CSS corner). The theme also hides them outside the select tool.\n */\n function syncHandles(node: HTMLElement, want: boolean): void {\n const existing = node.querySelectorAll(':scope > [data-handle]')\n if (!want) {\n existing.forEach((h) => h.remove())\n return\n }\n if (existing.length === HANDLES.length) return\n existing.forEach((h) => h.remove())\n for (const corner of HANDLES) {\n const h = doc.createElement('div')\n h.className = 'ink-handle'\n h.dataset.handle = corner\n h.setAttribute('aria-hidden', 'true')\n const off = `${-HANDLE_PX / 2}px`\n h.style.cssText =\n `position:absolute;width:${HANDLE_PX}px;height:${HANDLE_PX}px;pointer-events:auto;` +\n `${corner[0] === 'n' ? 'top' : 'bottom'}:${off};` +\n `${corner[1] === 'w' ? 'left' : 'right'}:${off};`\n node.append(h)\n }\n }\n\n function applyAttributes(node: HTMLElement, a: Annotation): void {\n node.dataset.type = a.type\n node.dataset.source = a.source\n setFlag(node, 'locked', a.locked === true)\n setData(node, 'origin', a.type === 'redact' ? a.origin : undefined)\n setData(node, 'confidence', confidenceAttr(a))\n node.setAttribute('aria-label', ariaLabel(a))\n }\n\n function applyGeometry(node: HTMLElement, a: Annotation): void {\n // Custom elements hold host content laid out against the annotation's own rect.\n const box =\n opts.isCustom?.(a) === true\n ? transform.toCssRect(a.rect)\n : annotationBox(a, transform)\n node.style.left = `${box.left}px`\n node.style.top = `${box.top}px`\n node.style.width = `${box.width}px`\n node.style.height = `${box.height}px`\n }\n\n function applyContent(node: HTMLElement, a: Annotation): void {\n const custom = opts.isCustom?.(a) === true\n setFlag(node, 'custom', custom)\n node.style.pointerEvents = custom ? 'auto' : 'none'\n // Custom elements are the host's to fill: draw nothing.\n if (custom) {\n if (drawn.delete(a.id)) node.replaceChildren()\n return\n }\n const last = drawn.get(a.id)\n if (last?.a === a && last.t === transform) return\n // Embedded annotations are already painted on the canvas by PDF.js, so they get only an\n // invisible hit area.\n if (a.source === 'pdf') renderHitArea(node, a, transform)\n else renderAnnotationContent(node, a, transform)\n drawn.set(a.id, { a, t: transform })\n }\n\n function activate(id: string): void {\n store.select([id])\n opts.onActivate?.(id)\n }\n\n function focusAt(index: number): void {\n const id = order[Math.max(0, Math.min(order.length - 1, index))]\n if (id !== undefined) elements.get(id)?.focus()\n }\n\n /**\n * `Shift+Arrow` moves the annotation 1 pt in user space (`Shift+Alt+Arrow` 10 pt; up is +y).\n * `Ctrl+Shift+Arrow` or `Meta+Shift+Arrow` resizes a rect-shaped one by 1 pt: Right and Down\n * grow it, Left and Up shrink it, keeping its top-left corner. Locked items ignore both.\n * Returns true when the key was one of these chords.\n */\n function onEditKey(e: KeyboardEvent, id: string): boolean {\n const step = ARROW_STEPS[e.key]\n if (!step || !e.shiftKey) return false\n e.preventDefault()\n const a = store.get(id)\n if (!a || a.locked) return true\n if (e.ctrlKey || e.metaKey) {\n if (hasRectGeometry(a))\n store.update(id, { rect: resizedRect(a.rect, step.x, -step.y) })\n return true\n }\n const by = e.altKey ? 10 : 1\n store.update(id, translated(a, step.x * by, step.y * by))\n return true\n }\n\n function onKey(e: KeyboardEvent, id: string): void {\n if (onEditKey(e, id)) return\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n activate(id)\n break\n case 'Delete':\n case 'Backspace': {\n // The overlay owns deletion from a focused annotation: it removes that one only, never\n // the rest of the selection. `preventDefault` tells the select tool to stand down.\n e.preventDefault()\n const a = store.get(id)\n if (a && !a.locked) store.remove(id)\n break\n }\n case 'Escape':\n e.preventDefault()\n store.select([])\n break\n case 'ArrowDown':\n case 'ArrowUp':\n e.preventDefault()\n focusAt(order.indexOf(id) + (e.key === 'ArrowDown' ? 1 : -1))\n break\n default:\n }\n }\n\n function create(id: string): HTMLElement {\n const node = doc.createElement('div')\n node.className = 'ink-annotation'\n node.dataset.annotation = id\n node.setAttribute('role', 'button')\n node.style.position = 'absolute'\n node.addEventListener('pointerenter', () => {\n hovered.add(id)\n applyState(node, id)\n })\n node.addEventListener('pointerleave', () => {\n hovered.delete(id)\n applyState(node, id)\n })\n node.addEventListener('pointerdown', (e) => {\n if (e.button !== 0) return\n // A press on a custom element's own content (a host's button, say) is that content's:\n // no selection, and it bubbles on to the host's delegated handlers.\n if (\n e.target !== node &&\n node.hasAttribute('data-custom') &&\n !(e.target instanceof Element && e.target.closest('[data-handle]'))\n )\n return\n // A tool listening on the page root must not start a drag from this press.\n e.stopPropagation()\n activate(id)\n })\n node.addEventListener('keydown', (e) => {\n // Keys typed in descendants (a custom element's buttons and inputs) are theirs.\n if (e.target !== node) return\n onKey(e, id)\n })\n return node\n }\n\n function render(): void {\n if (destroyed) return\n const current = store.byPage(page).sort(readingOrder)\n const ids = new Set(current.map((a) => a.id))\n const active = doc.activeElement\n let focusId = [...elements].find(([, n]) => n === active)?.[0]\n /** The focused element is going away with nothing on this page to take over. */\n let focusRoot = false\n\n if (focusId !== undefined && !ids.has(focusId)) {\n // The focused element is going away: hand focus to the next survivor, else the previous.\n const i = order.indexOf(focusId)\n focusId =\n order.slice(i + 1).find((x) => ids.has(x)) ??\n order\n .slice(0, i)\n .reverse()\n .find((x) => ids.has(x))\n focusRoot = focusId === undefined\n }\n for (const [id, node] of elements) {\n if (ids.has(id)) continue\n node.remove()\n elements.delete(id)\n drawn.delete(id)\n hovered.delete(id)\n }\n\n order = current.map((a) => a.id)\n for (const a of current) {\n let node = elements.get(a.id)\n if (!node) {\n node = create(a.id)\n elements.set(a.id, node)\n }\n applyAttributes(node, a)\n applyGeometry(node, a)\n applyContent(node, a)\n applyState(node, a.id)\n }\n\n // DOM order is tab order: keep it in reading order. Moving nodes blurs them, so only\n // re-append when the order actually changed.\n const inDom = [...root.children]\n if (\n inDom.length !== order.length ||\n order.some((id, i) => inDom[i] !== elements.get(id))\n ) {\n for (const id of order) root.append(elements.get(id)!)\n }\n if (focusId !== undefined) {\n const target = elements.get(focusId)\n if (target && doc.activeElement !== target) target.focus({ preventScroll: true })\n } else if (focusRoot) {\n // Last one on the page: back to the scroll element (as the popovers do), not <body>.\n const scroll = opts.host.closest<HTMLElement>('[data-ink-viewport]')\n if (scroll) {\n // A container the host did not make focusable still takes focus from script.\n if (!scroll.hasAttribute('tabindex')) scroll.tabIndex = -1\n scroll.focus({ preventScroll: true })\n }\n }\n }\n\n const offList = store.list.subscribe(render)\n const offSelection = store.selection.subscribe(() => {\n for (const [id, node] of elements) applyState(node, id)\n })\n render()\n\n return {\n element: root,\n update(next) {\n transform = next\n render()\n },\n elementFor: (id) => elements.get(id),\n destroy() {\n if (destroyed) return\n destroyed = true\n offList()\n offSelection()\n toolObserver?.disconnect()\n root.remove()\n elements.clear()\n drawn.clear()\n hovered.clear()\n order = []\n },\n }\n}\n","import { createOverlay, type Overlay } from './overlay'\nimport { createPageRenderer, type PageRenderer } from './page-renderer'\nimport { createTextLayer, type TextLayerHandle } from './text-layer'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\nimport type { Annotation } from '../model/annotations/types'\nimport type { InkDocument } from '../model/document'\n\nexport interface PageMountOptions {\n document: InkDocument\n /** Zero-based page index. */\n page: number\n /** The page host (`div.ink-page`) from the viewport's `onMount`. */\n host: HTMLElement\n transform: PageTransform\n store: AnnotationStore\n onActivate?(id: string): void\n isCustom?(a: Annotation): boolean\n /** Defaults to `window.devicePixelRatio`. */\n devicePixelRatio?: number\n /**\n * Canvas and text layer failures, with the layer that failed (cancellations are not\n * reported).\n */\n onError?(error: unknown, layer: PageLayer): void\n /**\n * A layer finished without error: the canvas painted, or the text layer mounted or applied\n * an update. Pair it with `onError` to tell when a failed layer has recovered.\n */\n onRendered?(layer: PageLayer): void\n}\n\n/** The page layers that can fail and recover: the canvas and the text layer. */\nexport type PageLayer = 'canvas' | 'text'\n\nexport interface PageMount {\n readonly renderer: PageRenderer\n readonly textLayer: TextLayerHandle\n readonly overlay: Overlay\n update(transform: PageTransform): void\n destroy(): void\n}\n\n/** Canvas, text layer and annotation overlay for one page, stacked in that order. */\nexport function createPageMount(opts: PageMountOptions): PageMount {\n const { document, page, host, transform } = opts\n const callbacks = (layer: PageLayer) => ({\n ...(opts.onError\n ? { onError: (error: unknown) => opts.onError?.(error, layer) }\n : {}),\n ...(opts.onRendered ? { onRendered: () => opts.onRendered?.(layer) } : {}),\n })\n const renderer = createPageRenderer({\n document,\n page,\n host,\n transform,\n ...(opts.devicePixelRatio === undefined\n ? {}\n : { devicePixelRatio: opts.devicePixelRatio }),\n ...callbacks('canvas'),\n })\n const textLayer = createTextLayer({\n document,\n page,\n host,\n transform,\n ...callbacks('text'),\n })\n const overlay = createOverlay({\n host,\n page,\n store: opts.store,\n transform,\n ...(opts.onActivate ? { onActivate: (id: string) => opts.onActivate?.(id) } : {}),\n ...(opts.isCustom\n ? { isCustom: (a: Annotation) => opts.isCustom?.(a) === true }\n : {}),\n })\n return {\n renderer,\n textLayer,\n overlay,\n update(next) {\n renderer.update(next)\n textLayer.update(next)\n overlay.update(next)\n },\n destroy() {\n overlay.destroy()\n textLayer.destroy()\n renderer.destroy()\n },\n }\n}\n","// The controller writes two things to the root: `data-ink-tool=\"<id>\"` (a marker for themes\n// and tests; `data-tool` belongs to toolbar buttons) and `style.cursor` from the active tool.\n// Both are structural, and both are removed on destroy.\n//\n// `pointerdown` is listened for in the capture phase. The overlay stops propagation of presses\n// on annotation shapes (so a creation tool never starts a drag from one), but a capture\n// listener on the root runs before that, so the controller can pass the pressed annotation's\n// id to the tool. Move, up and key events bubble normally.\n//\n// When a tool starts a gesture (its `onPointerDown` returns true) the controller captures the\n// pointer on the root, so the release still arrives when it happens outside. `pointercancel`\n// and `lostpointercapture` reach the tool as `onPointerCancel`. `touch-action` is left to the\n// theme or host: touch gestures are theirs to arbitrate.\n//\n// The controller tracks the pressed pointer. Switching tools mid-press cancels the old tool's\n// gesture and swallows that pointer's release, so the new tool never sees half a gesture.\n// `lostpointercapture` after a completed release is not a cancel. Only primary-button presses\n// and releases reach tools. The root's own inline cursor is restored on destroy.\nimport { readonly, writable, type Readable } from '../../model/readable'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Point } from '../../model/geometry'\nimport type { SelectionQuads } from '../selection'\nimport type { Viewport, ViewportHit } from '../viewport'\n\nexport type ToolId = 'view' | 'select' | 'highlight' | 'redact-area' | 'note'\n\nexport interface PageHit extends ViewportHit {\n /** Pointer position in user space. */\n user: Point\n /** Pointer position relative to the page host's top-left, CSS px. */\n css: Point\n}\n\nexport interface ToolContext {\n store: AnnotationStore\n viewport: Viewport\n /** The element pointer and key events are listened on (the viewport container). */\n root: HTMLElement\n /** The live text selection as user-space quads, one entry per page. */\n selectionQuads(): SelectionQuads[]\n clearSelection(): void\n onActivate?(id: string): void\n}\n\nexport interface Tool {\n id: ToolId\n cursor: string\n activate(ctx: ToolContext): void\n deactivate(): void\n /**\n * Runs in the capture phase, before the overlay sees the press. `annotationId` is set when\n * the press landed on an annotation; the overlay then selects and activates it, so tools\n * other than `select` should ignore such presses. Calling `e.stopPropagation()` here keeps\n * the overlay from handling it. Return true when the press starts a gesture: the controller\n * then captures the pointer until it is released or cancelled.\n */\n onPointerDown?(\n e: PointerEvent,\n hit: PageHit | undefined,\n annotationId?: string\n ): boolean | void\n /**\n * A move with `e.buttons === 0` during a gesture means the release was missed (it happened\n * where no listener saw it): tools treat it as a cancel.\n */\n onPointerMove?(e: PointerEvent, hit: PageHit | undefined): void\n onPointerUp?(e: PointerEvent, hit: PageHit | undefined): void\n /** `pointercancel` or `lostpointercapture`: drop any gesture in progress without writing. */\n onPointerCancel?(e: PointerEvent): void\n onKeyDown?(e: KeyboardEvent): void\n}\n\nexport interface ToolController {\n readonly active: Readable<ToolId>\n set(id: ToolId): void\n destroy(): void\n}\n\nexport interface ToolControllerOptions {\n ctx: ToolContext\n /** Default `'view'`. */\n initial?: ToolId\n tools: Tool[]\n}\n\n/** Host-relative CSS point for a client point. */\nexport function cssIn(host: HTMLElement, e: { clientX: number; clientY: number }): Point {\n const r = host.getBoundingClientRect()\n return { x: e.clientX - r.left, y: e.clientY - r.top }\n}\n\n/** Like `cssIn`, clamped to the host's box, so a drag past the page edge stops at the edge. */\nexport function clampedCssIn(\n host: HTMLElement,\n e: { clientX: number; clientY: number }\n): Point {\n const r = host.getBoundingClientRect()\n return {\n x: Math.min(Math.max(e.clientX - r.left, 0), r.width),\n y: Math.min(Math.max(e.clientY - r.top, 0), r.height),\n }\n}\n\n/** The mounted page under a client point, with the point in CSS px and user space. */\nexport function hitFor(\n ctx: ToolContext,\n e: { clientX: number; clientY: number }\n): PageHit | undefined {\n const hit = ctx.viewport.pageAtCss(e.clientX, e.clientY)\n if (!hit) return undefined\n const css = cssIn(hit.host, e)\n return { ...hit, css, user: hit.transform.fromCss(css) }\n}\n\nexport function createToolController(opts: ToolControllerOptions): ToolController {\n const { ctx } = opts\n const byId = new Map(opts.tools.map((t) => [t.id, t]))\n const active = writable<ToolId>(opts.initial ?? 'view')\n let current: Tool | undefined\n const originalCursor = ctx.root.style.cursor\n /** The pointer between a primary press and its release or cancel. */\n let pressed: number | undefined\n /** Pointers whose release belongs to a tool that is no longer active. */\n const swallow = new Set<number>()\n\n /** True for events from a pointer other than the one whose press is live. */\n const foreign = (e: PointerEvent): boolean =>\n pressed !== undefined && pressed !== e.pointerId\n\n const onDown = (e: PointerEvent): void => {\n if (!e.isPrimary || e.button !== 0 || inCustomContent(e.target)) return\n // One gesture at a time: a second pointer pressing mid-gesture is ignored.\n if (foreign(e)) return\n swallow.delete(e.pointerId)\n pressed = e.pointerId\n const target = e.target instanceof Element ? e.target : null\n const annotationId =\n target?.closest('[data-annotation]')?.getAttribute('data-annotation') ?? undefined\n if (current?.onPointerDown?.(e, hitFor(ctx, e), annotationId) === true)\n capture(e.pointerId)\n }\n const onMove = (e: PointerEvent): void => {\n if (!e.isPrimary || foreign(e)) return\n // A buttonless move means the release was missed: the press is over (tools drop their\n // own gesture on the same signal), so another pointer may press again.\n if (pressed === e.pointerId && e.buttons === 0) pressed = undefined\n current?.onPointerMove?.(e, hitFor(ctx, e))\n }\n const onUp = (e: PointerEvent): void => {\n if (!e.isPrimary || e.button !== 0 || foreign(e)) return\n if (pressed === e.pointerId) pressed = undefined\n if (swallow.delete(e.pointerId)) {\n release(e.pointerId)\n return\n }\n current?.onPointerUp?.(e, hitFor(ctx, e))\n release(e.pointerId)\n }\n const onCancel = (e: PointerEvent): void => {\n if (!e.isPrimary || foreign(e)) return\n // Capture is also lost when a completed release frees it: only a live press cancels.\n if (e.type === 'lostpointercapture' && pressed !== e.pointerId) return\n if (pressed === e.pointerId) pressed = undefined\n swallow.delete(e.pointerId)\n current?.onPointerCancel?.(e)\n }\n const onKey = (e: KeyboardEvent): void => {\n if (!inCustomContent(e.target)) current?.onKeyDown?.(e)\n }\n\n // Capture is best effort: synthetic events may carry a pointer id the browser does not know.\n function capture(id: number): void {\n try {\n ctx.root.setPointerCapture?.(id)\n } catch {\n // Not an active pointer: the gesture still works while the pointer stays over the root.\n }\n }\n function release(id: number): void {\n try {\n if (ctx.root.hasPointerCapture?.(id)) ctx.root.releasePointerCapture(id)\n } catch {\n // Already released.\n }\n }\n ctx.root.addEventListener('pointerdown', onDown, { capture: true })\n ctx.root.addEventListener('pointermove', onMove)\n ctx.root.addEventListener('pointerup', onUp)\n ctx.root.addEventListener('pointercancel', onCancel)\n ctx.root.addEventListener('lostpointercapture', onCancel)\n ctx.root.addEventListener('keydown', onKey)\n\n function set(id: ToolId): void {\n const next = byId.get(id)\n if (!next) throw new RangeError(`Unknown tool ${id}`)\n if (pressed !== undefined) {\n // Mid-press: end the old tool's gesture here and keep its release from the new tool.\n current?.onPointerCancel?.(\n new PointerEvent('pointercancel', { pointerId: pressed, isPrimary: true })\n )\n swallow.add(pressed)\n pressed = undefined\n }\n current?.deactivate()\n current = next\n next.activate(ctx)\n ctx.root.dataset.inkTool = id\n ctx.root.style.cursor = next.cursor\n active.set(id)\n }\n set(opts.initial ?? 'view')\n\n return {\n active: readonly(active),\n set,\n destroy() {\n current?.deactivate()\n current = undefined\n ctx.root.removeEventListener('pointerdown', onDown, { capture: true })\n ctx.root.removeEventListener('pointermove', onMove)\n ctx.root.removeEventListener('pointerup', onUp)\n ctx.root.removeEventListener('pointercancel', onCancel)\n ctx.root.removeEventListener('lostpointercapture', onCancel)\n ctx.root.removeEventListener('keydown', onKey)\n delete ctx.root.dataset.inkTool\n ctx.root.style.cursor = originalCursor\n },\n }\n}\n\n/**\n * True for an unmodified, unhandled Enter on the viewport's own elements: the scroll element\n * (`root`), a page host, or content of a page's text layer or canvas layer. Every other target\n * (annotations, custom slot content, any control a host puts in the page) keeps its Enter.\n * This is the keyboard trigger for the creation tools.\n */\nexport function isViewportEnter(e: KeyboardEvent, root: HTMLElement): boolean {\n if (e.key !== 'Enter' || e.defaultPrevented) return false\n if (e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.isComposing) return false\n const target = e.target\n if (target === root) return true\n if (!(target instanceof Element) || !root.contains(target)) return false\n if (target.matches('.ink-page[data-page]')) return true\n return target.closest('[data-ink-text-layer], [data-ink-canvas-layer]') !== null\n}\n\n/**\n * True for a target inside a custom annotation element (`data-custom`) but not that element\n * itself: the host's buttons and inputs there own their presses and keys, as in the overlay.\n */\nfunction inCustomContent(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n const el = target.closest('[data-annotation]')\n return (\n el !== null &&\n el !== target &&\n el.hasAttribute('data-custom') &&\n // Resize handles are the overlay's, not the host's content.\n target.closest('[data-handle]') === null\n )\n}\n","import { isViewportEnter, type Tool, type ToolContext } from './controller'\n\n/**\n * Turns the text selection into one highlight per page when the pointer is released, or on\n * Enter in the viewport (a keyboard selection). Without a selection both do nothing.\n */\nexport function highlightTool(): Tool {\n let ctx: ToolContext | undefined\n const convert = (): boolean => {\n if (!ctx) return false\n const selections = ctx.selectionQuads()\n if (selections.length === 0) return false\n for (const s of selections) {\n ctx.store.add({\n type: 'highlight',\n page: s.page,\n quads: s.quads,\n contents: s.text,\n })\n }\n ctx.clearSelection()\n return true\n }\n return {\n id: 'highlight',\n cursor: 'text',\n activate(c) {\n ctx = c\n },\n deactivate() {\n ctx = undefined\n },\n onPointerUp() {\n convert()\n },\n onKeyDown(e) {\n if (!!ctx && isViewportEnter(e, ctx.root) && convert()) e.preventDefault()\n },\n }\n}\n","import { isViewportEnter, type PageHit, type Tool, type ToolContext } from './controller'\n\nimport type { Point } from '../../model/geometry'\n\n/** Side of a new note's icon box, user-space points. */\nconst SIZE = 20\n\n/** Frames to wait for a controlled host to apply a new note before giving up on focusing it. */\nconst FOCUS_FRAMES = 10\n\n/**\n * Click places a note centred on the press. Enter in the viewport places one at the centre of\n * the current page and focuses it. Either way the note is selected and activated.\n */\nexport function noteTool(): Tool {\n let ctx: ToolContext | undefined\n let down: PageHit | undefined\n\n const place = (c: ToolContext, page: number, at: Point): string => {\n const a = c.store.add({\n type: 'text',\n page,\n rect: { x: at.x - SIZE / 2, y: at.y - SIZE / 2, width: SIZE, height: SIZE },\n })\n c.store.select([a.id])\n return a.id\n }\n\n return {\n id: 'note',\n cursor: 'copy',\n activate(c) {\n ctx = c\n },\n deactivate() {\n ctx = undefined\n down = undefined\n },\n onPointerDown(_e, hit, annotationId) {\n down = annotationId === undefined ? hit : undefined\n return down !== undefined\n },\n onPointerCancel() {\n down = undefined\n },\n onPointerUp(_e, hit) {\n const pressed = down\n down = undefined\n if (!ctx || !pressed || !hit || hit.page !== pressed.page) return\n const id = place(ctx, hit.page, hit.user)\n ctx.onActivate?.(id)\n },\n onKeyDown(e) {\n if (!ctx || !isViewportEnter(e, ctx.root)) return\n e.preventDefault()\n const c = ctx\n const page = c.viewport.currentPage.get()\n const { box } = c.viewport.transformFor(page).page\n const id = place(c, page, { x: box.x + box.width / 2, y: box.y + box.height / 2 })\n focusWhenDrawn(c, id)\n c.onActivate?.(id)\n },\n }\n}\n\n/**\n * Focuses the note's overlay element. An uncontrolled store draws it synchronously; a\n * controlled host applies the change later, so wait a few frames, and give up if focus has\n * meanwhile moved off the viewport (a popover took it).\n */\nfunction focusWhenDrawn(ctx: ToolContext, id: string): void {\n const doc = ctx.root.ownerDocument\n const find = (): HTMLElement | null =>\n ctx.root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`)\n const now = find()\n if (now) {\n now.focus({ preventScroll: true })\n return\n }\n let frames = 0\n const view = doc.defaultView\n const tick = (): void => {\n if (doc.activeElement !== ctx.root) return\n const el = find()\n if (el) el.focus({ preventScroll: true })\n else if (++frames < FOCUS_FRAMES) view?.requestAnimationFrame(tick)\n }\n view?.requestAnimationFrame(tick)\n}\n","// The live draft is `position:absolute; pointer-events:none` with left/top/width/height from\n// the drag: geometry only. Its look comes from the theme (`.ink-draft[data-ink-draft]`).\nimport {\n clampedCssIn,\n isViewportEnter,\n type PageHit,\n type Tool,\n type ToolContext,\n} from './controller'\n\n/** Smallest drag, in CSS px on each axis, that draws a box rather than counting as a click. */\nconst MIN_CSS = 3\n\nexport function redactAreaTool(): Tool {\n let ctx: ToolContext | undefined\n let start: PageHit | undefined\n let draft: HTMLElement | undefined\n\n /** Text redactions from the live selection, one per page. False when nothing is selected. */\n const fromSelection = (): boolean => {\n if (!ctx) return false\n const selections = ctx.selectionQuads()\n if (selections.length === 0) return false\n for (const s of selections)\n ctx.store.add({ type: 'redact', page: s.page, quads: s.quads })\n ctx.clearSelection()\n return true\n }\n\n const clear = (): void => {\n draft?.remove()\n draft = undefined\n start = undefined\n }\n\n return {\n id: 'redact-area',\n cursor: 'crosshair',\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n if (!hit || annotationId !== undefined) return\n start = hit\n // Keeps the press from starting a text selection; an existing one survives for the\n // text-derived mode on pointerup.\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!start) return\n // No button down: the release was missed, so drop the draft. A host scrolled out of\n // the mounted range is gone with it.\n if (e.buttons === 0 || !start.host.isConnected) {\n clear()\n return\n }\n const css = clampedCssIn(start.host, e)\n if (!draft) {\n draft = start.host.ownerDocument.createElement('div')\n draft.className = 'ink-draft'\n draft.dataset.inkDraft = 'redact'\n draft.style.position = 'absolute'\n draft.style.pointerEvents = 'none'\n start.host.append(draft)\n }\n draft.style.left = `${Math.min(start.css.x, css.x)}px`\n draft.style.top = `${Math.min(start.css.y, css.y)}px`\n draft.style.width = `${Math.abs(css.x - start.css.x)}px`\n draft.style.height = `${Math.abs(css.y - start.css.y)}px`\n },\n onPointerCancel() {\n clear()\n },\n onPointerUp(e) {\n if (!ctx || !start) return\n if (!start.host.isConnected) {\n clear()\n return\n }\n const css = clampedCssIn(start.host, e)\n const width = Math.abs(css.x - start.css.x)\n const height = Math.abs(css.y - start.css.y)\n if (width >= MIN_CSS && height >= MIN_CSS) {\n const rect = start.transform.fromCssRect({\n left: Math.min(start.css.x, css.x),\n top: Math.min(start.css.y, css.y),\n width,\n height,\n })\n ctx.store.add({ type: 'redact', page: start.page, rect })\n } else {\n fromSelection()\n }\n clear()\n },\n onKeyDown(e) {\n // The keyboard path for text marks: select text, then Enter.\n if (!!ctx && isViewportEnter(e, ctx.root) && fromSelection()) e.preventDefault()\n },\n }\n}\n","// The marquee is `position:absolute; pointer-events:none` with left/top/width/height from the\n// drag, and a moving annotation is shown with a temporary `transform: translate(...)` on its\n// overlay element; a resizing one with `translate(...) scale(...)` from a `0 0` origin. All\n// are geometry; the marquee's look comes from the theme.\n//\n// Resize: a press on one of the overlay's corner handles (`[data-handle]`, drawn on a\n// selected, unlocked rect-shaped annotation) drags that CSS corner while the opposite one\n// stays put. The new box is converted back to user space once, on release, as one\n// `store.update` of `rect`. Neither side goes below 1 pt.\nimport { MIN_SIZE, hasRectGeometry, translated } from '../../model/annotations/edit'\nimport { rectFromPoints, rectsIntersect } from '../../model/geometry'\n\nimport { cssIn, type PageHit, type Tool, type ToolContext } from './controller'\n\nimport type { Point } from '../../model/geometry'\nimport type { CssRect } from '../transform'\n\ntype Corner = 'nw' | 'ne' | 'sw' | 'se'\nconst CORNERS: readonly string[] = ['nw', 'ne', 'sw', 'se']\n\n/** Pointer travel, CSS px, before a press on an annotation becomes a move. */\nconst DRAG_THRESHOLD = 3\n\ntype Mode =\n | { kind: 'idle' }\n | { kind: 'press'; id: string; start: PageHit }\n | { kind: 'move'; id: string; start: PageHit; el: HTMLElement | undefined }\n | { kind: 'marquee'; start: PageHit; el: HTMLElement; additive: boolean }\n | {\n kind: 'resize'\n id: string\n start: PageHit\n corner: Corner\n /** The annotation's CSS box when the press began. */\n box: CssRect\n el: HTMLElement | undefined\n }\n\nexport function selectTool(): Tool {\n let ctx: ToolContext | undefined\n let mode: Mode = { kind: 'idle' }\n\n const reset = (): void => {\n if (mode.kind === 'marquee') mode.el.remove()\n if ((mode.kind === 'move' || mode.kind === 'resize') && mode.el) {\n mode.el.style.transform = ''\n mode.el.style.transformOrigin = ''\n }\n mode = { kind: 'idle' }\n }\n\n return {\n id: 'select',\n cursor: 'default',\n activate(c) {\n ctx = c\n },\n deactivate() {\n reset()\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n if (!ctx || !hit) return\n reset()\n if (annotationId !== undefined) {\n const corner = handleOf(e.target)\n const a = corner === undefined ? undefined : ctx.store.get(annotationId)\n if (corner !== undefined && a && !a.locked && hasRectGeometry(a)) {\n // The annotation is already selected (it has handles): keep the overlay from\n // re-activating it.\n e.stopPropagation()\n e.preventDefault()\n const el =\n hit.host.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(annotationId)}\"]`\n ) ?? undefined\n mode = {\n kind: 'resize',\n id: annotationId,\n start: hit,\n corner,\n box: hit.transform.toCssRect(a.rect),\n el,\n }\n return true\n }\n if (e.shiftKey) {\n // Toggle membership ourselves; the overlay would replace the selection.\n e.stopPropagation()\n const selected = ctx.store.selection.get()\n ctx.store.select(\n selected.includes(annotationId)\n ? selected.filter((s) => s !== annotationId)\n : [...selected, annotationId]\n )\n return\n }\n // The overlay selects and activates it once this capture-phase handler returns.\n mode = { kind: 'press', id: annotationId, start: hit }\n e.preventDefault()\n return true\n }\n const el = hit.host.ownerDocument.createElement('div')\n el.className = 'ink-marquee'\n el.dataset.inkMarquee = ''\n el.style.cssText = `position:absolute;pointer-events:none;left:${hit.css.x}px;top:${hit.css.y}px;width:0;height:0;`\n hit.host.append(el)\n mode = { kind: 'marquee', start: hit, el, additive: e.shiftKey }\n if (!e.shiftKey) ctx.store.select([])\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!ctx || mode.kind === 'idle') return\n // No button down: the release was missed, so drop the gesture. So does a start host\n // that scrolling has unmounted.\n if (e.buttons === 0 || !mode.start.host.isConnected) {\n reset()\n return\n }\n const { start } = mode\n if (mode.kind === 'resize') {\n const { box, el } = mode\n const next = resizeCss(box, mode.corner, cornerAt(mode, e), minCss(start))\n if (el) {\n el.style.transformOrigin = '0 0'\n el.style.transform =\n `translate(${next.left - box.left}px, ${next.top - box.top}px) ` +\n `scale(${next.width / box.width}, ${next.height / box.height})`\n }\n return\n }\n const css = cssIn(start.host, e)\n const dx = css.x - start.css.x\n const dy = css.y - start.css.y\n if (mode.kind === 'press') {\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return\n const a = ctx.store.get(mode.id)\n if (!a || a.locked) {\n mode = { kind: 'idle' }\n return\n }\n const el =\n start.host.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(mode.id)}\"]`\n ) ?? undefined\n mode = { kind: 'move', id: mode.id, start, el }\n }\n if (mode.kind === 'move') {\n if (mode.el) mode.el.style.transform = `translate(${dx}px, ${dy}px)`\n return\n }\n mode.el.style.left = `${Math.min(start.css.x, css.x)}px`\n mode.el.style.top = `${Math.min(start.css.y, css.y)}px`\n mode.el.style.width = `${Math.abs(dx)}px`\n mode.el.style.height = `${Math.abs(dy)}px`\n },\n onPointerCancel() {\n reset()\n },\n onPointerUp(e) {\n if (!ctx) return\n const current = mode\n reset()\n if (current.kind !== 'idle' && !current.start.host.isConnected) return\n if (current.kind === 'move') {\n const { start } = current\n const end = start.transform.fromCss(cssIn(start.host, e))\n const a = ctx.store.get(current.id)\n if (a && !a.locked)\n ctx.store.update(\n a.id,\n translated(a, end.x - start.user.x, end.y - start.user.y)\n )\n } else if (current.kind === 'resize') {\n const { start, box } = current\n const next = resizeCss(box, current.corner, cornerAt(current, e), minCss(start))\n if (\n next.left === box.left &&\n next.top === box.top &&\n next.width === box.width &&\n next.height === box.height\n )\n return\n const a = ctx.store.get(current.id)\n if (!a || a.locked) return\n const r = start.transform.fromCssRect(next)\n ctx.store.update(a.id, {\n rect: {\n ...r,\n width: Math.max(MIN_SIZE, r.width),\n height: Math.max(MIN_SIZE, r.height),\n },\n })\n } else if (current.kind === 'marquee') {\n const { start } = current\n const box = rectFromPoints(\n start.user,\n start.transform.fromCss(cssIn(start.host, e))\n )\n if (box.width === 0 && box.height === 0) return\n const ids = ctx.store\n .byPage(start.page)\n .filter((a) => rectsIntersect(a.rect, box))\n .map((a) => a.id)\n ctx.store.select(\n current.additive ? [...new Set([...ctx.store.selection.get(), ...ids])] : ids\n )\n }\n },\n onKeyDown(e) {\n if (!ctx) return\n if (e.key === 'Escape') {\n reset()\n ctx.store.select([])\n return\n }\n if (e.key !== 'Delete' && e.key !== 'Backspace') return\n // A focused annotation's overlay element owns the key (it removes that one annotation\n // and prevents the default); deleting the selection too would double-handle it.\n if (e.defaultPrevented) return\n const target = e.target instanceof Element ? e.target : null\n if (\n target?.closest(\n '[data-annotation], input, textarea, [contenteditable]:not([contenteditable=\"false\"])'\n )\n )\n return\n for (const id of ctx.store.selection.get()) {\n if (ctx.store.get(id)?.locked !== true) ctx.store.remove(id)\n }\n },\n }\n}\n\n/** The corner of the resize handle a press landed on, if it landed on one. */\nfunction handleOf(target: EventTarget | null): Corner | undefined {\n if (!(target instanceof Element)) return undefined\n const corner = target.closest('[data-handle]')?.getAttribute('data-handle')\n return corner && CORNERS.includes(corner) ? (corner as Corner) : undefined\n}\n\n/**\n * Where the dragged corner is now: where it started plus the pointer's travel since the\n * press, kept on the page. Keeping the press's offset from the corner means a click on a\n * handle, with no drag, leaves the box as it was.\n */\nfunction cornerAt(\n mode: { start: PageHit; box: CssRect; corner: Corner },\n e: { clientX: number; clientY: number }\n): Point {\n const { start, box, corner } = mode\n const css = cssIn(start.host, e)\n const x = (corner[1] === 'w' ? box.left : box.left + box.width) + css.x - start.css.x\n const y = (corner[0] === 'n' ? box.top : box.top + box.height) + css.y - start.css.y\n const { cssWidth, cssHeight } = start.transform\n return {\n x: Math.min(Math.max(x, 0), cssWidth),\n y: Math.min(Math.max(y, 0), cssHeight),\n }\n}\n\n/** `MIN_SIZE` points as CSS px on the press's page. */\nfunction minCss(start: PageHit): number {\n return start.transform.toCssLength(MIN_SIZE)\n}\n\n/** `box` with its `corner` dragged to `p` and the opposite corner fixed, at least `min` a side. */\nfunction resizeCss(box: CssRect, corner: Corner, p: Point, min: number): CssRect {\n let left = box.left\n let top = box.top\n let right = box.left + box.width\n let bottom = box.top + box.height\n if (corner[1] === 'w') left = Math.min(p.x, right - min)\n else right = Math.max(p.x, left + min)\n if (corner[0] === 'n') top = Math.min(p.y, bottom - min)\n else bottom = Math.max(p.y, top + min)\n return { left, top, width: right - left, height: bottom - top }\n}\n","import type { Tool } from './controller'\n\n/** Reading only: text selection stays native and the overlay still selects annotations. */\nexport function viewTool(): Tool {\n return { id: 'view', cursor: 'auto', activate() {}, deactivate() {} }\n}\n","import {\n createToolController as createWith,\n type Tool,\n type ToolControllerOptions,\n type ToolController,\n} from './controller'\nimport { highlightTool } from './highlight'\nimport { noteTool } from './note'\nimport { redactAreaTool } from './redact-area'\nimport { selectTool } from './select'\nimport { viewTool } from './view'\n\nexport type {\n PageHit,\n Tool,\n ToolContext,\n ToolController,\n ToolControllerOptions,\n ToolId,\n} from './controller'\nexport { hitFor } from './controller'\nexport { highlightTool, noteTool, redactAreaTool, selectTool, viewTool }\n\n/** Fresh instances of every built-in tool. */\nexport function builtinTools(): Tool[] {\n return [viewTool(), selectTool(), highlightTool(), redactAreaTool(), noteTool()]\n}\n\n/** Listens on `ctx.root` and routes pointer and key events to the active tool. */\nexport function createToolController(\n opts: Omit<ToolControllerOptions, 'tools'> & { tools?: Tool[] }\n): ToolController {\n return createWith({ ...opts, tools: opts.tools ?? builtinTools() })\n}\n","// Vocabulary the framework packages share: labels, zoom levels and the props they hand to\n// host-rendered content. Core owns these so Vue and React cannot drift apart.\nimport type { ToolId } from './tools'\nimport type {\n Annotation,\n ConfidenceBucket,\n NoteAnnotation,\n RedactAnnotation,\n Suggestion,\n} from '../model/annotations/types'\n\n/** Accessible names of the built-in tools, as the toolbar buttons announce them. */\nexport const TOOL_LABELS: Readonly<Record<ToolId, string>> = {\n view: 'View',\n select: 'Select',\n highlight: 'Highlight',\n 'redact-area': 'Mark for redaction',\n note: 'Add note',\n}\n\n/** Zoom levels the zoom select offers, as scale factors. */\nexport const ZOOM_LEVELS: readonly number[] = [0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4]\n\n/** The overlay's per-annotation state, as on its `data-state` attribute. */\nexport type AnnotationState = 'idle' | 'hover' | 'selected'\n\n/**\n * What a host-rendered annotation receives: Vue's `annotation` slot and React's\n * `renderAnnotation`.\n */\nexport interface AnnotationSlotProps {\n annotation: Annotation\n state: AnnotationState\n locked: boolean\n select: () => void\n remove: () => void\n /** Turns a suggested redaction into the user's own. No-op for anything else. */\n accept: () => void\n /** Removes a suggested redaction. No-op for anything else. */\n dismiss: () => void\n}\n\n/** What a host-rendered note thread receives. */\nexport interface NotePopoverSlotProps {\n note: NoteAnnotation\n replies: Annotation[]\n reply: (text: string) => void\n update: (contents: string) => void\n remove: () => void\n close: () => void\n}\n\n/** What a host-rendered suggestion card receives. */\nexport interface SuggestionCardSlotProps {\n annotation: RedactAnnotation\n suggestion: Suggestion | undefined\n bucket: ConfidenceBucket | undefined\n accept: () => void\n dismiss: () => void\n close: () => void\n}\n","/** The overlay element drawn for annotation `id` under `root`, if it is in the DOM. */\nexport function annotationElementFor(root: ParentNode, id: string): HTMLElement | null {\n return root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`)\n}\n\n/**\n * Resolves the overlay element for `id` and keeps resolving while `root`'s subtree changes:\n * the overlay creates and removes these elements outside any framework (a page mounts as it\n * scrolls into view), so a popover anchored to one has to follow. Calls `onChange` once now\n * and again whenever the answer changes. The returned function stops observing.\n */\nexport function observeAnnotationElement(\n root: HTMLElement,\n id: string,\n onChange: (el: HTMLElement | null) => void\n): () => void {\n let last: HTMLElement | null | undefined\n const resolve = (): void => {\n const found = annotationElementFor(root, id)\n if (found === last) return\n last = found\n onChange(found)\n }\n resolve()\n const observer = new MutationObserver(resolve)\n observer.observe(root, { childList: true, subtree: true })\n return () => observer.disconnect()\n}\n","/*\n * Shared behaviour for popovers anchored to an overlay annotation element. There is no popover\n * trigger, so the primitive library's own focus return has nothing to return to.\n */\nimport { annotationElementFor } from './annotation-element'\n\n/**\n * A press that will activate an annotation is not a dismissal: the popover follows the\n * activation. Mirrors the overlay's rule: a press on the annotation element or on its drawn\n * shape activates; a press on a custom element's own content belongs to that content.\n */\nexport function shouldKeepOpenOnAnnotation(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n const annotation = target.closest('[data-annotation]')\n if (!annotation) return false\n return target === annotation || !annotation.hasAttribute('data-custom')\n}\n\nexport interface FocusReturnOptions {\n root: () => HTMLElement | null\n /** The activated annotation id when the popover closes. */\n activated: () => string | null\n}\n\nexport interface FocusReturn {\n /**\n * Call just before removing the anchor's annotation: remembers where focus goes instead,\n * the next annotation on the page in reading order (the next one matching `prefer`\n * first), else the previous one, else the scroll element.\n */\n beforeRemove(anchor: HTMLElement | null, prefer?: string): void\n /** The popover's close-auto-focus handler. Prevents the default and places focus itself. */\n onCloseAutoFocus(event: Event, anchor: HTMLElement | null): void\n}\n\nexport function createFocusReturn(opts: FocusReturnOptions): FocusReturn {\n let fallbacks: HTMLElement[] = []\n /** Set by `beforeRemove`: the close comes from removing the anchor's annotation. */\n let removing = false\n\n return {\n beforeRemove(anchor, prefer) {\n fallbacks = []\n removing = true\n // The overlay keeps its elements in reading order, so DOM order is reading order.\n const siblings = anchor?.parentElement\n ? [...anchor.parentElement.children].filter(\n (el): el is HTMLElement =>\n el instanceof HTMLElement && el.hasAttribute('data-annotation')\n )\n : []\n const i = anchor ? siblings.indexOf(anchor) : -1\n if (i >= 0) {\n const after = siblings.slice(i + 1)\n const preferred = prefer ? after.filter((el) => el.matches(prefer)) : []\n fallbacks.push(...preferred, ...after, ...siblings.slice(0, i).reverse())\n }\n },\n onCloseAutoFocus(event, anchor) {\n event.preventDefault()\n const plan = fallbacks\n const removed = removing\n fallbacks = []\n removing = false\n const root = opts.root()\n if (!root) return\n // Activation moved to another annotation that is on screen: its popover takes focus. An\n // id whose element is gone (the host removed it) does not count.\n const activated = opts.activated()\n if (activated !== null && annotationElementFor(root, activated)) return\n // The close can be reported more than once; focus already returned to the document stays.\n const active = root.ownerDocument.activeElement\n if (active && active !== root && root.contains(active)) return\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n // After a removal the anchor may still be connected (a controlled host has not applied\n // the change yet), but it is on its way out: go straight to what follows it.\n const candidates = removed ? [...plan, scroll] : [anchor, ...plan, scroll]\n candidates.find((el) => el?.isConnected)?.focus({ preventScroll: true })\n },\n }\n}\n","/*\n * The wiring every viewer needs: a viewport over the scroll element, page layers in each page\n * host it creates, page-error tracking, the tool controller and keyboard shortcuts. Framework\n * bindings and `createViewer` sit on top: they render their own chrome and get pages and\n * errors back through the callbacks.\n */\nimport { InkError, isInkError } from '../model/errors'\n\nimport { createPageMount, type PageLayer, type PageMount } from './page-mount'\nimport { getSelectionQuads } from './selection'\nimport { createToolController, type ToolController, type ToolId } from './tools'\nimport { createViewport, type Viewport, type ZoomValue } from './viewport'\nimport { attachViewportKeys } from './viewport-keys'\n\nimport type { LayoutMode } from './layout'\nimport type { PageTransform, ViewRotation } from './transform'\nimport type { InkDocument } from '../model/document'\nimport type { Point } from '../model/geometry'\n\n/** A user-space point on a page, used to put the scroll position back after a rebuild. */\ninterface ScrollAnchor {\n page: number\n user: Point\n /** Whether the vertical position is restored too, not only the horizontal one. */\n vertical: boolean\n}\n\nexport interface MountViewerOptions {\n container: HTMLElement\n document: InkDocument\n zoom?: ZoomValue\n page?: number\n mode?: LayoutMode\n rotation?: ViewRotation\n gap?: number\n buffer?: number\n tool?: ToolId\n /** Annotation content is rendered by the host (custom slots). Changing it needs `rebuild`. */\n customAnnotations?: boolean\n onActivate?(id: string): void\n /**\n * After every (re)build: subscribe to the new viewport and controller here. It fires inside\n * `mountViewer` before it returns, and after the build's `onPageMount` calls.\n */\n onBuild?(viewport: Viewport, tools: ToolController): void\n /**\n * The viewport mounts pages synchronously, so a build's `onPageMount` calls fire before its\n * `onBuild` (on the first build, before `mountViewer` returns). Do not read `engine.viewport`\n * or `engine.tools` here: during a rebuild they still point at the destroyed objects. Use\n * the arguments, or wait for `onBuild`.\n */\n onPageMount?(page: number, mount: PageMount, host: HTMLElement): void\n /** Same ordering rule as `onPageMount`: do not read `engine.viewport` or `engine.tools`. */\n onPageUnmount?(page: number): void\n /**\n * `error` when a page's canvas or text layer fails; `null` once every failed layer recovers.\n * Unmounting a failed page does not emit `null`: hosts that track errors by page must clear\n * them in `onPageUnmount`. Same ordering rule as `onPageMount`: do not read `engine.viewport`\n * or `engine.tools`.\n */\n onPageError?(page: number, error: InkError | null): void\n}\n\nexport interface ViewerEngine {\n readonly viewport: Viewport\n readonly tools: ToolController\n readonly pages: ReadonlyMap<number, PageMount>\n /**\n * Recreates the viewport for construction-only options, keeping zoom, page, mode, rotation\n * and tool. The scroll position is kept too: the user-space point at the top-left of the\n * visible area stays there. When that corner is in a gap rather than on a page, the page below\n * the gap lands where `scrollToPage` puts it, with the new gap above it.\n */\n rebuild(opts: { gap?: number; buffer?: number; customAnnotations?: boolean }): void\n destroy(): void\n}\n\nexport function mountViewer(opts: MountViewerOptions): ViewerEngine {\n const { container: el, document: doc } = opts\n const pages = new Map<number, PageMount>()\n let gap = opts.gap\n let buffer = opts.buffer\n let custom = opts.customAnnotations ?? false\n let viewport: Viewport\n let tools: ToolController\n let stopKeys: () => void = () => undefined\n let destroyed = false\n\n function mountPage(page: number, host: HTMLElement, transform: PageTransform): void {\n /** Layers that failed and have not rendered since; the error clears when this empties. */\n const failed = new Set<PageLayer>()\n let error: InkError | null = null\n const isCustom = custom\n const mount = createPageMount({\n document: doc,\n page,\n host,\n transform,\n store: doc.annotations,\n onActivate: (id) => opts.onActivate?.(id),\n isCustom: () => isCustom,\n onError: (cause, layer) => {\n failed.add(layer)\n // The first failure wins: a canvas and a text layer failing together report once.\n if (error) return\n error = isInkError(cause)\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n { page },\n cause\n )\n host.setAttribute('data-state', 'error')\n opts.onPageError?.(page, error)\n },\n onRendered: (layer) => {\n failed.delete(layer)\n if (!error || failed.size > 0) return\n error = null\n host.removeAttribute('data-state')\n opts.onPageError?.(page, null)\n },\n })\n pages.set(page, mount)\n opts.onPageMount?.(page, mount, host)\n }\n\n function unmountPage(page: number): void {\n const mount = pages.get(page)\n if (!mount) return\n pages.delete(page)\n opts.onPageUnmount?.(page)\n mount.destroy()\n }\n\n /** The client point at the top-left of the container's visible content area. */\n function viewTopLeft(): Point {\n const r = el.getBoundingClientRect()\n return { x: r.left + el.clientLeft, y: r.top + el.clientTop }\n }\n\n /** The client point of the pages element's top-left: the origin of the layout's page boxes. */\n function layoutOrigin(): Point | undefined {\n const pagesEl = el.querySelector<HTMLElement>(':scope > [data-ink-pages]')\n if (!pagesEl) return undefined\n const r = pagesEl.getBoundingClientRect()\n return { x: r.left, y: r.top }\n }\n\n /**\n * Where the view sits before a rebuild: the user-space point under the top-left of the\n * visible area, on the page whose box contains it. When the top of the view is in a gap or a\n * margin, only the horizontal position is kept, and the page lands where `scrollToPage` puts\n * it, the new gap above it (a view resting at a page boundary stays at that boundary).\n */\n function scrollAnchor(vp: Viewport): ScrollAnchor | undefined {\n const o = layoutOrigin()\n if (!o) return undefined\n const corner = viewTopLeft()\n const x = corner.x - o.x\n const y = corner.y - o.y\n const boxes = vp.layout.get().boxes\n const inside = boxes.find((b) => y >= b.top && y < b.top + b.height)\n // In a gap or margin: the page just below it, which the view reaches first. Past the\n // last page there is none, so the current page stands in.\n const box =\n inside ??\n boxes.find((b) => b.top > y) ??\n boxes.find((b) => b.index === vp.currentPage.get())\n if (!box) return undefined\n // Transforms are affine, so a point left or right of the page maps back exactly too.\n const user = vp.transformFor(box.index).fromCss({ x: x - box.left, y: y - box.top })\n return { page: box.index, user, vertical: inside !== undefined }\n }\n\n /** Scrolls so the anchor's point sits under the top-left of the visible area again. */\n function restoreScroll(vp: Viewport, anchor: ScrollAnchor): void {\n const o = layoutOrigin()\n const box = vp.layout.get().boxes.find((b) => b.index === anchor.page)\n if (!o || !box) return\n const css = vp.transformFor(anchor.page).toCss(anchor.user)\n const corner = viewTopLeft()\n el.scrollLeft += o.x + box.left + css.x - corner.x\n if (anchor.vertical) el.scrollTop += o.y + box.top + css.y - corner.y\n }\n\n function build(state: {\n zoom: ZoomValue\n page: number | undefined\n mode: LayoutMode | undefined\n rotation: ViewRotation | undefined\n tool: ToolId | undefined\n anchor?: ScrollAnchor | undefined\n }): void {\n const vp = createViewport({\n container: el,\n document: doc,\n zoom: state.zoom,\n ...(state.mode === undefined ? {} : { mode: state.mode }),\n ...(state.rotation === undefined ? {} : { rotation: state.rotation }),\n ...(gap === undefined ? {} : { gap }),\n ...(buffer === undefined ? {} : { buffer }),\n onMount: mountPage,\n onUpdate: (page, _host, transform) => pages.get(page)?.update(transform),\n onUnmount: unmountPage,\n })\n const tc = createToolController({\n ...(state.tool === undefined ? {} : { initial: state.tool }),\n ctx: {\n store: doc.annotations,\n viewport: vp,\n root: el,\n selectionQuads: () =>\n getSelectionQuads(el, (host) => {\n const page = Number(host.dataset.page)\n return { page, transform: vp.transformFor(page) }\n }),\n clearSelection: () =>\n el.ownerDocument.defaultView?.getSelection()?.removeAllRanges(),\n onActivate: (id) => opts.onActivate?.(id),\n },\n })\n viewport = vp\n tools = tc\n stopKeys = attachViewportKeys(el, { viewport: vp, pageCount: () => doc.pages.length })\n // A view resting in a gap lands on the page below it, not on the most visible page.\n // The scroll position resets on teardown, so the guard below must not skip a gap anchor.\n if (state.anchor && !state.anchor.vertical) vp.scrollToPage(state.anchor.page)\n else if (state.page !== undefined && state.page !== vp.currentPage.get())\n vp.scrollToPage(state.page)\n if (state.anchor) restoreScroll(vp, state.anchor)\n opts.onBuild?.(vp, tc)\n }\n\n function teardown(): void {\n stopKeys()\n tools.destroy()\n // The viewport unmounts every page it mounted, which destroys the page mounts.\n viewport.destroy()\n for (const page of [...pages.keys()]) unmountPage(page)\n }\n\n build({\n zoom: opts.zoom ?? 'fit-width',\n page: opts.page,\n mode: opts.mode,\n rotation: opts.rotation,\n tool: opts.tool,\n })\n\n return {\n get viewport() {\n return viewport\n },\n get tools() {\n return tools\n },\n pages,\n rebuild(next) {\n if (destroyed) return\n const state = {\n zoom: viewport.zoom.get(),\n page: viewport.currentPage.get(),\n mode: viewport.mode.get(),\n rotation: viewport.rotation.get(),\n tool: tools.active.get(),\n anchor: scrollAnchor(viewport),\n }\n teardown()\n if (next.gap !== undefined) gap = next.gap\n if (next.buffer !== undefined) buffer = next.buffer\n if (next.customAnnotations !== undefined) custom = next.customAnnotations\n build(state)\n },\n destroy() {\n if (destroyed) return\n destroyed = true\n teardown()\n },\n }\n}\n","/** `document.createElement` with attributes and children. */\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n ...children: (Node | string)[]\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag)\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value)\n el.append(...children)\n return el\n}\n\nexport function button(label: string, onClick: () => void): HTMLButtonElement {\n const b = h('button', { type: 'button' }, label)\n b.addEventListener('click', onClick)\n return b\n}\n","/*\n * A panel anchored to an annotation's overlay element, shared by the note thread and the\n * suggestion card. The overlay creates and removes those elements as pages mount and unmount,\n * so the panel follows the element by id: a replaced element re-anchors it, and while the\n * element is gone (its page scrolled out) the panel hides but stays logically open.\n */\nimport { observeAnnotationElement } from '../annotation-element'\nimport { shouldKeepOpenOnAnnotation, type FocusReturn } from '../popover-focus'\n\nimport { h } from './dom'\n\n/** Space between the anchor and the panel, and between the panel and the window edge. */\nconst GAP = 6\nconst MARGIN = 8\nconst TABBABLE = 'button, input, select, textarea, a[href], [tabindex]'\n\nexport interface PopoverOptions {\n /** The viewer root: anchors are looked up and focus returns inside it. */\n root: HTMLElement\n attrs: Record<string, string>\n focusReturn: FocusReturn\n /** Escape, or a press outside that will not activate an annotation. */\n onDismiss(): void\n}\n\nexport interface Popover {\n readonly panel: HTMLElement\n /** The anchor element, or null while it is not in the DOM. */\n readonly anchor: HTMLElement | null\n /** Anchors to annotation `id`. The panel shows whenever its element is in the DOM. */\n show(id: string): void\n /** Hides the panel and returns focus the way the bindings do. */\n hide(): void\n destroy(): void\n}\n\nexport function createPopover(opts: PopoverOptions): Popover {\n const { root, focusReturn } = opts\n const panel = h('div', { ...opts.attrs, role: 'dialog', hidden: '' })\n document.body.append(panel)\n let anchoredId: string | null = null\n let anchor: HTMLElement | null = null\n let stopObserving: () => void = () => undefined\n /** The element that had focus in the panel when the anchor went away. */\n let stranded: HTMLElement | null = null\n\n const place = (): void => {\n if (!anchor || panel.hidden) return\n const r = anchor.getBoundingClientRect()\n const { innerWidth: vw, innerHeight: vh } = window\n const w = panel.offsetWidth\n const ht = panel.offsetHeight\n // Below the anchor; above it when only that fits; clamped to the window either way.\n let top = r.bottom + GAP\n if (top + ht > vh - MARGIN && r.top - GAP - ht >= MARGIN) top = r.top - GAP - ht\n top = Math.max(MARGIN, Math.min(top, vh - ht - MARGIN))\n const left = Math.max(MARGIN, Math.min(r.left, vw - w - MARGIN))\n panel.style.position = 'fixed'\n panel.style.left = `${left}px`\n panel.style.top = `${top}px`\n }\n\n // The anchor changes size on zoom; the panel when its content changes.\n const resizes = new ResizeObserver(place)\n resizes.observe(panel)\n\n const onAnchor = (el: HTMLElement | null, closing = false): void => {\n if (anchor) resizes.unobserve(anchor)\n anchor = el\n if (!el) {\n const active = document.activeElement\n if (\n !closing &&\n !panel.hidden &&\n active instanceof HTMLElement &&\n panel.contains(active)\n ) {\n // Hiding the panel would drop focus to the body: keep the keyboard in the viewer.\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n if (scroll) {\n stranded = active\n scroll.focus({ preventScroll: true })\n }\n }\n panel.hidden = true\n return\n }\n resizes.observe(el)\n const wasHidden = panel.hidden\n panel.hidden = false\n place()\n if (wasHidden && stranded) {\n const back = stranded\n stranded = null\n const scroll = root.querySelector<HTMLElement>('[data-ink-scroll]')\n if (panel.contains(back) && document.activeElement === scroll)\n back.focus({ preventScroll: true })\n }\n }\n\n const onKey = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape' || panel.hidden || e.defaultPrevented) return\n // An Escape meant for a host's own dialog elsewhere on the page is not ours.\n const target = e.target\n if (!(target instanceof Node) || !(panel.contains(target) || root.contains(target)))\n return\n e.preventDefault()\n opts.onDismiss()\n }\n const onPress = (e: PointerEvent): void => {\n if (panel.hidden || panel.contains(e.target as Node)) return\n // A press that will activate an annotation hands over to it instead of closing.\n if (shouldKeepOpenOnAnnotation(e.target)) return\n opts.onDismiss()\n }\n // Focus loops inside the panel, as the bindings' non-modal popovers do.\n const onTab = (e: KeyboardEvent): void => {\n if (e.key !== 'Tab' || e.altKey || e.ctrlKey || e.metaKey) return\n const tabbable = [...panel.querySelectorAll<HTMLElement>(TABBABLE)].filter(\n (el) => !(el as HTMLButtonElement).disabled && el.tabIndex >= 0\n )\n const first = tabbable[0]\n const last = tabbable.at(-1)\n if (!first || !last) return\n const active = document.activeElement\n if (e.shiftKey ? active !== first : active !== last) return\n e.preventDefault()\n ;(e.shiftKey ? last : first).focus()\n }\n panel.addEventListener('keydown', onTab)\n document.addEventListener('keydown', onKey)\n document.addEventListener('pointerdown', onPress, true)\n // The viewer's scroll element and any scrolling ancestor in the host page.\n document.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n\n return {\n panel,\n get anchor() {\n return anchor\n },\n show(id) {\n if (id === anchoredId) return\n stopObserving()\n anchoredId = id\n stopObserving = observeAnnotationElement(root, id, onAnchor)\n },\n hide() {\n if (anchoredId === null) return\n stopObserving()\n stopObserving = () => undefined\n anchoredId = null\n const back = anchor\n stranded = null\n onAnchor(null, true)\n // After the change that closed the popover has settled (a removed anchor is out of the\n // DOM, a cleared activation is cleared), as the bindings' close-auto-focus runs after\n // their render. A popover reopened meanwhile keeps focus where it is.\n queueMicrotask(() => {\n if (anchoredId !== null || !panel.isConnected) return\n focusReturn.onCloseAutoFocus(\n new Event('closeautofocus', { cancelable: true }),\n back\n )\n })\n },\n destroy() {\n stopObserving()\n resizes.disconnect()\n document.removeEventListener('keydown', onKey)\n document.removeEventListener('pointerdown', onPress, true)\n panel.removeEventListener('keydown', onTab)\n document.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n panel.remove()\n },\n }\n}\n","/*\n * The thread for the activated note, anchored to the note's overlay element. Activating a\n * reply opens the whole thread from its root. Closing (Close, Escape, a press outside) clears\n * the activation.\n *\n * A new note has no text. While its root is empty (and unlocked) the form writes the root's\n * own `contents`, labelled \"Comment\", and the thread list stays hidden until there is\n * something in it; after that the form adds replies. A root closed, or left for another\n * annotation, while still empty and without replies is removed. The thread list re-renders on\n * every store change; the form, and the draft in it, stays until the popover moves to another\n * note or the note is gone.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '../../model/annotations/threads'\n\nimport { button, h } from './dom'\nimport { createPopover } from './popover'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Annotation, NoteAnnotation } from '../../model/annotations/types'\nimport type { Writable } from '../../model/readable'\nimport type { FocusReturn } from '../popover-focus'\n\nexport interface NotePopoverOptions {\n root: HTMLElement\n store: AnnotationStore\n activated: Writable<string | null>\n focusReturn: FocusReturn\n}\n\nexport function createNotePopover(opts: NotePopoverOptions): { destroy(): void } {\n const { root, store, activated, focusReturn } = opts\n const popover = createPopover({\n root,\n attrs: {\n class: 'ink-note-popover',\n 'data-ink-note-popover': '',\n 'aria-label': 'Note thread',\n },\n focusReturn,\n onDismiss: close,\n })\n const thread = h('ol', { class: 'ink-thread', 'data-ink-thread': '' })\n let form: ThreadForm | null = null\n /** The root note shown now. */\n let current: string | null = null\n /** Notes given text or a reply here: never dropped as abandoned. */\n const written = new Set<string>()\n /** Notes already removed from here, so they are not removed twice. */\n const dropped = new Set<string>()\n\n function shown(): NoteAnnotation | null {\n const a = current ? store.get(current) : undefined\n return a?.type === 'text' ? a : null\n }\n\n function target(): NoteAnnotation | null {\n const list = store.list.get()\n const id = activated.get()\n const a = id === null ? undefined : list.find((x) => x.id === id)\n return a?.type === 'text' ? threadRoot(list, a) : null\n }\n\n const editingRoot = (n: NoteAnnotation): boolean => !n.locked && !n.contents?.trim()\n\n function isEmptyRoot(n: NoteAnnotation): boolean {\n return (\n !written.has(n.id) && editingRoot(n) && threadOf(store.list.get(), n).length === 1\n )\n }\n\n function dropIfEmpty(id: string): void {\n if (dropped.has(id) || written.has(id) || !isAbandonedNote(store.list.get(), id))\n return\n dropped.add(id)\n store.remove(id)\n }\n\n function renderThread(n: NoteAnnotation): void {\n const items = threadOf(store.list.get(), n)\n if (editingRoot(n) && items.length === 1) {\n thread.remove()\n return\n }\n thread.replaceChildren(...items.map(threadItem))\n if (!thread.isConnected) popover.panel.prepend(thread)\n }\n\n function update(): void {\n const n = target()\n const id = n?.id ?? null\n if (id === current) {\n if (n && form) {\n renderThread(n)\n form.sync(n)\n }\n return\n }\n const previous = current\n current = id\n if (n) {\n const hadFocus = popover.panel.contains(document.activeElement)\n const opening = popover.panel.hidden\n form = createThreadForm(n, { submit, remove: removeThread, close })\n popover.panel.replaceChildren(form.element)\n renderThread(n)\n popover.show(n.id)\n if ((opening || hadFocus) && !popover.panel.hidden) form.textarea.focus()\n } else {\n form = null\n popover.hide()\n }\n // Activation moved on from a note that never got any text: drop it. This can re-enter\n // `update`, which finds `current` already settled.\n if (previous !== null) dropIfEmpty(previous)\n }\n\n function submit(text: string): void {\n const n = shown()\n if (!n) return\n written.add(n.id)\n if (editingRoot(n)) store.update(n.id, { contents: text })\n else\n store.add({\n type: 'text',\n page: n.page,\n rect: n.rect,\n contents: text,\n inReplyTo: n.id,\n })\n }\n\n /** Locked notes cannot be removed: Delete is not offered for them. */\n function removeThread(): void {\n const n = shown()\n if (!n || n.locked) return\n focusReturn.beforeRemove(popover.anchor)\n dropped.add(n.id)\n store.remove(n.id)\n activated.set(null)\n }\n\n function close(): void {\n const n = shown()\n if (n && isEmptyRoot(n)) focusReturn.beforeRemove(popover.anchor)\n // `update` hides the popover and drops the note if it is still empty.\n activated.set(null)\n }\n\n const stops = [store.list.subscribe(update), activated.subscribe(update)]\n update()\n\n return {\n destroy() {\n for (const stop of stops) stop()\n popover.destroy()\n },\n }\n}\n\nfunction threadItem(a: Annotation): HTMLLIElement {\n return h(\n 'li',\n {\n class: 'ink-thread-item',\n 'data-ink-thread-item': '',\n ...(a.inReplyTo ? { 'data-reply': '' } : {}),\n },\n h('span', { class: 'ink-thread-author' }, a.author ?? 'Anonymous'),\n h(\n 'time',\n { class: 'ink-thread-time', datetime: a.createdAt },\n new Date(a.createdAt).toLocaleString()\n ),\n h('p', { class: 'ink-thread-text' }, a.contents ?? '')\n )\n}\n\ninterface ThreadForm {\n readonly element: HTMLFormElement\n readonly textarea: HTMLTextAreaElement\n /** Follows the note's state: \"Comment\" while its own text is empty, \"Reply\" after. */\n sync(n: NoteAnnotation): void\n}\n\nfunction createThreadForm(\n n: NoteAnnotation,\n actions: { submit: (text: string) => void; remove: () => void; close: () => void }\n): ThreadForm {\n const textarea = h('textarea', { rows: '2' })\n const send = h('button', { type: 'submit' })\n const remove = button('Delete', actions.remove)\n const actionRow = h(\n 'div',\n { class: 'ink-thread-actions' },\n send,\n remove,\n button('Close', actions.close)\n )\n const element = h(\n 'form',\n { class: 'ink-thread-reply', 'data-ink-thread-reply': '' },\n textarea,\n actionRow\n )\n const syncSend = (): void => {\n send.disabled = !textarea.value.trim()\n }\n textarea.addEventListener('input', syncSend)\n element.addEventListener('submit', (e) => {\n e.preventDefault()\n const text = textarea.value.trim()\n if (!text) return\n // Cleared first: the store change re-renders the thread straight away.\n textarea.value = ''\n syncSend()\n actions.submit(text)\n })\n\n function sync(note: NoteAnnotation): void {\n const label = !note.locked && !note.contents?.trim() ? 'Comment' : 'Reply'\n textarea.setAttribute('aria-label', label)\n textarea.placeholder = label\n send.textContent = label\n if (note.locked) remove.remove()\n else if (!remove.isConnected) send.after(remove)\n }\n sync(n)\n syncSend()\n return { element, textarea, sync }\n}\n","/*\n * Review card for a suggested redaction: opens when the activated annotation, or the only\n * selected one (a marquee selects without activating), is a redaction with\n * `origin: 'suggested'`. It closes when that stops being true: accepted, dismissed, or removed\n * some other way (an undo). Locked suggestions cannot be dismissed, so they get no Dismiss\n * button. Closing clears the activation and the selection.\n */\nimport { acceptSuggestion } from '../../model/annotations/suggestions'\nimport { confidenceBucket } from '../../model/annotations/types'\n\nimport { button, h } from './dom'\nimport { createPopover } from './popover'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { RedactAnnotation } from '../../model/annotations/types'\nimport type { Writable } from '../../model/readable'\nimport type { FocusReturn } from '../popover-focus'\n\nexport interface SuggestionCardOptions {\n root: HTMLElement\n store: AnnotationStore\n activated: Writable<string | null>\n focusReturn: FocusReturn\n}\n\nexport function createSuggestionCard(opts: SuggestionCardOptions): { destroy(): void } {\n const { root, store, activated, focusReturn } = opts\n const popover = createPopover({\n root,\n attrs: {\n class: 'ink-suggestion-card',\n 'data-ink-suggestion-card': '',\n 'aria-label': 'Suggested redaction',\n },\n focusReturn,\n onDismiss: close,\n })\n /** The suggestion as last rendered. */\n let shown: RedactAnnotation | null = null\n\n function suggestion(id: string | null | undefined): RedactAnnotation | null {\n const a = id ? store.get(id) : undefined\n return a?.type === 'redact' && a.origin === 'suggested' ? a : null\n }\n\n function target(): RedactAnnotation | null {\n const selection = store.selection.get()\n return (\n suggestion(activated.get()) ??\n (selection.length === 1 ? suggestion(selection[0]) : null)\n )\n }\n\n function update(): void {\n const t = target()\n if (t === shown) return\n const previous = shown\n shown = t\n if (!t) {\n popover.hide()\n return\n }\n const hadFocus = popover.panel.contains(document.activeElement)\n const opening = previous === null || previous.id !== t.id\n render(t)\n popover.show(t.id)\n if ((opening || hadFocus) && !popover.panel.hidden)\n popover.panel.querySelector('button')?.focus()\n }\n\n function render(a: RedactAnnotation): void {\n const { suggestion: s } = a\n const bucket = s ? confidenceBucket(s.confidence) : undefined\n popover.panel.replaceChildren(\n h(\n 'p',\n { class: 'ink-suggestion-reason' },\n h('strong', {}, s?.reason ?? 'Suggested redaction'),\n ...(bucket\n ? [\n h(\n 'span',\n { class: 'ink-suggestion-confidence', 'data-confidence': bucket },\n `${bucket} confidence`\n ),\n ]\n : [])\n ),\n ...(s?.explanation\n ? [h('p', { class: 'ink-suggestion-explanation' }, s.explanation)]\n : []),\n h(\n 'div',\n { class: 'ink-suggestion-actions' },\n button('Accept', accept),\n ...(a.locked ? [] : [button('Dismiss', dismiss)])\n )\n )\n }\n\n function close(): void {\n activated.set(null)\n store.select([])\n }\n\n function accept(): void {\n if (shown) acceptSuggestion(store, shown.id)\n close()\n }\n\n /** Locked annotations cannot be removed: Dismiss is not offered for them. */\n function dismiss(): void {\n if (!shown || shown.locked) return\n focusReturn.beforeRemove(popover.anchor, '[data-origin=\"suggested\"]')\n store.remove(shown.id)\n close()\n }\n\n const stops = [\n store.list.subscribe(update),\n store.selection.subscribe(update),\n activated.subscribe(update),\n ]\n update()\n\n return {\n destroy() {\n for (const stop of stops) stop()\n popover.destroy()\n },\n }\n}\n","/*\n * A viewer without a framework: opens a document, mounts the engine and renders the note\n * thread and suggestion card, with the bindings' markup so `@inkbar/theme` styles it\n * unchanged. Toolbars are the host's, built from the controls in ./controls.\n */\nimport {\n cssVariableDefaults,\n type AnnotationDefaults,\n} from '../../model/annotations/defaults'\nimport {\n openDocument,\n type InkDocument,\n type InkStatus,\n type OpenOptions,\n} from '../../model/document'\nimport { InkError, isInkError } from '../../model/errors'\nimport { readonly, writable, type Readable } from '../../model/readable'\nimport { createFocusReturn } from '../popover-focus'\nimport { mountViewer, type MountViewerOptions, type ViewerEngine } from '../viewer-engine'\n\nimport { h } from './dom'\nimport { createNotePopover } from './note-popover'\nimport { createSuggestionCard } from './suggestion-card'\n\nimport type { DocumentSource } from '../../model/source'\nimport type { PdfAssets } from '../../pdfjs/types'\nimport type { ToolController } from '../tools'\nimport type { Viewport } from '../viewport'\n\nexport interface CreateViewerOptions extends Omit<\n MountViewerOptions,\n 'container' | 'document'\n> {\n source: DocumentSource\n assets: PdfAssets\n /** User password for encrypted files. `open` can pass its own for one load. */\n password?: string\n /** Default: read from the theme's CSS variables on the viewer root. */\n defaults?: AnnotationDefaults\n history?: OpenOptions['history']\n /** Note thread popover. Default true. */\n notes?: boolean\n /** Suggested-redaction card. Default true. */\n suggestions?: boolean\n onReady?(this: void, doc: InkDocument): void\n onError?(this: void, error: InkError): void\n}\n\nexport interface Viewer {\n /** The root element (`[data-ink-root]`) the viewer rendered into the host element. */\n readonly element: HTMLElement\n readonly status: Readable<InkStatus>\n readonly document: Readable<InkDocument | null>\n /** Set while a document is ready; `null` otherwise. */\n readonly engine: Readable<ViewerEngine | null>\n /**\n * The current viewport and tool controller; `null` while no document is ready. Both change\n * when the engine rebuilds, so read them here rather than holding on to `engine.viewport`.\n */\n readonly viewport: Readable<Viewport | null>\n readonly tools: Readable<ToolController | null>\n /**\n * Opens another document in place; the previous one is destroyed. Latest call wins.\n * `password` is used for this load only; without it, the constructor's `password` applies.\n */\n open(source: DocumentSource, opts?: { password?: string }): void\n destroy(): void\n}\n\nexport function createViewer(el: HTMLElement, opts: CreateViewerOptions): Viewer {\n const {\n source: initial,\n assets,\n password,\n defaults,\n history,\n notes: withNotes = true,\n suggestions: withSuggestions = true,\n onReady,\n onError,\n onActivate,\n onBuild,\n onPageMount,\n onPageUnmount,\n onPageError,\n ...view\n } = opts\n const status = writable<InkStatus>({ state: 'idle' })\n const current = writable<InkDocument | null>(null)\n const engine = writable<ViewerEngine | null>(null)\n const viewport = writable<Viewport | null>(null)\n const tools = writable<ToolController | null>(null)\n /** The activated annotation: the note thread and the suggestion card open from it. */\n const activated = writable<string | null>(null)\n\n const root = h('div', { 'data-ink-root': '', 'data-state': 'idle' })\n const scroll = h('div', {\n class: 'ink-scroll',\n 'data-ink-scroll': '',\n tabindex: '0',\n role: 'document',\n 'aria-label': 'Document',\n })\n const viewportRoot = h(\n 'div',\n { class: 'ink-viewport-root', 'data-ink-viewport-root': '', 'data-state': 'idle' },\n scroll\n )\n root.append(viewportRoot)\n el.append(root)\n\n const focusReturn = createFocusReturn({\n root: () => root,\n activated: () => activated.get(),\n })\n\n let statusEl: HTMLElement | null = null\n function renderStatus(s: InkStatus): void {\n root.dataset.state = s.state\n viewportRoot.dataset.state = s.state\n statusEl?.remove()\n statusEl = null\n if (s.state === 'loading') {\n statusEl = h(\n 'div',\n { class: 'ink-status', role: 'status', 'aria-live': 'polite' },\n 'Loading document…'\n )\n } else if (s.state === 'error') {\n // The engine's message is not written for readers: it stays on the code's tooltip.\n statusEl = h(\n 'div',\n { class: 'ink-status ink-error', role: 'alert' },\n h('p', { class: 'ink-error-title' }, 'This document could not be opened.'),\n h(\n 'p',\n {},\n h('code', { class: 'ink-error-code', title: s.error.message }, s.error.code)\n )\n )\n }\n if (statusEl) viewportRoot.prepend(statusEl)\n }\n function setStatus(s: InkStatus): void {\n renderStatus(s)\n status.set(s)\n }\n\n /** Mounts the engine and the popovers for a ready document; returns their teardown. */\n function start(doc: InkDocument): () => void {\n const store = doc.annotations\n const popovers = [\n withNotes ? createNotePopover({ root, store, activated, focusReturn }) : null,\n withSuggestions\n ? createSuggestionCard({ root, store, activated, focusReturn })\n : null,\n ]\n // An activated annotation that has gone (removed, undone) is no longer activated, so it\n // does not reopen its popover if it comes back.\n const stopList = store.list.subscribe(() => {\n const id = activated.get()\n if (id !== null && !store.get(id)) activated.set(null)\n })\n const hosts = new Map<number, HTMLElement>()\n const errors = new Map<number, HTMLElement>()\n const clearError = (page: number): void => {\n errors.get(page)?.remove()\n errors.delete(page)\n }\n const mounted = mountViewer({\n ...view,\n container: scroll,\n document: doc,\n onActivate: (id) => {\n activated.set(id)\n onActivate?.(id)\n },\n onBuild: (vp, tc) => {\n // Tools first: a viewport subscriber may read the tools.\n tools.set(tc)\n viewport.set(vp)\n onBuild?.(vp, tc)\n },\n onPageMount: (page, mount, host) => {\n hosts.set(page, host)\n onPageMount?.(page, mount, host)\n },\n // A failed page that unmounts reports no recovery: its error goes with it.\n onPageUnmount: (page) => {\n hosts.delete(page)\n clearError(page)\n onPageUnmount?.(page)\n },\n onPageError: (page, error) => {\n clearError(page)\n const host = hosts.get(page)\n if (error && host) {\n const shown = h(\n 'div',\n { class: 'ink-page-error', 'data-ink-page-error': '', role: 'alert' },\n h('p', {}, `Page ${page + 1} could not be shown.`),\n h('code', { class: 'ink-error-code' }, error.code)\n )\n host.append(shown)\n errors.set(page, shown)\n }\n onPageError?.(page, error)\n },\n })\n engine.set(mounted)\n return () => {\n stopList()\n for (const p of popovers) p?.destroy()\n activated.set(null)\n engine.set(null)\n mounted.destroy()\n viewport.set(null)\n tools.set(null)\n }\n }\n\n let loads = 0\n let destroyed = false\n let stop: () => void = () => undefined\n\n /** Tears down the open document, if any, and destroys it. */\n function close(): void {\n stop()\n stop = () => undefined\n const doc = current.get()\n current.set(null)\n doc?.destroy()\n }\n\n function open(source: DocumentSource, openOpts?: { password?: string }): void {\n if (destroyed) return\n const load = ++loads\n close()\n setStatus({ state: 'loading' })\n // The theme's colour variables are read from the root, which is in the page by now.\n openDocument(source, {\n assets,\n password: openOpts?.password ?? password,\n defaults: defaults ?? cssVariableDefaults(root),\n history,\n }).then(\n (doc) => {\n // A later `open` or `destroy` superseded this load.\n if (load !== loads) {\n doc.destroy()\n return\n }\n current.set(doc)\n const s = doc.status.get()\n if (s.state === 'error') {\n setStatus(s)\n onError?.(s.error)\n return\n }\n // The status leaves the layout before the engine measures the scroll element, and the\n // engine is set before anyone hears `ready`.\n renderStatus({ state: 'ready' })\n stop = start(doc)\n status.set({ state: 'ready' })\n // A status subscriber may have opened another document already.\n if (load === loads) onReady?.(doc)\n },\n (cause: unknown) => {\n // Only a programmer error (missing assets) rejects; it gets the error state too.\n if (load !== loads) return\n const error = isInkError(cause)\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n setStatus({ state: 'error', error })\n onError?.(error)\n }\n )\n }\n\n open(initial)\n\n return {\n element: root,\n status: readonly(status),\n document: readonly(current),\n engine: readonly(engine),\n viewport: readonly(viewport),\n tools: readonly(tools),\n open,\n destroy() {\n if (destroyed) return\n destroyed = true\n loads++\n close()\n root.remove()\n },\n }\n}\n","/*\n * Toolbar controls for createViewer, with the classes and data attributes of the bindings'\n * components so `@inkbar/theme` styles them. Each control follows a viewer: it is disabled\n * while no document is ready and picks up the new viewport after every engine rebuild. A\n * control lives as long as its viewer.\n *\n * Buttons show an icon from `@inkbar/icons`; replace their children with your own and the\n * accessible name stays. Put controls in a `createToolbar()` bar, and put the bar where it\n * belongs: `viewer.element.prepend(bar)` above the document, `append` below it.\n */\nimport {\n ChevronLeft,\n ChevronRight,\n Hand,\n Highlighter,\n ICON_ATTRIBUTES,\n MessageSquare,\n MousePointer2,\n Redo2,\n Square,\n Undo2,\n ZoomIn,\n ZoomOut,\n type IconNode,\n} from '@inkbar/icons'\n\nimport { TOOL_LABELS, ZOOM_LEVELS } from '../ui'\n\nimport { h } from './dom'\n\nimport type { InkDocument } from '../../model/document'\nimport type { Readable } from '../../model/readable'\nimport type { ToolController, ToolId } from '../tools'\nimport type { Viewport } from '../viewport'\nimport type { Viewer } from './create-viewer'\n\ntype Control = HTMLButtonElement | HTMLSelectElement | HTMLInputElement\n\n/**\n * Runs `connect` for every value `source` takes while it is set, undoing the previous run's\n * subscriptions first, and disables `control` while it is `null`.\n */\nfunction follow<T>(\n source: Readable<T | null>,\n control: Control,\n connect: (value: T, watch: <V>(r: Readable<V>, fn: (value: V) => void) => void) => void,\n reset?: () => void\n): void {\n let stops: (() => void)[] = []\n const watch = <V>(r: Readable<V>, fn: (value: V) => void): void => {\n fn(r.get())\n stops.push(r.subscribe(fn))\n }\n const run = (value: T | null): void => {\n for (const s of stops) s()\n stops = []\n control.disabled = value === null\n if (value === null) reset?.()\n else connect(value, watch)\n }\n run(source.get())\n source.subscribe(run)\n}\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\nconst TOOL_ICONS: Readonly<Record<ToolId, IconNode>> = {\n view: Hand,\n select: MousePointer2,\n highlight: Highlighter,\n 'redact-area': Square,\n note: MessageSquare,\n}\n\n/**\n * An `<svg>` drawing `icon` from `@inkbar/icons`, hidden from assistive technology: the\n * control it sits in carries the name. The theme sizes it with `--ink-icon-size`.\n */\nexport function createIcon(icon: IconNode): SVGSVGElement {\n const svg = document.createElementNS(SVG, 'svg')\n const attrs = {\n ...ICON_ATTRIBUTES,\n width: '18',\n height: '18',\n class: 'ink-icon',\n 'aria-hidden': 'true',\n }\n for (const [k, v] of Object.entries(attrs)) svg.setAttribute(k, v)\n for (const [tag, shape] of icon) {\n const child = document.createElementNS(SVG, tag)\n for (const [k, v] of Object.entries(shape)) child.setAttribute(k, v)\n svg.append(child)\n }\n return svg\n}\n\nfunction button(\n label: string,\n attrs: Record<string, string>,\n icon: IconNode\n): HTMLButtonElement {\n const b = h('button', { type: 'button', ...attrs, 'aria-label': label, title: label })\n b.append(createIcon(icon))\n return b\n}\n\n/**\n * A toolbar following the WAI-ARIA toolbar pattern: its buttons share one Tab stop, with\n * arrow keys, Home and End to move between them. Fields and selects are Tab stops of their\n * own and keep their keys. Buttons added later join in.\n */\nexport function createToolbar(opts: { label?: string } = {}): HTMLElement {\n const bar = h('div', {\n class: 'ink-toolbar',\n 'data-ink-toolbar': '',\n role: 'toolbar',\n 'aria-label': opts.label ?? 'Document tools',\n 'aria-orientation': 'horizontal',\n })\n rovingTabindex(bar)\n return bar\n}\n\n/** A divider between groups of controls in a horizontal toolbar. Not focusable. */\nexport function createToolbarSeparator(): HTMLDivElement {\n return h('div', {\n role: 'separator',\n 'aria-orientation': 'vertical',\n class: 'ink-toolbar-separator',\n 'data-ink-toolbar-separator': '',\n })\n}\n\n/** Undoes the last change to the document's annotations; disabled when there is none. */\nexport function createUndo(viewer: Viewer): HTMLButtonElement {\n return historyButton(viewer, 'undo')\n}\n\n/** Redoes the last undone change; disabled when there is none. */\nexport function createRedo(viewer: Viewer): HTMLButtonElement {\n return historyButton(viewer, 'redo')\n}\n\nfunction historyButton(viewer: Viewer, action: 'undo' | 'redo'): HTMLButtonElement {\n const label = action === 'undo' ? 'Undo' : 'Redo'\n const b = button(\n label,\n { class: `ink-${action}`, [`data-ink-${action}`]: '' },\n action === 'undo' ? Undo2 : Redo2\n )\n b.addEventListener('click', () => viewer.document.get()?.history[action]())\n follow<InkDocument>(viewer.document, b, (doc, watch) =>\n watch(action === 'undo' ? doc.history.canUndo : doc.history.canRedo, (can) => {\n b.disabled = !can\n })\n )\n return b\n}\n\n/** Sets the tool; pressed while it is the active one. */\nexport function createToolButton(\n viewer: Viewer,\n tool: ToolId,\n opts: { label?: string } = {}\n): HTMLButtonElement {\n const label = opts.label ?? TOOL_LABELS[tool]\n const b = button(\n label,\n { class: 'ink-tool-button', 'data-ink-tool-button': '', 'data-tool': tool },\n TOOL_ICONS[tool]\n )\n const show = (active: ToolId | null): void => {\n const on = active === tool\n b.dataset.state = on ? 'on' : 'off'\n b.setAttribute('aria-pressed', String(on))\n }\n b.addEventListener('click', () => viewer.tools.get()?.set(tool))\n follow<ToolController>(\n viewer.tools,\n b,\n (tools, watch) => watch(tools.active, show),\n () => show(null)\n )\n return b\n}\n\nexport function createZoomIn(viewer: Viewer): HTMLButtonElement {\n const b = button('Zoom in', { class: 'ink-zoom-in', 'data-ink-zoom-in': '' }, ZoomIn)\n b.addEventListener('click', () => viewer.viewport.get()?.zoomBy(1.25))\n follow(viewer.viewport, b, () => undefined)\n return b\n}\n\nexport function createZoomOut(viewer: Viewer): HTMLButtonElement {\n const b = button(\n 'Zoom out',\n { class: 'ink-zoom-out', 'data-ink-zoom-out': '' },\n ZoomOut\n )\n b.addEventListener('click', () => viewer.viewport.get()?.zoomBy(0.8))\n follow(viewer.viewport, b, () => undefined)\n return b\n}\n\n/** Fit width, fit page and the zoom levels; a zoom between levels gets an option of its own. */\nexport function createZoomSelect(viewer: Viewer): HTMLSelectElement {\n const custom = h('option', { value: 'custom' })\n const select = h(\n 'select',\n { class: 'ink-zoom-select', 'data-ink-zoom-select': '', 'aria-label': 'Zoom' },\n h('option', { value: 'fit-width' }, 'Fit width'),\n h('option', { value: 'fit-page' }, 'Fit page'),\n ...ZOOM_LEVELS.map((l) =>\n h('option', { value: String(l) }, `${Math.round(l * 100)}%`)\n )\n )\n select.addEventListener('change', () => {\n const v = select.value\n const viewport = viewer.viewport.get()\n if (v === 'fit-width' || v === 'fit-page') viewport?.setZoom(v)\n else if (v !== 'custom') viewport?.setZoom(Number(v))\n })\n follow<Viewport>(\n viewer.viewport,\n select,\n (viewport, watch) =>\n watch(viewport.zoom, (z) => {\n const level =\n typeof z === 'number'\n ? ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\n : undefined\n if (typeof z === 'number' && level === undefined) {\n custom.textContent = `${Math.round(z * 100)}%`\n // In order among the levels.\n const after = [...select.options].find(\n (o) => o !== custom && Number(o.value) > z\n )\n select.insertBefore(custom, after ?? null)\n select.value = 'custom'\n } else {\n custom.remove()\n select.value = typeof z === 'number' ? String(level) : z\n }\n }),\n () => {\n custom.remove()\n select.value = 'fit-width'\n }\n )\n return select\n}\n\n/**\n * The current page, 1-based. Enter or leaving the field goes to the page typed; a number out\n * of range puts the current page back.\n */\nexport function createPageInput(viewer: Viewer): HTMLInputElement {\n const input = h('input', {\n class: 'ink-page-input',\n 'data-ink-page-input': '',\n type: 'number',\n inputmode: 'numeric',\n 'aria-label': 'Page',\n min: '1',\n })\n const commit = (): void => {\n const viewport = viewer.viewport.get()\n const doc = viewer.document.get()\n if (!viewport || !doc) return\n const n = Number(input.value)\n const current = viewport.currentPage.get()\n if (Number.isInteger(n) && n >= 1 && n <= doc.pages.length) {\n if (n - 1 !== current) viewport.scrollToPage(n - 1)\n } else input.value = String(current + 1)\n }\n // `change` fires on blur after typing and on each arrow-key or spinner step.\n input.addEventListener('change', commit)\n input.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' || e.defaultPrevented) return\n e.preventDefault()\n commit()\n })\n follow<Viewport>(\n viewer.viewport,\n input,\n (viewport, watch) => {\n input.max = String(viewer.document.get()?.pages.length ?? 1)\n watch(viewport.currentPage, (p) => (input.value = String(p + 1)))\n },\n () => (input.value = '')\n )\n return input\n}\n\n/** \"of 12\": the page count, announced when it changes. */\nexport function createPageCount(viewer: Viewer): HTMLSpanElement {\n const span = h('span', {\n class: 'ink-page-count',\n 'data-ink-page-count': '',\n 'aria-live': 'polite',\n })\n const show = (): void => {\n const doc = viewer.document.get()\n span.textContent = doc && viewer.viewport.get() ? `of ${doc.pages.length}` : ''\n }\n show()\n viewer.viewport.subscribe(show)\n return span\n}\n\n/** Disabled on the first page. */\nexport function createPrevPage(viewer: Viewer): HTMLButtonElement {\n return pageButton(viewer, -1)\n}\n\n/** Disabled on the last page. */\nexport function createNextPage(viewer: Viewer): HTMLButtonElement {\n return pageButton(viewer, 1)\n}\n\nfunction pageButton(viewer: Viewer, step: -1 | 1): HTMLButtonElement {\n const b =\n step < 0\n ? button(\n 'Previous page',\n { class: 'ink-prev-page', 'data-ink-prev-page': '' },\n ChevronLeft\n )\n : button(\n 'Next page',\n { class: 'ink-next-page', 'data-ink-next-page': '' },\n ChevronRight\n )\n b.addEventListener('click', () => {\n const viewport = viewer.viewport.get()\n viewport?.scrollToPage(viewport.currentPage.get() + step)\n })\n follow<Viewport>(viewer.viewport, b, (viewport, watch) => {\n const last = (viewer.document.get()?.pages.length ?? 1) - 1\n watch(viewport.currentPage, (p) => {\n b.disabled = step < 0 ? p <= 0 : p >= last\n })\n })\n return b\n}\n\n/** Roving items, as in the bindings' Radix toolbar: buttons only. */\nconst ITEMS = 'button'\n\n/**\n * One Tab stop across the enabled buttons in `bar`: the current one has `tabindex=\"0\"`, the\n * rest `-1`. ArrowLeft and ArrowRight move between them and wrap, Home and End go to the ends.\n * Inputs, selects and textareas, built in or added by the host, keep their own tabindex (a\n * Tab stop of their own by default) and their own arrow, Home and End keys.\n */\nfunction rovingTabindex(bar: HTMLElement): { sync(): void; destroy(): void } {\n let current: HTMLElement | null = null\n const items = (): HTMLElement[] =>\n [...bar.querySelectorAll<HTMLButtonElement>(ITEMS)].filter(\n (el) => !el.disabled && !el.closest('[hidden]')\n )\n const sync = (): void => {\n const list = items()\n if (!current || !list.includes(current)) current = list[0] ?? null\n for (const el of bar.querySelectorAll<HTMLElement>(ITEMS))\n el.tabIndex = el === current ? 0 : -1\n // Fields are left alone: they are Tab stops by default, and a host's tabindex on one stays.\n }\n const onFocusIn = (e: FocusEvent): void => {\n const target = e.target as HTMLElement\n if (!items().includes(target)) return\n current = target\n sync()\n }\n const onKeyDown = (e: KeyboardEvent): void => {\n if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey) return\n const list = items()\n const i = list.indexOf(e.target as HTMLElement)\n if (i < 0) return\n const last = list.length - 1\n const next =\n e.key === 'ArrowRight'\n ? i === last\n ? 0\n : i + 1\n : e.key === 'ArrowLeft'\n ? i === 0\n ? last\n : i - 1\n : e.key === 'Home'\n ? 0\n : e.key === 'End'\n ? last\n : -1\n if (next < 0) return\n e.preventDefault()\n list[next]!.focus()\n }\n // Host-added buttons, and buttons a host enables or disables, join the rotation.\n const observer = new MutationObserver(sync)\n observer.observe(bar, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['disabled', 'hidden'],\n })\n bar.addEventListener('focusin', onFocusIn)\n bar.addEventListener('keydown', onKeyDown)\n sync()\n return {\n sync,\n destroy() {\n observer.disconnect()\n bar.removeEventListener('focusin', onFocusIn)\n bar.removeEventListener('keydown', onKeyDown)\n },\n }\n}\n"],"mappings":"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"}
|