@embedpdf/plugin-annotation 3.0.0-next.1 → 3.0.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-Cl9x8oLS.cjs","names":["initialTextStyle","textQuadBounds","initialTextStyle","FLAG_KEYS","InteractionToken","CONTINUOUS_RENDER_POLICY","SelectionPublicToken"],"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 {\n createCapabilityToken,\n type DocumentEvent,\n type PageObjectNumber,\n} 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 CommentThread,\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\n/**\n * Whole-document annotation hydration. The plugin always hydrates ALL\n * pages through `doc.annotations.listRawAll()` (one bulk request on\n * cloud, one worker job locally) — a comments sidebar needs every page,\n * and per-page lazy loading could never truthfully claim completeness.\n * `loading` covers the initial ingest AND a desync re-ingest; `error`\n * means live events still apply but the whole-document view is\n * incomplete until a rehydrate succeeds.\n */\nexport type AnnotationHydration =\n | { status: 'loading' }\n | { status: 'complete' }\n | { status: 'error'; error: unknown }\n // The scope lacks `doc.annotate.read`: hydration never runs (no doomed\n // request), the comments panel hides, and `rehydrate` re-checks — the\n // state clears if an /access refresh grants read later.\n | { status: 'forbidden' };\n\nexport interface AnnotationState {\n model: Model;\n hydration: AnnotationHydration;\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_HYDRATION'; hydration: AnnotationHydration }\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 * True for a link CHILD riding an editable annotation (an `/RT /Group`\n * subordinate) — a PROPERTY of its parent while authoring, a nav behavior\n * only while reading. The nav layer stands its anchors down for attached\n * items whenever the active tool enables `annotation-edit`, so the parent\n * stays selectable/movable; standalone document links navigate regardless.\n */\n attached: boolean;\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 */\n/**\n * Per-thread action gates, composed from two axes: authority (the\n * engine's collab-resolver mirrors — `allowsAnnotationCreate` for\n * reply/status, `allowsAnnotationMutation` against each target's\n * stamped owner for edit/delete) and PDF state (the two lock flags\n * gate DIFFERENT aspects, ISO 32000 Table 167: `lockedContents` blocks\n * text edits, `locked` blocks deletion). A courtesy, not the guard — the\n * engine independently enforces every write.\n */\nexport interface CommentPermissions {\n /** A reply is an annotation CREATE. */\n canReply: boolean;\n /** Editing this comment's text (`contents`) — gated by `lockedContents`. */\n canEditText: boolean;\n /** Deleting this one annotation — gated by `locked`. */\n canDelete: boolean;\n /** A status change is a NEW hidden annotation — create authority only,\n * never edit rights on someone else's comment. */\n canSetStatus: boolean;\n /** `canDelete` over EVERY thread member (root, replies, grouped parts,\n * state annotations) — the whole-thread preflight. */\n canDeleteThread: boolean;\n}\n\nexport interface ThreadDeleteResult {\n deleted: AnnotationRef[];\n failed: Array<{ ref: AnnotationRef; error: unknown }>;\n}\n\n/**\n * The conversation plane's surface: a derived, memoized threads index over\n * the annotation substrate, plus the ISO-native verbs. Every verb compiles\n * down to plain annotation creates/patches/deletes — one optimistic\n * pipeline, no second write path — so remote SSE events, own edits, and\n * hydration all update `threads()` for free.\n *\n * Threads carry `pageObjectNumber` (identity is PON, like everything\n * else); DISPLAY order is a behavior of `threads()` (sorted against the\n * live layout at computation time), and display labels (`pageIndex`) are a\n * framework-hook enrichment — the layer that watches both stores.\n */\nexport interface CommentsApi {\n /** Every comment thread in the document, display-ordered, memoized. */\n threads(): CommentThread[];\n /** The thread containing ANY member ref (root, reply, grouped part, or\n * state annotation), or null. */\n thread(ref: AnnotationRef): CommentThread | null;\n /** Whole-document hydration status (the sidebar's honest loading state). */\n hydration(): AnnotationHydration;\n /** Re-run whole-document hydration (desync recovery / manual refresh). */\n rehydrate(): Promise<void>;\n\n /** Reply to a thread. Writes FLAT (`/IRT` → the thread root, ISO reply\n * type), whatever member was passed — presentation stays one level. */\n reply(ref: AnnotationRef, text: string): Promise<AnnotationRef>;\n /** Edit a comment's text. Appearance-inert for every kind except\n * free-text and redaction (whose `/AP` paints `/Contents`). */\n edit(ref: AnnotationRef, text: string): Promise<void>;\n /**\n * Set this session's review status on the thread (ISO 32000 §12.5.6.3):\n * creates a hidden state annotation chained to the caller's previous\n * status when one exists, else to the root. The target annotation is\n * never modified. Known states: accepted / rejected / cancelled /\n * completed / none (custom vocabularies ride the raw create API).\n */\n setStatus(ref: AnnotationRef, state: string): Promise<void>;\n /** Toggle this session's Marked-model checkmark on the thread. */\n setMarked(ref: AnnotationRef, marked: boolean): Promise<void>;\n /** Delete exactly ONE annotation (a reply, a status, or a bare root). */\n remove(ref: AnnotationRef): Promise<void>;\n /**\n * Delete a WHOLE thread, children first. Preflighted: when any member\n * fails the delete gate the call returns every blocked ref as `failed`\n * and deletes nothing; mid-flight races surface the same way.\n */\n removeThread(ref: AnnotationRef): Promise<ThreadDeleteResult>;\n\n /** Truthful per-thread action gates for the ref's thread. */\n permissionsFor(ref: AnnotationRef): CommentPermissions;\n}\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: the `can` twins (permissions.md). Each answers \"would\n // this verb succeed now for this session?\" — authority (the engine's\n // collab mirrors) AND document flags, via the same fused predicates the\n // gestures and chrome consume; the active tool is deliberately excluded\n // (twins are facts; mode gates rendering). `canRead` mirrors\n // `doc.annotate.read`: false → hydration reports `forbidden` and the\n // comments UI hides. The engine independently enforces everything. ──\n canRead(): boolean;\n // ── authorization: per-record mirrors of the engine's collab resolver\n // (`security.allowsAnnotation*`). `canCreate` asks about the caller's\n // own identity; `canEdit`/`canDelete` about the TARGET's stamped owner,\n // so under a narrowed grant (`annotations:update:self`) they answer\n // per annotation. Pure authority — the `locked`/`lockedContents` flag\n // gates live with the surfaces that touch that aspect (see\n // `comments.permissionsFor`). The engine independently enforces. ──\n canCreate(): boolean;\n canEdit(ref: AnnotationRef): boolean;\n canDelete(ref: AnnotationRef): boolean;\n\n /** The conversation plane's read/write surface — see {@link CommentsApi}. */\n comments: CommentsApi;\n\n /**\n * The attached-link lens: an annotation's link is a `/Link` CHILD grouped\n * under it in the document (ISO-native, Acrobat-interoperable) — a\n * PROPERTY while authoring, a nav BEHAVIOR while reading. `of` derives\n * from the committed children (the one source of truth); `set`/`clear`\n * resolve when the children are committed, after which `of` reflects the\n * change. `updateSelection({ link })` remains the props-pipeline alias.\n * On the link KIND itself, `of` reads the annotation's own `/A` target\n * (retarget standalone links via `updateSelection`).\n */\n links: {\n of(ref: AnnotationRef): PdfLinkTarget | null;\n set(ref: AnnotationRef, target: PdfLinkTarget): Promise<void>;\n clear(ref: AnnotationRef): Promise<void>;\n };\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 // ── text-selection authoring (one-shot; requires the selection plugin) ──\n /**\n * Turn the CURRENT text selection into markup annotations — one per\n * selected page, from the selection's oriented per-line quads — then clear\n * the selection. The one-call form of what the markup tools do on\n * commit, made for selection-menu buttons (\"Highlight\") and automation.\n * `preset` is a tool id whose defaults style the markup (e.g.\n * `'highlight'`); defaults to the subtype's own. Returns false (and does\n * nothing) when no selection plugin is installed or nothing is selected.\n */\n markupFromSelection(subtype: Subtype, preset?: string): boolean;\n\n // ── multi-click creation drafts (polygon, polyline, …) ──\n /** Commit the in-progress multi-click creation draft (no-op when there is\n * none, or it can't finish yet — see `creationDraftAnchor().canFinish`). */\n finishCreationDraft(): void;\n /** Discard the in-progress multi-click creation draft. */\n cancelCreationDraft(): 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 /** No-op since whole-document hydration: the model is seeded by\n * `listRawAll()` at document open. Kept as API for layers that call it\n * on page mount. */\n ensurePage(pon: PageObjectNumber): void;\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 // ── whole-document hydration (see the controller in capability.ts) ──\n /** Live hydration status — `loading` covers initial ingest AND a desync\n * re-ingest. */\n hydration(): AnnotationHydration;\n /** Kick hydration exactly once per document; the effects layer calls\n * this at registration. Subsequent calls no-op. */\n ensureHydrated(): void;\n /** Re-run whole-document hydration (desync recovery). Safe to call while\n * one is in flight — the fresh run is chained after it. */\n rehydrate(): Promise<void>;\n /**\n * The effects layer hands every REMOTE `annotation.*` event here: during\n * a hydration window it queues (replayed by audit cursor after ingest —\n * the delete-resurrection guard); otherwise it applies immediately.\n */\n deliverRemoteAnnotationEvent(event: DocumentEvent): 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 / long-press by the interaction edit handler. Returns\n * whether an editable free-text was actually found and opened; false lets\n * the caller fall through to a normal press (so a long-press on a highlight\n * selects it instead of being swallowed by a no-op edit attempt). */\n beginTextEditAt(\n pon: PageObjectNumber,\n point: Vec,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): boolean;\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 /** Widen grab zones to finger-sized targets (pass `pointerType === 'touch'`). */\n touch?: boolean,\n ): 'handle' | 'rotate' | 'group-handle' | 'annot' | 'empty';\n /**\n * TOUCH CONSENT (the interaction hub's `claimsTouch` predicate): should a\n * finger landing here own a TOOL gesture instead of navigating? True over\n * the selection's chrome (resize handles, rotate knob, group box) and over\n * the body of an already-SELECTED, transformable annotation — never over an\n * unselected one, so annotation-dense pages still scroll; tap-select first\n * is the platform convention (Apple Markup). Uses finger-sized grab zones.\n * Pure read.\n */\n claimsTouchAt(\n pon: PageObjectNumber,\n point: Vec,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ): boolean;\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 /** Finger-sized grab zones for the gesture's own hit resolution — pass the\n * sample's `pointerType === 'touch'` so the gesture grabs exactly what\n * {@link claimsTouchAt} claimed. */\n touch?: boolean,\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 /** Commit the strokes currently buffered by an ink tool's grouping window. */\n finishInkDraft(): 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 hint: `add annotationPlugin() from '@embedpdf/plugin-annotation' to your plugins list`,\n});\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, border, and line endings; and their\n * `/EMBD_Metadata/Rotation` is an advisory scalar (the points are already\n * 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/**\n * A lowering whose key is an INPUT of the derived /Rect: the visual bounds\n * ride along with every emission, so a sparse patch can never change an input\n * without re-emitting the derivation. (The bug this kills: patch `lineEndings`\n * alone → the engine re-bakes the /AP inside the stale /Rect → the new\n * arrowhead is clipped in every viewer except the live vector one.)\n */\nconst withRect =\n (lower: (a: Annot, crop: PdfRect) => Wire) =>\n (a: Annot, crop: PdfRect): Wire => ({ ...lower(a, crop), ...visualRect(a, crop) });\n\n/** Stroke-family prop exceptions: width, border, AND line endings feed the\n * derived /Rect — an ending's arrowhead reaches well past the endpoint, and\n * ISO 32000 requires /Rect to enclose it. Where a key can't change the\n * bounds (a line's border restyle), the re-emitted rect is an idempotent\n * no-op — uniformity beats per-case reasoning here. */\nconst strokeProps: KindProjection['prop'] = {\n strokeWidth: withRect((a) => ({ strokeWidth: a.style.strokeWidth })),\n border: withRect((a) => ({ ...borderSlice(a.style), ...polyCloudy(a) })),\n lineEndings: withRect((a) =>\n (a.geom.t === 'line' || a.geom.t === 'poly') && a.geom.ends\n ? { lineEndings: a.geom.ends }\n : {},\n ),\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/** 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 { 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 // Seed /NM on every create: a durable identity that survives save/reload\n // and gives replies and status annotations a stable join key from birth\n // (the engine never auto-stamps on read — creation is the one moment).\n return { ...base, ...extras, nm: crypto.randomUUID(), 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 // The text plate inset MIRRORS the engine's AP generator, so the DOM text\n // sits exactly where the baked text will land (WYSIWYG across the\n // baked↔live swap): callout body = border + 2 (`kCalloutTextPadding`),\n // plain free-text body = border width (two half-width deflates).\n const sw = a?.style.strokeWidth ?? 0;\n const isCallout = a?.geom.t === 'text' && !!a.geom.callout;\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: isCallout ? sw + 2 : sw,\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 * Whether arming this ANNOTATION tool is touch consent (`Tool.touchDirect`):\n * drag-CREATE tools — shape/ink draw and text-markup select — take\n * single-finger touch wholesale (finger draws/marks, two fingers navigate:\n * the drawing-app convention). Click-to-PLACE tools (stamp, note) do not: a\n * tap places without any claim, and drags keep scrolling. Derived from the\n * gesture tags, so custom registered tools inherit the right behavior. Only\n * annotation-owned tools run through this — the built-in `pointer` tool also\n * enables `text-select`, but it is registered by the hub, not here.\n */\nexport const isTouchDirect = (enables: ReadonlySet<string>): boolean =>\n enables.has('annotation-draw') || enables.has('text-select');\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 DocumentEvent,\n type PluginContext,\n} from '@embedpdf/core';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport {\n buildCommentThreads,\n encodeStableIdKey,\n resolveBinarySource,\n sniffBinaryMetadata,\n type CommentThread,\n type AnnotationDraft,\n type AnnotationDTO,\n type AnnotationPatch,\n type AnnotationRef,\n type AttachmentFileSource,\n type BinarySource,\n type PdfLinkTarget,\n type PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport { SelectionToken as SelectionPublicToken } from '@embedpdf/plugin-selection';\nimport {\n canMove,\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 annotContentsEditable,\n annotDeletable,\n annotTransformable,\n isSubstrateOnly,\n linkChildrenOf,\n linkOf,\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 fromDTO,\n linkChildRects,\n refKey,\n toCreateDraft,\n toPatch,\n toScopedPatch,\n writableTarget,\n} from './repository';\nimport { buildTextItems } from './text-item';\nimport { buildToolRegistry, isTouchDirect } from './tools';\nimport type { AnnotationToolInput, ResolvedTool } from './tools';\nimport type {\n AnnotationAction,\n AnnotationConfig,\n AnnotationHostCapability,\n AnnotationHydration,\n AnnotationState,\n ArmedStampPreview,\n CommentPermissions,\n CommentsApi,\n ThreadDeleteResult,\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\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 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 * `boost` widens the GRAB tolerances only (never the drawn chrome or the\n * knob's position) — the touch path passes {@link TOUCH_GRAB_BOOST} so\n * handles present finger-sized targets. */\n const chromeGeomAt = (scale?: number, boost = 1): ChromeGeom => {\n const cs = chromeSettings();\n const s = scale || 1;\n return {\n handleTol: (cs.handles.hitSize / 2 / s) * boost,\n knobTol: (cs.knob.hitSize / 2 / s) * boost,\n knobOffset: cs.knob.offset / s,\n };\n };\n /** Finger-sized grab zones: 2× the mouse tolerances lands a ~24px handle hit\n * box in Apple's ~44pt-target territory without moving any visuals. */\n const TOUCH_GRAB_BOOST = 2;\n const grabBoost = (touch?: boolean): number => (touch ? TOUCH_GRAB_BOOST : 1);\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 // `link` is the one derived value: parents store nothing — the committed\n // children are the truth, read through the lens (the link KIND still\n // reads its own /A off the annot).\n const valueOf = (a: Annot, key: PropKey): unknown =>\n key === 'link' && a.subtype !== 'link' ? linkOf(m, a.id) : readProp(a, key);\n for (const spec of specs) {\n const first = valueOf(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(valueOf(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.subtype !== 'link') continue;\n if (!viewable(a.flags, false)) continue; // hidden links don't navigate\n // Standalone links carry their own model `link` (/A); attached children\n // carry the target on their DTO. Rects are the CHILD's own committed\n // geometry — anchors render only in view contexts, where nothing is\n // mid-gesture, so no live parent-derivation is needed.\n const target =\n a.link ?? (a.data?.subtype === 'link' ? (a.data.target ?? null) : null);\n if (target == null || a.geom.t !== 'rect') continue;\n v.push({ id, rect: a.geom.rect, target, attached: a.group !== undefined });\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: [ingestDTO(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 // ── whole-document hydration ──────────────────────────────────────────\n // The plugin ALWAYS hydrates every page via `listRawAll()` — one bulk\n // request on cloud, one raw worker job locally. A comments sidebar needs\n // every page, and per-page lazy loading could never truthfully claim\n // completeness. Coherence protocol: the snapshot arrives cursor-stamped\n // (`auditHead`); remote annotation events arriving DURING the hydration\n // window queue here and replay by cursor after ingest — events with\n // `serverId <= auditHead` are already inside the snapshot and drop,\n // newer ones apply on top. This makes the delete-during-hydrate\n // resurrection structurally impossible. `stream.desynced` re-runs the\n // same ingest with `bumpAp` (rasters may have changed invisibly inside\n // the gap).\n let hydrationStarted = false;\n let hydrationWindow = false;\n let hydrationRunning: Promise<void> | null = null;\n let hydrateAgain = false;\n const pendingRemote: DocumentEvent[] = [];\n\n const setHydration = (hydration: AnnotationHydration): void =>\n ctx.dispatch({ type: 'SET_HYDRATION', hydration });\n\n const ingestSnapshot = (\n snap: Awaited<ReturnType<NonNullable<typeof ctx.doc>['annotations']['listRawAll']>>,\n bumpAp: boolean,\n ): void => {\n const annots: Annot[] = [];\n for (const page of snap.pages) {\n const crop = cropOf(page.pageState.pageObjectNumber);\n if (!crop) continue;\n // Children (replies, states, attached links) enter the substrate as\n // first-class annots; the planes derive (paint cull + lenses).\n annots.push(...page.annotations.map((d) => ingestDTO(d, crop)));\n }\n apply({ t: 'hydrated', annots, bumpAp });\n };\n\n const canRead = (): boolean => ctx.doc?.security.allows('doc.annotate.read') ?? true;\n\n const runHydration = (bumpAp: boolean): Promise<void> => {\n const doc = ctx.doc;\n if (!doc) return Promise.resolve();\n // No read grant → no doomed listRawAll: the state says so, the comments\n // panel hides, and a later rehydrate (e.g. post-/access) re-checks.\n if (!canRead()) {\n setHydration({ status: 'forbidden' });\n return Promise.resolve();\n }\n hydrationWindow = true;\n setHydration({ status: 'loading' });\n const run = doc.annotations\n .listRawAll()\n .then((snap) => {\n ingestSnapshot(snap, bumpAp);\n const head = snap.auditHead;\n const queued = pendingRemote.splice(0);\n hydrationWindow = false;\n for (const event of queued) {\n const serverId = 'origin' in event ? event.origin.serverId : null;\n // ≤ auditHead ⇒ already inside the snapshot; drop. Absent head =\n // a local engine, which has no remote events anyway.\n if (head !== undefined && serverId !== null && serverId <= head) continue;\n applyRemoteAnnotationEvent(event);\n }\n setHydration({ status: 'complete' });\n })\n .catch((error: unknown) => {\n // Degrade to live-only: queued and future events apply directly so\n // the view stays as correct as it can be until a rehydrate lands.\n hydrationWindow = false;\n for (const event of pendingRemote.splice(0)) applyRemoteAnnotationEvent(event);\n setHydration({ status: 'error', error });\n })\n .finally(() => {\n hydrationRunning = null;\n if (hydrateAgain) {\n hydrateAgain = false;\n hydrationRunning = runHydration(true);\n }\n });\n hydrationRunning = run;\n return run;\n };\n\n const rehydrate = (): Promise<void> => {\n if (hydrationRunning) {\n // A desync during an in-flight hydration: that snapshot may already\n // be stale — run once more after it settles.\n hydrateAgain = true;\n return hydrationRunning;\n }\n hydrationRunning = runHydration(true);\n return hydrationRunning;\n };\n\n /**\n * Fold one REMOTE annotation event into the model (transplanted from the\n * effects layer so hydration can queue + replay through the same code\n * path). `bump` re-fetches rasters, `keep` doesn't — driven by the\n * ENGINE'S appearance echo riding the event, so a remote MOVE costs\n * peers zero re-renders while a remote restyle refreshes exactly once.\n */\n const upsertRemote = (\n dtos: ReadonlyArray<Parameters<typeof fromDTO>[0]>,\n bumpAp: boolean,\n ): void => {\n const bump: Annot[] = [];\n const keep: Annot[] = [];\n for (const dto of dtos) {\n const crop = cropOf(dto.pageObjectNumber);\n if (!crop) continue;\n // Another session authored this — trust the engine's baked AP.\n const a = ingestDTO(dto, crop, 'baked');\n // Substrate-only annotations (replies, review states, attached link\n // children) never paint, so their arrival must not trigger a raster\n // fetch or epoch churn. A remote link child is just an upsert — the\n // `linkOf` lens re-derives the parent's value on the next read.\n (bumpAp && !isSubstrateOnly(a) ? bump : keep).push(a);\n }\n if (bump.length) apply({ t: 'upsert', annots: bump, bumpAp: true });\n if (keep.length) apply({ t: 'upsert', annots: keep });\n };\n\n const applyRemoteAnnotationEvent = (event: DocumentEvent): void => {\n switch (event.type) {\n case 'annotation.created':\n // A create ships with a freshly baked /AP — fetch it.\n upsertRemote([event.created], true);\n break;\n case 'annotation.updated':\n // The engine's verdict rides the event: preserved moves keep the\n // cached raster, regenerated appearances re-fetch exactly once.\n upsertRemote([event.updated], event.appearance.changed);\n break;\n case 'annotation.moved':\n // A z-order move never touches /AP.\n upsertRemote(event.moved, false);\n break;\n case 'annotation.deleted':\n if (event.deleted) {\n const key = encodeStableIdKey(event.deleted);\n // Attached link children are model annotations, so a remote child\n // delete is this same plain remove — the `linkOf` lens re-derives.\n if (model().byId[key]) apply({ t: 'remove', ids: [key] });\n }\n break;\n default:\n break;\n }\n };\n\n // ── the comments lens (the conversation plane's surface) ──────────────\n // A derived, memoized threads index over the substrate. Because every\n // path — optimistic writes, engine confirms, remote events, hydration —\n // lands in the model, the sidebar updates with zero extra wiring. The\n // memo keys on the model's annotation content (byId/order — hover and\n // drafts don't invalidate) PLUS the layout (display order is computed\n // fresh against the live pages) and the session identity.\n\n const currentUserId = (): string | undefined => ctx.doc?.security.identity?.user_id;\n\n interface ThreadsIndex {\n threads: CommentThread[];\n byMember: Map<Id, CommentThread>;\n }\n let threadsMemo:\n | (ThreadsIndex & {\n byId: Model['byId'];\n order: Model['order'];\n layout: string;\n userId: string | undefined;\n })\n | null = null;\n\n /** Value-stable layout key: display order is all the sort consumes, so\n * the memo must survive hosts that rebuild the pages array per read. */\n const layoutSignature = (): string =>\n (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber).join(',');\n\n const computeThreadsIndex = (): ThreadsIndex => {\n const m = model();\n // Committed truth only: optimistic tmp drafts have no DTO yet and join\n // the index when their create confirms.\n const dtos: AnnotationDTO[] = [];\n for (const id of m.order) {\n const data = m.byId[id]?.data;\n if (data) dtos.push(data);\n }\n const threads = buildCommentThreads(dtos, { currentUserId: currentUserId() });\n\n // Display order: page position first (live layout), then top of page\n // (PDF user space is y-up — larger `top` sits higher), then creation.\n const pages = ctx.document()?.pages ?? [];\n const displayIndex = new Map(pages.map((p, i) => [p.pageObjectNumber, i]));\n threads.sort((a, b) => {\n const pa = displayIndex.get(a.pageObjectNumber) ?? Number.MAX_SAFE_INTEGER;\n const pb = displayIndex.get(b.pageObjectNumber) ?? Number.MAX_SAFE_INTEGER;\n if (pa !== pb) return pa - pb;\n if (a.root.rect.top !== b.root.rect.top) return b.root.rect.top - a.root.rect.top;\n const ca = a.root.created ?? '';\n const cb = b.root.created ?? '';\n return ca < cb ? -1 : ca > cb ? 1 : 0;\n });\n\n const byMember = new Map<Id, CommentThread>();\n for (const t of threads) {\n byMember.set(refKey(t.root.ref), t);\n for (const r of t.replies) byMember.set(refKey(r.ref), t);\n for (const g of t.groupedParts) byMember.set(refKey(g.ref), t);\n for (const s of t.review.statusRefs) byMember.set(refKey(s), t);\n }\n return { threads, byMember };\n };\n\n const threadsIndex = (): ThreadsIndex => {\n const m = model();\n const layout = layoutSignature();\n const userId = currentUserId();\n if (\n threadsMemo &&\n threadsMemo.byId === m.byId &&\n threadsMemo.order === m.order &&\n threadsMemo.layout === layout &&\n threadsMemo.userId === userId\n ) {\n return threadsMemo;\n }\n threadsMemo = { ...computeThreadsIndex(), byId: m.byId, order: m.order, layout, userId };\n return threadsMemo;\n };\n\n const threadOf = (ref: AnnotationRef): CommentThread => {\n const t = threadsIndex().byMember.get(refKey(ref));\n if (!t) throw new Error('[annotation] no comment thread contains this ref');\n return t;\n };\n\n /** Engine create + model sync for conversation-plane annotations (they\n * never paint, so the render source is immaterial — 'baked' avoids any\n * vector-scene work). */\n const createConversationAnnot = async (\n pon: number,\n draft: AnnotationDraft,\n ): Promise<AnnotationDTO> => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n const res = await doc.page(pon).annotations.create(draft);\n syncDTO(res.created, 'baked');\n return res.created;\n };\n\n const deleteOne = async (ref: AnnotationRef): Promise<void> => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[annotation] no document bound');\n await doc.page(ref.pageObjectNumber).annotations.delete(ref);\n apply({ t: 'remove', ids: [refKey(ref)] });\n };\n\n // Screen-anchored like a sticky note; `print` for Acrobat parity.\n const REPLY_FLAGS = { print: true, noZoom: true, noRotate: true };\n // Status annotations are metadata: hidden everywhere (our paint plane\n // culls them regardless; `hidden` keeps foreign viewers from drawing an\n // icon). Phase 0 golden fixtures may refine this convention.\n const STATUS_FLAGS = { hidden: true, noZoom: true, noRotate: true };\n\n /** Coarse authority mirror (doc.annotate.modify) — B3 replaces this with\n * the collab-scope mirrors; the FLAG split is already the real rule. */\n // ── authorization: the engine's own collab resolver, mirrored ──\n // `allowsAnnotationMutation` asks about the TARGET's stamped owner,\n // built from the record's EMBD metadata. An unstamped record yields\n // `{}`, which any narrowed grant denies — matching the engine, so a\n // control gated here never disagrees with the write's outcome.\n const mutationTarget = (ref: AnnotationRef): { userId?: string; groupId?: string } => {\n const d = model().byId[refKey(ref)]?.data;\n return {\n ...(d?.userId !== undefined ? { userId: d.userId } : {}),\n ...(d?.groupId !== undefined ? { groupId: d.groupId } : {}),\n };\n };\n const allowsCreate = (): boolean => ctx.doc?.security.allowsAnnotationCreate() ?? false;\n\n /**\n * Ingest an engine DTO with this session's per-record AUTHORITY projected\n * onto it (permissions.md) — asked of the SAME mirrors the server enforces\n * with, against the record's stamped owner. Fused into\n * `annotTransformable`/`annotDeletable`, so hit-test, chrome, props and\n * delete all agree with the engine by construction. No security context\n * (bare local engines, tests) → unstamped → allowed; the engine enforces.\n */\n const ingestDTO = (\n dto: Parameters<typeof fromDTO>[0],\n crop: PdfRect,\n source?: Parameters<typeof fromDTO>[2],\n ): Annot => {\n const a = fromDTO(dto, crop, source);\n const sec = ctx.doc?.security;\n if (!sec) return a;\n const target = {\n ...(dto.userId !== undefined ? { userId: dto.userId } : {}),\n ...(dto.groupId !== undefined ? { groupId: dto.groupId } : {}),\n };\n return {\n ...a,\n authority: {\n update: sec.allowsAnnotationMutation('update', target),\n delete: sec.allowsAnnotationMutation('delete', target),\n },\n };\n };\n const allowsMutation = (action: 'update' | 'delete', ref: AnnotationRef): boolean =>\n ctx.doc?.security.allowsAnnotationMutation(action, mutationTarget(ref)) ?? false;\n const deletableOne = (ref: AnnotationRef): boolean => {\n const a = model().byId[refKey(ref)];\n return !!a && annotDeletable(a);\n };\n const threadMemberRefs = (t: CommentThread): AnnotationRef[] => [\n ...t.replies.map((r) => r.ref),\n ...t.groupedParts.map((g) => g.ref),\n ...t.review.statusRefs,\n t.root.ref, // root LAST — children first keeps foreign readers coherent\n ];\n\n const comments: CommentsApi = {\n threads: () => threadsIndex().threads,\n thread: (ref) => threadsIndex().byMember.get(refKey(ref)) ?? null,\n hydration: () => ctx.getState().hydration,\n rehydrate,\n\n reply: async (ref, text) => {\n const t = threadOf(ref);\n const created = await createConversationAnnot(t.pageObjectNumber, {\n subtype: 'text',\n rect: t.root.rect,\n icon: 'comment',\n contents: text,\n inReplyTo: t.root.ref,\n flags: { ...REPLY_FLAGS },\n } as AnnotationDraft);\n return created.ref;\n },\n\n edit: async (ref, text) => {\n const subtype = model().byId[refKey(ref)]?.data?.subtype;\n if (!subtype) throw new Error('[annotation] cannot edit an uncommitted annotation');\n await updateOne(ref, { subtype, contents: text } as AnnotationPatch);\n },\n\n setStatus: async (ref, state) => {\n const t = threadOf(ref);\n const userId = currentUserId();\n // ISO chain: reply to the caller's previous state annotation when one\n // exists, else to the root. Readers everywhere (ours included) accept\n // both shapes.\n const previous = userId ? t.review.byReviewer[userId] : undefined;\n await createConversationAnnot(t.pageObjectNumber, {\n subtype: 'text',\n rect: t.root.rect,\n inReplyTo: previous?.ref ?? t.root.ref,\n state,\n stateModel: 'review',\n flags: { ...STATUS_FLAGS },\n } as AnnotationDraft);\n },\n\n setMarked: async (ref, marked) => {\n const t = threadOf(ref);\n await createConversationAnnot(t.pageObjectNumber, {\n subtype: 'text',\n rect: t.root.rect,\n inReplyTo: t.root.ref,\n state: marked ? 'marked' : 'unmarked',\n stateModel: 'marked',\n flags: { ...STATUS_FLAGS },\n } as AnnotationDraft);\n },\n\n remove: deleteOne,\n\n removeThread: async (ref): Promise<ThreadDeleteResult> => {\n const t = threadOf(ref);\n const members = threadMemberRefs(t);\n // Preflight: all-or-nothing. A blocked member means NOTHING deletes —\n // a half-deleted thread orphans replies in every other viewer.\n const blocked = members.filter((r) => !deletableOne(r));\n if (blocked.length > 0) {\n return {\n deleted: [],\n failed: blocked.map((r) => ({ ref: r, error: new Error('delete not permitted') })),\n };\n }\n const deleted: AnnotationRef[] = [];\n const failed: ThreadDeleteResult['failed'] = [];\n for (const member of members) {\n // A child failure (a race: someone else acted first) stops the\n // cascade before the root, so nothing orphans.\n if (failed.length > 0) break;\n try {\n await deleteOne(member);\n deleted.push(member);\n } catch (error) {\n failed.push({ ref: member, error });\n }\n }\n return { deleted, failed };\n },\n\n permissionsFor: (ref): CommentPermissions => {\n const flags = model().byId[refKey(ref)]?.flags;\n const t = threadsIndex().byMember.get(refKey(ref)) ?? null;\n return {\n // Replying and setting status CREATE new annotations — gated on\n // the caller's own identity, not the target's owner.\n canReply: allowsCreate(),\n canSetStatus: allowsCreate(),\n canEditText: (() => {\n const a = model().byId[refKey(ref)];\n return !!a && annotContentsEditable(a);\n })(),\n canDelete: deletableOne(ref),\n canDeleteThread: t !== null && threadMemberRefs(t).every(deletableOne),\n };\n },\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 /**\n * Queue a reconcile. `intent` is either an explicit target (a set/clear —\n * captured by THIS run's closure, so chained sets stay latest-wins) or\n * `'keep'` (a geometry follow: re-rect the children toward whatever target\n * the substrate holds AT RUN TIME — so a remote retarget is never undone\n * by a local move). Returns the chain, so `links.set()` can await commit.\n */\n const scheduleLinkSync = (id: Id, intent: { target: PdfLinkTarget | null } | 'keep'): Promise<void> => {\n const prev = linkSyncChains.get(id) ?? Promise.resolve();\n const next = prev.then(() =>\n reconcileLinkChildren(id, intent === 'keep' ? linkOf(model(), id) : intent.target),\n );\n linkSyncChains.set(id, next);\n void next.finally(() => {\n if (linkSyncChains.get(id) === next) linkSyncChains.delete(id);\n });\n return next;\n };\n\n /**\n * THE one place attached link children are created, retargeted, re-rected,\n * or deleted. Declarative: desired state = `desired` target + the parent's\n * committed geometry (`linkChildRects`); CURRENT state is read straight\n * from the substrate (`linkChildrenOf`) — no join-key ledger. Results land\n * as ordinary substrate upserts/removes, so the `linkOf` lens converges\n * immediately locally and via events everywhere else. Idempotent — foreign\n * inconsistencies heal on the next local edit.\n */\n const reconcileLinkChildren = async (id: Id, desired: PdfLinkTarget | null): 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(desired);\n const rects = desired == null ? [] : linkChildRects(a).map((r) => contentToPdfRect(r, crop));\n const current = linkChildrenOf(model(), id);\n try {\n const paired = Math.min(current.length, rects.length);\n for (let i = 0; i < paired; i++) {\n const ref = current[i].ref;\n if (!ref) continue;\n const res = await page.annotations.update(ref, {\n subtype: 'link',\n rect: rects[i],\n ...(target ? { target } : {}),\n });\n apply({ t: 'upsert', annots: [ingestDTO(res.updated, crop, 'baked')] });\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 apply({ t: 'upsert', annots: [ingestDTO(res.created, crop, 'baked')] });\n }\n for (let i = rects.length; i < current.length; i++) {\n const child = current[i];\n if (child.ref) await page.annotations.delete(child.ref);\n apply({ t: 'remove', ids: [child.id] });\n }\n } catch (err) {\n console.error('[annotation] attached-link sync failed:', err);\n }\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 (linkChildrenOf(model(), fx.id).length)\n void scheduleLinkSync(fx.id, 'keep');\n },\n // A refused write (a race, a stale /access) must not leave the\n // optimistic patch as a lie. The effect runs AFTER the reducer\n // applied it, so the pre-image is the annot's own canonical DTO —\n // the last COMMITTED truth — re-ingested with fresh authority.\n () => {\n if (a.data && crop) apply({ t: 'upsert', annots: [ingestDTO(a.data, crop, a.source)] });\n },\n );\n } else if (fx.fx === 'syncLink') {\n void scheduleLinkSync(fx.id, { target: fx.target });\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({\n id: resolved.id,\n cursor: resolved.cursor,\n enables: resolved.enables,\n touchDirect: isTouchDirect(resolved.enables),\n });\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: per-record mirrors of the engine's collab\n // resolver. `canCreate` asks about the caller's own identity;\n // `canEdit`/`canDelete` about the target's stamped owner. Pure\n // authority — aspect-specific flag gates (`locked` for geometry\n // and delete, `lockedContents` for text) live with the surfaces\n // that touch that aspect (comments.permissionsFor, interaction).\n canRead: () => canRead(),\n canCreate: () => allowsCreate(),\n // The twins answer \"would the verb succeed?\" — authority AND flags, via\n // the SAME fused predicates the gestures and chrome consume, so a false\n // twin and a bare-outline render can never disagree (permissions.md).\n canEdit: (ref) => {\n const a = model().byId[refKey(ref)];\n return !!a && annotTransformable(a);\n },\n canDelete: (ref) => {\n const a = model().byId[refKey(ref)];\n return !!a && annotDeletable(a);\n },\n\n comments,\n\n links: {\n of: (ref) => {\n const a = model().byId[refKey(ref)];\n if (!a) return null;\n return a.subtype === 'link' ? (a.link ?? null) : linkOf(model(), a.id);\n },\n // The verbs go straight to the reconciler chain (latest-wins per\n // parent) and resolve when the children are COMMITTED — `of` reads\n // the new value the moment the promise settles.\n set: (ref, target) => scheduleLinkSync(refKey(ref), { target }),\n clear: (ref) => scheduleLinkSync(refKey(ref), { target: null }),\n },\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, touch) =>\n hitTest(\n model(),\n pon,\n point,\n chromeGeomAt(scale, grabBoost(touch)),\n model().hitMargin,\n pageBoxOf(pon),\n inertIdsAt(pon),\n viewEnv(zoom, rotation),\n ).t,\n claimsTouchAt: (pon, point, scale, rotation, zoom) => {\n const m = model();\n const t = hitTest(\n m,\n pon,\n point,\n chromeGeomAt(scale, TOUCH_GRAB_BOOST),\n m.hitMargin,\n pageBoxOf(pon),\n inertIdsAt(pon),\n viewEnv(zoom, rotation),\n );\n // Selection chrome only exists FOR the selection — always a claim (the\n // hit-tester already suppresses handles on kinds/states that can't\n // resize or rotate).\n if (t.t === 'handle' || t.t === 'rotate' || t.t === 'group-handle') return true;\n // A body claims only when a drag would actually ARM A MOVE — mirror the\n // core's edit-down exactly (update.ts editPointer: a hit on a selected\n // member moves the WHOLE selection only if every member canMove). A\n // selected highlight/caret (selectable, not movable) and a locked\n // annotation must keep scrolling, never eat the drag into a dead zone.\n if (t.t === 'annot') {\n return m.selected.includes(t.id) && m.selected.every((id) => canMove(m, id));\n }\n return false;\n },\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 // Conversation-plane annotations never paint — a remote reply or\n // status change must not churn the page's raster cache key.\n if (isSubstrateOnly(a)) 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, touch) =>\n apply({\n t: 'editPointer',\n phase,\n in: {\n pon,\n point,\n shift,\n pageBox: pageBoxOf(pon),\n // Touch grabs with the same widened zones the claim used, so the\n // gesture picks up exactly what claimsTouchAt said it would.\n chrome: chromeGeomAt(scale, grabBoost(touch)),\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 // No create authority → creation gestures are inert: no ghost, no\n // draft, no doomed 403. The engine enforces; this keeps pixels honest.\n if (!allowsCreate()) return;\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 markupFromSelection: (subtype, preset) => {\n // One-shot form of the markup tools' commit: selection quads → one\n // markup per page → clear. Selection is an OPTIONAL peer — resolve\n // lazily so annotation keeps working without it installed.\n if (!allowsCreate()) return false;\n const selection = ctx.tryGet(SelectionPublicToken);\n if (!selection || !selection.hasSelection()) return false;\n const snapshot = selection.snapshot();\n let created = false;\n for (const page of snapshot.pages) {\n if (!page.segments.length) continue;\n apply({\n t: 'createMarkup',\n subtype,\n pon: page.pon,\n quads: page.segments.map((s) => s.quad),\n preset,\n flags: preset ? registry.get(preset)?.flags : undefined,\n });\n created = true;\n }\n if (created) selection.clear();\n return created;\n },\n createMarkup: (subtype, pon, quads, preset) => {\n // Optimistic create — the same self-refusal `createPointer` has.\n if (!allowsCreate()) return;\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 },\n createCaret: (pon, anchor) => {\n if (!allowsCreate()) return;\n apply({ t: 'createCaret', pon, anchor });\n },\n createReplaceText: (pon, quads, anchor, preset) => {\n if (!allowsCreate()) return;\n apply({ t: 'createReplaceText', pon, quads, anchor, preset });\n },\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 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 // Grouping WRITES a relationship onto every member — each must\n // pass the per-record update check.\n if (!members.every((a) => a.ref != null && allowsMutation('update', a.ref))) 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 const m = model();\n // Ungrouping clears the relationship on every member of every\n // selected group — same per-record write gate as `ungroup` hits.\n const subs = expandGroups(m, m.selected)\n .map((id) => m.byId[id])\n .filter((a): a is Annot => !!a && !!a.group);\n return subs.length > 0 && subs.every((a) => a.ref != null && allowsMutation('update', a.ref));\n },\n\n // Whole-document hydration supersedes per-page loading: the model is\n // seeded by `listRawAll()` at document open (see `ensureHydrated`), so\n // a page mount has nothing to fetch. Kept as API for layers/plugins\n // that call it on mount; appearance fetching stays per-page/viewport.\n ensurePage: () => {},\n\n reloadPage: async (pon) => {\n const doc = ctx.doc;\n const crop = cropOf(pon);\n if (!doc || !crop) return;\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({ t: 'loaded', annots: snap.annotations.map((d) => ingestDTO(d, crop)) });\n } catch {\n // A failed reload leaves the previous view; the next event or a\n // rehydrate reconciles.\n }\n },\n\n hydration: () => ctx.getState().hydration,\n ensureHydrated: () => {\n if (hydrationStarted) return;\n hydrationStarted = true;\n void runHydration(false);\n },\n rehydrate,\n deliverRemoteAnnotationEvent: (event) => {\n if (hydrationWindow) {\n pendingRemote.push(event);\n return;\n }\n applyRemoteAnnotationEvent(event);\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') {\n apply({ t: 'beginTextEdit', id });\n return true;\n }\n // Nothing editable here — report it so the caller can fall through to a\n // normal press instead of swallowing the gesture on a non-text annotation.\n return false;\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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"}