@inkbar/core 0.2.0 → 0.4.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/dist/dom.mjs.map CHANGED
@@ -1 +1 @@
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.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 * 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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"}
1
+ {"version":3,"file":"dom.mjs","names":["isCancellation","SVG","CORNERS","fmt","SVG","createToolController","SVG_NS","MIN_CSS","MIN_CSS","SVG_NS","createWith","ITEMS","TABBABLE","button","button","button","SVG_NS"],"sources":["../src/dom/transform.ts","../src/dom/layout.ts","../src/dom/viewport.ts","../src/dom/viewport-keys.ts","../src/dom/dpr-watch.ts","../src/dom/page-renderer.ts","../src/pdfjs/text-layer.ts","../src/dom/text-layer.ts","../src/dom/selection.ts","../src/dom/ink-stroke.ts","../src/dom/overlay-render.ts","../src/dom/freetext-editor.ts","../src/pdfjs/render-region.ts","../src/dom/loupe-layer.ts","../src/dom/mask-layer.ts","../src/dom/overlay.ts","../src/dom/page-mount.ts","../src/dom/tools/options.ts","../src/dom/tools/controller.ts","../src/dom/tools/freehand.ts","../src/dom/tools/draw.ts","../src/dom/tools/freetext.ts","../src/dom/tools/highlight.ts","../src/dom/tools/note.ts","../src/dom/tools/redact-area.ts","../src/dom/tools/selection-edit.ts","../src/dom/tools/select.ts","../src/dom/tools/select-text.ts","../src/dom/tools/shape.ts","../src/dom/tools/signature.ts","../src/dom/tools/sketch.ts","../src/dom/tools/index.ts","../src/dom/palette.ts","../src/dom/ui.ts","../src/dom/menu-keys.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/suggestion-card.ts","../src/dom/viewer/thread-popover.ts","../src/dom/viewer/create-viewer.ts","../src/dom/viewer/controls.ts","../src/dom/viewer/menu.ts","../src/dom/viewer/style-menu.ts","../src/dom/viewer/color-menu.ts","../src/dom/viewer/text-style-menu.ts","../src/dom/shape-icons.ts","../src/dom/viewer/shape-menu.ts","../src/dom/markup-icons.ts","../src/dom/viewer/highlight-menu.ts","../src/dom/signature-pad.ts","../src/dom/signature-draft.ts","../src/dom/viewer/signature-dialog.ts","../src/dom/viewer/signature-menu.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","// Watches the device pixel ratio for the layers that render at it: the page canvas and the\n// loupes. The media query matches only the ratio it was built for, so it is rebuilt after\n// every change. During a browser-zoom or screen transition the query can fire while\n// devicePixelRatio still reports the old value, so each change also schedules follow-up checks.\n\nconst RECHECK_MS = [100, 500]\n\nexport interface DprWatch {\n /** Watches for a change away from `dpr`, the ratio just rendered at. */\n watch(dpr: number): void\n destroy(): void\n}\n\n/**\n * Calls `onChange` when `view`'s device pixel ratio moves away from the one last passed to\n * `watch`. `current` reads the ratio now. Does nothing where `matchMedia` is missing.\n */\nexport function watchDevicePixelRatio(\n view: Window | null | undefined,\n current: () => number,\n onChange: () => void\n): DprWatch {\n let query: MediaQueryList | undefined\n let watched: number | undefined\n let rechecks: ReturnType<typeof setTimeout>[] = []\n let destroyed = false\n\n const clearRechecks = (): void => {\n rechecks.forEach(clearTimeout)\n rechecks = []\n }\n const fire = (): void => {\n if (destroyed) return\n arm(current(), true)\n onChange()\n clearRechecks()\n rechecks = RECHECK_MS.map((ms) =>\n setTimeout(() => {\n if (!destroyed && current() !== watched) fire()\n }, ms)\n )\n }\n function arm(dpr: number, force = false): void {\n if (destroyed || !view?.matchMedia) return\n if (dpr === watched && !force) return\n watched = dpr\n query?.removeEventListener('change', fire)\n query = view.matchMedia(`(resolution: ${dpr}dppx)`)\n query.addEventListener('change', fire)\n }\n\n return {\n watch: (dpr) => arm(dpr),\n destroy() {\n destroyed = true\n query?.removeEventListener('change', fire)\n query = undefined\n clearRechecks()\n },\n }\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 { watchDevicePixelRatio } from './dpr-watch'\n\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 dprWatch?.watch(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.\n const dprWatch =\n opts.devicePixelRatio === undefined\n ? watchDevicePixelRatio(view, currentDpr, () => void render(latest))\n : undefined\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 dprWatch?.destroy()\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","// Turns the sampled points of an ink stroke into a smoothed, filled outline. Overlay rendering\n// and the draw tool's live preview share it, so a stroke looks the same while drawn and after.\nimport { getStroke } from 'perfect-freehand'\n\nimport type { Point } from '../model/geometry'\n\n/** Strokes started within this long of the last one join its annotation. */\nexport const JOIN_GAP_MS = 1000\n\n/**\n * The polygon around a stroke. `width` is the stroke width, in the points' own unit; without\n * `pressure` the line keeps an even width.\n */\nexport function strokeOutline(\n points: readonly Point[],\n pressure: readonly number[] | undefined,\n width: number\n): Point[] {\n const withPressure = pressure !== undefined\n const input = points.map(\n (p, i) => [p.x, p.y, pressure?.[i] ?? 0.5] as [number, number, number]\n )\n return getStroke(input, {\n size: width,\n thinning: withPressure ? 0.5 : 0,\n smoothing: 0.5,\n streamline: 0.5,\n simulatePressure: false,\n }).map(([x, y]) => ({ x, y }))\n}\n\n/** A closed SVG path `d` through `outline`; empty for an empty outline. */\nexport function outlinePath(outline: readonly Point[]): string {\n if (outline.length === 0) return ''\n const r = (n: number): string => String(Math.round(n * 100) / 100)\n return `M${outline.map((p) => `${r(p.x)},${r(p.y)}`).join('L')}Z`\n}\n","import { ICON_ATTRIBUTES, MessageSquareText } from '@inkbar/icons'\n\nimport {\n calloutStroke,\n freeTextBox,\n isStandardCallout,\n} from '../model/annotations/callout'\nimport { isBubble, isTextMarkup, WEDGE_HALF } from '../model/annotations/edit'\nimport { isKnown, LINE_ENDINGS } from '../model/annotations/pdf-names'\n\nimport { outlinePath, strokeOutline } from './ink-stroke'\nimport { normalizeRotation, type CssRect, type PageTransform } from './transform'\n\nimport type {\n Annotation,\n FreeTextAnnotation,\n LineEnding,\n StampAnnotation,\n TextMarkupAnnotation,\n} from '../model/annotations/types'\nimport type { Point, Quad } from '../model/geometry'\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\n/** Side of an edit handle, CSS px. */\nconst HANDLE_PX = 8\nconst CORNERS = ['nw', 'ne', 'sw', 'se'] as const\n/** Width in CSS px of the band along a mask's edge that takes presses. */\nconst MASK_EDGE = 6\n\n/**\n * Which edit handles an element shows: none, the four CSS corners of a box (`nw`, `ne`, `sw`,\n * `se`), or a line's two ends (`start`, `end`), all element-local CSS px.\n */\nexport type HandleSpec =\n | { kind: 'none' }\n | {\n kind: 'corners'\n /** The box's top-left corner; 0,0 (the element's own) when absent. */\n left?: number\n top?: number\n width: number\n height: number\n /** A callout's tip: one more handle, `callout`. */\n tail?: Point\n }\n | { kind: 'ends'; start: Point; end: Point }\n\n/**\n * Syncs an element's edit handles (`.ink-handle[data-handle]`) with `spec`. Each is an 8px\n * `position:absolute; pointer-events:auto` box centred on its point; its look is the theme's.\n */\nexport function syncHandles(node: HTMLElement, spec: HandleSpec): void {\n const existing = [...node.querySelectorAll<HTMLElement>(':scope > [data-handle]')]\n const names: readonly string[] =\n spec.kind === 'none'\n ? []\n : spec.kind === 'ends'\n ? ['start', 'end']\n : spec.tail\n ? [...CORNERS, 'callout']\n : CORNERS\n if (\n existing.length !== names.length ||\n existing.some((h, i) => h.dataset.handle !== names[i])\n ) {\n existing.forEach((h) => h.remove())\n existing.length = 0\n for (const name of names) {\n const h = node.ownerDocument.createElement('div')\n h.className = 'ink-handle'\n h.dataset.handle = name\n h.setAttribute('aria-hidden', 'true')\n h.style.cssText = `position:absolute;width:${HANDLE_PX}px;height:${HANDLE_PX}px;pointer-events:auto;`\n node.append(h)\n existing.push(h)\n }\n }\n for (const h of existing) {\n const name = h.dataset.handle!\n const at =\n spec.kind === 'ends'\n ? name === 'start'\n ? spec.start\n : spec.end\n : spec.kind === 'corners'\n ? name === 'callout' && spec.tail\n ? spec.tail\n : {\n x: (spec.left ?? 0) + (name[1] === 'w' ? 0 : spec.width),\n y: (spec.top ?? 0) + (name[0] === 'n' ? 0 : spec.height),\n }\n : { x: 0, y: 0 }\n h.style.left = `${at.x - HANDLE_PX / 2}px`\n h.style.top = `${at.y - HANDLE_PX / 2}px`\n }\n}\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 stroke = Math.max(t.toCssLength(a.width), 1)\n // Endings reach up to ENDING_SCALE strokes either side of their end.\n const pad = hasEndings(a) ? ENDING_SCALE * stroke : stroke / 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\n/** An ending's length, and its full width, as a multiple of the stroke width. */\nconst ENDING_SCALE = 3\n\n/** A name Inkbar does not draw is drawn as no ending; the annotation keeps it. */\nfunction drawable(kind: LineEnding | undefined): LineEnding {\n return kind !== undefined && isKnown(LINE_ENDINGS, kind) ? kind : 'None'\n}\n\nfunction endingKinds(a: Annotation): { head: LineEnding; tail: LineEnding } | undefined {\n return a.type === 'line' || a.type === 'polyline'\n ? { head: drawable(a.head), tail: drawable(a.tail) }\n : undefined\n}\n\nfunction hasEndings(a: Annotation): boolean {\n const e = endingKinds(a)\n return e !== undefined && (e.head !== 'None' || e.tail !== 'None')\n}\n\nconst fmt = (n: number): string => String(Math.round(n * 1000) / 1000 + 0)\n\n/**\n * SVG path data for a line ending at `at`, in the caller's coordinates (CSS px). `from` is the\n * other end of the segment the ending sits on, so the ending points from `from` towards `at`.\n * Sized from the stroke `width` (at least 1): arrows are 3 strokes long, the rest 3 across.\n * Returns an empty string for `none` or a zero-length segment.\n */\nexport function lineEndingPath(\n kind: LineEnding,\n at: Point,\n from: Point,\n width: number\n): string {\n const len = Math.hypot(at.x - from.x, at.y - from.y)\n if (!isKnown(LINE_ENDINGS, kind) || kind === 'None' || len === 0) return ''\n const size = ENDING_SCALE * Math.max(width, 1)\n const half = size / 2\n const dx = (at.x - from.x) / len\n const dy = (at.y - from.y) / len\n // Unit normal, 90 degrees clockwise on screen.\n const nx = -dy\n const ny = dx\n const pt = (along: number, across: number, o: Point = at): string =>\n `${fmt(o.x + dx * along + nx * across)} ${fmt(o.y + dy * along + ny * across)}`\n switch (kind) {\n case 'OpenArrow':\n return `M${pt(-size, -half)}L${pt(0, 0)}L${pt(-size, half)}`\n case 'ClosedArrow':\n return `M${pt(-size, -half)}L${pt(0, 0)}L${pt(-size, half)}Z`\n case 'ROpenArrow':\n return `M${pt(0, -half)}L${pt(-size, 0)}L${pt(0, half)}`\n case 'RClosedArrow':\n return `M${pt(0, -half)}L${pt(-size, 0)}L${pt(0, half)}Z`\n case 'Square':\n return `M${pt(-half, -half)}L${pt(half, -half)}L${pt(half, half)}L${pt(-half, half)}Z`\n case 'Diamond':\n return `M${pt(-half, 0)}L${pt(0, -half)}L${pt(half, 0)}L${pt(0, half)}Z`\n case 'Circle':\n return `M${pt(half, 0)}A${fmt(half)} ${fmt(half)} 0 1 0 ${pt(-half, 0)}A${fmt(half)} ${fmt(half)} 0 1 0 ${pt(half, 0)}Z`\n case 'Butt':\n return `M${pt(0, -half)}L${pt(0, half)}`\n case 'Slash': {\n // Tilted 30 degrees from the butt, as PDF draws it.\n const s = Math.sin(Math.PI / 6) * half\n const c = Math.cos(Math.PI / 6) * half\n return `M${pt(-s, -c)}L${pt(s, c)}`\n }\n default:\n return ''\n }\n}\n\n/** Endings that are solid shapes: filled with the stroke colour. */\nconst FILLED_ENDINGS: ReadonlySet<LineEnding> = new Set([\n 'ClosedArrow',\n 'RClosedArrow',\n 'Square',\n 'Circle',\n 'Diamond',\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 /** A user-space point in element-local CSS px. */\n const at = (p: Point): Point => {\n const c = t.toCss(p)\n return { x: c.x - box.left, y: c.y - box.top }\n }\n const local = (p: Point): string => {\n const c = at(p)\n return `${c.x},${c.y}`\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 if (isBubble(a)) {\n // One path draws the box and its tail; the text box sits above it with no look of its own.\n const svg = boxSvg(doc, box.width, box.height)\n svg.classList.add('ink-annotation-shape')\n svg.setAttribute('opacity', String(a.opacity))\n const path = node('path', {\n d: bubblePath(a, t),\n fill: a.color ?? 'none',\n stroke: a.width > 0 ? (a.borderColor ?? a.defaultStyle.color) : 'none',\n 'stroke-width': t.toCssLength(a.width),\n 'stroke-linejoin': 'round',\n 'pointer-events': 'visiblePainted',\n })\n path.classList.add('ink-bubble')\n dash(path, a.dashes, t)\n svg.append(path)\n el.append(svg)\n } else if (isStandardCallout(a)) {\n // The leader line runs from the tip to the box, with its ending at the tip.\n const svg = boxSvg(doc, box.width, box.height)\n svg.classList.add('ink-annotation-shape')\n svg.setAttribute('opacity', String(a.opacity))\n const stroke = calloutStroke(a)\n const sw = t.toCssLength(stroke.width)\n const line = node('polyline', {\n points: a.callout.map(local).join(' '),\n fill: 'none',\n stroke: stroke.color,\n 'stroke-width': sw,\n 'stroke-linejoin': 'round',\n 'stroke-linecap': 'butt',\n 'pointer-events': 'visiblePainted',\n })\n line.classList.add('ink-callout-line')\n // The leader line is dashed as the box's border is.\n dash(line, a.dashes, t)\n svg.append(line)\n const kind = drawable(a.head)\n const d = lineEndingPath(kind, at(a.callout[0]!), at(a.callout[1]!), sw)\n if (d) {\n const ending = node('path', {\n d,\n fill: FILLED_ENDINGS.has(kind) ? stroke.color : 'none',\n stroke: stroke.color,\n 'stroke-width': sw,\n 'stroke-linejoin': 'round',\n 'stroke-linecap': kind === 'Butt' || kind === 'Slash' ? 'butt' : 'round',\n 'pointer-events': 'visiblePainted',\n })\n ending.setAttribute('data-ending', 'head')\n svg.append(ending)\n }\n el.append(svg)\n }\n // HTML rather than SVG <text>: a text box must wrap, and SVG text does not.\n const text = doc.createElement('div')\n text.className = 'ink-free-text'\n text.textContent = a.contents\n styleFreeText(text, a, t)\n if (a.fringe) {\n // Inset from the element, which covers the whole rect.\n const inner = freeTextLocalBox(a, t)\n text.style.position = 'absolute'\n text.style.left = `${inner.left}px`\n text.style.top = `${inner.top}px`\n text.style.width = `${inner.width}px`\n text.style.height = `${inner.height}px`\n }\n // Structural: the element itself ignores the pointer, the text box takes it.\n text.style.pointerEvents = 'auto'\n el.append(text)\n appendSelectionFrame(el, a, t)\n return\n }\n\n if (a.type === 'stamp') {\n el.append(stampImage(doc, a, t, box))\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 ...(a.cornerRadius ? { rx: t.toCssLength(a.cornerRadius) } : {}),\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 dash(shape, a.dashes, t)\n svg.append(shape)\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'loupe': {\n // The rim, over the magnified canvas the overlay's loupe layer puts first in the\n // element. Its transparent fill takes presses anywhere on the lens.\n const sw = t.toCssLength(a.width)\n const rim = node('circle', {\n cx: box.width / 2,\n cy: box.height / 2,\n r: Math.max(0, Math.min(box.width, box.height) / 2 - sw / 2),\n fill: 'transparent',\n stroke: sw > 0 ? a.color : 'none',\n 'stroke-width': sw,\n })\n rim.classList.add('ink-loupe-rim')\n svg.append(rim)\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'mask': {\n // The shape's outline as an invisible band just inside the edge: it takes presses on\n // the edge only, so the spotlight stays readable, selectable and annotatable, and the\n // dimmed area outside belongs to the page. The dimming is the mask layer's.\n const inset = MASK_EDGE / 2\n const shape =\n a.shape === 'ellipse'\n ? node('ellipse', {\n cx: box.width / 2,\n cy: box.height / 2,\n rx: Math.max(0, box.width / 2 - inset),\n ry: Math.max(0, box.height / 2 - inset),\n })\n : node('rect', {\n x: inset,\n y: inset,\n width: Math.max(0, box.width - MASK_EDGE),\n height: Math.max(0, box.height - MASK_EDGE),\n })\n shape.setAttribute('fill', 'none')\n shape.setAttribute('stroke', 'transparent')\n shape.setAttribute('stroke-width', String(MASK_EDGE))\n shape.classList.add('ink-mask-shape')\n svg.append(shape)\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 const stroked = 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 dash(stroked, a.dashes, t)\n svg.append(stroked)\n const ends = endingKinds(a)\n if (ends && pts.length >= 2) {\n for (const [name, kind, tip, other] of [\n ['head', ends.head, pts[0]!, pts[1]!],\n ['tail', ends.tail, pts[pts.length - 1]!, pts[pts.length - 2]!],\n ] as const) {\n const d = lineEndingPath(kind, at(tip), at(other), t.toCssLength(a.width))\n if (!d) continue\n const ending = node('path', {\n d,\n fill: FILLED_ENDINGS.has(kind) ? a.color : 'none',\n stroke: a.color,\n 'stroke-width': t.toCssLength(a.width),\n 'stroke-linejoin': 'round',\n // A butt or slash ending is a cut across the line: a round cap would blunt it.\n 'stroke-linecap': kind === 'Butt' || kind === 'Slash' ? 'butt' : 'round',\n })\n ending.setAttribute('data-ending', name)\n svg.append(ending)\n }\n }\n svg.setAttribute('opacity', String(a.opacity))\n break\n }\n case 'ink':\n // Every stroke is a smoothed filled outline, thinned by pressure when there is some.\n // Dashes do not apply to a filled outline.\n a.inklist.forEach((path, i) => {\n const outline = strokeOutline(\n path.map(at),\n a.pressure?.[i],\n t.toCssLength(a.width)\n )\n svg.append(\n node('path', { class: 'ink-stroke', d: outlinePath(outline), fill: a.color })\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 appendCommentMarker(el, a, t)\n}\n\n/**\n * A stamp's `img.ink-stamp`, filling the element's box. The image is upright in user space\n * turned by the stamp's `rotation` (anticlockwise), and the page turns it again on screen\n * (clockwise), so it is drawn turned by the difference: a signature placed against the page's\n * turn reads upright. Size, position and turn are geometry, set inline; the opacity travels as\n * `--ink-opacity` for the theme.\n */\nfunction stampImage(\n doc: Document,\n a: StampAnnotation,\n t: PageTransform,\n box: CssRect\n): HTMLImageElement {\n const img = doc.createElement('img')\n img.className = 'ink-stamp'\n img.alt = ''\n img.draggable = false\n img.decoding = 'async'\n img.src = a.imagedata\n const turn = normalizeRotation(t.totalRotation - (a.rotation ?? 0))\n const sideways = turn === 90 || turn === 270\n const width = sideways ? box.height : box.width\n const height = sideways ? box.width : box.height\n img.style.position = 'absolute'\n img.style.left = `${(box.width - width) / 2}px`\n img.style.top = `${(box.height - height) / 2}px`\n img.style.width = `${width}px`\n img.style.height = `${height}px`\n if (turn !== 0) img.style.transform = `rotate(${turn}deg)`\n // Structural: the element itself ignores the pointer, the image takes it.\n img.style.pointerEvents = 'auto'\n img.style.setProperty('--ink-opacity', String(a.opacity))\n return img\n}\n\n/**\n * Styles a free-text box (`.ink-free-text`) from its annotation, as the theme reads it: the text\n * style, fill, border colour and width, corner radius and opacity travel as custom properties\n * (`--ink-font-size`, `--ink-font-family`, `--ink-font-weight`, `--ink-font-style`,\n * `--ink-text-decoration`, `--ink-text-color`, `--ink-fill`, `--ink-box-border`,\n * `--ink-border-width`, `--ink-corner-radius`, `--ink-opacity`); alignment as `data-align`,\n * and a border as `data-border` (`solid` or `dashed`, absent at width 0). Lengths are scaled to\n * CSS px. Shared by the overlay and the in-place editor, so both look the same.\n */\nexport function styleFreeText(\n node: HTMLElement,\n a: FreeTextAnnotation,\n t: PageTransform\n): void {\n const s = a.defaultStyle\n const set = (name: string, value: string | undefined): void => {\n if (value === undefined) node.style.removeProperty(name)\n else node.style.setProperty(name, value)\n }\n set('--ink-font-size', `${t.toCssLength(s.fontSize)}px`)\n set('--ink-font-family', cssString(s.fontFamily))\n set('--ink-font-weight', s.fontWeight)\n set('--ink-font-style', s.fontStyle)\n set('--ink-text-decoration', s.textDecoration)\n set('--ink-text-color', s.color)\n // A speech bubble's outline and fill are drawn by its path, not by the text box.\n const bubble = isBubble(a)\n set('--ink-fill', bubble ? undefined : a.color)\n // Not `--ink-border`, the interface's border token: a box with no border colour of its own\n // takes its text colour, as a bubble's outline does.\n set('--ink-box-border', bubble ? undefined : (a.borderColor ?? s.color))\n set(\n '--ink-border-width',\n !bubble && a.width > 0 ? `${t.toCssLength(a.width)}px` : undefined\n )\n set(\n '--ink-corner-radius',\n !bubble && a.cornerRadius ? `${t.toCssLength(a.cornerRadius)}px` : undefined\n )\n set('--ink-opacity', String(a.opacity))\n node.dataset.align = s.textAlign\n if (bubble) node.dataset.bubble = ''\n else delete node.dataset.bubble\n if (!bubble && a.width > 0) node.dataset.border = a.dashes?.length ? 'dashed' : 'solid'\n else delete node.dataset.border\n}\n\n/**\n * A free text's text box (`freeTextBox`) in CSS px, relative to the top-left of its rect on\n * screen, where its overlay element sits.\n */\nexport function freeTextLocalBox(a: FreeTextAnnotation, t: PageTransform): CssRect {\n const origin = t.toCssRect(a.rect)\n const box = t.toCssRect(freeTextBox(a))\n return {\n left: box.left - origin.left,\n top: box.top - origin.top,\n width: box.width,\n height: box.height,\n }\n}\n\n/**\n * The outline of a speech bubble as SVG path data in CSS px relative to `origin` (by default\n * the top-left of its rect on screen, where its overlay element sits): the rounded text box\n * (`freeTextBox`) with a wedge to the tip, `callout[0]`. The wedge leaves the box edge nearest\n * `callout`'s last point, at that point's position along it, kept clear of the corners.\n */\nexport function bubblePath(\n a: FreeTextAnnotation & { callout: readonly Point[] },\n t: PageTransform,\n origin: { left: number; top: number } = t.toCssRect(a.rect)\n): string {\n const css = t.toCssRect(freeTextBox(a))\n // Box-relative CSS px: the box's top-left is 0,0.\n const inBox = (p: Point): Point => {\n const c = t.toCss(p)\n return { x: c.x - css.left, y: c.y - css.top }\n }\n const tip = inBox(a.callout[0]!)\n const edge = inBox(a.callout[a.callout.length - 1]!)\n const w = css.width\n const h = css.height\n const r = Math.min(t.toCssLength(a.cornerRadius ?? 0), w / 2, h / 2)\n // The edge nearest the last point, as `nearestEdge` (model/annotations/edit.ts) picks it,\n // ties included (left, right, bottom, top on an unturned page); change both together.\n const gaps = {\n left: Math.abs(edge.x),\n right: Math.abs(edge.x - w),\n bottom: Math.abs(edge.y - h),\n top: Math.abs(edge.y),\n }\n const side = (Object.keys(gaps) as (keyof typeof gaps)[]).reduce((best, s) =>\n gaps[s] < gaps[best] ? s : best\n )\n const along = side === 'top' || side === 'bottom' ? w : h\n const half = Math.min(t.toCssLength(WEDGE_HALF), along / 4)\n const lo = Math.min(r + half, along / 2)\n const at = Math.min(\n Math.max(side === 'top' || side === 'bottom' ? edge.x : edge.y, lo),\n along - lo\n )\n const dx = css.left - origin.left\n const dy = css.top - origin.top\n const P = (x: number, y: number): string => `${fmt(x + dx)} ${fmt(y + dy)}`\n const arc = (x: number, y: number): string =>\n r > 0 ? `A${fmt(r)} ${fmt(r)} 0 0 1 ${P(x, y)}` : ''\n const spike = (x: number, y: number): string => `L${P(x, y)}L${P(tip.x, tip.y)}`\n return [\n `M${P(r, 0)}`,\n side === 'top' ? `${spike(at - half, 0)}L${P(at + half, 0)}` : '',\n `L${P(w - r, 0)}${arc(w, r)}`,\n side === 'right' ? `${spike(w, at - half)}L${P(w, at + half)}` : '',\n `L${P(w, h - r)}${arc(w - r, h)}`,\n side === 'bottom' ? `${spike(at + half, h)}L${P(at - half, h)}` : '',\n `L${P(r, h)}${arc(0, h - r)}`,\n side === 'left' ? `${spike(0, at + half)}L${P(0, at - half)}` : '',\n `L${P(0, r)}${arc(r, 0)}Z`,\n ].join('')\n}\n\n/**\n * Redraws an open bubble's outline as `a`, a draft of it (the editor's, as its box grows with\n * its text), in an element whose top-left is `origin` on screen. No-op on any other element.\n */\nexport function refitBubble(\n el: HTMLElement,\n a: FreeTextAnnotation,\n t: PageTransform,\n origin: { left: number; top: number }\n): void {\n const path = el.querySelector(':scope > svg > .ink-bubble')\n if (!path || !isBubble(a)) return\n path.setAttribute('d', bubblePath(a, t, origin))\n}\n\n/** Sets `stroke-dasharray` from a dash pattern in points, scaled to CSS px. */\nfunction dash(\n shape: Element,\n dashes: readonly number[] | undefined,\n t: PageTransform\n): void {\n if (!dashes || dashes.length === 0) return\n shape.setAttribute('stroke-dasharray', dashes.map((d) => t.toCssLength(d)).join(' '))\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 drawHitArea(el, a, t)\n if (a.type === 'freetext') appendSelectionFrame(el, a, t)\n appendCommentMarker(el, a, t)\n}\n\n/**\n * For a free text inset by a fringe: a `div.ink-selection-frame` over its text box, where its\n * corner handles sit, and `data-framed` on the element, so the theme draws the selection\n * outline on the box rather than round the whole rect. Geometry only, `pointer-events:none`.\n */\nfunction appendSelectionFrame(\n el: HTMLElement,\n a: FreeTextAnnotation,\n t: PageTransform\n): void {\n el.toggleAttribute('data-framed', a.fringe !== undefined)\n if (!a.fringe) return\n const box = freeTextLocalBox(a, t)\n const frame = el.ownerDocument.createElement('div')\n frame.className = 'ink-selection-frame'\n frame.setAttribute('aria-hidden', 'true')\n frame.style.cssText =\n `position:absolute;pointer-events:none;left:${box.left}px;top:${box.top}px;` +\n `width:${box.width}px;height:${box.height}px;`\n el.append(frame)\n}\n\n/** True for text markup whose `contents` holds a comment. */\nexport function hasComment(a: Annotation): a is TextMarkupAnnotation {\n return isTextMarkup(a) && !!a.contents?.trim()\n}\n\n/**\n * Marks commented text markup with `span.ink-comment-marker`, holding a comment glyph, at the\n * last quad's top-right corner (its end in reading order), relative to the element. The theme\n * sizes and colours it.\n */\nfunction appendCommentMarker(el: HTMLElement, a: Annotation, t: PageTransform): void {\n if (!hasComment(a)) return\n const last = a.quads[a.quads.length - 1]\n if (!last) return\n const box = annotationBox(a, t)\n const at = t.toCss(last.p2)\n const marker = el.ownerDocument.createElement('span')\n marker.className = 'ink-comment-marker'\n marker.dataset.inkCommentMarker = ''\n marker.setAttribute('aria-hidden', 'true')\n marker.style.left = `${at.x - box.left}px`\n marker.style.top = `${at.y - box.top}px`\n const icon = el.ownerDocument.createElementNS(SVG, 'svg')\n for (const [k, v] of Object.entries(ICON_ATTRIBUTES)) icon.setAttribute(k, v)\n for (const [tag, attrs] of MessageSquareText) {\n const child = el.ownerDocument.createElementNS(SVG, tag)\n for (const [k, v] of Object.entries(attrs)) child.setAttribute(k, v)\n icon.append(child)\n }\n marker.append(icon)\n el.append(marker)\n}\n\nfunction drawHitArea(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","// In-place editing for a free-text box. The editor is a plain-text `contenteditable` laid over\n// the box inside its overlay element, styled from the annotation exactly as the box is\n// (`styleFreeText`), with the box itself hidden underneath. It grows downwards on screen as the\n// text needs more lines, and nothing reaches the store until it closes: a commit hands back the\n// text and the grown rect together, so the edit is one change and one undo step. A callout's\n// `rect` and `fringe` are refit around the grown box and its callout (`grownFreeText`).\n//\n// Inline styles here are structural or geometric only: the editor's position and minimum\n// height, the box's `visibility` while it is covered, and the element's grown height.\nimport { freeTextBox } from '../model/annotations/callout'\nimport { hasCallout, isBubble, resizedBox, withBox } from '../model/annotations/edit'\n\nimport { freeTextLocalBox, refitBubble, styleFreeText } from './overlay-render'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\nimport type { Annotation, FreeTextAnnotation } from '../model/annotations/types'\nimport type { Point, Rect } from '../model/geometry'\n\nexport interface FreeTextEditor {\n /** Closes the editor, handing its text to `commit` (true) or calling `cancel` (false). */\n close(commit: boolean): void\n}\n\nexport interface FreeTextEditorOptions {\n transform: PageTransform\n /**\n * The edited text and the box's rect, grown to fit it (`grownFreeText`), in user space.\n * `grown` is the growth alone, in CSS px (0 when the box kept its height), for a caller whose\n * box may have moved or been resized while the editor was open.\n */\n commit(contents: string, rect: Rect, grown: number): void\n cancel(): void\n}\n\n/** The open editor on each overlay element. */\nconst editors = new WeakMap<HTMLElement, FreeTextEditor>()\n/** Presses that closed an editor, so a tool can leave them alone. */\nconst closingPresses = new WeakSet<Event>()\n\n/** The editor open on an overlay element, if any. */\nexport function editorFor(el: HTMLElement): FreeTextEditor | undefined {\n return editors.get(el)\n}\n\n/** True when `e` is a press outside an editor that closed it. */\nexport function closedEditor(e: Event): boolean {\n return closingPresses.has(e)\n}\n\n/** Point within which a grown height counts as unchanged, CSS px. */\nconst SAME_PX = 0.5\n/** The editor's narrowest width, in ems of the box's font size, for a box inset to nothing. */\nconst MIN_WIDTH_EM = 2\n\n/**\n * Opens an editor on `el`, the overlay element showing `a` (or a stand-in for a box not in the\n * store yet). `Escape` commits; a press outside the editor, or focus leaving it, commits too.\n * Closing while the editor has focus hands focus to `el`. Keys typed in the\n * editor stop there, so no viewport or tool shortcut sees them. Opening a second editor on the\n * same element commits the first.\n */\nexport function editFreeText(\n el: HTMLElement,\n a: FreeTextAnnotation,\n opts: FreeTextEditorOptions\n): FreeTextEditor {\n editors.get(el)?.close(true)\n const doc = el.ownerDocument\n const view = doc.defaultView\n // The element covers the rect; the text box sits inside it, inset by any fringe.\n const base = opts.transform.toCssRect(a.rect)\n const inner = freeTextLocalBox(a, opts.transform)\n const box = el.querySelector<HTMLElement>(':scope > .ink-free-text')\n\n const field = doc.createElement('div')\n field.className = 'ink-free-text'\n field.dataset.inkEditor = ''\n field.setAttribute('role', 'textbox')\n field.setAttribute('aria-multiline', 'true')\n field.setAttribute('aria-label', 'Text box')\n styleFreeText(field, a, opts.transform)\n field.style.position = 'absolute'\n field.style.left = `${inner.left}px`\n field.style.top = `${inner.top}px`\n // A fringe can leave a box too narrow to type in: never narrower than a couple of letters.\n const floor = opts.transform.toCssLength(a.defaultStyle.fontSize * MIN_WIDTH_EM)\n field.style.width = a.fringe ? `${Math.max(inner.width, floor)}px` : '100%'\n field.style.height = 'auto'\n field.style.minHeight = `${inner.height}px`\n field.style.pointerEvents = 'auto'\n makeEditable(field)\n field.textContent = a.contents\n if (box) box.style.visibility = 'hidden'\n el.append(field)\n\n /** The box's CSS height for the text now in it: never less than it started at. */\n const height = (): number =>\n Math.max(inner.height, field.getBoundingClientRect().height)\n /** `a` with its box grown by `grown` CSS px. */\n const grownTo = (grown: number): FreeTextAnnotation =>\n grown === 0 ? a : { ...a, ...grownFreeText(a, grown, opts.transform) }\n const grow = (): void => {\n const h = height()\n el.style.height = `${base.height + h - inner.height}px`\n // A bubble's outline grows with its text.\n refitBubble(el, grownTo(h - inner.height), opts.transform, base)\n }\n const Observer = view?.ResizeObserver\n const observer = Observer ? new Observer(grow) : undefined\n observer?.observe(field)\n\n const read = (): string => {\n const text = field.innerText.replace(/\\r\\n?/g, '\\n')\n // A trailing line break is held open by a placeholder <br>, which reads as one more.\n return field.lastChild?.nodeName === 'BR' ? text.replace(/\\n$/, '') : text\n }\n /** How far the box grew, CSS px; 0 within `SAME_PX`. */\n const growth = (): number => {\n const grown = height() - inner.height\n return Math.abs(grown) < SAME_PX ? 0 : grown\n }\n\n let closed = false\n const finish = (commit: boolean): void => {\n if (closed) return\n closed = true\n const contents = read()\n const grown = growth()\n const next = grownTo(grown).rect\n observer?.disconnect()\n view?.removeEventListener('pointerdown', onOutside, true)\n editors.delete(el)\n // While the editor has focus, it moves to the box before the editor goes, so it never\n // falls back to <body>. Focus that already left (a click on a control) stays where it is.\n if (field.contains(doc.activeElement)) el.focus({ preventScroll: true })\n field.remove()\n box?.style.removeProperty('visibility')\n el.style.height = `${base.height}px`\n refitBubble(el, a, opts.transform, base)\n if (commit) opts.commit(contents, next, grown)\n else opts.cancel()\n }\n\n const onOutside = (e: Event): void => {\n if (e.target instanceof Node && field.contains(e.target)) return\n closingPresses.add(e)\n finish(true)\n }\n view?.addEventListener('pointerdown', onOutside, true)\n field.addEventListener('keydown', (e) => {\n e.stopPropagation()\n if (e.key === 'Escape' && !e.isComposing) {\n e.preventDefault()\n finish(true)\n }\n })\n field.addEventListener('focusout', (e) => {\n // A window losing focus (another tab, devtools) leaves the edit open.\n if (!doc.hasFocus()) return\n const to = e.relatedTarget\n if (to instanceof Node && field.contains(to)) return\n finish(true)\n })\n // Plain text only, whatever the clipboard holds and whichever editing mode the browser has.\n field.addEventListener('paste', (e) => {\n e.preventDefault()\n insertText(field, e.clipboardData?.getData('text/plain') ?? '')\n })\n field.addEventListener('beforeinput', (e) => {\n if (e.inputType.startsWith('format')) e.preventDefault()\n })\n\n field.focus({ preventScroll: true })\n const selection = doc.getSelection()\n if (selection) {\n const range = doc.createRange()\n range.selectNodeContents(field)\n range.collapse(false)\n selection.removeAllRanges()\n selection.addRange(range)\n }\n grow()\n\n const editor: FreeTextEditor = { close: (commit) => finish(commit) }\n editors.set(el, editor)\n return editor\n}\n\n/**\n * True when `a` can be edited in place on its overlay element `el`: an unlocked free-text box\n * the overlay draws itself. Embedded boxes (painted on the canvas, with only a hit area here)\n * and host-rendered (`data-custom`) elements are not. Every edit path asks this.\n */\nexport function canEditFreeText(\n a: Annotation | undefined,\n el: Element | null | undefined\n): a is FreeTextAnnotation {\n return (\n a !== undefined &&\n a.type === 'freetext' &&\n !a.locked &&\n a.source !== 'pdf' &&\n !!el &&\n !el.hasAttribute('data-custom')\n )\n}\n\n/**\n * Opens an editor on the overlay element `el` for the free-text box `id`, wired to the store: a\n * commit is one `update` with the text and the grown rect (none when neither changed), and an\n * empty box is removed, as an abandoned note is. A speech bubble is the exception: its outline\n * shows without text, so it is kept. Returns undefined when the box cannot be\n * edited (`canEditFreeText`).\n */\nexport function editFreeTextIn(\n store: AnnotationStore,\n el: HTMLElement,\n id: string,\n transform: PageTransform\n): FreeTextEditor | undefined {\n const a = store._getProposed(id) ?? store.get(id)\n if (!canEditFreeText(a, el)) return undefined\n const current = (): FreeTextAnnotation | undefined => {\n const now = store._getProposed(id) ?? store.get(id)\n return now?.type === 'freetext' ? now : undefined\n }\n return editFreeText(el, a, {\n transform,\n commit(contents, _rect, grown) {\n const now = current()\n if (!now) return\n if (contents.trim() === '' && !isBubble(now)) {\n store.remove(id)\n return\n }\n // The growth applies to the box as it is now: it may have moved while the editor was open.\n if (grown === 0) {\n if (contents !== now.contents) store.update(id, { contents })\n return\n }\n store.update(id, { contents, ...grownFreeText(now, grown, transform) })\n },\n cancel() {\n const now = current()\n if (now && now.contents.trim() === '' && !isBubble(now)) store.remove(id)\n },\n })\n}\n\n/**\n * The patch that grows a free text's text box down the screen by `grown` CSS px, its top edge\n * fixed, with `rect` and `fringe` refit. A callout's last point moves with the box edge it sits\n * on. A bubble's tip below the box comes down with it; a standard callout's tip and bend stay on\n * what they point at.\n */\nexport function grownFreeText(\n a: FreeTextAnnotation,\n grown: number,\n t: PageTransform\n): Partial<FreeTextAnnotation> {\n const css = t.toCssRect(freeTextBox(a))\n const box = t.fromCssRect({ ...css, height: css.height + grown })\n if (!hasCallout(a)) return withBox(a, box)\n const resized = resizedBox(a, box)\n if (!isBubble(a) || t.toCss(a.callout[0]).y <= css.top + css.height) return resized\n const last = a.callout.length - 1\n const down = (p: Point): Point => {\n const c = t.toCss(p)\n return t.fromCss({ x: c.x, y: c.y + grown })\n }\n return withBox(\n a,\n box,\n resized.callout!.map((p, i) => (i === last ? p : down(p)))\n )\n}\n\n/** `plaintext-only` where the browser has it, else `true` (paste and formatting are then guarded). */\nfunction makeEditable(field: HTMLElement): void {\n try {\n field.contentEditable = 'plaintext-only'\n } catch {\n // Older engines throw on the value.\n }\n if (field.contentEditable !== 'plaintext-only') field.contentEditable = 'true'\n}\n\n/** Inserts `text` at the caret, replacing any selected text, and leaves the caret after it. */\nfunction insertText(field: HTMLElement, text: string): void {\n const doc = field.ownerDocument\n const selection = doc.getSelection()\n const node = doc.createTextNode(text)\n if (!selection || selection.rangeCount === 0) {\n field.append(node)\n return\n }\n const range = selection.getRangeAt(0)\n if (!field.contains(range.commonAncestorContainer)) {\n field.append(node)\n return\n }\n range.deleteContents()\n range.insertNode(node)\n range.setStartAfter(node)\n range.collapse(true)\n selection.removeAllRanges()\n selection.addRange(range)\n}\n","// Renders one region of a page, in PDF user space, into a canvas of its own: the loupe's\n// magnified view. The viewport is the page's own at `scale`, shifted so the region's top-left\n// corner lands on the canvas origin, so the region fills the canvas exactly.\nimport type { InkDocument } from '../model/document'\nimport type { Rect } from '../model/geometry'\n\nconst isCancellation = (error: unknown): boolean =>\n (error as { name?: unknown } | null)?.name === 'RenderingCancelledException'\n\n/**\n * Draws `userRect` of `page` (0-based) into `canvas` at `scale` device pixels per user-space\n * unit (times `/UserUnit`, as PDF.js applies it), turned by `rotation`: the page's /Rotate plus\n * any view rotation, the page's own /Rotate when omitted. The canvas is resized to the region,\n * so a 50 pt square at scale 4 gives a 200 × 200 canvas. Like the page canvas, the background\n * is white and embedded annotation appearances are drawn.\n *\n * Rejects with `signal.reason` once `signal` aborts; an abort mid-render cancels it, leaving\n * the canvas partly drawn.\n *\n * @internal\n */\nexport async function renderRegion(\n doc: InkDocument,\n page: number,\n userRect: Rect,\n scale: number,\n canvas: HTMLCanvasElement,\n signal?: AbortSignal,\n rotation?: number\n): Promise<void> {\n signal?.throwIfAborted()\n const pdfPage = await doc._pdfjs.getPage(page)\n signal?.throwIfAborted()\n const turn = rotation ?? pdfPage.rotate\n const full = pdfPage.getViewport({ scale, rotation: turn })\n // The region's corners on the unshifted canvas, in device pixels.\n const [x1, y1] = full.convertToViewportPoint(userRect.x, userRect.y) as [number, number]\n const [x2, y2] = full.convertToViewportPoint(\n userRect.x + userRect.width,\n userRect.y + userRect.height\n ) as [number, number]\n const viewport = pdfPage.getViewport({\n scale,\n rotation: turn,\n offsetX: -Math.min(x1, x2),\n offsetY: -Math.min(y1, y2),\n })\n canvas.width = Math.max(1, Math.round(Math.abs(x2 - x1)))\n canvas.height = Math.max(1, Math.round(Math.abs(y2 - y1)))\n const task = pdfPage.render({\n canvas,\n viewport,\n background: '#ffffff',\n annotationMode: doc._pdfjs.module.AnnotationMode.ENABLE,\n })\n const cancel = (): void => task.cancel()\n signal?.addEventListener('abort', cancel, { once: true })\n try {\n await task.promise\n } catch (error) {\n if (signal?.aborted && isCancellation(error)) throw signal.reason\n throw error\n } finally {\n signal?.removeEventListener('abort', cancel)\n }\n // Finished just as the signal aborted: the caller has moved on.\n signal?.throwIfAborted()\n}\n","// The loupe's magnified view: one canvas per loupe, first in the loupe's own annotation\n// element, under the rim the overlay draws. It holds the page region under the loupe's centre,\n// `magnification` times smaller than the loupe, rendered at the zoom times the device pixel\n// ratio times the magnification, so it fills the element at full sharpness. Page content only:\n// session annotations under the loupe are not magnified.\n//\n// Inline styles are structural: the canvas fills the element (`position:absolute; left:0;\n// top:0; width:100%; height:100%`), is clipped to the inscribed circle (`clip-path`) and leaves\n// the pointer to the rim (`pointer-events:none`).\nimport { renderRegion } from '../pdfjs/render-region'\n\nimport { watchDevicePixelRatio, type DprWatch } from './dpr-watch'\n\nimport type { PageTransform } from './transform'\nimport type { LoupeAnnotation } from '../model/annotations/types'\nimport type { InkDocument } from '../model/document'\nimport type { Rect } from '../model/geometry'\n\n/** Pause after a move, resize or zoom before a loupe re-renders, in ms. */\nexport const LOUPE_RENDER_DELAY = 100\n\nexport interface LoupeLayerOptions {\n document: InkDocument\n /**\n * Fixed device pixel ratio. When omitted, `window.devicePixelRatio` is read at every render\n * and the loupes re-render when it changes (browser zoom, moving to another screen).\n */\n devicePixelRatio?: number\n}\n\nexport interface LoupeLayer {\n /**\n * Puts the loupe's canvas first in `el`, its annotation element, and brings it up to date\n * with `a` at `t`. The first render starts at once; later ones wait for a pause of\n * `LOUPE_RENDER_DELAY` ms in the changes, and a change aborts a render in flight. The last\n * bitmap stays, stretched with the element, until the next one lands.\n */\n attach(el: HTMLElement, a: LoupeAnnotation, t: PageTransform): void\n /** Forgets a loupe that is gone, cancelling its render. */\n drop(id: string): void\n destroy(): void\n}\n\n/** The page region a loupe shows: its rect shrunk by the magnification about its centre. */\nexport function loupeRegion(a: Pick<LoupeAnnotation, 'rect' | 'magnification'>): Rect {\n const { rect, magnification } = a\n const width = rect.width / magnification\n const height = rect.height / magnification\n return {\n x: rect.x + (rect.width - width) / 2,\n y: rect.y + (rect.height - height) / 2,\n width,\n height,\n }\n}\n\ninterface Lens {\n canvas: HTMLCanvasElement\n /** What the canvas shows or is about to: the last scheduled render's inputs. */\n key: string | undefined\n timer: ReturnType<typeof setTimeout> | undefined\n controller: AbortController | undefined\n /** The last `attach`, replayed when the device pixel ratio changes. */\n last: { el: HTMLElement; a: LoupeAnnotation; t: PageTransform } | undefined\n}\n\n/** Frees a canvas's bitmap now rather than at garbage collection (Safari caps the total). */\nfunction release(canvas: HTMLCanvasElement): void {\n canvas.width = 0\n canvas.height = 0\n canvas.remove()\n}\n\nexport function createLoupeLayer(opts: LoupeLayerOptions): LoupeLayer {\n const lenses = new Map<string, Lens>()\n let destroyed = false\n let dprWatch: DprWatch | undefined\n\n const dprOf = (el: HTMLElement): number => {\n if (opts.devicePixelRatio !== undefined) return opts.devicePixelRatio\n const ratio = el.ownerDocument.defaultView?.devicePixelRatio ?? 1\n return ratio > 0 ? ratio : 1\n }\n\n const stop = (lens: Lens): void => {\n clearTimeout(lens.timer)\n lens.timer = undefined\n lens.controller?.abort()\n lens.controller = undefined\n }\n\n async function render(\n lens: Lens,\n page: number,\n region: Rect,\n scale: number,\n rotation: number\n ): Promise<void> {\n const controller = new AbortController()\n lens.controller = controller\n const doc = lens.canvas.ownerDocument\n const next = doc.createElement('canvas')\n try {\n await renderRegion(\n opts.document,\n page,\n region,\n scale,\n next,\n controller.signal,\n rotation\n )\n if (controller.signal.aborted || destroyed) return\n lens.canvas.width = next.width\n lens.canvas.height = next.height\n lens.canvas.getContext('2d')?.drawImage(next, 0, 0)\n } catch {\n // Aborted for a newer render, or failed: the last bitmap stays. A failure has nowhere\n // useful to go; the page canvas reports the document's render failures.\n } finally {\n release(next)\n if (lens.controller === controller) lens.controller = undefined\n }\n }\n\n function lensFor(el: HTMLElement, id: string): Lens {\n const known = lenses.get(id)\n if (known) return known\n const canvas = el.ownerDocument.createElement('canvas')\n canvas.className = 'ink-loupe-lens'\n canvas.dataset.inkLoupe = ''\n canvas.setAttribute('aria-hidden', 'true')\n canvas.style.cssText =\n 'position:absolute;left:0;top:0;width:100%;height:100%;' +\n 'clip-path:circle(50%);pointer-events:none;'\n // Blank until the first render lands.\n canvas.width = 0\n canvas.height = 0\n const lens: Lens = {\n canvas,\n key: undefined,\n timer: undefined,\n controller: undefined,\n last: undefined,\n }\n lenses.set(id, lens)\n return lens\n }\n\n function attach(el: HTMLElement, a: LoupeAnnotation, t: PageTransform): void {\n if (destroyed) return\n const lens = lensFor(el, a.id)\n lens.last = { el, a, t }\n if (el.firstChild !== lens.canvas) el.prepend(lens.canvas)\n const region = loupeRegion(a)\n const dpr = dprOf(el)\n if (opts.devicePixelRatio === undefined) {\n dprWatch ??= watchDevicePixelRatio(\n el.ownerDocument.defaultView,\n () => dprOf(el),\n () => {\n for (const { last } of [...lenses.values()])\n if (last) attach(last.el, last.a, last.t)\n }\n )\n dprWatch.watch(dpr)\n }\n const scale = t.zoom * dpr * a.magnification\n const rotation = t.totalRotation\n const key = JSON.stringify([a.page, region, scale, rotation])\n if (key === lens.key) return\n const first = lens.key === undefined\n lens.key = key\n stop(lens)\n if (first) {\n void render(lens, a.page, region, scale, rotation)\n return\n }\n lens.timer = setTimeout(() => {\n lens.timer = undefined\n void render(lens, a.page, region, scale, rotation)\n }, LOUPE_RENDER_DELAY)\n }\n\n return {\n attach,\n drop(id) {\n const lens = lenses.get(id)\n if (!lens) return\n stop(lens)\n release(lens.canvas)\n lenses.delete(id)\n },\n destroy() {\n if (destroyed) return\n destroyed = true\n dprWatch?.destroy()\n for (const lens of lenses.values()) {\n stop(lens)\n release(lens.canvas)\n }\n lenses.clear()\n },\n }\n}\n","// The mask's dimming: one SVG per page, between the page content (canvas, text layer) and the\n// annotation overlay, holding one even-odd path: the whole page, minus the mask's shape. The\n// mask annotation's own element (drawn by the overlay) is the shape's outline and takes the\n// hits; this layer never does.\n//\n// Inline styles and attributes are structural: the SVG is `position:absolute; left:0; top:0;\n// pointer-events:none` at the page's CSS size, and the path's fill is the mask's colour at its\n// `dim`.\nimport type { PageTransform } from './transform'\nimport type { MaskAnnotation } from '../model/annotations/types'\n\nconst SVG = 'http://www.w3.org/2000/svg'\n\nconst fmt = (n: number): string => String(Math.round(n * 1000) / 1000)\n\n/**\n * The path data of a mask's dimming at `t`, in CSS pixels from the page's top-left corner: the\n * page rectangle, then the shape (the rectangle, or the ellipse inscribed in it) as a second\n * subpath that the even-odd rule cuts out. `t.toCssRect` turns the shape's box with the page,\n * so this holds at any /Rotate and view rotation.\n */\nexport function maskPath(\n a: Pick<MaskAnnotation, 'rect' | 'shape'>,\n t: Pick<PageTransform, 'toCssRect' | 'cssWidth' | 'cssHeight'>\n): string {\n const w = t.cssWidth\n const h = t.cssHeight\n const page = `M0 0L${fmt(w)} 0L${fmt(w)} ${fmt(h)}L0 ${fmt(h)}Z`\n const { left, top, width, height } = t.toCssRect(a.rect)\n if (a.shape === 'ellipse') {\n const rx = width / 2\n const ry = height / 2\n const cy = top + ry\n const arc = `A${fmt(rx)} ${fmt(ry)} 0 1 0`\n return `${page}M${fmt(left)} ${fmt(cy)}${arc} ${fmt(left + width)} ${fmt(cy)}${arc} ${fmt(left)} ${fmt(cy)}Z`\n }\n const right = left + width\n const bottom = top + height\n return `${page}M${fmt(left)} ${fmt(top)}L${fmt(right)} ${fmt(top)}L${fmt(right)} ${fmt(bottom)}L${fmt(left)} ${fmt(bottom)}Z`\n}\n\nexport interface MaskLayer {\n /** Draws `mask` at `t`, or removes the layer when there is none. */\n update(mask: MaskAnnotation | undefined, t: PageTransform): void\n destroy(): void\n}\n\n/** The page's mask layer: its SVG goes into `host` just before `before`, the annotation overlay. */\nexport function createMaskLayer(host: HTMLElement, before: Node): MaskLayer {\n let svg: SVGSVGElement | undefined\n let path: SVGPathElement | undefined\n\n return {\n update(mask, t) {\n if (!mask) {\n svg?.remove()\n svg = undefined\n path = undefined\n return\n }\n if (!svg || !path) {\n const doc = host.ownerDocument\n svg = doc.createElementNS(SVG, 'svg')\n svg.classList.add('ink-mask-layer')\n svg.dataset.inkMaskLayer = ''\n svg.setAttribute('aria-hidden', 'true')\n svg.style.cssText = 'position:absolute;left:0;top:0;pointer-events:none;'\n path = doc.createElementNS(SVG, 'path')\n path.setAttribute('fill-rule', 'evenodd')\n path.setAttribute('clip-rule', 'evenodd')\n path.setAttribute('stroke', 'none')\n svg.append(path)\n }\n if (svg.parentNode !== host || svg.nextSibling !== before)\n host.insertBefore(svg, before)\n svg.setAttribute('width', String(t.cssWidth))\n svg.setAttribute('height', String(t.cssHeight))\n svg.setAttribute('viewBox', `0 0 ${t.cssWidth} ${t.cssHeight}`)\n path.setAttribute('d', maskPath(mask, t))\n path.setAttribute('fill', mask.color)\n path.setAttribute('fill-opacity', String(mask.dim))\n },\n destroy() {\n svg?.remove()\n svg = undefined\n path = undefined\n },\n }\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// Edit handles (`.ink-handle[data-handle]`) are 8px `position:absolute;\n// pointer-events:auto` boxes on the element's corners or a line's ends, placed with\n// left/top; 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 { freeTextBox } from '../model/annotations/callout'\nimport {\n hasCallout,\n hasCornerHandles,\n hasRectGeometry,\n isTextMarkup,\n keepsAspect,\n resizedBox,\n resizedRect,\n translated,\n} from '../model/annotations/edit'\nimport { withoutReplies } from '../model/annotations/threads'\nimport {\n confidenceBucket,\n type Annotation,\n type MaskAnnotation,\n} from '../model/annotations/types'\n\nimport { canEditFreeText, editFreeTextIn, editorFor } from './freetext-editor'\nimport { createLoupeLayer } from './loupe-layer'\nimport { createMaskLayer } from './mask-layer'\nimport {\n annotationBox,\n freeTextLocalBox,\n hasComment,\n renderAnnotationContent,\n renderHitArea,\n syncHandles,\n type HandleSpec,\n} from './overlay-render'\n\nimport type { PageTransform } from './transform'\nimport type { AnnotationStore } from '../model/annotations/store'\nimport type { InkDocument } from '../model/document'\nimport type { Point } from '../model/geometry'\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 * The document the page belongs to. Loupes magnify its page content; without it they show\n * only their rim.\n */\n document?: InkDocument\n /** Fixed device pixel ratio for loupes; `window.devicePixelRatio` when omitted. */\n devicePixelRatio?: number\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/** A text position: a node and an offset in it. */\ninterface Caret {\n node: Node\n offset: number\n}\n\n/** Pointer travel, CSS px, within which a press on text markup is still a click. */\nconst CLICK_SLOP = 3\n/** Longest press, ms, that still counts as a click on text markup. */\nconst CLICK_MS = 500\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: 'Strikethrough',\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 stamp: 'Stamp',\n loupe: 'Loupe',\n mask: 'Mask',\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 : a.subject === 'Signature' && (a.type === 'ink' || a.type === 'stamp')\n ? 'Signature'\n : LABELS[a.type]\n const named = hasComment(a) ? `${base} with comment` : base\n return a.author ? `${named} by ${a.author}` : named\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 const masks = createMaskLayer(opts.host, root)\n const loupes = opts.document\n ? createLoupeLayer({\n document: opts.document,\n ...(opts.devicePixelRatio === undefined\n ? {}\n : { devicePixelRatio: opts.devicePixelRatio }),\n })\n : undefined\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 a && !a.locked && state === 'selected' && selectToolActive()\n ? handleSpec(node, a)\n : { kind: 'none' }\n )\n }\n\n /**\n * Line ends for a line, corners for what a corner drag resizes (a free text's on its text\n * box), plus the tip for a callout, else none.\n */\n function handleSpec(node: HTMLElement, a: Annotation): HandleSpec {\n const left = parseFloat(node.style.left) || 0\n const top = parseFloat(node.style.top) || 0\n if (a.type === 'line') {\n const local = (p: Point): Point => {\n const c = transform.toCss(p)\n return { x: c.x - left, y: c.y - top }\n }\n return { kind: 'ends', start: local(a.start), end: local(a.end) }\n }\n if (!hasCornerHandles(a)) return { kind: 'none' }\n const corners =\n a.type === 'freetext'\n ? { kind: 'corners' as const, ...freeTextLocalBox(a, transform) }\n : {\n kind: 'corners' as const,\n width: parseFloat(node.style.width) || 0,\n height: parseFloat(node.style.height) || 0,\n }\n if (!hasCallout(a)) return corners\n const tip = transform.toCss(a.callout[0])\n return { ...corners, tail: { x: tip.x - left, y: tip.y - top } }\n }\n\n /**\n * True while the tool controller marks the tool root (an ancestor) with a select tool,\n * `data-ink-tool=\"select\"` or `\"select-text\"`.\n */\n function selectToolActive(): boolean {\n const tool = opts.host.closest('[data-ink-tool]')?.getAttribute('data-ink-tool')\n return tool === 'select' || tool === 'select-text'\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 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 loupes?.drop(a.id)\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 if (a.type === 'loupe') loupes?.attach(node, a, transform)\n drawn.set(a.id, { a, t: transform })\n }\n\n /**\n * Opens the in-place editor on a free-text box this overlay draws. False when it cannot be\n * edited: not free text, locked, embedded or host-rendered.\n */\n function edit(id: string): boolean {\n const a = store.get(id)\n const node = elements.get(id)\n if (!node || !canEditFreeText(a, node) || opts.isCustom?.(a) === true) return false\n if (editorFor(node)) return true\n return editFreeTextIn(store, node, id, transform) !== undefined\n }\n\n /** Commits every open editor: before a redraw that would lose it, or teardown. */\n function closeEditors(): void {\n for (const node of elements.values()) editorFor(node)?.close(true)\n }\n\n function activate(id: string): void {\n store.select([id])\n opts.onActivate?.(id)\n }\n\n /** The live press on text markup, until its release or cancel. */\n let markupPress: (() => void) | undefined\n\n /**\n * A press on text markup does nothing yet. A release within `CLICK_SLOP` px and `CLICK_MS`\n * of it selects and activates the markup (with `Shift`, toggles it in the selection); a\n * longer drag selects the text under it instead, from the press point to the pointer, as a\n * drag on the bare text would. Rectangle select claims markup presses before they get here.\n */\n function pressMarkup(e: PointerEvent, id: string): void {\n // The browser's own selection would start inside the overlay, not the text: drive it here.\n e.preventDefault()\n markupPress?.()\n const view = doc.defaultView\n if (!view) return\n const { clientX: x0, clientY: y0, pointerId, timeStamp: t0 } = e\n let anchor: Caret | undefined\n let dragging = false\n const mine = (ev: PointerEvent): boolean => ev.pointerId === pointerId\n const onMove = (ev: PointerEvent): void => {\n if (!mine(ev)) return\n if (ev.buttons === 0) return end()\n if (!dragging && Math.hypot(ev.clientX - x0, ev.clientY - y0) <= CLICK_SLOP) return\n dragging = true\n anchor ??= caretAt(x0, y0)\n const focus = caretAt(ev.clientX, ev.clientY)\n if (anchor && focus)\n doc\n .getSelection()\n ?.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset)\n }\n const onUp = (ev: PointerEvent): void => {\n if (!mine(ev) || ev.button !== 0) return\n end()\n if (\n !dragging &&\n !destroyed &&\n Math.hypot(ev.clientX - x0, ev.clientY - y0) <= CLICK_SLOP &&\n ev.timeStamp - t0 <= CLICK_MS &&\n store.get(id)\n ) {\n if (!(e.shiftKey || ev.shiftKey)) return activate(id)\n // Shift-click adds the markup to the selection, or takes it out.\n const selected = store.selection.get()\n store.select(\n selected.includes(id) ? selected.filter((s) => s !== id) : [...selected, id]\n )\n }\n }\n const onCancel = (ev: PointerEvent): void => {\n if (mine(ev)) end()\n }\n const end = (): void => {\n view.removeEventListener('pointermove', onMove, true)\n view.removeEventListener('pointerup', onUp, true)\n view.removeEventListener('pointercancel', onCancel, true)\n if (markupPress === end) markupPress = undefined\n }\n // Capture on the window: the release still arrives when a tool captured the pointer or a\n // handler on the way stops it.\n view.addEventListener('pointermove', onMove, true)\n view.addEventListener('pointerup', onUp, true)\n view.addEventListener('pointercancel', onCancel, true)\n markupPress = end\n }\n\n /**\n * The text position under a client point on this page's text layer, looked up with the\n * overlay hidden so the markup on top does not answer instead.\n */\n function caretAt(x: number, y: number): Caret | undefined {\n const visibility = root.style.visibility\n root.style.visibility = 'hidden'\n let caret: Caret | undefined\n try {\n if (typeof doc.caretPositionFromPoint === 'function') {\n const p = doc.caretPositionFromPoint(x, y)\n if (p) caret = { node: p.offsetNode, offset: p.offset }\n } else if (typeof doc.caretRangeFromPoint === 'function') {\n const r = doc.caretRangeFromPoint(x, y)\n if (r) caret = { node: r.startContainer, offset: r.startOffset }\n }\n } finally {\n root.style.visibility = visibility\n }\n const layer = opts.host.querySelector('[data-ink-text-layer]')\n return caret && layer?.contains(caret.node) ? caret : undefined\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. A free text resizes its text\n * box, as its corner handles do. 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 (a.type === 'freetext')\n store.update(id, resizedBox(a, resizedRect(freeTextBox(a), step.x, -step.y)))\n else if (hasRectGeometry(a))\n store.update(id, { rect: resizedRect(a.rect, step.x, -step.y, keepsAspect(a)) })\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 // Enter on a free-text box edits it in place.\n if (e.key === 'Enter' && edit(id)) store.select([id])\n else 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 // Presses in a free-text editor place the caret: they are the editor's.\n if (e.target instanceof Element && e.target.closest('[data-ink-editor]')) 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 // Text markup waits for the release: a drag across it is a text selection.\n const a = store.get(id)\n if (a && isTextMarkup(a)) {\n pressMarkup(e, id)\n return\n }\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('dblclick', (e) => {\n if (e.target instanceof Element && e.target.closest('[data-ink-editor]')) return\n if (edit(id)) e.preventDefault()\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 // Replies show in the thread popover only: no element, hit area or tab stop here.\n const current = withoutReplies(store.list.get())\n .filter((a) => a.page === page)\n .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 // The box is gone (removed elsewhere, or undone): its edit goes with it.\n editorFor(node)?.close(false)\n node.remove()\n loupes?.drop(id)\n elements.delete(id)\n drawn.delete(id)\n hovered.delete(id)\n }\n\n masks.update(\n current.find((a): a is MaskAnnotation => a.type === 'mask'),\n transform\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 // An open editor owns the element's content and height until it closes; the element\n // still follows the page.\n if (editorFor(node)) {\n const height = node.style.height\n applyGeometry(node, a)\n node.style.height = height\n } else {\n applyGeometry(node, a)\n applyContent(node, a)\n }\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 // An editor is laid out for one zoom and rotation: a change to either commits it first\n // (focus moves to its box). Any other relayout leaves it open.\n if (next.zoom !== transform.zoom || next.rotation !== transform.rotation)\n closeEditors()\n transform = next\n render()\n },\n elementFor: (id) => elements.get(id),\n destroy() {\n if (destroyed) return\n closeEditors()\n destroyed = true\n markupPress?.()\n offList()\n offSelection()\n toolObserver?.disconnect()\n loupes?.destroy()\n masks.destroy()\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 document,\n ...(opts.devicePixelRatio === undefined\n ? {}\n : { devicePixelRatio: opts.devicePixelRatio }),\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","// Per-tool options (the shape kind, the highlight kind, the chosen signature…). They persist\n// per tool for the viewer's life: the engine keeps one registry across rebuilds, so reopening a\n// tool, or rebuilding the viewport, keeps its last options.\nimport { readonly, writable, type Readable, type Writable } from '../../model/readable'\n\nimport type { Tool, ToolId } from './controller'\n\nexport interface ToolOptions {\n /** The tool's current options. Throws a `RangeError` for an id no tool registered. */\n readable(id: ToolId): Readable<object>\n get(id: ToolId): object\n /** Merges `patch` into the tool's options. */\n merge(id: ToolId, patch: object): void\n /** Registers tools not seen yet, seeded from their `defaultOptions`; known ids keep theirs. */\n register(tools: readonly Tool[]): void\n}\n\nexport function createToolOptions(tools: readonly Tool[] = []): ToolOptions {\n const byId = new Map<ToolId, Writable<object>>()\n const views = new Map<ToolId, Readable<object>>()\n\n const entry = (id: ToolId): Writable<object> => {\n const w = byId.get(id)\n if (!w) throw new RangeError(`Unknown tool ${id}`)\n return w\n }\n\n function register(list: readonly Tool[]): void {\n for (const t of list) {\n if (byId.has(t.id)) continue\n const w = writable<object>({ ...(t.defaultOptions ?? {}) })\n byId.set(t.id, w)\n views.set(t.id, readonly(w))\n }\n }\n register(tools)\n\n return {\n readable(id) {\n entry(id)\n return views.get(id) as Readable<object>\n },\n get: (id) => entry(id).get(),\n merge(id, patch) {\n const w = entry(id)\n w.set({ ...w.get(), ...patch })\n },\n register,\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 other than text markup (so a creation tool never starts a drag from\n// one), but a capture listener on the root runs before that, so the controller can pass the\n// pressed annotation's 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 {\n createToolStyle,\n type StyleGroup,\n type ToolStyle,\n} from '../../model/annotations/tool-style'\nimport { readonly, writable, type Readable } from '../../model/readable'\nimport { canEditFreeText, editFreeTextIn } from '../freetext-editor'\n\nimport { createToolOptions, type ToolOptions } from './options'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Point } from '../../model/geometry'\nimport type { SignatureLibrary } from '../../model/signatures'\nimport type { SelectionQuads } from '../selection'\nimport type { Viewport, ViewportHit } from '../viewport'\n\nexport type BuiltinToolId =\n | 'select-text'\n | 'select'\n | 'highlight'\n | 'redact-area'\n | 'note'\n | 'shape'\n | 'freetext'\n | 'draw'\n | 'sketch'\n | 'signature'\n/** A built-in tool's id, or any id a host registers its own tool under. */\nexport type ToolId = BuiltinToolId | (string & {})\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 /** The style each group creates with, shared with the style controls. */\n toolStyle: ToolStyle\n /** The active tool's current options. */\n options<O extends object>(): O\n /**\n * Groups a gesture's changes into one undo step (a group move). Without it each change is\n * its own step.\n */\n history?: { batch(fn: () => void): void }\n /** The signature templates the `signature` tool places. Without it, it places nothing. */\n signatures?: SignatureLibrary | undefined\n}\n\nexport interface Tool<O extends object = object> {\n id: ToolId\n cursor: string\n /** Style group the tool creates into; select tools have none. */\n styleGroup?: StyleGroup\n /** Option defaults. Options persist per tool for the viewer's life. */\n defaultOptions?: O\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 (text markup\n * on a click, other types on the press), so tools other than the select tools should ignore\n * such presses. Calling `e.stopPropagation()` here keeps the overlay from handling it.\n * Return true when the press starts a gesture: the controller then captures the pointer\n * 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 /** Switches to the tool, first merging `options` into its options. */\n set(id: ToolId, options?: object): void\n /** Merges `patch` into a tool's options without switching to it. */\n setOptions(id: ToolId, patch: object): void\n options(id: ToolId): Readable<object>\n destroy(): void\n}\n\nexport interface ToolControllerOptions {\n /** The controller adds `options`; `toolStyle` defaults to one of the controller's own. */\n ctx: Omit<ToolContext, 'toolStyle' | 'options'> & { toolStyle?: ToolStyle }\n /** Default `'select-text'`. */\n initial?: ToolId\n tools: Tool[]\n /**\n * Where options live. Pass the same registry to each controller that replaces another (a\n * rebuild) so options persist; by default the controller keeps its own.\n */\n options?: ToolOptions\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 byId = new Map(opts.tools.map((t) => [t.id, t]))\n const active = writable<ToolId>(opts.initial ?? 'select-text')\n let current: Tool | undefined\n const registry = opts.options ?? createToolOptions()\n registry.register(opts.tools)\n const ctx: ToolContext = {\n ...opts.ctx,\n // Read through, as a spread copies a getter's value once: the host's library may change.\n get signatures() {\n return opts.ctx.signatures\n },\n toolStyle:\n opts.ctx.toolStyle ??\n createToolStyle({\n store: opts.ctx.store,\n history: opts.ctx.history ?? { batch: (fn) => fn() },\n activeGroup: () => current?.styleGroup,\n active,\n }),\n // `current` is the activating tool already, so `activate` reads its own options.\n options: <O extends object>() => registry.get(current?.id ?? active.get()) as O,\n }\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)) return\n current?.onKeyDown?.(e)\n // Enter that no tool took edits the one selected text box, wherever focus is in the viewport.\n if (isViewportEnter(e, ctx.root)) editSelectedText(e)\n }\n function editSelectedText(e: KeyboardEvent): void {\n const selected = ctx.store.selection.get()\n if (selected.length !== 1) return\n const id = selected[0]!\n const a = ctx.store.get(id)\n const el = ctx.root.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(id)}\"]`\n )\n if (!canEditFreeText(a, el) || !el) return\n e.preventDefault()\n editFreeTextIn(ctx.store, el, id, ctx.viewport.transformFor(a.page))\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, options?: object): void {\n const next = byId.get(id)\n if (!next) throw new RangeError(`Unknown tool ${id}`)\n if (options) registry.merge(id, options)\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 ?? 'select-text')\n\n return {\n active: readonly(active),\n set,\n setOptions(id, patch) {\n if (!byId.has(id)) throw new RangeError(`Unknown tool ${id}`)\n registry.merge(id, patch)\n },\n options(id) {\n if (!byId.has(id)) throw new RangeError(`Unknown tool ${id}`)\n return registry.readable(id)\n },\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 // A free-text editor's presses and keys are its own, too.\n if (target.closest('[data-ink-editor]')) return true\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","// Freehand stroke capture, shared by `draw` and `sketch`. A press-drag-release is one stroke:\n// samples come from coalesced pointer events where the browser has them, with pen and touch\n// pressure, and a live preview paints the stroke as the ink it will become. The tool decides\n// what a finished stroke writes.\nimport { outlinePath, strokeOutline } from '../ink-stroke'\n\nimport {\n clampedCssIn,\n type PageHit,\n type Tool,\n type ToolContext,\n type ToolId,\n} from './controller'\n\nimport type { AnnotationInput } from '../../model/annotations/types'\nimport type { Point } from '../../model/geometry'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** A finished stroke, in user space. */\nexport interface FreehandStroke {\n page: number\n points: Point[]\n /**\n * One value per point, 0 to 1, from a pen or touch that reports real pressure; undefined for\n * a mouse, or a device that only ever reports 0 or 0.5.\n */\n pressure: number[] | undefined\n /** When the press happened (`Date.now()`). */\n startedAt: number\n}\n\nexport interface FreehandOptions {\n id: ToolId\n /** Writes a finished stroke. */\n commit(ctx: ToolContext, stroke: FreehandStroke): void\n /** Escape, or the tool deactivating. */\n end?(): void\n /** The tool deactivating (a tool switch, or the controller's destroy). */\n deactivate?(): void\n}\n\n/** A stroke being drawn: its page, and each sample in CSS px (host-relative) and user space. */\ninterface Stroke {\n from: PageHit\n css: Point[]\n user: Point[]\n /** One value per sample for pen and touch, else undefined. */\n pressure: number[] | undefined\n startedAt: number\n}\n\n/** Pressure from a device that reports it, else undefined. Shared with the signature pad. */\nexport function pressureOf(e: PointerEvent): number | undefined {\n if (e.pointerType !== 'pen' && e.pointerType !== 'touch') return undefined\n // Two decimals: the device's float32 noise has no place in the saved file.\n return Math.round(Math.min(Math.max(e.pressure, 0), 1) * 100) / 100\n}\n\n/** True when the samples carry real pressure: not all 0 or 0.5, the values of a device with none. */\nexport function reportsPressure(samples: readonly number[]): boolean {\n return samples.some((p) => p !== 0 && p !== 0.5)\n}\n\n/**\n * A tool in the `ink` style group that captures freehand strokes and previews them in\n * `.ink-draft[data-ink-draft=<id>]`.\n */\nexport function freehandTool(opts: FreehandOptions): Tool {\n let ctx: ToolContext | undefined\n let stroke: Stroke | undefined\n let draft: HTMLElement | undefined\n\n const clear = (): void => {\n draft?.remove()\n draft = undefined\n stroke = undefined\n }\n\n /** Adds a sample. A release reports 0 pressure, so it repeats the last sample's instead. */\n const sample = (s: Stroke, e: PointerEvent, release = false): void => {\n const css = clampedCssIn(s.from.host, e)\n s.css.push(css)\n s.user.push(s.from.transform.fromCss(css))\n const p = release ? s.pressure?.[s.pressure.length - 1] : pressureOf(e)\n if (p !== undefined) (s.pressure ??= []).push(p)\n }\n\n const paint = (c: ToolContext, s: Stroke): void => {\n const host = s.from.host\n const doc = host.ownerDocument\n if (!draft) {\n draft = doc.createElement('div')\n draft.className = 'ink-draft'\n draft.dataset.inkDraft = opts.id\n draft.style.position = 'absolute'\n draft.style.pointerEvents = 'none'\n draft.style.left = '0'\n draft.style.top = '0'\n host.append(draft)\n }\n draft.style.width = `${host.clientWidth}px`\n draft.style.height = `${host.clientHeight}px`\n const blank: AnnotationInput & { type: 'ink' } = {\n type: 'ink',\n page: s.from.page,\n inklist: [[]],\n }\n const style = c.toolStyle.resolve('ink', blank)\n const path = doc.createElementNS(SVG_NS, 'path')\n path.setAttribute(\n 'd',\n outlinePath(\n strokeOutline(s.css, s.pressure, s.from.transform.toCssLength(style.width ?? 2))\n )\n )\n path.setAttribute('fill', style.color ?? '#000000')\n if (style.opacity !== undefined) path.setAttribute('opacity', String(style.opacity))\n const svg = doc.createElementNS(SVG_NS, 'svg')\n svg.setAttribute('width', String(host.clientWidth))\n svg.setAttribute('height', String(host.clientHeight))\n svg.style.overflow = 'visible'\n svg.append(path)\n draft.replaceChildren(svg)\n }\n\n return {\n id: opts.id,\n cursor: 'crosshair',\n styleGroup: 'ink',\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n opts.end?.()\n opts.deactivate?.()\n ctx = undefined\n },\n onPointerDown(e, hit) {\n if (!hit) return\n stroke = {\n from: hit,\n css: [],\n user: [],\n pressure: undefined,\n startedAt: Date.now(),\n }\n sample(stroke, e)\n // Drawing over an annotation draws; it neither selects it nor starts a text selection.\n e.stopPropagation()\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!ctx || !stroke) return\n // No button down: the release was missed, so drop the stroke. A host scrolled out of the\n // mounted range is gone with it.\n if (e.buttons === 0 || !stroke.from.host.isConnected) {\n clear()\n return\n }\n const coalesced = e.getCoalescedEvents?.() ?? []\n for (const ev of coalesced.length > 0 ? coalesced : [e]) sample(stroke, ev)\n paint(ctx, stroke)\n },\n onPointerCancel() {\n clear()\n },\n onPointerUp(e) {\n if (!ctx || !stroke) return\n const s = stroke\n if (!s.from.host.isConnected) {\n clear()\n return\n }\n const last = s.css[s.css.length - 1]!\n const end = clampedCssIn(s.from.host, e)\n if (end.x !== last.x || end.y !== last.y) sample(s, e, true)\n clear()\n opts.commit(ctx, {\n page: s.from.page,\n points: s.user,\n pressure: s.pressure && reportsPressure(s.pressure) ? s.pressure : undefined,\n startedAt: s.startedAt,\n })\n },\n onKeyDown(e) {\n if (e.key !== 'Escape') return\n // Drops a stroke in progress too, so the release that follows commits nothing.\n clear()\n opts.end?.()\n },\n }\n}\n","// Freehand ink. A press-drag-release is one stroke; strokes that start within JOIN_GAP_MS of\n// the last one join its annotation, so a handwritten word stays one object. Each stroke is its\n// own undo step: the first is an `add`, the rest are `update`s that append to `inklist`.\n// Switching tools or pressing Escape ends the annotation. Pen and touch report pressure;\n// a mouse, or a device that always reports 0 or 0.5, leaves it out.\nimport { deriveRect } from '../../model/annotations/store'\nimport { JOIN_GAP_MS } from '../ink-stroke'\n\nimport { freehandTool } from './freehand'\n\nimport type { Tool, ToolContext } from './controller'\nimport type { InkAnnotation } from '../../model/annotations/types'\nimport type { Point } from '../../model/geometry'\n\n/** The annotation later strokes join, until the gap passes or something ends it. */\ninterface Session {\n id: string\n page: number\n endedAt: number\n}\n\nexport function drawTool(): Tool {\n let session: Session | undefined\n\n const join = (\n c: ToolContext,\n ink: InkAnnotation,\n points: Point[],\n pressure: number[] | undefined\n ): void => {\n const inklist = [...ink.inklist, points]\n // A stroke without pressure takes 0.5 throughout, which draws as no pressure does.\n const even = (p: Point[]): number[] => p.map(() => 0.5)\n const next =\n ink.pressure || pressure\n ? [...(ink.pressure ?? ink.inklist.map(even)), pressure ?? even(points)]\n : undefined\n c.store.update(ink.id, {\n inklist,\n pressure: next,\n rect: deriveRect({ type: 'ink', page: ink.page, inklist, width: ink.width }),\n })\n }\n\n return freehandTool({\n id: 'draw',\n end() {\n session = undefined\n },\n /** Appends the stroke to the live session's annotation, else starts a new one. */\n commit(c, s) {\n // The gap runs from the last stroke's release to this one's press. Under a host that\n // applies changes later, the last stroke may be proposed but not yet applied.\n const joined = session\n const current =\n joined && joined.page === s.page && s.startedAt - joined.endedAt <= JOIN_GAP_MS\n ? (c.store._getProposed(joined.id) ?? c.store.get(joined.id))\n : undefined\n if (current?.type === 'ink' && !current.locked) {\n join(c, current, s.points, s.pressure)\n session = { id: current.id, page: current.page, endedAt: Date.now() }\n return\n }\n const added = c.store.add(\n c.toolStyle.resolve('ink', {\n type: 'ink',\n page: s.page,\n inklist: [s.points],\n ...(s.pressure ? { pressure: [s.pressure] } : {}),\n })\n )\n session = { id: added.id, page: added.page, endedAt: Date.now() }\n },\n })\n}\n","// A click places a text box with its top-left corner at the press, a drag sizes one, and Enter\n// on the viewport places one at the centre of the current page. Each new box opens straight\n// into the in-place editor, and joins the store, selected, once it has text. The live draft is\n// `.ink-draft[data-ink-draft='freetext']`, `position:absolute; pointer-events:none`: geometry\n// only, the look is the theme's.\nimport { closedEditor, editFreeText, type FreeTextEditor } from '../freetext-editor'\nimport { renderAnnotationContent } from '../overlay-render'\n\nimport {\n clampedCssIn,\n isViewportEnter,\n type PageHit,\n type Tool,\n type ToolContext,\n} from './controller'\n\nimport type { AnnotationInput } from '../../model/annotations/types'\nimport type { CssRect } from '../transform'\n\ntype FreeTextInput = Extract<AnnotationInput, { type: 'freetext' }>\n\n/** Width of a box placed with a click or Enter, user-space points. */\nexport const DEFAULT_FREETEXT_WIDTH = 144\n\n/** Line height as a multiple of the font size, as the theme sets it. */\nconst LINE_HEIGHT = 1.2\n\n/** Font size a box gets when neither the text group nor the input sets one, points. */\nconst FONT_SIZE = 12\n\n/** Smallest drag, in CSS px on each axis, that sizes a box rather than counting as a click. */\nconst MIN_CSS = 3\n\nexport function freetextTool(): Tool {\n let ctx: ToolContext | undefined\n let start: PageHit | undefined\n let draft: HTMLElement | undefined\n\n const clear = (): void => {\n draft?.remove()\n draft = undefined\n start = undefined\n }\n\n /** The new box being typed into: it joins the store on its first non-empty commit. */\n let pending: FreeTextEditor | undefined\n\n /**\n * Opens an editor on a new box on `page` over `css` (the page host's CSS px), or, without a\n * box, one line high and `DEFAULT_FREETEXT_WIDTH` wide with its top-left at `at` (or centred\n * on it). The box is a stand-in element until the first commit with text, which adds and\n * selects it: creating and typing are one change and one undo step, and an empty box never\n * reaches the store.\n */\n const place = (\n c: ToolContext,\n page: number,\n css: CssRect | { at: { x: number; y: number }; centred: boolean }\n ): void => {\n const host = c.viewport.hostFor(page)\n if (!host) return\n pending?.close(true)\n const t = c.viewport.transformFor(page)\n const blank: FreeTextInput = { type: 'freetext', page, contents: '' }\n const input = c.toolStyle.resolve('text', blank)\n let box: CssRect\n if ('at' in css) {\n const size = input.defaultStyle?.fontSize ?? FONT_SIZE\n const border = input.width ?? 0\n const width = t.toCssLength(DEFAULT_FREETEXT_WIDTH)\n const height = t.toCssLength(size * LINE_HEIGHT + border * 2)\n box = css.centred\n ? { left: css.at.x - width / 2, top: css.at.y - height / 2, width, height }\n : { left: css.at.x, top: css.at.y, width, height }\n } else {\n box = css\n }\n const draftBox = c.store.completeInput({ ...input, rect: t.fromCssRect(box) })\n if (draftBox.type !== 'freetext') return\n const doc = host.ownerDocument\n // Laid out as the overlay lays out an annotation, stacked above the overlay (the theme\n // gives it z-index 1) so existing annotations under the new box neither cover its editor\n // nor take its presses.\n const el = doc.createElement('div')\n el.className = 'ink-annotation'\n el.dataset.inkPending = ''\n el.dataset.type = 'freetext'\n el.tabIndex = -1\n el.style.cssText = `position:absolute;left:${box.left}px;top:${box.top}px;width:${box.width}px;height:${box.height}px;pointer-events:none;z-index:2;`\n host.append(el)\n renderAnnotationContent(el, draftBox, t)\n\n // A new zoom or rotation commits the box as it stands, as does its page unmounting.\n const view = [\n ...[c.viewport.scale, c.viewport.rotation].map((r) =>\n r.subscribe(() => editor.close(true))\n ),\n c.viewport.mounted.subscribe((pages) => {\n if (!pages.includes(page)) editor.close(true)\n }),\n ]\n const done = (): void => {\n view.forEach((stop) => stop())\n el.remove()\n if (pending === editor) pending = undefined\n }\n /** After the stand-in goes: focus the new box, else the viewport, never <body>. */\n const refocus = (id?: string): void => {\n // Focus that already moved on (a click on a control) stays there.\n const active = doc.activeElement\n if (active && active !== doc.body && active !== el) return\n const drawn =\n id === undefined\n ? null\n : c.root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`)\n if (drawn) drawn.focus({ preventScroll: true })\n else {\n if (!c.root.hasAttribute('tabindex')) c.root.tabIndex = -1\n c.root.focus({ preventScroll: true })\n }\n }\n const editor = editFreeText(el, draftBox, {\n transform: t,\n commit(contents, rect) {\n done()\n if (contents.trim() === '') return refocus()\n const created = c.store.add({ ...input, id: draftBox.id, contents, rect })\n c.store.select([created.id])\n refocus(created.id)\n },\n cancel() {\n done()\n refocus()\n },\n })\n pending = editor\n }\n\n const paint = (from: PageHit, e: PointerEvent): void => {\n const css = clampedCssIn(from.host, e)\n if (!draft) {\n draft = from.host.ownerDocument.createElement('div')\n draft.className = 'ink-draft'\n draft.dataset.inkDraft = 'freetext'\n draft.style.position = 'absolute'\n draft.style.pointerEvents = 'none'\n from.host.append(draft)\n }\n draft.style.left = `${Math.min(from.css.x, css.x)}px`\n draft.style.top = `${Math.min(from.css.y, css.y)}px`\n draft.style.width = `${Math.abs(css.x - from.css.x)}px`\n draft.style.height = `${Math.abs(css.y - from.css.y)}px`\n }\n\n return {\n id: 'freetext',\n cursor: 'text',\n styleGroup: 'text',\n defaultOptions: {},\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n pending?.close(true)\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n // A press that ended an edit only ends it.\n if (!hit || annotationId !== undefined || closedEditor(e)) return\n start = hit\n // Keeps the press from starting a text selection or taking focus from the editor to be.\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!start) return\n if (e.buttons === 0 || !start.host.isConnected) {\n clear()\n return\n }\n paint(start, e)\n },\n onPointerCancel() {\n clear()\n },\n onPointerUp(e) {\n const from = start\n clear()\n if (!ctx || !from || !from.host.isConnected) return\n const css = clampedCssIn(from.host, e)\n const dx = Math.abs(css.x - from.css.x)\n const dy = Math.abs(css.y - from.css.y)\n if (dx >= MIN_CSS && dy >= MIN_CSS) {\n place(ctx, from.page, {\n left: Math.min(from.css.x, css.x),\n top: Math.min(from.css.y, css.y),\n width: dx,\n height: dy,\n })\n } else {\n place(ctx, from.page, { at: from.css, centred: false })\n }\n },\n onKeyDown(e) {\n if (!ctx || !isViewportEnter(e, ctx.root)) return\n e.preventDefault()\n const page = ctx.viewport.currentPage.get()\n const t = ctx.viewport.transformFor(page)\n const { box } = t.page\n const middle = t.toCss({ x: box.x + box.width / 2, y: box.y + box.height / 2 })\n place(ctx, page, { at: middle, centred: true })\n },\n }\n}\n","import { isViewportEnter, type Tool, type ToolContext } from './controller'\n\nimport type { TextMarkupAnnotation } from '../../model/annotations/types'\n\nexport type MarkupKind = TextMarkupAnnotation['type']\n\n/** The text markup kinds, in menu order. */\nexport const MARKUP_KINDS: readonly MarkupKind[] = [\n 'highlight',\n 'underline',\n 'strikeout',\n 'squiggly',\n]\n\nexport interface HighlightOptions {\n /** Which text markup the tool makes. */\n kind: MarkupKind\n}\n\nexport const DEFAULT_HIGHLIGHT_OPTIONS: Readonly<HighlightOptions> = { kind: 'highlight' }\n\n/**\n * Turns the text selection into one markup of the chosen kind per page when the pointer is\n * released, or on Enter in the viewport (a keyboard selection), and selects what it made.\n * Without a selection both do nothing. The markup's `contents` is left for a comment: hosts\n * read the marked text with `doc.text(page)`.\n */\nexport function highlightTool(): Tool<HighlightOptions> {\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 const { kind } = { ...DEFAULT_HIGHLIGHT_OPTIONS, ...ctx.options<HighlightOptions>() }\n const ids: string[] = []\n for (const s of selections) {\n const a = ctx.store.add(\n ctx.toolStyle.resolve('markup', { type: kind, page: s.page, quads: s.quads })\n )\n ids.push(a.id)\n }\n ctx.clearSelection()\n ctx.store.select(ids)\n return true\n }\n return {\n id: 'highlight',\n cursor: 'text',\n styleGroup: 'markup',\n defaultOptions: { ...DEFAULT_HIGHLIGHT_OPTIONS },\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 icon: 'Comment',\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 { isTextMarkup } from '../../model/annotations/edit'\n\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(\n ctx.toolStyle.resolve('redact', { type: 'redact', page: s.page, quads: s.quads })\n )\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 styleGroup: 'redact',\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n if (!hit) return\n if (annotationId !== undefined) {\n // Text markup would let a drag through to text selection, which the next click here\n // turns into a text redaction. Claim the press instead, as rectangle select does: a\n // drag from markup draws an area, and a click redacts the live selection.\n const a = ctx?.store.get(annotationId)\n if (!a || !isTextMarkup(a)) return\n e.stopPropagation()\n }\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(\n ctx.toolStyle.resolve('redact', { type: 'redact', page: start.page, rect })\n )\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","// Move, resize and marquee for the two select tools.\n//\n// The marquee is `position:absolute; pointer-events:none` with left/top/width/height from the\n// drag. Moving annotations are shown with a temporary `transform: translate(...)` on their\n// overlay elements; a resizing one with `translate(...) scale(...)` from a `0 0` origin. A line\n// whose end is being dragged is hidden (`visibility`) and drawn into a temporary\n// `pointer-events:none` preview element beside it. All of these are geometry; their look comes\n// from the theme.\n//\n// Resize: a press on one of the overlay's corner handles (`[data-handle=nw|ne|sw|se]`, drawn\n// on a selected, unlocked annotation) drags that CSS corner while the opposite one stays put.\n// The new box is converted back to user space once, on release, and the annotation's rect and\n// points are scaled onto it in one `store.update`. Neither side goes below 1 pt. `Shift`, or\n// a type that always keeps its aspect (`keepsAspect`), keeps the box's aspect ratio. A free\n// text's corners are its text box's: the box takes the new size and `rect` and `fringe` are\n// refit around it (`resizedBox`). One with a fringe or a callout is shown resizing in a\n// preview element, as a line end is, since scaling its element would stretch the callout too.\n//\n// Line ends: a press on `[data-handle=start|end]` drags that end; the other stays put. A\n// callout's tip (`[data-handle=callout]`) drags the same way and moves `callout[0]` only, the\n// text box staying where it is (`movedTip`).\n//\n// Move: dragging a pressed annotation moves it, or, when it belongs to the selection, every\n// selected unlocked annotation, in one history step.\n//\n// Under select-text, text markup is left to the overlay: a drag across it selects text, a\n// click selects it. Rectangle select (`marquee`) handles markup like any other annotation.\nimport { freeTextBox } from '../../model/annotations/callout'\nimport {\n MIN_SIZE,\n hasCallout,\n hasCornerHandles,\n hasRectGeometry,\n isTextMarkup,\n keepsAspect,\n movedEndpoint,\n movedTip,\n resizedBox,\n scaled,\n translated,\n} from '../../model/annotations/edit'\nimport { withoutReplies } from '../../model/annotations/threads'\nimport { rectFromPoints, rectsIntersect } from '../../model/geometry'\nimport { annotationBox, renderAnnotationContent } from '../overlay-render'\n\nimport { cssIn, type PageHit, type ToolContext } from './controller'\n\nimport type { Annotation } from '../../model/annotations/types'\nimport type { Point, Rect } from '../../model/geometry'\nimport type { CssRect, PageTransform } from '../transform'\n\ntype Corner = 'nw' | 'ne' | 'sw' | 'se'\ntype End = 'start' | 'end' | 'callout'\nconst CORNERS: readonly string[] = ['nw', 'ne', 'sw', 'se']\nconst ENDS: readonly string[] = ['start', 'end']\nconst CALLOUT = 'callout'\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 | {\n kind: 'press'\n id: string\n start: PageHit\n /** Pressed a member of a multi-selection: a click narrows the selection to it. */\n narrow: boolean\n }\n | { kind: 'move'; ids: string[]; start: PageHit; els: HTMLElement[] }\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 /** Keeps its aspect ratio whatever the modifier keys. */\n locked: boolean\n /** Where the resized annotation is drawn instead of scaling `el`, for a free text. */\n preview: HTMLElement | undefined\n }\n | {\n kind: 'endpoint'\n id: string\n start: PageHit\n which: End\n /** Where the dragged end was when the press began, CSS px. */\n from: Point\n el: HTMLElement | undefined\n preview: HTMLElement\n }\n\nexport interface SelectionEdit {\n onPointerDown(e: PointerEvent, hit: PageHit | undefined, id?: string): boolean | void\n onPointerMove(e: PointerEvent, hit: PageHit | undefined): void\n onPointerUp(e: PointerEvent, hit: PageHit | undefined): void\n onPointerCancel(): void\n /** `Escape` clears the selection; `Delete` and `Backspace` remove the unlocked selected. */\n onKeyDown(e: KeyboardEvent): void\n /** Drops any gesture in progress without writing. */\n reset(): void\n}\n\nexport interface SelectionEditOptions {\n /** A press on empty space draws a marquee (rectangle select). Otherwise it is left alone. */\n marquee?: boolean\n}\n\nexport function createSelectionEdit(\n ctx: ToolContext,\n opts: SelectionEditOptions = {}\n): SelectionEdit {\n let mode: Mode = { kind: 'idle' }\n const batch = (fn: () => void): void => (ctx.history ? ctx.history.batch(fn) : fn())\n\n const reset = (): void => {\n if (mode.kind === 'marquee') mode.el.remove()\n if (mode.kind === 'move') for (const el of mode.els) el.style.transform = ''\n if (mode.kind === 'resize' && mode.el) {\n mode.el.style.transform = ''\n mode.el.style.transformOrigin = ''\n mode.el.style.visibility = ''\n }\n if (mode.kind === 'resize') mode.preview?.remove()\n if (mode.kind === 'endpoint') {\n mode.preview.remove()\n if (mode.el) mode.el.style.visibility = ''\n }\n mode = { kind: 'idle' }\n }\n\n const elementIn = (root: ParentNode, id: string): HTMLElement | undefined =>\n root.querySelector<HTMLElement>(`[data-annotation=\"${CSS.escape(id)}\"]`) ?? undefined\n\n const previewFor = (host: HTMLElement, a: Annotation): HTMLElement => {\n const preview = host.ownerDocument.createElement('div')\n preview.className = 'ink-annotation ink-edit-preview'\n preview.dataset.inkPreview = ''\n preview.dataset.type = a.type\n preview.style.cssText = 'position:absolute;pointer-events:none;'\n return preview\n }\n\n /** Shows `draft` in `preview` beside `el`, which is hidden meanwhile. */\n const showPreview = (\n preview: HTMLElement,\n el: HTMLElement | undefined,\n draft: Annotation,\n start: PageHit\n ): void => {\n drawPreview(preview, draft, start)\n if (el) el.style.visibility = 'hidden'\n // Beside the annotation in the overlay, so it paints where the annotation does.\n if (!preview.isConnected) (el?.parentElement ?? start.host).append(preview)\n }\n\n function startHandle(\n e: PointerEvent,\n hit: PageHit,\n a: Annotation,\n handle: string\n ): boolean {\n const el = elementIn(hit.host, a.id)\n if (CORNERS.includes(handle) && hasCornerHandles(a)) {\n const text = a.type === 'freetext'\n mode = {\n kind: 'resize',\n id: a.id,\n start: hit,\n corner: handle as Corner,\n box: text\n ? hit.transform.toCssRect(freeTextBox(a))\n : el\n ? boxOf(el)\n : annotationBox(a, hit.transform),\n el,\n locked: keepsAspect(a),\n preview:\n text && (a.fringe !== undefined || hasCallout(a))\n ? previewFor(hit.host, a)\n : undefined,\n }\n } else if (\n (ENDS.includes(handle) && a.type === 'line') ||\n (handle === CALLOUT && hasCallout(a))\n ) {\n const preview = previewFor(hit.host, a)\n mode = {\n kind: 'endpoint',\n id: a.id,\n start: hit,\n which: handle as End,\n from: hit.transform.toCss(endOf(a, handle as End)!),\n el,\n preview,\n }\n } else {\n return false\n }\n // The annotation is already selected (it has handles): keep the overlay from\n // re-activating it.\n e.stopPropagation()\n e.preventDefault()\n return true\n }\n\n return {\n reset,\n onPointerDown(e, hit, annotationId) {\n if (!hit) return\n reset()\n if (annotationId !== undefined) {\n const a = ctx.store.get(annotationId)\n if (!a) return\n // Under select-text, text markup lets a drag through to text selection and the overlay\n // selects it on a click. Rectangle select treats it as any other annotation: it selects\n // on the press and a drag moves it, so it claims the press from the overlay.\n const markup = isTextMarkup(a)\n if (markup && !opts.marquee) return\n const handle = handleOf(e.target)\n if (handle !== undefined && !a.locked && startHandle(e, hit, a, handle))\n return true\n const selected = ctx.store.selection.get()\n if (e.shiftKey) {\n // Toggle membership ourselves; the overlay would replace the selection.\n e.stopPropagation()\n ctx.store.select(\n selected.includes(annotationId)\n ? selected.filter((s) => s !== annotationId)\n : [...selected, annotationId]\n )\n return\n }\n const narrow = selected.length > 1 && selected.includes(annotationId)\n // A press on a member of the selection keeps the selection, so it can move as one.\n // Otherwise the overlay selects and activates it once this capture-phase handler\n // returns, except markup, which the overlay would hold until the release.\n if (narrow) e.stopPropagation()\n else if (markup) {\n e.stopPropagation()\n ctx.store.select([annotationId])\n ctx.onActivate?.(annotationId)\n }\n mode = { kind: 'press', id: annotationId, start: hit, narrow }\n e.preventDefault()\n return true\n }\n if (!opts.marquee) return\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 (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, preview } = mode\n const next = resizeCss(box, mode.corner, cornerAt(mode, e), minCss(start), {\n aspect: mode.locked || e.shiftKey,\n page: start.transform,\n })\n if (preview) {\n const a = ctx.store.get(mode.id)\n if (a?.type !== 'freetext') return\n const draft = { ...a, ...resizedBox(a, userBox(start.transform, next)) }\n showPreview(preview, el, draft, start)\n } else 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 if (mode.kind === 'endpoint') {\n const a = ctx.store.get(mode.id)\n if (!a) return\n const patch = endPatch(a, mode.which, endAt(mode, e))\n if (!patch) return\n showPreview(mode.preview, mode.el, { ...a, ...patch } as Annotation, start)\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 selected = ctx.store.selection.get()\n // Text markup is anchored to its text, and may carry a comment: it moves only when it\n // is what the drag pressed, never along with the rest of a selection.\n const pressed = mode.id\n const ids = selected.includes(pressed)\n ? selected.filter((id) => {\n const m = ctx.store.get(id)\n return m !== undefined && !m.locked && (id === pressed || !isTextMarkup(m))\n })\n : [pressed]\n const els = ids\n .map((id) => elementIn(ctx.root, id))\n .filter((el): el is HTMLElement => el !== undefined)\n mode = { kind: 'move', ids, start, els }\n }\n if (mode.kind === 'move') {\n for (const el of mode.els) 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 const current = mode\n reset()\n if (current.kind !== 'idle' && !current.start.host.isConnected) return\n switch (current.kind) {\n case 'press':\n // A click on a member of a multi-selection: just that one, as the overlay would.\n if (current.narrow) {\n ctx.store.select([current.id])\n ctx.onActivate?.(current.id)\n }\n return\n case 'move': {\n const { start } = current\n const end = start.transform.fromCss(cssIn(start.host, e))\n const dx = end.x - start.user.x\n const dy = end.y - start.user.y\n batch(() => {\n for (const id of current.ids) {\n const a = ctx.store.get(id)\n if (a && !a.locked) ctx.store.update(id, translated(a, dx, dy))\n }\n })\n return\n }\n case 'resize': {\n const { start, box } = current\n const next = resizeCss(\n box,\n current.corner,\n cornerAt(current, e),\n minCss(start),\n {\n aspect: current.locked || e.shiftKey,\n page: start.transform,\n }\n )\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 to = userBox(start.transform, next)\n if (a.type === 'freetext') {\n ctx.store.update(a.id, resizedBox(a, to))\n return\n }\n // A rect-shaped annotation's box is its rect; a point-based one's is its drawn box.\n const from = hasRectGeometry(a) ? a.rect : start.transform.fromCssRect(box)\n ctx.store.update(a.id, scaled(a, from, to))\n return\n }\n case 'endpoint': {\n const a = ctx.store.get(current.id)\n if (!a || a.locked) return\n const css = cssIn(current.start.host, e)\n if (css.x === current.start.css.x && css.y === current.start.css.y) return\n const patch = endPatch(a, current.which, endAt(current, e))\n if (patch) ctx.store.update(a.id, patch)\n return\n }\n case '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 // Replies have no element on the page, so a marquee never picks them.\n const ids = withoutReplies(ctx.store.list.get())\n .filter((a) => a.page === start.page && 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 return\n }\n default:\n }\n },\n onKeyDown(e) {\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 handle (`nw`, `start`, ...) a press landed on, if it landed on one. */\nfunction handleOf(target: EventTarget | null): string | undefined {\n if (!(target instanceof Element)) return undefined\n return target.closest('[data-handle]')?.getAttribute('data-handle') ?? undefined\n}\n\n/** An overlay element's CSS box, from its inline geometry. */\nfunction boxOf(el: HTMLElement): CssRect {\n return {\n left: parseFloat(el.style.left) || 0,\n top: parseFloat(el.style.top) || 0,\n width: parseFloat(el.style.width) || 0,\n height: parseFloat(el.style.height) || 0,\n }\n}\n\n/** The point a line's end or a callout's tip handle sits on. */\nfunction endOf(a: Annotation, which: End): Point | undefined {\n if (which === 'callout') return hasCallout(a) ? a.callout[0] : undefined\n return a.type === 'line' ? a[which] : undefined\n}\n\n/** The patch that moves a line's end, or a callout's tip, to `to`; undefined for neither. */\nfunction endPatch(a: Annotation, which: End, to: Point): Partial<Annotation> | undefined {\n if (which === 'callout') return hasCallout(a) ? movedTip(a, to) : undefined\n return a.type === 'line' ? movedEndpoint(a, which, to) : undefined\n}\n\n/** A resized CSS box in user space, at least `MIN_SIZE` a side. */\nfunction userBox(t: PageTransform, css: CssRect): Rect {\n const r = t.fromCssRect(css)\n return {\n ...r,\n width: Math.max(MIN_SIZE, r.width),\n height: Math.max(MIN_SIZE, r.height),\n }\n}\n\n/** Draws `a` into the preview element at its own box. */\nfunction drawPreview(el: HTMLElement, a: Annotation, start: PageHit): void {\n const box = annotationBox(a, start.transform)\n el.style.left = `${box.left}px`\n el.style.top = `${box.top}px`\n el.style.width = `${box.width}px`\n el.style.height = `${box.height}px`\n renderAnnotationContent(el, a, start.transform)\n}\n\n/** Keeps a CSS point on the page. */\nfunction onPage(start: PageHit, x: number, y: number): Point {\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/**\n * Where the dragged line end is now, in user space: where it started plus the pointer's\n * travel, kept on the page.\n */\nfunction endAt(\n mode: { start: PageHit; from: Point },\n e: { clientX: number; clientY: number }\n): Point {\n const { start, from } = mode\n const css = cssIn(start.host, e)\n return start.transform.fromCss(\n onPage(start, from.x + css.x - start.css.x, from.y + css.y - start.css.y)\n )\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 return onPage(start, x, y)\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/**\n * `box` with its `corner` dragged to `p` and the opposite corner fixed, at least `min` a side.\n * With `aspect`, the box keeps its proportions: it scales by the larger of the two axes'\n * changes, kept on the page.\n */\nfunction resizeCss(\n box: CssRect,\n corner: Corner,\n p: Point,\n min: number,\n opts: { aspect: boolean; page: { cssWidth: number; cssHeight: number } }\n): CssRect {\n const west = corner[1] === 'w'\n const north = corner[0] === 'n'\n /** The fixed corner. */\n const fx = west ? box.left + box.width : box.left\n const fy = north ? box.top + box.height : box.top\n let width = Math.max(west ? fx - p.x : p.x - fx, min)\n let height = Math.max(north ? fy - p.y : p.y - fy, min)\n if (opts.aspect && box.width > 0 && box.height > 0) {\n // Room from the fixed corner to the page edge the dragged corner moves towards.\n const roomX = west ? fx : opts.page.cssWidth - fx\n const roomY = north ? fy : opts.page.cssHeight - fy\n const lo = min / Math.min(box.width, box.height)\n const hi = Math.min(roomX / box.width, roomY / box.height)\n const s = Math.min(\n Math.max(width / box.width, height / box.height, lo),\n Math.max(hi, lo)\n )\n width = box.width * s\n height = box.height * s\n }\n return {\n left: west ? fx - width : fx,\n top: north ? fy - height : fy,\n width,\n height,\n }\n}\n","import { createSelectionEdit, type SelectionEdit } from './selection-edit'\n\nimport type { Tool } from './controller'\n\n/**\n * Rectangle select: a drag on empty space draws a marquee that selects the annotations it\n * touches (`Shift` adds to the selection). Presses on annotations select, move and resize them\n * as `select-text` does (selection-edit.ts).\n */\nexport function selectTool(): Tool {\n let edit: SelectionEdit | undefined\n return {\n id: 'select',\n cursor: 'default',\n activate(ctx) {\n edit = createSelectionEdit(ctx, { marquee: true })\n },\n deactivate() {\n edit?.reset()\n edit = undefined\n },\n onPointerDown: (e, hit, id) => edit?.onPointerDown(e, hit, id),\n onPointerMove: (e, hit) => edit?.onPointerMove(e, hit),\n onPointerUp: (e, hit) => edit?.onPointerUp(e, hit),\n onPointerCancel: () => edit?.onPointerCancel(),\n onKeyDown: (e) => edit?.onKeyDown(e),\n }\n}\n","import { createSelectionEdit, type SelectionEdit } from './selection-edit'\n\nimport type { Tool } from './controller'\n\n/**\n * The default tool. Text selection stays native: presses on text, and drags across text\n * markup, select text. Presses on other annotations select them, and drags move and resize\n * them (selection-edit.ts). There is no marquee.\n */\nexport function selectTextTool(): Tool {\n let edit: SelectionEdit | undefined\n return {\n id: 'select-text',\n cursor: 'auto',\n activate(ctx) {\n edit = createSelectionEdit(ctx)\n },\n deactivate() {\n edit?.reset()\n edit = undefined\n },\n onPointerDown: (e, hit, id) => edit?.onPointerDown(e, hit, id),\n onPointerMove: (e, hit) => edit?.onPointerMove(e, hit),\n onPointerUp: (e, hit) => edit?.onPointerUp(e, hit),\n onPointerCancel: () => edit?.onPointerCancel(),\n onKeyDown: (e) => edit?.onKeyDown(e),\n }\n}\n","// Drag draws a shape between the press and the release; a click, or Enter on the viewport,\n// places a default-size one. Enter places no loupe or mask: they are pointer-only. The live\n// draft is `position:absolute; pointer-events:none`, a box over the shape's bounds holding an\n// SVG preview: geometry only, the look comes from the theme\n// (`.ink-draft[data-ink-draft='shape']`).\nimport {\n calloutStroke,\n freeTextBox,\n withCalloutBounds,\n} from '../../model/annotations/callout'\nimport { isBubble } from '../../model/annotations/edit'\nimport {\n constrain,\n DEFAULT_SHAPE_OPTIONS,\n defaultEnds,\n isPointerOnlyKind,\n shapeInput,\n type ShapeOptions,\n} from '../../model/annotations/shape-geometry'\nimport { closedEditor, editFreeTextIn } from '../freetext-editor'\n\nimport {\n clampedCssIn,\n isViewportEnter,\n type PageHit,\n type Tool,\n type ToolContext,\n} from './controller'\n\nimport type {\n Annotation,\n AnnotationInput,\n FreeTextAnnotation,\n} from '../../model/annotations/types'\nimport type { Point } from '../../model/geometry'\n\nexport {\n DEFAULT_CORNER_RADIUS,\n DEFAULT_SHAPE_SIZE,\n SHAPE_KINDS,\n type ShapeKind,\n type ShapeOptions,\n} from '../../model/annotations/shape-geometry'\n\n/** Smallest drag, in CSS px on its longer axis, that draws a shape rather than counting as a click. */\nconst MIN_CSS = 3\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\nexport function shapeTool(): Tool<ShapeOptions> {\n let ctx: ToolContext | undefined\n let start: PageHit | undefined\n let draft: HTMLElement | undefined\n\n const clear = (): void => {\n draft?.remove()\n draft = undefined\n start = undefined\n }\n\n const options = (c: ToolContext): ShapeOptions => ({\n ...DEFAULT_SHAPE_OPTIONS,\n ...c.options<ShapeOptions>(),\n })\n\n /** The input for a drag from `a` to `b` (user space), with Shift's constraint applied. */\n const inputFor = (\n c: ToolContext,\n page: number,\n a: Point,\n b: Point,\n shift: boolean\n ): AnnotationInput | undefined => {\n const o = options(c)\n return shapeInput(o.kind, page, a, shift ? constrain(o.kind, a, b) : b, o)\n }\n\n /** The input with the shape group's style and, for a bubble, the text group's text style. */\n const styled = (c: ToolContext, input: AnnotationInput): AnnotationInput => {\n if (input.type !== 'freetext') return c.toolStyle.resolve('shape', input)\n // The group's width must not lose to the bubble's default one, so it is filled last.\n const shape = c.toolStyle.resolve('shape', { ...input, width: undefined })\n const blank: AnnotationInput & { type: 'freetext' } = {\n type: 'freetext',\n page: input.page,\n contents: '',\n }\n const text = c.toolStyle.resolve('text', blank)\n const out = {\n ...shape,\n width: shape.width ?? input.width,\n defaultStyle: { ...text.defaultStyle, ...input.defaultStyle },\n }\n if (!input.callout || !input.rect) return out\n // The bounds were fit to the bubble's default width: refit them to the group's.\n const box = freeTextBox({ rect: input.rect, fringe: input.fringe })\n const { width } = calloutStroke(out as FreeTextAnnotation)\n return { ...out, ...withCalloutBounds(box, input.callout, width, input.head) }\n }\n\n /** Stops waiting for a bubble the host has not applied yet. */\n let waiting: (() => void) | undefined\n\n const openEditor = (c: ToolContext, a: Annotation): boolean => {\n const el = c.root.querySelector<HTMLElement>(\n `[data-annotation=\"${CSS.escape(a.id)}\"]`\n )\n return (\n el !== null &&\n editFreeTextIn(c.store, el, a.id, c.viewport.transformFor(a.page)) !== undefined\n )\n }\n\n /**\n * Opens the in-place editor on a new bubble. When a controlled host has not applied it yet,\n * the editor opens once it does.\n */\n const edit = (c: ToolContext, a: Annotation): void => {\n waiting?.()\n waiting = undefined\n if (openEditor(c, a)) return\n const stop = c.store.list.subscribe(() => {\n if (!c.store.get(a.id)) return\n stop()\n if (waiting === stop) waiting = undefined\n openEditor(c, a)\n })\n waiting = stop\n }\n\n const add = (c: ToolContext, input: AnnotationInput | undefined): void => {\n if (!input) return\n const created = c.store.add(styled(c, input))\n c.store.select([created.id])\n if (isBubble(created)) edit(c, created)\n }\n\n const paint = (c: ToolContext, from: PageHit, e: PointerEvent): void => {\n const css = clampedCssIn(from.host, e)\n const user = from.transform.fromCss(css)\n const input = inputFor(c, from.page, from.user, user, e.shiftKey)\n if (!input) return\n const t = from.transform\n let box: { left: number; top: number; width: number; height: number }\n let points: Point[] | undefined\n let kind: 'rect' | 'ellipse' | 'path' = 'path'\n if (\n input.type === 'square' ||\n input.type === 'circle' ||\n input.type === 'freetext' ||\n input.type === 'loupe' ||\n input.type === 'mask'\n ) {\n if (!input.rect) return\n // A bubble previews its text box; its tail comes with the bubble itself.\n box = t.toCssRect(\n input.type === 'freetext'\n ? freeTextBox({ rect: input.rect, fringe: input.fringe })\n : input.rect\n )\n kind =\n input.type === 'circle' ||\n input.type === 'loupe' ||\n (input.type === 'mask' && input.shape === 'ellipse')\n ? 'ellipse'\n : 'rect'\n } else {\n if (input.type === 'line') points = [t.toCss(input.start), t.toCss(input.end)]\n else if (input.type === 'polygon') points = input.vertices.map((v) => t.toCss(v))\n else return\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const left = Math.min(...xs)\n const top = Math.min(...ys)\n box = {\n left,\n top,\n width: Math.max(...xs) - left,\n height: Math.max(...ys) - top,\n }\n }\n if (!draft) {\n draft = from.host.ownerDocument.createElement('div')\n draft.className = 'ink-draft'\n draft.dataset.inkDraft = 'shape'\n draft.style.position = 'absolute'\n draft.style.pointerEvents = 'none'\n from.host.append(draft)\n }\n draft.dataset.inkShape = options(c).kind\n draft.style.left = `${box.left}px`\n draft.style.top = `${box.top}px`\n draft.style.width = `${box.width}px`\n draft.style.height = `${box.height}px`\n const doc = from.host.ownerDocument\n const svg = doc.createElementNS(SVG_NS, 'svg')\n svg.setAttribute('width', String(box.width))\n svg.setAttribute('height', String(box.height))\n svg.style.overflow = 'visible'\n const node =\n kind === 'path'\n ? doc.createElementNS(SVG_NS, input.type === 'line' ? 'polyline' : 'polygon')\n : doc.createElementNS(SVG_NS, kind)\n if (kind === 'path') {\n node.setAttribute(\n 'points',\n (points ?? []).map((p) => `${p.x - box.left},${p.y - box.top}`).join(' ')\n )\n } else if (kind === 'ellipse') {\n node.setAttribute('cx', String(box.width / 2))\n node.setAttribute('cy', String(box.height / 2))\n node.setAttribute('rx', String(box.width / 2))\n node.setAttribute('ry', String(box.height / 2))\n } else {\n node.setAttribute('width', String(box.width))\n node.setAttribute('height', String(box.height))\n if ((input.type === 'square' || input.type === 'freetext') && input.cornerRadius)\n node.setAttribute('rx', String(t.toCssLength(input.cornerRadius)))\n }\n svg.append(node)\n draft.replaceChildren(svg)\n }\n\n return {\n id: 'shape',\n cursor: 'crosshair',\n styleGroup: 'shape',\n defaultOptions: { ...DEFAULT_SHAPE_OPTIONS },\n activate(c) {\n ctx = c\n },\n deactivate() {\n clear()\n waiting?.()\n waiting = undefined\n ctx = undefined\n },\n onPointerDown(e, hit, annotationId) {\n // A press that ended a bubble's edit only ends it.\n if (!hit || annotationId !== undefined || closedEditor(e)) return\n start = hit\n // Keeps the press from starting a text selection.\n e.preventDefault()\n return true\n },\n onPointerMove(e) {\n if (!ctx || !start) return\n // No button down: the release was missed, so drop the draft. A host scrolled out of the\n // mounted range is gone with it.\n if (e.buttons === 0 || !start.host.isConnected) {\n clear()\n return\n }\n paint(ctx, start, e)\n },\n onPointerCancel() {\n clear()\n },\n onPointerUp(e) {\n if (!ctx || !start) return\n const from = start\n if (!from.host.isConnected) {\n clear()\n return\n }\n const css = clampedCssIn(from.host, e)\n const long = Math.max(Math.abs(css.x - from.css.x), Math.abs(css.y - from.css.y))\n if (long >= MIN_CSS) {\n add(\n ctx,\n inputFor(ctx, from.page, from.user, from.transform.fromCss(css), e.shiftKey)\n )\n } else {\n const [a, b] = defaultEnds(\n options(ctx).kind,\n from.user,\n from.transform.page.rotate\n )\n add(ctx, inputFor(ctx, from.page, a, b, false))\n }\n clear()\n },\n onKeyDown(e) {\n if (!ctx || !isViewportEnter(e, ctx.root)) return\n // The loupe and the mask are pointer-only, like area redaction.\n if (isPointerOnlyKind(options(ctx).kind)) return\n e.preventDefault()\n const page = ctx.viewport.currentPage.get()\n const { box, rotate } = ctx.viewport.transformFor(page).page\n const [a, b] = defaultEnds(\n options(ctx).kind,\n { x: box.x + box.width / 2, y: box.y + box.height / 2 },\n rotate\n )\n add(ctx, inputFor(ctx, page, a, b, false))\n },\n }\n}\n","// Places the chosen signature template. A click puts it centred on the press, about 150 pt\n// wide; Enter in the viewport puts it at the centre of the current page. It is turned against\n// the page's own /Rotate, so it reads upright on the page as the file displays it; a view\n// rotation is the viewer's, and turns it with the page like any annotation. Ink takes the\n// `ink` group's colour at the template's own width; an image is placed as it is. Either way\n// the new annotation is selected, one undo step, and the tool stays active for the next one.\nimport {\n DEFAULT_SIGNATURE_WIDTH,\n placeSignature,\n type SignatureOptions,\n type SignatureTemplate,\n} from '../../model/signatures'\n\nimport { isViewportEnter, type PageHit, type Tool, type ToolContext } from './controller'\n\nimport type { Point } from '../../model/geometry'\nimport type { PageRotation } from '../../model/pages'\n\nexport type { SignatureOptions }\n\nexport function signatureTool(): Tool<SignatureOptions> {\n let ctx: ToolContext | undefined\n let down: PageHit | undefined\n /** Bumped on deactivate, so a load still pending from an earlier use places nothing. */\n let generation = 0\n\n const place = (\n c: ToolContext,\n t: SignatureTemplate,\n page: number,\n at: Point,\n rotation: PageRotation\n ): void => {\n const input = placeSignature(t, page, at, DEFAULT_SIGNATURE_WIDTH, rotation)\n const a = c.store.add(\n input.type === 'ink' ? c.toolStyle.resolve('ink', input) : input\n )\n c.store.select([a.id])\n }\n\n /**\n * Places the selected template, from the library at once, or after reloading it when the\n * template was saved since the last load. False when there is nothing to place.\n */\n const placeSelected = (\n c: ToolContext,\n page: number,\n at: Point,\n rotation: PageRotation\n ): boolean => {\n const id = c.options<SignatureOptions>().templateId\n const library = c.signatures\n if (id === undefined || !library) return false\n const t = library.get(id)\n if (t) {\n place(c, t, page, at, rotation)\n return true\n }\n const gen = generation\n void library.refresh().then(() => {\n // The tool may have been switched (even away and back), or the template removed.\n const later = library.get(id)\n if (\n later &&\n ctx === c &&\n gen === generation &&\n c.options<SignatureOptions>().templateId === id\n )\n place(c, later, page, at, rotation)\n })\n return true\n }\n\n return {\n id: 'signature',\n cursor: 'copy',\n defaultOptions: {},\n activate(c) {\n ctx = c\n },\n deactivate() {\n ctx = undefined\n down = undefined\n generation++\n },\n onPointerDown(_e, hit, annotationId) {\n down = annotationId === undefined ? hit : undefined\n return down !== undefined\n },\n onPointerMove(e) {\n // The release was missed: treat it as a cancel.\n if (e.buttons === 0) 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 placeSelected(ctx, hit.page, hit.user, hit.transform.page.rotate)\n },\n onKeyDown(e) {\n if (!ctx || !isViewportEnter(e, ctx.root)) return\n const page = ctx.viewport.currentPage.get()\n const t = ctx.viewport.transformFor(page)\n const { box } = t.page\n const centre = { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n if (placeSelected(ctx, page, centre, t.page.rotate)) e.preventDefault()\n },\n }\n}\n","// Freehand ink that tidies itself. It captures and previews strokes as `draw` does, but each\n// stroke stands alone: sketch never joins strokes. On release the stroke is added as ink, then\n// `recogniseStroke` scores it; a fit at `RECOGNISE_THRESHOLD` or better replaces the ink with\n// the clean shape, styled from the `shape` group. Two undo steps: the ink, then the swap (one\n// `history.batch`), so one undo brings the stroke back and a second removes it.\n//\n// A controlled host applies the ink later, or never. The swap waits until the ink is in the\n// list, then a task more, so the host's own history records the ink as a step before the swap.\n// Deactivating the tool cancels a swap still waiting.\nimport { DEFAULT_SHAPE_OPTIONS, shapeInput } from '../../model/annotations/shape-geometry'\nimport {\n recogniseStroke,\n RECOGNISE_THRESHOLD,\n type Recognised,\n} from '../../model/recognise'\n\nimport { freehandTool } from './freehand'\n\nimport type { Tool, ToolContext } from './controller'\nimport type { AnnotationInput } from '../../model/annotations/types'\n\n/** How long the swap waits for a controlled host to apply the ink before giving up. */\nconst APPLY_WAIT_MS = 2000\n\n/**\n * The smallest stroke, in CSS px across its longer side, that can become a shape. A click or\n * its jitter stays a dot of ink, as with `draw`, rather than an invisible sliver of a line.\n */\nconst MIN_SHAPE_PX = 4\n\n/** The longer side of the box `points` span, in the units they are in. */\nfunction extent(points: readonly { x: number; y: number }[]): number {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n return Math.max(Math.max(...xs) - Math.min(...xs), Math.max(...ys) - Math.min(...ys))\n}\n\n/** The annotation a recognised stroke becomes. */\nfunction recognisedInput(shape: Recognised, page: number): AnnotationInput | undefined {\n switch (shape.kind) {\n case 'line':\n case 'arrow':\n return shapeInput(shape.kind, page, shape.start, shape.end, DEFAULT_SHAPE_OPTIONS)\n case 'rectangle':\n case 'ellipse': {\n const { x, y, width, height } = shape.rect\n return shapeInput(\n shape.kind,\n page,\n { x, y },\n { x: x + width, y: y + height },\n DEFAULT_SHAPE_OPTIONS\n )\n }\n // The recogniser already tidied the vertices: a polygon keeps the corners the stroke had,\n // a star is regular.\n case 'polygon':\n case 'star':\n return { type: 'polygon', page, vertices: shape.vertices }\n }\n}\n\n/**\n * Runs `fn` once the annotation `id` is in the list and the host has had a task to record it.\n * Gives up (calling `onGiveUp`) when the host has not applied it in `APPLY_WAIT_MS`. Returns a\n * cancel that drops whatever is still pending.\n */\nfunction whenApplied(\n c: ToolContext,\n id: string,\n fn: () => void,\n onGiveUp: () => void\n): () => void {\n if (c.store.get(id)) {\n fn()\n return () => undefined\n }\n let swap: ReturnType<typeof setTimeout> | undefined\n // Every timer and the subscription exist before anything can call `cancel`.\n const giveUp = setTimeout(() => {\n cancel()\n onGiveUp()\n }, APPLY_WAIT_MS)\n let stop: (() => void) | undefined = c.store.list.subscribe(() => {\n if (!c.store.get(id)) return\n cancel()\n swap = setTimeout(fn, 0)\n })\n function cancel(): void {\n stop?.()\n stop = undefined\n clearTimeout(giveUp)\n clearTimeout(swap)\n }\n return cancel\n}\n\nexport function sketchTool(): Tool {\n /** Cancels for swaps still waiting on a controlled host. */\n const pending = new Set<() => void>()\n return freehandTool({\n id: 'sketch',\n // Switching tools or tearing the viewer down drops any swap still waiting: the stroke\n // stays ink, and nothing fires against a store that may be gone.\n deactivate() {\n for (const cancel of pending) cancel()\n pending.clear()\n },\n commit(c, s) {\n const ink = c.store.add(\n c.toolStyle.resolve('ink', {\n type: 'ink',\n page: s.page,\n inklist: [s.points],\n ...(s.pressure ? { pressure: [s.pressure] } : {}),\n })\n )\n if (c.viewport.transformFor(s.page).toCssLength(extent(s.points)) < MIN_SHAPE_PX)\n return\n const fit = recogniseStroke(s.points)\n if (!fit || fit.score < RECOGNISE_THRESHOLD) return\n const input = recognisedInput(fit.shape, s.page)\n if (!input) return\n const shape = c.toolStyle.resolve('shape', input)\n const batch = (fn: () => void): void => (c.history ? c.history.batch(fn) : fn())\n // Uncontrolled, the swap runs straight away, before `whenApplied` returns.\n let ran = false\n let cancel = (): void => undefined\n cancel = whenApplied(\n c,\n ink.id,\n () => {\n ran = true\n pending.delete(cancel)\n // Undone, or changed, before the swap: leave the stroke as it is. A host may hand back\n // copies, so the check is by modification time, not identity.\n if (c.store.get(ink.id)?.modifiedAt !== ink.modifiedAt) return\n batch(() => {\n c.store.remove(ink.id)\n c.store.add(shape)\n })\n },\n () => pending.delete(cancel)\n )\n if (!ran) pending.add(cancel)\n },\n })\n}\n","import { createToolStyle, type ToolStyle } from '../../model/annotations/tool-style'\nimport { writable } from '../../model/readable'\n\nimport {\n createToolController as createWith,\n type Tool,\n type ToolControllerOptions,\n type ToolController,\n type ToolId,\n} from './controller'\nimport { drawTool } from './draw'\nimport { DEFAULT_FREETEXT_WIDTH, freetextTool } from './freetext'\nimport { highlightTool } from './highlight'\nimport { noteTool } from './note'\nimport { redactAreaTool } from './redact-area'\nimport { selectTool } from './select'\nimport { selectTextTool } from './select-text'\nimport { shapeTool } from './shape'\nimport { signatureTool } from './signature'\nimport { sketchTool } from './sketch'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\n\nexport type {\n BuiltinToolId,\n PageHit,\n Tool,\n ToolContext,\n ToolController,\n ToolControllerOptions,\n ToolId,\n} from './controller'\nexport { hitFor } from './controller'\nexport { createToolOptions, type ToolOptions } from './options'\nexport {\n DEFAULT_FREETEXT_WIDTH,\n drawTool,\n freetextTool,\n highlightTool,\n noteTool,\n redactAreaTool,\n selectTextTool,\n selectTool,\n shapeTool,\n signatureTool,\n sketchTool,\n}\nexport type { SignatureOptions } from './signature'\nexport {\n DEFAULT_HIGHLIGHT_OPTIONS,\n MARKUP_KINDS,\n type HighlightOptions,\n type MarkupKind,\n} from './highlight'\nexport {\n DEFAULT_CORNER_RADIUS,\n DEFAULT_SHAPE_SIZE,\n SHAPE_KINDS,\n type ShapeKind,\n type ShapeOptions,\n} from './shape'\n\n/** Fresh instances of every built-in tool. */\nexport function builtinTools(): Tool[] {\n return [\n selectTextTool(),\n selectTool(),\n highlightTool(),\n redactAreaTool(),\n sketchTool(),\n drawTool(),\n noteTool(),\n shapeTool(),\n freetextTool(),\n signatureTool(),\n ]\n}\n\n/** The built-in tools with a host's tools added, a host tool replacing a built-in by id. */\nexport function withHostTools(host: readonly Tool[] = []): Tool[] {\n const byId = new Map(builtinTools().map((t) => [t.id, t]))\n for (const t of host) byId.set(t.id, t)\n return [...byId.values()]\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\nexport interface ToolStyleTracker {\n readonly toolStyle: ToolStyle\n /** Call when the active tool changes: the style's active group follows it. */\n setTool(id: ToolId): void\n}\n\n/**\n * A `ToolStyle` whose active group is the style group of the active tool among `tools` (the\n * built-ins plus a host's). The engine makes one when it is not handed a style; a binding\n * makes its own per document, so its style controls work before the viewport mounts.\n */\nexport function trackToolStyle(opts: {\n store: AnnotationStore\n history: { batch(fn: () => void): void }\n /** Host tools, as passed to `mountViewer`. */\n tools?: readonly Tool[] | undefined\n tool?: ToolId | undefined\n}): ToolStyleTracker {\n const groups = new Map(withHostTools(opts.tools).map((t) => [t.id, t.styleGroup]))\n const active = writable<ToolId>(opts.tool ?? 'select-text')\n const toolStyle = createToolStyle({\n store: opts.store,\n history: opts.history,\n activeGroup: () => groups.get(active.get()),\n active,\n })\n return { toolStyle, setTool: (id) => active.set(id) }\n}\n","// The swatches the colour menus offer: a row of common colours, a row of greys, and a tonal\n// grid. Every value is upper-case #RRGGBB, so a style's colour compares to a swatch directly.\n\nexport interface Palette {\n /** 12 swatches, the top row. */\n readonly common: readonly string[]\n /** 12 greys, white to black. */\n readonly greys: readonly string[]\n /** 8 rows of 12 hue columns (red round to rose in 30 degree steps), dark to light. */\n readonly grid: readonly (readonly string[])[]\n}\n\nexport const PALETTE: Palette = {\n common: [\n '#FF3B30',\n '#FF9500',\n '#FFCC00',\n '#34C759',\n '#00C7BE',\n '#32ADE6',\n '#007AFF',\n '#5856D6',\n '#AF52DE',\n '#FF2D55',\n '#A2845E',\n '#8E8E93',\n ],\n greys: [\n '#FFFFFF',\n '#E8E8E8',\n '#D1D1D1',\n '#B9B9B9',\n '#A2A2A2',\n '#8B8B8B',\n '#747474',\n '#5D5D5D',\n '#464646',\n '#2E2E2E',\n '#171717',\n '#000000',\n ],\n grid: [\n [\n '#590D0D',\n '#59330D',\n '#59590D',\n '#33590D',\n '#0D590D',\n '#0D5933',\n '#0D5959',\n '#0D3359',\n '#0D0D59',\n '#330D59',\n '#590D59',\n '#590D33',\n ],\n [\n '#861313',\n '#864D13',\n '#868613',\n '#4D8613',\n '#138613',\n '#13864D',\n '#138686',\n '#134D86',\n '#131386',\n '#4D1386',\n '#861386',\n '#86134D',\n ],\n [\n '#B31919',\n '#B36619',\n '#B3B319',\n '#66B319',\n '#19B319',\n '#19B366',\n '#19B3B3',\n '#1966B3',\n '#1919B3',\n '#6619B3',\n '#B319B3',\n '#B31966',\n ],\n [\n '#DF2020',\n '#DF8020',\n '#DFDF20',\n '#80DF20',\n '#20DF20',\n '#20DF80',\n '#20DFDF',\n '#2080DF',\n '#2020DF',\n '#8020DF',\n '#DF20DF',\n '#DF2080',\n ],\n [\n '#E64C4C',\n '#E6994C',\n '#E6E64C',\n '#99E64C',\n '#4CE64C',\n '#4CE699',\n '#4CE6E6',\n '#4C99E6',\n '#4C4CE6',\n '#994CE6',\n '#E64CE6',\n '#E64C99',\n ],\n [\n '#EC7979',\n '#ECB379',\n '#ECEC79',\n '#B3EC79',\n '#79EC79',\n '#79ECB3',\n '#79ECEC',\n '#79B3EC',\n '#7979EC',\n '#B379EC',\n '#EC79EC',\n '#EC79B3',\n ],\n [\n '#F2A6A6',\n '#F2CCA6',\n '#F2F2A6',\n '#CCF2A6',\n '#A6F2A6',\n '#A6F2CC',\n '#A6F2F2',\n '#A6CCF2',\n '#A6A6F2',\n '#CCA6F2',\n '#F2A6F2',\n '#F2A6CC',\n ],\n [\n '#F9D2D2',\n '#F9E6D2',\n '#F9F9D2',\n '#E6F9D2',\n '#D2F9D2',\n '#D2F9E6',\n '#D2F9F9',\n '#D2E6F9',\n '#D2D2F9',\n '#E6D2F9',\n '#F9D2F9',\n '#F9D2E6',\n ],\n ],\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 { isKnown, LINE_ENDINGS } from '../model/annotations/pdf-names'\n\nimport { PALETTE } from './palette'\n\nimport type {\n HighlightOptions,\n MarkupKind,\n ShapeKind,\n ShapeOptions,\n ToolId,\n} from './tools'\nimport type { CurrentStyle, StyleKey, StyleProps } from '../model/annotations/tool-style'\nimport type {\n Annotation,\n ConfidenceBucket,\n LineEnding,\n NoteAnnotation,\n RedactAnnotation,\n Suggestion,\n TextMarkupAnnotation,\n} from '../model/annotations/types'\nimport type { SignatureOptions, SignatureTemplate } from '../model/signatures'\n\n/**\n * Accessible names of the built-in tools, as the toolbar buttons announce them. A host tool has\n * no entry: its button takes the host's `label`, else the tool id.\n */\nexport const TOOL_LABELS: Readonly<Partial<Record<ToolId, string>>> = {\n 'select-text': 'Select text',\n select: 'Rectangle select',\n highlight: 'Highlight',\n 'redact-area': 'Mark for redaction',\n sketch: 'Sketch',\n draw: 'Draw',\n note: 'Add note',\n shape: 'Shape',\n freetext: 'Text',\n signature: 'Sign',\n}\n\n/**\n * The font families a text box offers by default: the PDF standard families, which a PDF\n * writer can use without embedding a font. Hosts pass their own list as `fonts`.\n */\nexport const FONT_FAMILIES: readonly string[] = ['Helvetica', 'Times', 'Courier']\n\n/**\n * The fonts a typed signature offers by default: the browser's own handwriting family. Hosts\n * load handwriting fonts and pass them as `signatureFonts`.\n */\nexport const SIGNATURE_FONTS: readonly string[] = ['cursive']\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/** Stroke weights the line style menu offers, in points. */\nexport const LINE_WEIGHTS: readonly number[] = [0.5, 1, 2, 3, 4, 6, 8]\n\n/** The dash pattern the menu's dashed choice writes, in points. */\nexport const DASH_PATTERN: readonly number[] = [3, 3]\n\n/** The ending the menu's arrowhead choices draw. */\nexport const ARROWHEAD_ENDING: LineEnding = 'OpenArrow'\n\nexport type ArrowheadChoice = 'none' | 'start' | 'end' | 'both'\n\n/** The arrowhead choices in menu order, with the style each one writes (`head` is the start). */\nexport const ARROWHEAD_CHOICES: readonly {\n value: ArrowheadChoice\n label: string\n patch: Pick<StyleProps, 'head' | 'tail'>\n}[] = [\n { value: 'none', label: 'No arrowheads', patch: { head: 'None', tail: 'None' } },\n {\n value: 'start',\n label: 'Arrowhead at start',\n patch: { head: ARROWHEAD_ENDING, tail: 'None' },\n },\n {\n value: 'end',\n label: 'Arrowhead at end',\n patch: { head: 'None', tail: ARROWHEAD_ENDING },\n },\n {\n value: 'both',\n label: 'Arrowheads at both ends',\n patch: { head: ARROWHEAD_ENDING, tail: ARROWHEAD_ENDING },\n },\n]\n\n/**\n * Which arrowhead choice a style shows, `'mixed'` when the selection disagrees, else `undefined`.\n * Only an ending Inkbar draws counts: one it does not know draws as `None`.\n */\nexport function arrowheadChoice(\n head: LineEnding | 'mixed' | undefined,\n tail: LineEnding | 'mixed' | undefined\n): ArrowheadChoice | 'mixed' | undefined {\n if (head === undefined && tail === undefined) return undefined\n if (head === 'mixed' || tail === 'mixed') return 'mixed'\n const drawn = (e: LineEnding | undefined) =>\n e !== undefined && e !== 'None' && isKnown(LINE_ENDINGS, e)\n const start = drawn(head)\n const end = drawn(tail)\n return start ? (end ? 'both' : 'start') : end ? 'end' : 'none'\n}\n\nexport interface LineStyleMenuItem {\n key: string\n label: string\n checked: boolean\n /** What choosing the item writes through the tool style. */\n patch: StyleProps\n}\n\nexport interface LineStyleMenuSection {\n label: string\n /** The selection or active tool supports none of the section's props. */\n disabled: boolean\n items: LineStyleMenuItem[]\n}\n\nexport interface LineStyleMenuModel {\n /** False when nothing supports weight, pattern or endings: the trigger disables. */\n enabled: boolean\n /** The selection disagrees on weight, pattern or endings. */\n mixed: boolean\n sections: LineStyleMenuSection[]\n}\n\n/**\n * What the line style menu shows for a style: sections of checkable items, each section\n * disabled when `supported` lacks its props. A section whose value is mixed checks nothing.\n * Shared by the bindings and the vanilla menu so they cannot drift apart.\n */\nexport function lineStyleMenuModel(\n current: CurrentStyle,\n supported: ReadonlySet<StyleKey>\n): LineStyleMenuModel {\n const canWeight = supported.has('width')\n const canDash = supported.has('dashes')\n const canEnds = supported.has('head') || supported.has('tail')\n const dashed = Array.isArray(current.dashes) && current.dashes.length > 0\n const ends = arrowheadChoice(current.head, current.tail)\n return {\n enabled: canWeight || canDash || canEnds,\n mixed: (['width', 'dashes', 'head', 'tail'] as const).some(\n (k) => current[k] === 'mixed'\n ),\n sections: [\n {\n label: 'Weight',\n disabled: !canWeight,\n items: LINE_WEIGHTS.map((w) => ({\n key: String(w),\n label: `${w} pt`,\n checked: current.width === w,\n patch: { width: w },\n })),\n },\n {\n label: 'Pattern',\n disabled: !canDash,\n items: [\n {\n key: 'solid',\n label: 'Solid',\n checked: current.dashes === null,\n patch: { dashes: null },\n },\n {\n key: 'dashed',\n label: 'Dashed',\n checked: dashed,\n patch: { dashes: [...DASH_PATTERN] },\n },\n ],\n },\n {\n label: 'Arrowheads',\n disabled: !canEnds,\n items: ARROWHEAD_CHOICES.map((c) => ({\n key: c.value,\n label: c.label,\n checked: ends === c.value,\n patch: c.patch,\n })),\n },\n ],\n }\n}\n\n/** The colour props a colour menu can set. */\nexport type ColorProperty = 'border' | 'fill' | 'textColor'\n\n/** Accessible names of the colour menus, by property. */\nexport const COLOR_LABELS: Readonly<Record<ColorProperty, string>> = {\n border: 'Border colour',\n fill: 'Fill colour',\n textColor: 'Text colour',\n}\n\n/** Columns of the swatch grid: the arrow keys move by this much between rows. */\nexport const COLOR_COLUMNS = 12\n\nexport interface ColorMenuSwatch {\n /** Unique within the menu. */\n key: string\n /** The swatch's accessible name: its hex value. */\n label: string\n color: string\n checked: boolean\n patch: StyleProps\n}\n\n/** What the trigger's swatch shows. */\nexport type ColorTrigger =\n | { kind: 'color'; color: string }\n /** No fill. */\n | { kind: 'none' }\n /** The selection disagrees. */\n | { kind: 'mixed' }\n /** Nothing to show: the menu is disabled or the style has no value. */\n | { kind: 'empty' }\n\nexport interface ColorMenuModel {\n label: string\n /** False when nothing supports the property: the trigger disables. */\n enabled: boolean\n mixed: boolean\n trigger: ColorTrigger\n /** Common colours, greys, then the tonal grid, `COLOR_COLUMNS` to a row. */\n swatches: ColorMenuSwatch[]\n /** The \"No fill\" choice, for `fill` only. */\n noFill: { checked: boolean; patch: StyleProps } | null\n /** The colour the custom picker starts on. */\n customValue: string\n /** What picking `hex` in the custom picker writes. */\n custom(hex: string): StyleProps\n}\n\n/**\n * What a colour menu shows for a style: the palette with the matching swatch checked, \"No fill\"\n * for `fill`, and the trigger's swatch. Shared by the bindings and the vanilla menu.\n */\nexport function colorMenuModel(\n property: ColorProperty,\n current: CurrentStyle,\n supported: ReadonlySet<StyleKey>\n): ColorMenuModel {\n const value = current[property]\n const enabled = supported.has(property)\n const color =\n typeof value === 'string' && value !== 'mixed' ? value.toUpperCase() : undefined\n const flat = [\n ...PALETTE.common.map((c, i) => [`common-${i}`, c] as const),\n ...PALETTE.greys.map((c, i) => [`grey-${i}`, c] as const),\n ...PALETTE.grid.flatMap((row, r) =>\n row.map((c, i) => [`grid-${r}-${i}`, c] as const)\n ),\n ]\n const patchFor = (c: string): StyleProps => ({ [property]: c })\n const trigger: ColorTrigger = !enabled\n ? { kind: 'empty' }\n : value === 'mixed'\n ? { kind: 'mixed' }\n : value === null\n ? { kind: 'none' }\n : typeof value === 'string'\n ? { kind: 'color', color: value }\n : { kind: 'empty' }\n return {\n label: COLOR_LABELS[property],\n enabled,\n mixed: value === 'mixed',\n trigger,\n swatches: flat.map(([key, c]) => ({\n key,\n label: c,\n color: c,\n checked: color === c,\n patch: patchFor(c),\n })),\n noFill:\n property === 'fill' ? { checked: value === null, patch: { fill: null } } : null,\n customValue: color ?? '#000000',\n custom: (hex) => patchFor(hex.toUpperCase()),\n }\n}\n\n/** The smallest, largest and default text size in points, and what one step changes. */\nexport const FONT_SIZE_MIN = 1\nexport const FONT_SIZE_MAX = 144\nexport const FONT_SIZE_DEFAULT = 12\nexport const FONT_SIZE_STEP = 1\n\n/** A typed size as the menu stores it: a whole number of points within the range. */\nexport function clampFontSize(size: number): number {\n return Math.min(FONT_SIZE_MAX, Math.max(FONT_SIZE_MIN, Math.round(size)))\n}\n\nexport type TextToggleKey = 'bold' | 'italic' | 'underline'\nexport type TextAlignKey = 'left' | 'center' | 'right' | 'justify'\n\nexport interface TextStyleToggle {\n key: TextToggleKey\n label: string\n /** `'mixed'` when the selection disagrees. */\n pressed: boolean | 'mixed'\n /** What pressing writes: the opposite of `pressed`, and on for a mix. */\n patch: StyleProps\n}\n\nexport interface TextAlignChoice {\n key: TextAlignKey\n label: string\n checked: boolean\n /** The one radio in the Tab order: the checked one, else the first. */\n tabStop: boolean\n patch: StyleProps\n}\n\nexport interface TextStyleMenuModel {\n label: string\n /** False when nothing supports text style: the trigger disables. */\n enabled: boolean\n mixed: boolean\n font: {\n label: string\n /** The family, or `''` when the selection disagrees. */\n value: string\n /** The families on offer, each once; a current family outside the list is added. */\n options: string[]\n patch(family: string): StyleProps\n }\n size: {\n label: string\n /** The size, the default when the style sets none, or `null` when the selection disagrees. */\n value: number | null\n min: number\n max: number\n step: number\n /** What committing a typed size writes, or `null` when it changes nothing. */\n commit(raw: number): StyleProps | null\n /** What a stepper press writes, or `null` at the end of the range. */\n nudge(direction: 1 | -1): StyleProps | null\n }\n toggles: TextStyleToggle[]\n align: { label: string; choices: TextAlignChoice[] }\n}\n\nconst TEXT_KEYS: readonly StyleKey[] = [\n 'fontFamily',\n 'fontSize',\n 'fontWeight',\n 'fontStyle',\n 'textDecoration',\n 'textAlign',\n]\n\nconst ALIGN_KEYS: readonly TextAlignKey[] = ['left', 'center', 'right', 'justify']\n\nconst ALIGN_LABELS: Readonly<Record<TextAlignKey, string>> = {\n left: 'Align left',\n center: 'Align centre',\n right: 'Align right',\n justify: 'Justify',\n}\n\n/**\n * What the text style menu shows for a style: the font, size, bold/italic/underline and\n * alignment, each with the patch choosing it. `fonts` is the list the host offers.\n */\nexport function textStyleMenuModel(\n current: CurrentStyle,\n supported: ReadonlySet<StyleKey>,\n fonts: readonly string[]\n): TextStyleMenuModel {\n const family = current.fontFamily\n const size = current.fontSize\n // A style with no size yet (a fresh group) shows the size a new box gets.\n const value =\n size === 'mixed' ? null : typeof size === 'number' ? size : FONT_SIZE_DEFAULT\n const toggle = (\n key: TextToggleKey,\n label: string,\n prop: 'fontWeight' | 'fontStyle' | 'textDecoration',\n on: string,\n off: string\n ): TextStyleToggle => {\n const now = current[prop]\n const pressed = now === 'mixed' ? 'mixed' : now === on\n return { key, label, pressed, patch: { [prop]: pressed === true ? off : on } }\n }\n const nudge = (direction: 1 | -1): StyleProps | null => {\n const next = clampFontSize((value ?? FONT_SIZE_DEFAULT) + direction * FONT_SIZE_STEP)\n return next === value ? null : { fontSize: next }\n }\n return {\n label: 'Text style',\n enabled: TEXT_KEYS.some((k) => supported.has(k)),\n // The panel holds the text colour too, so a mix of colours shows on the trigger.\n mixed: [...TEXT_KEYS, 'textColor' as const].some((k) => current[k] === 'mixed'),\n font: {\n label: 'Font',\n value: typeof family === 'string' && family !== 'mixed' ? family : '',\n options: [\n ...new Set(\n typeof family === 'string' && family !== 'mixed' ? [...fonts, family] : fonts\n ),\n ],\n patch: (f) => ({ fontFamily: f }),\n },\n size: {\n label: 'Font size',\n value,\n min: FONT_SIZE_MIN,\n max: FONT_SIZE_MAX,\n step: FONT_SIZE_STEP,\n commit: (raw) => {\n if (!Number.isFinite(raw)) return null\n const next = clampFontSize(raw)\n return next === value ? null : { fontSize: next }\n },\n nudge,\n },\n toggles: [\n toggle('bold', 'Bold', 'fontWeight', 'bold', 'normal'),\n toggle('italic', 'Italic', 'fontStyle', 'italic', 'normal'),\n toggle('underline', 'Underline', 'textDecoration', 'underline', 'none'),\n ],\n align: {\n label: 'Alignment',\n choices: ALIGN_KEYS.map((key, i) => ({\n key,\n label: ALIGN_LABELS[key],\n checked: current.textAlign === key,\n tabStop:\n current.textAlign === key ||\n (i === 0 && !ALIGN_KEYS.includes(current.textAlign as TextAlignKey)),\n patch: { textAlign: key },\n })),\n },\n }\n}\n\n/** Accessible names of the shape kinds, as the shape menu announces them. */\nexport const SHAPE_LABELS: Readonly<Record<ShapeKind, string>> = {\n line: 'Line',\n arrow: 'Arrow',\n rectangle: 'Rectangle',\n roundedRectangle: 'Rounded rectangle',\n ellipse: 'Ellipse',\n bubble: 'Speech bubble',\n star: 'Star',\n polygon: 'Polygon',\n loupe: 'Loupe',\n mask: 'Mask',\n ovalMask: 'Oval mask',\n}\n\n/** Accessible names of the text markup kinds, as the highlight menu announces them. */\nexport const MARKUP_LABELS: Readonly<Record<MarkupKind, string>> = {\n highlight: 'Highlight',\n underline: 'Underline',\n strikeout: 'Strikethrough',\n squiggly: 'Squiggly underline',\n}\n\nexport interface HighlightMenuItem {\n kind: MarkupKind\n label: string\n checked: boolean\n}\n\nexport interface HighlightMenuModel {\n /** The kind the main button makes. */\n kind: MarkupKind\n /** The main button's accessible name. */\n label: string\n /** The kinds on offer, in menu order, with the current one checked. */\n items: HighlightMenuItem[]\n}\n\n/** What the highlight menu shows for the highlight tool's options. */\nexport function highlightMenuModel(\n options: Partial<HighlightOptions>,\n kinds: readonly MarkupKind[]\n): HighlightMenuModel {\n const kind =\n options.kind !== undefined && kinds.includes(options.kind)\n ? options.kind\n : (kinds[0] ?? 'highlight')\n return {\n kind,\n label: MARKUP_LABELS[kind],\n items: kinds.map((k) => ({ kind: k, label: MARKUP_LABELS[k], checked: k === kind })),\n }\n}\n\n/** Columns of the shape grid: the arrow keys move by this much between rows. */\nexport const SHAPE_COLUMNS = 2\n\nexport interface ShapeMenuItem {\n kind: ShapeKind\n label: string\n checked: boolean\n}\n\nexport interface ShapeMenuModel {\n /** The kind the main button draws. */\n kind: ShapeKind\n /** The main button's accessible name. */\n label: string\n /** The kinds on offer, in menu order, with the current one checked. */\n items: ShapeMenuItem[]\n}\n\n/**\n * What the shape menu shows for the shape tool's options, over the kinds in `kinds`\n * (`SHAPE_KINDS`). A kind that is not on offer falls back to `rectangle` when that is offered,\n * else to the first.\n */\nexport function shapeMenuModel(\n options: Partial<ShapeOptions>,\n kinds: readonly ShapeKind[]\n): ShapeMenuModel {\n const kind =\n options.kind !== undefined && kinds.includes(options.kind)\n ? options.kind\n : (kinds.find((k) => k === 'rectangle') ?? kinds[0] ?? 'rectangle')\n return {\n kind,\n label: `Shape: ${SHAPE_LABELS[kind]}`,\n items: kinds.map((k) => ({ kind: k, label: SHAPE_LABELS[k], checked: k === kind })),\n }\n}\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/** The thread popover's accessible name: \"Note thread\" for a note, \"Comment thread\" for markup. */\nexport function threadPopoverLabel(root: Pick<Annotation, 'type'>): string {\n return root.type === 'text' ? 'Note thread' : 'Comment thread'\n}\n\n/**\n * The thread popover's delete button. It removes the root and its replies, so on text markup\n * it says it deletes the highlight, not only the comment.\n */\nexport function threadDeleteLabel(root: Pick<Annotation, 'type'>): string {\n return root.type === 'text' ? 'Delete' : 'Delete highlight'\n}\n\n/** What a host-rendered comment thread receives: a note's, or text markup's. */\nexport interface ThreadPopoverSlotProps {\n root: NoteAnnotation | TextMarkupAnnotation\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\n/** The signature controls' words, shared so every binding announces the same names. */\nexport const SIGNATURE_LABELS = {\n /** The menu's group and main button. */\n sign: 'Sign',\n trigger: 'Choose signature',\n menu: 'Signatures',\n saved: 'Saved signatures',\n create: 'Create signature',\n /** The dialog's title. */\n dialog: 'Create signature',\n tabs: 'Signature source',\n draw: 'Draw',\n type: 'Type',\n image: 'Image',\n pad: 'Signature pad',\n clear: 'Clear',\n name: 'Name',\n namePlaceholder: 'Your name',\n fonts: 'Font',\n file: 'Image file',\n cancel: 'Cancel',\n save: 'Save',\n} as const\n\n/** The dialog's tabs, in order. */\nexport const SIGNATURE_TABS = ['draw', 'type', 'image'] as const\nexport type SignatureTab = (typeof SIGNATURE_TABS)[number]\n\nexport interface SignatureMenuItem {\n id: string\n /** `Signature 1`, `Signature 2`… in saved order. */\n label: string\n /** The remove button's accessible name. */\n removeLabel: string\n checked: boolean\n template: SignatureTemplate\n}\n\nexport interface SignatureMenuModel {\n /** The template the tool places, when it is still saved. */\n selected: SignatureTemplate | undefined\n items: SignatureMenuItem[]\n}\n\n/** What the signature menu shows for the saved templates and the signature tool's options. */\nexport function signatureMenuModel(\n templates: readonly SignatureTemplate[],\n options: SignatureOptions\n): SignatureMenuModel {\n const items = templates.map((template, i) => ({\n id: template.id,\n label: `Signature ${i + 1}`,\n removeLabel: `Remove signature ${i + 1}`,\n checked: template.id === options.templateId,\n template,\n }))\n return { selected: items.find((i) => i.checked)?.template, items }\n}\n","// Keyboard support the style menus share across the bindings and the vanilla factories. Items\n// are `[role=\"menuitemradio\"]` (or `menuitem`) buttons that are not focus stops themselves\n// (`tabindex=\"-1\"`): the menu moves focus between them, and Tab leaves the menu.\n//\n// An element with `data-ink-menu-columns=\"N\"` lays its items out as a grid N wide: ArrowLeft\n// and ArrowRight move within a row, ArrowUp and ArrowDown between rows, and past the first or\n// last row they carry on to the items before or after the grid.\n\nconst ITEMS =\n ':is([role=\"menuitemradio\"], [role=\"menuitem\"]):not(:disabled):not([aria-disabled=\"true\"])'\n\n/** The menu's enabled items in document order. */\nexport function menuItems(root: ParentNode): HTMLElement[] {\n return [...root.querySelectorAll<HTMLElement>(ITEMS)]\n}\n\n/** Focuses the first checked item, else the first enabled one. */\nexport function focusInitialMenuItem(root: ParentNode): void {\n const items = menuItems(root)\n const target =\n items.find((el) => el.getAttribute('aria-checked') === 'true') ?? items[0]\n target?.focus({ preventScroll: true })\n}\n\n/** The index to focus for a key, or -1 when the key means nothing here. */\nfunction nextIndex(key: string, items: HTMLElement[], i: number): number {\n const last = items.length - 1\n if (key === 'Home') return 0\n if (key === 'End') return last\n const grid = items[i]?.closest<HTMLElement>('[data-ink-menu-columns]')\n const cols = Number(grid?.dataset.inkMenuColumns)\n if (grid && cols > 0) {\n const cells = items.filter((el) => grid.contains(el))\n const first = items.indexOf(cells[0]!)\n const end = first + cells.length - 1\n const at = i - first\n if (key === 'ArrowRight')\n return at % cols === cols - 1 || at === cells.length - 1 ? i : i + 1\n if (key === 'ArrowLeft') return at % cols === 0 ? i : i - 1\n if (key === 'ArrowDown')\n return at + cols < cells.length ? i + cols : end === last ? 0 : end + 1\n if (key === 'ArrowUp')\n return at - cols >= 0 ? i - cols : first === 0 ? last : first - 1\n return -1\n }\n if (key === 'ArrowDown') return i < 0 || i === last ? 0 : i + 1\n if (key === 'ArrowUp') return i <= 0 ? last : i - 1\n return -1\n}\n\n/**\n * ArrowDown and ArrowUp move between enabled items and wrap; Home and End go to the ends.\n * Inside a grid the arrow keys move in both directions.\n */\nexport function handleMenuKeys(e: KeyboardEvent, root: ParentNode): void {\n if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey) return\n const items = menuItems(root)\n if (items.length === 0) return\n const next = nextIndex(\n e.key,\n items,\n items.indexOf(document.activeElement as HTMLElement)\n )\n if (next < 0) return\n e.preventDefault()\n items[next]!.focus({ preventScroll: true })\n}\n\n/**\n * Arrow keys inside a `role=\"radiogroup\"`: the next (or previous) enabled `role=\"radio\"`\n * takes focus and is chosen, wrapping at the ends, as a native radio group does.\n */\nexport function handleRadioKeys(e: KeyboardEvent, group: ParentNode): void {\n if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return\n const forward = e.key === 'ArrowRight' || e.key === 'ArrowDown'\n if (!forward && e.key !== 'ArrowLeft' && e.key !== 'ArrowUp') return\n const radios = [...group.querySelectorAll<HTMLElement>('[role=\"radio\"]:not(:disabled)')]\n const at = radios.indexOf(document.activeElement as HTMLElement)\n if (at < 0) return\n e.preventDefault()\n const next = radios[(at + (forward ? 1 : -1) + radios.length) % radios.length]!\n next.focus({ preventScroll: true })\n next.click()\n}\n\n/**\n * Arrow keys, Home and End inside a `role=\"tablist\"`: the next (or previous) enabled\n * `role=\"tab\"` takes focus and is chosen, wrapping at the ends.\n */\nexport function handleTabKeys(e: KeyboardEvent, tablist: ParentNode): void {\n if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return\n const tabs = [\n ...tablist.querySelectorAll<HTMLElement>(\n '[role=\"tab\"]:not(:disabled):not([aria-disabled=\"true\"])'\n ),\n ]\n const at = tabs.indexOf(document.activeElement as HTMLElement)\n if (at < 0) return\n const last = tabs.length - 1\n const next =\n e.key === 'ArrowRight' || e.key === 'ArrowDown'\n ? at === last\n ? 0\n : at + 1\n : e.key === 'ArrowLeft' || e.key === 'ArrowUp'\n ? at === 0\n ? last\n : at - 1\n : e.key === 'Home'\n ? 0\n : e.key === 'End'\n ? last\n : -1\n if (next < 0) return\n e.preventDefault()\n tabs[next]!.focus({ preventScroll: true })\n tabs[next]!.click()\n}\n\nconst TABBABLE = [\n 'a[href]',\n 'button:not(:disabled)',\n 'input:not(:disabled):not([type=\"hidden\"])',\n 'select:not(:disabled)',\n 'textarea:not(:disabled)',\n '[tabindex]',\n]\n .map((s) => `${s}:not([tabindex=\"-1\"])`)\n .join(', ')\n\n/**\n * Keeps Tab inside `container`, a modal: Tab from its last stop goes to its first, and\n * Shift+Tab from the first to the last.\n */\nexport function trapTab(e: KeyboardEvent, container: HTMLElement): void {\n if (e.key !== 'Tab' || e.defaultPrevented) return\n const stops = [...container.querySelectorAll<HTMLElement>(TABBABLE)].filter(\n (el) => !el.matches(':disabled') && el.getClientRects().length > 0\n )\n if (stops.length === 0) {\n e.preventDefault()\n return\n }\n const first = stops[0]!\n const last = stops[stops.length - 1]!\n const active = document.activeElement\n if (e.shiftKey && (active === first || !container.contains(active))) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && (active === last || !container.contains(active))) {\n e.preventDefault()\n first.focus()\n }\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'\nimport {\n createMemorySignatureStore,\n createSignatureLibrary,\n type SignatureLibrary,\n type SignatureStore,\n} from '../model/signatures'\n\nimport { createPageMount, type PageLayer, type PageMount } from './page-mount'\nimport { getSelectionQuads } from './selection'\nimport {\n createToolController,\n createToolOptions,\n trackToolStyle,\n withHostTools,\n type Tool,\n type ToolController,\n type ToolId,\n type ToolOptions,\n} from './tools'\nimport { FONT_FAMILIES, SIGNATURE_FONTS } from './ui'\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 { ToolStyle } from '../model/annotations/tool-style'\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 /**\n * Host tools, added to the built-ins. A host tool with a built-in's id replaces it. The same\n * instances are reused when the engine rebuilds.\n */\n tools?: Tool[]\n /**\n * The tools' options (the shape kind, the highlight kind…). A binding or `createViewer` passes\n * one it keeps for its own life, so options persist across documents, as for the life of the\n * viewer. By default the engine makes one, which lasts as long as the engine.\n */\n toolOptions?: ToolOptions\n /**\n * The style the tools create with. A binding passes its own, made with `trackToolStyle` and\n * its own history (and keeps its active group in step with the tool). By default the engine\n * makes one over the document's history.\n */\n toolStyle?: ToolStyle\n /**\n * The history the tools group a gesture's changes with (a group move, a sketch's swap to its\n * shape). A binding passes its own, so a controlled host's undo steps match the gesture. By\n * default the document's history.\n */\n toolHistory?: { batch(fn: () => void): void }\n /**\n * The font families text boxes offer, replacing the default `FONT_FAMILIES` (the PDF\n * standard families). Fonts beyond those are the PDF writer's to embed.\n */\n fonts?: string[]\n /**\n * Where signature templates live. Default: memory, gone on reload\n * (`createMemorySignatureStore`). `createLocalSignatureStore` keeps them in the browser.\n */\n signatures?: SignatureStore\n /**\n * The templates the `signature` tool and the signature controls share. A binding or\n * `createViewer` passes its own, so they outlive one document; it wins over `signatures`.\n * A function is read each time the library is needed, so a host that swaps its library\n * after mount reaches the tool too.\n */\n signatureLibrary?: SignatureLibrary | (() => SignatureLibrary)\n /**\n * The handwriting fonts a typed signature offers. The host loads them (`@font-face`).\n * Default `SIGNATURE_FONTS`.\n */\n signatureFonts?: string[]\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 /**\n * The style each group creates with, shared by the tools and the style controls. It lives as\n * long as the engine, across rebuilds.\n */\n readonly toolStyle: ToolStyle\n /** The font families text boxes offer: the `fonts` option, else `FONT_FAMILIES`. */\n readonly fonts: readonly string[]\n /** The signature templates: the host's current library, or the engine's own. */\n readonly signatures: SignatureLibrary\n /** The fonts a typed signature offers: the `signatureFonts` option, else `SIGNATURE_FONTS`. */\n readonly signatureFonts: readonly string[]\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 stopActive: () => void = () => undefined\n let destroyed = false\n const hostTools = opts.tools ?? []\n /** Option values outlive rebuilds: every controller shares this registry. */\n const toolOptions = opts.toolOptions ?? createToolOptions()\n /** Without a host style, the engine's own follows the active tool across rebuilds. */\n const tracker = opts.toolStyle\n ? undefined\n : trackToolStyle({\n store: doc.annotations,\n history: opts.toolHistory ?? doc.history,\n tools: hostTools,\n tool: opts.tool,\n })\n const toolStyle = opts.toolStyle ?? (tracker as NonNullable<typeof tracker>).toolStyle\n const host = opts.signatureLibrary\n const own = host\n ? undefined\n : createSignatureLibrary(opts.signatures ?? createMemorySignatureStore())\n /** The library now: a host getter is read each time, so a swapped library takes effect. */\n const signatures = (): SignatureLibrary =>\n typeof host === 'function' ? host() : (host ?? (own as SignatureLibrary))\n void signatures().refresh()\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 list = withHostTools(hostTools)\n const tc = createToolController({\n ...(state.tool === undefined ? {} : { initial: state.tool }),\n tools: list,\n options: toolOptions,\n ctx: {\n toolStyle,\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 history: opts.toolHistory ?? doc.history,\n get signatures() {\n return signatures()\n },\n },\n })\n viewport = vp\n tools = tc\n if (tracker) {\n tracker.setTool(tc.active.get())\n stopActive = tc.active.subscribe((id) => tracker.setTool(id))\n }\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 stopActive()\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 toolStyle,\n fonts: opts.fonts ? [...opts.fonts] : FONT_FAMILIES,\n get signatures() {\n return signatures()\n },\n signatureFonts: opts.signatureFonts ? [...opts.signatureFonts] : SIGNATURE_FONTS,\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\n/**\n * Fixed-positions `panel` below `anchor` (above it when only that fits), clamped to the\n * window. Shared by the annotation popovers and the trigger-anchored menus.\n */\nexport function placePanel(panel: HTMLElement, anchor: DOMRect): void {\n const { innerWidth: vw, innerHeight: vh } = window\n const w = panel.offsetWidth\n const ht = panel.offsetHeight\n let top = anchor.bottom + GAP\n if (top + ht > vh - MARGIN && anchor.top - GAP - ht >= MARGIN)\n top = anchor.top - GAP - ht\n top = Math.max(MARGIN, Math.min(top, vh - ht - MARGIN))\n const left = Math.max(MARGIN, Math.min(anchor.left, vw - w - MARGIN))\n panel.style.position = 'fixed'\n panel.style.left = `${left}px`\n panel.style.top = `${top}px`\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 placePanel(panel, anchor.getBoundingClientRect())\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 * 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 thread for the activated note or text markup, anchored to the root's overlay element.\n * Activating a reply opens the whole thread from its root. Closing (Close, Escape, a press\n * outside) clears the activation.\n *\n * A new note, or a highlight, has no text. While its root is empty (and unlocked) the form\n * writes the root's own `contents`, labelled \"Comment\", and the thread list stays hidden until\n * there is something in it; after that the form adds replies. A note closed, or left for\n * another annotation, while still empty and without replies is removed; markup stays, since\n * the mark is the point. The thread list re-renders on every store change; the form, and the\n * draft in it, stays until the popover moves to another thread or the root is gone.\n */\nimport {\n isAbandonedNote,\n isThreadRoot,\n threadOf,\n threadRoot,\n type ThreadRoot,\n} from '../../model/annotations/threads'\nimport { threadDeleteLabel, threadPopoverLabel } from '../ui'\n\nimport { button, h } from './dom'\nimport { createPopover } from './popover'\n\nimport type { AnnotationStore } from '../../model/annotations/store'\nimport type { Annotation } from '../../model/annotations/types'\nimport type { Writable } from '../../model/readable'\nimport type { FocusReturn } from '../popover-focus'\n\nexport interface ThreadPopoverOptions {\n root: HTMLElement\n store: AnnotationStore\n activated: Writable<string | null>\n focusReturn: FocusReturn\n}\n\nexport function createThreadPopover(opts: ThreadPopoverOptions): { destroy(): void } {\n const { root, store, activated, focusReturn } = opts\n const popover = createPopover({\n root,\n attrs: {\n class: 'ink-thread-popover',\n 'data-ink-thread-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 thread root shown now. */\n let current: string | null = null\n /** Roots 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(): ThreadRoot | null {\n const a = current ? store.get(current) : undefined\n return a && isThreadRoot(a) ? a : null\n }\n\n function target(): ThreadRoot | 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 ? threadRoot(list, a) : null\n }\n\n const editingRoot = (n: ThreadRoot): boolean => !n.locked && !n.contents?.trim()\n\n /** A note that closing now would remove. */\n function isEmptyRoot(n: ThreadRoot): boolean {\n return !written.has(n.id) && isAbandonedNote(n, store.list.get())\n }\n\n function dropIfEmpty(id: string): void {\n const list = store.list.get()\n const a = list.find((x) => x.id === id)\n if (!a || dropped.has(id) || written.has(id) || !isAbandonedNote(a, list)) return\n dropped.add(id)\n store.remove(id)\n }\n\n function renderThread(n: ThreadRoot): 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 popover.panel.setAttribute('aria-label', threadPopoverLabel(n))\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 roots 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 root's state: \"Comment\" while its own text is empty, \"Reply\" after. */\n sync(n: ThreadRoot): void\n}\n\nfunction createThreadForm(\n n: ThreadRoot,\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(threadDeleteLabel(n), 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(root: ThreadRoot): void {\n const label = !root.locked && !root.contents?.trim() ? 'Comment' : 'Reply'\n textarea.setAttribute('aria-label', label)\n textarea.placeholder = label\n send.textContent = label\n if (root.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 * 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 {\n createMemorySignatureStore,\n createSignatureLibrary,\n} from '../../model/signatures'\nimport { createFocusReturn } from '../popover-focus'\nimport { createToolOptions } from '../tools'\nimport { mountViewer, type MountViewerOptions, type ViewerEngine } from '../viewer-engine'\n\nimport { h } from './dom'\nimport { createSuggestionCard } from './suggestion-card'\nimport { createThreadPopover } from './thread-popover'\n\nimport type { DocumentSource } from '../../model/source'\nimport type { PdfAssets } from '../../pdfjs/types'\nimport type { ToolController } from '../tools'\nimport type { Viewport } from '../viewport'\n\n/**\n * The engine options, less what the viewer owns: the container, the document, the tool style\n * (bound to one document's store, so each engine makes its own), and the tool options and\n * signature library (one for the viewer's life).\n */\nexport interface CreateViewerOptions extends Omit<\n MountViewerOptions,\n | 'container'\n | 'document'\n | 'toolStyle'\n | 'toolHistory'\n | 'toolOptions'\n | 'signatureLibrary'\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 /** The thread popover for notes and text markup. Default true. */\n threads?: 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 threads: withThreads = true,\n suggestions: withSuggestions = true,\n onReady,\n onError,\n onActivate,\n onBuild,\n onPageMount,\n onPageUnmount,\n onPageError,\n // Not options (see the type), but a caller without types could still pass them.\n toolStyle: _toolStyle,\n toolOptions: _toolOptions,\n signatureLibrary: _signatureLibrary,\n signatures: signatureStore,\n ...view\n } = opts as CreateViewerOptions &\n Pick<MountViewerOptions, 'toolStyle' | 'toolOptions' | 'signatureLibrary'>\n /** One library for the viewer's life, so templates and the menu outlive each document. */\n const signatures = createSignatureLibrary(\n signatureStore ?? createMemorySignatureStore()\n )\n /** Tool options persist for the viewer's life; the tool style is per document. */\n const toolOptions = createToolOptions()\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 withThreads ? createThreadPopover({ 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 toolOptions,\n signatureLibrary: signatures,\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 Highlighter,\n ICON_ATTRIBUTES,\n MessageSquare,\n PenLine,\n PenTool,\n Signature,\n Redo2,\n Square,\n SquareDashedMousePointer,\n TextCursor,\n Type,\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<Partial<Record<ToolId, IconNode>>> = {\n 'select-text': TextCursor,\n select: SquareDashedMousePointer,\n highlight: Highlighter,\n 'redact-area': Square,\n sketch: PenTool,\n draw: PenLine,\n note: MessageSquare,\n freetext: Type,\n signature: Signature,\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 | undefined\n): HTMLButtonElement {\n const b = h('button', { type: 'button', ...attrs, 'aria-label': label, title: label })\n if (icon) 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/**\n * Sets the tool; pressed while it is the active one. A host tool's button has no icon (append\n * your own) and is named by `label`, else by the tool id.\n */\nexport function createToolButton(\n viewer: Viewer,\n tool: ToolId,\n opts: { label?: string } = {}\n): HTMLButtonElement {\n const label = opts.label ?? TOOL_LABELS[tool] ?? 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","/*\n * A menu anchored to a trigger button, shared by the vanilla style controls. The shell owns\n * the panel (`role=\"menu\"`, created on open and removed on close), its placement (the\n * popover's), and dismissal: an outside press, focus leaving, or Escape (which returns focus\n * to the trigger). ArrowDown on the trigger opens it with the first enabled item focused.\n * It closes when the trigger becomes disabled. Items are `[role=\"menuitemradio\"]` buttons;\n * ArrowUp, ArrowDown, Home and End move between them.\n */\nimport { focusInitialMenuItem, handleMenuKeys, menuItems } from '../menu-keys'\n\nimport { h } from './dom'\nimport { placePanel } from './popover'\n\nexport interface MenuOptions {\n label: string\n /** Extra attributes for the panel. */\n attrs?: Record<string, string>\n /**\n * The panel's role. `menu` (the default) is a list of items with arrow-key movement; `dialog`\n * is for a panel of mixed widgets, which take Tab and their own keys, and opens on the first\n * focusable one.\n */\n role?: 'menu' | 'dialog'\n /**\n * Whether `target` belongs to a menu nested in this one (its panel sits outside this panel\n * in the DOM). Presses, focus and Escape inside it neither dismiss this menu nor close it.\n */\n owns?(target: Node): boolean\n /** Builds the items on first call and updates them in place after; called on open and `refresh`. */\n render(menu: HTMLElement): void\n}\n\nexport interface Menu {\n readonly isOpen: boolean\n /** Re-renders an open menu, and closes it if the trigger has become disabled. */\n refresh(): void\n close(restoreFocus?: boolean): void\n}\n\nconst FOCUSABLE =\n 'select:not(:disabled), input:not(:disabled), button:not(:disabled):not([tabindex=\"-1\"])'\n\nexport function createMenu(trigger: HTMLButtonElement, opts: MenuOptions): Menu {\n const role = opts.role ?? 'menu'\n let panel: HTMLElement | null = null\n let teardown: (() => void) | null = null\n\n const place = (): void => {\n if (panel) placePanel(panel, trigger.getBoundingClientRect())\n }\n\n function close(restoreFocus = false): void {\n if (!panel) return\n teardown?.()\n teardown = null\n panel.remove()\n panel = null\n trigger.setAttribute('aria-expanded', 'false')\n trigger.dataset.state = 'closed'\n if (restoreFocus) trigger.focus()\n }\n\n function open(focus: 'initial' | 'first'): void {\n if (panel || trigger.disabled) return\n const el = h('div', {\n role,\n 'aria-label': opts.label,\n class: 'ink-select-content ink-menu-content',\n 'data-ink-select-content': '',\n ...opts.attrs,\n })\n panel = el\n el.style.visibility = 'hidden'\n document.body.append(el)\n opts.render(el)\n place()\n el.style.visibility = ''\n trigger.setAttribute('aria-expanded', 'true')\n trigger.dataset.state = 'open'\n if (role === 'dialog')\n el.querySelector<HTMLElement>(FOCUSABLE)?.focus({ preventScroll: true })\n else if (focus === 'first') menuItems(el)[0]?.focus({ preventScroll: true })\n else focusInitialMenuItem(el)\n\n const onKey = (e: KeyboardEvent): void => {\n const nested = opts.owns?.(e.target as Node) === true\n if (e.key === 'Escape') {\n // The nested menu closes itself; this one stays.\n if (nested) return\n e.preventDefault()\n close(true)\n } else if (role === 'menu' && el.contains(e.target as Node)) handleMenuKeys(e, el)\n }\n const outside = (t: Node): boolean =>\n !el.contains(t) && !trigger.contains(t) && opts.owns?.(t) !== true\n const onPress = (e: PointerEvent): void => {\n if (outside(e.target as Node)) close()\n }\n const onFocus = (e: FocusEvent): void => {\n if (outside(e.target as Node)) close()\n }\n document.addEventListener('keydown', onKey, true)\n document.addEventListener('pointerdown', onPress, true)\n document.addEventListener('focusin', onFocus)\n window.addEventListener('resize', place)\n document.addEventListener('scroll', place, true)\n teardown = () => {\n document.removeEventListener('keydown', onKey, true)\n document.removeEventListener('pointerdown', onPress, true)\n document.removeEventListener('focusin', onFocus)\n window.removeEventListener('resize', place)\n document.removeEventListener('scroll', place, true)\n }\n }\n\n trigger.addEventListener('click', () => (panel ? close(true) : open('initial')))\n trigger.addEventListener('keydown', (e) => {\n // An enclosing menu that already moved focus on this key keeps it.\n if (e.key !== 'ArrowDown' || e.defaultPrevented || panel || trigger.disabled) return\n e.preventDefault()\n open('first')\n })\n\n return {\n get isOpen() {\n return panel !== null\n },\n refresh() {\n if (!panel) return\n if (trigger.disabled) close()\n else {\n opts.render(panel)\n place()\n }\n },\n close,\n }\n}\n","/*\n * The line style menu for createViewer: the same markup, classes and data attributes as the\n * bindings' `InkLineStyleMenu`, so `@inkbar/theme` styles both. The trigger follows the\n * viewer's tool style (disabled while nothing supports line style, `data-mixed` when the\n * selection disagrees); the panel is created on open and removed on close.\n */\nimport { Check, Minus } from '@inkbar/icons'\n\nimport { lineStyleMenuModel, type LineStyleMenuModel } from '../ui'\n\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\n\nimport type { Viewer } from './create-viewer'\nimport type { ToolStyle } from '../../model/annotations/tool-style'\n\n/** A button that opens the line style menu: weight, solid or dashed, and arrowheads. */\nexport function createLineStyleMenu(viewer: Viewer): HTMLButtonElement {\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-line-style-menu',\n 'data-ink-line-style-menu': '',\n 'data-state': 'closed',\n 'aria-label': 'Line style',\n title: 'Line style',\n 'aria-haspopup': 'menu',\n 'aria-expanded': 'false',\n })\n trigger.append(createIcon(Minus))\n trigger.disabled = true\n\n let style: ToolStyle | null = null\n let stops: (() => void)[] = []\n\n const model = (): LineStyleMenuModel =>\n lineStyleMenuModel(style?.current.get() ?? {}, style?.supported.get() ?? new Set())\n\n function refresh(): void {\n const m = model()\n trigger.disabled = !m.enabled\n if (m.mixed) trigger.setAttribute('data-mixed', '')\n else trigger.removeAttribute('data-mixed')\n menu.refresh()\n }\n\n /** Builds the panel's sections on the first call; later calls update them in place. */\n function paint(root: HTMLElement, m: LineStyleMenuModel): void {\n const menu = root\n if (menu.childElementCount === 0) {\n for (const section of m.sections) {\n const group = h(\n 'div',\n { role: 'group', class: 'ink-menu-group', 'aria-label': section.label },\n h('div', { class: 'ink-menu-label', 'aria-hidden': 'true' }, section.label)\n )\n for (const item of section.items) {\n const b = h(\n 'button',\n {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-select-item ink-menu-item',\n 'data-ink-select-item': '',\n tabindex: '-1',\n 'data-key': item.key,\n },\n item.label\n )\n b.addEventListener('click', () => {\n const found = model()\n .sections.flatMap((s) => s.items)\n .find((i) => i.key === item.key && i.label === item.label)\n if (found) style?.set(found.patch)\n })\n group.append(b)\n }\n menu.append(group)\n }\n }\n m.sections.forEach((section, i) => {\n const group = menu.children[i] as HTMLElement\n group.toggleAttribute('data-disabled', section.disabled)\n if (section.disabled) group.setAttribute('aria-disabled', 'true')\n else group.removeAttribute('aria-disabled')\n section.items.forEach((item, j) => {\n const b = group.children[j + 1] as HTMLButtonElement\n b.disabled = section.disabled\n b.setAttribute('aria-checked', String(item.checked))\n b.dataset.state = item.checked ? 'checked' : 'unchecked'\n const mark = b.querySelector('.ink-select-indicator')\n if (item.checked && !mark) {\n const span = h('span', { class: 'ink-select-indicator' })\n span.append(createIcon(Check))\n b.append(span)\n } else if (!item.checked) mark?.remove()\n })\n })\n }\n\n const menu = createMenu(trigger, {\n label: 'Line style',\n attrs: { 'data-ink-menu': 'line-style' },\n render: (root) => paint(root, model()),\n })\n\n const follow = (engine: { toolStyle: ToolStyle } | null): void => {\n for (const stop of stops) stop()\n stops = []\n style = engine?.toolStyle ?? null\n if (style)\n stops = [style.current.subscribe(refresh), style.supported.subscribe(refresh)]\n // The panel's old style is gone with the old document.\n if (!style) menu.close()\n refresh()\n }\n follow(viewer.engine.get())\n viewer.engine.subscribe(follow)\n return trigger\n}\n","/*\n * The colour menus for createViewer: the same markup, classes and data attributes as the\n * bindings' `InkColorMenu`, so `@inkbar/theme` styles both. The trigger shows the current\n * colour as a swatch and follows the viewer's tool style (disabled while nothing supports the\n * property); the panel is created on open and removed on close.\n */\nimport { Check } from '@inkbar/icons'\n\nimport {\n COLOR_COLUMNS,\n colorMenuModel,\n type ColorMenuModel,\n type ColorProperty,\n} from '../ui'\n\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\n\nimport type { Viewer } from './create-viewer'\nimport type {\n CurrentStyle,\n StyleGroup,\n StyleKey,\n StyleProps,\n ToolStyle,\n} from '../../model/annotations/tool-style'\nimport type { Readable } from '../../model/readable'\n\nexport interface ColorMenuOptions {\n property: ColorProperty\n /** Accessible name; defaults to \"Border colour\", \"Fill colour\" or \"Text colour\". */\n label?: string\n /**\n * Scopes the menu to one style group (`ToolStyle.scoped`): it shows and sets that group's\n * colour whatever tool is active, and recolours the selection only when it is all in the group.\n */\n group?: StyleGroup\n}\n\n/** Sets a swatch element's kind and colour from the model's trigger. */\nfunction paintSwatch(swatch: HTMLElement, model: ColorMenuModel): void {\n const t = model.trigger\n swatch.dataset.kind = t.kind\n if (t.kind === 'color') {\n swatch.dataset.color = t.color\n swatch.style.setProperty('--ink-swatch', t.color)\n } else {\n delete swatch.dataset.color\n swatch.style.removeProperty('--ink-swatch')\n }\n}\n\nfunction checkmark(): HTMLElement {\n const span = h('span', { class: 'ink-select-indicator' })\n span.append(createIcon(Check))\n return span\n}\n\n/** A button that opens a colour menu for one colour property of the selection or tool. */\nexport function createColorMenu(\n viewer: Viewer,\n opts: ColorMenuOptions\n): HTMLButtonElement {\n const { property } = opts\n const name = opts.label ?? colorMenuModel(property, {}, new Set()).label\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-color-menu',\n 'data-ink-color-menu': property,\n 'data-state': 'closed',\n 'aria-label': name,\n title: name,\n 'aria-haspopup': 'menu',\n 'aria-expanded': 'false',\n })\n const swatch = h('span', {\n class: 'ink-swatch',\n 'data-ink-swatch': '',\n 'data-property': property,\n 'aria-hidden': 'true',\n })\n trigger.append(swatch)\n trigger.disabled = true\n\n /** What the menu reads and writes: the whole tool style, or one group's view of it. */\n let style: {\n current: Readable<CurrentStyle>\n supported: Readable<ReadonlySet<StyleKey>>\n set(patch: StyleProps): void\n } | null = null\n let stops: (() => void)[] = []\n\n const model = (): ColorMenuModel =>\n colorMenuModel(\n property,\n style?.current.get() ?? {},\n style?.supported.get() ?? new Set()\n )\n\n function refresh(): void {\n const m = model()\n trigger.disabled = !m.enabled\n if (m.mixed) trigger.setAttribute('data-mixed', '')\n else trigger.removeAttribute('data-mixed')\n paintSwatch(swatch, m)\n if (picker && !trigger.isConnected) picker.remove()\n menu.refresh()\n }\n\n /**\n * The native colour input lives beside the trigger, not in the panel: the panel is removed\n * when the menu closes, and a pick that arrives after that must still land. Created on\n * first use and reused.\n */\n let picker: HTMLInputElement | null = null\n function pickerInput(): HTMLInputElement {\n if (!picker) {\n picker = h('input', {\n type: 'color',\n class: 'ink-color-input',\n 'aria-label': 'Custom colour',\n 'data-ink-color-input': property,\n tabindex: '-1',\n })\n picker.addEventListener('change', () => style?.set(model().custom(picker!.value)))\n }\n picker.value = model().customValue.toLowerCase()\n if (picker.parentNode !== trigger.parentNode || !picker.isConnected)\n if (trigger.parentNode) trigger.after(picker)\n else document.body.append(picker)\n return picker\n }\n\n function paint(root: HTMLElement, m: ColorMenuModel): void {\n if (root.childElementCount === 0) {\n if (m.noFill) {\n const b = h(\n 'button',\n {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-select-item ink-menu-item',\n 'data-ink-select-item': '',\n 'data-key': 'no-fill',\n tabindex: '-1',\n },\n 'No fill'\n )\n b.addEventListener('click', () => {\n const found = model().noFill\n if (found) style?.set(found.patch)\n })\n root.append(b)\n }\n const grid = h('div', {\n role: 'group',\n 'aria-label': 'Colours',\n class: 'ink-color-grid',\n 'data-ink-menu-columns': String(COLOR_COLUMNS),\n })\n for (const sw of m.swatches) {\n const b = h('button', {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-swatch-item',\n 'aria-label': sw.label,\n 'data-key': sw.key,\n tabindex: '-1',\n })\n b.style.setProperty('--ink-swatch', sw.color)\n b.addEventListener('click', () => {\n const found = model().swatches.find((s) => s.key === sw.key)\n if (found) style?.set(found.patch)\n })\n grid.append(b)\n }\n root.append(grid)\n const custom = h(\n 'button',\n {\n type: 'button',\n role: 'menuitem',\n class: 'ink-select-item ink-menu-item',\n 'data-ink-select-item': '',\n 'data-key': 'custom',\n tabindex: '-1',\n },\n 'Custom…'\n )\n custom.addEventListener('click', () => pickerInput().click())\n root.append(custom)\n }\n const noFill = root.querySelector<HTMLElement>('[data-key=\"no-fill\"]')\n if (noFill && m.noFill) mark(noFill, m.noFill.checked, true)\n const cells = root.querySelectorAll<HTMLElement>('.ink-swatch-item')\n m.swatches.forEach((sw, i) => mark(cells[i]!, sw.checked, false))\n if (picker) picker.value = m.customValue.toLowerCase()\n }\n\n /** Reflects checked state on an item; `withMark` adds the check icon (labelled items). */\n function mark(el: HTMLElement, checked: boolean, withMark: boolean): void {\n el.setAttribute('aria-checked', String(checked))\n el.dataset.state = checked ? 'checked' : 'unchecked'\n if (!withMark) return\n const existing = el.querySelector('.ink-select-indicator')\n if (checked && !existing) el.append(checkmark())\n else if (!checked) existing?.remove()\n }\n\n const menu = createMenu(trigger, {\n label: opts.label ?? model().label,\n attrs: { 'data-ink-menu': `color-${property}` },\n render: (root) => paint(root, model()),\n })\n\n const follow = (engine: { toolStyle: ToolStyle } | null): void => {\n for (const stop of stops) stop()\n stops = []\n const tool = engine?.toolStyle ?? null\n style = tool && opts.group ? tool.scoped(opts.group) : tool\n if (style)\n stops = [style.current.subscribe(refresh), style.supported.subscribe(refresh)]\n if (!style) menu.close()\n refresh()\n }\n follow(viewer.engine.get())\n viewer.engine.subscribe(follow)\n return trigger\n}\n","/*\n * The text style menu for createViewer: the same markup, classes and data attributes as the\n * bindings' `InkTextStyleMenu`, so `@inkbar/theme` styles both. The trigger follows the\n * viewer's tool style (disabled while nothing supports text style, `data-mixed` when the\n * selection disagrees); the panel is created on open and removed on close. It holds a font\n * select, the text colour menu, a size input with a stepper, bold/italic/underline toggles\n * and an alignment radio group.\n */\nimport {\n ALargeSmall,\n AlignCenter,\n AlignJustify,\n AlignLeft,\n AlignRight,\n Bold,\n Italic,\n Minus,\n Plus,\n Underline,\n} from '@inkbar/icons'\n\nimport { handleRadioKeys } from '../menu-keys'\nimport { FONT_FAMILIES, textStyleMenuModel, type TextStyleMenuModel } from '../ui'\n\nimport { createColorMenu } from './color-menu'\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\n\nimport type { Viewer } from './create-viewer'\nimport type { ToolStyle } from '../../model/annotations/tool-style'\n\nconst TOGGLE_ICONS = { bold: Bold, italic: Italic, underline: Underline }\nconst ALIGN_ICONS = {\n left: AlignLeft,\n center: AlignCenter,\n right: AlignRight,\n justify: AlignJustify,\n}\n\nfunction iconButton(label: string, icon: Parameters<typeof createIcon>[0]) {\n const b = h('button', {\n type: 'button',\n class: 'ink-text-style-button',\n 'aria-label': label,\n title: label,\n })\n const svg = createIcon(icon)\n svg.setAttribute('width', '16')\n svg.setAttribute('height', '16')\n b.append(svg)\n return b\n}\n\n/** A button that opens the text style menu: font, size, colour, emphasis and alignment. */\nexport function createTextStyleMenu(viewer: Viewer): HTMLButtonElement {\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-text-style-menu',\n 'data-ink-text-style-menu': '',\n 'data-state': 'closed',\n 'aria-label': 'Text style',\n title: 'Text style',\n 'aria-haspopup': 'dialog',\n 'aria-expanded': 'false',\n })\n trigger.append(createIcon(ALargeSmall))\n trigger.disabled = true\n\n let style: ToolStyle | null = null\n let stops: (() => void)[] = []\n\n const model = (): TextStyleMenuModel =>\n textStyleMenuModel(\n style?.current.get() ?? {},\n style?.supported.get() ?? new Set(),\n viewer.engine.get()?.fonts ?? FONT_FAMILIES\n )\n\n // One text colour menu for the life of the control; each panel adopts its trigger.\n const colour = createColorMenu(viewer, { property: 'textColor' })\n\n let select: HTMLSelectElement | null = null\n let input: HTMLInputElement | null = null\n /** True while the size holds text the user has typed and not yet committed. */\n let drafting = false\n\n function commitSize(): void {\n if (!drafting || !input) return\n drafting = false\n if (input.value.trim() !== '') {\n const patch = model().size.commit(Number(input.value))\n if (patch) style?.set(patch)\n }\n input.value = model().size.value === null ? '' : String(model().size.value)\n }\n function nudge(direction: 1 | -1): void {\n drafting = false\n const patch = model().size.nudge(direction)\n if (patch) style?.set(patch)\n }\n\n function build(root: HTMLElement, m: TextStyleMenuModel): void {\n select = h('select', { class: 'ink-text-style-font', 'aria-label': m.font.label })\n select.addEventListener('change', () => style?.set(model().font.patch(select!.value)))\n\n input = h('input', {\n type: 'number',\n class: 'ink-text-style-input',\n 'aria-label': m.size.label,\n min: String(m.size.min),\n max: String(m.size.max),\n step: String(m.size.step),\n })\n input.addEventListener('input', () => (drafting = true))\n input.addEventListener('blur', commitSize)\n input.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter') return\n e.preventDefault()\n commitSize()\n })\n const less = iconButton('Decrease font size', Minus)\n const more = iconButton('Increase font size', Plus)\n less.addEventListener('click', () => nudge(-1))\n more.addEventListener('click', () => nudge(1))\n const size = h(\n 'div',\n { class: 'ink-text-style-size', role: 'group', 'aria-label': 'Size' },\n less,\n input,\n more\n )\n\n const emphasis = h('div', {\n class: 'ink-text-style-row',\n role: 'group',\n 'aria-label': 'Emphasis',\n })\n for (const t of m.toggles) {\n const b = iconButton(t.label, TOGGLE_ICONS[t.key])\n b.dataset.key = t.key\n b.addEventListener('click', () => {\n const found = model().toggles.find((x) => x.key === t.key)\n if (found) style?.set(found.patch)\n })\n emphasis.append(b)\n }\n\n const align = h('div', {\n class: 'ink-text-style-row',\n role: 'radiogroup',\n 'aria-label': m.align.label,\n })\n align.addEventListener('keydown', (e) => handleRadioKeys(e, align))\n for (const c of m.align.choices) {\n const b = iconButton(c.label, ALIGN_ICONS[c.key])\n b.setAttribute('role', 'radio')\n b.dataset.key = c.key\n b.addEventListener('click', () => {\n const found = model().align.choices.find((x) => x.key === c.key)\n if (found) style?.set(found.patch)\n })\n align.append(b)\n }\n\n root.append(\n select,\n h('div', { class: 'ink-text-style-row' }, colour, size),\n emphasis,\n align\n )\n }\n\n function paint(root: HTMLElement, m: TextStyleMenuModel): void {\n if (root.childElementCount === 0) build(root, m)\n const sel = select!\n const options = m.font.value === '' ? ['', ...m.font.options] : m.font.options\n if (\n sel.options.length !== options.length ||\n options.some((o, i) => sel.options[i]!.value !== o)\n ) {\n sel.replaceChildren(\n ...options.map((o) => {\n const opt = h('option', { value: o }, o === '' ? 'Mixed' : o)\n if (o === '') {\n opt.disabled = true\n opt.hidden = true\n }\n return opt\n })\n )\n }\n sel.value = m.font.value\n if (!drafting) input!.value = m.size.value === null ? '' : String(m.size.value)\n root\n .querySelectorAll<HTMLElement>('[role=\"group\"][aria-label=\"Emphasis\"] button')\n .forEach((b) => {\n const t = m.toggles.find((x) => x.key === b.dataset.key)!\n b.setAttribute('aria-pressed', String(t.pressed))\n b.dataset.state = t.pressed === true ? 'on' : 'off'\n if (t.pressed === 'mixed') b.setAttribute('data-mixed', '')\n else b.removeAttribute('data-mixed')\n })\n root.querySelectorAll<HTMLElement>('[role=\"radio\"]').forEach((b) => {\n const c = m.align.choices.find((x) => x.key === b.dataset.key)!\n b.setAttribute('aria-checked', String(c.checked))\n b.dataset.state = c.checked ? 'on' : 'off'\n b.tabIndex = c.tabStop ? 0 : -1\n })\n }\n\n function refresh(): void {\n const m = model()\n trigger.disabled = !m.enabled\n if (m.mixed) trigger.setAttribute('data-mixed', '')\n else trigger.removeAttribute('data-mixed')\n menu.refresh()\n }\n\n const menu = createMenu(trigger, {\n label: 'Text style',\n role: 'dialog',\n attrs: {\n 'data-ink-menu': 'text-style',\n class: 'ink-select-content ink-menu-content ink-text-style-content',\n },\n owns: (t) =>\n t instanceof Element && t.closest('[data-ink-menu=\"color-textColor\"]') !== null,\n render: (root) => paint(root, model()),\n })\n\n const follow = (engine: { toolStyle: ToolStyle } | null): void => {\n for (const stop of stops) stop()\n stops = []\n style = engine?.toolStyle ?? null\n if (style)\n stops = [style.current.subscribe(refresh), style.supported.subscribe(refresh)]\n // The panel's old style is gone with the old document.\n if (!style) menu.close()\n refresh()\n }\n follow(viewer.engine.get())\n viewer.engine.subscribe(follow)\n return trigger\n}\n","// The icon each shape kind draws in the shape menu, shared by the vanilla menu and the\n// framework bindings so a kind has one icon everywhere.\nimport {\n Circle,\n CircleDashed,\n Hexagon,\n MessageCircle,\n MoveUpRight,\n RectangleHorizontal,\n Search,\n Slash,\n Square,\n SquareDashed,\n Star,\n type IconNode,\n} from '@inkbar/icons'\n\nimport type { ShapeKind } from './tools'\n\nexport const SHAPE_ICONS: Readonly<Record<ShapeKind, IconNode>> = {\n line: Slash,\n arrow: MoveUpRight,\n rectangle: Square,\n roundedRectangle: RectangleHorizontal,\n ellipse: Circle,\n bubble: MessageCircle,\n star: Star,\n polygon: Hexagon,\n loupe: Search,\n mask: SquareDashed,\n ovalMask: CircleDashed,\n}\n","/*\n * The shape menu for createViewer: a split button with the same markup, classes and data\n * attributes as the bindings' `InkShapeMenu`, so `@inkbar/theme` styles both. The main button\n * activates the shape tool with the current kind and draws that kind's icon; the chevron\n * opens a two-column grid of kinds. Choosing one switches to the shape tool with that kind.\n */\nimport { ChevronDown } from '@inkbar/icons'\n\nimport { SHAPE_ICONS } from '../shape-icons'\nimport { SHAPE_KINDS, type ShapeKind, type ToolController } from '../tools'\nimport { SHAPE_COLUMNS, shapeMenuModel, type ShapeMenuModel } from '../ui'\n\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\n\nimport type { Viewer } from './create-viewer'\n\n/** A split button: the main part draws with the current shape kind, the chevron picks the kind. */\nexport function createShapeMenu(viewer: Viewer): HTMLElement {\n const main = h('button', {\n type: 'button',\n class: 'ink-tool-button ink-shape-button',\n 'data-ink-tool-button': '',\n 'data-ink-shape-button': '',\n 'data-tool': 'shape',\n 'data-state': 'off',\n 'aria-pressed': 'false',\n })\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-shape-menu-trigger',\n 'data-ink-shape-menu-trigger': '',\n 'data-state': 'closed',\n 'aria-label': 'Choose shape',\n title: 'Choose shape',\n 'aria-haspopup': 'menu',\n 'aria-expanded': 'false',\n })\n trigger.append(createIcon(ChevronDown))\n const root = h(\n 'div',\n {\n class: 'ink-split-button ink-shape-menu',\n 'data-ink-shape-menu': '',\n role: 'group',\n 'aria-label': 'Shape',\n },\n main,\n trigger\n )\n main.disabled = true\n trigger.disabled = true\n\n let tools: ToolController | null = null\n let stops: (() => void)[] = []\n let shownKind: ShapeKind | null = null\n\n const model = (): ShapeMenuModel =>\n shapeMenuModel(tools?.options('shape').get() ?? {}, SHAPE_KINDS)\n\n function refresh(): void {\n const m = model()\n main.disabled = trigger.disabled = tools === null\n main.setAttribute('aria-label', m.label)\n main.title = m.label\n main.dataset.kind = m.kind\n if (shownKind !== m.kind) {\n main.replaceChildren(createIcon(SHAPE_ICONS[m.kind]))\n shownKind = m.kind\n }\n const on = tools?.active.get() === 'shape'\n main.dataset.state = on ? 'on' : 'off'\n main.setAttribute('aria-pressed', String(on))\n menu.refresh()\n }\n\n function paint(panel: HTMLElement, m: ShapeMenuModel): void {\n if (panel.childElementCount === 0) {\n const grid = h('div', {\n role: 'group',\n 'aria-label': 'Shapes',\n class: 'ink-shape-grid',\n 'data-ink-menu-columns': String(SHAPE_COLUMNS),\n })\n for (const item of m.items) {\n const b = h(\n 'button',\n {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-select-item ink-menu-item ink-shape-item',\n 'data-ink-select-item': '',\n 'data-key': item.kind,\n tabindex: '-1',\n },\n item.label\n )\n b.prepend(createIcon(SHAPE_ICONS[item.kind]))\n b.addEventListener('click', () => {\n tools?.set('shape', { kind: item.kind })\n menu.close(true)\n })\n grid.append(b)\n }\n panel.append(grid)\n }\n const cells = panel.querySelectorAll<HTMLElement>('.ink-shape-item')\n m.items.forEach((item, i) => {\n cells[i]!.setAttribute('aria-checked', String(item.checked))\n cells[i]!.dataset.state = item.checked ? 'checked' : 'unchecked'\n })\n }\n\n const menu = createMenu(trigger, {\n label: 'Shapes',\n attrs: { 'data-ink-menu': 'shape' },\n render: (panel) => paint(panel, model()),\n })\n\n main.addEventListener('click', () => tools?.set('shape'))\n\n const follow = (next: ToolController | null): void => {\n for (const stop of stops) stop()\n stops = []\n tools = next\n if (tools)\n stops = [tools.active.subscribe(refresh), tools.options('shape').subscribe(refresh)]\n if (!tools) menu.close()\n refresh()\n }\n follow(viewer.tools.get())\n viewer.tools.subscribe(follow)\n return root\n}\n","// The icon each text markup kind draws in the highlight menu, shared by the vanilla menu and\n// the framework bindings so a kind has one icon everywhere.\nimport {\n Highlighter,\n SpellCheck2,\n Strikethrough,\n Underline,\n type IconNode,\n} from '@inkbar/icons'\n\nimport type { MarkupKind } from './tools'\n\nexport const MARKUP_ICONS: Readonly<Record<MarkupKind, IconNode>> = {\n highlight: Highlighter,\n underline: Underline,\n strikeout: Strikethrough,\n squiggly: SpellCheck2,\n}\n","/*\n * The highlight menu for createViewer: a split button with the same markup, classes and data\n * attributes as the bindings' `InkHighlightMenu`, so `@inkbar/theme` styles both. The main\n * button activates the highlight tool with the current markup kind and draws that kind's icon;\n * the chevron opens a menu of kinds plus the markup colour. Choosing a kind switches to the\n * highlight tool with that kind. The colour is a nested colour menu scoped to the `markup`\n * style group, so it works whatever tool is active.\n */\nimport { ChevronDown } from '@inkbar/icons'\n\nimport { MARKUP_ICONS } from '../markup-icons'\nimport { MARKUP_KINDS, type MarkupKind, type ToolController } from '../tools'\nimport { highlightMenuModel, type HighlightMenuModel } from '../ui'\n\nimport { createColorMenu } from './color-menu'\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\n\nimport type { Viewer } from './create-viewer'\n\n/** The nested colour menu's accessible name. */\nconst COLOUR_LABEL = 'Highlight colour'\n\n/** A split button: the main part marks text with the current kind, the chevron picks it. */\nexport function createHighlightMenu(viewer: Viewer): HTMLElement {\n const main = h('button', {\n type: 'button',\n class: 'ink-tool-button ink-highlight-button',\n 'data-ink-tool-button': '',\n 'data-ink-highlight-button': '',\n 'data-tool': 'highlight',\n 'data-state': 'off',\n 'aria-pressed': 'false',\n })\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-highlight-menu-trigger',\n 'data-ink-highlight-menu-trigger': '',\n 'data-state': 'closed',\n 'aria-label': 'Choose highlight',\n title: 'Choose highlight',\n 'aria-haspopup': 'menu',\n 'aria-expanded': 'false',\n })\n trigger.append(createIcon(ChevronDown))\n const root = h(\n 'div',\n {\n class: 'ink-split-button ink-highlight-menu',\n 'data-ink-highlight-menu': '',\n role: 'group',\n 'aria-label': 'Highlight',\n },\n main,\n trigger\n )\n main.disabled = true\n trigger.disabled = true\n\n // One colour menu for the life of the control; each panel adopts its trigger.\n const colour = createColorMenu(viewer, {\n property: 'border',\n group: 'markup',\n label: COLOUR_LABEL,\n })\n colour.setAttribute('role', 'menuitem')\n colour.tabIndex = -1\n\n let tools: ToolController | null = null\n let stops: (() => void)[] = []\n let shownKind: MarkupKind | null = null\n\n const model = (): HighlightMenuModel =>\n highlightMenuModel(tools?.options('highlight').get() ?? {}, MARKUP_KINDS)\n\n function refresh(): void {\n const m = model()\n main.disabled = trigger.disabled = tools === null\n main.setAttribute('aria-label', m.label)\n main.title = m.label\n main.dataset.kind = m.kind\n if (shownKind !== m.kind) {\n main.replaceChildren(createIcon(MARKUP_ICONS[m.kind]))\n shownKind = m.kind\n }\n const on = tools?.active.get() === 'highlight'\n main.dataset.state = on ? 'on' : 'off'\n main.setAttribute('aria-pressed', String(on))\n menu.refresh()\n }\n\n function paint(panel: HTMLElement, m: HighlightMenuModel): void {\n if (panel.childElementCount === 0) {\n const kinds = h('div', {\n role: 'group',\n 'aria-label': 'Kinds',\n class: 'ink-highlight-kinds',\n })\n for (const item of m.items) {\n const b = h(\n 'button',\n {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-select-item ink-menu-item ink-highlight-item',\n 'data-ink-select-item': '',\n 'data-key': item.kind,\n tabindex: '-1',\n },\n item.label\n )\n b.prepend(createIcon(MARKUP_ICONS[item.kind]))\n b.addEventListener('click', () => {\n tools?.set('highlight', { kind: item.kind })\n menu.close(true)\n })\n kinds.append(b)\n }\n const colourRow = h(\n 'div',\n { role: 'group', 'aria-label': 'Colour', class: 'ink-highlight-colour' },\n h(\n 'span',\n { class: 'ink-highlight-colour-label', 'aria-hidden': 'true' },\n 'Colour'\n ),\n colour\n )\n panel.append(\n kinds,\n h('div', { role: 'separator', class: 'ink-select-separator' }),\n colourRow\n )\n }\n const cells = panel.querySelectorAll<HTMLElement>('.ink-highlight-item')\n m.items.forEach((item, i) => {\n cells[i]!.setAttribute('aria-checked', String(item.checked))\n cells[i]!.dataset.state = item.checked ? 'checked' : 'unchecked'\n })\n }\n\n const menu = createMenu(trigger, {\n label: 'Highlights',\n attrs: { 'data-ink-menu': 'highlight' },\n owns: (t) =>\n t instanceof Element && t.closest('[data-ink-menu=\"color-border\"]') !== null,\n render: (panel) => paint(panel, model()),\n })\n\n main.addEventListener('click', () => tools?.set('highlight'))\n\n const follow = (next: ToolController | null): void => {\n for (const stop of stops) stop()\n stops = []\n tools = next\n if (tools)\n stops = [\n tools.active.subscribe(refresh),\n tools.options('highlight').subscribe(refresh),\n ]\n if (!tools) menu.close()\n refresh()\n }\n follow(viewer.tools.get())\n viewer.tools.subscribe(follow)\n return root\n}\n","// Making signature templates in the browser: a pad to draw one, a name typed in a handwriting\n// font, or an image file. The pad samples like the `draw` tool (coalesced events, pen and touch\n// pressure) and paints with its renderer, so a drawn signature looks the same placed.\nimport { readonly, writable, type Readable } from '../model/readable'\nimport {\n createImageTemplate,\n createInkTemplate,\n type SignatureTemplate,\n} from '../model/signatures'\n\nimport { outlinePath, strokeOutline } from './ink-stroke'\nimport { pressureOf, reportsPressure } from './tools/freehand'\n\nimport type { Point } from '../model/geometry'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** The pad's stroke width, CSS px. */\nconst PAD_STROKE = 3\n\nexport interface SignaturePad {\n /** The drawing surface, `svg.ink-signature-pad`, filling the host. */\n readonly element: SVGSVGElement\n /** True while nothing is drawn. */\n readonly empty: Readable<boolean>\n clear(): void\n /** The drawing as an ink template with a new id; undefined while the pad is empty. */\n toTemplate(): SignatureTemplate | undefined\n destroy(): void\n}\n\ninterface PadStroke {\n points: Point[]\n pressure: number[]\n path: SVGPathElement\n}\n\n/**\n * A drawing pad in `host`. Each press-drag-release is a stroke; the theme colours it through\n * `path.ink-stroke` (`fill: currentColor` by default).\n */\nexport function createSignaturePad(host: HTMLElement): SignaturePad {\n const doc = host.ownerDocument\n const svg = doc.createElementNS(SVG_NS, 'svg')\n svg.classList.add('ink-signature-pad')\n svg.dataset.inkSignaturePad = ''\n svg.setAttribute('width', '100%')\n svg.setAttribute('height', '100%')\n svg.setAttribute('aria-hidden', 'true')\n // Structural: the pad owns its touches, so a finger draws instead of scrolling.\n svg.style.touchAction = 'none'\n svg.style.display = 'block'\n host.append(svg)\n\n const strokes: PadStroke[] = []\n const empty = writable(true)\n let live: { id: number; stroke: PadStroke } | undefined\n\n const at = (e: PointerEvent): Point => {\n const r = svg.getBoundingClientRect()\n return { x: e.clientX - r.left, y: e.clientY - r.top }\n }\n const paint = (s: PadStroke): void => {\n const pressure = reportsPressure(s.pressure) ? s.pressure : undefined\n s.path.setAttribute('d', outlinePath(strokeOutline(s.points, pressure, PAD_STROKE)))\n }\n const sample = (s: PadStroke, e: PointerEvent): void => {\n s.points.push(at(e))\n s.pressure.push(pressureOf(e) ?? 0.5)\n }\n\n const onDown = (e: PointerEvent): void => {\n if (!e.isPrimary || e.button !== 0 || live) return\n e.preventDefault()\n const path = doc.createElementNS(SVG_NS, 'path')\n path.classList.add('ink-stroke')\n svg.append(path)\n const stroke: PadStroke = { points: [], pressure: [], path }\n sample(stroke, e)\n paint(stroke)\n live = { id: e.pointerId, stroke }\n try {\n svg.setPointerCapture(e.pointerId)\n } catch {\n // A synthetic pointer: the stroke still works while it stays over the pad.\n }\n }\n const onMove = (e: PointerEvent): void => {\n if (!live || e.pointerId !== live.id) return\n if (e.buttons === 0) {\n finish()\n return\n }\n const coalesced = e.getCoalescedEvents?.() ?? []\n for (const ev of coalesced.length > 0 ? coalesced : [e]) sample(live.stroke, ev)\n paint(live.stroke)\n }\n const finish = (e?: PointerEvent): void => {\n if (!live) return\n const s = live.stroke\n live = undefined\n const last = s.points[s.points.length - 1]!\n const end = e ? at(e) : last\n // A release reports no pressure: it repeats the last sample's.\n if (end.x !== last.x || end.y !== last.y) {\n s.points.push(end)\n s.pressure.push(s.pressure[s.pressure.length - 1]!)\n }\n paint(s)\n strokes.push(s)\n empty.set(false)\n }\n const onUp = (e: PointerEvent): void => {\n if (live && e.pointerId === live.id) finish(e)\n }\n const onCancel = (e: PointerEvent): void => {\n if (!live || e.pointerId !== live.id) return\n live.stroke.path.remove()\n live = undefined\n }\n /** Capture gone mid-stroke: keep what was drawn, as a touch sends no move to end it. */\n const onLostCapture = (e: PointerEvent): void => {\n if (live && e.pointerId === live.id) finish()\n }\n svg.addEventListener('pointerdown', onDown)\n svg.addEventListener('pointermove', onMove)\n svg.addEventListener('pointerup', onUp)\n svg.addEventListener('pointercancel', onCancel)\n svg.addEventListener('lostpointercapture', onLostCapture)\n\n return {\n element: svg,\n empty: readonly(empty),\n clear() {\n live?.stroke.path.remove()\n live = undefined\n for (const s of strokes.splice(0)) s.path.remove()\n empty.set(true)\n },\n toTemplate() {\n if (strokes.length === 0) return undefined\n // CSS y grows downwards; a template's grows upwards.\n const inklist = strokes.map((s) => s.points.map((p) => ({ x: p.x, y: -p.y })))\n const pressured = strokes.some((s) => reportsPressure(s.pressure))\n return createInkTemplate(\n inklist,\n pressured ? strokes.map((s) => [...s.pressure]) : undefined\n )\n },\n destroy() {\n svg.removeEventListener('pointerdown', onDown)\n svg.removeEventListener('pointermove', onMove)\n svg.removeEventListener('pointerup', onUp)\n svg.removeEventListener('pointercancel', onCancel)\n svg.removeEventListener('lostpointercapture', onLostCapture)\n svg.remove()\n },\n }\n}\n\n/** CSS generic families, which a font shorthand must not quote. */\nconst GENERIC_FAMILIES = new Set([\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n 'emoji',\n 'fangsong',\n])\n\n/** `font` as a CSS font-family value: quoted unless it is a generic family. */\nexport function fontFamilyValue(font: string): string {\n return GENERIC_FAMILIES.has(font) ? font : `\"${font.replace(/[\"\\\\]/g, '\\\\$&')}\"`\n}\n\nexport interface TypedSignatureOptions {\n /** The image's height in pixels. Default 96. */\n height?: number\n /** The ink colour. Default `#151820`, the theme's ink. */\n color?: string\n}\n\ninterface Rendered {\n url: string\n width: number\n height: number\n}\n\nasync function drawTyped(\n name: string,\n font: string,\n opts: TypedSignatureOptions = {}\n): Promise<Rendered> {\n const text = name.trim()\n if (text === '') throw new RangeError('A typed signature needs a name')\n const height = opts.height ?? 96\n const size = height * 0.625\n const margin = height / 8\n const shorthand = `${size}px ${fontFamilyValue(font)}`\n try {\n // Draws in the fallback font if the face never arrives.\n await document.fonts.load(shorthand, text)\n } catch {\n // Unavailable: the canvas uses the fallback.\n }\n const canvas = document.createElement('canvas')\n const measure = canvas.getContext('2d')\n if (!measure) throw new Error('Canvas 2D is unavailable')\n measure.font = shorthand\n const m = measure.measureText(text)\n const left = m.actualBoundingBoxLeft\n const width = Math.ceil(left + m.actualBoundingBoxRight + margin * 2)\n canvas.width = width\n canvas.height = height\n // Resizing a canvas resets its state.\n const ctx = canvas.getContext('2d')!\n ctx.font = shorthand\n ctx.fillStyle = opts.color ?? '#151820'\n ctx.textBaseline = 'middle'\n ctx.fillText(text, margin + left, height / 2)\n return { url: canvas.toDataURL('image/png'), width, height }\n}\n\n/**\n * `name` drawn in `font` on a transparent canvas, as a PNG data URL. Waits for the font to load\n * (`document.fonts.load`) first. Rejects with a RangeError for an empty name.\n */\nexport async function renderTypedSignature(\n name: string,\n font: string,\n opts?: TypedSignatureOptions\n): Promise<string> {\n return (await drawTyped(name, font, opts)).url\n}\n\n/** A typed signature as an image template, with a new id. */\nexport async function createTypedSignature(\n name: string,\n font: string,\n opts?: TypedSignatureOptions\n): Promise<SignatureTemplate> {\n const r = await drawTyped(name, font, opts)\n return createImageTemplate(r.url, r.width / r.height)\n}\n\n/** The image types a signature image may be. */\nexport const SIGNATURE_IMAGE_TYPES: readonly string[] = ['image/png', 'image/jpeg']\n\n/** The longest side, in pixels, an image signature is stored at. */\nexport const SIGNATURE_IMAGE_MAX_SIDE = 1000\n\n/**\n * The longest data URL, in characters, an image signature may be once scaled. Templates live\n * in host storage (`localStorage` holds about 5 MB) and are copied into every placed stamp.\n */\nexport const SIGNATURE_IMAGE_MAX_LENGTH = 3_000_000\n\n/**\n * An image file (a scan of a signature) as an image template. The image is drawn again at no\n * more than `SIGNATURE_IMAGE_MAX_SIDE` pixels on its long side, as a PNG (a JPEG stays a JPEG,\n * as photos compress far better that way), so a phone photo does not fill the store. Rejects\n * with a TypeError for anything but a PNG or JPEG, and a RangeError when the result is still\n * longer than `SIGNATURE_IMAGE_MAX_LENGTH`.\n */\nexport async function createImageSignature(file: Blob): Promise<SignatureTemplate> {\n if (!SIGNATURE_IMAGE_TYPES.includes(file.type))\n throw new TypeError('A signature image must be a PNG or JPEG')\n const source = URL.createObjectURL(file)\n try {\n const img = new Image()\n img.src = source\n try {\n await img.decode()\n } catch {\n throw new TypeError('The image could not be read')\n }\n const { naturalWidth: w, naturalHeight: h } = img\n if (w === 0 || h === 0) throw new TypeError('The image is empty')\n const scale = Math.min(1, SIGNATURE_IMAGE_MAX_SIDE / Math.max(w, h))\n const canvas = document.createElement('canvas')\n canvas.width = Math.max(1, Math.round(w * scale))\n canvas.height = Math.max(1, Math.round(h * scale))\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('Canvas 2D is unavailable')\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n const url =\n file.type === 'image/jpeg'\n ? canvas.toDataURL('image/jpeg', 0.9)\n : canvas.toDataURL('image/png')\n if (url.length > SIGNATURE_IMAGE_MAX_LENGTH)\n throw new RangeError('The signature image is too large')\n return createImageTemplate(url, canvas.width / canvas.height)\n } finally {\n URL.revokeObjectURL(source)\n }\n}\n\n/** The preview's height in its own units; the width follows the template's aspect. */\nconst PREVIEW_HEIGHT = 100\nconst PREVIEW_STROKE = 4\n\n/**\n * An ink template drawn for a menu: one filled outline per stroke (the `draw` renderer) in a\n * `viewBox` of the template's aspect, with room for the stroke. Paint `paths` with\n * `fill: currentColor`.\n */\nexport function signaturePreview(t: SignatureTemplate & { kind: 'ink' }): {\n viewBox: string\n paths: string[]\n} {\n const h = PREVIEW_HEIGHT\n const w = h * t.aspect\n const pad = PREVIEW_STROKE\n const paths = t.inklist.map((stroke, i) =>\n outlinePath(\n strokeOutline(\n stroke.map((p) => ({ x: p.x * w, y: (1 - p.y) * h })),\n t.pressure?.[i],\n PREVIEW_STROKE\n )\n )\n )\n const r = (n: number): number => Math.round(n * 100) / 100\n return { viewBox: `${-pad} ${-pad} ${r(w + pad * 2)} ${r(h + pad * 2)}`, paths }\n}\n","// The state behind the \"Create signature\" dialog, shared by every binding and the vanilla\n// dialog: which tab is open, the pad, the typed name and font, the chosen image, and whether\n// Save can go. The bindings render it; nothing here touches their markup.\nimport { readonly, writable, type Readable } from '../model/readable'\n\nimport {\n createImageSignature,\n createSignaturePad,\n createTypedSignature,\n type SignaturePad,\n} from './signature-pad'\nimport { SIGNATURE_FONTS, type SignatureTab } from './ui'\n\nimport type { SignatureLibrary, SignatureTemplate } from '../model/signatures'\n\nexport interface SignatureDraftState {\n tab: SignatureTab\n /** True while the pad has nothing on it. */\n padEmpty: boolean\n name: string\n font: string\n /** The chosen image, read and checked. */\n image: SignatureTemplate | undefined\n /** Why the chosen file was refused, for the Image tab to show. */\n imageError: string | undefined\n /** Why the last save failed (the store refused it, full or offline), for the dialog to show. */\n saveError: string | undefined\n /** True when the open tab has something to save. */\n canSave: boolean\n saving: boolean\n}\n\nexport interface SignatureDraft {\n readonly state: Readable<SignatureDraftState>\n readonly fonts: readonly string[]\n setTab(tab: SignatureTab): void\n setName(name: string): void\n setFont(font: string): void\n /** Mounts the pad in `host`; returns its teardown. One pad at a time. */\n attachPad(host: HTMLElement): () => void\n clearPad(): void\n /** Reads an image file for the Image tab. */\n chooseFile(file: Blob | undefined): Promise<void>\n /**\n * Builds the open tab's template and saves it to `library`. Resolves with it, or undefined\n * when there is nothing to save, the save failed (setting `saveError`), or the draft was\n * destroyed before the save finished.\n */\n save(library: SignatureLibrary): Promise<SignatureTemplate | undefined>\n /** Back to an empty Draw tab. */\n reset(): void\n destroy(): void\n}\n\nexport function createSignatureDraft(\n opts: { fonts?: readonly string[] } = {}\n): SignatureDraft {\n const fonts = opts.fonts && opts.fonts.length > 0 ? [...opts.fonts] : SIGNATURE_FONTS\n const initial = (): SignatureDraftState => ({\n tab: 'draw',\n padEmpty: true,\n name: '',\n font: fonts[0]!,\n image: undefined,\n imageError: undefined,\n saveError: undefined,\n canSave: false,\n saving: false,\n })\n const state = writable<SignatureDraftState>(initial())\n let pad: SignaturePad | undefined\n let stopPad: (() => void) | undefined\n /** Only the latest file read lands. */\n let reads = 0\n /** Set by `destroy`: a save that finishes later selects nothing. */\n let destroyed = false\n\n const ready = (s: SignatureDraftState): boolean =>\n s.tab === 'draw'\n ? !s.padEmpty\n : s.tab === 'type'\n ? s.name.trim() !== ''\n : s.image !== undefined\n const patch = (p: Partial<SignatureDraftState>): void => {\n const next = { ...state.get(), ...p }\n state.set({ ...next, canSave: !next.saving && ready(next) })\n }\n\n const detachPad = (): void => {\n stopPad?.()\n stopPad = undefined\n pad?.destroy()\n pad = undefined\n }\n\n return {\n state: readonly(state),\n fonts,\n setTab: (tab) => patch({ tab }),\n setName: (name) => patch({ name }),\n setFont: (font) => patch({ font }),\n attachPad(host) {\n // Mounting again revives a destroyed draft, as React's StrictMode remounts do.\n destroyed = false\n detachPad()\n const p = createSignaturePad(host)\n pad = p\n stopPad = p.empty.subscribe((padEmpty) => patch({ padEmpty }))\n patch({ padEmpty: p.empty.get() })\n return () => {\n if (pad === p) detachPad()\n }\n },\n clearPad() {\n pad?.clear()\n },\n async chooseFile(file) {\n const n = ++reads\n if (!file) {\n patch({ image: undefined, imageError: undefined })\n return\n }\n // The old image goes at once, so Save waits for the new one.\n patch({ image: undefined, imageError: undefined })\n try {\n const image = await createImageSignature(file)\n if (n === reads) patch({ image, imageError: undefined })\n } catch (e) {\n if (n === reads)\n patch({\n image: undefined,\n imageError:\n e instanceof RangeError\n ? 'This image is too large. Choose a smaller one.'\n : 'Choose a PNG or JPEG image.',\n })\n }\n },\n async save(library) {\n const s = state.get()\n if (!s.canSave) return undefined\n patch({ saving: true, saveError: undefined })\n try {\n const t =\n s.tab === 'draw'\n ? pad?.toTemplate()\n : s.tab === 'type'\n ? await createTypedSignature(s.name, s.font)\n : s.image\n if (!t) return undefined\n await library.save(t)\n // Closed while saving: the template stays in the library, but nothing acts on it.\n return destroyed ? undefined : t\n } catch {\n patch({\n saveError: 'The signature could not be saved. Try again, or try a smaller one.',\n })\n return undefined\n } finally {\n patch({ saving: false })\n }\n },\n reset() {\n reads++\n pad?.clear()\n state.set({ ...initial(), padEmpty: pad ? pad.empty.get() : true })\n },\n destroy() {\n destroyed = true\n reads++\n detachPad()\n },\n }\n}\n","/*\n * The \"Create signature\" dialog for createViewer, with the same markup, classes and data\n * attributes as the bindings' `InkSignatureDialog`, so `@inkbar/theme` styles both. A modal:\n * Tab stays inside it, Escape or a press on the overlay closes it, and focus goes back where it\n * came from. Draw, Type and Image tabs each make a template; Save stores it in the viewer's\n * signature library and selects it for the `signature` tool.\n */\nimport { handleRadioKeys, handleTabKeys, trapTab } from '../menu-keys'\nimport { createSignatureDraft, type SignatureDraftState } from '../signature-draft'\nimport { fontFamilyValue } from '../signature-pad'\nimport {\n SIGNATURE_FONTS,\n SIGNATURE_LABELS,\n SIGNATURE_TABS,\n type SignatureTab,\n} from '../ui'\n\nimport { h } from './dom'\n\nimport type { Viewer } from './create-viewer'\n\nexport interface SignatureDialogOptions {\n /** The fonts the Type tab offers. Default: the viewer's `signatureFonts`. */\n fonts?: string[]\n}\n\nexport interface SignatureDialog {\n readonly isOpen: boolean\n /** Opens the dialog. On close, focus goes to `returnFocus`, else to what had it before. */\n open(opts?: { returnFocus?: HTMLElement | null }): void\n close(): void\n destroy(): void\n}\n\nlet dialogs = 0\n\nexport function createSignatureDialog(\n viewer: Viewer,\n opts: SignatureDialogOptions = {}\n): SignatureDialog {\n const uid = `ink-signature-dialog-${++dialogs}`\n let teardown: (() => void) | null = null\n\n function close(): void {\n teardown?.()\n teardown = null\n }\n\n function open(o: { returnFocus?: HTMLElement | null } = {}): void {\n if (teardown) return\n const returnTo =\n o.returnFocus ??\n (document.activeElement instanceof HTMLElement ? document.activeElement : null)\n const draft = createSignatureDraft({\n fonts: opts.fonts ?? viewer.engine.get()?.signatureFonts ?? SIGNATURE_FONTS,\n })\n\n const tabs = new Map<SignatureTab, HTMLButtonElement>()\n const panels = new Map<SignatureTab, HTMLElement>()\n const tablist = h('div', {\n role: 'tablist',\n 'aria-label': SIGNATURE_LABELS.tabs,\n class: 'ink-tabs',\n })\n for (const tab of SIGNATURE_TABS) {\n const b = h(\n 'button',\n {\n type: 'button',\n role: 'tab',\n id: `${uid}-tab-${tab}`,\n 'aria-controls': `${uid}-panel-${tab}`,\n class: 'ink-tab',\n 'data-key': tab,\n },\n SIGNATURE_LABELS[tab]\n )\n b.addEventListener('click', () => draft.setTab(tab))\n tabs.set(tab, b)\n tablist.append(b)\n panels.set(\n tab,\n h('div', {\n role: 'tabpanel',\n id: `${uid}-panel-${tab}`,\n 'aria-labelledby': `${uid}-tab-${tab}`,\n class: 'ink-tab-panel',\n 'data-key': tab,\n })\n )\n }\n tablist.addEventListener('keydown', (e) => handleTabKeys(e, tablist))\n\n // Draw\n const padHost = h('div', {\n class: 'ink-signature-pad-host',\n 'data-ink-signature-pad-host': '',\n role: 'img',\n 'aria-label': SIGNATURE_LABELS.pad,\n })\n const clear = h(\n 'button',\n { type: 'button', class: 'ink-button', 'data-ink-signature-clear': '' },\n SIGNATURE_LABELS.clear\n )\n clear.addEventListener('click', () => draft.clearPad())\n panels.get('draw')!.append(padHost, h('div', { class: 'ink-dialog-row' }, clear))\n const detachPad = draft.attachPad(padHost)\n\n // Type\n const name = h('input', {\n type: 'text',\n class: 'ink-input',\n 'data-ink-signature-name': '',\n autocomplete: 'name',\n placeholder: SIGNATURE_LABELS.namePlaceholder,\n })\n name.addEventListener('input', () => draft.setName(name.value))\n const fontGroup = h('div', {\n role: 'radiogroup',\n 'aria-label': SIGNATURE_LABELS.fonts,\n class: 'ink-signature-fonts',\n })\n const fontSamples = draft.fonts.map((font) => {\n const b = h('button', {\n type: 'button',\n role: 'radio',\n class: 'ink-signature-font',\n 'data-key': font,\n 'aria-label': font,\n })\n const sample = h('span', { class: 'ink-signature-font-sample' })\n // The font is the option itself, so it is set on the element, not left to the theme.\n sample.style.fontFamily = fontFamilyValue(font)\n b.append(sample)\n b.addEventListener('click', () => draft.setFont(font))\n fontGroup.append(b)\n return sample\n })\n fontGroup.addEventListener('keydown', (e) => handleRadioKeys(e, fontGroup))\n panels\n .get('type')!\n .append(\n h('label', { class: 'ink-field' }, h('span', {}, SIGNATURE_LABELS.name), name),\n fontGroup\n )\n\n // Image\n const file = h('input', {\n type: 'file',\n accept: 'image/png,image/jpeg',\n class: 'ink-input',\n 'data-ink-signature-file': '',\n })\n file.addEventListener('change', () => void draft.chooseFile(file.files?.[0]))\n const preview = h('img', { class: 'ink-signature-image', alt: '' })\n const imageError = h('p', { class: 'ink-field-error', role: 'alert' })\n panels\n .get('image')!\n .append(\n h('label', { class: 'ink-field' }, h('span', {}, SIGNATURE_LABELS.file), file),\n preview,\n imageError\n )\n\n // Actions\n const saveError = h('p', {\n class: 'ink-field-error',\n role: 'alert',\n 'data-ink-signature-save-error': '',\n })\n const cancel = h(\n 'button',\n { type: 'button', class: 'ink-button', 'data-ink-signature-cancel': '' },\n SIGNATURE_LABELS.cancel\n )\n cancel.addEventListener('click', () => close())\n const save = h(\n 'button',\n {\n type: 'button',\n class: 'ink-button',\n 'data-variant': 'primary',\n 'data-ink-signature-save': '',\n },\n SIGNATURE_LABELS.save\n )\n save.addEventListener('click', () => {\n const library = viewer.engine.get()?.signatures\n if (!library) return\n draft.save(library).then(\n (t) => {\n if (!t) return\n viewer.tools.get()?.set('signature', { templateId: t.id })\n close()\n },\n () => {\n // The host's store refused it: the dialog stays open to try again.\n }\n )\n })\n\n const title = h(\n 'h2',\n { id: `${uid}-title`, class: 'ink-dialog-title' },\n SIGNATURE_LABELS.dialog\n )\n const content = h(\n 'div',\n {\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-labelledby': `${uid}-title`,\n class: 'ink-dialog ink-signature-dialog',\n 'data-ink-signature-dialog': '',\n 'data-state': 'open',\n tabindex: '-1',\n },\n title,\n tablist,\n ...panels.values(),\n saveError,\n h('div', { class: 'ink-dialog-actions' }, cancel, save)\n )\n const overlay = h('div', {\n class: 'ink-dialog-overlay',\n 'data-ink-dialog-overlay': '',\n 'data-state': 'open',\n })\n overlay.addEventListener('pointerdown', () => close())\n\n const paint = (s: SignatureDraftState): void => {\n for (const [tab, b] of tabs) {\n const on = tab === s.tab\n b.setAttribute('aria-selected', String(on))\n b.dataset.state = on ? 'active' : 'inactive'\n b.tabIndex = on ? 0 : -1\n panels.get(tab)!.hidden = !on\n }\n clear.disabled = s.padEmpty\n draft.fonts.forEach((font, i) => {\n const sample = fontSamples[i]!\n const b = sample.parentElement!\n const on = font === s.font\n b.setAttribute('aria-checked', String(on))\n b.dataset.state = on ? 'checked' : 'unchecked'\n b.tabIndex = on ? 0 : -1\n sample.textContent = s.name.trim() || SIGNATURE_LABELS.namePlaceholder\n })\n if (s.image?.kind === 'image') {\n preview.src = s.image.imagedata\n preview.hidden = false\n } else {\n preview.removeAttribute('src')\n preview.hidden = true\n }\n imageError.textContent = s.imageError ?? ''\n imageError.hidden = s.imageError === undefined\n saveError.textContent = s.saveError ?? ''\n saveError.hidden = s.saveError === undefined\n save.disabled = !s.canSave || !viewer.engine.get()\n }\n const stopState = draft.state.subscribe(paint)\n paint(draft.state.get())\n\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n close()\n return\n }\n trapTab(e, content)\n }\n // Focus that escapes (a click on the page behind) comes back in.\n const onFocus = (e: FocusEvent): void => {\n if (!content.contains(e.target as Node)) tabs.get(draft.state.get().tab)?.focus()\n }\n document.addEventListener('keydown', onKey, true)\n document.addEventListener('focusin', onFocus)\n document.body.append(overlay, content)\n tabs.get('draw')!.focus({ preventScroll: true })\n\n teardown = () => {\n document.removeEventListener('keydown', onKey, true)\n document.removeEventListener('focusin', onFocus)\n stopState()\n detachPad()\n draft.destroy()\n overlay.remove()\n content.remove()\n if (returnTo?.isConnected) returnTo.focus({ preventScroll: true })\n }\n }\n\n return {\n get isOpen() {\n return teardown !== null\n },\n open,\n close,\n destroy: close,\n }\n}\n","/*\n * The signature menu for createViewer: a split button with the same markup, classes and data\n * attributes as the bindings' `InkSignatureMenu`, so `@inkbar/theme` styles both. The main\n * button activates the signature tool with the chosen template (or opens the menu when none is\n * chosen); the chevron opens the saved signatures, each with a remove button, and \"Create\n * signature\", which opens the signature dialog.\n */\nimport { ChevronDown, Plus, Signature, Trash2 } from '@inkbar/icons'\n\nimport { signaturePreview } from '../signature-pad'\nimport { SIGNATURE_LABELS, signatureMenuModel, type SignatureMenuModel } from '../ui'\n\nimport { createIcon } from './controls'\nimport { h } from './dom'\nimport { createMenu } from './menu'\nimport { createSignatureDialog, type SignatureDialogOptions } from './signature-dialog'\n\nimport type { Viewer } from './create-viewer'\nimport type { SignatureLibrary, SignatureTemplate } from '../../model/signatures'\nimport type { ToolController } from '../tools'\nimport type { ViewerEngine } from '../viewer-engine'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** A template drawn small: ink as an SVG of filled outlines, an image as an `<img>`. */\nexport function createSignaturePreview(t: SignatureTemplate): HTMLElement {\n const box = h('span', { class: 'ink-signature-preview', 'data-kind': t.kind })\n if (t.kind === 'image') {\n box.append(h('img', { src: t.imagedata, alt: '', draggable: 'false' }))\n return box\n }\n const { viewBox, paths } = signaturePreview(t)\n const svg = document.createElementNS(SVG_NS, 'svg')\n svg.setAttribute('viewBox', viewBox)\n svg.setAttribute('aria-hidden', 'true')\n for (const d of paths) {\n const path = document.createElementNS(SVG_NS, 'path')\n path.setAttribute('d', d)\n path.setAttribute('fill', 'currentColor')\n svg.append(path)\n }\n box.append(svg)\n return box\n}\n\nexport function createSignatureMenu(\n viewer: Viewer,\n opts: SignatureDialogOptions = {}\n): HTMLElement {\n const main = h('button', {\n type: 'button',\n class: 'ink-tool-button ink-signature-button',\n 'data-ink-tool-button': '',\n 'data-ink-signature-button': '',\n 'data-tool': 'signature',\n 'data-state': 'off',\n 'aria-pressed': 'false',\n 'aria-label': SIGNATURE_LABELS.sign,\n title: SIGNATURE_LABELS.sign,\n })\n main.append(createIcon(Signature))\n const trigger = h('button', {\n type: 'button',\n class: 'ink-menu-trigger ink-signature-menu-trigger',\n 'data-ink-signature-menu-trigger': '',\n 'data-state': 'closed',\n 'aria-label': SIGNATURE_LABELS.trigger,\n title: SIGNATURE_LABELS.trigger,\n 'aria-haspopup': 'menu',\n 'aria-expanded': 'false',\n })\n trigger.append(createIcon(ChevronDown))\n const root = h(\n 'div',\n {\n class: 'ink-split-button ink-signature-menu',\n 'data-ink-signature-menu': '',\n role: 'group',\n 'aria-label': SIGNATURE_LABELS.sign,\n },\n main,\n trigger\n )\n main.disabled = true\n trigger.disabled = true\n\n const dialog = createSignatureDialog(viewer, opts)\n let tools: ToolController | null = null\n let library: SignatureLibrary | null = null\n let stops: (() => void)[] = []\n /** The ids the open panel shows, to rebuild it only when the list changes. */\n let shown = ''\n\n const model = (): SignatureMenuModel =>\n signatureMenuModel(\n library?.templates.get() ?? [],\n tools?.options('signature').get() ?? {}\n )\n\n function refresh(): void {\n main.disabled = trigger.disabled = tools === null\n const on = tools?.active.get() === 'signature'\n main.dataset.state = on ? 'on' : 'off'\n main.setAttribute('aria-pressed', String(on))\n menu.refresh()\n }\n\n /** Removes a template; focus moves to the signature now in its row, else \"Create signature\". */\n function remove(panel: HTMLElement, id: string): void {\n const row = model().items.findIndex((i) => i.id === id)\n library?.remove(id).then(\n () => {\n if (!menu.isOpen) return\n const rows = panel.querySelectorAll<HTMLElement>('.ink-signature-item')\n const next =\n rows[Math.min(row, rows.length - 1)] ??\n panel.querySelector<HTMLElement>('[data-ink-signature-create]')\n next?.focus({ preventScroll: true })\n },\n () => {\n // The store refused: the row stays, and `removeError` shows in the menu.\n }\n )\n }\n\n function paint(panel: HTMLElement, m: SignatureMenuModel): void {\n const ids = m.items.map((i) => i.id).join(' ')\n // A fresh panel is a fresh opening: an old removal error is not news any more.\n if (panel.childElementCount === 0) library?.clearRemoveError()\n if (panel.childElementCount === 0 || ids !== shown) {\n shown = ids\n const list = h('div', {\n role: 'group',\n 'aria-label': SIGNATURE_LABELS.saved,\n class: 'ink-signature-list',\n 'data-ink-menu-columns': '2',\n })\n for (const item of m.items) {\n const choose = h('button', {\n type: 'button',\n role: 'menuitemradio',\n class: 'ink-select-item ink-menu-item ink-signature-item',\n 'data-ink-select-item': '',\n 'data-key': item.id,\n 'aria-label': item.label,\n tabindex: '-1',\n })\n choose.append(createSignaturePreview(item.template))\n choose.addEventListener('click', () => {\n tools?.set('signature', { templateId: item.id })\n menu.close(true)\n })\n const drop = h('button', {\n type: 'button',\n role: 'menuitem',\n class: 'ink-menu-item ink-signature-remove',\n 'data-ink-signature-remove': '',\n 'data-key': item.id,\n 'aria-label': item.removeLabel,\n title: item.removeLabel,\n tabindex: '-1',\n })\n drop.append(createIcon(Trash2))\n drop.addEventListener('click', () => remove(panel, item.id))\n list.append(choose, drop)\n }\n const create = h(\n 'button',\n {\n type: 'button',\n role: 'menuitem',\n class: 'ink-select-item ink-menu-item ink-signature-create',\n 'data-ink-select-item': '',\n 'data-ink-signature-create': '',\n tabindex: '-1',\n },\n SIGNATURE_LABELS.create\n )\n create.prepend(createIcon(Plus))\n create.addEventListener('click', () => {\n menu.close()\n dialog.open({ returnFocus: main })\n })\n panel.replaceChildren(\n ...(m.items.length > 0\n ? [list, h('div', { role: 'separator', class: 'ink-select-separator' })]\n : []),\n create,\n h('p', {\n class: 'ink-field-error ink-signature-remove-error',\n role: 'alert',\n 'data-ink-signature-remove-error': '',\n })\n )\n }\n const error = panel.querySelector<HTMLElement>('[data-ink-signature-remove-error]')!\n const message = library?.removeError.get()\n error.textContent = message ?? ''\n error.hidden = message === undefined\n for (const item of m.items) {\n const el = panel.querySelector<HTMLElement>(\n `.ink-signature-item[data-key=\"${CSS.escape(item.id)}\"]`\n )\n el?.setAttribute('aria-checked', String(item.checked))\n if (el) el.dataset.state = item.checked ? 'checked' : 'unchecked'\n }\n }\n\n const menu = createMenu(trigger, {\n label: SIGNATURE_LABELS.menu,\n attrs: { 'data-ink-menu': 'signature' },\n render: (panel) => paint(panel, model()),\n })\n\n main.addEventListener('click', () => {\n if (!tools) return\n if (model().selected) tools.set('signature')\n else trigger.click()\n })\n\n const follow = (next: ToolController | null): void => {\n for (const stop of stops) stop()\n stops = []\n tools = next\n if (tools)\n stops = [\n tools.active.subscribe(refresh),\n tools.options('signature').subscribe(refresh),\n ]\n if (!tools) {\n menu.close()\n dialog.close()\n }\n refresh()\n }\n // The library lives as long as the viewer, but reaches the menu with the first engine.\n let stopLibrary: () => void = () => undefined\n const followLibrary = (engine: ViewerEngine | null): void => {\n const next = engine?.signatures ?? null\n if (next === library) return\n stopLibrary()\n library = next\n const stops = library\n ? [library.templates.subscribe(refresh), library.removeError.subscribe(refresh)]\n : []\n stopLibrary = () => stops.forEach((stop) => stop())\n refresh()\n }\n follow(viewer.tools.get())\n viewer.tools.subscribe(follow)\n followLibrary(viewer.engine.get())\n viewer.engine.subscribe(followLibrary)\n return root\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;;;ACpDA,MAAM,aAAa,CAAC,KAAK,GAAG;;;;;AAY5B,SAAgB,sBACd,MACA,SACA,UACU;CACV,IAAI;CACJ,IAAI;CACJ,IAAI,WAA4C,CAAC;CACjD,IAAI,YAAY;CAEhB,MAAM,sBAA4B;EAChC,SAAS,QAAQ,YAAY;EAC7B,WAAW,CAAC;CACd;CACA,MAAM,aAAmB;EACvB,IAAI,WAAW;EACf,IAAI,QAAQ,GAAG,IAAI;EACnB,SAAS;EACT,cAAc;EACd,WAAW,WAAW,KAAK,OACzB,iBAAiB;GACf,IAAI,CAAC,aAAa,QAAQ,MAAM,SAAS,KAAK;EAChD,GAAG,EAAE,CACP;CACF;CACA,SAAS,IAAI,KAAa,QAAQ,OAAa;EAC7C,IAAI,aAAa,CAAC,MAAM,YAAY;EACpC,IAAI,QAAQ,WAAW,CAAC,OAAO;EAC/B,UAAU;EACV,OAAO,oBAAoB,UAAU,IAAI;EACzC,QAAQ,KAAK,WAAW,gBAAgB,IAAI,MAAM;EAClD,MAAM,iBAAiB,UAAU,IAAI;CACvC;CAEA,OAAO;EACL,QAAQ,QAAQ,IAAI,GAAG;EACvB,UAAU;GACR,YAAY;GACZ,OAAO,oBAAoB,UAAU,IAAI;GACzC,QAAQ,KAAA;GACR,cAAc;EAChB;CACF;AACF;;;ACrBA,MAAMA,oBAAkB,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,UAAU,MAAM,GAAG;EACnB,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,eACpBA,iBAAe,KAAK,MAAM,CAAC,WAAW,KAAK,UAAU,KAAK;EAChF,UAAU;GACR,IAAI,QAAQ,YAAY,OAAO;EACjC;CACF;CAGA,MAAM,WACJ,KAAK,qBAAqB,KAAA,IACtB,sBAAsB,MAAM,kBAAkB,KAAK,OAAO,MAAM,CAAC,IACjE,KAAA;CAEN,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,QAAQ;GAClB,MAAM,OAAO;GACb,OAAO,KAAA;GACP,IAAI,SAAS,QAAQ,OAAO;GAC5B,UAAU,KAAA;GACV,QAAQ,OAAO;GACf,OAAO;EACT;CACF;AACF;;;;;;;;;AChJA,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;;;;;ACrFA,SAAgB,cACd,QACA,UACA,OACS;CACT,MAAM,eAAe,aAAa,KAAA;CAClC,MAAM,QAAQ,OAAO,KAClB,GAAG,MAAM;EAAC,EAAE;EAAG,EAAE;EAAG,WAAW,MAAM;CAAG,CAC3C;CACA,OAAO,UAAU,OAAO;EACtB,MAAM;EACN,UAAU,eAAe,KAAM;EAC/B,WAAW;EACX,YAAY;EACZ,kBAAkB;CACpB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,QAAQ;EAAE;EAAG;CAAE,EAAE;AAC/B;;AAGA,SAAgB,YAAY,SAAmC;CAC7D,IAAI,QAAQ,WAAW,GAAG,OAAO;CACjC,MAAM,KAAK,MAAsB,OAAO,KAAK,MAAM,IAAI,GAAG,IAAI,GAAG;CACjE,OAAO,IAAI,QAAQ,KAAK,MAAM,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;AACjE;;;ACdA,MAAMC,QAAM;;AAGZ,MAAM,YAAY;AAClB,MAAMC,YAAU;CAAC;CAAM;CAAM;CAAM;AAAI;;AAEvC,MAAM,YAAY;;;;;AAwBlB,SAAgB,YAAY,MAAmB,MAAwB;CACrE,MAAM,WAAW,CAAC,GAAG,KAAK,iBAA8B,wBAAwB,CAAC;CACjF,MAAM,QACJ,KAAK,SAAS,SACV,CAAC,IACD,KAAK,SAAS,SACZ,CAAC,SAAS,KAAK,IACf,KAAK,OACH,CAAC,GAAGA,WAAS,SAAS,IACtBA;CACV,IACE,SAAS,WAAW,MAAM,UAC1B,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,WAAW,MAAM,EAAE,GACrD;EACA,SAAS,SAAS,MAAM,EAAE,OAAO,CAAC;EAClC,SAAS,SAAS;EAClB,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,IAAI,KAAK,cAAc,cAAc,KAAK;GAChD,EAAE,YAAY;GACd,EAAE,QAAQ,SAAS;GACnB,EAAE,aAAa,eAAe,MAAM;GACpC,EAAE,MAAM,UAAU,2BAA2B,UAAU,YAAY,UAAU;GAC7E,KAAK,OAAO,CAAC;GACb,SAAS,KAAK,CAAC;EACjB;CACF;CACA,KAAK,MAAM,KAAK,UAAU;EACxB,MAAM,OAAO,EAAE,QAAQ;EACvB,MAAM,KACJ,KAAK,SAAS,SACV,SAAS,UACP,KAAK,QACL,KAAK,MACP,KAAK,SAAS,YACZ,SAAS,aAAa,KAAK,OACzB,KAAK,OACL;GACE,IAAI,KAAK,QAAQ,MAAM,KAAK,OAAO,MAAM,IAAI,KAAK;GAClD,IAAI,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,IAAI,KAAK;EACnD,IACF;GAAE,GAAG;GAAG,GAAG;EAAE;EACrB,EAAE,MAAM,OAAO,GAAG,GAAG,IAAI,YAAY,EAAE;EACvC,EAAE,MAAM,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE;CACxC;AACF;;;;;;;;;AAUA,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,QAAQ,KAAK,IACf,KAAA;CACV,IAAI,CAAC,UAAU,OAAO,WAAW,KAAK,EAAE,WAAW,IAAI,OAAO,EAAE,UAAU,EAAE,IAAI;CAChF,MAAM,MAAM,EAAE,UAAU,YAAY,MAAM,CAAC;CAC3C,MAAM,SAAS,KAAK,IAAI,EAAE,YAAY,EAAE,KAAK,GAAG,CAAC;CAEjD,MAAM,MAAM,WAAW,CAAC,IAAI,eAAe,SAAS,SAAS;CAC7D,OAAO;EACL,MAAM,IAAI,OAAO;EACjB,KAAK,IAAI,MAAM;EACf,OAAO,IAAI,QAAQ,MAAM;EACzB,QAAQ,IAAI,SAAS,MAAM;CAC7B;AACF;;AAGA,MAAM,eAAe;;AAGrB,SAAS,SAAS,MAA0C;CAC1D,OAAO,SAAS,KAAA,KAAa,QAAQ,cAAc,IAAI,IAAI,OAAO;AACpE;AAEA,SAAS,YAAY,GAAmE;CACtF,OAAO,EAAE,SAAS,UAAU,EAAE,SAAS,aACnC;EAAE,MAAM,SAAS,EAAE,IAAI;EAAG,MAAM,SAAS,EAAE,IAAI;CAAE,IACjD,KAAA;AACN;AAEA,SAAS,WAAW,GAAwB;CAC1C,MAAM,IAAI,YAAY,CAAC;CACvB,OAAO,MAAM,KAAA,MAAc,EAAE,SAAS,UAAU,EAAE,SAAS;AAC7D;AAEA,MAAMC,SAAO,MAAsB,OAAO,KAAK,MAAM,IAAI,GAAI,IAAI,MAAO,CAAC;;;;;;;AAQzE,SAAgB,eACd,MACA,IACA,MACA,OACQ;CACR,MAAM,MAAM,KAAK,MAAM,GAAG,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,CAAC;CACnD,IAAI,CAAC,QAAQ,cAAc,IAAI,KAAK,SAAS,UAAU,QAAQ,GAAG,OAAO;CACzE,MAAM,OAAO,eAAe,KAAK,IAAI,OAAO,CAAC;CAC7C,MAAM,OAAO,OAAO;CACpB,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;CAC7B,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;CAE7B,MAAM,KAAK,CAAC;CACZ,MAAM,KAAK;CACX,MAAM,MAAM,OAAe,QAAgB,IAAW,OACpD,GAAGA,MAAI,EAAE,IAAI,KAAK,QAAQ,KAAK,MAAM,EAAE,GAAGA,MAAI,EAAE,IAAI,KAAK,QAAQ,KAAK,MAAM;CAC9E,QAAQ,MAAR;EACE,KAAK,aACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI;EAC3D,KAAK,eACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;EAC7D,KAAK,cACH,OAAO,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI;EACvD,KAAK,gBACH,OAAO,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI,EAAE;EACzD,KAAK,UACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;EACtF,KAAK,WACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI,EAAE;EACxE,KAAK,UACH,OAAO,IAAI,GAAG,MAAM,CAAC,EAAE,GAAGA,MAAI,IAAI,EAAE,GAAGA,MAAI,IAAI,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC,EAAE,GAAGA,MAAI,IAAI,EAAE,GAAGA,MAAI,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,EAAE;EACxH,KAAK,QACH,OAAO,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI;EACvC,KAAK,SAAS;GAEZ,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI;GAClC,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI;GAClC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;EAClC;EACA,SACE,OAAO;CACX;AACF;;AAGA,MAAM,iCAA0C,IAAI,IAAI;CACtD;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,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;;CAE9B,MAAM,MAAM,MAAoB;EAC9B,MAAM,IAAI,EAAE,MAAM,CAAC;EACnB,OAAO;GAAE,GAAG,EAAE,IAAI,IAAI;GAAM,GAAG,EAAE,IAAI,IAAI;EAAI;CAC/C;CACA,MAAM,SAAS,MAAqB;EAClC,MAAM,IAAI,GAAG,CAAC;EACd,OAAO,GAAG,EAAE,EAAE,GAAG,EAAE;CACrB;CACA,MAAM,QAAQ,MAAc,UAAuD;EACjF,MAAM,IAAI,IAAI,gBAAgBF,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;EACzB,IAAI,SAAS,CAAC,GAAG;GAEf,MAAM,MAAM,OAAO,KAAK,IAAI,OAAO,IAAI,MAAM;GAC7C,IAAI,UAAU,IAAI,sBAAsB;GACxC,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C,MAAM,OAAO,KAAK,QAAQ;IACxB,GAAG,WAAW,GAAG,CAAC;IAClB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,QAAQ,IAAK,EAAE,eAAe,EAAE,aAAa,QAAS;IAChE,gBAAgB,EAAE,YAAY,EAAE,KAAK;IACrC,mBAAmB;IACnB,kBAAkB;GACpB,CAAC;GACD,KAAK,UAAU,IAAI,YAAY;GAC/B,KAAK,MAAM,EAAE,QAAQ,CAAC;GACtB,IAAI,OAAO,IAAI;GACf,GAAG,OAAO,GAAG;EACf,OAAO,IAAI,kBAAkB,CAAC,GAAG;GAE/B,MAAM,MAAM,OAAO,KAAK,IAAI,OAAO,IAAI,MAAM;GAC7C,IAAI,UAAU,IAAI,sBAAsB;GACxC,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C,MAAM,SAAS,cAAc,CAAC;GAC9B,MAAM,KAAK,EAAE,YAAY,OAAO,KAAK;GACrC,MAAM,OAAO,KAAK,YAAY;IAC5B,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;IACrC,MAAM;IACN,QAAQ,OAAO;IACf,gBAAgB;IAChB,mBAAmB;IACnB,kBAAkB;IAClB,kBAAkB;GACpB,CAAC;GACD,KAAK,UAAU,IAAI,kBAAkB;GAErC,KAAK,MAAM,EAAE,QAAQ,CAAC;GACtB,IAAI,OAAO,IAAI;GACf,MAAM,OAAO,SAAS,EAAE,IAAI;GAC5B,MAAM,IAAI,eAAe,MAAM,GAAG,EAAE,QAAQ,EAAG,GAAG,GAAG,EAAE,QAAQ,EAAG,GAAG,EAAE;GACvE,IAAI,GAAG;IACL,MAAM,SAAS,KAAK,QAAQ;KAC1B;KACA,MAAM,eAAe,IAAI,IAAI,IAAI,OAAO,QAAQ;KAChD,QAAQ,OAAO;KACf,gBAAgB;KAChB,mBAAmB;KACnB,kBAAkB,SAAS,UAAU,SAAS,UAAU,SAAS;KACjE,kBAAkB;IACpB,CAAC;IACD,OAAO,aAAa,eAAe,MAAM;IACzC,IAAI,OAAO,MAAM;GACnB;GACA,GAAG,OAAO,GAAG;EACf;EAEA,MAAM,OAAO,IAAI,cAAc,KAAK;EACpC,KAAK,YAAY;EACjB,KAAK,cAAc,EAAE;EACrB,cAAc,MAAM,GAAG,CAAC;EACxB,IAAI,EAAE,QAAQ;GAEZ,MAAM,QAAQ,iBAAiB,GAAG,CAAC;GACnC,KAAK,MAAM,WAAW;GACtB,KAAK,MAAM,OAAO,GAAG,MAAM,KAAK;GAChC,KAAK,MAAM,MAAM,GAAG,MAAM,IAAI;GAC9B,KAAK,MAAM,QAAQ,GAAG,MAAM,MAAM;GAClC,KAAK,MAAM,SAAS,GAAG,MAAM,OAAO;EACtC;EAEA,KAAK,MAAM,gBAAgB;EAC3B,GAAG,OAAO,IAAI;EACd,qBAAqB,IAAI,GAAG,CAAC;EAC7B;CACF;CAEA,IAAI,EAAE,SAAS,SAAS;EACtB,GAAG,OAAO,WAAW,KAAK,GAAG,GAAG,GAAG,CAAC;EACpC;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,aAAa;IACtC,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,KAAK;GAChC,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;IACnC,GAAI,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,CAAC;GAChE,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,iBAAiB,MAAM;GACpD,MAAM,aAAa,UAAU,EAAE,KAAK;GACpC,MAAM,aAAa,gBAAgB,OAAO,EAAE,CAAC;GAC7C,KAAK,OAAO,EAAE,QAAQ,CAAC;GACvB,IAAI,OAAO,KAAK;GAChB,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK,SAAS;GAGZ,MAAM,KAAK,EAAE,YAAY,EAAE,KAAK;GAChC,MAAM,MAAM,KAAK,UAAU;IACzB,IAAI,IAAI,QAAQ;IAChB,IAAI,IAAI,SAAS;IACjB,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,IAAI,MAAM,IAAI,IAAI,KAAK,CAAC;IAC3D,MAAM;IACN,QAAQ,KAAK,IAAI,EAAE,QAAQ;IAC3B,gBAAgB;GAClB,CAAC;GACD,IAAI,UAAU,IAAI,eAAe;GACjC,IAAI,OAAO,GAAG;GACd,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK,QAAQ;GAIX,MAAM,QAAQ,YAAY;GAC1B,MAAM,QACJ,EAAE,UAAU,YACR,KAAK,WAAW;IACd,IAAI,IAAI,QAAQ;IAChB,IAAI,IAAI,SAAS;IACjB,IAAI,KAAK,IAAI,GAAG,IAAI,QAAQ,IAAI,KAAK;IACrC,IAAI,KAAK,IAAI,GAAG,IAAI,SAAS,IAAI,KAAK;GACxC,CAAC,IACD,KAAK,QAAQ;IACX,GAAG;IACH,GAAG;IACH,OAAO,KAAK,IAAI,GAAG,IAAI,QAAQ,SAAS;IACxC,QAAQ,KAAK,IAAI,GAAG,IAAI,SAAS,SAAS;GAC5C,CAAC;GACP,MAAM,aAAa,QAAQ,MAAM;GACjC,MAAM,aAAa,UAAU,aAAa;GAC1C,MAAM,aAAa,gBAAgB,OAAO,SAAS,CAAC;GACpD,MAAM,UAAU,IAAI,gBAAgB;GACpC,IAAI,OAAO,KAAK;GAChB;EACF;EACA,KAAK;EACL,KAAK;EACL,KAAK,WAAW;GACd,MAAM,MAAM,EAAE,SAAS,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE;GACrD,MAAM,UAAU,KAAK,EAAE,SAAS,YAAY,YAAY,YAAY;IAClE,QAAQ,IAAI,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG;IAC/B,MAAM,EAAE,SAAS,YAAa,EAAE,iBAAiB,SAAU;IAC3D,QAAQ,EAAE;IACV,gBAAgB,EAAE,YAAY,EAAE,KAAK;IACrC,mBAAmB;GACrB,CAAC;GACD,KAAK,SAAS,EAAE,QAAQ,CAAC;GACzB,IAAI,OAAO,OAAO;GAClB,MAAM,OAAO,YAAY,CAAC;GAC1B,IAAI,QAAQ,IAAI,UAAU,GACxB,KAAK,MAAM,CAAC,MAAM,MAAM,KAAK,UAAU,CACrC;IAAC;IAAQ,KAAK;IAAM,IAAI;IAAK,IAAI;GAAG,GACpC;IAAC;IAAQ,KAAK;IAAM,IAAI,IAAI,SAAS;IAAK,IAAI,IAAI,SAAS;GAAG,CAChE,GAAY;IACV,MAAM,IAAI,eAAe,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,YAAY,EAAE,KAAK,CAAC;IACzE,IAAI,CAAC,GAAG;IACR,MAAM,SAAS,KAAK,QAAQ;KAC1B;KACA,MAAM,eAAe,IAAI,IAAI,IAAI,EAAE,QAAQ;KAC3C,QAAQ,EAAE;KACV,gBAAgB,EAAE,YAAY,EAAE,KAAK;KACrC,mBAAmB;KAEnB,kBAAkB,SAAS,UAAU,SAAS,UAAU,SAAS;IACnE,CAAC;IACD,OAAO,aAAa,eAAe,IAAI;IACvC,IAAI,OAAO,MAAM;GACnB;GAEF,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;GAC7C;EACF;EACA,KAAK;GAGH,EAAE,QAAQ,SAAS,MAAM,MAAM;IAC7B,MAAM,UAAU,cACd,KAAK,IAAI,EAAE,GACX,EAAE,WAAW,IACb,EAAE,YAAY,EAAE,KAAK,CACvB;IACA,IAAI,OACF,KAAK,QAAQ;KAAE,OAAO;KAAc,GAAG,YAAY,OAAO;KAAG,MAAM,EAAE;IAAM,CAAC,CAC9E;GACF,CAAC;GACD,IAAI,aAAa,WAAW,OAAO,EAAE,OAAO,CAAC;CAEjD;CAEA,KAAK,MAAM,SAAS,IAAI,UAAU,MAAM,aAAa,kBAAkB,gBAAgB;CACvF,GAAG,OAAO,GAAG;CACb,oBAAoB,IAAI,GAAG,CAAC;AAC9B;;;;;;;;AASA,SAAS,WACP,KACA,GACA,GACA,KACkB;CAClB,MAAM,MAAM,IAAI,cAAc,KAAK;CACnC,IAAI,YAAY;CAChB,IAAI,MAAM;CACV,IAAI,YAAY;CAChB,IAAI,WAAW;CACf,IAAI,MAAM,EAAE;CACZ,MAAM,OAAO,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE;CAClE,MAAM,WAAW,SAAS,MAAM,SAAS;CACzC,MAAM,QAAQ,WAAW,IAAI,SAAS,IAAI;CAC1C,MAAM,SAAS,WAAW,IAAI,QAAQ,IAAI;CAC1C,IAAI,MAAM,WAAW;CACrB,IAAI,MAAM,OAAO,IAAI,IAAI,QAAQ,SAAS,EAAE;CAC5C,IAAI,MAAM,MAAM,IAAI,IAAI,SAAS,UAAU,EAAE;CAC7C,IAAI,MAAM,QAAQ,GAAG,MAAM;CAC3B,IAAI,MAAM,SAAS,GAAG,OAAO;CAC7B,IAAI,SAAS,GAAG,IAAI,MAAM,YAAY,UAAU,KAAK;CAErD,IAAI,MAAM,gBAAgB;CAC1B,IAAI,MAAM,YAAY,iBAAiB,OAAO,EAAE,OAAO,CAAC;CACxD,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,cACd,MACA,GACA,GACM;CACN,MAAM,IAAI,EAAE;CACZ,MAAM,OAAO,MAAc,UAAoC;EAC7D,IAAI,UAAU,KAAA,GAAW,KAAK,MAAM,eAAe,IAAI;OAClD,KAAK,MAAM,YAAY,MAAM,KAAK;CACzC;CACA,IAAI,mBAAmB,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG;CACvD,IAAI,qBAAqB,UAAU,EAAE,UAAU,CAAC;CAChD,IAAI,qBAAqB,EAAE,UAAU;CACrC,IAAI,oBAAoB,EAAE,SAAS;CACnC,IAAI,yBAAyB,EAAE,cAAc;CAC7C,IAAI,oBAAoB,EAAE,KAAK;CAE/B,MAAM,SAAS,SAAS,CAAC;CACzB,IAAI,cAAc,SAAS,KAAA,IAAY,EAAE,KAAK;CAG9C,IAAI,oBAAoB,SAAS,KAAA,IAAa,EAAE,eAAe,EAAE,KAAM;CACvE,IACE,sBACA,CAAC,UAAU,EAAE,QAAQ,IAAI,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAA,CAC3D;CACA,IACE,uBACA,CAAC,UAAU,EAAE,eAAe,GAAG,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,KAAA,CACrE;CACA,IAAI,iBAAiB,OAAO,EAAE,OAAO,CAAC;CACtC,KAAK,QAAQ,QAAQ,EAAE;CACvB,IAAI,QAAQ,KAAK,QAAQ,SAAS;MAC7B,OAAO,KAAK,QAAQ;CACzB,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,KAAK,QAAQ,SAAS,EAAE,QAAQ,SAAS,WAAW;MAC3E,OAAO,KAAK,QAAQ;AAC3B;;;;;AAMA,SAAgB,iBAAiB,GAAuB,GAA2B;CACjF,MAAM,SAAS,EAAE,UAAU,EAAE,IAAI;CACjC,MAAM,MAAM,EAAE,UAAU,YAAY,CAAC,CAAC;CACtC,OAAO;EACL,MAAM,IAAI,OAAO,OAAO;EACxB,KAAK,IAAI,MAAM,OAAO;EACtB,OAAO,IAAI;EACX,QAAQ,IAAI;CACd;AACF;;;;;;;AAQA,SAAgB,WACd,GACA,GACA,SAAwC,EAAE,UAAU,EAAE,IAAI,GAClD;CACR,MAAM,MAAM,EAAE,UAAU,YAAY,CAAC,CAAC;CAEtC,MAAM,SAAS,MAAoB;EACjC,MAAM,IAAI,EAAE,MAAM,CAAC;EACnB,OAAO;GAAE,GAAG,EAAE,IAAI,IAAI;GAAM,GAAG,EAAE,IAAI,IAAI;EAAI;CAC/C;CACA,MAAM,MAAM,MAAM,EAAE,QAAQ,EAAG;CAC/B,MAAM,OAAO,MAAM,EAAE,QAAQ,EAAE,QAAQ,SAAS,EAAG;CACnD,MAAM,IAAI,IAAI;CACd,MAAM,IAAI,IAAI;CACd,MAAM,IAAI,KAAK,IAAI,EAAE,YAAY,EAAE,gBAAgB,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;CAGnE,MAAM,OAAO;EACX,MAAM,KAAK,IAAI,KAAK,CAAC;EACrB,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;EAC1B,QAAQ,KAAK,IAAI,KAAK,IAAI,CAAC;EAC3B,KAAK,KAAK,IAAI,KAAK,CAAC;CACtB;CACA,MAAM,OAAQ,OAAO,KAAK,IAAI,CAAC,CAA2B,QAAQ,MAAM,MACtE,KAAK,KAAK,KAAK,QAAQ,IAAI,IAC7B;CACA,MAAM,QAAQ,SAAS,SAAS,SAAS,WAAW,IAAI;CACxD,MAAM,OAAO,KAAK,IAAI,EAAE,YAAA,CAAsB,GAAG,QAAQ,CAAC;CAC1D,MAAM,KAAK,KAAK,IAAI,IAAI,MAAM,QAAQ,CAAC;CACvC,MAAM,KAAK,KAAK,IACd,KAAK,IAAI,SAAS,SAAS,SAAS,WAAW,KAAK,IAAI,KAAK,GAAG,EAAE,GAClE,QAAQ,EACV;CACA,MAAM,KAAK,IAAI,OAAO,OAAO;CAC7B,MAAM,KAAK,IAAI,MAAM,OAAO;CAC5B,MAAM,KAAK,GAAW,MAAsB,GAAGE,MAAI,IAAI,EAAE,EAAE,GAAGA,MAAI,IAAI,EAAE;CACxE,MAAM,OAAO,GAAW,MACtB,IAAI,IAAI,IAAIA,MAAI,CAAC,EAAE,GAAGA,MAAI,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM;CACpD,MAAM,SAAS,GAAW,MAAsB,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;CAC7E,OAAO;EACL,IAAI,EAAE,GAAG,CAAC;EACV,SAAS,QAAQ,GAAG,MAAM,KAAK,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,MAAM;EAC/D,IAAI,EAAE,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC;EAC1B,SAAS,UAAU,GAAG,MAAM,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,MAAM;EACjE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC;EAC9B,SAAS,WAAW,GAAG,MAAM,KAAK,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,MAAM;EAClE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC;EAC1B,SAAS,SAAS,GAAG,MAAM,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,MAAM;EAChE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE;CAC1B,CAAC,CAAC,KAAK,EAAE;AACX;;;;;AAMA,SAAgB,YACd,IACA,GACA,GACA,QACM;CACN,MAAM,OAAO,GAAG,cAAc,4BAA4B;CAC1D,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG;CAC3B,KAAK,aAAa,KAAK,WAAW,GAAG,GAAG,MAAM,CAAC;AACjD;;AAGA,SAAS,KACP,OACA,QACA,GACM;CACN,IAAI,CAAC,UAAU,OAAO,WAAW,GAAG;CACpC,MAAM,aAAa,oBAAoB,OAAO,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AACtF;;;;;AAMA,SAAgB,cAAc,IAAiB,GAAe,GAAwB;CACpF,YAAY,IAAI,GAAG,CAAC;CACpB,IAAI,EAAE,SAAS,YAAY,qBAAqB,IAAI,GAAG,CAAC;CACxD,oBAAoB,IAAI,GAAG,CAAC;AAC9B;;;;;;AAOA,SAAS,qBACP,IACA,GACA,GACM;CACN,GAAG,gBAAgB,eAAe,EAAE,WAAW,KAAA,CAAS;CACxD,IAAI,CAAC,EAAE,QAAQ;CACf,MAAM,MAAM,iBAAiB,GAAG,CAAC;CACjC,MAAM,QAAQ,GAAG,cAAc,cAAc,KAAK;CAClD,MAAM,YAAY;CAClB,MAAM,aAAa,eAAe,MAAM;CACxC,MAAM,MAAM,UACV,8CAA8C,IAAI,KAAK,SAAS,IAAI,IAAI,WAC/D,IAAI,MAAM,YAAY,IAAI,OAAO;CAC5C,GAAG,OAAO,KAAK;AACjB;;AAGA,SAAgB,WAAW,GAA0C;CACnE,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,KAAK;AAC/C;;;;;;AAOA,SAAS,oBAAoB,IAAiB,GAAe,GAAwB;CACnF,IAAI,CAAC,WAAW,CAAC,GAAG;CACpB,MAAM,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS;CACtC,IAAI,CAAC,MAAM;CACX,MAAM,MAAM,cAAc,GAAG,CAAC;CAC9B,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE;CAC1B,MAAM,SAAS,GAAG,cAAc,cAAc,MAAM;CACpD,OAAO,YAAY;CACnB,OAAO,QAAQ,mBAAmB;CAClC,OAAO,aAAa,eAAe,MAAM;CACzC,OAAO,MAAM,OAAO,GAAG,GAAG,IAAI,IAAI,KAAK;CACvC,OAAO,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI;CACrC,MAAM,OAAO,GAAG,cAAc,gBAAgBF,OAAK,KAAK;CACxD,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,eAAe,GAAG,KAAK,aAAa,GAAG,CAAC;CAC5E,KAAK,MAAM,CAAC,KAAK,UAAU,mBAAmB;EAC5C,MAAM,QAAQ,GAAG,cAAc,gBAAgBA,OAAK,GAAG;EACvD,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG,MAAM,aAAa,GAAG,CAAC;EACnE,KAAK,OAAO,KAAK;CACnB;CACA,OAAO,OAAO,IAAI;CAClB,GAAG,OAAO,MAAM;AAClB;AAEA,SAAS,YAAY,IAAiB,GAAe,GAAwB;CAC3E,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;;;;AC7zBA,MAAM,0BAAU,IAAI,QAAqC;;AAEzD,MAAM,iCAAiB,IAAI,QAAe;;AAG1C,SAAgB,UAAU,IAA6C;CACrE,OAAO,QAAQ,IAAI,EAAE;AACvB;;AAGA,SAAgB,aAAa,GAAmB;CAC9C,OAAO,eAAe,IAAI,CAAC;AAC7B;;AAGA,MAAM,UAAU;;AAEhB,MAAM,eAAe;;;;;;;;AASrB,SAAgB,aACd,IACA,GACA,MACgB;CAChB,QAAQ,IAAI,EAAE,CAAC,EAAE,MAAM,IAAI;CAC3B,MAAM,MAAM,GAAG;CACf,MAAM,OAAO,IAAI;CAEjB,MAAM,OAAO,KAAK,UAAU,UAAU,EAAE,IAAI;CAC5C,MAAM,QAAQ,iBAAiB,GAAG,KAAK,SAAS;CAChD,MAAM,MAAM,GAAG,cAA2B,yBAAyB;CAEnE,MAAM,QAAQ,IAAI,cAAc,KAAK;CACrC,MAAM,YAAY;CAClB,MAAM,QAAQ,YAAY;CAC1B,MAAM,aAAa,QAAQ,SAAS;CACpC,MAAM,aAAa,kBAAkB,MAAM;CAC3C,MAAM,aAAa,cAAc,UAAU;CAC3C,cAAc,OAAO,GAAG,KAAK,SAAS;CACtC,MAAM,MAAM,WAAW;CACvB,MAAM,MAAM,OAAO,GAAG,MAAM,KAAK;CACjC,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI;CAE/B,MAAM,QAAQ,KAAK,UAAU,YAAY,EAAE,aAAa,WAAW,YAAY;CAC/E,MAAM,MAAM,QAAQ,EAAE,SAAS,GAAG,KAAK,IAAI,MAAM,OAAO,KAAK,EAAE,MAAM;CACrE,MAAM,MAAM,SAAS;CACrB,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO;CACxC,MAAM,MAAM,gBAAgB;CAC5B,aAAa,KAAK;CAClB,MAAM,cAAc,EAAE;CACtB,IAAI,KAAK,IAAI,MAAM,aAAa;CAChC,GAAG,OAAO,KAAK;;CAGf,MAAM,eACJ,KAAK,IAAI,MAAM,QAAQ,MAAM,sBAAsB,CAAC,CAAC,MAAM;;CAE7D,MAAM,WAAW,UACf,UAAU,IAAI,IAAI;EAAE,GAAG;EAAG,GAAG,cAAc,GAAG,OAAO,KAAK,SAAS;CAAE;CACvE,MAAM,aAAmB;EACvB,MAAM,IAAI,OAAO;EACjB,GAAG,MAAM,SAAS,GAAG,KAAK,SAAS,IAAI,MAAM,OAAO;EAEpD,YAAY,IAAI,QAAQ,IAAI,MAAM,MAAM,GAAG,KAAK,WAAW,IAAI;CACjE;CACA,MAAM,WAAW,MAAM;CACvB,MAAM,WAAW,WAAW,IAAI,SAAS,IAAI,IAAI,KAAA;CACjD,UAAU,QAAQ,KAAK;CAEvB,MAAM,aAAqB;EACzB,MAAM,OAAO,MAAM,UAAU,QAAQ,UAAU,IAAI;EAEnD,OAAO,MAAM,WAAW,aAAa,OAAO,KAAK,QAAQ,OAAO,EAAE,IAAI;CACxE;;CAEA,MAAM,eAAuB;EAC3B,MAAM,QAAQ,OAAO,IAAI,MAAM;EAC/B,OAAO,KAAK,IAAI,KAAK,IAAI,UAAU,IAAI;CACzC;CAEA,IAAI,SAAS;CACb,MAAM,UAAU,WAA0B;EACxC,IAAI,QAAQ;EACZ,SAAS;EACT,MAAM,WAAW,KAAK;EACtB,MAAM,QAAQ,OAAO;EACrB,MAAM,OAAO,QAAQ,KAAK,CAAC,CAAC;EAC5B,UAAU,WAAW;EACrB,MAAM,oBAAoB,eAAe,WAAW,IAAI;EACxD,QAAQ,OAAO,EAAE;EAGjB,IAAI,MAAM,SAAS,IAAI,aAAa,GAAG,GAAG,MAAM,EAAE,eAAe,KAAK,CAAC;EACvE,MAAM,OAAO;EACb,KAAK,MAAM,eAAe,YAAY;EACtC,GAAG,MAAM,SAAS,GAAG,KAAK,OAAO;EACjC,YAAY,IAAI,GAAG,KAAK,WAAW,IAAI;EACvC,IAAI,QAAQ,KAAK,OAAO,UAAU,MAAM,KAAK;OACxC,KAAK,OAAO;CACnB;CAEA,MAAM,aAAa,MAAmB;EACpC,IAAI,EAAE,kBAAkB,QAAQ,MAAM,SAAS,EAAE,MAAM,GAAG;EAC1D,eAAe,IAAI,CAAC;EACpB,OAAO,IAAI;CACb;CACA,MAAM,iBAAiB,eAAe,WAAW,IAAI;CACrD,MAAM,iBAAiB,YAAY,MAAM;EACvC,EAAE,gBAAgB;EAClB,IAAI,EAAE,QAAQ,YAAY,CAAC,EAAE,aAAa;GACxC,EAAE,eAAe;GACjB,OAAO,IAAI;EACb;CACF,CAAC;CACD,MAAM,iBAAiB,aAAa,MAAM;EAExC,IAAI,CAAC,IAAI,SAAS,GAAG;EACrB,MAAM,KAAK,EAAE;EACb,IAAI,cAAc,QAAQ,MAAM,SAAS,EAAE,GAAG;EAC9C,OAAO,IAAI;CACb,CAAC;CAED,MAAM,iBAAiB,UAAU,MAAM;EACrC,EAAE,eAAe;EACjB,WAAW,OAAO,EAAE,eAAe,QAAQ,YAAY,KAAK,EAAE;CAChE,CAAC;CACD,MAAM,iBAAiB,gBAAgB,MAAM;EAC3C,IAAI,EAAE,UAAU,WAAW,QAAQ,GAAG,EAAE,eAAe;CACzD,CAAC;CAED,MAAM,MAAM,EAAE,eAAe,KAAK,CAAC;CACnC,MAAM,YAAY,IAAI,aAAa;CACnC,IAAI,WAAW;EACb,MAAM,QAAQ,IAAI,YAAY;EAC9B,MAAM,mBAAmB,KAAK;EAC9B,MAAM,SAAS,KAAK;EACpB,UAAU,gBAAgB;EAC1B,UAAU,SAAS,KAAK;CAC1B;CACA,KAAK;CAEL,MAAM,SAAyB,EAAE,QAAQ,WAAW,OAAO,MAAM,EAAE;CACnE,QAAQ,IAAI,IAAI,MAAM;CACtB,OAAO;AACT;;;;;;AAOA,SAAgB,gBACd,GACA,IACyB;CACzB,OACE,MAAM,KAAA,KACN,EAAE,SAAS,cACX,CAAC,EAAE,UACH,EAAE,WAAW,SACb,CAAC,CAAC,MACF,CAAC,GAAG,aAAa,aAAa;AAElC;;;;;;;;AASA,SAAgB,eACd,OACA,IACA,IACA,WAC4B;CAC5B,MAAM,IAAI,MAAM,aAAa,EAAE,KAAK,MAAM,IAAI,EAAE;CAChD,IAAI,CAAC,gBAAgB,GAAG,EAAE,GAAG,OAAO,KAAA;CACpC,MAAM,gBAAgD;EACpD,MAAM,MAAM,MAAM,aAAa,EAAE,KAAK,MAAM,IAAI,EAAE;EAClD,OAAO,KAAK,SAAS,aAAa,MAAM,KAAA;CAC1C;CACA,OAAO,aAAa,IAAI,GAAG;EACzB;EACA,OAAO,UAAU,OAAO,OAAO;GAC7B,MAAM,MAAM,QAAQ;GACpB,IAAI,CAAC,KAAK;GACV,IAAI,SAAS,KAAK,MAAM,MAAM,CAAC,SAAS,GAAG,GAAG;IAC5C,MAAM,OAAO,EAAE;IACf;GACF;GAEA,IAAI,UAAU,GAAG;IACf,IAAI,aAAa,IAAI,UAAU,MAAM,OAAO,IAAI,EAAE,SAAS,CAAC;IAC5D;GACF;GACA,MAAM,OAAO,IAAI;IAAE;IAAU,GAAG,cAAc,KAAK,OAAO,SAAS;GAAE,CAAC;EACxE;EACA,SAAS;GACP,MAAM,MAAM,QAAQ;GACpB,IAAI,OAAO,IAAI,SAAS,KAAK,MAAM,MAAM,CAAC,SAAS,GAAG,GAAG,MAAM,OAAO,EAAE;EAC1E;CACF,CAAC;AACH;;;;;;;AAQA,SAAgB,cACd,GACA,OACA,GAC6B;CAC7B,MAAM,MAAM,EAAE,UAAU,YAAY,CAAC,CAAC;CACtC,MAAM,MAAM,EAAE,YAAY;EAAE,GAAG;EAAK,QAAQ,IAAI,SAAS;CAAM,CAAC;CAChE,IAAI,CAAC,WAAW,CAAC,GAAG,OAAO,QAAQ,GAAG,GAAG;CACzC,MAAM,UAAU,WAAW,GAAG,GAAG;CACjC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,IAAI,MAAM,IAAI,QAAQ,OAAO;CAC5E,MAAM,OAAO,EAAE,QAAQ,SAAS;CAChC,MAAM,QAAQ,MAAoB;EAChC,MAAM,IAAI,EAAE,MAAM,CAAC;EACnB,OAAO,EAAE,QAAQ;GAAE,GAAG,EAAE;GAAG,GAAG,EAAE,IAAI;EAAM,CAAC;CAC7C;CACA,OAAO,QACL,GACA,KACA,QAAQ,QAAS,KAAK,GAAG,MAAO,MAAM,OAAO,IAAI,KAAK,CAAC,CAAE,CAC3D;AACF;;AAGA,SAAS,aAAa,OAA0B;CAC9C,IAAI;EACF,MAAM,kBAAkB;CAC1B,QAAQ,CAER;CACA,IAAI,MAAM,oBAAoB,kBAAkB,MAAM,kBAAkB;AAC1E;;AAGA,SAAS,WAAW,OAAoB,MAAoB;CAC1D,MAAM,MAAM,MAAM;CAClB,MAAM,YAAY,IAAI,aAAa;CACnC,MAAM,OAAO,IAAI,eAAe,IAAI;CACpC,IAAI,CAAC,aAAa,UAAU,eAAe,GAAG;EAC5C,MAAM,OAAO,IAAI;EACjB;CACF;CACA,MAAM,QAAQ,UAAU,WAAW,CAAC;CACpC,IAAI,CAAC,MAAM,SAAS,MAAM,uBAAuB,GAAG;EAClD,MAAM,OAAO,IAAI;EACjB;CACF;CACA,MAAM,eAAe;CACrB,MAAM,WAAW,IAAI;CACrB,MAAM,cAAc,IAAI;CACxB,MAAM,SAAS,IAAI;CACnB,UAAU,gBAAgB;CAC1B,UAAU,SAAS,KAAK;AAC1B;;;AC9SA,MAAM,kBAAkB,UACrB,OAAqC,SAAS;;;;;;;;;;;;;AAcjD,eAAsB,aACpB,KACA,MACA,UACA,OACA,QACA,QACA,UACe;CACf,QAAQ,eAAe;CACvB,MAAM,UAAU,MAAM,IAAI,OAAO,QAAQ,IAAI;CAC7C,QAAQ,eAAe;CACvB,MAAM,OAAO,YAAY,QAAQ;CACjC,MAAM,OAAO,QAAQ,YAAY;EAAE;EAAO,UAAU;CAAK,CAAC;CAE1D,MAAM,CAAC,IAAI,MAAM,KAAK,uBAAuB,SAAS,GAAG,SAAS,CAAC;CACnE,MAAM,CAAC,IAAI,MAAM,KAAK,uBACpB,SAAS,IAAI,SAAS,OACtB,SAAS,IAAI,SAAS,MACxB;CACA,MAAM,WAAW,QAAQ,YAAY;EACnC;EACA,UAAU;EACV,SAAS,CAAC,KAAK,IAAI,IAAI,EAAE;EACzB,SAAS,CAAC,KAAK,IAAI,IAAI,EAAE;CAC3B,CAAC;CACD,OAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;CACxD,OAAO,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;CACzD,MAAM,OAAO,QAAQ,OAAO;EAC1B;EACA;EACA,YAAY;EACZ,gBAAgB,IAAI,OAAO,OAAO,eAAe;CACnD,CAAC;CACD,MAAM,eAAqB,KAAK,OAAO;CACvC,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,MAAM,KAAK,CAAC;CACxD,IAAI;EACF,MAAM,KAAK;CACb,SAAS,OAAO;EACd,IAAI,QAAQ,WAAW,eAAe,KAAK,GAAG,MAAM,OAAO;EAC3D,MAAM;CACR,UAAU;EACR,QAAQ,oBAAoB,SAAS,MAAM;CAC7C;CAEA,QAAQ,eAAe;AACzB;;ACvBA,SAAgB,YAAY,GAA0D;CACpF,MAAM,EAAE,MAAM,kBAAkB;CAChC,MAAM,QAAQ,KAAK,QAAQ;CAC3B,MAAM,SAAS,KAAK,SAAS;CAC7B,OAAO;EACL,GAAG,KAAK,KAAK,KAAK,QAAQ,SAAS;EACnC,GAAG,KAAK,KAAK,KAAK,SAAS,UAAU;EACrC;EACA;CACF;AACF;;AAaA,SAAS,QAAQ,QAAiC;CAChD,OAAO,QAAQ;CACf,OAAO,SAAS;CAChB,OAAO,OAAO;AAChB;AAEA,SAAgB,iBAAiB,MAAqC;CACpE,MAAM,yBAAS,IAAI,IAAkB;CACrC,IAAI,YAAY;CAChB,IAAI;CAEJ,MAAM,SAAS,OAA4B;EACzC,IAAI,KAAK,qBAAqB,KAAA,GAAW,OAAO,KAAK;EACrD,MAAM,QAAQ,GAAG,cAAc,aAAa,oBAAoB;EAChE,OAAO,QAAQ,IAAI,QAAQ;CAC7B;CAEA,MAAM,QAAQ,SAAqB;EACjC,aAAa,KAAK,KAAK;EACvB,KAAK,QAAQ,KAAA;EACb,KAAK,YAAY,MAAM;EACvB,KAAK,aAAa,KAAA;CACpB;CAEA,eAAe,OACb,MACA,MACA,QACA,OACA,UACe;EACf,MAAM,aAAa,IAAI,gBAAgB;EACvC,KAAK,aAAa;EAElB,MAAM,OADM,KAAK,OAAO,cACP,cAAc,QAAQ;EACvC,IAAI;GACF,MAAM,aACJ,KAAK,UACL,MACA,QACA,OACA,MACA,WAAW,QACX,QACF;GACA,IAAI,WAAW,OAAO,WAAW,WAAW;GAC5C,KAAK,OAAO,QAAQ,KAAK;GACzB,KAAK,OAAO,SAAS,KAAK;GAC1B,KAAK,OAAO,WAAW,IAAI,CAAC,EAAE,UAAU,MAAM,GAAG,CAAC;EACpD,QAAQ,CAGR,UAAU;GACR,QAAQ,IAAI;GACZ,IAAI,KAAK,eAAe,YAAY,KAAK,aAAa,KAAA;EACxD;CACF;CAEA,SAAS,QAAQ,IAAiB,IAAkB;EAClD,MAAM,QAAQ,OAAO,IAAI,EAAE;EAC3B,IAAI,OAAO,OAAO;EAClB,MAAM,SAAS,GAAG,cAAc,cAAc,QAAQ;EACtD,OAAO,YAAY;EACnB,OAAO,QAAQ,WAAW;EAC1B,OAAO,aAAa,eAAe,MAAM;EACzC,OAAO,MAAM,UACX;EAGF,OAAO,QAAQ;EACf,OAAO,SAAS;EAChB,MAAM,OAAa;GACjB;GACA,KAAK,KAAA;GACL,OAAO,KAAA;GACP,YAAY,KAAA;GACZ,MAAM,KAAA;EACR;EACA,OAAO,IAAI,IAAI,IAAI;EACnB,OAAO;CACT;CAEA,SAAS,OAAO,IAAiB,GAAoB,GAAwB;EAC3E,IAAI,WAAW;EACf,MAAM,OAAO,QAAQ,IAAI,EAAE,EAAE;EAC7B,KAAK,OAAO;GAAE;GAAI;GAAG;EAAE;EACvB,IAAI,GAAG,eAAe,KAAK,QAAQ,GAAG,QAAQ,KAAK,MAAM;EACzD,MAAM,SAAS,YAAY,CAAC;EAC5B,MAAM,MAAM,MAAM,EAAE;EACpB,IAAI,KAAK,qBAAqB,KAAA,GAAW;GACvC,aAAa,sBACX,GAAG,cAAc,mBACX,MAAM,EAAE,SACR;IACJ,KAAK,MAAM,EAAE,UAAU,CAAC,GAAG,OAAO,OAAO,CAAC,GACxC,IAAI,MAAM,OAAO,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC;GAC5C,CACF;GACA,SAAS,MAAM,GAAG;EACpB;EACA,MAAM,QAAQ,EAAE,OAAO,MAAM,EAAE;EAC/B,MAAM,WAAW,EAAE;EACnB,MAAM,MAAM,KAAK,UAAU;GAAC,EAAE;GAAM;GAAQ;GAAO;EAAQ,CAAC;EAC5D,IAAI,QAAQ,KAAK,KAAK;EACtB,MAAM,QAAQ,KAAK,QAAQ,KAAA;EAC3B,KAAK,MAAM;EACX,KAAK,IAAI;EACT,IAAI,OAAO;GACT,OAAY,MAAM,EAAE,MAAM,QAAQ,OAAO,QAAQ;GACjD;EACF;EACA,KAAK,QAAQ,iBAAiB;GAC5B,KAAK,QAAQ,KAAA;GACb,OAAY,MAAM,EAAE,MAAM,QAAQ,OAAO,QAAQ;EACnD,GAAA,GAAqB;CACvB;CAEA,OAAO;EACL;EACA,KAAK,IAAI;GACP,MAAM,OAAO,OAAO,IAAI,EAAE;GAC1B,IAAI,CAAC,MAAM;GACX,KAAK,IAAI;GACT,QAAQ,KAAK,MAAM;GACnB,OAAO,OAAO,EAAE;EAClB;EACA,UAAU;GACR,IAAI,WAAW;GACf,YAAY;GACZ,UAAU,QAAQ;GAClB,KAAK,MAAM,QAAQ,OAAO,OAAO,GAAG;IAClC,KAAK,IAAI;IACT,QAAQ,KAAK,MAAM;GACrB;GACA,OAAO,MAAM;EACf;CACF;AACF;;;ACjMA,MAAMG,QAAM;AAEZ,MAAM,OAAO,MAAsB,OAAO,KAAK,MAAM,IAAI,GAAI,IAAI,GAAI;;;;;;;AAQrE,SAAgB,SACd,GACA,GACQ;CACR,MAAM,IAAI,EAAE;CACZ,MAAM,IAAI,EAAE;CACZ,MAAM,OAAO,QAAQ,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;CAC9D,MAAM,EAAE,MAAM,KAAK,OAAO,WAAW,EAAE,UAAU,EAAE,IAAI;CACvD,IAAI,EAAE,UAAU,WAAW;EACzB,MAAM,KAAK,QAAQ;EACnB,MAAM,KAAK,SAAS;EACpB,MAAM,KAAK,MAAM;EACjB,MAAM,MAAM,IAAI,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE;EACnC,OAAO,GAAG,KAAK,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,EAAE,GAAG,IAAI,EAAE,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE;CAC7G;CACA,MAAM,QAAQ,OAAO;CACrB,MAAM,SAAS,MAAM;CACrB,OAAO,GAAG,KAAK,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,MAAM,EAAE;AAC7H;;AASA,SAAgB,gBAAgB,MAAmB,QAAyB;CAC1E,IAAI;CACJ,IAAI;CAEJ,OAAO;EACL,OAAO,MAAM,GAAG;GACd,IAAI,CAAC,MAAM;IACT,KAAK,OAAO;IACZ,MAAM,KAAA;IACN,OAAO,KAAA;IACP;GACF;GACA,IAAI,CAAC,OAAO,CAAC,MAAM;IACjB,MAAM,MAAM,KAAK;IACjB,MAAM,IAAI,gBAAgBA,OAAK,KAAK;IACpC,IAAI,UAAU,IAAI,gBAAgB;IAClC,IAAI,QAAQ,eAAe;IAC3B,IAAI,aAAa,eAAe,MAAM;IACtC,IAAI,MAAM,UAAU;IACpB,OAAO,IAAI,gBAAgBA,OAAK,MAAM;IACtC,KAAK,aAAa,aAAa,SAAS;IACxC,KAAK,aAAa,aAAa,SAAS;IACxC,KAAK,aAAa,UAAU,MAAM;IAClC,IAAI,OAAO,IAAI;GACjB;GACA,IAAI,IAAI,eAAe,QAAQ,IAAI,gBAAgB,QACjD,KAAK,aAAa,KAAK,MAAM;GAC/B,IAAI,aAAa,SAAS,OAAO,EAAE,QAAQ,CAAC;GAC5C,IAAI,aAAa,UAAU,OAAO,EAAE,SAAS,CAAC;GAC9C,IAAI,aAAa,WAAW,OAAO,EAAE,SAAS,GAAG,EAAE,WAAW;GAC9D,KAAK,aAAa,KAAK,SAAS,MAAM,CAAC,CAAC;GACxC,KAAK,aAAa,QAAQ,KAAK,KAAK;GACpC,KAAK,aAAa,gBAAgB,OAAO,KAAK,GAAG,CAAC;EACpD;EACA,UAAU;GACR,KAAK,OAAO;GACZ,MAAM,KAAA;GACN,OAAO,KAAA;EACT;CACF;AACF;;;;ACHA,MAAM,aAAa;;AAEnB,MAAM,WAAW;;AAGjB,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,OAAO;CACP,OAAO;CACP,MAAM;CACN,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,EAAE,YAAY,gBAAgB,EAAE,SAAS,SAAS,EAAE,SAAS,WAC3D,cACA,OAAO,EAAE;CACjB,MAAM,QAAQ,WAAW,CAAC,IAAI,GAAG,KAAK,iBAAiB;CACvD,OAAO,EAAE,SAAS,GAAG,MAAM,MAAM,EAAE,WAAW;AAChD;;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;CAC9C,MAAM,QAAQ,gBAAgB,KAAK,MAAM,IAAI;CAC7C,MAAM,SAAS,KAAK,WAChB,iBAAiB;EACf,UAAU,KAAK;EACf,GAAI,KAAK,qBAAqB,KAAA,IAC1B,CAAC,IACD,EAAE,kBAAkB,KAAK,iBAAiB;CAChD,CAAC,IACD,KAAA;;CAEJ,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,KAAK,CAAC,EAAE,UAAU,UAAU,cAAc,iBAAiB,IACvD,WAAW,MAAM,CAAC,IAClB,EAAE,MAAM,OAAO,CACrB;CACF;;;;;CAMA,SAAS,WAAW,MAAmB,GAA2B;EAChE,MAAM,OAAO,WAAW,KAAK,MAAM,IAAI,KAAK;EAC5C,MAAM,MAAM,WAAW,KAAK,MAAM,GAAG,KAAK;EAC1C,IAAI,EAAE,SAAS,QAAQ;GACrB,MAAM,SAAS,MAAoB;IACjC,MAAM,IAAI,UAAU,MAAM,CAAC;IAC3B,OAAO;KAAE,GAAG,EAAE,IAAI;KAAM,GAAG,EAAE,IAAI;IAAI;GACvC;GACA,OAAO;IAAE,MAAM;IAAQ,OAAO,MAAM,EAAE,KAAK;IAAG,KAAK,MAAM,EAAE,GAAG;GAAE;EAClE;EACA,IAAI,CAAC,iBAAiB,CAAC,GAAG,OAAO,EAAE,MAAM,OAAO;EAChD,MAAM,UACJ,EAAE,SAAS,aACP;GAAE,MAAM;GAAoB,GAAG,iBAAiB,GAAG,SAAS;EAAE,IAC9D;GACE,MAAM;GACN,OAAO,WAAW,KAAK,MAAM,KAAK,KAAK;GACvC,QAAQ,WAAW,KAAK,MAAM,MAAM,KAAK;EAC3C;EACN,IAAI,CAAC,WAAW,CAAC,GAAG,OAAO;EAC3B,MAAM,MAAM,UAAU,MAAM,EAAE,QAAQ,EAAE;EACxC,OAAO;GAAE,GAAG;GAAS,MAAM;IAAE,GAAG,IAAI,IAAI;IAAM,GAAG,IAAI,IAAI;GAAI;EAAE;CACjE;;;;;CAMA,SAAS,mBAA4B;EACnC,MAAM,OAAO,KAAK,KAAK,QAAQ,iBAAiB,CAAC,EAAE,aAAa,eAAe;EAC/E,OAAO,SAAS,YAAY,SAAS;CACvC;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;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,QAAQ,KAAK,EAAE,EAAE;GACjB,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,IAAI,EAAE,SAAS,SAAS,QAAQ,OAAO,MAAM,GAAG,SAAS;EACzD,MAAM,IAAI,EAAE,IAAI;GAAE;GAAG,GAAG;EAAU,CAAC;CACrC;;;;;CAMA,SAAS,KAAK,IAAqB;EACjC,MAAM,IAAI,MAAM,IAAI,EAAE;EACtB,MAAM,OAAO,SAAS,IAAI,EAAE;EAC5B,IAAI,CAAC,QAAQ,CAAC,gBAAgB,GAAG,IAAI,KAAK,KAAK,WAAW,CAAC,MAAM,MAAM,OAAO;EAC9E,IAAI,UAAU,IAAI,GAAG,OAAO;EAC5B,OAAO,eAAe,OAAO,MAAM,IAAI,SAAS,MAAM,KAAA;CACxD;;CAGA,SAAS,eAAqB;EAC5B,KAAK,MAAM,QAAQ,SAAS,OAAO,GAAG,UAAU,IAAI,CAAC,EAAE,MAAM,IAAI;CACnE;CAEA,SAAS,SAAS,IAAkB;EAClC,MAAM,OAAO,CAAC,EAAE,CAAC;EACjB,KAAK,aAAa,EAAE;CACtB;;CAGA,IAAI;;;;;;;CAQJ,SAAS,YAAY,GAAiB,IAAkB;EAEtD,EAAE,eAAe;EACjB,cAAc;EACd,MAAM,OAAO,IAAI;EACjB,IAAI,CAAC,MAAM;EACX,MAAM,EAAE,SAAS,IAAI,SAAS,IAAI,WAAW,WAAW,OAAO;EAC/D,IAAI;EACJ,IAAI,WAAW;EACf,MAAM,QAAQ,OAA8B,GAAG,cAAc;EAC7D,MAAM,UAAU,OAA2B;GACzC,IAAI,CAAC,KAAK,EAAE,GAAG;GACf,IAAI,GAAG,YAAY,GAAG,OAAO,IAAI;GACjC,IAAI,CAAC,YAAY,KAAK,MAAM,GAAG,UAAU,IAAI,GAAG,UAAU,EAAE,KAAK,YAAY;GAC7E,WAAW;GACX,WAAW,QAAQ,IAAI,EAAE;GACzB,MAAM,QAAQ,QAAQ,GAAG,SAAS,GAAG,OAAO;GAC5C,IAAI,UAAU,OACZ,IACG,aAAa,CAAC,EACb,iBAAiB,OAAO,MAAM,OAAO,QAAQ,MAAM,MAAM,MAAM,MAAM;EAC7E;EACA,MAAM,QAAQ,OAA2B;GACvC,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,GAAG;GAClC,IAAI;GACJ,IACE,CAAC,YACD,CAAC,aACD,KAAK,MAAM,GAAG,UAAU,IAAI,GAAG,UAAU,EAAE,KAAK,cAChD,GAAG,YAAY,MAAM,YACrB,MAAM,IAAI,EAAE,GACZ;IACA,IAAI,EAAE,EAAE,YAAY,GAAG,WAAW,OAAO,SAAS,EAAE;IAEpD,MAAM,WAAW,MAAM,UAAU,IAAI;IACrC,MAAM,OACJ,SAAS,SAAS,EAAE,IAAI,SAAS,QAAQ,MAAM,MAAM,EAAE,IAAI,CAAC,GAAG,UAAU,EAAE,CAC7E;GACF;EACF;EACA,MAAM,YAAY,OAA2B;GAC3C,IAAI,KAAK,EAAE,GAAG,IAAI;EACpB;EACA,MAAM,YAAkB;GACtB,KAAK,oBAAoB,eAAe,QAAQ,IAAI;GACpD,KAAK,oBAAoB,aAAa,MAAM,IAAI;GAChD,KAAK,oBAAoB,iBAAiB,UAAU,IAAI;GACxD,IAAI,gBAAgB,KAAK,cAAc,KAAA;EACzC;EAGA,KAAK,iBAAiB,eAAe,QAAQ,IAAI;EACjD,KAAK,iBAAiB,aAAa,MAAM,IAAI;EAC7C,KAAK,iBAAiB,iBAAiB,UAAU,IAAI;EACrD,cAAc;CAChB;;;;;CAMA,SAAS,QAAQ,GAAW,GAA8B;EACxD,MAAM,aAAa,KAAK,MAAM;EAC9B,KAAK,MAAM,aAAa;EACxB,IAAI;EACJ,IAAI;GACF,IAAI,OAAO,IAAI,2BAA2B,YAAY;IACpD,MAAM,IAAI,IAAI,uBAAuB,GAAG,CAAC;IACzC,IAAI,GAAG,QAAQ;KAAE,MAAM,EAAE;KAAY,QAAQ,EAAE;IAAO;GACxD,OAAO,IAAI,OAAO,IAAI,wBAAwB,YAAY;IACxD,MAAM,IAAI,IAAI,oBAAoB,GAAG,CAAC;IACtC,IAAI,GAAG,QAAQ;KAAE,MAAM,EAAE;KAAgB,QAAQ,EAAE;IAAY;GACjE;EACF,UAAU;GACR,KAAK,MAAM,aAAa;EAC1B;EACA,MAAM,QAAQ,KAAK,KAAK,cAAc,uBAAuB;EAC7D,OAAO,SAAS,OAAO,SAAS,MAAM,IAAI,IAAI,QAAQ,KAAA;CACxD;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;;;;;;;;CASA,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,EAAE,SAAS,YACb,MAAM,OAAO,IAAI,WAAW,GAAG,YAAY,YAAY,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,IAAI,gBAAgB,CAAC,GACxB,MAAM,OAAO,IAAI,EAAE,MAAM,YAAY,EAAE,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,YAAY,CAAC,CAAC,EAAE,CAAC;GACjF,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;IAEjB,IAAI,EAAE,QAAQ,WAAW,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC;SAC/C,SAAS,EAAE;IAChB;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;GAEpB,IAAI,EAAE,kBAAkB,WAAW,EAAE,OAAO,QAAQ,mBAAmB,GAAG;GAG1E,IACE,EAAE,WAAW,QACb,KAAK,aAAa,aAAa,KAC/B,EAAE,EAAE,kBAAkB,WAAW,EAAE,OAAO,QAAQ,eAAe,IAEjE;GAEF,MAAM,IAAI,MAAM,IAAI,EAAE;GACtB,IAAI,KAAK,aAAa,CAAC,GAAG;IACxB,YAAY,GAAG,EAAE;IACjB;GACF;GAEA,EAAE,gBAAgB;GAClB,SAAS,EAAE;EACb,CAAC;EACD,KAAK,iBAAiB,aAAa,MAAM;GACvC,IAAI,EAAE,kBAAkB,WAAW,EAAE,OAAO,QAAQ,mBAAmB,GAAG;GAC1E,IAAI,KAAK,EAAE,GAAG,EAAE,eAAe;EACjC,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;EAEf,MAAM,UAAU,eAAe,MAAM,KAAK,IAAI,CAAC,CAAC,CAC7C,QAAQ,MAAM,EAAE,SAAS,IAAI,CAAC,CAC9B,KAAK,YAAY;EACpB,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;GAEjB,UAAU,IAAI,CAAC,EAAE,MAAM,KAAK;GAC5B,KAAK,OAAO;GACZ,QAAQ,KAAK,EAAE;GACf,SAAS,OAAO,EAAE;GAClB,MAAM,OAAO,EAAE;GACf,QAAQ,OAAO,EAAE;EACnB;EAEA,MAAM,OACJ,QAAQ,MAAM,MAA2B,EAAE,SAAS,MAAM,GAC1D,SACF;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;GAGvB,IAAI,UAAU,IAAI,GAAG;IACnB,MAAM,SAAS,KAAK,MAAM;IAC1B,cAAc,MAAM,CAAC;IACrB,KAAK,MAAM,SAAS;GACtB,OAAO;IACL,cAAc,MAAM,CAAC;IACrB,aAAa,MAAM,CAAC;GACtB;GACA,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;GAGX,IAAI,KAAK,SAAS,UAAU,QAAQ,KAAK,aAAa,UAAU,UAC9D,aAAa;GACf,YAAY;GACZ,OAAO;EACT;EACA,aAAa,OAAO,SAAS,IAAI,EAAE;EACnC,UAAU;GACR,IAAI,WAAW;GACf,aAAa;GACb,YAAY;GACZ,cAAc;GACd,QAAQ;GACR,aAAa;GACb,cAAc,WAAW;GACzB,QAAQ,QAAQ;GAChB,MAAM,QAAQ;GACd,KAAK,OAAO;GACZ,SAAS,MAAM;GACf,MAAM,MAAM;GACZ,QAAQ,MAAM;GACd,QAAQ,CAAC;EACX;CACF;AACF;;;;ACvkBA,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;EACA,GAAI,KAAK,qBAAqB,KAAA,IAC1B,CAAC,IACD,EAAE,kBAAkB,KAAK,iBAAiB;EAC9C,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;;;AClFA,SAAgB,kBAAkB,QAAyB,CAAC,GAAgB;CAC1E,MAAM,uBAAO,IAAI,IAA8B;CAC/C,MAAM,wBAAQ,IAAI,IAA8B;CAEhD,MAAM,SAAS,OAAiC;EAC9C,MAAM,IAAI,KAAK,IAAI,EAAE;EACrB,IAAI,CAAC,GAAG,MAAM,IAAI,WAAW,gBAAgB,IAAI;EACjD,OAAO;CACT;CAEA,SAAS,SAAS,MAA6B;EAC7C,KAAK,MAAM,KAAK,MAAM;GACpB,IAAI,KAAK,IAAI,EAAE,EAAE,GAAG;GACpB,MAAM,IAAI,SAAiB,EAAE,GAAI,EAAE,kBAAkB,CAAC,EAAG,CAAC;GAC1D,KAAK,IAAI,EAAE,IAAI,CAAC;GAChB,MAAM,IAAI,EAAE,IAAI,SAAS,CAAC,CAAC;EAC7B;CACF;CACA,SAAS,KAAK;CAEd,OAAO;EACL,SAAS,IAAI;GACX,MAAM,EAAE;GACR,OAAO,MAAM,IAAI,EAAE;EACrB;EACA,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC,IAAI;EAC3B,MAAM,IAAI,OAAO;GACf,MAAM,IAAI,MAAM,EAAE;GAClB,EAAE,IAAI;IAAE,GAAG,EAAE,IAAI;IAAG,GAAG;GAAM,CAAC;EAChC;EACA;CACF;AACF;;;;ACqFA,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,OAAO,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CACrD,MAAM,SAAS,SAAiB,KAAK,WAAW,aAAa;CAC7D,IAAI;CACJ,MAAM,WAAW,KAAK,WAAW,kBAAkB;CACnD,SAAS,SAAS,KAAK,KAAK;CAC5B,MAAM,MAAmB;EACvB,GAAG,KAAK;EAER,IAAI,aAAa;GACf,OAAO,KAAK,IAAI;EAClB;EACA,WACE,KAAK,IAAI,aACT,gBAAgB;GACd,OAAO,KAAK,IAAI;GAChB,SAAS,KAAK,IAAI,WAAW,EAAE,QAAQ,OAAO,GAAG,EAAE;GACnD,mBAAmB,SAAS;GAC5B;EACF,CAAC;EAEH,eAAiC,SAAS,IAAI,SAAS,MAAM,OAAO,IAAI,CAAC;CAC3E;CACA,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,gBAAgB,EAAE,MAAM,GAAG;EAC/B,SAAS,YAAY,CAAC;EAEtB,IAAI,gBAAgB,GAAG,IAAI,IAAI,GAAG,iBAAiB,CAAC;CACtD;CACA,SAAS,iBAAiB,GAAwB;EAChD,MAAM,WAAW,IAAI,MAAM,UAAU,IAAI;EACzC,IAAI,SAAS,WAAW,GAAG;EAC3B,MAAM,KAAK,SAAS;EACpB,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE;EAC1B,MAAM,KAAK,IAAI,KAAK,cAClB,qBAAqB,IAAI,OAAO,EAAE,EAAE,GACtC;EACA,IAAI,CAAC,gBAAgB,GAAG,EAAE,KAAK,CAAC,IAAI;EACpC,EAAE,eAAe;EACjB,eAAe,IAAI,OAAO,IAAI,IAAI,IAAI,SAAS,aAAa,EAAE,IAAI,CAAC;CACrE;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,IAAY,SAAwB;EAC/C,MAAM,OAAO,KAAK,IAAI,EAAE;EACxB,IAAI,CAAC,MAAM,MAAM,IAAI,WAAW,gBAAgB,IAAI;EACpD,IAAI,SAAS,SAAS,MAAM,IAAI,OAAO;EACvC,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,aAAa;CAEjC,OAAO;EACL,QAAQ,SAAS,MAAM;EACvB;EACA,WAAW,IAAI,OAAO;GACpB,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,WAAW,gBAAgB,IAAI;GAC5D,SAAS,MAAM,IAAI,KAAK;EAC1B;EACA,QAAQ,IAAI;GACV,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,WAAW,gBAAgB,IAAI;GAC5D,OAAO,SAAS,SAAS,EAAE;EAC7B;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;CAEzC,IAAI,OAAO,QAAQ,mBAAmB,GAAG,OAAO;CAChD,MAAM,KAAK,OAAO,QAAQ,mBAAmB;CAC7C,OACE,OAAO,QACP,OAAO,UACP,GAAG,aAAa,aAAa,KAE7B,OAAO,QAAQ,eAAe,MAAM;AAExC;;;AC/UA,MAAMC,WAAS;;AAoCf,SAAgB,WAAW,GAAqC;CAC9D,IAAI,EAAE,gBAAgB,SAAS,EAAE,gBAAgB,SAAS,OAAO,KAAA;CAEjE,OAAO,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI;AAClE;;AAGA,SAAgB,gBAAgB,SAAqC;CACnE,OAAO,QAAQ,MAAM,MAAM,MAAM,KAAK,MAAM,EAAG;AACjD;;;;;AAMA,SAAgB,aAAa,MAA6B;CACxD,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,cAAoB;EACxB,OAAO,OAAO;EACd,QAAQ,KAAA;EACR,SAAS,KAAA;CACX;;CAGA,MAAM,UAAU,GAAW,GAAiB,UAAU,UAAgB;EACpE,MAAM,MAAM,aAAa,EAAE,KAAK,MAAM,CAAC;EACvC,EAAE,IAAI,KAAK,GAAG;EACd,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,QAAQ,GAAG,CAAC;EACzC,MAAM,IAAI,UAAU,EAAE,WAAW,EAAE,SAAS,SAAS,KAAK,WAAW,CAAC;EACtE,IAAI,MAAM,KAAA,GAAW,CAAC,EAAE,aAAa,CAAC,EAAA,CAAG,KAAK,CAAC;CACjD;CAEA,MAAM,SAAS,GAAgB,MAAoB;EACjD,MAAM,OAAO,EAAE,KAAK;EACpB,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,OAAO;GACV,QAAQ,IAAI,cAAc,KAAK;GAC/B,MAAM,YAAY;GAClB,MAAM,QAAQ,WAAW,KAAK;GAC9B,MAAM,MAAM,WAAW;GACvB,MAAM,MAAM,gBAAgB;GAC5B,MAAM,MAAM,OAAO;GACnB,MAAM,MAAM,MAAM;GAClB,KAAK,OAAO,KAAK;EACnB;EACA,MAAM,MAAM,QAAQ,GAAG,KAAK,YAAY;EACxC,MAAM,MAAM,SAAS,GAAG,KAAK,aAAa;EAC1C,MAAM,QAA2C;GAC/C,MAAM;GACN,MAAM,EAAE,KAAK;GACb,SAAS,CAAC,CAAC,CAAC;EACd;EACA,MAAM,QAAQ,EAAE,UAAU,QAAQ,OAAO,KAAK;EAC9C,MAAM,OAAO,IAAI,gBAAgBA,UAAQ,MAAM;EAC/C,KAAK,aACH,KACA,YACE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,UAAU,YAAY,MAAM,SAAS,CAAC,CAAC,CACjF,CACF;EACA,KAAK,aAAa,QAAQ,MAAM,SAAS,SAAS;EAClD,IAAI,MAAM,YAAY,KAAA,GAAW,KAAK,aAAa,WAAW,OAAO,MAAM,OAAO,CAAC;EACnF,MAAM,MAAM,IAAI,gBAAgBA,UAAQ,KAAK;EAC7C,IAAI,aAAa,SAAS,OAAO,KAAK,WAAW,CAAC;EAClD,IAAI,aAAa,UAAU,OAAO,KAAK,YAAY,CAAC;EACpD,IAAI,MAAM,WAAW;EACrB,IAAI,OAAO,IAAI;EACf,MAAM,gBAAgB,GAAG;CAC3B;CAEA,OAAO;EACL,IAAI,KAAK;EACT,QAAQ;EACR,YAAY;EACZ,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,KAAK,MAAM;GACX,KAAK,aAAa;GAClB,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK;GACpB,IAAI,CAAC,KAAK;GACV,SAAS;IACP,MAAM;IACN,KAAK,CAAC;IACN,MAAM,CAAC;IACP,UAAU,KAAA;IACV,WAAW,KAAK,IAAI;GACtB;GACA,OAAO,QAAQ,CAAC;GAEhB,EAAE,gBAAgB;GAClB,EAAE,eAAe;GACjB,OAAO;EACT;EACA,cAAc,GAAG;GACf,IAAI,CAAC,OAAO,CAAC,QAAQ;GAGrB,IAAI,EAAE,YAAY,KAAK,CAAC,OAAO,KAAK,KAAK,aAAa;IACpD,MAAM;IACN;GACF;GACA,MAAM,YAAY,EAAE,qBAAqB,KAAK,CAAC;GAC/C,KAAK,MAAM,MAAM,UAAU,SAAS,IAAI,YAAY,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE;GAC1E,MAAM,KAAK,MAAM;EACnB;EACA,kBAAkB;GAChB,MAAM;EACR;EACA,YAAY,GAAG;GACb,IAAI,CAAC,OAAO,CAAC,QAAQ;GACrB,MAAM,IAAI;GACV,IAAI,CAAC,EAAE,KAAK,KAAK,aAAa;IAC5B,MAAM;IACN;GACF;GACA,MAAM,OAAO,EAAE,IAAI,EAAE,IAAI,SAAS;GAClC,MAAM,MAAM,aAAa,EAAE,KAAK,MAAM,CAAC;GACvC,IAAI,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,GAAG,OAAO,GAAG,GAAG,IAAI;GAC3D,MAAM;GACN,KAAK,OAAO,KAAK;IACf,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE;IACV,UAAU,EAAE,YAAY,gBAAgB,EAAE,QAAQ,IAAI,EAAE,WAAW,KAAA;IACnE,WAAW,EAAE;GACf,CAAC;EACH;EACA,UAAU,GAAG;GACX,IAAI,EAAE,QAAQ,UAAU;GAExB,MAAM;GACN,KAAK,MAAM;EACb;CACF;AACF;;;AC7KA,SAAgB,WAAiB;CAC/B,IAAI;CAEJ,MAAM,QACJ,GACA,KACA,QACA,aACS;EACT,MAAM,UAAU,CAAC,GAAG,IAAI,SAAS,MAAM;EAEvC,MAAM,QAAQ,MAAyB,EAAE,UAAU,EAAG;EACtD,MAAM,OACJ,IAAI,YAAY,WACZ,CAAC,GAAI,IAAI,YAAY,IAAI,QAAQ,IAAI,IAAI,GAAI,YAAY,KAAK,MAAM,CAAC,IACrE,KAAA;EACN,EAAE,MAAM,OAAO,IAAI,IAAI;GACrB;GACA,UAAU;GACV,MAAM,WAAW;IAAE,MAAM;IAAO,MAAM,IAAI;IAAM;IAAS,OAAO,IAAI;GAAM,CAAC;EAC7E,CAAC;CACH;CAEA,OAAO,aAAa;EAClB,IAAI;EACJ,MAAM;GACJ,UAAU,KAAA;EACZ;;EAEA,OAAO,GAAG,GAAG;GAGX,MAAM,SAAS;GACf,MAAM,UACJ,UAAU,OAAO,SAAS,EAAE,QAAQ,EAAE,YAAY,OAAO,WAAA,MACpD,EAAE,MAAM,aAAa,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,OAAO,EAAE,IACzD,KAAA;GACN,IAAI,SAAS,SAAS,SAAS,CAAC,QAAQ,QAAQ;IAC9C,KAAK,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ;IACrC,UAAU;KAAE,IAAI,QAAQ;KAAI,MAAM,QAAQ;KAAM,SAAS,KAAK,IAAI;IAAE;IACpE;GACF;GACA,MAAM,QAAQ,EAAE,MAAM,IACpB,EAAE,UAAU,QAAQ,OAAO;IACzB,MAAM;IACN,MAAM,EAAE;IACR,SAAS,CAAC,EAAE,MAAM;IAClB,GAAI,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC;GACjD,CAAC,CACH;GACA,UAAU;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM;IAAM,SAAS,KAAK,IAAI;GAAE;EAClE;CACF,CAAC;AACH;;;;ACpDA,MAAa,yBAAyB;;AAGtC,MAAM,cAAc;;AAGpB,MAAM,YAAY;;AAGlB,MAAMC,YAAU;AAEhB,SAAgB,eAAqB;CACnC,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,cAAoB;EACxB,OAAO,OAAO;EACd,QAAQ,KAAA;EACR,QAAQ,KAAA;CACV;;CAGA,IAAI;;;;;;;;CASJ,MAAM,SACJ,GACA,MACA,QACS;EACT,MAAM,OAAO,EAAE,SAAS,QAAQ,IAAI;EACpC,IAAI,CAAC,MAAM;EACX,SAAS,MAAM,IAAI;EACnB,MAAM,IAAI,EAAE,SAAS,aAAa,IAAI;EACtC,MAAM,QAAuB;GAAE,MAAM;GAAY;GAAM,UAAU;EAAG;EACpE,MAAM,QAAQ,EAAE,UAAU,QAAQ,QAAQ,KAAK;EAC/C,IAAI;EACJ,IAAI,QAAQ,KAAK;GACf,MAAM,OAAO,MAAM,cAAc,YAAY;GAC7C,MAAM,SAAS,MAAM,SAAS;GAC9B,MAAM,QAAQ,EAAE,YAAA,GAAkC;GAClD,MAAM,SAAS,EAAE,YAAY,OAAO,cAAc,SAAS,CAAC;GAC5D,MAAM,IAAI,UACN;IAAE,MAAM,IAAI,GAAG,IAAI,QAAQ;IAAG,KAAK,IAAI,GAAG,IAAI,SAAS;IAAG;IAAO;GAAO,IACxE;IAAE,MAAM,IAAI,GAAG;IAAG,KAAK,IAAI,GAAG;IAAG;IAAO;GAAO;EACrD,OACE,MAAM;EAER,MAAM,WAAW,EAAE,MAAM,cAAc;GAAE,GAAG;GAAO,MAAM,EAAE,YAAY,GAAG;EAAE,CAAC;EAC7E,IAAI,SAAS,SAAS,YAAY;EAClC,MAAM,MAAM,KAAK;EAIjB,MAAM,KAAK,IAAI,cAAc,KAAK;EAClC,GAAG,YAAY;EACf,GAAG,QAAQ,aAAa;EACxB,GAAG,QAAQ,OAAO;EAClB,GAAG,WAAW;EACd,GAAG,MAAM,UAAU,0BAA0B,IAAI,KAAK,SAAS,IAAI,IAAI,WAAW,IAAI,MAAM,YAAY,IAAI,OAAO;EACnH,KAAK,OAAO,EAAE;EACd,wBAAwB,IAAI,UAAU,CAAC;EAGvC,MAAM,OAAO,CACX,GAAG,CAAC,EAAE,SAAS,OAAO,EAAE,SAAS,QAAQ,CAAC,CAAC,KAAK,MAC9C,EAAE,gBAAgB,OAAO,MAAM,IAAI,CAAC,CACtC,GACA,EAAE,SAAS,QAAQ,WAAW,UAAU;GACtC,IAAI,CAAC,MAAM,SAAS,IAAI,GAAG,OAAO,MAAM,IAAI;EAC9C,CAAC,CACH;EACA,MAAM,aAAmB;GACvB,KAAK,SAAS,SAAS,KAAK,CAAC;GAC7B,GAAG,OAAO;GACV,IAAI,YAAY,QAAQ,UAAU,KAAA;EACpC;;EAEA,MAAM,WAAW,OAAsB;GAErC,MAAM,SAAS,IAAI;GACnB,IAAI,UAAU,WAAW,IAAI,QAAQ,WAAW,IAAI;GACpD,MAAM,QACJ,OAAO,KAAA,IACH,OACA,EAAE,KAAK,cAA2B,qBAAqB,IAAI,OAAO,EAAE,EAAE,GAAG;GAC/E,IAAI,OAAO,MAAM,MAAM,EAAE,eAAe,KAAK,CAAC;QACzC;IACH,IAAI,CAAC,EAAE,KAAK,aAAa,UAAU,GAAG,EAAE,KAAK,WAAW;IACxD,EAAE,KAAK,MAAM,EAAE,eAAe,KAAK,CAAC;GACtC;EACF;EACA,MAAM,SAAS,aAAa,IAAI,UAAU;GACxC,WAAW;GACX,OAAO,UAAU,MAAM;IACrB,KAAK;IACL,IAAI,SAAS,KAAK,MAAM,IAAI,OAAO,QAAQ;IAC3C,MAAM,UAAU,EAAE,MAAM,IAAI;KAAE,GAAG;KAAO,IAAI,SAAS;KAAI;KAAU;IAAK,CAAC;IACzE,EAAE,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC3B,QAAQ,QAAQ,EAAE;GACpB;GACA,SAAS;IACP,KAAK;IACL,QAAQ;GACV;EACF,CAAC;EACD,UAAU;CACZ;CAEA,MAAM,SAAS,MAAe,MAA0B;EACtD,MAAM,MAAM,aAAa,KAAK,MAAM,CAAC;EACrC,IAAI,CAAC,OAAO;GACV,QAAQ,KAAK,KAAK,cAAc,cAAc,KAAK;GACnD,MAAM,YAAY;GAClB,MAAM,QAAQ,WAAW;GACzB,MAAM,MAAM,WAAW;GACvB,MAAM,MAAM,gBAAgB;GAC5B,KAAK,KAAK,OAAO,KAAK;EACxB;EACA,MAAM,MAAM,OAAO,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC,EAAE;EAClD,MAAM,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC,EAAE;EACjD,MAAM,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,EAAE;EACpD,MAAM,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,EAAE;CACvD;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,YAAY;EACZ,gBAAgB,CAAC;EACjB,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,SAAS,MAAM,IAAI;GACnB,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK,cAAc;GAElC,IAAI,CAAC,OAAO,iBAAiB,KAAA,KAAa,aAAa,CAAC,GAAG;GAC3D,QAAQ;GAER,EAAE,eAAe;GACjB,OAAO;EACT;EACA,cAAc,GAAG;GACf,IAAI,CAAC,OAAO;GACZ,IAAI,EAAE,YAAY,KAAK,CAAC,MAAM,KAAK,aAAa;IAC9C,MAAM;IACN;GACF;GACA,MAAM,OAAO,CAAC;EAChB;EACA,kBAAkB;GAChB,MAAM;EACR;EACA,YAAY,GAAG;GACb,MAAM,OAAO;GACb,MAAM;GACN,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK,aAAa;GAC7C,MAAM,MAAM,aAAa,KAAK,MAAM,CAAC;GACrC,MAAM,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;GACtC,MAAM,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;GACtC,IAAI,MAAMA,aAAW,MAAMA,WACzB,MAAM,KAAK,KAAK,MAAM;IACpB,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAChC,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/B,OAAO;IACP,QAAQ;GACV,CAAC;QAED,MAAM,KAAK,KAAK,MAAM;IAAE,IAAI,KAAK;IAAK,SAAS;GAAM,CAAC;EAE1D;EACA,UAAU,GAAG;GACX,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,IAAI,IAAI,GAAG;GAC3C,EAAE,eAAe;GACjB,MAAM,OAAO,IAAI,SAAS,YAAY,IAAI;GAC1C,MAAM,IAAI,IAAI,SAAS,aAAa,IAAI;GACxC,MAAM,EAAE,QAAQ,EAAE;GAClB,MAAM,SAAS,EAAE,MAAM;IAAE,GAAG,IAAI,IAAI,IAAI,QAAQ;IAAG,GAAG,IAAI,IAAI,IAAI,SAAS;GAAE,CAAC;GAC9E,MAAM,KAAK,MAAM;IAAE,IAAI;IAAQ,SAAS;GAAK,CAAC;EAChD;CACF;AACF;;;;AC/MA,MAAa,eAAsC;CACjD;CACA;CACA;CACA;AACF;AAOA,MAAa,4BAAwD,EAAE,MAAM,YAAY;;;;;;;AAQzF,SAAgB,gBAAwC;CACtD,IAAI;CACJ,MAAM,gBAAyB;EAC7B,IAAI,CAAC,KAAK,OAAO;EACjB,MAAM,aAAa,IAAI,eAAe;EACtC,IAAI,WAAW,WAAW,GAAG,OAAO;EACpC,MAAM,EAAE,SAAS;GAAE,GAAG;GAA2B,GAAG,IAAI,QAA0B;EAAE;EACpF,MAAM,MAAgB,CAAC;EACvB,KAAK,MAAM,KAAK,YAAY;GAC1B,MAAM,IAAI,IAAI,MAAM,IAClB,IAAI,UAAU,QAAQ,UAAU;IAAE,MAAM;IAAM,MAAM,EAAE;IAAM,OAAO,EAAE;GAAM,CAAC,CAC9E;GACA,IAAI,KAAK,EAAE,EAAE;EACf;EACA,IAAI,eAAe;EACnB,IAAI,MAAM,OAAO,GAAG;EACpB,OAAO;CACT;CACA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,YAAY;EACZ,gBAAgB,EAAE,GAAG,0BAA0B;EAC/C,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;;;;AC1DA,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,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;;;;AC5EA,MAAMC,YAAU;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,IACR,IAAI,UAAU,QAAQ,UAAU;GAAE,MAAM;GAAU,MAAM,EAAE;GAAM,OAAO,EAAE;EAAM,CAAC,CAClF;EACF,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,YAAY;EACZ,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK,cAAc;GAClC,IAAI,CAAC,KAAK;GACV,IAAI,iBAAiB,KAAA,GAAW;IAI9B,MAAM,IAAI,KAAK,MAAM,IAAI,YAAY;IACrC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG;IAC5B,EAAE,gBAAgB;GACpB;GACA,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,SAASA,aAAW,UAAUA,WAAS;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,IACR,IAAI,UAAU,QAAQ,UAAU;KAAE,MAAM;KAAU,MAAM,MAAM;KAAM;IAAK,CAAC,CAC5E;GACF,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;;;ACnEA,MAAM,UAA6B;CAAC;CAAM;CAAM;CAAM;AAAI;AAC1D,MAAM,OAA0B,CAAC,SAAS,KAAK;AAC/C,MAAM,UAAU;;AAGhB,MAAM,iBAAiB;AAqDvB,SAAgB,oBACd,KACA,OAA6B,CAAC,GACf;CACf,IAAI,OAAa,EAAE,MAAM,OAAO;CAChC,MAAM,SAAS,OAA0B,IAAI,UAAU,IAAI,QAAQ,MAAM,EAAE,IAAI,GAAG;CAElF,MAAM,cAAoB;EACxB,IAAI,KAAK,SAAS,WAAW,KAAK,GAAG,OAAO;EAC5C,IAAI,KAAK,SAAS,QAAQ,KAAK,MAAM,MAAM,KAAK,KAAK,GAAG,MAAM,YAAY;EAC1E,IAAI,KAAK,SAAS,YAAY,KAAK,IAAI;GACrC,KAAK,GAAG,MAAM,YAAY;GAC1B,KAAK,GAAG,MAAM,kBAAkB;GAChC,KAAK,GAAG,MAAM,aAAa;EAC7B;EACA,IAAI,KAAK,SAAS,UAAU,KAAK,SAAS,OAAO;EACjD,IAAI,KAAK,SAAS,YAAY;GAC5B,KAAK,QAAQ,OAAO;GACpB,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,aAAa;EAC1C;EACA,OAAO,EAAE,MAAM,OAAO;CACxB;CAEA,MAAM,aAAa,MAAkB,OACnC,KAAK,cAA2B,qBAAqB,IAAI,OAAO,EAAE,EAAE,GAAG,KAAK,KAAA;CAE9E,MAAM,cAAc,MAAmB,MAA+B;EACpE,MAAM,UAAU,KAAK,cAAc,cAAc,KAAK;EACtD,QAAQ,YAAY;EACpB,QAAQ,QAAQ,aAAa;EAC7B,QAAQ,QAAQ,OAAO,EAAE;EACzB,QAAQ,MAAM,UAAU;EACxB,OAAO;CACT;;CAGA,MAAM,eACJ,SACA,IACA,OACA,UACS;EACT,YAAY,SAAS,OAAO,KAAK;EACjC,IAAI,IAAI,GAAG,MAAM,aAAa;EAE9B,IAAI,CAAC,QAAQ,aAAa,CAAC,IAAI,iBAAiB,MAAM,KAAA,CAAM,OAAO,OAAO;CAC5E;CAEA,SAAS,YACP,GACA,KACA,GACA,QACS;EACT,MAAM,KAAK,UAAU,IAAI,MAAM,EAAE,EAAE;EACnC,IAAI,QAAQ,SAAS,MAAM,KAAK,iBAAiB,CAAC,GAAG;GACnD,MAAM,OAAO,EAAE,SAAS;GACxB,OAAO;IACL,MAAM;IACN,IAAI,EAAE;IACN,OAAO;IACP,QAAQ;IACR,KAAK,OACD,IAAI,UAAU,UAAU,YAAY,CAAC,CAAC,IACtC,KACE,MAAM,EAAE,IACR,cAAc,GAAG,IAAI,SAAS;IACpC;IACA,QAAQ,YAAY,CAAC;IACrB,SACE,SAAS,EAAE,WAAW,KAAA,KAAa,WAAW,CAAC,KAC3C,WAAW,IAAI,MAAM,CAAC,IACtB,KAAA;GACR;EACF,OAAO,IACJ,KAAK,SAAS,MAAM,KAAK,EAAE,SAAS,UACpC,WAAW,WAAW,WAAW,CAAC,GACnC;GACA,MAAM,UAAU,WAAW,IAAI,MAAM,CAAC;GACtC,OAAO;IACL,MAAM;IACN,IAAI,EAAE;IACN,OAAO;IACP,OAAO;IACP,MAAM,IAAI,UAAU,MAAM,MAAM,GAAG,MAAa,CAAE;IAClD;IACA;GACF;EACF,OACE,OAAO;EAIT,EAAE,gBAAgB;EAClB,EAAE,eAAe;EACjB,OAAO;CACT;CAEA,OAAO;EACL;EACA,cAAc,GAAG,KAAK,cAAc;GAClC,IAAI,CAAC,KAAK;GACV,MAAM;GACN,IAAI,iBAAiB,KAAA,GAAW;IAC9B,MAAM,IAAI,IAAI,MAAM,IAAI,YAAY;IACpC,IAAI,CAAC,GAAG;IAIR,MAAM,SAAS,aAAa,CAAC;IAC7B,IAAI,UAAU,CAAC,KAAK,SAAS;IAC7B,MAAM,SAAS,SAAS,EAAE,MAAM;IAChC,IAAI,WAAW,KAAA,KAAa,CAAC,EAAE,UAAU,YAAY,GAAG,KAAK,GAAG,MAAM,GACpE,OAAO;IACT,MAAM,WAAW,IAAI,MAAM,UAAU,IAAI;IACzC,IAAI,EAAE,UAAU;KAEd,EAAE,gBAAgB;KAClB,IAAI,MAAM,OACR,SAAS,SAAS,YAAY,IAC1B,SAAS,QAAQ,MAAM,MAAM,YAAY,IACzC,CAAC,GAAG,UAAU,YAAY,CAChC;KACA;IACF;IACA,MAAM,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,YAAY;IAIpE,IAAI,QAAQ,EAAE,gBAAgB;SACzB,IAAI,QAAQ;KACf,EAAE,gBAAgB;KAClB,IAAI,MAAM,OAAO,CAAC,YAAY,CAAC;KAC/B,IAAI,aAAa,YAAY;IAC/B;IACA,OAAO;KAAE,MAAM;KAAS,IAAI;KAAc,OAAO;KAAK;IAAO;IAC7D,EAAE,eAAe;IACjB,OAAO;GACT;GACA,IAAI,CAAC,KAAK,SAAS;GACnB,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,KAAK,SAAS,QAAQ;GAG1B,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,IAAI,YAAY;IAC7B,MAAM,OAAO,UAAU,KAAK,KAAK,QAAQ,SAAS,MAAM,CAAC,GAAG,OAAO,KAAK,GAAG;KACzE,QAAQ,KAAK,UAAU,EAAE;KACzB,MAAM,MAAM;IACd,CAAC;IACD,IAAI,SAAS;KACX,MAAM,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE;KAC/B,IAAI,GAAG,SAAS,YAAY;KAC5B,MAAM,QAAQ;MAAE,GAAG;MAAG,GAAG,WAAW,GAAG,QAAQ,MAAM,WAAW,IAAI,CAAC;KAAE;KACvE,YAAY,SAAS,IAAI,OAAO,KAAK;IACvC,OAAO,IAAI,IAAI;KACb,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,IAAI,KAAK,SAAS,YAAY;IAC5B,MAAM,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE;IAC/B,IAAI,CAAC,GAAG;IACR,MAAM,QAAQ,SAAS,GAAG,KAAK,OAAO,MAAM,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO;IACZ,YAAY,KAAK,SAAS,KAAK,IAAI;KAAE,GAAG;KAAG,GAAG;IAAM,GAAiB,KAAK;IAC1E;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,WAAW,IAAI,MAAM,UAAU,IAAI;IAGzC,MAAM,UAAU,KAAK;IACrB,MAAM,MAAM,SAAS,SAAS,OAAO,IACjC,SAAS,QAAQ,OAAO;KACtB,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE;KAC1B,OAAO,MAAM,KAAA,KAAa,CAAC,EAAE,WAAW,OAAO,WAAW,CAAC,aAAa,CAAC;IAC3E,CAAC,IACD,CAAC,OAAO;IAIZ,OAAO;KAAE,MAAM;KAAQ;KAAK;KAAO,KAHvB,IACT,KAAK,OAAO,UAAU,IAAI,MAAM,EAAE,CAAC,CAAC,CACpC,QAAQ,OAA0B,OAAO,KAAA,CACP;IAAE;GACzC;GACA,IAAI,KAAK,SAAS,QAAQ;IACxB,KAAK,MAAM,MAAM,KAAK,KAAK,GAAG,MAAM,YAAY,aAAa,GAAG,MAAM,GAAG;IACzE;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,MAAM,UAAU;GAChB,MAAM;GACN,IAAI,QAAQ,SAAS,UAAU,CAAC,QAAQ,MAAM,KAAK,aAAa;GAChE,QAAQ,QAAQ,MAAhB;IACE,KAAK;KAEH,IAAI,QAAQ,QAAQ;MAClB,IAAI,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;MAC7B,IAAI,aAAa,QAAQ,EAAE;KAC7B;KACA;IACF,KAAK,QAAQ;KACX,MAAM,EAAE,UAAU;KAClB,MAAM,MAAM,MAAM,UAAU,QAAQ,MAAM,MAAM,MAAM,CAAC,CAAC;KACxD,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK;KAC9B,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK;KAC9B,YAAY;MACV,KAAK,MAAM,MAAM,QAAQ,KAAK;OAC5B,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE;OAC1B,IAAI,KAAK,CAAC,EAAE,QAAQ,IAAI,MAAM,OAAO,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;MAChE;KACF,CAAC;KACD;IACF;IACA,KAAK,UAAU;KACb,MAAM,EAAE,OAAO,QAAQ;KACvB,MAAM,OAAO,UACX,KACA,QAAQ,QACR,SAAS,SAAS,CAAC,GACnB,OAAO,KAAK,GACZ;MACE,QAAQ,QAAQ,UAAU,EAAE;MAC5B,MAAM,MAAM;KACd,CACF;KACA,IACE,KAAK,SAAS,IAAI,QAClB,KAAK,QAAQ,IAAI,OACjB,KAAK,UAAU,IAAI,SACnB,KAAK,WAAW,IAAI,QAEpB;KACF,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE;KAClC,IAAI,CAAC,KAAK,EAAE,QAAQ;KACpB,MAAM,KAAK,QAAQ,MAAM,WAAW,IAAI;KACxC,IAAI,EAAE,SAAS,YAAY;MACzB,IAAI,MAAM,OAAO,EAAE,IAAI,WAAW,GAAG,EAAE,CAAC;MACxC;KACF;KAEA,MAAM,OAAO,gBAAgB,CAAC,IAAI,EAAE,OAAO,MAAM,UAAU,YAAY,GAAG;KAC1E,IAAI,MAAM,OAAO,EAAE,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC;KAC1C;IACF;IACA,KAAK,YAAY;KACf,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE;KAClC,IAAI,CAAC,KAAK,EAAE,QAAQ;KACpB,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,CAAC;KACvC,IAAI,IAAI,MAAM,QAAQ,MAAM,IAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI,GAAG;KACpE,MAAM,QAAQ,SAAS,GAAG,QAAQ,OAAO,MAAM,SAAS,CAAC,CAAC;KAC1D,IAAI,OAAO,IAAI,MAAM,OAAO,EAAE,IAAI,KAAK;KACvC;IACF;IACA,KAAK,WAAW;KACd,MAAM,EAAE,UAAU;KAClB,MAAM,MAAM,eACV,MAAM,MACN,MAAM,UAAU,QAAQ,MAAM,MAAM,MAAM,CAAC,CAAC,CAC9C;KACA,IAAI,IAAI,UAAU,KAAK,IAAI,WAAW,GAAG;KAEzC,MAAM,MAAM,eAAe,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAC7C,QAAQ,MAAM,EAAE,SAAS,MAAM,QAAQ,eAAe,EAAE,MAAM,GAAG,CAAC,CAAC,CACnE,KAAK,MAAM,EAAE,EAAE;KAClB,IAAI,MAAM,OACR,QAAQ,WAAW,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,IAAI,MAAM,UAAU,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,GAC5E;KACA;IACF;GAEF;EACF;EACA,UAAU,GAAG;GACX,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,OAAO,OAAO,QAAQ,eAAe,CAAC,EAAE,aAAa,aAAa,KAAK,KAAA;AACzE;;AAGA,SAAS,MAAM,IAA0B;CACvC,OAAO;EACL,MAAM,WAAW,GAAG,MAAM,IAAI,KAAK;EACnC,KAAK,WAAW,GAAG,MAAM,GAAG,KAAK;EACjC,OAAO,WAAW,GAAG,MAAM,KAAK,KAAK;EACrC,QAAQ,WAAW,GAAG,MAAM,MAAM,KAAK;CACzC;AACF;;AAGA,SAAS,MAAM,GAAe,OAA+B;CAC3D,IAAI,UAAU,WAAW,OAAO,WAAW,CAAC,IAAI,EAAE,QAAQ,KAAK,KAAA;CAC/D,OAAO,EAAE,SAAS,SAAS,EAAE,SAAS,KAAA;AACxC;;AAGA,SAAS,SAAS,GAAe,OAAY,IAA4C;CACvF,IAAI,UAAU,WAAW,OAAO,WAAW,CAAC,IAAI,SAAS,GAAG,EAAE,IAAI,KAAA;CAClE,OAAO,EAAE,SAAS,SAAS,cAAc,GAAG,OAAO,EAAE,IAAI,KAAA;AAC3D;;AAGA,SAAS,QAAQ,GAAkB,KAAoB;CACrD,MAAM,IAAI,EAAE,YAAY,GAAG;CAC3B,OAAO;EACL,GAAG;EACH,OAAO,KAAK,IAAA,GAAc,EAAE,KAAK;EACjC,QAAQ,KAAK,IAAA,GAAc,EAAE,MAAM;CACrC;AACF;;AAGA,SAAS,YAAY,IAAiB,GAAe,OAAsB;CACzE,MAAM,MAAM,cAAc,GAAG,MAAM,SAAS;CAC5C,GAAG,MAAM,OAAO,GAAG,IAAI,KAAK;CAC5B,GAAG,MAAM,MAAM,GAAG,IAAI,IAAI;CAC1B,GAAG,MAAM,QAAQ,GAAG,IAAI,MAAM;CAC9B,GAAG,MAAM,SAAS,GAAG,IAAI,OAAO;CAChC,wBAAwB,IAAI,GAAG,MAAM,SAAS;AAChD;;AAGA,SAAS,OAAO,OAAgB,GAAW,GAAkB;CAC3D,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;;;;;AAMA,SAAS,MACP,MACA,GACO;CACP,MAAM,EAAE,OAAO,SAAS;CACxB,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC;CAC/B,OAAO,MAAM,UAAU,QACrB,OAAO,OAAO,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,CAC1E;AACF;;;;;;AAOA,SAAS,SACP,MACA,GACO;CACP,MAAM,EAAE,OAAO,KAAK,WAAW;CAC/B,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC;CAG/B,OAAO,OAAO,QAFH,OAAO,OAAO,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI,IACzE,OAAO,OAAO,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,UAAU,IAAI,IAAI,MAAM,IAAI,CAC1D;AAC3B;;AAGA,SAAS,OAAO,OAAwB;CACtC,OAAO,MAAM,UAAU,YAAA,CAAoB;AAC7C;;;;;;AAOA,SAAS,UACP,KACA,QACA,GACA,KACA,MACS;CACT,MAAM,OAAO,OAAO,OAAO;CAC3B,MAAM,QAAQ,OAAO,OAAO;;CAE5B,MAAM,KAAK,OAAO,IAAI,OAAO,IAAI,QAAQ,IAAI;CAC7C,MAAM,KAAK,QAAQ,IAAI,MAAM,IAAI,SAAS,IAAI;CAC9C,IAAI,QAAQ,KAAK,IAAI,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG;CACpD,IAAI,SAAS,KAAK,IAAI,QAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG;CACtD,IAAI,KAAK,UAAU,IAAI,QAAQ,KAAK,IAAI,SAAS,GAAG;EAElD,MAAM,QAAQ,OAAO,KAAK,KAAK,KAAK,WAAW;EAC/C,MAAM,QAAQ,QAAQ,KAAK,KAAK,KAAK,YAAY;EACjD,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,OAAO,IAAI,MAAM;EAC/C,MAAM,KAAK,KAAK,IAAI,QAAQ,IAAI,OAAO,QAAQ,IAAI,MAAM;EACzD,MAAM,IAAI,KAAK,IACb,KAAK,IAAI,QAAQ,IAAI,OAAO,SAAS,IAAI,QAAQ,EAAE,GACnD,KAAK,IAAI,IAAI,EAAE,CACjB;EACA,QAAQ,IAAI,QAAQ;EACpB,SAAS,IAAI,SAAS;CACxB;CACA,OAAO;EACL,MAAM,OAAO,KAAK,QAAQ;EAC1B,KAAK,QAAQ,KAAK,SAAS;EAC3B;EACA;CACF;AACF;;;;;;;;ACpjBA,SAAgB,aAAmB;CACjC,IAAI;CACJ,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,KAAK;GACZ,OAAO,oBAAoB,KAAK,EAAE,SAAS,KAAK,CAAC;EACnD;EACA,aAAa;GACX,MAAM,MAAM;GACZ,OAAO,KAAA;EACT;EACA,gBAAgB,GAAG,KAAK,OAAO,MAAM,cAAc,GAAG,KAAK,EAAE;EAC7D,gBAAgB,GAAG,QAAQ,MAAM,cAAc,GAAG,GAAG;EACrD,cAAc,GAAG,QAAQ,MAAM,YAAY,GAAG,GAAG;EACjD,uBAAuB,MAAM,gBAAgB;EAC7C,YAAY,MAAM,MAAM,UAAU,CAAC;CACrC;AACF;;;;;;;;AClBA,SAAgB,iBAAuB;CACrC,IAAI;CACJ,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,SAAS,KAAK;GACZ,OAAO,oBAAoB,GAAG;EAChC;EACA,aAAa;GACX,MAAM,MAAM;GACZ,OAAO,KAAA;EACT;EACA,gBAAgB,GAAG,KAAK,OAAO,MAAM,cAAc,GAAG,KAAK,EAAE;EAC7D,gBAAgB,GAAG,QAAQ,MAAM,cAAc,GAAG,GAAG;EACrD,cAAc,GAAG,QAAQ,MAAM,YAAY,GAAG,GAAG;EACjD,uBAAuB,MAAM,gBAAgB;EAC7C,YAAY,MAAM,MAAM,UAAU,CAAC;CACrC;AACF;;;;ACkBA,MAAM,UAAU;AAEhB,MAAMC,WAAS;AAEf,SAAgB,YAAgC;CAC9C,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,cAAoB;EACxB,OAAO,OAAO;EACd,QAAQ,KAAA;EACR,QAAQ,KAAA;CACV;CAEA,MAAM,WAAW,OAAkC;EACjD,GAAG;EACH,GAAG,EAAE,QAAsB;CAC7B;;CAGA,MAAM,YACJ,GACA,MACA,GACA,GACA,UACgC;EAChC,MAAM,IAAI,QAAQ,CAAC;EACnB,OAAO,WAAW,EAAE,MAAM,MAAM,GAAG,QAAQ,UAAU,EAAE,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC;CAC3E;;CAGA,MAAM,UAAU,GAAgB,UAA4C;EAC1E,IAAI,MAAM,SAAS,YAAY,OAAO,EAAE,UAAU,QAAQ,SAAS,KAAK;EAExE,MAAM,QAAQ,EAAE,UAAU,QAAQ,SAAS;GAAE,GAAG;GAAO,OAAO,KAAA;EAAU,CAAC;EACzE,MAAM,QAAgD;GACpD,MAAM;GACN,MAAM,MAAM;GACZ,UAAU;EACZ;EACA,MAAM,OAAO,EAAE,UAAU,QAAQ,QAAQ,KAAK;EAC9C,MAAM,MAAM;GACV,GAAG;GACH,OAAO,MAAM,SAAS,MAAM;GAC5B,cAAc;IAAE,GAAG,KAAK;IAAc,GAAG,MAAM;GAAa;EAC9D;EACA,IAAI,CAAC,MAAM,WAAW,CAAC,MAAM,MAAM,OAAO;EAE1C,MAAM,MAAM,YAAY;GAAE,MAAM,MAAM;GAAM,QAAQ,MAAM;EAAO,CAAC;EAClE,MAAM,EAAE,UAAU,cAAc,GAAyB;EACzD,OAAO;GAAE,GAAG;GAAK,GAAG,kBAAkB,KAAK,MAAM,SAAS,OAAO,MAAM,IAAI;EAAE;CAC/E;;CAGA,IAAI;CAEJ,MAAM,cAAc,GAAgB,MAA2B;EAC7D,MAAM,KAAK,EAAE,KAAK,cAChB,qBAAqB,IAAI,OAAO,EAAE,EAAE,EAAE,GACxC;EACA,OACE,OAAO,QACP,eAAe,EAAE,OAAO,IAAI,EAAE,IAAI,EAAE,SAAS,aAAa,EAAE,IAAI,CAAC,MAAM,KAAA;CAE3E;;;;;CAMA,MAAM,QAAQ,GAAgB,MAAwB;EACpD,UAAU;EACV,UAAU,KAAA;EACV,IAAI,WAAW,GAAG,CAAC,GAAG;EACtB,MAAM,OAAO,EAAE,MAAM,KAAK,gBAAgB;GACxC,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE,EAAE,GAAG;GACxB,KAAK;GACL,IAAI,YAAY,MAAM,UAAU,KAAA;GAChC,WAAW,GAAG,CAAC;EACjB,CAAC;EACD,UAAU;CACZ;CAEA,MAAM,OAAO,GAAgB,UAA6C;EACxE,IAAI,CAAC,OAAO;EACZ,MAAM,UAAU,EAAE,MAAM,IAAI,OAAO,GAAG,KAAK,CAAC;EAC5C,EAAE,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;EAC3B,IAAI,SAAS,OAAO,GAAG,KAAK,GAAG,OAAO;CACxC;CAEA,MAAM,SAAS,GAAgB,MAAe,MAA0B;EACtE,MAAM,MAAM,aAAa,KAAK,MAAM,CAAC;EACrC,MAAM,OAAO,KAAK,UAAU,QAAQ,GAAG;EACvC,MAAM,QAAQ,SAAS,GAAG,KAAK,MAAM,KAAK,MAAM,MAAM,EAAE,QAAQ;EAChE,IAAI,CAAC,OAAO;EACZ,MAAM,IAAI,KAAK;EACf,IAAI;EACJ,IAAI;EACJ,IAAI,OAAoC;EACxC,IACE,MAAM,SAAS,YACf,MAAM,SAAS,YACf,MAAM,SAAS,cACf,MAAM,SAAS,WACf,MAAM,SAAS,QACf;GACA,IAAI,CAAC,MAAM,MAAM;GAEjB,MAAM,EAAE,UACN,MAAM,SAAS,aACX,YAAY;IAAE,MAAM,MAAM;IAAM,QAAQ,MAAM;GAAO,CAAC,IACtD,MAAM,IACZ;GACA,OACE,MAAM,SAAS,YACf,MAAM,SAAS,WACd,MAAM,SAAS,UAAU,MAAM,UAAU,YACtC,YACA;EACR,OAAO;GACL,IAAI,MAAM,SAAS,QAAQ,SAAS,CAAC,EAAE,MAAM,MAAM,KAAK,GAAG,EAAE,MAAM,MAAM,GAAG,CAAC;QACxE,IAAI,MAAM,SAAS,WAAW,SAAS,MAAM,SAAS,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3E;GACL,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;GAChC,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;GAChC,MAAM,OAAO,KAAK,IAAI,GAAG,EAAE;GAC3B,MAAM,MAAM,KAAK,IAAI,GAAG,EAAE;GAC1B,MAAM;IACJ;IACA;IACA,OAAO,KAAK,IAAI,GAAG,EAAE,IAAI;IACzB,QAAQ,KAAK,IAAI,GAAG,EAAE,IAAI;GAC5B;EACF;EACA,IAAI,CAAC,OAAO;GACV,QAAQ,KAAK,KAAK,cAAc,cAAc,KAAK;GACnD,MAAM,YAAY;GAClB,MAAM,QAAQ,WAAW;GACzB,MAAM,MAAM,WAAW;GACvB,MAAM,MAAM,gBAAgB;GAC5B,KAAK,KAAK,OAAO,KAAK;EACxB;EACA,MAAM,QAAQ,WAAW,QAAQ,CAAC,CAAC,CAAC;EACpC,MAAM,MAAM,OAAO,GAAG,IAAI,KAAK;EAC/B,MAAM,MAAM,MAAM,GAAG,IAAI,IAAI;EAC7B,MAAM,MAAM,QAAQ,GAAG,IAAI,MAAM;EACjC,MAAM,MAAM,SAAS,GAAG,IAAI,OAAO;EACnC,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,MAAM,IAAI,gBAAgBA,UAAQ,KAAK;EAC7C,IAAI,aAAa,SAAS,OAAO,IAAI,KAAK,CAAC;EAC3C,IAAI,aAAa,UAAU,OAAO,IAAI,MAAM,CAAC;EAC7C,IAAI,MAAM,WAAW;EACrB,MAAM,OACJ,SAAS,SACL,IAAI,gBAAgBA,UAAQ,MAAM,SAAS,SAAS,aAAa,SAAS,IAC1E,IAAI,gBAAgBA,UAAQ,IAAI;EACtC,IAAI,SAAS,QACX,KAAK,aACH,WACC,UAAU,CAAC,EAAA,CAAG,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI,KAAK,GAAG,EAAE,IAAI,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG,CAC1E;OACK,IAAI,SAAS,WAAW;GAC7B,KAAK,aAAa,MAAM,OAAO,IAAI,QAAQ,CAAC,CAAC;GAC7C,KAAK,aAAa,MAAM,OAAO,IAAI,SAAS,CAAC,CAAC;GAC9C,KAAK,aAAa,MAAM,OAAO,IAAI,QAAQ,CAAC,CAAC;GAC7C,KAAK,aAAa,MAAM,OAAO,IAAI,SAAS,CAAC,CAAC;EAChD,OAAO;GACL,KAAK,aAAa,SAAS,OAAO,IAAI,KAAK,CAAC;GAC5C,KAAK,aAAa,UAAU,OAAO,IAAI,MAAM,CAAC;GAC9C,KAAK,MAAM,SAAS,YAAY,MAAM,SAAS,eAAe,MAAM,cAClE,KAAK,aAAa,MAAM,OAAO,EAAE,YAAY,MAAM,YAAY,CAAC,CAAC;EACrE;EACA,IAAI,OAAO,IAAI;EACf,MAAM,gBAAgB,GAAG;CAC3B;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,YAAY;EACZ,gBAAgB,EAAE,GAAG,sBAAsB;EAC3C,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM;GACN,UAAU;GACV,UAAU,KAAA;GACV,MAAM,KAAA;EACR;EACA,cAAc,GAAG,KAAK,cAAc;GAElC,IAAI,CAAC,OAAO,iBAAiB,KAAA,KAAa,aAAa,CAAC,GAAG;GAC3D,QAAQ;GAER,EAAE,eAAe;GACjB,OAAO;EACT;EACA,cAAc,GAAG;GACf,IAAI,CAAC,OAAO,CAAC,OAAO;GAGpB,IAAI,EAAE,YAAY,KAAK,CAAC,MAAM,KAAK,aAAa;IAC9C,MAAM;IACN;GACF;GACA,MAAM,KAAK,OAAO,CAAC;EACrB;EACA,kBAAkB;GAChB,MAAM;EACR;EACA,YAAY,GAAG;GACb,IAAI,CAAC,OAAO,CAAC,OAAO;GACpB,MAAM,OAAO;GACb,IAAI,CAAC,KAAK,KAAK,aAAa;IAC1B,MAAM;IACN;GACF;GACA,MAAM,MAAM,aAAa,KAAK,MAAM,CAAC;GAErC,IADa,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,CACxE,KAAK,SACV,IACE,KACA,SAAS,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,UAAU,QAAQ,GAAG,GAAG,EAAE,QAAQ,CAC7E;QACK;IACL,MAAM,CAAC,GAAG,KAAK,YACb,QAAQ,GAAG,CAAC,CAAC,MACb,KAAK,MACL,KAAK,UAAU,KAAK,MACtB;IACA,IAAI,KAAK,SAAS,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,CAAC;GAChD;GACA,MAAM;EACR;EACA,UAAU,GAAG;GACX,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,IAAI,IAAI,GAAG;GAE3C,IAAI,kBAAkB,QAAQ,GAAG,CAAC,CAAC,IAAI,GAAG;GAC1C,EAAE,eAAe;GACjB,MAAM,OAAO,IAAI,SAAS,YAAY,IAAI;GAC1C,MAAM,EAAE,KAAK,WAAW,IAAI,SAAS,aAAa,IAAI,CAAC,CAAC;GACxD,MAAM,CAAC,GAAG,KAAK,YACb,QAAQ,GAAG,CAAC,CAAC,MACb;IAAE,GAAG,IAAI,IAAI,IAAI,QAAQ;IAAG,GAAG,IAAI,IAAI,IAAI,SAAS;GAAE,GACtD,MACF;GACA,IAAI,KAAK,SAAS,KAAK,MAAM,GAAG,GAAG,KAAK,CAAC;EAC3C;CACF;AACF;;;ACrRA,SAAgB,gBAAwC;CACtD,IAAI;CACJ,IAAI;;CAEJ,IAAI,aAAa;CAEjB,MAAM,SACJ,GACA,GACA,MACA,IACA,aACS;EACT,MAAM,QAAQ,eAAe,GAAG,MAAM,IAAA,KAA6B,QAAQ;EAC3E,MAAM,IAAI,EAAE,MAAM,IAChB,MAAM,SAAS,QAAQ,EAAE,UAAU,QAAQ,OAAO,KAAK,IAAI,KAC7D;EACA,EAAE,MAAM,OAAO,CAAC,EAAE,EAAE,CAAC;CACvB;;;;;CAMA,MAAM,iBACJ,GACA,MACA,IACA,aACY;EACZ,MAAM,KAAK,EAAE,QAA0B,CAAC,CAAC;EACzC,MAAM,UAAU,EAAE;EAClB,IAAI,OAAO,KAAA,KAAa,CAAC,SAAS,OAAO;EACzC,MAAM,IAAI,QAAQ,IAAI,EAAE;EACxB,IAAI,GAAG;GACL,MAAM,GAAG,GAAG,MAAM,IAAI,QAAQ;GAC9B,OAAO;EACT;EACA,MAAM,MAAM;EACZ,QAAa,QAAQ,CAAC,CAAC,WAAW;GAEhC,MAAM,QAAQ,QAAQ,IAAI,EAAE;GAC5B,IACE,SACA,QAAQ,KACR,QAAQ,cACR,EAAE,QAA0B,CAAC,CAAC,eAAe,IAE7C,MAAM,GAAG,OAAO,MAAM,IAAI,QAAQ;EACtC,CAAC;EACD,OAAO;CACT;CAEA,OAAO;EACL,IAAI;EACJ,QAAQ;EACR,gBAAgB,CAAC;EACjB,SAAS,GAAG;GACV,MAAM;EACR;EACA,aAAa;GACX,MAAM,KAAA;GACN,OAAO,KAAA;GACP;EACF;EACA,cAAc,IAAI,KAAK,cAAc;GACnC,OAAO,iBAAiB,KAAA,IAAY,MAAM,KAAA;GAC1C,OAAO,SAAS,KAAA;EAClB;EACA,cAAc,GAAG;GAEf,IAAI,EAAE,YAAY,GAAG,OAAO,KAAA;EAC9B;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,cAAc,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,UAAU,KAAK,MAAM;EAClE;EACA,UAAU,GAAG;GACX,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,IAAI,IAAI,GAAG;GAC3C,MAAM,OAAO,IAAI,SAAS,YAAY,IAAI;GAC1C,MAAM,IAAI,IAAI,SAAS,aAAa,IAAI;GACxC,MAAM,EAAE,QAAQ,EAAE;GAClB,MAAM,SAAS;IAAE,GAAG,IAAI,IAAI,IAAI,QAAQ;IAAG,GAAG,IAAI,IAAI,IAAI,SAAS;GAAE;GACrE,IAAI,cAAc,KAAK,MAAM,QAAQ,EAAE,KAAK,MAAM,GAAG,EAAE,eAAe;EACxE;CACF;AACF;;;;ACzFA,MAAM,gBAAgB;;;;;AAMtB,MAAM,eAAe;;AAGrB,SAAS,OAAO,QAAqD;CACnE,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,CAAC;CAChC,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;AACtF;;AAGA,SAAS,gBAAgB,OAAmB,MAA2C;CACrF,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK,SACH,OAAO,WAAW,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,KAAK,qBAAqB;EACnF,KAAK;EACL,KAAK,WAAW;GACd,MAAM,EAAE,GAAG,GAAG,OAAO,WAAW,MAAM;GACtC,OAAO,WACL,MAAM,MACN,MACA;IAAE;IAAG;GAAE,GACP;IAAE,GAAG,IAAI;IAAO,GAAG,IAAI;GAAO,GAC9B,qBACF;EACF;EAGA,KAAK;EACL,KAAK,QACH,OAAO;GAAE,MAAM;GAAW;GAAM,UAAU,MAAM;EAAS;CAC7D;AACF;;;;;;AAOA,SAAS,YACP,GACA,IACA,IACA,UACY;CACZ,IAAI,EAAE,MAAM,IAAI,EAAE,GAAG;EACnB,GAAG;EACH,aAAa,KAAA;CACf;CACA,IAAI;CAEJ,MAAM,SAAS,iBAAiB;EAC9B,OAAO;EACP,SAAS;CACX,GAAG,aAAa;CAChB,IAAI,OAAiC,EAAE,MAAM,KAAK,gBAAgB;EAChE,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE,GAAG;EACtB,OAAO;EACP,OAAO,WAAW,IAAI,CAAC;CACzB,CAAC;CACD,SAAS,SAAe;EACtB,OAAO;EACP,OAAO,KAAA;EACP,aAAa,MAAM;EACnB,aAAa,IAAI;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,aAAmB;;CAEjC,MAAM,0BAAU,IAAI,IAAgB;CACpC,OAAO,aAAa;EAClB,IAAI;EAGJ,aAAa;GACX,KAAK,MAAM,UAAU,SAAS,OAAO;GACrC,QAAQ,MAAM;EAChB;EACA,OAAO,GAAG,GAAG;GACX,MAAM,MAAM,EAAE,MAAM,IAClB,EAAE,UAAU,QAAQ,OAAO;IACzB,MAAM;IACN,MAAM,EAAE;IACR,SAAS,CAAC,EAAE,MAAM;IAClB,GAAI,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC;GACjD,CAAC,CACH;GACA,IAAI,EAAE,SAAS,aAAa,EAAE,IAAI,CAAC,CAAC,YAAY,OAAO,EAAE,MAAM,CAAC,IAAI,cAClE;GACF,MAAM,MAAM,gBAAgB,EAAE,MAAM;GACpC,IAAI,CAAC,OAAO,IAAI,QAAA,IAA6B;GAC7C,MAAM,QAAQ,gBAAgB,IAAI,OAAO,EAAE,IAAI;GAC/C,IAAI,CAAC,OAAO;GACZ,MAAM,QAAQ,EAAE,UAAU,QAAQ,SAAS,KAAK;GAChD,MAAM,SAAS,OAA0B,EAAE,UAAU,EAAE,QAAQ,MAAM,EAAE,IAAI,GAAG;GAE9E,IAAI,MAAM;GACV,IAAI,eAAqB,KAAA;GACzB,SAAS,YACP,GACA,IAAI,UACE;IACJ,MAAM;IACN,QAAQ,OAAO,MAAM;IAGrB,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC,EAAE,eAAe,IAAI,YAAY;IACxD,YAAY;KACV,EAAE,MAAM,OAAO,IAAI,EAAE;KACrB,EAAE,MAAM,IAAI,KAAK;IACnB,CAAC;GACH,SACM,QAAQ,OAAO,MAAM,CAC7B;GACA,IAAI,CAAC,KAAK,QAAQ,IAAI,MAAM;EAC9B;CACF,CAAC;AACH;;;;ACpFA,SAAgB,eAAuB;CACrC,OAAO;EACL,eAAe;EACf,WAAW;EACX,cAAc;EACd,eAAe;EACf,WAAW;EACX,SAAS;EACT,SAAS;EACT,UAAU;EACV,aAAa;EACb,cAAc;CAChB;AACF;;AAGA,SAAgB,cAAc,OAAwB,CAAC,GAAW;CAChE,MAAM,OAAO,IAAI,IAAI,aAAa,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CACzD,KAAK,MAAM,KAAK,MAAM,KAAK,IAAI,EAAE,IAAI,CAAC;CACtC,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;;AAGA,SAAgB,qBACd,MACgB;CAChB,OAAOC,uBAAW;EAAE,GAAG;EAAM,OAAO,KAAK,SAAS,aAAa;CAAE,CAAC;AACpE;;;;;;AAaA,SAAgB,eAAe,MAMV;CACnB,MAAM,SAAS,IAAI,IAAI,cAAc,KAAK,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;CACjF,MAAM,SAAS,SAAiB,KAAK,QAAQ,aAAa;CAO1D,OAAO;EAAE,WANS,gBAAgB;GAChC,OAAO,KAAK;GACZ,SAAS,KAAK;GACd,mBAAmB,OAAO,IAAI,OAAO,IAAI,CAAC;GAC1C;EACF,CACiB;EAAG,UAAU,OAAO,OAAO,IAAI,EAAE;CAAE;AACtD;;;AC3GA,MAAa,UAAmB;CAC9B,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM;EACJ;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;CACF;AACF;;;;;;;AC9HA,MAAa,cAAyD;CACpE,eAAe;CACf,QAAQ;CACR,WAAW;CACX,eAAe;CACf,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACP,UAAU;CACV,WAAW;AACb;;;;;AAMA,MAAa,gBAAmC;CAAC;CAAa;CAAS;AAAS;;;;;AAMhF,MAAa,kBAAqC,CAAC,SAAS;;AAG5D,MAAa,cAAiC;CAAC;CAAK;CAAM;CAAG;CAAM;CAAK;CAAG;CAAG;AAAC;;AAG/E,MAAa,eAAkC;CAAC;CAAK;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;;AAGrE,MAAa,eAAkC,CAAC,GAAG,CAAC;;AAGpD,MAAa,mBAA+B;;AAK5C,MAAa,oBAIP;CACJ;EAAE,OAAO;EAAQ,OAAO;EAAiB,OAAO;GAAE,MAAM;GAAQ,MAAM;EAAO;CAAE;CAC/E;EACE,OAAO;EACP,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"}