@embedpdf/plugin-annotation 3.0.0-next.4 → 3.0.0-next.6

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"capability-CYbikyob.cjs","names":["initialTextStyle","textQuadBounds","initialTextStyle","FLAG_KEYS","InteractionToken","CONTINUOUS_RENDER_POLICY"],"sources":["../src/types.ts","../src/repository/seam.ts","../src/repository/props.ts","../src/repository/projection.ts","../src/repository/kinds/shape.ts","../src/repository/kinds/stroke.ts","../src/repository/kinds/freeText.ts","../src/repository/kinds/quads.ts","../src/repository/kinds/misc.ts","../src/repository/links.ts","../src/repository/index.ts","../src/text-item.ts","../src/tools.ts","../src/placement.ts","../src/capability.ts"],"sourcesContent":["import { createCapabilityToken, type PageObjectNumber } from '@embedpdf/core';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport type {\n AnnotationAppearanceImage,\n AnnotationDTO,\n AnnotationDraft,\n AnnotationPatch,\n AnnotationRef,\n AttachmentContent,\n AttachmentFileSource,\n BinarySource,\n PdfLinkTarget,\n PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport type { AnnotationToolInput, ResolvedTool } from './tools';\nimport type {\n AnnotationFlags,\n AnnotationProps,\n AnnotationPropsPatch,\n ChromeNode,\n CreationDraftAnchor,\n Geom,\n Id,\n Model,\n PropKey,\n PropSpec,\n Rect,\n RenderItem,\n SnapSettings,\n Subtype,\n TextEndAnchor,\n TextQuad,\n Vec,\n ViewEnv,\n} from '@embedpdf/core-annotation';\n\n/**\n * Selection-chrome settings: the outline, resize/vertex handles, and the rotate\n * knob. ONE unit story — every length is CSS px, screen-constant across zoom\n * (the plugin converts to content units per event/page via the view scale).\n * Every color falls back to `accent`, so the common case is one line:\n * `annotationPlugin({ chrome: { accent: '#e91e63' } })`. Deep-partial merged\n * over {@link DEFAULT_CHROME}; live-adjustable via\n * {@link AnnotationCapability.setChrome}.\n */\nexport interface ChromeSettings {\n /** The one color every chrome piece derives from unless overridden. */\n accent: string;\n outline: {\n /** ONE style at rest AND while rotated — the box never flips style mid-gesture. */\n style: 'solid' | 'dashed';\n /** Stroke width, px. */\n width: number;\n /** Overrides `accent`. */\n color?: string;\n };\n /** Resize + vertex handles (independent of the knob — size them apart). */\n handles: {\n /** Visual square side, px. */\n size: number;\n /** Grab-zone square side, px — keep ≥ 24 for touch. */\n hitSize: number;\n fill: string;\n /** Overrides `accent`. */\n stroke?: string;\n };\n /** The rotate handle. Page-bound placement (flip/clamp) always applies. */\n knob: {\n /** Grab-dot diameter, px. */\n size: number;\n /** Grab-zone square side, px — keep ≥ 24 for touch. */\n hitSize: number;\n /** Stalk length, px — selection edge to dot centre. */\n offset: number;\n /** Draw the connector stalk. */\n stalk: boolean;\n fill: string;\n /** Overrides `accent` (dot outline + stalk). */\n stroke?: string;\n };\n /** The rotation guides shown while a rotate gesture runs: a fixed 0°/90°\n * reference cross + a live indicator line, drawn as full-bleed chords of the\n * page through the pivot. */\n guides: {\n /** Show the guides at all. Default true. */\n enabled: boolean;\n style: 'solid' | 'dashed';\n /** Stroke width, px. */\n width: number;\n /** The fixed reference cross. Color overrides `accent`. */\n axisColor?: string;\n axisOpacity: number;\n /** The line riding the live angle. Color overrides `accent`. */\n indicatorColor?: string;\n indicatorOpacity: number;\n };\n}\n\n/** Deep-partial patch for {@link ChromeSettings} — config + `setChrome` input. */\nexport interface ChromeSettingsPatch {\n accent?: string;\n outline?: Partial<ChromeSettings['outline']>;\n handles?: Partial<ChromeSettings['handles']>;\n knob?: Partial<ChromeSettings['knob']>;\n guides?: Partial<ChromeSettings['guides']>;\n}\n\nexport interface AnnotationState {\n model: Model;\n chrome: ChromeSettings;\n /**\n * The armed tool's FOOTPRINT ghost: where (and what) the NEXT click would\n * place — the stamp's fitted image box, or a click-create tool's default\n * geometry — computed by the same rules the placement uses (WYSIWYG). In the\n * store (not the capability closure) because it is RENDERED — vector ghosts\n * ride `pageItems`, image ghosts (stamp) render via the framework's\n * `ToolGhost`. The armed bytes stay out of the store.\n */\n toolGhost: ToolGhost | null;\n /** Bumps on every arm/disarm — the render layer's cue to rebuild (or drop)\n * the ghost preview object URL. Never rendered itself. */\n stampArmEpoch: number;\n}\n\n/** The armed tool's would-be placement under the cursor (content space). */\nexport type ToolGhost = {\n pon: PageObjectNumber;\n /** The exact box the click's placement would use. */\n box: Rect;\n /** The tool's upright counter-rotation at this hover (deg, CW). */\n rot: number;\n} & (\n | { kind: 'image' } // the armed stamp raster — framework blits it\n | { kind: 'vector'; toolId: string; geom: Geom } // painted via pageItems/scene\n);\n\n/** Registration options for {@link annotationPlugin} — the initial values of the\n * live-adjustable {@link AnnotationCapability.setSnap} /\n * {@link AnnotationCapability.setChrome} settings. */\nexport interface AnnotationConfig {\n snap?: {\n /** Alignment guides while moving (snap to other annotations + the page).\n * Default true. */\n guides?: boolean;\n /** Guide snap tolerance, content units (PDF pt). Default 5. */\n guideThreshold?: number;\n /** Snap the rotate gesture onto `rotationAngles`. Default true. */\n rotation?: boolean;\n /** Default `[0, 90, 180, 270]`. */\n rotationAngles?: number[];\n /** Rotation snap tolerance, degrees. Default 4. */\n rotationThreshold?: number;\n };\n /** Selection-chrome styling + grab geometry (all lengths CSS px). */\n chrome?: ChromeSettingsPatch;\n /**\n * Add or configure authoring tools at load. Entries MERGE over the built-ins by\n * id (configure one — `{ id: 'ink', defaults: { strokeWidth: 6 } }`), ADD a new\n * tool (a fresh id), or make a preset with `extends`\n * (`{ id: 'arrow', extends: 'line', defaults: { lineEndings: { end: 'open-arrow' } } }`).\n * See {@link AnnotationToolDef}. The runtime equivalent is\n * {@link AnnotationCapability.registerTool}.\n */\n tools?: AnnotationToolInput[];\n}\nexport type AnnotationAction =\n | { type: 'SET_MODEL'; model: Model }\n | { type: 'SET_CHROME'; patch: ChromeSettingsPatch }\n | { type: 'SET_TOOL_GHOST'; ghost: ToolGhost | null }\n | { type: 'STAMP_ARM_CHANGED' };\n\n/** A plugin (forms, links) marks some annotations as interactive: while engaged,\n * they render their own DOM and are NOT geometry-editable. Suspend → editable. */\n/**\n * One clickable link area on a page (content space): a standalone link\n * annotation, or one segment of a parent's ATTACHED link. See\n * {@link AnnotationHostCapability.linkItemsOn}.\n */\nexport interface LinkNavItem {\n /** Stable per-page key: the annot id, `#n`-suffixed for attached segments. */\n id: string;\n rect: Rect;\n target: PdfLinkTarget;\n}\n\nexport interface Behavior {\n id: string;\n matches(a: { subtype: Subtype; ref: AnnotationRef | null }): boolean;\n engaged(): boolean;\n}\n\n/**\n * The current selection's editable properties, ready to render: the ordered\n * {@link PropSpec}s EVERY selected kind declares (a mixed selection shows the\n * shared subset, in the first kind's order), the first member's `values`, and\n * which keys differ across members (`mixed` — render an indeterminate control).\n * Empty `specs` = nothing selected / nothing editable.\n */\nexport interface SelectionProps {\n specs: PropSpec[];\n values: Partial<AnnotationProps>;\n mixed: PropKey[];\n}\n\n/**\n * The selection's `/F` flag state, ready for a menu/sidebar: one value per\n * flag — `true`/`false` when every selected annotation agrees, `null` when\n * they differ (render an indeterminate control). The read half of\n * {@link AnnotationCapability.updateSelectionFlags}.\n */\nexport type SelectionFlags = { [K in keyof AnnotationFlags]: boolean | null };\n\n/**\n * A free-text annotation projected for the framework: the box (content space,\n * live gesture applied) + the plain text + an `editing` flag + a ready-to-spread\n * CSS style. The framework renders ONE editable element from this and nothing\n * more — all the mapping (fonts, colours, alignment) is done here, once.\n */\nexport interface TextItem {\n id: Id;\n ref: AnnotationRef | null;\n box: Rect;\n contents: string;\n editing: boolean;\n /** Applied rotation (deg, CW). `box` is the UNROTATED text box; the framework\n * rotates the editable element about its centre by this. 0/undefined = none. */\n rot?: number;\n css: {\n fontFamily: string;\n /** Content units (the framework multiplies by the page scale). */\n fontSize: number;\n lineHeight: number;\n color: string;\n align: 'left' | 'center' | 'right';\n padding: number;\n /** `/C` box background as a CSS colour, or null for transparent. */\n background: string | null;\n };\n}\n\n/**\n * The PUBLIC annotation API — the documented, stable surface for application code\n * (toolbars, sidebars, app logic). Resolve it with the token re-exported from the\n * package root (`@embedpdf/plugin-annotation`).\n *\n * Framework-only plumbing (render projection, pointer gestures, behavior\n * registration) lives on {@link AnnotationHostCapability}, reachable only through\n * the `@embedpdf/plugin-annotation/internal` entry. Both are the SAME runtime\n * object — two typed lenses on one token — so app code simply can't see the host\n * methods.\n */\nexport interface AnnotationCapability {\n // ── data API: the mutation vocabulary (engine-core types, addressable by ref) ──\n /**\n * Create an annotation on a page. `draft` is the engine-core draft for its\n * subtype (PDF-space, sRGB). Resolves to the new annotation's durable `ref`.\n * The same path the draw tools use, so programmatic and interactive creation\n * share one optimistic flow + one event stream.\n */\n create(pon: PageObjectNumber, draft: AnnotationDraft): Promise<AnnotationRef>;\n /**\n * Patch an existing annotation. `patch` is the engine-core patch for the\n * annotation's subtype — style, endings, contents, geometry are ALL just\n * fields here (there is no separate \"set style\"). Attribution is automatic\n * from the session identity.\n */\n update(ref: AnnotationRef, patch: AnnotationPatch): Promise<void>;\n /** Delete an annotation by ref. */\n delete(ref: AnnotationRef): Promise<void>;\n /**\n * Restyle the current selection with ONE flat property patch — the write half\n * of {@link getSelectionProps}. Each selected annotation takes the keys its\n * kind declares (`propsFor`) and ignores the rest, so a single patch restyles\n * a mixed selection. Optimistic: the model updates immediately; one engine\n * write per changed member re-syncs from the authoritative DTO.\n */\n updateSelection(patch: AnnotationPropsPatch): void;\n /**\n * Merge a `/F` flags patch into the current selection — the write half of\n * {@link getSelectionFlags}. Optimistic; one flags-only engine write per\n * changed member, which never re-bakes an appearance. Deliberately NOT\n * blocked by `locked`: this is how you unlock (Acrobat's Locked checkbox\n * stays live on a locked annotation). E.g. `{ locked: true }`,\n * `{ print: false }`, `{ hidden: true }`.\n */\n updateSelectionFlags(patch: Partial<AnnotationFlags>): void;\n /**\n * The selection's `/F` flag state: per-flag `true`/`false`, or `null` when\n * the selected annotations disagree (indeterminate). `null` overall when\n * nothing is selected. Stable reference between model changes.\n */\n getSelectionFlags(): SelectionFlags | null;\n\n // ── property introspection (the machine-readable \"what can I edit here\") ──\n /**\n * The selection's editable properties: ordered specs shared by every selected\n * kind + current values + which keys are mixed. THE way to build a property\n * sidebar/toolbar — render `specs` in order, write back via\n * {@link updateSelection}. Stable reference between model changes.\n */\n getSelectionProps(): SelectionProps;\n /** The ordered property specs a TOOL's target kind declares (callout → the\n * free-text kind). Drives the same sidebar when nothing is selected, paired\n * with {@link currentDefaults}/{@link setDefaults}. */\n propsForTool(toolId: string): PropSpec[];\n\n // ── authorization (mirrors the engine's own enforcement; the engine still\n // independently enforces, and per-owner collab rules are checked there) ──\n canCreate(): boolean;\n canEdit(ref: AnnotationRef): boolean;\n canDelete(ref: AnnotationRef): boolean;\n\n // ── reads (canonical engine DTOs) ──\n /** The annotation for a ref, or null if unknown / not yet committed. */\n get(ref: AnnotationRef): AnnotationDTO | null;\n /** Every committed annotation on a page, in z-order. */\n list(pon: PageObjectNumber): AnnotationDTO[];\n /** The selected annotations as DTOs (skips not-yet-committed drafts). */\n getSelected(): AnnotationDTO[];\n\n // ── selection ──\n selection(): Id[];\n /** The current selection as durable annotation refs (skips not-yet-committed drafts). */\n getSelection(): AnnotationRef[];\n /**\n * Select an annotation by ref programmatically — e.g. auto-selecting a\n * freshly placed form widget. Selecting a group member takes the whole\n * group, exactly like a click. Unknown/unselectable refs no-op. `add`\n * extends the current selection instead of replacing it.\n */\n select(ref: AnnotationRef, options?: { add?: boolean }): void;\n\n // ── grouping (engine `/IRT` + `/RT /Group`; selecting one member selects all) ──\n /** Group the current selection into one unit (the bottom-most member is the\n * primary; the rest become `/RT /Group` subordinates). Page-local: no-op\n * unless 2+ committed annotations on a single page are selected. */\n group(): Promise<void>;\n /** Ungroup the group(s) the current selection touches — every subordinate\n * becomes top-level again. */\n ungroup(): Promise<void>;\n /** Whether {@link group} would do something for the current selection. */\n canGroup(): boolean;\n /** Whether {@link ungroup} would do something for the current selection. */\n canUngroup(): boolean;\n\n // ── tool defaults (LOCAL drawing preferences — never collaborative) ──\n /** Patch a tool's defaults for newly drawn annotations — the SAME flat\n * vocabulary {@link updateSelection} writes. */\n setDefaults(subtype: Subtype, patch: AnnotationPropsPatch): void;\n /** The RESOLVED full props bag a tool will use for new annotations. */\n currentDefaults(subtype: Subtype): AnnotationProps;\n // ── snapping (alignment guides while moving + rotation snap) ──\n /** Live-adjust snapping — wire a UI toggle here (e.g.\n * `setSnap({ guides: false })`). Initial values come from the plugin's\n * registration config ({@link AnnotationConfig}). */\n setSnap(patch: Partial<SnapSettings>): void;\n /** The current snap settings. */\n snapSettings(): SnapSettings;\n // ── selection chrome (outline / handles / rotate knob; all lengths CSS px) ──\n /** Live-adjust the selection chrome — wire theming here (e.g.\n * `setChrome({ accent: '#e91e63' })`). Deep-partial merge; initial values\n * come from the plugin's registration config ({@link AnnotationConfig}). */\n setChrome(patch: ChromeSettingsPatch): void;\n /** The current (fully resolved) chrome settings. */\n chromeSettings(): ChromeSettings;\n // ── rotation (selection-scoped; rotatable kinds only) ──\n /** Rotate the current selection a quarter-turn clockwise about its centre\n * (a single shape's own centre / the union-box centre for a group). */\n rotateSelection90(): void;\n /** Reset the current selection to its as-authored orientation (rotation → 0). */\n resetSelectionRotation(): void;\n // ── stamp tool (click-to-place with an armed binary payload) ──\n /**\n * Arm the stamp tool: `source` (PNG, JPEG, or single-page PDF bytes —\n * format sniffed, never trusted) becomes the content of the next stamp(s)\n * placed by clicking a page. The placement rect is sized from the image's\n * intrinsic aspect ratio around `targetWidth` (PDF points, default 150)\n * and centred on the click. Also activates the `'stamp'` interaction tool;\n * the payload stays armed for repeat placement until the tool changes or\n * {@link disarmStamp} is called. Resolves once the payload is validated.\n */\n armStamp(input: StampToolInput): Promise<void>;\n /** Drop the armed stamp payload (a tool change away from 'stamp' does this too). */\n disarmStamp(): void;\n /**\n * Install the ONE file-picker port every click-then-pick tool resolves\n * through (see {@link FilePickerProvider}) — the stamp `'prompt'` source and\n * the file-attachment tool today. The framework adapter installs a\n * file-dialog provider by default; pass your own (asset library, cloud\n * drive — switch on `req.subtype` / `req.toolId`), or `null` to make\n * click-then-pick tools inert. One slot; last write wins.\n */\n setFilePickerProvider(provider: FilePickerProvider | null): void;\n /**\n * Decode and return the file embedded in a FileAttachment annotation —\n * bytes plus the name/mime needed to hand it to the user. Listings carry\n * only metadata (`FileAttachmentAnnotationDTO.file`); this is the explicit\n * bytes-out call. Throws when the engine transport has not shipped\n * attachment download (feature-detected).\n */\n downloadAttachment(ref: AnnotationRef): Promise<AttachmentContent>;\n\n // ── tools (add/configure at runtime; the config equivalent is `tools`) ──\n /**\n * Register (or replace, by id) an authoring tool at runtime — the imperative\n * mirror of the `tools` config. Same {@link AnnotationToolDef} vocabulary\n * (`extends`, per-tool `defaults`, …). Returns an unregister fn.\n */\n registerTool(def: AnnotationToolInput): () => void;\n\n // ── lifecycle ──\n deleteSelection(): void;\n deselect(): void;\n cancel(): void;\n}\n\n/** Payload for {@link AnnotationCapability.armStamp}. */\nexport interface StampToolInput {\n /** PNG, JPEG, or single-page PDF bytes (`Blob | Uint8Array | BinaryPayload`). */\n source: BinarySource;\n /** Placed width in PDF points (height follows the intrinsic aspect). Default 150. */\n targetWidth?: number;\n /**\n * A browser-paintable render of `source` for the hover ghost (PNG/JPEG).\n * Required for the ghost when `source` is PDF bytes — the browser cannot\n * paint those; the caller (e.g. a stamp library) supplies its cached page\n * render. Raster sources default to the source itself; omit everywhere\n * else and the tool simply shows no ghost.\n */\n preview?: BinarySource;\n /**\n * The source's intrinsic size in PDF points. Raster sources are measured\n * from their own header, but PDF bytes carry no sniffable dimensions —\n * callers that know the page size (a stamp library does, from import)\n * pass it here so placement honours the true aspect instead of falling\n * back to a square.\n */\n intrinsicSize?: { width: number; height: number };\n}\n\n/** The armed stamp's paintable preview, for the render layer's ghost `<img>`. */\nexport interface ArmedStampPreview {\n bytes: Uint8Array;\n mimeType?: string;\n}\n\n/**\n * What the {@link FilePickerProvider} is asked for: which tool clicked (id +\n * the kind it creates), the tool's `accept` filter, and the page-space point\n * the click landed on — enough to route per tool (asset library for stamps,\n * cloud drive for attachments) or position a picker near the click. Pure\n * data — the request crosses the plugin↔adapter boundary as a message.\n */\nexport interface FilePromptRequest {\n toolId: string;\n /** The kind the placement creates — the routing key for per-tool pickers. */\n subtype: Subtype;\n /** The tool's file-dialog filter hint (from the tool def). UX only —\n * the engine sniffs/validates the bytes for real. */\n accept?: string;\n pon: PageObjectNumber;\n /** The content-space point the placement is centred on. */\n point: Vec;\n}\n\n/**\n * The ONE environment port behind every click-then-pick tool — the stamp\n * `'prompt'` source and the file-attachment tool (the file is picked AFTER\n * the spot): given a click, produce the file to place, `null` to cancel. The\n * plugin declares this contract but never implements it — \"get bytes from the\n * environment\" is a DOM concern (a file dialog), so the framework adapter\n * installs the implementation via\n * {@link AnnotationCapability.setFilePickerProvider}. This keeps the plugin\n * DOM-free (Rust-portable) while the zero-config file dialog works out of the\n * box. The return shape is the engine's file vocabulary: a stamp consumes\n * only `data`; an attachment embeds the whole thing. A picked `File` carries\n * its own name and mime — a provider returning raw bytes for an attachment\n * must supply `name` itself.\n */\nexport type FilePickerProvider = (req: FilePromptRequest) => Promise<AttachmentFileSource | null>;\n\n/**\n * The HOST (framework) surface: everything the render layer, the interaction hub,\n * and sibling plugins need, on top of the public {@link AnnotationCapability}.\n * Internal — import the token from `@embedpdf/plugin-annotation/internal`, never\n * from application code.\n */\nexport interface AnnotationHostCapability extends AnnotationCapability {\n // ── render projection (consumed by the framework render layer) ──\n /** `view` (the page's scale + total display rotation, from its transform)\n * projects screen-anchored (`noZoom`/`noRotate`) bodies to their effective\n * footprint. Pass it from the page context; absent → stored geometry. */\n pageItems(pon: PageObjectNumber, view?: ViewEnv): RenderItem[];\n /** `scale` (view px per content unit, from the page's transform) converts the\n * px chrome settings into content units — pass it so the knob stalk and grab\n * zones are screen-constant. `rotation` (the page's total display rotation)\n * and `zoom` (the page's zoom RELATIVE to its 100% baseline —\n * `transform.zoom`, NOT `viewScale`) complete the view env for\n * screen-anchored bodies. Absent scale → settings are read as content\n * units. */\n chrome(\n pon: PageObjectNumber,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): ChromeNode[];\n /** The anchor for a selection-aware floating menu: the primary page + the\n * selection's union box on that page (content space), or null when nothing\n * selectable is selected. One anchor regardless of cross-page selection.\n * `scale`/`rotation`/`zoom` as in {@link chrome} (the anchor page's view). */\n selectionAnchor(\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): { pon: PageObjectNumber; bounds: Rect; knob?: Vec } | null;\n /** The anchor + action state for a live multi-click creation draft, or null. */\n creationDraftAnchor(): CreationDraftAnchor | null;\n /** Cache key for a page's baked appearances: the COMMITTED id + AP box of every\n * baked annotation (gesture previews excluded). Changes exactly once per\n * committed create/geometry-edit, so the render layer refetches rasters then —\n * and only then (a stamp resize re-fits its AP engine-side, for example). */\n appearanceEpoch(pon: PageObjectNumber): string;\n /**\n * The scale a baked appearance should render at for a desired device\n * scale — `snapAppearanceScale` over the document's `renderPolicy` (the\n * kernel-materialized fact; identity under `continuous`). THE identity a\n * render layer keys its bake effect on: inside an appearance-lattice rung,\n * zoom ticks produce the same value → no re-bake; crossing a rung re-bakes\n * once. This plugin owns its raster product end to end — the policy is a\n * document fact, not another plugin's possession.\n */\n bakeScale(renderScale: number): number;\n /** The engine's rendered /AP appearance images for a page — the `baked` visual. */\n appearances(\n pon: PageObjectNumber,\n scale: number,\n signal?: AbortSignal,\n ): Promise<AnnotationAppearanceImage[]>;\n /** Convert an engine appearance rect (PDF user space) to a content-space box, so\n * the renderer places the baked bitmap by its OWN `/Rect` without touching the\n * PDF↔content seam. Null if the page's crop box is unknown. */\n toContentBox(pon: PageObjectNumber, rect: PdfRect): Rect | null;\n ensurePage(pon: PageObjectNumber): void; // lazy-load a page's annotations\n /**\n * Drop and RE-READ one page's annotations from the engine — the hook for\n * cross-plane mutations (e.g. `doc.forms.createField`/`deleteField`\n * changing the page's widget population underneath this plugin). Resolves\n * when the fresh page is in the model, so a caller can select what it just\n * created.\n */\n reloadPage(pon: PageObjectNumber): Promise<void>;\n // ── free-text (the editable-element layer) ──\n /** The free-text boxes on a page, ready to render as editable elements.\n * `view` as in {@link pageItems}. */\n textItems(pon: PageObjectNumber, view?: ViewEnv): TextItem[];\n /** The id of the annotation currently being text-edited, or null. Read live (not\n * from a stale render) so the editor can tell a real exit from a focus-steal. */\n currentEditing(): Id | null;\n /** Enter text-edit on a free-text annotation (focus its editable element). */\n beginTextEdit(ref: AnnotationRef): void;\n /** Enter text-edit on whatever free-text box is under a content point — wired\n * to a double-click by the interaction edit handler. */\n beginTextEditAt(\n pon: PageObjectNumber,\n point: Vec,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): void;\n /** Apply the editor's plain text — optimistic locally, debounced to the engine. */\n setContents(ref: AnnotationRef, text: string): void;\n /** Leave text-edit (flush any pending write). */\n endTextEdit(): void;\n // ── hit-testing & cursor (consumed by the interaction edit handler) ──\n /** What's under a content point — for the edit handler's capture decision.\n * `scale` (the page's view px per content unit) keeps grab zones\n * screen-constant; `rotation` + `zoom` (relative, `transform.zoom`)\n * complete the view env for screen-anchored bodies. Pass all three from\n * the pointer sample. */\n hitKind(\n pon: PageObjectNumber,\n point: Vec,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): 'handle' | 'rotate' | 'group-handle' | 'annot' | 'empty';\n /** The cursor to show at a content point (resize over a handle, move/pointer over a body, else null). */\n cursorAt(\n pon: PageObjectNumber,\n point: Vec,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): string | null;\n /**\n * Report the pointer's position for hover state (`null` = off every page).\n * Diffs the topmost hit against the model and dispatches only on CHANGE\n * (enter/leave cadence) — drives scene-level hover affordances like the\n * redaction mark's applied-look preview. Called from the edit handler's\n * onHover, which already samples every move for cursor claims.\n */\n hoverAt(\n at: {\n pon: PageObjectNumber;\n point: Vec;\n scale?: number;\n rotation?: PageRotation;\n zoom?: number;\n } | null,\n ): void;\n behaviorFor(a: { subtype: Subtype; ref: AnnotationRef | null }): Behavior | null;\n /**\n * The clickable link areas of a page (content space): standalone link\n * annotations plus every ATTACHED-link segment (folded children — their\n * rects derived by the SAME rule the reconciler writes, so the clickable\n * area and the written `/Rect`s can't disagree). Hidden annotations are\n * excluded. THE data feed for the navigation plane (plugin-link);\n * memoized by model identity for selector use.\n */\n linkItemsOn(pon: PageObjectNumber): LinkNavItem[];\n /** Drop selected annotations whose Behavior is currently ENGAGED — inert\n * things cannot stay selected. Call after anything that flips engagement\n * (the plugin wires it to tool changes). */\n pruneEngagedSelection(): void;\n // ── interaction intents (run the pure core + perform engine effects) ──\n editPointer(\n phase: 'down' | 'move' | 'up',\n pon: PageObjectNumber,\n point: Vec,\n shift: boolean,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): void;\n marqueePointer(\n phase: 'down' | 'move' | 'up',\n pon: PageObjectNumber,\n point: Vec,\n shift: boolean,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): void;\n /** Run the draw gesture for an authoring TOOL (by id). The plugin resolves it\n * to a routing subtype + defaults preset; a bare subtype also works (headless).\n * `displayRotation` (the DOWN sample's page rotation: /Rotate + view rotation)\n * feeds the tool's `upright` policy — omit it and upright is a no-op. */\n createPointer(\n tool: string,\n phase: 'down' | 'move' | 'up',\n pon: PageObjectNumber,\n point: Vec,\n finish?: boolean,\n displayRotation?: PageRotation,\n ): void;\n finishCreationDraft(): void;\n /** Commit the strokes currently buffered by an ink tool's grouping window. */\n finishInkDraft(): void;\n cancelCreationDraft(): void;\n /** Create one text-markup annotation on a page from the selected text's\n * per-line oriented quads (content space) — the `text-selection` create\n * gesture. Axis-aligned callers build quads with `textQuadFromRect`. */\n createMarkup(subtype: Subtype, pon: PageObjectNumber, quads: TextQuad[], preset?: string): void;\n /** Create a caret annotation at a text-selection end anchor. */\n createCaret(pon: PageObjectNumber, anchor: TextEndAnchor): void;\n /** Create one Adobe-compatible Caret + StrikeOut replace-text group. */\n createReplaceText(\n pon: PageObjectNumber,\n quads: TextQuad[],\n anchor: TextEndAnchor,\n preset?: string,\n ): void;\n /** Set the live markup preview from the selection's per-page quads (renders a\n * ghost that looks like the markup it will become). */\n previewMarkup(subtype: Subtype, quadsByPage: Record<number, TextQuad[]>, preset?: string): void;\n clearMarkupPreview(): void;\n // ── stamp placement (consumed by the interaction stamp handler) ──\n /** Place the armed stamp centred on a content point. Returns false (no\n * capture) when nothing is armed. `displayRotation` (the click sample's page\n * rotation) feeds the active tool's `upright` policy. */\n placeArmedStamp(pon: PageObjectNumber, point: Vec, displayRotation?: PageRotation): boolean;\n /**\n * The one click-to-place entry for every payload-carrying tool (stamp /\n * note / file attachment) — the place handler forwards each down here.\n * Armed payload first, then the active tool's kind routes; returns whether\n * the click was consumed.\n */\n placeAt(pon: PageObjectNumber, point: Vec, displayRotation?: PageRotation): boolean;\n /** Whether a stamp payload is armed — the hover handler's cheap pre-check. */\n hasArmedStamp(): boolean;\n /**\n * Update the armed tool's FOOTPRINT ghost to a content point — the stamp's\n * fitted image box (same fit + clamp as placement), or a click-create tool's\n * default geometry (same anchor + clamp as the click commit). The ghost IS\n * the placement, never an approximation. Tools without a determinable\n * footprint (or with a `false` ghost policy) clear instead.\n */\n ghostHoverAt(\n toolId: string,\n pon: PageObjectNumber,\n point: Vec,\n displayRotation?: PageRotation,\n ): void;\n /** Drop the hover ghost (pointer left the pages / a gesture started). */\n clearGhost(): void;\n /**\n * Drive the transient placement preview during an EXTERNALLY-owned creation\n * gesture (the form plugin's drag-to-place): the box the commit would use,\n * page-clamped, styled from the TOOL's defaults, painted through the same\n * ghost pipeline as every footprint. Sibling plugins call THIS — never the\n * annotation store directly.\n */\n setPlacementPreview(toolId: string, pon: PageObjectNumber, box: Rect): void;\n /** Drop the placement preview (gesture ended — commit, cancel, or error). */\n clearPlacementPreview(): void;\n // ── ghost projection (consumed by the framework render layer) ──\n /** The armed tool's footprint ghost on a page (content space), or null.\n * Vector ghosts also ride {@link pageItems}; only `kind: 'image'` ghosts\n * need the framework's blit. */\n toolGhost(pon: PageObjectNumber): ToolGhost | null;\n /** The armed stamp's paintable preview bytes, or null (no ghost to show). */\n armedStampPreview(): ArmedStampPreview | null;\n /** Bumps on arm/disarm — keys the render layer's preview object-URL lifetime. */\n stampArmEpoch(): number;\n /**\n * Resolve the ACTIVE tool's {@link StampSourceSpec} for a click and place a\n * stamp centred on `point`: fixed `bytes` land immediately; a `'prompt'` source\n * asks the installed {@link FilePickerProvider} (placement is dropped if it\n * cancels, or if the tool/document changed while it was open). Returns false\n * (no capture) when the active tool has no source. The click-then-pick\n * counterpart of {@link placeArmedStamp}. `displayRotation` as on\n * {@link placeArmedStamp}.\n */\n requestStampAt(pon: PageObjectNumber, point: Vec, displayRotation?: PageRotation): boolean;\n // ── tool registry (consumed by the plugin init + interaction handlers) ──\n /** Every resolved tool (built-ins + config `tools`), for the registration loop. */\n tools(): ResolvedTool[];\n /** One resolved tool by id, or null when it is not registered. */\n tool(id: string): ResolvedTool | null;\n /** A tool's routing subtype (arrow → `line`) — how the draw handler picks the\n * gesture and the created annotation's PDF kind. Falls back to the id. */\n toolSubtype(id: string): Subtype;\n // ── extension point for sibling plugins (forms, links) ──\n registerBehavior(b: Behavior): () => void;\n}\n\n/**\n * The annotation capability token. Typed to the full {@link AnnotationHostCapability}\n * here (the package internals + the `/internal` entry use this view). The package\n * root re-exports the SAME token narrowed to {@link AnnotationCapability}.\n */\nexport const AnnotationToken = createCapabilityToken<AnnotationHostCapability>('annotation');\n","/**\n * The geometry/colour/rotation SEAM between the engine's PDF-space wire\n * vocabulary and the core's content-space model. Every conversion between the\n * two worlds lives here — kind modules speak through these helpers and never\n * hand-roll a convention flip.\n */\nimport type {\n AnnotationDTO,\n AnnotationRef,\n Color,\n PdfLinkTarget,\n PdfLinkTargetWritable,\n PdfRect,\n PdfRectDifferences,\n StandardFont,\n WidgetAppearance,\n} from '@embedpdf/engine-core/runtime';\nimport {\n contentToPdfRect,\n normalizeDeg,\n pdfToContentRect,\n rotatedAabb,\n type AnnotationPropsPatch,\n type Border,\n type Geom,\n type Rect,\n type Style,\n} from '@embedpdf/core-annotation';\n\n// The content↔PDF bridge, re-exported so kind modules cross the seam through\n// ONE import point and never reach into the core's geometry directly.\nexport {\n contentToPdfPoint,\n contentToPdfRect,\n pdfToContentPoint,\n pdfToContentRect,\n} from '@embedpdf/core-annotation';\n\nexport function refKey(ref: AnnotationRef): string {\n return ref.kind === 'objectNumber'\n ? `obj:${ref.annotObjectNumber}`\n : ref.kind === 'nm'\n ? `nm:${ref.nm}`\n : `idx:${ref.pageObjectNumber}:${ref.index}`;\n}\n\n/* ── colour seam (engine Color ↔ CSS hex) ─────────────────────────────────── */\n\nconst h2 = (n: number) =>\n Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, '0');\nexport const colorToCss = (c: Color): string => `#${h2(c.r)}${h2(c.g)}${h2(c.b)}`;\nexport function cssToColor(css: string): Color {\n const s = css.trim();\n const m6 = /^#?([0-9a-f]{6})$/i.exec(s);\n if (m6) {\n const n = parseInt(m6[1], 16);\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };\n }\n const m3 = /^#?([0-9a-f]{3})$/i.exec(s);\n if (m3) {\n const [a, b, c] = m3[1];\n return { r: parseInt(a + a, 16), g: parseInt(b + b, 16), b: parseInt(c + c, 16) };\n }\n return { r: 0, g: 0, b: 0 };\n}\n\n/* ── rotation seam (CW content ↔ PDF convention) ──────────────────────────────\n * The model's `rot` is CLOCKWISE in content space (y-down). PDF user space is\n * y-up, so the y-flip at this boundary turns a CW content tilt into a CCW PDF\n * tilt of the same magnitude — i.e. the stored `/EMBD_Metadata/Rotation` is the\n * NEGATION (mod 360). This is the ONE place the convention is converted; every\n * layer above speaks CW-content and the engine/PDFium speaks the PDF angle.\n */\nexport const toPdfRotation = (rotCW: number): number => normalizeDeg(-rotCW);\nexport const fromPdfRotation = (rotPdf: number): number => normalizeDeg(-rotPdf);\n\n/** Advisory `rot` for a vertex geom, from a DTO's (PDF-convention) `rotation`.\n * Absent → no `rot` key (kept off the geom so unrotated shapes stay clean). */\nexport const rotFromDTO = (rotation?: number): { rot?: number } =>\n rotation ? { rot: fromPdfRotation(rotation) } : {};\n\n/**\n * Geometry/rotation fields for a BOX kind (square/circle/plain free-text). The\n * model's `rect` is the UNROTATED logical box and `rot` the applied tilt, so:\n * - rot == 0 → `/Rect` IS the box; the transform pair is stated as `null`\n * (TOTAL projection — the engine's tri-state writes preserve omissions, so\n * an omitted field would keep a stale rotation instead of flattening it).\n * - rot != 0 → `/Rect` is the rotated visual AABB (PDFium clips the baked /AP\n * to it), `unrotatedRect` the logical box, `rotation` the PDF angle.\n */\nexport function boxGeomFields(\n rect: Rect,\n rot: number,\n crop: PdfRect,\n): { rect: PdfRect; unrotatedRect: PdfRect | null; rotation: number | null } {\n if (!rot) return { rect: contentToPdfRect(rect, crop), rotation: null, unrotatedRect: null };\n return {\n rect: contentToPdfRect(rotatedAabb(rect, rot), crop),\n unrotatedRect: contentToPdfRect(rect, crop),\n rotation: toPdfRotation(rot),\n };\n}\n\n/** A box geom (square/circle/stamp) from its DTO: when rotated, the LOCAL box\n * is the stored `unrotatedRect` (the AABB `/Rect` is the rendered envelope)\n * and `rot` the converted tilt; unrotated, `/Rect` IS the box. */\nexport function boxGeomFromDTO(\n dto: { rect: PdfRect },\n rotation: number | undefined,\n unrotatedRect: PdfRect | undefined,\n crop: PdfRect,\n ellipse: boolean,\n): Geom {\n const rot = rotation ? fromPdfRotation(rotation) : 0;\n const box = rot && unrotatedRect ? unrotatedRect : dto.rect;\n return { t: 'rect', rect: pdfToContentRect(box, crop), ellipse, ...(rot ? { rot } : {}) };\n}\n\n/** Inset a PdfRect by a `/RD` (PDF user space, y-up: all four are non-negative\n * insets from the matching `/Rect` edge). Used to recover the callout text box. */\nexport const insetPdfRectByRD = (r: PdfRect, rd?: PdfRectDifferences | null): PdfRect =>\n rd\n ? {\n left: r.left + rd.left,\n bottom: r.bottom + rd.bottom,\n right: r.right - rd.right,\n top: r.top - rd.top,\n }\n : r;\n\n/** Engine border fields (`/BS /S`, `/BS /D`, `/BE /I`) → the `Border` union. A\n * cloudy effect wins over the underlying border style (which stays solid). */\nexport function borderFromDTO(d: {\n borderStyle?: string;\n dashArray?: number[];\n cloudyIntensity?: number | null;\n}): Border {\n if ((d.cloudyIntensity ?? 0) > 0) return { kind: 'cloudy', intensity: d.cloudyIntensity! };\n if (d.borderStyle === 'dashed')\n return { kind: 'dashed', dash: d.dashArray?.length ? d.dashArray : [3, 3] };\n return { kind: 'solid' };\n}\n\n/** The writable projection of a `link` value: `goto`/`uri` pass through,\n * read-only arms (`javascript`, `named`, `goto-remote`, `launch`,\n * `unsupported`) yield `null` — they can be carried, never (re)written. */\nexport function writableTarget(t: PdfLinkTarget | null | undefined): PdfLinkTargetWritable | null {\n return t && (t.kind === 'goto' || t.kind === 'uri') ? t : null;\n}\n\nexport const TEXT_MARKUP = new Set(['highlight', 'underline', 'squiggly', 'strikeout']);\n// Geometric kinds that carry the `/C` stroke colour + `/BS` border. Ink belongs\n// here too (it has a stroke but no `/IC`, so its interiorColor reads back null).\nconst STROKE_KINDS = new Set(['square', 'circle', 'line', 'polygon', 'polyline', 'ink']);\n\n/** Engine DTO → content-space `Style` (CSS colours, `Border` union). Exported so\n * selection-aware UIs can read display values straight off a {@link AnnotationDTO}\n * without re-deriving the colour/border mapping. */\nexport function styleFromDTO(dto: AnnotationDTO): Style {\n if (dto.subtype === 'widget') {\n return {\n color: dto.color ? colorToCss(dto.color) : '#1a1a1a',\n interiorColor: dto.interiorColor ? colorToCss(dto.interiorColor) : null,\n strokeWidth: dto.strokeWidth,\n opacity: 1,\n blendMode: dto.blendMode,\n border: dto.borderStyle === 'dashed' ? { kind: 'dashed', dash: [3, 3] } : { kind: 'solid' },\n };\n }\n if (STROKE_KINDS.has(dto.subtype)) {\n const d = dto as Extract<\n AnnotationDTO,\n { interiorColor: Color | null; opacity: number; strokeWidth: number }\n >;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: d.strokeWidth,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: borderFromDTO(d),\n };\n }\n if (TEXT_MARKUP.has(dto.subtype)) {\n const d = dto as Extract<AnnotationDTO, { color: Color }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 0,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'caret') {\n const d = dto as Extract<AnnotationDTO, { color: Color; opacity: number }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 1,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'free-text') {\n // `/DA` colour is the border + leader stroke; `/C` is the box background; `/BS`\n // gives the width. A plain text box draws no vector scene, so these only matter\n // for a callout's leader/arrow/box-border (and the style toolbar's readout).\n const d = dto as Extract<AnnotationDTO, { subtype: 'free-text' }>;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: d.strokeWidth,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: borderFromDTO(d),\n };\n }\n if (dto.subtype === 'redact') {\n // `/C` is the marking-stage outline; `/IC` the fill painted on apply.\n // No `/BS` on redact — the outline weight is a client rendering choice.\n const d = dto as Extract<AnnotationDTO, { subtype: 'redact' }>;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: 1.5,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'text' || dto.subtype === 'file-attachment') {\n // Icon kinds: /C is the icon fill, /CA its opacity — no stroke/fill split.\n const d = dto as Extract<AnnotationDTO, { color: Color; opacity: number }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 1,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n return {\n color: '#444444',\n interiorColor: null,\n strokeWidth: 1,\n opacity: 1,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n}\n\n/**\n * The flat props vocabulary (CSS colours, house keys) → the engine's widget\n * appearance for `doc.forms` authoring — the SAME mapping the widget patch\n * lowering uses, exported as a boundary utility so the form plugin can style\n * `placeField` from a tool's `currentDefaults` without growing a second CSS\n * parser. Absent keys stay absent (the engine writes nothing for them).\n */\nexport function widgetAppearanceFromProps(props: AnnotationPropsPatch): WidgetAppearance {\n return {\n ...(props.color !== undefined ? { color: cssToColor(props.color) } : {}),\n ...(props.interiorColor !== undefined\n ? { interiorColor: props.interiorColor ? cssToColor(props.interiorColor) : null }\n : {}),\n ...(props.strokeWidth !== undefined ? { strokeWidth: props.strokeWidth } : {}),\n ...(props.border !== undefined\n ? { borderStyle: props.border.kind === 'dashed' ? ('dashed' as const) : ('solid' as const) }\n : {}),\n ...(props.fontFamily !== undefined ? { fontFamily: props.fontFamily as StandardFont } : {}),\n ...(props.fontSize !== undefined ? { fontSize: props.fontSize } : {}),\n ...(props.fontColor !== undefined ? { fontColor: cssToColor(props.fontColor) } : {}),\n ...(props.textAlign !== undefined ? { textAlign: props.textAlign } : {}),\n };\n}\n","/**\n * GENERIC per-key prop lowerings — the 1:1 mappings from the flat props\n * vocabulary to wire fields that hold for every kind that declares the key.\n * Kind modules override ONLY their exceptions (a coupling lives in its\n * owner's file: cloudy `/RD` in shape.ts, visual-bounds `/Rect` in stroke.ts,\n * the link target in link.ts).\n */\nimport { initialTextStyle, type Annot, type PropKey } from '@embedpdf/core-annotation';\n\nimport type { Wire } from './projection';\nimport { cssToColor } from './seam';\n\n/** /BS slice of the style — a cloudy border keeps a solid underlying stroke\n * (the scallops are the /BE effect, layered on by the shape kinds). */\nexport const borderSlice = (style: Annot['style']): Wire => ({\n borderStyle: style.border.kind === 'dashed' ? ('dashed' as const) : ('solid' as const),\n ...(style.border.kind === 'dashed' ? { dashArray: style.border.dash } : {}),\n});\n\n/** The `/DA`-styled text slice falls back to the draw-time seed exactly like\n * the old projections did (a fresh draft may not carry `text` yet). */\nconst textOf = (a: Annot) => a.text ?? initialTextStyle;\n\nexport const GENERIC_PROPS: Partial<Record<PropKey, (a: Annot) => Wire>> = {\n color: (a) => ({ color: cssToColor(a.style.color) }),\n opacity: (a) => ({ opacity: a.style.opacity }),\n blendMode: (a) => ({ blendMode: a.style.blendMode }),\n interiorColor: (a) => ({\n interiorColor: a.style.interiorColor ? cssToColor(a.style.interiorColor) : null,\n }),\n strokeWidth: (a) => ({ strokeWidth: a.style.strokeWidth }),\n border: (a) => borderSlice(a.style),\n fontFamily: (a) => ({ fontFamily: textOf(a).fontFamily }),\n fontSize: (a) => ({ fontSize: textOf(a).fontSize }),\n fontColor: (a) => ({ fontColor: cssToColor(textOf(a).fontColor) }),\n textAlign: (a) => ({ textAlign: textOf(a).textAlign }),\n icon: (a) => (a.icon !== undefined ? { icon: a.icon } : {}),\n // A non-link kind's `link` prop is NOT wire data on the parent: it\n // materializes as attached child annotations through the syncLink\n // reconciler. The link KIND overrides this with its own `/A` target.\n link: () => ({}),\n};\n","import type { AnnotationDTO, PdfRect } from '@embedpdf/engine-core/runtime';\nimport { geomRotation, type Annot, type PropKey } from '@embedpdf/core-annotation';\n\nimport { boxGeomFields } from './seam';\n\n/** An untyped partial wire statement — merged fragments are cast to the\n * concrete `AnnotationDraft`/`AnnotationPatch` at the derivation boundary. */\nexport type Wire = Record<string, unknown>;\n\n/** The kind-specific slice a DTO ingest contributes on top of the generic\n * base (id/ref/flags/relationships) that `fromDTO` builds for every kind. */\nexport type IngestSlice = { geom: Annot['geom'] } & Partial<\n Pick<Annot, 'text' | 'icon' | 'label' | 'link' | 'intent'>\n>;\n\n/**\n * ONE declaration per kind family; every wire statement shape derives from it\n * (see `repository/index.ts`):\n *\n * full patch = geometry(a) ∪ props(a, every key the kind declares)\n * create draft = full patch ∪ draftExtras(a)\n * scoped patch = geometry(a) | props(a, the touched keys)\n *\n * This is the wire-side sibling of the core's PropSpec table: a new kind\n * declares one projection and gets ingest, drafts, full patches, and scoped\n * patches for free. The algebra is sound because of the engine's tri-state\n * law — omission preserves, so a statement never has to restate what it\n * didn't change.\n */\nexport interface KindProjection {\n /** DTO → the kind's model slice (geom + text/icon/label/link/intent). */\n ingest(dto: AnnotationDTO, crop: PdfRect): IngestSlice;\n /**\n * The committed-geometry wire group: the primary geometry plus every field\n * the engine writers couple to it (the box transform trio, a callout's\n * leader group, advisory rotation). `null` = the kind has no editable\n * geometry (text markup) — geometry statements fall back to the full patch.\n */\n geometry(a: Annot, crop: PdfRect): Wire | null;\n /** Kind-specific prop lowerings — ONLY the exceptions; `props.ts` GENERIC\n * covers every 1:1 key. A kind's couplings live here, in its owner's file. */\n prop?: Partial<Record<PropKey, (a: Annot, crop: PdfRect) => Wire>>;\n /** Create-only statement extras (intent, quadPoints, contents seeds…). */\n draftExtras?(a: Annot, crop: PdfRect): Wire | null;\n /** Kinds whose creates do NOT go through the repository (stamps carry a\n * binary source and use their own create path; widgets are form-plane). */\n createable?: false;\n}\n\n/** Box-kind geometry emission: the model's unrotated `rect` + applied tilt →\n * `/Rect`(+`unrotatedRect`+`rotation`), total (nulls state the clears). */\nexport const boxEmit = (a: Annot, crop: PdfRect): Wire => {\n const g = a.geom as Extract<Annot['geom'], { t: 'rect' } | { t: 'text' }>;\n return boxGeomFields(g.rect, geomRotation(a.geom), crop);\n};\n","/**\n * Square + circle. Owns the cloudy-border physics: the `/BE` intensity, the\n * derived `/RD` inset (`cloudyBorderExtent(intensity, strokeWidth)` — client\n * policy, the engine never derives it), and the tri-state clears that remove\n * both when the border returns to plain. The `/Rect` we emit is the OUTER box\n * and `/RD` insets the drawn geometry so the scallops bulge back out to it —\n * derived, never stored on the model.\n */\nimport type { AnnotationDTO, PdfRect } from '@embedpdf/engine-core/runtime';\nimport { cloudyBorderExtent, type Annot } from '@embedpdf/core-annotation';\n\nimport { boxEmit, type KindProjection, type Wire } from '../projection';\nimport { borderSlice } from '../props';\nimport { boxGeomFromDTO } from '../seam';\n\ntype ShapeDTO = Extract<AnnotationDTO, { subtype: 'square' | 'circle' }>;\n\n/** Cloudy `/BE` + `/RD` for a rect shape — TOTAL: the non-cloudy state is\n * stated as `null` (tri-state remove), never omitted, so toggling cloudy OFF\n * removes the stale inset (the Adobe phantom-padding bug). */\nexport function cloudyExtras(a: Annot): Wire {\n if (a.geom.t !== 'rect') return {};\n if (a.style.border.kind === 'cloudy') {\n const inset = cloudyBorderExtent(a.style.border.intensity, a.style.strokeWidth, a.geom.ellipse);\n return {\n cloudyIntensity: a.style.border.intensity,\n rectDifferences: { left: inset, top: inset, right: inset, bottom: inset },\n };\n }\n return { cloudyIntensity: null, rectDifferences: null };\n}\n\nconst ingest = (dto: AnnotationDTO, crop: PdfRect, ellipse: boolean) => {\n const d = dto as ShapeDTO;\n return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, ellipse) };\n};\n\nconst projection = (ellipse: boolean): KindProjection => ({\n ingest: (dto, crop) => ingest(dto, crop, ellipse),\n geometry: (a, crop) => boxEmit(a, crop),\n prop: {\n // The inset derives from intensity × stroke width, so a width change on a\n // cloudy shape re-states the /RD it owns.\n strokeWidth: (a) => ({ strokeWidth: a.style.strokeWidth, ...cloudyExtras(a) }),\n border: (a) => ({ ...borderSlice(a.style), ...cloudyExtras(a) }),\n },\n});\n\nexport const square: KindProjection = projection(false);\nexport const circle: KindProjection = projection(true);\n","/**\n * The stroke family — line, polygon, polyline, ink. Shared physics: their\n * `/Rect` is the VISUAL bounds (stroke radius included — and, for a cloudy\n * polygon, the outward curl extent), so it derives from the point geometry\n * PLUS the stroke width and border; and their `/EMBD_Metadata/Rotation` is an\n * advisory scalar (the points are already rotated; inert for AP).\n */\nimport type { AnnotationDTO, PdfRect } from '@embedpdf/engine-core/runtime';\nimport {\n geomPdfBounds,\n geomRotation,\n pdfToContentPoint,\n type Annot,\n} from '@embedpdf/core-annotation';\n\nimport type { KindProjection, Wire } from '../projection';\nimport { borderSlice } from '../props';\nimport { contentToPdfPoint, rotFromDTO, toPdfRotation } from '../seam';\n\n/** Advisory rotation, TOTAL: rotation 0 states `null` (tri-state clear) —\n * omission would preserve a stale advisory angle. */\nconst advisoryRotation = (g: Annot['geom']): { rotation: number | null } => {\n const rot = geomRotation(g);\n return { rotation: rot ? toPdfRotation(rot) : null };\n};\n\n/** `/BE` intensity for a closed poly (polygon): the curls are generated from\n * /Vertices + /BE alone — per ISO 32000 no /RD applies — and the /Rect\n * (geomPdfBounds WITH the border) already includes the outward cloud extent. */\nconst polyCloudy = (a: Annot): Wire =>\n a.geom.t === 'poly' && a.geom.closed\n ? { cloudyIntensity: a.style.border.kind === 'cloudy' ? a.style.border.intensity : null }\n : {};\n\n/** The visual-bounds `/Rect` (stroke + border included) of a stroke geom. */\nconst visualRect = (a: Annot, crop: PdfRect): Wire => {\n const g = a.geom;\n if (g.t === 'line' || g.t === 'ink') return { rect: geomPdfBounds(g, a.style.strokeWidth, crop) };\n if (g.t === 'poly') return { rect: geomPdfBounds(g, a.style.strokeWidth, crop, a.style.border) };\n return {};\n};\n\n/** Stroke-family prop exceptions: width and border feed the derived /Rect. */\nconst strokeProps: KindProjection['prop'] = {\n strokeWidth: (a, crop) => ({ strokeWidth: a.style.strokeWidth, ...visualRect(a, crop) }),\n border: (a, crop) => ({\n ...borderSlice(a.style),\n ...polyCloudy(a),\n // Only a closed poly's rect depends on the border (cloud extent).\n ...(a.geom.t === 'poly' && a.geom.closed ? visualRect(a, crop) : {}),\n }),\n lineEndings: (a) =>\n (a.geom.t === 'line' || a.geom.t === 'poly') && a.geom.ends ? { lineEndings: a.geom.ends } : {},\n};\n\nexport const line: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'line' }>;\n return {\n geom: {\n t: 'line',\n a: pdfToContentPoint(d.linePoints.start, crop),\n b: pdfToContentPoint(d.linePoints.end, crop),\n ends: d.lineEndings,\n ...rotFromDTO(d.rotation),\n },\n };\n },\n geometry: (a, crop) => {\n const g = a.geom;\n if (g.t !== 'line') return null;\n return {\n linePoints: { start: contentToPdfPoint(g.a, crop), end: contentToPdfPoint(g.b, crop) },\n ...visualRect(a, crop),\n ...advisoryRotation(g),\n };\n },\n prop: strokeProps,\n};\n\nconst polyProjection = (closed: boolean): KindProjection => ({\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'polygon' | 'polyline' }>;\n return {\n geom: {\n t: 'poly',\n points: d.vertices.map((p) => pdfToContentPoint(p, crop)),\n closed,\n ...('lineEndings' in d ? { ends: d.lineEndings } : {}),\n ...rotFromDTO(d.rotation),\n },\n };\n },\n geometry: (a, crop) => {\n const g = a.geom;\n if (g.t !== 'poly') return null;\n return {\n vertices: g.points.map((p) => contentToPdfPoint(p, crop)),\n ...visualRect(a, crop),\n ...advisoryRotation(g),\n };\n },\n prop: strokeProps,\n});\n\nexport const polygon: KindProjection = polyProjection(true);\nexport const polyline: KindProjection = polyProjection(false);\n\nexport const ink: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'ink' }>;\n return {\n geom: {\n t: 'ink',\n strokes: d.inkList.map((stroke) => stroke.map((p) => pdfToContentPoint(p, crop))),\n ...rotFromDTO(d.rotation),\n },\n ...(d.intent ? { intent: d.intent } : {}),\n };\n },\n geometry: (a, crop) => {\n const g = a.geom;\n if (g.t !== 'ink') return null;\n return {\n inkList: g.strokes.map((stroke) => stroke.map((p) => contentToPdfPoint(p, crop))),\n ...visualRect(a, crop),\n ...advisoryRotation(g),\n };\n },\n prop: strokeProps,\n // `/IT` is set at create and never patched (the engine preserves it).\n draftExtras: (a) => (a.intent === 'ink-highlight' ? { intent: a.intent } : {}),\n};\n","/**\n * Free text (plain box + callout). Owns the callout leader group — the one\n * geometry where `/RD` means \"text box inset\" rather than a border effect —\n * and the `/DA` text-slice ingest. Font/size/colour lowerings are the GENERIC\n * 1:1 keys (safe as singles since the engine's `/DA` read-modify-write).\n */\nimport type {\n AnnotationDTO,\n CalloutLine,\n LineEnding,\n PdfRect,\n PdfRectDifferences,\n} from '@embedpdf/engine-core/runtime';\nimport {\n calloutLinePoints,\n geomPdfBounds,\n geomRotation,\n rotatedAabb,\n type Annot,\n type TextStyle,\n} from '@embedpdf/core-annotation';\n\nimport { boxEmit, type KindProjection } from '../projection';\nimport {\n colorToCss,\n contentToPdfPoint,\n contentToPdfRect,\n fromPdfRotation,\n insetPdfRectByRD,\n pdfToContentPoint,\n pdfToContentRect,\n toPdfRotation,\n} from '../seam';\n\ntype FreeTextDTO = Extract<AnnotationDTO, { subtype: 'free-text' }>;\n\n/** Free-text `/DA` fields → content {@link TextStyle}. An absent `fontColor`\n * falls back to the `/DA` colour — the same rule the CPVT renderer applies. */\nfunction textFromDTO(dto: FreeTextDTO): TextStyle {\n return {\n fontFamily: dto.fontFamily,\n fontSize: dto.fontSize,\n fontColor: colorToCss(dto.fontColor ?? dto.color),\n textAlign: dto.textAlign,\n };\n}\n\n/**\n * The engine geometry for a callout: the overall `/Rect` (text box ∪ leader ∪\n * arrow), the `/RD` inset that recovers the text box from it, the `/CL` leader\n * (`[tip, knee, conn]` with the connection point derived), and the `/LE`\n * ending. All in PDF user space (y-up), with every `/RD` inset clamped\n * non-negative.\n *\n * A tilted box (the upright policy) additionally emits `rotation` +\n * `unrotatedRect` (the logical text box) — the engine bakes the box + text\n * under an INLINE rotation about the box centre while the leader stays\n * page-space, so (unlike plain boxes) the /AP form `/Matrix` stays identity\n * and the raster stays placed by `/Rect`. `/RD` then insets to the ROTATED\n * box's AABB — the best axis-aligned text box a foreign viewer regenerating\n * the AP can draw (spec-conformant degradation). The transform pair is TOTAL\n * (nulls state the clears) like every box emission.\n */\nexport function calloutFields(\n a: Annot,\n crop: PdfRect,\n): {\n rect: PdfRect;\n rectDifferences: PdfRectDifferences;\n calloutLine: CalloutLine;\n lineEnding: LineEnding;\n rotation: number | null;\n unrotatedRect: PdfRect | null;\n} | null {\n const g = a.geom;\n if (g.t !== 'text' || !g.callout) return null;\n const rot = geomRotation(g);\n const overall = geomPdfBounds(g, a.style.strokeWidth, crop);\n const tb = contentToPdfRect(rot ? rotatedAabb(g.rect, rot) : g.rect, crop);\n const nn = (n: number) => Math.max(0, n);\n const pts = calloutLinePoints(g).map((p) => contentToPdfPoint(p, crop));\n const calloutLine = (\n pts.length === 3 ? [pts[0], pts[1], pts[2]] : [pts[0], pts[1]]\n ) as CalloutLine;\n return {\n rect: overall,\n rectDifferences: {\n left: nn(tb.left - overall.left),\n bottom: nn(tb.bottom - overall.bottom),\n right: nn(overall.right - tb.right),\n top: nn(overall.top - tb.top),\n },\n calloutLine,\n lineEnding: g.callout.ending,\n ...(rot\n ? { rotation: toPdfRotation(rot), unrotatedRect: contentToPdfRect(g.rect, crop) }\n : { rotation: null, unrotatedRect: null }),\n };\n}\n\nexport const freeText: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as FreeTextDTO;\n // A callout (`/IT free-text-callout` + a `/CL` leader): the stored `rect`\n // is the TEXT BOX (the overall `/Rect` inset by `/RD`); the leader's tip\n // is `cl[0]` and the elbow `cl[1]` (a 3-point `/CL`). The connection point\n // — `cl` last — is NOT stored; it's re-derived from the box. A tilted box\n // (the upright policy) reads back from `unrotatedRect` + `rotation`\n // instead — `/RD` only recovers its axis-aligned AABB; foreign PDFs\n // (no EMBD metadata) keep the `/RD` path bit-identically.\n if (d.intent === 'free-text-callout' && d.calloutLine && d.calloutLine.length >= 2) {\n const cl = d.calloutLine;\n const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;\n const box =\n rot && d.unrotatedRect\n ? pdfToContentRect(d.unrotatedRect, crop)\n : pdfToContentRect(insetPdfRectByRD(d.rect, d.rectDifferences), crop);\n return {\n geom: {\n t: 'text',\n rect: box,\n callout: {\n tip: pdfToContentPoint(cl[0], crop),\n knee: cl.length === 3 ? pdfToContentPoint(cl[1], crop) : undefined,\n ending: d.lineEnding ?? 'none',\n },\n ...(rot && d.unrotatedRect ? { rot } : {}),\n },\n text: textFromDTO(d),\n };\n }\n // Plain text box: a box kind — read back the unrotated box + advisory tilt.\n const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;\n const box = rot && d.unrotatedRect ? d.unrotatedRect : d.rect;\n return {\n geom: { t: 'text', rect: pdfToContentRect(box, crop), ...(rot ? { rot } : {}) },\n text: textFromDTO(d),\n };\n },\n geometry: (a, crop) => {\n if (a.geom.t !== 'text') return null;\n const cf = calloutFields(a, crop);\n if (cf) return { ...cf };\n return boxEmit(a, crop);\n },\n // `/IT` + the initial `/Contents` are create-only statements; while typing,\n // the debounced text-edit write owns `contents`.\n draftExtras: (a, crop) => ({\n intent: calloutFields(a, crop) ? 'free-text-callout' : 'free-text',\n contents: a.data?.contents ?? '',\n }),\n};\n","/**\n * The quad-bound kinds: text markup (highlight/underline/squiggly/strikeout),\n * caret, and redact. Their `/QuadPoints` are text-anchored — set at create and\n * never patched — so markup and text-redact have NO editable geometry (the\n * full projection is their geometry fallback), while an AREA redact and a\n * caret are box-like and move by `/Rect`.\n */\nimport type { AnnotationDTO, PdfRect } from '@embedpdf/engine-core/runtime';\nimport { normalizeQuad } from '@embedpdf/core-geometry';\nimport { type Annot, type TextQuad } from '@embedpdf/core-annotation';\n\nimport type { KindProjection } from '../projection';\nimport {\n boxGeomFields,\n colorToCss,\n contentToPdfPoint,\n contentToPdfRect,\n fromPdfRotation,\n pdfToContentPoint,\n pdfToContentRect,\n} from '../seam';\n\ntype PdfPt = { x: number; y: number };\ntype QuadDTO = { p1: PdfPt; p2: PdfPt; p3: PdfPt; p4: PdfPt };\n\n/**\n * Imported `/QuadPoints` → semantic TextQuads. `normalizeQuad` is a\n * NORMALIZER, not a cast: the de-facto zigzag order passes through, ring-order\n * producers are repaired, and garbage gets a deterministic labeling — so\n * drawing code can never put an underline on the wrong edge of a well-formed\n * quad, rotated ones included.\n */\nconst quadsFromDTO = (quadPoints: QuadDTO[], crop: PdfRect): TextQuad[] =>\n quadPoints.map((q) =>\n normalizeQuad({\n p1: pdfToContentPoint(q.p1, crop),\n p2: pdfToContentPoint(q.p2, crop),\n p3: pdfToContentPoint(q.p3, crop),\n p4: pdfToContentPoint(q.p4, crop),\n }),\n );\n\n/** Content quads → engine `/QuadPoints` (PDF user space, zigzag slot order:\n * p1..p4 = upper-start, upper-end, lower-start, lower-end — under the y-flip\n * exactly PDFium's documented TL, TR, BL, BR); null off quads geom. */\nexport function quadPointsFor(a: Annot, crop: PdfRect): QuadDTO[] | null {\n if (a.geom.t !== 'quads') return null;\n return a.geom.quads.map((q) => ({\n p1: contentToPdfPoint(q.upperStart, crop),\n p2: contentToPdfPoint(q.upperEnd, crop),\n p3: contentToPdfPoint(q.lowerStart, crop),\n p4: contentToPdfPoint(q.lowerEnd, crop),\n }));\n}\n\n/** PDF-space bounding box of a set of `/QuadPoints` quads — the `/Rect` a\n * quad-bearing draft must carry alongside its quads. */\nexport const pdfBoundsOfQuads = (quads: QuadDTO[]): PdfRect => {\n let left = Infinity;\n let bottom = Infinity;\n let right = -Infinity;\n let top = -Infinity;\n for (const q of quads) {\n for (const p of [q.p1, q.p2, q.p3, q.p4]) {\n if (p.x < left) left = p.x;\n if (p.x > right) right = p.x;\n if (p.y < bottom) bottom = p.y;\n if (p.y > top) top = p.y;\n }\n }\n return { left, bottom, right, top };\n};\n\nconst markupProjection = (subtype: 'highlight' | 'underline' | 'squiggly' | 'strikeout') => {\n const p: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: typeof subtype }>;\n return {\n geom: { t: 'quads', quads: quadsFromDTO(d.quadPoints, crop) },\n ...(subtype === 'strikeout' && 'intent' in d && d.intent ? { intent: d.intent } : {}),\n };\n },\n // /QuadPoints geometry isn't edited after create.\n geometry: () => null,\n draftExtras: (a, crop) => {\n const quads = quadPointsFor(a, crop);\n if (!quads) return null;\n return {\n quadPoints: quads,\n ...(subtype === 'strikeout' && a.intent === 'strikeout-text-edit'\n ? { intent: a.intent }\n : {}),\n };\n },\n };\n return p;\n};\n\nexport const highlight = markupProjection('highlight');\nexport const underline = markupProjection('underline');\nexport const squiggly = markupProjection('squiggly');\nexport const strikeout = markupProjection('strikeout');\n\nexport const caret: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'caret' }>;\n // Box-family rotation pair: when present, the model's `rect` is the\n // logical (unrotated) box and `rot` the tilt — the free-text/shape rule.\n const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;\n const box = rot && d.unrotatedRect ? d.unrotatedRect : d.rect;\n return {\n geom: { t: 'caret', rect: pdfToContentRect(box, crop), ...(rot ? { rot } : {}) },\n ...(d.intent ? { intent: d.intent } : {}),\n };\n },\n geometry: (a, crop) =>\n a.geom.t === 'caret' ? boxGeomFields(a.geom.rect, a.geom.rot ?? 0, crop) : null,\n // The fixed drawn-symbol inset + the replace-text intent + seeded contents\n // are create-only statements.\n draftExtras: (a) => ({\n rectDifferences: { left: 0.5, top: 0.5, right: 0.5, bottom: 0.5 },\n ...(a.intent === 'replace' ? { intent: a.intent } : {}),\n ...(a.data?.contents != null ? { contents: a.data.contents } : {}),\n }),\n};\n\nexport const redact: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'redact' }>;\n // Text redaction carries per-line quads; an AREA redaction is rect-only\n // (`/Rect` IS the removal region per ISO 32000-2), so its geometry is a\n // box and it moves/resizes like a shape.\n const geom: Annot['geom'] =\n d.quadPoints.length > 0\n ? { t: 'quads', quads: quadsFromDTO(d.quadPoints, crop) }\n : { t: 'rect', rect: pdfToContentRect(d.rect, crop), ellipse: false };\n return {\n geom,\n // The label is `/DA`-styled exactly like free text; `fontSize` 0 means\n // auto-fit and round-trips verbatim (the engine's convention).\n text: {\n fontFamily: d.fontFamily,\n fontSize: d.fontSize,\n fontColor: colorToCss(d.fontColor),\n textAlign: d.textAlign,\n },\n ...(d.overlayText ? { label: { text: d.overlayText, repeat: d.repeat } } : {}),\n };\n },\n // Only an AREA mark's box moves/resizes; text-mark quads are create-only.\n geometry: (a, crop) =>\n a.geom.t === 'rect' ? { rect: contentToPdfRect(a.geom.rect, crop) } : null,\n draftExtras: (a, crop) => {\n const quads = quadPointsFor(a, crop);\n // Text redaction: quads + their PDF bounding box as `/Rect` (the engine\n // requires an explicit rect). Area redaction: the geometry group has it.\n return quads ? { quadPoints: quads, rect: pdfBoundsOfQuads(quads) } : {};\n },\n};\n","/**\n * The remaining small families: icon kinds (text note / file attachment),\n * stamps, links, widgets, and the unsupported fallback. Icon kinds and links\n * are `/Rect`-movable with tiny prop surfaces; stamps and widgets emit\n * patches here but are NOT createable through the repository (stamps carry a\n * binary source through their own create path; widgets are form-plane).\n */\nimport type { AnnotationDTO, PdfRect } from '@embedpdf/engine-core/runtime';\nimport type { Annot, TextStyle } from '@embedpdf/core-annotation';\n\nimport { boxEmit, type KindProjection } from '../projection';\nimport {\n boxGeomFromDTO,\n colorToCss,\n contentToPdfRect,\n pdfToContentRect,\n writableTarget,\n} from '../seam';\n\nconst rectGeometry = (a: Annot, crop: PdfRect) =>\n 'rect' in a.geom ? { rect: contentToPdfRect(a.geom.rect, crop) } : null;\n\nconst iconProjection = (subtype: 'text' | 'file-attachment'): KindProjection => ({\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: typeof subtype }>;\n return {\n geom: { t: 'rect', rect: pdfToContentRect(d.rect, crop), ellipse: false },\n // The /Name icon is a content projection like `style` — icon kinds only.\n icon: d.icon,\n };\n },\n geometry: rectGeometry,\n // Creates go through the click-to-place path (placement.ts), which also\n // carries the attached file for file-attachment — never this repository.\n createable: false,\n});\n\nexport const textNote = iconProjection('text');\nexport const fileAttachment = iconProjection('file-attachment');\n\nexport const stamp: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'stamp' }>;\n return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, false) };\n },\n // Geometry only — the visual is the engine-baked /AP, re-fit natively when\n // /Rect changes. Content replacement carries bytes and goes through\n // `capability.update` with an inline `source`, never through this path.\n geometry: (a, crop) => boxEmit(a, crop),\n createable: false,\n};\n\nexport const link: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'link' }>;\n return {\n geom: { t: 'rect', rect: pdfToContentRect(d.rect, crop), ellipse: false },\n // The link kind's own target — attached links (grouped children of\n // another kind) fold onto their PARENT's `link` slot instead, in\n // `foldAttachedLinks`.\n link: d.target,\n };\n },\n // A geometry-only move deliberately omits `target`: a foreign read-only /A\n // (javascript/named/…) survives every drag untouched.\n geometry: rectGeometry,\n prop: {\n // Three-state target: a writable value replaces `/A`; an explicit model\n // `null` CLEARS it (the engine removes /A + /Dest); a read-only arm is\n // left untouched — the foreign action survives.\n link: (a) => {\n const target = writableTarget(a.link);\n return target ? { target } : a.link == null ? { target: null } : {};\n },\n },\n // The create-then-edit flow states its (possibly null) target explicitly.\n draftExtras: (a) => ({ target: writableTarget(a.link) }),\n};\n\n/** One PDF `widget` subtype → per-family CLIENT kinds (radios have no font). */\nconst WIDGET_KIND_BY_FAMILY: Record<string, string> = {\n text: 'widget-text',\n combobox: 'widget-choice',\n listbox: 'widget-choice',\n pushbutton: 'widget-button',\n checkbox: 'widget-toggle',\n radio: 'widget-toggle',\n};\nexport const widgetKindOf = (family: string): string =>\n WIDGET_KIND_BY_FAMILY[family] ?? 'widget-box';\nconst WIDGET_TEXT_KINDS = new Set(['widget-text', 'widget-choice', 'widget-button']);\n\nfunction widgetTextFromDTO(dto: Extract<AnnotationDTO, { subtype: 'widget' }>): TextStyle {\n return {\n fontFamily: dto.fontFamily ?? 'helvetica',\n fontSize: dto.fontSize ?? 0, // 0 = auto-size\n fontColor: dto.fontColor ? colorToCss(dto.fontColor) : '#000000',\n textAlign: dto.textAlign,\n };\n}\n\nexport const widget: KindProjection = {\n ingest: (dto, crop) => {\n const d = dto as Extract<AnnotationDTO, { subtype: 'widget' }>;\n return {\n geom: boxGeomFromDTO(d, undefined, undefined, crop, false),\n ...(WIDGET_TEXT_KINDS.has(widgetKindOf(d.fieldFamily)) ? { text: widgetTextFromDTO(d) } : {}),\n };\n },\n geometry: rectGeometry,\n createable: false,\n};\n\nexport const unsupported: KindProjection = {\n ingest: (dto, crop) => ({\n geom: { t: 'rect', rect: pdfToContentRect(dto.rect, crop), ellipse: false },\n }),\n geometry: () => null,\n createable: false,\n};\n","/**\n * Attached-link folding + desired-state derivation — RELATIONSHIP logic, not\n * projection: a `/Link` child grouped under a linkable parent becomes the\n * parent's `link` prop, and the reconciler derives the children it should\n * have from the parent's committed geometry.\n */\nimport { textQuadBounds } from '@embedpdf/core-geometry';\nimport {\n propsFor,\n selectionQuad,\n unionRect,\n type Annot,\n type Quad,\n type Rect,\n} from '@embedpdf/core-annotation';\n\nimport { refKey } from './seam';\n\n/** Does this kind's table declare the `link` prop (may it carry an attached\n * link)? Widgets/caret/redact/file-attachment deliberately don't. */\nconst takesLink = (subtype: string): boolean => propsFor(subtype).some((s) => s.key === 'link');\n\n/**\n * Fold attached link children onto their parents: a `/Link` annotation\n * grouped (`/RT /Group`) under a linkable non-link parent is not an object\n * in the client model — it becomes the parent's `link` prop value plus the\n * `linkRefs` join keys the write side needs. Folded children are REMOVED\n * from the returned list, so they never render, hit-test, or select.\n * Anything that doesn't match (orphans, links grouped under widgets or\n * other links) stays a standalone annotation — nothing is ever hidden.\n *\n * Multi-segment parents (markup) carry several children with one shared\n * target; the first child's target wins and the next write heals any\n * foreign disagreement.\n */\nexport function foldAttachedLinks(annots: Annot[]): Annot[] {\n const byId = new Map(annots.map((a) => [a.id, a]));\n const folded = new Set<string>();\n const patched = new Map<string, Annot>();\n for (const a of annots) {\n if (a.subtype !== 'link' || a.data?.subtype !== 'link') continue;\n if (a.data.replyType !== 'group' || !a.data.inReplyTo || !a.ref) continue;\n const parentId = refKey(a.data.inReplyTo);\n const parent = patched.get(parentId) ?? byId.get(parentId);\n if (!parent || parent.subtype === 'link' || !takesLink(parent.subtype)) continue;\n patched.set(parentId, {\n ...parent,\n link: parent.link ?? a.data.target,\n linkRefs: [...(parent.linkRefs ?? []), a.ref],\n });\n folded.add(a.id);\n }\n if (!folded.size) return annots;\n return annots.filter((a) => !folded.has(a.id)).map((a) => patched.get(a.id) ?? a);\n}\n\n/** Bounds of one quad (content space). */\nconst quadBounds = (q: Quad): Rect => unionRect(q);\n\n/**\n * The DESIRED hit rects (content space) of a parent's attached link\n * children — derived fresh from the parent's committed geometry, never\n * tracked: markup gets one child per quad (per-line hit areas, the v2\n * segment behaviour), every other kind one child over its visual bounds.\n * The reconciler and the navigation lens both read THIS, so the clickable\n * area and the written `/Rect`s can never disagree.\n *\n * A link's `/Rect` is axis-aligned by spec (no rotation exists for links),\n * so a ROTATED parent gets the AABB of its rotated footprint — the\n * `selectionQuad` corners (rotation + stroke included), the same envelope\n * the selection chrome outlines. Exact rotated hit regions need\n * `/QuadPoints` (tier 2).\n */\nexport function linkChildRects(a: Annot): Rect[] {\n if (a.geom.t === 'quads') return a.geom.quads.map(textQuadBounds);\n return [unionRect(selectionQuad(a.geom, a.style.strokeWidth, a.style.border))];\n}\n","/**\n * The boundary between the engine's PDF-space annotation DTOs and the core's\n * content-space `Annot` — organized KIND-MAJOR like the rest of the stack\n * (engine-core `kinds/`, the services writer registry, the core PropSpec\n * table): each family declares ONE {@link KindProjection} and every wire\n * statement shape derives from it here:\n *\n * full patch = geometry(a) ∪ props(a, every key the kind declares)\n * create draft = full patch ∪ draftExtras(a) (+ `/F` verbatim)\n * scoped patch = geometry(a) | props(a, the touched keys)\n *\n * The derivation is sound because of the engine's tri-state law (\"a patch\n * touches what it states, preserves what it omits\"): a statement never has to\n * restate what it didn't change, and the emitted key set IS the editable set\n * (`propsFor` — the same table that routes `setProps`), so anything outside\n * it can never change in the model. Any key a kind cannot lower degrades to\n * the FULL patch — verbose, never a dropped write.\n */\nimport type {\n AnnotationDraft,\n AnnotationDTO,\n AnnotationPatch,\n PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport { propsFor, type Annot, type PatchScope, type PropKey } from '@embedpdf/core-annotation';\n\nimport { boxEmit, type KindProjection, type Wire } from './projection';\nimport { GENERIC_PROPS } from './props';\nimport { circle, square } from './kinds/shape';\nimport { ink, line, polygon, polyline } from './kinds/stroke';\nimport { freeText } from './kinds/freeText';\nimport { caret, highlight, redact, squiggly, strikeout, underline } from './kinds/quads';\nimport {\n fileAttachment,\n link,\n stamp,\n textNote,\n unsupported,\n widget,\n widgetKindOf,\n} from './kinds/misc';\nimport { pdfToContentRect, refKey, styleFromDTO } from './seam';\nimport { geomRotation } from '@embedpdf/core-annotation';\n\nexport {\n boxGeomFields,\n colorToCss,\n cssToColor,\n refKey,\n styleFromDTO,\n widgetAppearanceFromProps,\n writableTarget,\n} from './seam';\nexport { foldAttachedLinks, linkChildRects } from './links';\nexport { boxEmit } from './projection';\nexport type { KindProjection } from './projection';\n\n/** Every wire subtype declares exactly one projection — a missing kind is a\n * COMPILE error, not a silent fall-through. */\nconst KINDS = {\n square,\n circle,\n line,\n polygon,\n polyline,\n ink,\n 'free-text': freeText,\n highlight,\n underline,\n squiggly,\n strikeout,\n caret,\n redact,\n text: textNote,\n 'file-attachment': fileAttachment,\n stamp,\n link,\n widget,\n unsupported,\n} satisfies Record<AnnotationDTO['subtype'], KindProjection>;\n\n/** Model subtypes are wire subtypes except the widget CLIENT kinds\n * (`widget-text`…), which all project through the widget family. */\nconst projectionOf = (subtype: string): KindProjection =>\n subtype.startsWith('widget')\n ? KINDS.widget\n : ((KINDS as Record<string, KindProjection>)[subtype] ?? KINDS.unsupported);\n\nconst wireSubtypeOf = (a: Annot): string => (a.subtype.startsWith('widget') ? 'widget' : a.subtype);\n\n/* ── DTO → content model ──────────────────────────────────────────────────── */\n\n/**\n * Engine DTO → content-space Annot. `source` decides how it renders: `'baked'`\n * shows the engine's appearance raster (a page load, or a remote edit — trust\n * the authored AP); `'vector'` renders live from geom/style (we authored or\n * changed it). `apBox` is the raster's content-space box, used while baked.\n */\nexport function fromDTO(\n dto: AnnotationDTO,\n crop: PdfRect,\n source: 'baked' | 'vector' = 'baked',\n): Annot {\n const slice = projectionOf(dto.subtype).ingest(dto, crop);\n // Rotation-stripped appearances (mirrors the engine's EXACT condition — see\n // AnnotationAppearanceReader): only when the DTO carries BOTH `rotation` and\n // `unrotatedRect` (box-family kinds) is the raster flat and placed by the\n // unrotated box, with the stripped rotation re-applied as a view transform\n // (`apRot`). Vertex kinds pre-rotate their geometry and never carry\n // `unrotatedRect` — their rasters stay placed by `/Rect`, untransformed.\n // A CALLOUT is excluded even when it carries both fields: only its text BOX\n // tilts, via an INLINE matrix mid-stream (the leader is page-space), so its\n // /AP form `/Matrix` is identity and the raster stays placed by `/Rect`.\n const isCallout = dto.subtype === 'free-text' && dto.intent === 'free-text-callout';\n const strippedRect =\n !isCallout && 'unrotatedRect' in dto && 'rotation' in dto && dto.rotation\n ? dto.unrotatedRect\n : undefined;\n return {\n id: refKey(dto.ref),\n ref: dto.ref,\n pon: dto.pageObjectNumber,\n subtype: dto.subtype === 'widget' ? widgetKindOf(dto.fieldFamily) : dto.subtype,\n // `/F` verbatim — every behavioral question (visible? selectable? frozen?)\n // is answered by the core's flag predicates, never derived here.\n flags: dto.flags,\n source,\n // Carry the canonical DTO; geom/style below are derived projections of it.\n data: dto,\n // Relationship to a parent annotation. `irt` mirrors `/IRT`; `group` is the\n // primary's key for `/RT /Group` subordinates only (a visual group acts as\n // a unit). `/RT /R` (comment replies) keep `irt` but are NOT a visual group.\n ...(dto.inReplyTo ? { irt: refKey(dto.inReplyTo) } : {}),\n ...(dto.replyType === 'group' && dto.inReplyTo ? { group: refKey(dto.inReplyTo) } : {}),\n style: styleFromDTO(dto),\n ...slice,\n apBox: pdfToContentRect(strippedRect ?? dto.rect, crop),\n ...(strippedRect ? { apRot: geomRotation(slice.geom) } : {}),\n };\n}\n\n/* ── content model → wire statements (the derivation) ─────────────────────── */\n\n/** Lower `keys` through the kind's overrides + the generic table. `null` =\n * some key has no lowering — the caller degrades to the full projection. */\nfunction emitProps(a: Annot, crop: PdfRect, keys: readonly PropKey[]): Wire | null {\n const kind = projectionOf(a.subtype);\n const out: Wire = {};\n for (const key of keys) {\n const lower = kind.prop?.[key] ?? GENERIC_PROPS[key];\n if (!lower) return null;\n Object.assign(out, lower(a, crop));\n }\n return out;\n}\n\nconst editableKeys = (subtype: string): PropKey[] => propsFor(subtype).map((s) => s.key);\n\n/** Content Annot → the FULL engine patch: the kind's geometry group plus every\n * prop it declares editable. The reference statement — scoped emission and\n * drafts both build on it. */\nexport function toPatch(a: Annot, crop: PdfRect): AnnotationPatch | null {\n const kind = projectionOf(a.subtype);\n const geo = kind.geometry(a, crop);\n const props = emitProps(a, crop, editableKeys(a.subtype)) ?? {};\n if (!geo && Object.keys(props).length === 0) return null;\n return { subtype: wireSubtypeOf(a), ...geo, ...props } as AnnotationPatch;\n}\n\n/**\n * Content Annot + a {@link PatchScope} → the SPARSE patch for exactly that\n * intent (the shell's `patch` effect emitter): the reducer says WHAT changed —\n * geometry, or the props keys verbatim — and this lowers only that. Kinds\n * without editable geometry (text markup) and unlowerable keys degrade to the\n * full patch: verbose, never a dropped write.\n */\nexport function toScopedPatch(a: Annot, scope: PatchScope, crop: PdfRect): AnnotationPatch | null {\n const kind = projectionOf(a.subtype);\n if (scope.kind === 'geometry') {\n const geo = kind.geometry(a, crop);\n return geo ? ({ subtype: wireSubtypeOf(a), ...geo } as AnnotationPatch) : toPatch(a, crop);\n }\n const props = emitProps(a, crop, scope.keys);\n if (props === null) return toPatch(a, crop);\n if (Object.keys(props).length === 0) return null;\n return { subtype: wireSubtypeOf(a), ...props } as AnnotationPatch;\n}\n\n/** Content Annot → engine create draft: the full statement plus the kind's\n * create-only extras, with the model's `/F` emitted verbatim, once, for every\n * kind (a fresh draw carries DRAWN_FLAGS plus any tool seed). `null` for the\n * kinds whose creates travel their own path (stamps, widgets, icon place). */\nexport function toCreateDraft(a: Annot, crop: PdfRect): AnnotationDraft | null {\n const kind = projectionOf(a.subtype);\n if (kind.createable === false) return null;\n const base = toPatch(a, crop);\n if (!base) return null;\n const extras = kind.draftExtras?.(a, crop);\n if (kind.draftExtras && extras === null) return null;\n return { ...base, ...extras, flags: a.flags } as AnnotationDraft;\n}\n","/**\n * The free-text presentation projection: the core's geometry-only `textBoxes`\n * joined with the DTO-derived font + CSS into render-ready {@link TextItem}s. This\n * is the text analogue of the core's `scene()` \"paint\" for shapes — it lives in\n * the plugin (not the portable core) because the font→CSS stack mapping and the\n * engine `Color`→CSS seam are web concerns, shared across every web framework.\n */\nimport { initialTextStyle, textBoxes, type Model, type ViewEnv } from '@embedpdf/core-annotation';\nimport type { TextItem } from './types';\n\n/** Map a free-text `/DA` font to a CSS font-family. A standard PDF font → a web\n * stack with the same metrics; anything else is a registered font key → mount it\n * as a `@font-face` of that family (see the framework `mountWebFont` helper). */\nconst STANDARD_FONT_CSS: Record<string, string> = {\n helvetica: 'Helvetica, Arial, sans-serif',\n 'helvetica-bold': 'Helvetica, Arial, sans-serif',\n courier: '\"Courier New\", Courier, monospace',\n 'times-roman': '\"Times New Roman\", Times, serif',\n symbol: 'serif',\n 'zapf-dingbats': 'serif',\n};\nconst cssFontFor = (font: string): string => STANDARD_FONT_CSS[font] ?? `\"${font}\", sans-serif`;\n\n/** Project the model's free-text boxes into render-ready {@link TextItem}s — the\n * core geometry (`textBoxes`) joined with the DTO-derived CSS. Pure; memoized by\n * model identity at the call site so selectors get a stable reference. */\nexport function buildTextItems(m: Model, pon: number, view?: ViewEnv): TextItem[] {\n return textBoxes(m, pon, view).map((tb) => {\n const a = m.byId[tb.id];\n // `text`/`style` are the OPTIMISTIC content projections (a props edit lands\n // here before the engine round-trips), so the editor restyles instantly.\n const t = a?.text ?? initialTextStyle;\n return {\n id: tb.id,\n ref: a?.ref ?? null,\n box: tb.box,\n contents: a?.data?.contents ?? '',\n editing: tb.editing,\n ...(tb.rot ? { rot: tb.rot } : {}),\n css: {\n fontFamily: cssFontFor(t.fontFamily),\n fontSize: t.fontSize,\n lineHeight: t.fontSize, // CPVT lays out free-text at line-height ≈ font size\n color: t.fontColor,\n align: t.textAlign,\n padding: 2,\n background: a?.style.interiorColor ?? null,\n },\n };\n });\n}\n","/**\n * The annotation TOOL registry — the one place that says which tools exist and\n * what each one authors. A tool is a named authoring PRESET, not a new kind: it\n * binds an `id` to a PDF `subtype`, a bag of per-tool `defaults`, a cursor, and\n * the interaction TAGS it turns on. Two tools can share a subtype but differ in\n * defaults (an \"arrow\" is a `line` with an arrowhead default), which is exactly\n * why defaults are keyed by the tool id (the `preset`), never by the subtype.\n *\n * The built-in {@link DEFAULT_TOOLS} reproduce v2's tool set; an embedder tweaks\n * or extends them with `annotationPlugin({ tools: [...] })`. Same-id entries MERGE\n * over the built-in (configure it); a new id ADDS a tool; `extends` inherits an\n * existing tool's subtype/cursor/tags so a preset is one line.\n */\nimport type {\n AnnotationFlags,\n AnnotationPropsPatch,\n ClickCreate,\n InkStraightenOptions,\n PropKey,\n Subtype,\n} from '@embedpdf/core-annotation';\nimport type { BinarySource, InkIntent } from '@embedpdf/engine-core/runtime';\n\n/**\n * How a stamp-family tool resolves the image bytes it places — pure DATA, so a\n * tool table stays JSON-serializable (config can come from a file, a DB, or the\n * server). Evaluated at CLICK time, so the user picks the spot first, then the\n * source:\n * - `{ kind: 'bytes' }` — fixed bytes: a company rubber-stamp.\n * - `{ kind: 'prompt' }` — ask the environment for bytes. The plugin does NOT\n * know how (a file dialog is DOM); the file-picker port (`FilePickerProvider`),\n * installed by the framework adapter, fulfils it. Resolve `null` there to cancel.\n */\nexport type StampSourceSpec = { kind: 'bytes'; source: BinarySource } | PromptSourceSpec;\n\n/**\n * The ask-the-environment resolution, shared by every click-then-pick tool\n * (a stamp's `'prompt'` source, the file-attachment tool). `accept` is the\n * file-dialog filter the picker request carries — a UX hint only, the engine\n * sniffs/validates the bytes for real. Unset = any file.\n */\nexport interface PromptSourceSpec {\n kind: 'prompt';\n accept?: string;\n}\n\n/** Declarative result of committing a text selection while a tool is active. */\nexport type SelectionAuthoring =\n | { kind: 'markup' }\n | { kind: 'text-edit'; operation: 'insert' | 'replace' };\n\n/**\n * The armed tool's IN-PAGE preview:\n * - `footprint` — the EXACT box a click would place, in the page (content\n * space, page-clamped, WYSIWYG). Meaningful only when the box is\n * determinable: an armed stamp payload, or a `clickCreate` size.\n * - `false` — no preview.\n * WHICH tool is armed is the CURSOR's job, not a ghost's: give the tool an\n * image cursor built from your toolbar icon (the hub's `setToolCursor` + the\n * web package's `svgCursor`), and the hub's claim/gap arbitration keeps it\n * honest over annotations, form fields, and page gaps.\n */\nexport type GhostPolicy = false | { mode: 'footprint' };\n\n/** Time/geometry policy for freehand ink authoring. */\nexport interface InkAuthoringOptions {\n /** Group strokes made within this interval into one `/InkList`; 0 commits immediately. */\n groupStrokesMs?: number;\n /** Optional pure straight-line recognition applied to each completed stroke. */\n straighten?: InkStraightenOptions;\n}\n\n/**\n * The creation properties each known authoring kind actually consumes. This is\n * deliberately separate from the flat internal patch vocabulary: it gives tool\n * configuration precise compile-time and runtime validation while mixed-selection\n * edits can keep using `AnnotationPropsPatch`.\n */\nexport const TOOL_DEFAULT_KEYS = {\n square: ['color', 'interiorColor', 'opacity', 'strokeWidth', 'border'],\n circle: ['color', 'interiorColor', 'opacity', 'strokeWidth', 'border'],\n line: ['color', 'interiorColor', 'opacity', 'strokeWidth', 'border', 'lineEndings'],\n polygon: ['color', 'interiorColor', 'opacity', 'strokeWidth', 'border'],\n polyline: ['color', 'interiorColor', 'opacity', 'strokeWidth', 'border', 'lineEndings'],\n ink: ['color', 'opacity', 'strokeWidth', 'blendMode'],\n 'free-text': [\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'textAlign',\n 'opacity',\n 'interiorColor',\n 'color',\n 'strokeWidth',\n 'border',\n ],\n 'free-text-callout': [\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'textAlign',\n 'opacity',\n 'interiorColor',\n 'color',\n 'strokeWidth',\n 'border',\n 'lineEndings',\n ],\n highlight: ['color', 'opacity', 'blendMode'],\n underline: ['color', 'opacity', 'blendMode'],\n strikeout: ['color', 'opacity', 'blendMode'],\n squiggly: ['color', 'opacity', 'blendMode'],\n caret: ['color', 'opacity'],\n redact: ['color', 'interiorColor', 'opacity', 'fontFamily', 'fontSize', 'fontColor', 'textAlign'],\n stamp: [],\n // A link preset may carry a FIXED target ('docs-link' style one-click links).\n link: ['link'],\n text: ['icon', 'color', 'opacity'],\n 'file-attachment': ['icon', 'color', 'opacity'],\n // Widget CLIENT kinds (the form plugin's palette tools): the same key sets\n // the kind table declares — box styling for every family, /DA text styling\n // for the text-bearing ones. The engine maps them onto /MK //BS //DA //Q.\n 'widget-text': [\n 'color',\n 'interiorColor',\n 'strokeWidth',\n 'border',\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'textAlign',\n ],\n 'widget-choice': [\n 'color',\n 'interiorColor',\n 'strokeWidth',\n 'border',\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'textAlign',\n ],\n 'widget-toggle': ['color', 'interiorColor', 'strokeWidth', 'border'],\n} as const satisfies Record<string, readonly PropKey[]>;\n\nexport type ToolAuthoringKind = keyof typeof TOOL_DEFAULT_KEYS;\ntype ToolDefaultKey<K extends ToolAuthoringKind> = (typeof TOOL_DEFAULT_KEYS)[K][number];\nexport type ToolDefaultsFor<K extends ToolAuthoringKind> = [ToolDefaultKey<K>] extends [never]\n ? never\n : Pick<AnnotationPropsPatch, ToolDefaultKey<K>>;\n\n/**\n * A tool definition — the public config vocabulary. Every field except `id` is\n * optional: the common cases are \"configure a built-in\" (`{ id, defaults }`) and\n * \"add a preset\" (`{ id, extends, defaults }`).\n */\nexport interface AnnotationToolDef<K extends ToolAuthoringKind = ToolAuthoringKind> {\n /** Stable tool id — the value passed to `activateTool` and the `defaults` key. */\n id: string;\n /** Inherit `subtype` / `propsKind` / `cursor` / `enables` / `source` /\n * `selection` / `intent` / `ink` / `meta`\n * from an existing tool id (a built-in or another entry). Own fields win. */\n extends?: string;\n /** The ROUTING KIND this tool authors — the core's client kind (the geometry\n * it draws + the props key). Usually the PDF subtype, but not always:\n * `free-text-callout` routes the callout gesture onto a free-text\n * annotation, and `widget-text`/`widget-choice`/`widget-toggle` are client\n * views of the ONE PDF `widget` subtype (a form tool's commit goes through\n * `doc.forms`, never this plugin — see the form plugin's tool table).\n * Defaults to the inherited kind, or the id when neither is given. */\n subtype?: Subtype;\n /** The kind whose editable-property specs a style panel shows for this tool.\n * Defaults to `subtype` (a callout authors `free-text` props, for example). */\n propsKind?: string;\n /** ADVANCED: the `defaults` key this tool reads/writes. Defaults to the id, and\n * that is almost always right — override it only to alias a shared defaults bag\n * (the built-in insert-caret tool points its preset at the `caret` key). */\n preset?: string;\n /** Seed defaults for newly drawn annotations — the flat AnnotationProps patch,\n * merged over any inherited defaults (line endings merge per side). */\n defaults?: ToolDefaultsFor<K>;\n /**\n * `/F` annotation flags seeded on everything this tool creates, merged over\n * the drawn default (`print` set — Acrobat parity) and any inherited seed.\n * A note tool passes `{ noZoom: true, noRotate: true }` so its icons stay\n * screen-sized and upright (the spec's rule for Text annotations).\n */\n flags?: Partial<AnnotationFlags>;\n /** The pointer cursor while this tool is active. Defaults inherited / `crosshair`. */\n cursor?: string;\n /** Interaction capability tags this tool enables (which handlers wake up). */\n enables?: string[];\n /**\n * How the click-to-place payload resolves. Stamps take the full spec\n * ({@link StampSourceSpec}: fixed bytes or prompt); file attachments are\n * prompt-only ({@link PromptSourceSpec} — the file always comes from the\n * environment). Other kinds carry no payload.\n */\n source?: K extends 'stamp'\n ? StampSourceSpec\n : K extends 'file-attachment'\n ? PromptSourceSpec\n : never;\n /** What a committed text selection authors. Omit for pointer/click tools. */\n selection?: SelectionAuthoring;\n /** PDF `/IT` authored by an intent-bearing ink preset. */\n intent?: K extends 'ink' ? InkIntent : never;\n /** Ink-only stroke grouping and straightening policy. */\n ink?: K extends 'ink' ? InkAuthoringOptions : never;\n /**\n * Place annotations UPRIGHT: counter-rotate what this tool creates against the\n * page's TOTAL display rotation (document /Rotate + any stage view rotation),\n * so it reads horizontally exactly as the author saw it — Adobe's behaviour\n * for stamps and text on rotated pages. WYSIWYG at authoring time: the\n * rotation is baked into the annotation, so a save keeps what the author saw\n * (other viewers apply only /Rotate — document that when view rotation is in\n * play). Box kinds only (stamp / free-text, where reading orientation is\n * meaningful); ignored by vertex kinds and callouts. Default: on for the\n * built-in `stamp` and `free-text` tools, off elsewhere.\n */\n upright?: boolean;\n /**\n * What a bare CLICK creates (v2's `clickBehavior`): a default-size shape\n * centred on the point / a default-length line from it / free-text's\n * type-here box — page-clamped, in PDF pt. `false` = drag-only. Defaults:\n * on for the built-in square/circle/line/free-text, off elsewhere.\n */\n clickCreate?: ClickCreate | false;\n /**\n * The armed-tool in-page preview ({@link GhostPolicy}). Defaults: inherited,\n * else off (the built-in stamp declares `footprint`).\n */\n ghost?: GhostPolicy;\n /** Opaque presentation hints (label/icon…) for a toolbar or cursor that builds\n * itself from the tool table. Never read by the plugin or the interaction hub. */\n meta?: Record<string, unknown>;\n}\n\nexport interface BuiltinToolKindMap {\n square: 'square';\n circle: 'circle';\n line: 'line';\n polygon: 'polygon';\n polyline: 'polyline';\n ink: 'ink';\n 'ink-highlight': 'ink';\n 'free-text': 'free-text';\n 'free-text-callout': 'free-text-callout';\n highlight: 'highlight';\n underline: 'underline';\n strikeout: 'strikeout';\n squiggly: 'squiggly';\n 'insert-text': 'caret';\n 'replace-text': 'strikeout';\n redact: 'redact';\n stamp: 'stamp';\n note: 'text';\n attachment: 'file-attachment';\n link: 'link';\n}\n\ntype DirectToolDef = {\n [K in ToolAuthoringKind]: Omit<AnnotationToolDef<K>, 'subtype'> & { subtype: K };\n}[ToolAuthoringKind];\ntype BuiltinToolOverride = {\n [I in keyof BuiltinToolKindMap]: Omit<\n AnnotationToolDef<BuiltinToolKindMap[I]>,\n 'id' | 'extends' | 'subtype'\n > & {\n id: I;\n extends?: never;\n subtype?: never;\n };\n}[keyof BuiltinToolKindMap];\ntype ExtendedBuiltinToolDef = {\n [I in keyof BuiltinToolKindMap]: Omit<\n AnnotationToolDef<BuiltinToolKindMap[I]>,\n 'extends' | 'subtype'\n > & {\n extends: I;\n subtype?: never;\n };\n}[keyof BuiltinToolKindMap];\n\n/** Public tool input: known overrides, known-base presets, or an explicit subtype. */\nexport type AnnotationToolInput = DirectToolDef | BuiltinToolOverride | ExtendedBuiltinToolDef;\n\n/** A fully-resolved tool — what the plugin, handlers, and registration loop read. */\nexport interface ResolvedTool {\n id: string;\n /** Routing token for the draw core + the created annotation's PDF subtype. */\n subtype: Subtype;\n /** The `defaults` key (always the tool id) — keeps same-subtype tools apart. */\n preset: string;\n /** The `propsFor` key for the style panel. */\n propsKind: string;\n cursor: string;\n enables: ReadonlySet<string>;\n defaults?: AnnotationPropsPatch;\n /** `/F` seed for created annotations (see {@link AnnotationToolDef.flags}). */\n flags?: Partial<AnnotationFlags>;\n source?: StampSourceSpec;\n selection?: SelectionAuthoring;\n intent?: InkIntent;\n ink?: InkAuthoringOptions;\n /** Counter-rotate creations against the page's display rotation (see\n * {@link AnnotationToolDef.upright}). */\n upright: boolean;\n /** What a bare click creates, or `false` for drag-only. */\n clickCreate: ClickCreate | false;\n /** The armed-tool in-page preview ({@link GhostPolicy}). */\n ghost: GhostPolicy;\n meta?: Record<string, unknown>;\n}\n\n// ── field groups shared by the built-ins (keeps the table readable) ──────────\nconst DRAW_TAGS = ['annotation-draw', 'annotation-edit'];\nconst MARKUP_TAGS = ['text-select', 'annotation-edit'];\n\n/**\n * The built-in tools — a data mirror of v2's registrations (shapes + lines + ink\n * + free text in the draw channel, text markup + caret behind text selection, and\n * the click-to-place stamp). Order is display-neutral; the toolbar owns layout.\n */\nexport const DEFAULT_TOOLS: AnnotationToolInput[] = [\n // shapes / lines / ink / free text — the `annotation-draw` gesture.\n // Draw tools carry v2's click-create defaults (a bare click places a\n // default-size annotation); armed-tool identity rides the cursor, so none\n // of them needs a ghost.\n {\n id: 'square',\n subtype: 'square',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6 },\n clickCreate: { width: 80, height: 60 },\n },\n {\n id: 'circle',\n subtype: 'circle',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6 },\n clickCreate: { width: 80, height: 60 },\n },\n {\n id: 'line',\n subtype: 'line',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6 },\n clickCreate: { length: 80 },\n },\n {\n id: 'polygon',\n subtype: 'polygon',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6 },\n },\n {\n id: 'polyline',\n subtype: 'polyline',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6 },\n },\n {\n id: 'ink',\n subtype: 'ink',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { color: '#ef4444', strokeWidth: 6, blendMode: 'normal' },\n ink: { groupStrokesMs: 800 },\n },\n {\n id: 'ink-highlight',\n extends: 'ink',\n intent: 'ink-highlight',\n defaults: { color: '#ffcd45', strokeWidth: 14, blendMode: 'multiply' },\n ink: {\n straighten: { deviationThreshold: 0.15, axisSnapDegrees: 15 },\n },\n },\n {\n id: 'free-text',\n subtype: 'free-text',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { fontColor: '#ef4444' },\n upright: true,\n // Top-left anchored: the box hangs where you'll type (the kind's reading\n // feel); shapes default to `center`. Anchoring is explicit policy data.\n clickCreate: { width: 180, height: 40, anchor: 'top-left' },\n },\n {\n // Routes on the `free-text-callout` subtype token but authors a `free-text`\n // annotation (leader + box). Its leader defaults to an open arrowhead.\n // `upright` applies to the text BOX only: on a rotated page it commits\n // counter-rotated (readable), while the leader tip/knee stay page-space\n // anchors — see the core's `calloutPointer`.\n id: 'free-text-callout',\n subtype: 'free-text-callout',\n propsKind: 'free-text',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n defaults: { strokeWidth: 6, lineEndings: { end: 'open-arrow' } },\n upright: true,\n },\n // text markup — the `text-select` gesture (inert without a selection plugin).\n // Base cursor is the plain arrow: the I-beam appears only where the action is\n // possible, via the selection handler's over-text claim (which an app can\n // reskin with the tool's icon — see the hub's ToolCursorSkin).\n {\n id: 'highlight',\n subtype: 'highlight',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ffe16a', blendMode: 'multiply' },\n selection: { kind: 'markup' },\n },\n // Redaction marking — the COMPOSED tool: over text it rides the selection\n // gesture (per-line quad marks, like a highlight); anywhere else it drag-\n // draws an area mark. One tool, both modes; the destructive apply lives in\n // plugin-redaction.\n {\n id: 'redact',\n subtype: 'redact',\n cursor: 'crosshair',\n enables: ['text-select', 'annotation-draw', 'annotation-edit'],\n defaults: {\n color: '#e44234',\n interiorColor: '#000000',\n fontColor: '#ffffff',\n opacity: 1,\n },\n selection: { kind: 'markup' },\n },\n {\n id: 'underline',\n subtype: 'underline',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ef4444' },\n selection: { kind: 'markup' },\n },\n {\n id: 'strikeout',\n subtype: 'strikeout',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ef4444' },\n selection: { kind: 'markup' },\n },\n {\n id: 'squiggly',\n subtype: 'squiggly',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ef4444' },\n selection: { kind: 'markup' },\n },\n {\n // The insert-caret tool authors a `caret` from a text selection. Its defaults\n // live under the `caret` preset — the key `createCaret` resolves.\n id: 'insert-text',\n subtype: 'caret',\n propsKind: 'caret',\n preset: 'caret',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ef4444' },\n selection: { kind: 'text-edit', operation: 'insert' },\n },\n {\n id: 'replace-text',\n subtype: 'strikeout',\n propsKind: 'strikeout',\n cursor: 'default',\n enables: MARKUP_TAGS,\n defaults: { color: '#ef4444' },\n selection: { kind: 'text-edit', operation: 'replace' },\n },\n // stamp — click-to-place; 'prompt' asks the environment through the ONE\n // file-picker port (the React adapter wires a file dialog by default; an\n // embedder can pass fixed bytes instead). `accept` narrows the dialog to\n // what the engine's stamp sniffer takes anyway.\n {\n id: 'stamp',\n subtype: 'stamp',\n cursor: 'copy',\n enables: ['annotation-place', 'annotation-edit'],\n source: { kind: 'prompt', accept: 'image/png,image/jpeg,application/pdf' },\n upright: true,\n ghost: { mode: 'footprint' },\n },\n // link — drag an invisible hit rectangle; the target is set afterwards\n // through the selection editor (create-then-edit), unless a preset carries\n // a fixed one (`{ id: 'docs-link', extends: 'link', defaults: { link: … } }`).\n // While this tool is active the navigation plane stands down (no `link-nav`),\n // so existing links become plain editable rects.\n {\n id: 'link',\n subtype: 'link',\n cursor: 'crosshair',\n enables: DRAW_TAGS,\n },\n // sticky note (\"comment\") — click-to-place, no payload: each click drops a\n // fixed 20×20 icon (engine-baked /AP from /C + /Name), screen-sized and\n // upright per the spec's Text-icon rule (the noZoom/noRotate seed).\n {\n id: 'note',\n subtype: 'text',\n cursor: 'crosshair',\n enables: ['annotation-place', 'annotation-edit'],\n defaults: { icon: 'comment', color: '#facc15' },\n flags: { noZoom: true, noRotate: true },\n upright: true,\n ghost: { mode: 'footprint' },\n },\n // file attachment — click-to-place with the spot-first-file-second rule:\n // the click opens the installed file-picker port (a file dialog by\n // default; `accept` unset = any file — attaching any format is the point);\n // the picked file embeds at the clicked point.\n {\n id: 'attachment',\n subtype: 'file-attachment',\n cursor: 'copy',\n enables: ['annotation-place', 'annotation-edit'],\n source: { kind: 'prompt' },\n defaults: { icon: 'paperclip', color: '#facc15' },\n flags: { noZoom: true, noRotate: true },\n upright: true,\n ghost: { mode: 'footprint' },\n },\n];\n\n/** Merge two default patches, `b` over `a`, with line endings merged per side. */\nfunction mergeDefaults(\n a?: AnnotationPropsPatch,\n b?: AnnotationPropsPatch,\n): AnnotationPropsPatch | undefined {\n if (!a) return b;\n if (!b) return a;\n const merged: AnnotationPropsPatch = { ...a, ...b };\n if (a.lineEndings || b.lineEndings) merged.lineEndings = { ...a.lineEndings, ...b.lineEndings };\n return merged;\n}\n\n/** Overlay a same-id override onto a base definition (configure a built-in). */\nfunction mergeDef(base: AnnotationToolDef, over: AnnotationToolDef): AnnotationToolDef {\n return {\n ...base,\n ...over,\n enables: over.enables ?? base.enables,\n meta: base.meta || over.meta ? { ...base.meta, ...over.meta } : undefined,\n defaults: mergeDefaults(base.defaults, over.defaults),\n flags: base.flags || over.flags ? { ...base.flags, ...over.flags } : undefined,\n ink: base.ink || over.ink ? { ...base.ink, ...over.ink } : undefined,\n };\n}\n\nfunction validateDefaults(tool: ResolvedTool): void {\n if (!tool.defaults) return;\n const allowed = TOOL_DEFAULT_KEYS[tool.subtype as ToolAuthoringKind];\n // Unknown/custom routing kinds remain extensible; known built-ins are strict.\n if (!allowed) return;\n const keys = new Set<string>(allowed);\n for (const key of Object.keys(tool.defaults)) {\n if (!keys.has(key)) {\n throw new Error(\n `[annotation] tool '${tool.id}' does not support default '${key}' for '${tool.subtype}'`,\n );\n }\n }\n}\n\n/**\n * Resolve {@link DEFAULT_TOOLS} + embedder overrides into the ready-to-use table.\n * A same-id override merges over the built-in; a new id adds a tool; `extends`\n * inherits from an already-defined tool. Keyed by id, so lookups are O(1).\n */\nexport function buildToolRegistry(\n overrides: AnnotationToolInput[] = [],\n): Map<string, ResolvedTool> {\n const defs = new Map<string, AnnotationToolDef>();\n for (const d of DEFAULT_TOOLS) defs.set(d.id, d);\n for (const o of overrides) {\n const prev = defs.get(o.id);\n defs.set(o.id, prev ? mergeDef(prev, o) : o);\n }\n\n const out = new Map<string, ResolvedTool>();\n const resolving = new Set<string>();\n const resolve = (id: string): ResolvedTool => {\n const cached = out.get(id);\n if (cached) return cached;\n const def = defs.get(id);\n if (!def) throw new Error(`[annotation] tool '${id}' extends an unknown tool`);\n // Inherit from the base first (guarding self / cyclic extends), then own fields win.\n let base: ResolvedTool | undefined;\n if (def.extends && def.extends !== id && !resolving.has(def.extends)) {\n resolving.add(id);\n base = resolve(def.extends);\n resolving.delete(id);\n }\n const subtype = (def.subtype ?? base?.subtype ?? def.id) as Subtype;\n const resolved: ResolvedTool = {\n id: def.id,\n subtype,\n preset: def.preset ?? def.id,\n propsKind: def.propsKind ?? base?.propsKind ?? subtype,\n cursor: def.cursor ?? base?.cursor ?? 'crosshair',\n enables: new Set(def.enables ?? (base ? [...base.enables] : [])),\n defaults: mergeDefaults(base?.defaults, def.defaults),\n flags: base?.flags || def.flags ? { ...base?.flags, ...def.flags } : undefined,\n source: def.source ?? base?.source,\n selection: def.selection ?? base?.selection,\n intent: def.intent ?? base?.intent,\n ink: base?.ink || def.ink ? { ...base?.ink, ...def.ink } : undefined,\n upright: def.upright ?? base?.upright ?? false,\n clickCreate: def.clickCreate ?? base?.clickCreate ?? false,\n ghost: def.ghost ?? base?.ghost ?? false,\n meta: base?.meta || def.meta ? { ...base?.meta, ...def.meta } : undefined,\n };\n validateDefaults(resolved);\n out.set(id, resolved);\n return resolved;\n };\n for (const id of defs.keys()) resolve(id);\n return out;\n}\n","import type {\n AnnotationDraft,\n AnnotationFlags,\n AttachmentFileSource,\n FileAttachmentIcon,\n NoteIcon,\n PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport type { AnnotationProps, Subtype } from '@embedpdf/core-annotation';\n\nimport { cssToColor } from './repository';\n\n/**\n * Per-kind CODE for the click-to-place ICON kinds (note / file attachment)\n * — the `props.ts`/`repository.ts` pattern: all tool CONFIG stays in the\n * tool table; this module only interprets it. The stamp keeps its own\n * sizing/sniffing path in the capability; everything funnels through the\n * one `placeAt` entry there.\n */\n\n/**\n * Icon kinds place at the generator's fixed box: the engine forces the\n * `/Rect` to 20×20 from its bottom-left corner (the spec's note-icon rule),\n * so the footprint ghost and the placement use exactly this size.\n */\nexport const ICON_PLACE_SIZE = { width: 20, height: 20 } as const;\n\nexport type IconPlaceKind = 'text' | 'file-attachment';\n\nexport const isIconPlaceKind = (subtype: Subtype): subtype is IconPlaceKind =>\n subtype === 'text' || subtype === 'file-attachment';\n\n/**\n * Build the engine create draft for a placed icon annotation. `geom` is the\n * repository's `boxGeomFields` emit (the `/Rect` + upright rotation pair);\n * `defaults` is the tool's resolved flat props bag (`defaultsFor`) — the\n * colour seam is crossed here via the repository's `cssToColor`, and the\n * icon falls back to the kind's own default when the bag carries none.\n */\nexport function iconPlacementDraft(\n subtype: IconPlaceKind,\n geom: { rect: PdfRect; rotation?: number | null; unrotatedRect?: PdfRect | null },\n defaults: AnnotationProps,\n flags: Partial<AnnotationFlags> | undefined,\n file: AttachmentFileSource | null,\n): AnnotationDraft {\n const shared = {\n ...geom,\n color: cssToColor(defaults.color),\n opacity: defaults.opacity,\n // A fresh placement carries print (Acrobat parity) plus the tool's seed\n // (the note/attachment tools pass noZoom + noRotate).\n flags: { print: true, ...flags },\n };\n if (subtype === 'text') {\n return { subtype: 'text', icon: (defaults.icon as NoteIcon) ?? 'comment', ...shared };\n }\n if (!file) {\n throw new Error('[annotation] a file-attachment placement requires a file payload');\n }\n return {\n subtype: 'file-attachment',\n icon: (defaults.icon as FileAttachmentIcon) ?? 'paperclip',\n file,\n ...shared,\n };\n}\n","import {\n CONTINUOUS_RENDER_POLICY,\n snapAppearanceScale,\n type DocCapability,\n type PluginContext,\n} from '@embedpdf/core';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport {\n resolveBinarySource,\n sniffBinaryMetadata,\n type AnnotationDraft,\n type AnnotationDTO,\n type AnnotationPatch,\n type AnnotationRef,\n type AttachmentFileSource,\n type BinarySource,\n} from '@embedpdf/engine-core/runtime';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport {\n chrome as coreChrome,\n clickCreateGeom,\n contentToPdfRect,\n creationDraftAnchor as coreCreationDraftAnchor,\n cursorAt,\n defaultsFor,\n expandGroups,\n FLAG_KEYS,\n fitStampBox,\n geomVisualBounds,\n groupKeyOf,\n hitTest,\n pageItems as corePageItems,\n pdfToContentRect,\n propsFor,\n readProp,\n resolveClickPlacement,\n selectionAnchor as coreSelectionAnchor,\n sharedProps,\n styleFromProps,\n update,\n uprightRotation,\n viewable,\n type Annot,\n type AnnotationProps,\n type ChromeGeom,\n type ChromeNode,\n type CreationDraftAnchor,\n type Effect,\n type Geom,\n type Id,\n type Model,\n type Msg,\n type PropKey,\n type Rect,\n type RenderItem,\n type Subtype,\n type Vec,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport {\n boxGeomFields,\n foldAttachedLinks,\n fromDTO,\n linkChildRects,\n refKey,\n toCreateDraft,\n toPatch,\n toScopedPatch,\n writableTarget,\n} from './repository';\nimport { buildTextItems } from './text-item';\nimport { buildToolRegistry } from './tools';\nimport type { AnnotationToolInput, ResolvedTool } from './tools';\nimport type {\n AnnotationAction,\n AnnotationConfig,\n AnnotationHostCapability,\n AnnotationState,\n ArmedStampPreview,\n Behavior,\n ChromeSettings,\n SelectionFlags,\n SelectionProps,\n FilePickerProvider,\n FilePromptRequest,\n LinkNavItem,\n StampToolInput,\n TextItem,\n} from './types';\nimport { ICON_PLACE_SIZE, iconPlacementDraft, isIconPlaceKind } from './placement';\n\n/** Fold `zoom`/`rotation` host args into the core's ViewEnv (or none).\n * `zoom` is the page's RELATIVE zoom (`transform.zoom`) — never the\n * px-per-point `scale` (that one only converts CSS-px chrome settings). */\nconst viewEnv = (zoom?: number, rotation?: number): ViewEnv | undefined =>\n zoom != null || rotation != null\n ? { zoom: zoom ?? 1, rotation: (rotation ?? 0) as ViewEnv['rotation'] }\n : undefined;\n\n/** Broad annotate-write capability (PDF bit 6). The engine independently\n * enforces this AND the per-owner collab rules; `canEdit`/`canDelete` are the\n * UI mirror of the coarse gate. */\nconst ANNOTATE_MODIFY: DocCapability = 'doc.annotate.modify';\n\nconst TEXT_COMMIT_DEBOUNCE_MS = 250;\n\n/**\n * The annotation shell. The pure `update` runs HERE (so it can emit effects);\n * the resulting model is dispatched to the store, and each effect is performed\n * against the engine repository — optimistic create → reconcile to the durable\n * ref, patch/delete fire-and-forget.\n */\nexport function createAnnotationCapability(\n ctx: PluginContext<AnnotationState, AnnotationAction>,\n config: AnnotationConfig = {},\n): AnnotationHostCapability {\n const loaded = new Set<number>();\n const behaviors: Behavior[] = [];\n /** Per-annotation debounce timer for the engine `contents` write while typing. */\n const textTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\n // The resolved tool table (built-ins + config overrides). A tool is a named\n // authoring preset: it maps its id → a routing subtype, a `defaults` key\n // (`preset`), a `propsFor` kind, and — for stamps — a source spec. `configTools`\n // is kept so `registerTool` can re-resolve `extends` against the same base pool.\n const configTools = config.tools ?? [];\n const registry = buildToolRegistry(configTools);\n /** The installed file-picker port (a DOM file dialog, wired by the framework\n * adapter), or null — every click-then-pick tool resolves through this ONE\n * slot. See {@link FilePickerProvider}. */\n let filePickerProvider: FilePickerProvider | null = null;\n\n const model = (): Model => ctx.getState().model;\n const chromeSettings = (): ChromeSettings => ctx.getState().chrome;\n\n /**\n * Ids on a page whose Behavior is currently ENGAGED (form widgets under a\n * fill tool): they render their own DOM, so hit-test/marquee must not see\n * them. Resolved per event — engagement follows the active tool live.\n */\n const inertIdsAt = (pon: number): ReadonlySet<Id> | undefined => {\n if (!behaviors.length) return undefined;\n const m = model();\n let out: Set<Id> | undefined;\n for (const id of m.order) {\n const a = m.byId[id];\n if (!a || a.pon !== pon) continue;\n if (behaviors.some((b) => b.matches({ subtype: a.subtype, ref: a.ref }) && b.engaged())) {\n (out ??= new Set()).add(id);\n }\n }\n return out;\n };\n\n /** The CSS-px chrome settings converted to CONTENT units by the page's view\n * scale (px per content unit) — screen-constant grab zones + stalk at every\n * zoom. No scale → the values are read as content units (headless callers). */\n const chromeGeomAt = (scale?: number): ChromeGeom => {\n const cs = chromeSettings();\n const s = scale || 1;\n return {\n handleTol: cs.handles.hitSize / 2 / s,\n knobTol: cs.knob.hitSize / 2 / s,\n knobOffset: cs.knob.offset / s,\n };\n };\n\n // Memoize the derived per-page arrays by input identity, so a selector returns\n // a STABLE reference between dispatches (useSyncExternalStore needs this — the\n // model object only changes when `update` produces a new one; chrome also keys\n // on the settings object + the page scale it was projected with).\n const itemsCache = new Map<\n number,\n {\n model: Model;\n ghost: AnnotationState['toolGhost'];\n zoom: number | undefined;\n rotation: number | undefined;\n v: RenderItem[];\n }\n >();\n const chromeCache = new Map<\n number,\n {\n model: Model;\n cs: ChromeSettings;\n scale: number | undefined;\n rotation: number | undefined;\n zoom: number | undefined;\n v: ChromeNode[];\n }\n >();\n const memoItems = (pon: number, view?: ViewEnv): RenderItem[] => {\n const m = model();\n const g = ctx.getState().toolGhost;\n const c = itemsCache.get(pon);\n if (\n c &&\n c.model === m &&\n c.ghost === g &&\n c.zoom === view?.zoom &&\n c.rotation === view?.rotation\n )\n return c.v;\n const v = corePageItems(m, pon, view);\n // The armed tool's VECTOR footprint ghost rides the same items pipeline as\n // every draft preview (image ghosts blit through the framework instead).\n if (g && g.pon === pon && g.kind === 'vector') {\n const tool = registry.get(g.toolId);\n const style = styleFromProps(defaultsFor(m, tool?.preset ?? g.toolId));\n v.push({\n id: 'tool-ghost',\n ref: null,\n subtype: tool?.subtype ?? 'square',\n geom: g.geom,\n box: g.box,\n style,\n source: 'ghost',\n selected: false,\n });\n }\n itemsCache.set(pon, { model: m, ghost: g, zoom: view?.zoom, rotation: view?.rotation, v });\n return v;\n };\n const memoChrome = (\n pon: number,\n scale?: number,\n rotation?: number,\n zoom?: number,\n ): ChromeNode[] => {\n const m = model();\n const cs = chromeSettings();\n const c = chromeCache.get(pon);\n if (\n c &&\n c.model === m &&\n c.cs === cs &&\n c.scale === scale &&\n c.rotation === rotation &&\n c.zoom === zoom\n )\n return c.v;\n let v = coreChrome(\n m,\n pon,\n pageBoxOf(pon),\n chromeGeomAt(scale).knobOffset,\n viewEnv(zoom, rotation),\n );\n // `guides.enabled` is presentation config, filtered HERE so the emitted\n // chrome stays authoritative for every painter (default and headless alike).\n if (!cs.guides.enabled) v = v.filter((n) => n.kind !== 'rotate-guides');\n chromeCache.set(pon, { model: m, cs, scale, rotation, zoom, v });\n return v;\n };\n // Anchor for the selection menu — memoized by input identity so the selector\n // returns a stable reference between unrelated dispatches.\n let anchorCache: {\n model: Model;\n cs: ChromeSettings;\n scale: number | undefined;\n rotation: number | undefined;\n zoom: number | undefined;\n v: { pon: number; bounds: Rect; knob?: Vec } | null;\n } | null = null;\n const memoAnchor = (\n scale?: number,\n rotation?: number,\n zoom?: number,\n ): { pon: number; bounds: Rect; knob?: Vec } | null => {\n const m = model();\n const cs = chromeSettings();\n if (\n anchorCache &&\n anchorCache.model === m &&\n anchorCache.cs === cs &&\n anchorCache.scale === scale &&\n anchorCache.rotation === rotation &&\n anchorCache.zoom === zoom\n )\n return anchorCache.v;\n const v = coreSelectionAnchor(\n m,\n pageBoxOf,\n () => chromeGeomAt(scale).knobOffset,\n () => viewEnv(zoom, rotation),\n );\n anchorCache = { model: m, cs, scale, rotation, zoom, v };\n return v;\n };\n let draftAnchorCache: { model: Model; v: CreationDraftAnchor | null } | null = null;\n const memoDraftAnchor = (): CreationDraftAnchor | null => {\n const m = model();\n if (draftAnchorCache && draftAnchorCache.model === m) return draftAnchorCache.v;\n const v = coreCreationDraftAnchor(m);\n draftAnchorCache = { model: m, v };\n return v;\n };\n // The selection's property schema + values — memoized by model identity so a\n // subscribed sidebar re-renders only when the model actually changed.\n let selPropsCache: { model: Model; v: SelectionProps } | null = null;\n const memoSelectionProps = (): SelectionProps => {\n const m = model();\n if (selPropsCache && selPropsCache.model === m) return selPropsCache.v;\n const members = m.selected.map((id) => m.byId[id]).filter((a): a is Annot => !!a);\n const specs = sharedProps(members.map((a) => a.subtype));\n const values: Partial<AnnotationProps> = {};\n const mixed: PropKey[] = [];\n for (const spec of specs) {\n const first = readProp(members[0], spec.key);\n (values as Record<PropKey, unknown>)[spec.key] = first;\n const firstJson = JSON.stringify(first);\n if (members.some((a) => JSON.stringify(readProp(a, spec.key)) !== firstJson))\n mixed.push(spec.key);\n }\n const v: SelectionProps = { specs, values, mixed };\n selPropsCache = { model: m, v };\n return v;\n };\n // The navigation plane's feed: clickable link areas per page — standalone\n // links + attached-link segments (rects derived by the reconciler's own\n // rule). Memoized by model identity for selector use.\n const linkItemsCache = new Map<number, { model: Model; v: LinkNavItem[] }>();\n const memoLinkItems = (pon: number): LinkNavItem[] => {\n const m = model();\n const c = linkItemsCache.get(pon);\n if (c && c.model === m) return c.v;\n const v: LinkNavItem[] = [];\n for (const id of m.order) {\n const a = m.byId[id];\n if (!a || a.pon !== pon || a.link == null) continue;\n if (!viewable(a.flags, false)) continue; // hidden links don't navigate\n if (a.subtype === 'link') {\n if (a.geom.t === 'rect') v.push({ id, rect: a.geom.rect, target: a.link });\n } else {\n linkChildRects(a).forEach((rect, i) => v.push({ id: `${id}#${i}`, rect, target: a.link! }));\n }\n }\n linkItemsCache.set(pon, { model: m, v });\n return v;\n };\n\n const textsCache = new Map<\n number,\n { model: Model; zoom: number | undefined; rotation: number | undefined; v: TextItem[] }\n >();\n const memoTexts = (pon: number, view?: ViewEnv): TextItem[] => {\n const m = model();\n const c = textsCache.get(pon);\n if (c && c.model === m && c.zoom === view?.zoom && c.rotation === view?.rotation) return c.v;\n const v = buildTextItems(m, pon, view);\n textsCache.set(pon, { model: m, zoom: view?.zoom, rotation: view?.rotation, v });\n return v;\n };\n // The selection's `/F` state — per-flag value, `null` where members disagree.\n let selFlagsCache: { model: Model; v: SelectionFlags | null } | null = null;\n const memoSelectionFlags = (): SelectionFlags | null => {\n const m = model();\n if (selFlagsCache && selFlagsCache.model === m) return selFlagsCache.v;\n const members = m.selected.map((id) => m.byId[id]).filter((a): a is Annot => !!a);\n let v: SelectionFlags | null = null;\n if (members.length) {\n v = {} as SelectionFlags;\n for (const key of FLAG_KEYS) {\n const first = members[0].flags[key];\n v[key] = members.every((a) => a.flags[key] === first) ? first : null;\n }\n }\n selFlagsCache = { model: m, v };\n return v;\n };\n const cropOf = (pon: number) =>\n ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.boxes.crop ?? null;\n /** The page's box in content space (origin at the crop top-left) — the box\n * pointer gestures clamp to, so annotations stay page-bound. */\n const pageBoxOf = (pon: number): Rect | undefined => {\n const crop = cropOf(pon);\n return crop\n ? { x: 0, y: 0, width: crop.right - crop.left, height: crop.top - crop.bottom }\n : undefined;\n };\n\n /**\n * The armed stamp-tool payload: the bytes the next click places, plus the\n * PDF-point placement size (derived from the sniffed intrinsic aspect).\n * Transient tool state — deliberately NOT in the model: it is never\n * rendered, never synced, and dies with the tool.\n */\n // The DESIRED placement size (PDF points, pre page-clamp): the image's own\n // intrinsic size unless the caller overrides it. Clamping to the page happens\n // at placement, since it depends on which page (and rotation) receives it.\n // `preview` is the browser-paintable render for the hover ghost — transient\n // tool state like the bytes themselves, so it lives here, not in the store.\n let armedStamp: {\n source: BinarySource;\n width: number;\n height: number;\n preview: ArmedStampPreview | null;\n } | null = null;\n\n /**\n * The desired stamp size (PDF points) from sniffed bytes: the image's\n * INTRINSIC pixel dimensions taken 1:1 as points (the v2 rule — keep the\n * artwork's own size, then clamp to the page at placement). A `targetWidth`\n * override scales to that width, aspect preserved. Vector (PDF) stamps carry\n * no sniffable dimensions — a caller-supplied `intrinsic` override (a stamp\n * library knows its page size) keeps the true aspect; without one they fall\n * back to a square target.\n */\n const desiredStampSize = (\n meta: NonNullable<ReturnType<typeof sniffBinaryMetadata>>,\n targetWidth?: number,\n intrinsicOverride?: { width: number; height: number },\n ): { width: number; height: number } => {\n const intrinsic =\n intrinsicOverride && intrinsicOverride.width > 0 && intrinsicOverride.height > 0\n ? intrinsicOverride\n : 'width' in meta && meta.width > 0\n ? { width: meta.width, height: meta.height }\n : { width: targetWidth ?? 150, height: targetWidth ?? 150 };\n if (targetWidth === undefined) return intrinsic;\n return { width: targetWidth, height: targetWidth * (intrinsic.height / intrinsic.width) };\n };\n\n const armStamp = async (input: StampToolInput): Promise<void> => {\n // Resolve + sniff up front: a bad payload fails HERE (at the button),\n // not at the click. The original `source` is kept for the create call —\n // normalization inside the engine handles it again from scratch.\n const resolved = await resolveBinarySource(input.source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new Error('[annotation] stamp source must be PNG, JPEG, or single-page PDF bytes');\n }\n // Ghost preview: an explicit `preview` wins (the only way for PDF sources —\n // browsers can't paint those); raster sources default to their own bytes.\n let preview: ArmedStampPreview | null = null;\n if (input.preview) {\n const p = await resolveBinarySource(input.preview);\n preview = { bytes: new Uint8Array(p.bytes), mimeType: p.mimeType };\n } else if (meta.mimeType !== 'application/pdf') {\n preview = { bytes: new Uint8Array(resolved.bytes), mimeType: meta.mimeType };\n }\n armedStamp = {\n source: input.source,\n ...desiredStampSize(meta, input.targetWidth, input.intrinsicSize),\n preview,\n };\n ctx.dispatch({ type: 'STAMP_ARM_CHANGED' });\n ctx.tryGet(InteractionToken)?.activateTool('stamp');\n };\n\n const disarmStamp = (): void => {\n if (!armedStamp) return;\n armedStamp = null;\n ctx.dispatch({ type: 'STAMP_ARM_CHANGED' });\n };\n\n /** Move the hover FOOTPRINT ghost to a content point. The box/geometry is\n * computed by the SAME rules the click's placement uses ({@link createStampAt}\n * fit + clamp for an armed stamp; the click-create anchor + page clamp for a\n * draw tool), so the ghost is the placement, not an approximation of it. */\n const ghostHoverAt = (\n toolId: string,\n pon: number,\n point: Vec,\n displayRotation?: number,\n ): void => {\n const tool = registry.get(toolId);\n const crop = cropOf(pon);\n if (!tool || tool.ghost === false || !crop) {\n clearGhost();\n return;\n }\n const page = { width: crop.right - crop.left, height: crop.top - crop.bottom };\n // The armed stamp: the fitted image box (the framework blits the preview).\n if (armedStamp) {\n const rot = uprightRotFor(displayRotation);\n const box = fitStampBox(\n point,\n { width: armedStamp.width, height: armedStamp.height },\n page,\n rot,\n );\n ctx.dispatch({ type: 'SET_TOOL_GHOST', ghost: { pon, box, rot, kind: 'image' } });\n return;\n }\n // Icon kinds: the fixed 20×20 footprint under the cursor — the SAME box\n // the click's placement uses (fit + clamp), painted as a vector ghost.\n if (isIconPlaceKind(tool.subtype)) {\n const rot = uprightRotFor(displayRotation);\n const box = fitStampBox(point, ICON_PLACE_SIZE, page, rot);\n dispatchVectorGhost(pon, toolId, { t: 'rect', rect: box, ellipse: false });\n return;\n }\n // A click-create tool: the SHARED placement layer resolves where the click\n // would land (same call the core's commit makes — preview ≡ commit by\n // construction), and the annotation-only conversion paints it as a vector\n // ghost through pageItems. No kind knowledge lives in this shell.\n if (!tool.clickCreate) {\n clearGhost();\n return;\n }\n const placement = resolveClickPlacement(point, tool.clickCreate, {\n pageBox: { x: 0, y: 0, width: page.width, height: page.height },\n upright: tool.upright,\n displayRotation: displayRotation as PageRotation | undefined,\n });\n const geom = clickCreateGeom(tool.subtype, placement, defaultsFor(model(), tool.preset));\n if (!geom) {\n clearGhost();\n return;\n }\n dispatchVectorGhost(pon, toolId, geom);\n };\n\n /** Paint a vector ghost item for a tool's would-be geometry — shared by the\n * hover footprint and the externally-driven placement preview. */\n const dispatchVectorGhost = (pon: number, toolId: string, geom: Geom): void => {\n const tool = registry.get(toolId);\n const style = styleFromProps(defaultsFor(model(), tool?.preset ?? toolId));\n ctx.dispatch({\n type: 'SET_TOOL_GHOST',\n ghost: {\n pon,\n box: geomVisualBounds(geom, style.strokeWidth, style.border),\n rot: 0,\n kind: 'vector',\n toolId,\n geom,\n },\n });\n };\n\n /**\n * Drive the placement preview during an EXTERNALLY-owned creation gesture\n * (the form plugin's drag-to-place): paint the box the commit would use,\n * styled from the TOOL's defaults, through the same ghost pipeline as every\n * footprint. The box is clamped to the page (a drag may overshoot).\n */\n const setPlacementPreview = (toolId: string, pon: number, box: Rect): void => {\n const crop = cropOf(pon);\n if (!crop) return;\n const page = { width: crop.right - crop.left, height: crop.top - crop.bottom };\n const x = Math.max(0, Math.min(box.x, page.width));\n const y = Math.max(0, Math.min(box.y, page.height));\n const rect: Rect = {\n x,\n y,\n width: Math.max(0, Math.min(box.x + box.width, page.width) - x),\n height: Math.max(0, Math.min(box.y + box.height, page.height) - y),\n };\n dispatchVectorGhost(pon, toolId, { t: 'rect', rect, ellipse: false });\n };\n\n const clearGhost = (): void => {\n if (ctx.getState().toolGhost) ctx.dispatch({ type: 'SET_TOOL_GHOST', ghost: null });\n };\n\n /** Place a stamp of `desired` PDF-point size centred on a content point — the\n * one engine-write both the armed and click-to-place paths funnel through.\n * The size is fit to the page and clamped fully onto it (v2 rubber-stamp\n * rule: never larger than the page, aspect preserved), and never spills off\n * the edge. `rotCW` (the tool's upright counter-rotation, CW content degrees)\n * emits the repository's box rotation fields — the engine bakes the tilted\n * /AP exactly as an interactively rotated stamp round-trips, and the fit uses\n * the ROTATED footprint. Returns false when the page/document isn't ready. */\n const createStampAt = (\n pon: number,\n point: Vec,\n source: BinarySource,\n desired: { width: number; height: number },\n rotCW = 0,\n ): boolean => {\n const doc = ctx.doc;\n const crop = cropOf(pon);\n if (!doc || !crop) return false;\n const page = { width: crop.right - crop.left, height: crop.top - crop.bottom };\n const box: Rect = fitStampBox(point, desired, page, rotCW);\n doc\n .page(pon)\n .annotations.create({\n subtype: 'stamp',\n ...boxGeomFields(box, rotCW, crop),\n source,\n fit: 'contain',\n })\n .then(\n // A stamp has no vector render — the engine-baked /AP IS the visual.\n // Every placement selects its result (the anchor for menus/editing).\n (res) => {\n syncDTO(res.created, 'baked');\n apply({ t: 'select', ids: [refKey(res.created.ref)] });\n },\n (err) => console.error('[annotation] stamp placement failed:', err),\n );\n return true;\n };\n\n /** The active tool's upright counter-rotation for a click at `displayRotation`\n * (0 when the tool doesn't ask for upright, or the display isn't rotated). */\n const uprightRotFor = (displayRotation?: number): number => {\n if (!displayRotation) return 0;\n const ix = ctx.tryGet(InteractionToken);\n const tool = ix ? registry.get(ix.activeToolId()) : undefined;\n return tool?.upright ? uprightRotation(displayRotation) : 0;\n };\n\n const placeArmedStamp = (pon: number, point: Vec, displayRotation?: number): boolean => {\n const armed = armedStamp;\n if (!armed) return false;\n return createStampAt(\n pon,\n point,\n armed.source,\n { width: armed.width, height: armed.height },\n uprightRotFor(displayRotation),\n );\n };\n\n /** Sniff a stamp source (rejecting non-image bytes) and place it at its\n * intrinsic size (fit to the page in {@link createStampAt}); `targetWidth`\n * overrides the width, aspect preserved. */\n const placeStampSource = async (\n pon: number,\n point: Vec,\n source: BinarySource,\n rotCW: number,\n targetWidth?: number,\n ): Promise<void> => {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n console.error('[annotation] stamp source must be PNG, JPEG, or single-page PDF bytes');\n return;\n }\n createStampAt(pon, point, source, desiredStampSize(meta, targetWidth), rotCW);\n };\n\n /**\n * Click-to-place: resolve the ACTIVE tool's source spec. Fixed `bytes` place\n * immediately; a `'prompt'` source asks the installed provider, then places on\n * resolve — dropping the placement if it was cancelled, or if the tool or\n * document changed while the picker was open (the intent expired).\n */\n const requestStampAt = (pon: number, point: Vec, displayRotation?: number): boolean => {\n const ix = ctx.tryGet(InteractionToken);\n const tool = ix ? registry.get(ix.activeToolId()) : undefined;\n const spec = tool?.source;\n if (!spec) return false;\n // Resolved AT the click (like the placement point): the upright intent\n // belongs to the moment the author picked the spot, even when a 'prompt'\n // source resolves the bytes later.\n const rotCW = tool.upright && displayRotation ? uprightRotation(displayRotation) : 0;\n if (spec.kind === 'bytes') {\n void placeStampSource(pon, point, spec.source, rotCW);\n return true;\n }\n // kind === 'prompt' — needs the environment: the ONE file-picker port.\n return promptFileAt(\n tool,\n pon,\n point,\n (picked) => void placeStampSource(pon, point, picked.data, rotCW),\n );\n };\n\n /**\n * Run the installed file-picker port for a click-then-pick tool, with the\n * shared expiry rule: the placement is dropped if the picker cancels, or if\n * the document or the active tool changed while it was open (the intent\n * expired with the click). No provider installed → decline the click (let a\n * lower-priority handler act) rather than swallow it.\n */\n const promptFileAt = (\n tool: ResolvedTool,\n pon: number,\n point: Vec,\n place: (picked: AttachmentFileSource) => void,\n ): boolean => {\n const provider = filePickerProvider;\n if (!provider) return false;\n const spec = tool.source;\n const req: FilePromptRequest = {\n toolId: tool.id,\n subtype: tool.subtype,\n accept: spec?.kind === 'prompt' ? spec.accept : undefined,\n pon,\n point,\n };\n const docAtClick = ctx.doc;\n provider(req).then(\n (picked) => {\n if (!picked) return; // cancelled\n if (ctx.doc !== docAtClick) return; // document changed underneath\n if (ctx.tryGet(InteractionToken)?.activeToolId() !== tool.id) return; // tool changed\n place(picked);\n },\n (err) => console.error('[annotation] file-picker provider failed:', err),\n );\n return true;\n };\n\n /** Place a fixed-size ICON annotation (note / file attachment) centred on a\n * content point — the icon-kind sibling of {@link createStampAt}. The\n * engine bakes the 20×20 /AP from /C + /Name; a successful create selects\n * the new annotation (the anchor for its menu / future comment popup). */\n const createIconAt = (\n tool: ResolvedTool,\n pon: number,\n point: Vec,\n rotCW: number,\n file: AttachmentFileSource | null,\n ): boolean => {\n const doc = ctx.doc;\n const crop = cropOf(pon);\n if (!doc || !crop || !isIconPlaceKind(tool.subtype)) return false;\n const page = { width: crop.right - crop.left, height: crop.top - crop.bottom };\n const box: Rect = fitStampBox(point, ICON_PLACE_SIZE, page, rotCW);\n const draft = iconPlacementDraft(\n tool.subtype,\n boxGeomFields(box, rotCW, crop),\n defaultsFor(model(), tool.preset),\n tool.flags,\n file,\n );\n doc\n .page(pon)\n .annotations.create(draft)\n .then(\n (res) => {\n syncDTO(res.created, 'baked');\n apply({ t: 'select', ids: [refKey(res.created.ref)] });\n },\n (err) => console.error('[annotation] icon placement failed:', err),\n );\n return true;\n };\n\n /**\n * The ONE click-to-place entry the place handler forwards every down to —\n * armed payload first, then the active tool's kind decides:\n * - stamp → the source spec (fixed bytes, or the file-picker port)\n * - note (text) → place immediately (no payload)\n * - attachment → spot first, file second: the file-picker port opens\n * inside the click gesture, and placement lands when it\n * resolves (dropped on cancel, or if the tool/document\n * changed while the picker was open).\n * Returns whether the click was consumed.\n */\n const placeAt = (pon: number, point: Vec, displayRotation?: number): boolean => {\n if (placeArmedStamp(pon, point, displayRotation)) return true;\n const ix = ctx.tryGet(InteractionToken);\n const tool = ix ? registry.get(ix.activeToolId()) : undefined;\n if (!tool) return false;\n if (tool.subtype === 'stamp') return requestStampAt(pon, point, displayRotation);\n if (!isIconPlaceKind(tool.subtype)) return false;\n const rotCW = tool.upright && displayRotation ? uprightRotation(displayRotation) : 0;\n if (tool.subtype === 'text') return createIconAt(tool, pon, point, rotCW, null);\n return promptFileAt(tool, pon, point, (picked) =>\n createIconAt(tool, pon, point, rotCW, picked),\n );\n };\n\n /** The page a ref lives on: from the loaded model first (covers obj/nm refs\n * that don't carry a pon), else the ref itself (index refs do). */\n const ponForRef = (ref: AnnotationRef): number | null =>\n model().byId[refKey(ref)]?.pon ?? (ref.kind === 'index' ? ref.pageObjectNumber : null);\n\n /**\n * Re-sync one annotation into the model from the authoritative engine DTO,\n * with the render `source` the caller decides: `'vector'` when WE authored or\n * changed the appearance (create / restyle / resize), `'baked'` when the AP is\n * still authoritative (a move, which preserves it, or a remote edit).\n * `bumpAp` marks the upsert as confirming an engine /AP re-bake with new\n * content, so the annotation's `apVersion` — and with it the page's\n * appearance epoch — advances and the shell fetches the fresh raster.\n */\n const syncDTO = (\n dto: Parameters<typeof fromDTO>[0],\n source: 'baked' | 'vector',\n bumpAp = false,\n ): void => {\n const crop = cropOf(dto.pageObjectNumber);\n if (crop) apply({ t: 'upsert', annots: [fromDTO(dto, crop, source)], bumpAp });\n };\n\n /** The one engine-update path, shared by `update` and `updateSelection`. A\n * programmatic patch changes the appearance → render live (vector). */\n const updateOne = async (ref: AnnotationRef, patch: AnnotationPatch): Promise<void> => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n const pon = ponForRef(ref);\n if (pon == null) throw new Error('[annotation] cannot resolve page for ref');\n const res = await doc.page(pon).annotations.update(ref, patch);\n syncDTO(res.updated, 'vector');\n };\n\n function apply(msg: Msg): void {\n const [next, effects] = update(model(), msg);\n ctx.dispatch({ type: 'SET_MODEL', model: next });\n for (const fx of effects) perform(fx, next);\n }\n\n /**\n * Per-parent serialization of attached-link reconciles: rapid edits chain\n * instead of interleaving (two overlapping runs could double-create\n * children). Each run reads the CURRENT model at execution time, so a\n * chained run converges on the latest desired state.\n */\n const linkSyncChains = new Map<Id, Promise<void>>();\n const scheduleLinkSync = (id: Id): void => {\n const prev = linkSyncChains.get(id) ?? Promise.resolve();\n const next = prev.then(() => reconcileLinkChildren(id));\n linkSyncChains.set(id, next);\n void next.finally(() => {\n if (linkSyncChains.get(id) === next) linkSyncChains.delete(id);\n });\n };\n\n /**\n * THE one place attached link children are created, retargeted, re-rected,\n * or deleted (the delete-with-parent expansion in the core is the one other\n * consumer of `linkRefs`). Declarative: desired state is derived fresh from\n * the parent's `link` value + committed geometry (`linkChildRects`), then\n * diffed against the join keys the last fold reported. Idempotent — foreign\n * inconsistencies heal on the next local edit.\n */\n const reconcileLinkChildren = async (id: Id): Promise<void> => {\n const doc = ctx.doc;\n const a = model().byId[id];\n if (!doc || !a || !a.ref || a.subtype === 'link') return;\n const crop = cropOf(a.pon);\n if (!crop) return;\n const page = doc.page(a.pon);\n // Read-only target arms can't be (re)written: children keep their /A and\n // only their rects follow the parent.\n const target = writableTarget(a.link);\n const rects = a.link == null ? [] : linkChildRects(a).map((r) => contentToPdfRect(r, crop));\n const current = a.linkRefs ?? [];\n const nextRefs: AnnotationRef[] = [];\n try {\n const paired = Math.min(current.length, rects.length);\n for (let i = 0; i < paired; i++) {\n const res = await page.annotations.update(current[i], {\n subtype: 'link',\n rect: rects[i],\n ...(target ? { target } : {}),\n });\n nextRefs.push(res.updated.ref);\n }\n for (let i = current.length; i < rects.length; i++) {\n const res = await page.annotations.create({\n subtype: 'link',\n rect: rects[i],\n target,\n inReplyTo: a.ref,\n replyType: 'group',\n });\n nextRefs.push(res.created.ref);\n }\n for (let i = rects.length; i < current.length; i++) {\n await page.annotations.delete(current[i]);\n }\n } catch (err) {\n console.error('[annotation] attached-link sync failed:', err);\n }\n // Refresh the join keys on the CURRENT model annot (it may have moved on\n // since this run was scheduled). Explicit `linkRefs` (possibly []) wins\n // over the upsert's fold preservation.\n const cur = model().byId[id];\n if (cur) apply({ t: 'upsert', annots: [{ ...cur, linkRefs: nextRefs }] });\n };\n\n /** A relationship-only engine patch (sets/clears `/IRT` + `/RT`) — geometry and\n * style are left untouched, so grouping never re-bakes an appearance. */\n const relationshipPatch = (\n subtype: AnnotationDTO['subtype'],\n rel: { inReplyTo: AnnotationRef | null; replyType?: 'group' },\n ): AnnotationPatch => ({ subtype, ...rel }) as AnnotationPatch;\n\n /** Write a relationship change to one committed annotation and re-sync it from\n * the authoritative DTO (preserving its render source — relationships don't\n * change the appearance). */\n const writeRelationship = async (\n a: Annot,\n rel: { inReplyTo: AnnotationRef | null; replyType?: 'group' },\n ): Promise<void> => {\n const doc = ctx.doc;\n if (!doc || !a.ref || !a.data) return;\n const res = await doc\n .page(a.pon)\n .annotations.update(a.ref, relationshipPatch(a.data.subtype, rel));\n syncDTO(res.updated, a.source);\n };\n\n /** Committed, data-backed annotations in the current selection. */\n const selectedCommitted = (): Annot[] => {\n const m = model();\n return m.selected.map((id) => m.byId[id]).filter((a): a is Annot => !!a && !!a.ref && !!a.data);\n };\n\n function perform(fx: Effect, m: Model): void {\n const doc = ctx.doc;\n if (!doc) return;\n if (fx.fx === 'createGroup') {\n const ids = [fx.primary, ...fx.members];\n const annots = ids.map((id) => m.byId[id]);\n const primary = annots[0];\n if (!primary || annots.some((a) => !a || a.pon !== primary.pon)) {\n apply({ t: 'remove', ids });\n return;\n }\n const crop = cropOf(primary.pon);\n const drafts = crop\n ? annots.map((a) => (a ? toCreateDraft(a, crop) : null))\n : annots.map(() => null);\n if (drafts.some((d) => !d)) {\n apply({ t: 'remove', ids });\n return;\n }\n\n void (async () => {\n const committed: Array<{ tempId: string; ref: AnnotationRef }> = [];\n try {\n const page = doc.page(primary.pon);\n const primaryResult = await page.annotations.create(drafts[0]!);\n committed.push({ tempId: fx.primary, ref: primaryResult.created.ref });\n apply({\n t: 'created',\n tempId: fx.primary,\n id: refKey(primaryResult.created.ref),\n ref: primaryResult.created.ref,\n });\n syncDTO(primaryResult.created, 'vector');\n\n for (let i = 0; i < fx.members.length; i++) {\n const tempId = fx.members[i]!;\n const draft = {\n ...drafts[i + 1]!,\n inReplyTo: primaryResult.created.ref,\n replyType: 'group' as const,\n } as AnnotationDraft;\n const result = await page.annotations.create(draft);\n committed.push({ tempId, ref: result.created.ref });\n apply({\n t: 'created',\n tempId,\n id: refKey(result.created.ref),\n ref: result.created.ref,\n });\n syncDTO(result.created, 'vector');\n }\n } catch (error) {\n // A PDF write cannot be transactional, so compensate in reverse: remove\n // every committed part. Keep any part whose rollback itself fails in the\n // model; the UI must reflect the authoritative PDF, never hide an orphan.\n const removeIds = ids.filter((id) => !committed.some((c) => c.tempId === id));\n for (const part of [...committed].reverse()) {\n try {\n await doc.page(primary.pon).annotations.delete(part.ref);\n removeIds.push(refKey(part.ref));\n } catch {\n // `syncDTO` already made this committed annotation visible.\n }\n }\n if (removeIds.length) apply({ t: 'remove', ids: removeIds });\n console.error('[annotation] grouped annotation creation failed:', error);\n }\n })();\n } else if (fx.fx === 'create') {\n const a = m.byId[fx.id];\n const crop = a && cropOf(a.pon);\n const draft = a && crop ? toCreateDraft(a, crop) : null;\n if (!a || !draft) return;\n doc\n .page(a.pon)\n .annotations.create(draft)\n .then(\n (res) => {\n // Reconcile temp→durable id (keeps selection/order), then attach the\n // authoritative DTO so the committed annotation is fully data-backed.\n apply({\n t: 'created',\n tempId: fx.id,\n id: refKey(res.created.ref),\n ref: res.created.ref,\n });\n // We just drew it — render live, not the engine's freshly-baked AP.\n syncDTO(res.created, 'vector');\n },\n () => apply({ t: 'createFailed', tempId: fx.id }),\n );\n } else if (fx.fx === 'flags') {\n // A `/F`-only write: the model already holds the MERGED flags, so emit\n // the full set (create/update both land on exactly these bits). The\n // re-sync PRESERVES the render source — flags never change an\n // appearance, so a baked raster stays authoritative and nothing\n // re-fetches.\n const a = m.byId[fx.id];\n if (!a || !a.ref || !a.data) return;\n doc\n .page(a.pon)\n .annotations.update(a.ref, {\n subtype: a.data.subtype,\n flags: a.flags,\n } as AnnotationPatch)\n .then(\n (res) => syncDTO(res.updated, a.source),\n (err) => console.error('[annotation] flags write failed:', err),\n );\n } else if (fx.fx === 'patch') {\n const a = m.byId[fx.id];\n const crop = a && cropOf(a.pon);\n const patch = a && a.ref && crop ? toScopedPatch(a, fx.scope, crop) : null;\n if (!a || !a.ref || !patch) return;\n // Re-sync from the authoritative DTO, PRESERVING the source the gesture\n // chose: a move kept it baked (raster rides along), a resize flipped it to\n // vector. So the round-trip can't silently re-bake an edited annotation.\n //\n // `apVersion` is driven by the ENGINE'S echo (`res.appearance.changed`),\n // not by guessing from the patch we sent: the engine value-diffs the\n // patch, verifies rigid translations, and reports whether the document's\n // appearance definition actually changed. Preserved moves (including\n // widget/stamp drags — their /AP survives now) cost zero re-fetches;\n // regenerated appearances re-fetch exactly once, when the engine is\n // done — never one-behind. The core's `fx.apChanged` prediction stays\n // advisory (a future pre-commit \"this will replace an imported\n // appearance\" affordance); the echo is the authority.\n doc\n .page(a.pon)\n .annotations.update(a.ref, patch)\n .then(\n (res) => {\n syncDTO(res.updated, a.source, res.appearance.changed);\n // Attached link children follow their parent's COMMITTED geometry\n // — scheduled after the parent's own write resolves, from ONE\n // place, so no gesture ever has to know the children exist.\n if (a.linkRefs?.length) scheduleLinkSync(fx.id);\n },\n () => {},\n );\n } else if (fx.fx === 'syncLink') {\n scheduleLinkSync(fx.id);\n } else {\n doc\n .page(fx.ref.pageObjectNumber)\n .annotations.delete(fx.ref)\n .then(\n () => {},\n () => {},\n );\n }\n }\n\n return {\n // ── data API: create / update / delete (engine-routed, ref-addressed) ──\n create: async (pon, draft: AnnotationDraft): Promise<AnnotationRef> => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n // Default `/F` to `print` (Acrobat parity — without it the annotation\n // disappears when printed). An EXPLICIT `flags` is respected verbatim.\n const withFlags = (\n draft.flags ? draft : { ...draft, flags: { print: true } }\n ) as AnnotationDraft;\n const res = await doc.page(pon).annotations.create(withFlags);\n // Stamps have no vector render — their engine-baked /AP is the visual.\n syncDTO(res.created, res.created.subtype === 'stamp' ? 'baked' : 'vector');\n return res.created.ref;\n },\n armStamp,\n disarmStamp,\n placeArmedStamp,\n requestStampAt,\n placeAt,\n hasArmedStamp: () => armedStamp != null,\n ghostHoverAt,\n clearGhost,\n setPlacementPreview,\n clearPlacementPreview: clearGhost,\n toolGhost: (pon) => {\n const g = ctx.getState().toolGhost;\n return g && g.pon === pon ? g : null;\n },\n armedStampPreview: () => armedStamp?.preview ?? null,\n stampArmEpoch: () => ctx.getState().stampArmEpoch,\n setFilePickerProvider: (provider) => {\n filePickerProvider = provider;\n },\n downloadAttachment: async (ref) => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n const pon = ponForRef(ref);\n if (pon == null) throw new Error('[annotation] cannot resolve page for ref');\n const annotations = doc.page(pon).annotations;\n if (!annotations.downloadFile) {\n throw new Error('[annotation] this engine does not support attachment download');\n }\n return annotations.downloadFile(ref);\n },\n // ── tool registry ──\n tools: () => [...registry.values()],\n tool: (id) => registry.get(id) ?? null,\n toolSubtype: (id) => registry.get(id)?.subtype ?? (id as Subtype),\n registerTool: (def: AnnotationToolInput) => {\n // Re-resolve against the same base pool so `extends` can reach built-ins /\n // config tools, then register just this one with the hub + seed its defaults.\n const resolved = buildToolRegistry([...configTools, def]).get(def.id);\n if (!resolved) throw new Error(`[annotation] could not resolve tool '${def.id}'`);\n registry.set(resolved.id, resolved);\n const un = ctx\n .tryGet(InteractionToken)\n ?.registerTool({ id: resolved.id, cursor: resolved.cursor, enables: resolved.enables });\n if (resolved.defaults)\n apply({ t: 'setDefaults', subtype: resolved.preset, patch: resolved.defaults });\n return () => {\n registry.delete(resolved.id);\n un?.();\n };\n },\n update: (ref: AnnotationRef, patch: AnnotationPatch) => updateOne(ref, patch),\n // Restyle the selection: ONE flat props patch through the pure core (the\n // same `update → patch effect → toPatch` path every gesture takes). Each\n // member takes the keys its kind declares and ignores the rest; the model\n // updates optimistically, the engine writes fire per member and re-sync.\n updateSelection: (patch) => apply({ t: 'setProps', patch }),\n // Flag writes take their own message (NOT the props path): they must never\n // flip a member to vector or re-bake its /AP, and they must work on a\n // LOCKED annotation — unlocking is the point.\n updateSelectionFlags: (patch) => apply({ t: 'setFlags', patch }),\n getSelectionFlags: () => memoSelectionFlags(),\n delete: async (ref: AnnotationRef): Promise<void> => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n const pon = ponForRef(ref);\n if (pon == null) throw new Error('[annotation] cannot resolve page for ref');\n await doc.page(pon).annotations.delete(ref);\n apply({ t: 'remove', ids: [refKey(ref)] });\n },\n\n // ── authorization (coarse UI mirror; engine enforces per-owner) ──\n canCreate: () => ctx.doc?.security.allows(ANNOTATE_MODIFY) ?? false,\n canEdit: () => ctx.doc?.security.allows(ANNOTATE_MODIFY) ?? false,\n canDelete: () => ctx.doc?.security.allows(ANNOTATE_MODIFY) ?? false,\n\n getSelection: (): AnnotationRef[] => {\n const m = model();\n return m.selected.map((id) => m.byId[id]?.ref).filter((r): r is AnnotationRef => r != null);\n },\n\n // ── DTO-returning reads (canonical engine vocabulary) ──\n get: (ref: AnnotationRef): AnnotationDTO | null => model().byId[refKey(ref)]?.data ?? null,\n list: (pon: number): AnnotationDTO[] => {\n const m = model();\n return m.order\n .map((id) => m.byId[id])\n .filter((a) => a?.pon === pon)\n .map((a) => a?.data)\n .filter((d): d is AnnotationDTO => d != null);\n },\n getSelected: (): AnnotationDTO[] => {\n const m = model();\n return m.selected.map((id) => m.byId[id]?.data).filter((d): d is AnnotationDTO => d != null);\n },\n\n // ── property introspection (the schema a sidebar renders from) ──\n getSelectionProps: () => memoSelectionProps(),\n // A tool's editable-prop schema comes from its kind: a callout edits free-text\n // props, an arrow edits line props. The registry holds that mapping.\n propsForTool: (toolId) => propsFor(registry.get(toolId)?.propsKind ?? toolId),\n\n // selectors\n pageItems: (pon, view) => memoItems(pon, view),\n chrome: (pon, scale, rotation, zoom) => memoChrome(pon, scale, rotation, zoom),\n selectionAnchor: (scale, rotation, zoom) => memoAnchor(scale, rotation, zoom),\n creationDraftAnchor: () => memoDraftAnchor(),\n selection: () => model().selected,\n hitKind: (pon, point, scale, rotation, zoom) =>\n hitTest(\n model(),\n pon,\n point,\n chromeGeomAt(scale),\n model().hitMargin,\n pageBoxOf(pon),\n inertIdsAt(pon),\n viewEnv(zoom, rotation),\n ).t,\n cursorAt: (pon, point, scale, rotation, zoom) =>\n cursorAt(\n model(),\n pon,\n point,\n chromeGeomAt(scale),\n model().hitMargin,\n pageBoxOf(pon),\n inertIdsAt(pon),\n viewEnv(zoom, rotation),\n ),\n hoverAt: (at) => {\n const m = model();\n let id: string | null = null;\n if (at) {\n const h = hitTest(\n m,\n at.pon,\n at.point,\n chromeGeomAt(at.scale),\n m.hitMargin,\n pageBoxOf(at.pon),\n inertIdsAt(at.pon),\n viewEnv(at.zoom, at.rotation),\n );\n if (h.t === 'annot') id = h.id;\n }\n // Diff HERE so the reducer sees enter/leave transitions only.\n if (m.hovered !== id) apply({ t: 'hover', id });\n },\n behaviorFor: (a) => behaviors.find((b) => b.matches(a) && b.engaged()) ?? null,\n linkItemsOn: (pon) => memoLinkItems(pon),\n\n appearanceEpoch: (pon) => {\n // What a baked raster DEPENDS on, and nothing else: which annotations are\n // baked on this page, and each one's /AP content version (`apVersion` —\n // bumped when a size-changing patch RESOLVES, or a remote edit folds in).\n // Position and rotation are deliberately absent: the blit translates\n // (`apBox`) and rotates (`apRot`) the same pixels, so a move or a spin\n // costs zero re-renders — and because the version bumps when the engine\n // CONFIRMS the re-bake, the fetch can never read a stale /AP (\"one\n // behind\"). Render scale is the shell effect's own dependency.\n const m = model();\n const parts: string[] = [];\n for (const id of m.order) {\n const a = m.byId[id];\n if (!a || a.pon !== pon || a.source !== 'baked' || !a.ref) continue;\n parts.push(`${id}@${a.apVersion ?? 0}`);\n }\n return parts.sort().join('|');\n },\n bakeScale: (renderScale) =>\n // The render policy is a document FACT off the kernel registry (like\n // `pages`), interpreted by the pure engine-core helper — one lifecycle,\n // one interpretation, no plugin dependency. Identity under continuous.\n snapAppearanceScale(ctx.document()?.renderPolicy ?? CONTINUOUS_RENDER_POLICY, renderScale),\n appearances: (pon, scale, signal) => {\n const doc = ctx.doc;\n if (!doc) return Promise.resolve([]);\n const task = doc.page(pon).annotations.renderAppearanceImages({ scale });\n if (signal) {\n if (signal.aborted) task.abort(signal.reason);\n else signal.addEventListener('abort', () => task.abort(signal.reason), { once: true });\n }\n return task.then(\n (r) => r.appearances,\n () => [],\n );\n },\n toContentBox: (pon, rect) => {\n const crop = cropOf(pon);\n return crop ? pdfToContentRect(rect, crop) : null;\n },\n\n // intents\n editPointer: (phase, pon, point, shift, scale, rotation, zoom) =>\n apply({\n t: 'editPointer',\n phase,\n in: {\n pon,\n point,\n shift,\n pageBox: pageBoxOf(pon),\n chrome: chromeGeomAt(scale),\n inert: inertIdsAt(pon),\n // the view env (screen-anchored bodies hit/clamp at their footprint)\n ...(zoom != null ? { zoom } : {}),\n ...(rotation != null ? { displayRotation: rotation } : {}),\n },\n }),\n marqueePointer: (phase, pon, point, shift, scale, rotation, zoom) =>\n apply({\n t: 'marqueePointer',\n phase,\n in: {\n pon,\n point,\n shift,\n pageBox: pageBoxOf(pon),\n inert: inertIdsAt(pon),\n ...(zoom != null ? { zoom } : {}),\n ...(rotation != null ? { displayRotation: rotation } : {}),\n },\n }),\n createPointer: (tool, phase, pon, point, finish = false, displayRotation) => {\n // Resolve the authoring TOOL to its routing subtype + defaults key. Two\n // tools can share a subtype (line / arrow); `preset` keeps their defaults\n // apart. Unknown id → treat it as a bare subtype (headless/programmatic).\n // The tool's `upright` policy + the sample's display rotation ride the\n // input bag; the core captures them on the draft at DOWN.\n const t = registry.get(tool);\n apply({\n t: 'createPointer',\n phase,\n subtype: t?.subtype ?? (tool as Subtype),\n preset: t?.preset ?? tool,\n intent: t?.intent,\n clickCreate: t?.clickCreate,\n flags: t?.flags,\n deferInkCommit: (t?.ink?.groupStrokesMs ?? 0) > 0,\n straightenInk: t?.ink?.straighten,\n in: {\n pon,\n point,\n shift: false,\n finish,\n pageBox: pageBoxOf(pon),\n displayRotation,\n upright: t?.upright,\n },\n });\n },\n finishCreationDraft: () => apply({ t: 'finishCreationDraft' }),\n finishInkDraft: () => apply({ t: 'finishInkDraft' }),\n cancelCreationDraft: () => apply({ t: 'cancel' }),\n createMarkup: (subtype, pon, quads, preset) =>\n // A markup tool's `/F` seed rides along (the preset IS the tool id).\n apply({\n t: 'createMarkup',\n subtype,\n pon,\n quads,\n preset,\n flags: preset ? registry.get(preset)?.flags : undefined,\n }),\n createCaret: (pon, anchor) => apply({ t: 'createCaret', pon, anchor }),\n createReplaceText: (pon, quads, anchor, preset) =>\n apply({ t: 'createReplaceText', pon, quads, anchor, preset }),\n previewMarkup: (subtype, quadsByPage, preset) =>\n apply({ t: 'setMarkupPreview', subtype, quadsByPage, preset }),\n clearMarkupPreview: () => apply({ t: 'clearMarkupPreview' }),\n setDefaults: (subtype, patch) => apply({ t: 'setDefaults', subtype, patch }),\n // Resolve through the tool's `preset` key so arrow reads arrow's defaults, not\n // line's (and the insert-caret tool reads the shared `caret` bag). Falls back\n // to the given id for a bare subtype.\n currentDefaults: (toolId) => defaultsFor(model(), registry.get(toolId)?.preset ?? toolId),\n // Live-adjustable snapping (a UI toggle); seeded by the registration config.\n setSnap: (patch) => apply({ t: 'setSnap', patch }),\n snapSettings: () => model().snap,\n // Live-adjustable selection chrome (theming); seeded by the registration config.\n setChrome: (patch) => ctx.dispatch({ type: 'SET_CHROME', patch }),\n chromeSettings: () => chromeSettings(),\n deleteSelection: () => apply({ t: 'delete' }),\n deselect: () => apply({ t: 'deselect' }),\n select: (ref, options) => {\n apply({ t: 'select', ids: [refKey(ref)], add: options?.add });\n },\n pruneEngagedSelection: () => {\n // Engaged ⇒ hit-test-inert ⇒ must not STAY selected either (a widget\n // selected in design mode keeps no chrome once the fill tool engages).\n const m = model();\n const drop = m.selected.filter((id) => {\n const a = m.byId[id];\n return (\n a && behaviors.some((b) => b.matches({ subtype: a.subtype, ref: a.ref }) && b.engaged())\n );\n });\n if (drop.length) apply({ t: 'deselect', ids: drop });\n },\n cancel: () => apply({ t: 'cancel' }),\n // Rotate the selection a quarter-turn clockwise / reset it to as-authored.\n // Both commit one geometry patch per rotatable member (the same path the\n // rotate-knob gesture uses), so they round-trip through the engine identically.\n rotateSelection90: () => apply({ t: 'rotate90' }),\n resetSelectionRotation: () => apply({ t: 'resetRotation' }),\n\n // ── grouping (engine `/IRT` + `/RT /Group`; page-local) ──\n /** Group the current selection into one unit: the bottom-most member becomes\n * the primary, every other member becomes a `/RT /Group` subordinate of it.\n * No-op unless 2+ committed annotations on a single page are selected. */\n group: async (): Promise<void> => {\n const m = model();\n const members = selectedCommitted();\n if (members.length < 2) return;\n const pon = members[0].pon;\n if (members.some((a) => a.pon !== pon)) return; // groups are page-local\n const ordered = [...members].sort((a, b) => m.order.indexOf(a.id) - m.order.indexOf(b.id));\n const [primary, ...rest] = ordered;\n if (!primary.ref) return;\n await Promise.all(\n rest.map((a) => writeRelationship(a, { inReplyTo: primary.ref, replyType: 'group' })),\n );\n },\n /** Ungroup: clear `/IRT` (+ `/RT`) on every subordinate in the group(s) the\n * selection touches, so each member becomes top-level again. */\n ungroup: async (): Promise<void> => {\n const m = model();\n const subs = expandGroups(m, m.selected)\n .map((id) => m.byId[id])\n .filter((a): a is Annot => !!a && !!a.ref && !!a.data && !!a.group);\n await Promise.all(subs.map((a) => writeRelationship(a, { inReplyTo: null })));\n },\n canGroup: (): boolean => {\n if (!(ctx.doc?.security.allows(ANNOTATE_MODIFY) ?? false)) return false;\n const m = model();\n const members = selectedCommitted();\n if (members.length < 2) return false;\n if (members.some((a) => a.pon !== members[0].pon)) return false;\n // Already exactly one complete group → nothing to do.\n const keys = new Set(m.selected.map((id) => groupKeyOf(m, id)));\n if (keys.size === 1 && !keys.has(null)) return false;\n return true;\n },\n canUngroup: (): boolean => {\n if (!(ctx.doc?.security.allows(ANNOTATE_MODIFY) ?? false)) return false;\n const m = model();\n return m.selected.some((id) => groupKeyOf(m, id) != null);\n },\n\n ensurePage: (pon) => {\n if (loaded.has(pon)) return;\n const doc = ctx.doc;\n const crop = cropOf(pon);\n if (!doc || !crop) return;\n loaded.add(pon);\n doc\n .page(pon)\n .annotations.list()\n .then(\n (snap) =>\n apply({\n t: 'loaded',\n annots: foldAttachedLinks(snap.annotations.map((d) => fromDTO(d, crop))),\n }),\n () => {\n loaded.delete(pon);\n },\n );\n },\n\n reloadPage: async (pon) => {\n const doc = ctx.doc;\n const crop = cropOf(pon);\n if (!doc || !crop) return;\n loaded.add(pon);\n try {\n const snap = await doc.page(pon).annotations.list();\n // Replace, not merge: drop this page's current annots first so\n // cross-plane deletions (deleteField) actually disappear.\n const m = model();\n const stale = m.order.filter((id) => m.byId[id]?.pon === pon);\n if (stale.length) apply({ t: 'remove', ids: stale });\n apply({\n t: 'loaded',\n annots: foldAttachedLinks(snap.annotations.map((d) => fromDTO(d, crop))),\n });\n } catch {\n loaded.delete(pon);\n }\n },\n\n // ── free-text (the editable-element layer) ──\n textItems: (pon, view) => memoTexts(pon, view),\n currentEditing: () => model().editing,\n beginTextEdit: (ref) => apply({ t: 'beginTextEdit', id: refKey(ref) }),\n beginTextEditAt: (pon, point, scale, rotation, zoom) => {\n const m = model();\n const h = hitTest(\n m,\n pon,\n point,\n chromeGeomAt(scale),\n m.hitMargin,\n pageBoxOf(pon),\n undefined,\n viewEnv(zoom, rotation),\n );\n // A double-click on the box body OR one of its resize handles both target the\n // same annotation; either should open it for editing.\n const id = h.t === 'annot' || h.t === 'handle' ? h.id : null;\n if (id != null && m.byId[id]?.geom.t === 'text') apply({ t: 'beginTextEdit', id });\n },\n setContents: (ref, text) => {\n apply({ t: 'setText', id: refKey(ref), text }); // optimistic, no engine churn\n const key = refKey(ref);\n clearTimeout(textTimers.get(key));\n textTimers.set(\n key,\n setTimeout(() => {\n textTimers.delete(key);\n const pon = ponForRef(ref);\n if (pon != null) {\n ctx.doc\n ?.page(pon)\n .annotations.update(ref, { subtype: 'free-text', contents: text })\n .then(\n () => {},\n () => {},\n );\n }\n }, TEXT_COMMIT_DEBOUNCE_MS),\n );\n },\n endTextEdit: () => {\n // flush any pending debounced write immediately, then leave edit mode\n for (const t of textTimers.values()) clearTimeout(t);\n const id = model().editing;\n const a = id ? model().byId[id] : null;\n if (a?.ref) {\n const pon = ponForRef(a.ref);\n const text = a.data?.contents ?? '';\n if (pon != null)\n ctx.doc\n ?.page(pon)\n .annotations.update(a.ref, { subtype: 'free-text', contents: text })\n .then(\n () => {},\n () => {},\n );\n }\n textTimers.clear();\n apply({ t: 'endTextEdit' });\n },\n\n registerBehavior: (b) => {\n behaviors.push(b);\n return () => {\n const i = behaviors.indexOf(b);\n if (i >= 0) behaviors.splice(i, 1);\n };\n },\n };\n}\n"],"mappings":"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"}