@embedpdf/plugin-annotation 3.0.0-next.14 → 3.0.0-next.15

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.
Files changed (61) hide show
  1. package/README.md +129 -0
  2. package/dist/authoring.cjs +12 -2
  3. package/dist/authoring.d.cts +2 -2
  4. package/dist/authoring.d.ts +2 -2
  5. package/dist/authoring.js +2 -3
  6. package/dist/contract/host.cjs +18 -2
  7. package/dist/contract/host.d.cts +3 -2
  8. package/dist/contract/host.d.ts +3 -2
  9. package/dist/contract/host.js +3 -2
  10. package/dist/contract-BK4LHe9v.d.cts +1127 -0
  11. package/dist/contract-BOo9iZKo.d.ts +1127 -0
  12. package/dist/contract-CPzpRG3h.cjs +692 -0
  13. package/dist/contract-CPzpRG3h.cjs.map +1 -0
  14. package/dist/contract-b2e_LZvu.js +651 -0
  15. package/dist/contract-b2e_LZvu.js.map +1 -0
  16. package/dist/contract.cjs +11 -10
  17. package/dist/contract.d.cts +2 -3
  18. package/dist/contract.d.ts +2 -3
  19. package/dist/contract.js +2 -4
  20. package/dist/host-contract-BbjhS_Fo.d.ts +310 -0
  21. package/dist/host-contract-CxrQPcPj.js +52 -0
  22. package/dist/host-contract-CxrQPcPj.js.map +1 -0
  23. package/dist/{contract-a4eaQWga.cjs → host-contract-DY9jFPPF.cjs} +36 -16
  24. package/dist/host-contract-DY9jFPPF.cjs.map +1 -0
  25. package/dist/host-contract-Nzxwh0XS.d.cts +310 -0
  26. package/dist/index.cjs +4985 -418
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +12 -17
  29. package/dist/index.d.ts +12 -17
  30. package/dist/index.js +4937 -390
  31. package/dist/index.js.map +1 -1
  32. package/package.json +11 -14
  33. package/dist/authoring-BhtyfsMx.d.cts +0 -37
  34. package/dist/authoring-R4ezdnXd.d.ts +0 -37
  35. package/dist/capability-Bt320iJP.cjs +0 -3249
  36. package/dist/capability-Bt320iJP.cjs.map +0 -1
  37. package/dist/capability-CoL4na7g.js +0 -3226
  38. package/dist/capability-CoL4na7g.js.map +0 -1
  39. package/dist/contract-C7rcuNp_.d.cts +0 -34
  40. package/dist/contract-CM2Ovdq_.d.ts +0 -34
  41. package/dist/contract-DtXE1hjY.js +0 -32
  42. package/dist/contract-DtXE1hjY.js.map +0 -1
  43. package/dist/contract-a4eaQWga.cjs.map +0 -1
  44. package/dist/internal.cjs +0 -8
  45. package/dist/internal.d.cts +0 -14
  46. package/dist/internal.d.ts +0 -14
  47. package/dist/internal.js +0 -5
  48. package/dist/seam-6pJeKOOJ.cjs +0 -296
  49. package/dist/seam-6pJeKOOJ.cjs.map +0 -1
  50. package/dist/seam-C4L_7rDt.js +0 -225
  51. package/dist/seam-C4L_7rDt.js.map +0 -1
  52. package/dist/tools-B3i1gjRs.cjs +0 -589
  53. package/dist/tools-B3i1gjRs.cjs.map +0 -1
  54. package/dist/tools-DsfqBn_a.js +0 -566
  55. package/dist/tools-DsfqBn_a.js.map +0 -1
  56. package/dist/types-BvB1vUKb.js +0 -20
  57. package/dist/types-BvB1vUKb.js.map +0 -1
  58. package/dist/types-ChRnKozg.d.cts +0 -1246
  59. package/dist/types-Dlhdw2k_.cjs +0 -31
  60. package/dist/types-Dlhdw2k_.cjs.map +0 -1
  61. package/dist/types-Dmz3eRSG.d.ts +0 -1246
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["AnnotationToken","AnnotationToken","PublicActionsToken","ActionsHostToken"],"sources":["../src/effects.ts","../src/handler.ts","../src/markup.ts","../src/reducer.ts","../src/annotation.plugin.ts"],"sourcesContent":["/**\n * Makes annotations REACTIVE to the document event stream.\n *\n * Own edits already update the model through the capability's promise path\n * (optimistic draw + re-sync from the engine DTO). This effect wires in\n * everything else:\n *\n * - it kicks whole-document hydration exactly once (`ensureHydrated`);\n * - remote `annotation.*` events are handed to the capability's\n * hydration-aware delivery (queued + cursor-replayed during the\n * hydration window, applied live otherwise);\n * - `stream.desynced` re-runs hydration — the gap's mutations will never\n * arrive as events;\n * - remote page inserts/deletes reconcile the model's page membership;\n * - form and redaction cross-plane events invalidate exactly what they\n * touched, as before.\n */\nimport type { DocumentEvent, EffectContext } from '@embedpdf/core';\nimport { encodeStableIdKey } from '@embedpdf/engine-core/runtime';\nimport { update, type Msg } from '@embedpdf/core-annotation';\n\nimport { AnnotationToken } from './types';\nimport type { AnnotationAction, AnnotationState } from './types';\n\nexport function registerAnnotationEffects(\n ctx: EffectContext<AnnotationState, AnnotationAction>,\n): void {\n const doc = ctx.doc;\n if (!doc) return;\n\n const host = () => ctx.get(AnnotationToken);\n\n const apply = (msg: Msg): void => {\n const [next] = update(ctx.getState().model, msg);\n ctx.dispatch({ type: 'SET_MODEL', model: next });\n };\n\n // Subscribe FIRST, then hydrate: the coherence protocol needs every event\n // from the snapshot's cursor onward to be observed (queued or applied) —\n // a gap between snapshot and stream is exactly the resurrection bug.\n const unsubscribe = doc.events.subscribe((event: DocumentEvent) => {\n // Widget appearances are re-baked by FORM value writes — a plane this\n // plugin doesn't own, so no remote-only filter: direct fills emit\n // `form.valueChanged`, while scripted batches emit `form.effectsApplied`.\n // Neither path touches this model directly. The bump tells the render\n // layer to re-fetch exactly the repainted widgets' rasters.\n if (event.type === 'form.valueChanged' || event.type === 'form.effectsApplied') {\n apply({\n t: 'bumpAp',\n ids: event.changedWidgets\n .filter((w) => w.annotObjectNumber > 0)\n .map((w) => encodeStableIdKey({ kind: 'objectNumber', value: w.annotObjectNumber })),\n });\n return;\n }\n // A field update re-bakes its widgets too — a signature field's visual\n // fill (`forms.setSignatureAppearance`) draws a mark into the widget\n // without a value write, so it arrives as `form.fieldUpdated`.\n if (event.type === 'form.fieldUpdated') {\n apply({\n t: 'bumpAp',\n ids: event.field.widgets\n .filter((w) => w.annotObjectNumber > 0)\n .map((w) => encodeStableIdKey({ kind: 'objectNumber', value: w.annotObjectNumber })),\n });\n return;\n }\n // A completed signature sealed the field with its mark as appearance:\n // repaint that widget. The session also moved to new bytes\n // (`document.versioned` follows); a remote completion arrives as that\n // event alone, so the versioned handler below re-reads the plane.\n if (event.type === 'signature.completed') {\n const widget = event.signature.widget;\n if (widget && widget.annotObjectNumber > 0) {\n apply({\n t: 'bumpAp',\n ids: [encodeStableIdKey({ kind: 'objectNumber', value: widget.annotObjectNumber })],\n });\n }\n return;\n }\n if (event.type === 'document.versioned') {\n void host().rehydrate();\n return;\n }\n // A redaction apply deleted the consumed marks plus every intersecting\n // annotation on the applied pages. ORIGIN-AGNOSTIC: our own applies run\n // through the redaction plugin's doc-level verb, never this plane's\n // capability paths, so the model is stale either way — reload the\n // affected pages from the engine. (Works without plugin-redaction\n // installed: a remote collaborator's apply still reconciles this view.)\n if (event.type === 'redaction.applied') {\n const affected = new Set(\n event.results.filter((r) => r.status === 'applied').map((r) => r.pageObjectNumber),\n );\n if (affected.size) {\n for (const pon of affected) void host().reloadPage(pon);\n }\n return;\n }\n // The live stream fell too far behind to replay — the gap's mutations\n // will NEVER arrive as events, so re-read the whole document.\n if (event.type === 'stream.desynced') {\n void host().rehydrate();\n return;\n }\n // Page membership changed. ORIGIN-AGNOSTIC like redaction: removing a\n // deleted page's annotations twice is a no-op, and reloading an\n // inserted page merges idempotently — correct whether the op was ours\n // or a collaborator's.\n if (event.type === 'pages.deleted') {\n const gone = new Set<number>(event.pageObjectNumbers);\n const m = ctx.getState().model;\n const ids = m.order.filter((id) => {\n const a = m.byId[id];\n return a !== undefined && gone.has(a.pon);\n });\n if (ids.length) apply({ t: 'remove', ids });\n return;\n }\n if (event.type === 'pages.inserted') {\n // A fresh page usually has no annotations, but an insert-from-bytes\n // can carry them. `reloadPage` no-ops harmlessly if the layout for\n // the new page hasn't landed in core state yet (crop unknown).\n for (const pon of event.insertedPageObjectNumbers) void host().reloadPage(pon);\n return;\n }\n // Only fold in OTHER sessions' edits; our own flow through the capability.\n if (!('origin' in event) || event.origin.kind !== 'remote') return;\n switch (event.type) {\n case 'annotation.created':\n case 'annotation.updated':\n case 'annotation.moved':\n case 'annotation.deleted':\n host().deliverRemoteAnnotationEvent(event);\n break;\n default:\n break;\n }\n });\n ctx.cleanup(unsubscribe);\n\n host().ensureHydrated();\n}\n","import type {\n InteractionCapability,\n InteractionHandler,\n PointerSample,\n} from '@embedpdf/plugin-interaction/contract';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport type { Subtype, Vec } from '@embedpdf/core-annotation';\nimport type { AnnotationHostCapability } from './types';\nimport {\n ANNOTATION_DRAW_PRIORITY,\n ANNOTATION_EDIT_PRIORITY,\n ANNOTATION_GHOST_PRIORITY,\n ANNOTATION_MARQUEE_PRIORITY,\n ANNOTATION_PLACE_PRIORITY,\n} from './priorities';\n\nconst MARQUEE_DRAG_THRESHOLD_PX = 4;\nconst isPolyTool = (subtype: Subtype): boolean => subtype === 'polygon' || subtype === 'polyline';\nconst isCalloutTool = (subtype: Subtype): boolean => subtype === 'free-text-callout';\n\n/**\n * Resolve a sample against a gesture's HOME page. Annotation gestures are\n * page-anchored: they track the page they started on, even when the cursor\n * wanders off it — `s.page` re-resolves per event (a page-2 point is a\n * DIFFERENT coordinate frame, the teleport bug), so prefer the source's\n * unclamped projection and fall back to the page hit only when it's the same\n * page. Null → this sample can't speak for the home page; ignore it.\n */\nconst pointOn = (s: PointerSample, pon: number): Vec | null =>\n s.project?.(pon) ?? (s.page?.pon === pon ? s.page.point : null);\n\n/**\n * Click-to-place for every payload-carrying tool (stamp / note / file\n * attachment). Each click places one annotation centred on the point (the\n * tool stays active for repeat placement — v2 rubber-stamp behaviour); the\n * capability's `placeAt` routes by the active tool's kind: armed stamp bytes,\n * a stamp/attachment prompt (pick the spot first, the payload second), or an\n * immediate note. No drag gesture — placement size comes from the content\n * (stamp aspect / the fixed icon box), not the pointer.\n *\n * Priority is deliberately BELOW the edit handler (100): a click over an\n * EXISTING annotation selects it; placement happens on empty page space.\n */\nexport function createPlaceHandler(anno: AnnotationHostCapability): InteractionHandler {\n return {\n id: 'annotation-place',\n // `annotation-stamp` is honoured as a legacy alias for embedder tool\n // configs written before the tags were unified.\n priority: ANNOTATION_PLACE_PRIORITY,\n enabledFor: (t) => t.enables.has('annotation-place') || t.enables.has('annotation-stamp'),\n onDown: (s) => {\n if (!s.page) return false;\n // The click sample's display rotation drives the tool's `upright` policy —\n // the placement lands reading horizontally on a rotated page/view.\n return anno.placeAt(s.page.pon, s.page.point, s.page.rotation);\n },\n };\n}\n\n/**\n * The armed tool's FOOTPRINT ghost: every hover re-computes the would-be\n * placement under the cursor (stamp image fit / click-create default geometry);\n * off-page clears it. One handler for every tool — `ghostHoverAt` resolves the\n * tool's ghost policy and clears when it isn't `footprint`. Never captures:\n * the highest priority makes its onDown run FIRST on every press (hiding the\n * ghost while a gesture runs), then declines so the real handlers route.\n */\nexport function createGhostHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionCapability,\n): InteractionHandler {\n const hover = (s: PointerSample): void => {\n if (s.page)\n anno.ghostHoverAt(interaction.activeToolId(), s.page.pon, s.page.point, s.page.rotation);\n else anno.clearGhost();\n };\n return {\n id: 'annotation-ghost',\n priority: ANNOTATION_GHOST_PRIORITY,\n enabledFor: () => true,\n onDown: () => {\n anno.clearGhost();\n return false;\n },\n onHover: hover,\n };\n}\n\n/**\n * Ambient editing: live under the `annotation-edit` tag, which BOTH the pointer\n * and pan tools enable — so you select/move/resize in any navigation mode (Adobe\n * behaviour). It captures only over an annotation/handle; over empty it\n * deselects and declines (so text-selection / pan still work). Hover drives the\n * cursor (move / pointer / resize) via a priority cursor claim.\n */\nexport function createEditHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionCapability,\n): InteractionHandler {\n // The gesture's home page + last resolved point, armed on down. Every\n // move/up resolves against THIS page (the annotation slides along its edge\n // when the cursor overshoots — the core clamps), never against whatever\n // page the sample happens to hit. `downPoint` keeps the untouched origin so\n // an aborted gesture (second finger → pinch) can REVERT instead of leaving\n // the annotation half-moved. `touch` rides the whole gesture so every phase\n // grabs with the same finger-sized zones the down resolved with.\n let origin: { pon: number; point: Vec; downPoint: Vec; touch: boolean } | null = null;\n return {\n id: 'annotation-edit',\n priority: ANNOTATION_EDIT_PRIORITY,\n enabledFor: (t) => t.enables.has('annotation-edit'),\n // Touch consent: a finger owns a tool drag only over the selection's own\n // chrome or a selected annotation's body (see claimsTouchAt) — unselected\n // bodies keep scrolling, matching the Markup convention.\n claimsTouch: (s) =>\n !!s.page &&\n anno.claimsTouchAt(s.page.pon, s.page.point, s.page.scale, s.page.rotation, s.page.zoom),\n onDown: (s) => {\n if (!s.page) return false;\n // The final distance-placement click belongs to its creation draft even\n // when it lands over an existing annotation.\n if (anno.distanceCreationPage?.() != null) return false;\n const touch = s.pointerType === 'touch';\n // While a free-text box is being edited it owns its own pointer events, so a\n // down that reaches the hub at all is a click OUTSIDE the editor — commit and\n // leave text edit. This makes exit hub-driven (deterministic) rather than\n // relying on a DOM blur, which races the focus-steal of the entering gesture.\n const wasEditing = anno.currentEditing() != null;\n if (wasEditing) anno.endTextEdit();\n if (\n anno.hitKind(\n s.page.pon,\n s.page.point,\n s.page.scale,\n s.page.rotation,\n s.page.zoom,\n touch,\n ) === 'empty'\n ) {\n // Plain empty click drops the selection. Shift-empty preserves it so the\n // lower-priority marquee handler can additive/toggle-select.\n if (!s.modifiers.shift) anno.deselect();\n // A click that dismissed an active edit is CONSUMED: its sole job was to\n // leave edit mode, so the draw tool doesn't also spawn a new annotation\n // (matches v2). Only when nothing was being edited do we decline, letting\n // pan / text-selection / draw act on the empty click.\n return wasEditing;\n }\n // Double-click / long-press over a FREE-TEXT box → enter text edit (not\n // a move). Over any other annotation the attempt reports false and the\n // press falls through to the normal path below (select / arm a move) —\n // so a long-press on a highlight selects it instead of the gesture\n // being swallowed by a no-op edit attempt.\n if ((s.clickCount ?? 1) >= 2) {\n if (\n anno.beginTextEditAt(s.page.pon, s.page.point, s.page.scale, s.page.rotation, s.page.zoom)\n ) {\n return true;\n }\n }\n anno.editPointer(\n 'down',\n s.page.pon,\n s.page.point,\n s.modifiers.shift,\n s.page.scale,\n s.page.rotation,\n s.page.zoom,\n touch,\n );\n origin = { pon: s.page.pon, point: s.page.point, downPoint: s.page.point, touch };\n return true;\n },\n onMove: (s) => {\n if (!origin) return;\n const point = pointOn(s, origin.pon);\n if (!point) return;\n origin.point = point;\n // The sample's scale/rotation ride along (uniform across pages), so a\n // screen-anchored member page-clamps at its effective footprint mid-drag.\n anno.editPointer(\n 'move',\n origin.pon,\n point,\n s.modifiers.shift,\n s.page?.scale,\n s.page?.rotation,\n s.page?.zoom,\n origin.touch,\n );\n },\n onUp: (s) => {\n if (!origin) return;\n // ALWAYS close the gesture — a release over a page gap or outside the\n // window must still commit (a dangling draft leaves a ghost that snaps\n // back on the next interaction). `editUp` doesn't read the point.\n anno.editPointer(\n 'up',\n origin.pon,\n pointOn(s, origin.pon) ?? origin.point,\n false,\n undefined,\n undefined,\n undefined,\n origin.touch,\n );\n origin = null;\n },\n onCancel: () => {\n if (!origin) return;\n // Aborted (second finger → pinch): REVERT, don't commit — replay the\n // gesture back to its own down point (every transform is delta-from-\n // down, so this restores the original geometry), then close it there.\n const { pon, downPoint, touch } = origin;\n origin = null;\n anno.editPointer('move', pon, downPoint, false, undefined, undefined, undefined, touch);\n anno.editPointer('up', pon, downPoint, false, undefined, undefined, undefined, touch);\n },\n onHover: (s) => {\n // priority 20 → beats text-select's 'text' (10) over an annotation; null clears.\n interaction.setCursor(\n 'annotation',\n s.page\n ? anno.cursorAt(s.page.pon, s.page.point, s.page.scale, s.page.rotation, s.page.zoom)\n : null,\n 20,\n );\n // Hover state for scene affordances (redact preview) — rides the same\n // per-move sample; the capability dispatches on change only.\n anno.hoverAt(\n s.page\n ? {\n pon: s.page.pon,\n point: s.page.point,\n scale: s.page.scale,\n rotation: s.page.rotation,\n zoom: s.page.zoom,\n }\n : null,\n );\n },\n };\n}\n\n/**\n * Empty-page drag selection. Lower priority than annotation edit and text\n * selection, so it only owns drags that begin on empty, non-text page space.\n */\nexport function createMarqueeHandler(anno: AnnotationHostCapability): InteractionHandler {\n let anchor: {\n pon: number;\n point: Vec;\n vx: number;\n vy: number;\n shift: boolean;\n } | null = null;\n let last: { pon: number; point: Vec } | null = null;\n let dragging = false;\n\n // The marquee page's view env at the down sample — the `up` intersects\n // screen-anchored annotations at their effective footprint with it.\n let view: { scale?: number; rotation?: PageRotation; zoom?: number } = {};\n return {\n id: 'annotation-marquee',\n priority: ANNOTATION_MARQUEE_PRIORITY,\n enabledFor: (t) => t.enables.has('annotation-marquee'),\n onDown: (s) => {\n if (!s.page) return false;\n anchor = {\n pon: s.page.pon,\n point: s.page.point,\n vx: s.viewport.x,\n vy: s.viewport.y,\n shift: s.modifiers.shift,\n };\n last = { pon: s.page.pon, point: s.page.point };\n view = { scale: s.page.scale, rotation: s.page.rotation, zoom: s.page.zoom };\n dragging = false;\n return true;\n },\n onMove: (s) => {\n if (!anchor) return;\n // Anchored to the page the drag started on; the projected point keeps the\n // marquee growing along the page edge when the cursor overshoots (the\n // core clamps it to the page box).\n const point = pointOn(s, anchor.pon);\n if (!point) return;\n last = { pon: anchor.pon, point };\n if (!dragging) {\n if (\n Math.hypot(s.viewport.x - anchor.vx, s.viewport.y - anchor.vy) < MARQUEE_DRAG_THRESHOLD_PX\n ) {\n return;\n }\n dragging = true;\n anno.marqueePointer(\n 'down',\n anchor.pon,\n anchor.point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n }\n anno.marqueePointer(\n 'move',\n anchor.pon,\n point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n },\n onUp: () => {\n if (dragging && anchor && last) {\n anno.marqueePointer(\n 'up',\n anchor.pon,\n last.point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n }\n anchor = null;\n last = null;\n dragging = false;\n },\n onCancel: () => {\n // Abort WITHOUT committing a selection; the core's cancel message clears\n // the marquee draft so no rectangle lingers. (Touch can't currently\n // reach the marquee — this is symmetry and future-proofing.)\n anchor = null;\n last = null;\n dragging = false;\n anno.cancelCreationDraft();\n },\n };\n}\n\n/** Drawing: live under `annotation-draw` (the square / circle / line tools). */\nexport function createDrawHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionCapability,\n): InteractionHandler {\n // The active tool id + its ROUTING subtype. The id is what `createPointer` takes\n // (it resolves the defaults preset — arrow vs line); the subtype is what the\n // poly/callout gesture checks read (arrow → `line`, a polygon preset → `polygon`).\n const toolId = () => interaction.activeToolId();\n const subtypeOf = (id: string): Subtype => anno.toolSubtype(id);\n let drawingPoly = false;\n // A callout is mid-creation between its tip/knee/box clicks; while it is, hover\n // (no button) must still drive the leader/box preview, like a poly's vertices.\n let drawingCallout = false;\n // The active drag's home page (down→up): moves/ups resolve against it, so a\n // shape keeps sizing along the page edge when the cursor overshoots.\n let origin: { pon: number; point: Vec } | null = null;\n let pendingInk: {\n tool: string;\n pon: number;\n timer: ReturnType<typeof setTimeout>;\n } | null = null;\n const flushPendingInk = () => {\n if (!pendingInk) return;\n clearTimeout(pendingInk.timer);\n pendingInk = null;\n anno.finishInkDraft();\n };\n interaction.onToolChange(() => {\n flushPendingInk();\n drawingPoly = false;\n drawingCallout = false;\n origin = null;\n });\n return {\n id: 'annotation-draw',\n // The gesture cascade — relative order IS the composition policy:\n // 100 annotation-edit existing annotations own their gestures\n // 95 annotation-place click-to-place armed tools\n // 60 text-select claims TEXT ONLY (self-gates via isOverText,\n // yields everywhere else)\n // 55 annotation-draw drag-create takes whatever text didn't claim\n // 50 annotation-marquee empty-space selection, the final fallback\n // Draw sits BELOW text-select so a COMPOSED tool (redact: text-select +\n // annotation-draw) lets text claim text — over a paragraph the drag makes\n // per-line quad marks, anywhere else it drag-creates. Priority only breaks\n // ties between simultaneously-ELIGIBLE handlers, and draw-only tools\n // (square/ink/arrow…) never co-enable text-select, so they are unaffected.\n priority: ANNOTATION_DRAW_PRIORITY,\n enabledFor: (t) => t.enables.has('annotation-draw'),\n onDown: (s) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n const distancePage = anno.distanceCreationPage?.();\n if (distancePage != null) {\n const point = pointOn(s, distancePage);\n if (point) {\n anno.createPointer(tool, 'down', distancePage, point);\n }\n // This click commits on down. Its up must not start another draft.\n origin = null;\n return true;\n }\n if (!s.page) return false;\n if (st === 'ink' && pendingInk) {\n if (pendingInk.tool === tool && pendingInk.pon === s.page.pon) {\n clearTimeout(pendingInk.timer);\n pendingInk = null;\n } else {\n flushPendingInk();\n }\n }\n // A down is a fresh intent — it may legitimately start on another page\n // (the core restarts the draft there), so it re-anchors the gesture.\n origin = { pon: s.page.pon, point: s.page.point };\n if (isPolyTool(st)) {\n const finish = (s.clickCount ?? 1) >= 2;\n anno.createPointer(tool, 'down', s.page.pon, s.page.point, finish);\n drawingPoly = !finish;\n return true;\n }\n drawingPoly = false;\n // Each callout click advances the core's tip → knee → box state machine; the\n // final box click/drag commits and clears the draft (so `drawingCallout`\n // resets on the next tool change or simply idles harmlessly).\n if (isCalloutTool(st)) drawingCallout = true;\n // The DOWN sample's display rotation rides along for the tool's `upright`\n // policy; the core captures it on the draft (later phases don't carry it).\n anno.createPointer(tool, 'down', s.page.pon, s.page.point, false, s.page.rotation);\n return true;\n },\n onMove: (s) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n // Drag-moves (button down): rect/line/ink/free-text size their box, and a\n // callout (a non-poly tool) sizes its text box during the box step. Poly\n // tools take vertices by click, so they ignore drag-moves.\n if (!origin || (isPolyTool(st) && !drawingPoly)) return;\n const point = pointOn(s, origin.pon);\n if (!point) return;\n origin.point = point;\n anno.createPointer(tool, 'move', origin.pon, point);\n },\n onUp: (s) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n if (origin && !isPolyTool(st)) {\n // ALWAYS commit the drag, even released off-page (point pins in core).\n anno.createPointer(tool, 'up', origin.pon, pointOn(s, origin.pon) ?? origin.point);\n if (st === 'ink') {\n const groupStrokesMs = anno.tool(tool)?.ink?.groupStrokesMs ?? 0;\n if (groupStrokesMs > 0) {\n const pon = origin.pon;\n const timer = setTimeout(() => {\n pendingInk = null;\n anno.finishInkDraft();\n }, groupStrokesMs);\n pendingInk = { tool, pon, timer };\n }\n }\n }\n origin = null;\n },\n onCancel: () => {\n // Aborted (second finger → pinch, or a system cancel): the draft DIES,\n // nothing commits — without this, the up-fallback would commit a shape\n // whose final point teleports to the second finger. For an ink group\n // this drops the whole in-window draft (there is no partial discard);\n // a cancel is a cancel, and the grouping window is sub-second.\n if (pendingInk) {\n clearTimeout(pendingInk.timer);\n pendingInk = null;\n }\n drawingPoly = false;\n drawingCallout = false;\n origin = null;\n anno.cancelCreationDraft();\n },\n onHover: (s) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n const distancePage = anno.distanceCreationPage?.();\n if (distancePage != null) {\n const point = pointOn(s, distancePage);\n if (point) {\n anno.createPointer(tool, 'move', distancePage, point);\n }\n return;\n }\n // Hover preview for the multi-click tools: poly (while placing vertices) and\n // callout (while placing the tip/knee/box) follow the cursor between clicks.\n if (s.page && ((drawingPoly && isPolyTool(st)) || (drawingCallout && isCalloutTool(st)))) {\n anno.createPointer(tool, 'move', s.page.pon, s.page.point);\n }\n },\n };\n}\n","/**\n * Text-selection authoring: the bridge that turns a TEXT SELECTION into markup\n * or a text-edit annotation (Insert / Replace). These tools have no gesture of\n * their own — they enable the selection plugin's `text-select` gesture, and this\n * module consumes its typed signals (`onCommit` to create, `onChange` to preview).\n * Selection is the producer; annotation the consumer — selection never knows\n * annotation exists. Kept out of the plugin-definition file so that stays lean.\n */\nimport type { InteractionCapability } from '@embedpdf/plugin-interaction/contract';\nimport type { SelectionHostCapability } from '@embedpdf/plugin-selection/contract/host';\nimport type { AnnotationHostCapability } from './types';\n\n/**\n * Wire the selection → annotation BRIDGE. The markup / caret TOOLS and their\n * defaults are registered by the plugin `init` from the tool registry; this\n * function only consumes the selection plugin's typed signals — so call it from\n * `init` only when a selection plugin is present. Selection is the producer,\n * annotation the consumer; selection never knows annotation exists.\n */\nexport function wireMarkup(\n annotation: AnnotationHostCapability,\n selection: SelectionHostCapability,\n interaction: InteractionCapability,\n): void {\n // Keep the live preview + the selection's own visual in sync with (active tool,\n // selection). While a markup tool is active the blue highlight is suppressed and\n // the in-progress selection renders as a markup ghost instead.\n const sync = () => {\n const tool = annotation.tool(interaction.activeToolId());\n const authoring = tool?.selection;\n const previewSubtype =\n authoring?.kind === 'markup'\n ? tool!.subtype\n : authoring?.kind === 'text-edit' && authoring.operation === 'replace'\n ? 'strikeout'\n : null;\n selection.setHighlightVisible(previewSubtype == null);\n if (previewSubtype && tool && selection.hasSelection()) {\n const quadsByPage: Record<number, ReturnType<typeof selection.segmentsForPage>[number]['quad'][]> =\n {};\n for (const page of selection.snapshot().pages) {\n quadsByPage[page.pon] = page.segments.map((s) => s.quad);\n }\n annotation.previewMarkup(previewSubtype, quadsByPage, tool.preset);\n } else {\n annotation.clearMarkupPreview();\n }\n };\n selection.onChange(sync); // drag-extend → live preview\n interaction.onToolChange(sync); // entering/leaving a markup tool → restore blue / clear ghost\n\n // On gesture-end, if a markup tool is active, turn the selection into markup.\n selection.onCommit(() => {\n const tool = annotation.tool(interaction.activeToolId());\n const authoring = tool?.selection;\n if (!tool || !authoring) return; // pointer tool → leave the selection (copy)\n const snapshot = selection.snapshot();\n if (authoring.kind === 'text-edit' && authoring.operation === 'insert') {\n if (snapshot.end) {\n annotation.createCaret(snapshot.end.pon, {\n glyphQuad: snapshot.end.glyphQuad,\n advance: snapshot.end.advance,\n });\n }\n selection.clear();\n return;\n }\n if (authoring.kind === 'text-edit' && authoring.operation === 'replace') {\n // `/IRT` relationships are page-local, so a cross-page selection becomes\n // one self-contained Caret + StrikeOut pair per page. The true glyph-cell\n // anchor exists only on the selection's end page; other pages anchor at\n // their last segment's trailing edge.\n for (const page of snapshot.pages) {\n const last = page.segments[page.segments.length - 1];\n if (!last) continue;\n const anchor =\n snapshot.end && snapshot.end.pon === page.pon\n ? { glyphQuad: snapshot.end.glyphQuad, advance: snapshot.end.advance }\n : { glyphQuad: last.quad, advance: last.advance };\n annotation.createReplaceText(\n page.pon,\n page.segments.map((s) => s.quad),\n anchor,\n tool.preset,\n );\n }\n selection.clear();\n return;\n }\n for (const page of snapshot.pages) {\n annotation.createMarkup(\n tool.subtype,\n page.pon,\n page.segments.map((s) => s.quad),\n tool.preset,\n );\n }\n selection.clear(); // fires onChange → preview clears; blue stays suppressed (markup tool still active)\n });\n}\n","import { initialModel } from '@embedpdf/core-annotation';\nimport type {\n AnnotationAction,\n AnnotationConfig,\n AnnotationState,\n ChromeSettings,\n ChromeSettingsPatch,\n} from './types';\n\n/**\n * Out-of-the-box selection chrome — a sensible document-annotation feel. Every\n * length is CSS px (screen-constant across zoom); every color falls back to\n * `accent`. Just defaults: override any field at registration\n * (`annotationPlugin({ chrome })`) or at runtime (`setChrome`).\n */\nexport const DEFAULT_CHROME: ChromeSettings = {\n accent: '#3858e9',\n // Solid, like the shape's own resting look — one style at rest AND rotated.\n outline: { style: 'solid', width: 1 },\n // 8px squares to look at, 24px to grab (touch-friendly without visual bulk).\n handles: { size: 8, hitSize: 24, fill: '#ffffff' },\n knob: { size: 10, hitSize: 24, offset: 32, stalk: true, fill: '#ffffff' },\n // Faint reference cross, prominent live indicator (v2 feel).\n guides: { enabled: true, style: 'solid', width: 1, axisOpacity: 0.35, indicatorOpacity: 0.8 },\n};\n\n/** Deep-partial merge of a chrome patch — one level per piece, like the\n * stage-settings convention (align pairs / pageFrame). */\nexport const mergeChrome = (base: ChromeSettings, patch: ChromeSettingsPatch): ChromeSettings => ({\n accent: patch.accent ?? base.accent,\n outline: { ...base.outline, ...patch.outline },\n handles: { ...base.handles, ...patch.handles },\n knob: { ...base.knob, ...patch.knob },\n guides: { ...base.guides, ...patch.guides },\n});\n\n/**\n * The slice holds the annotation-core Model + the selection-chrome settings.\n * The pure `update` runs in the capability (the shell, which also performs\n * effects); the reducer only stores new state — keeping the kernel store a\n * dumb, serializable container. The registration config seeds the model's\n * snap settings and the chrome.\n */\nexport const initialAnnotationState = (config: AnnotationConfig = {}): AnnotationState => ({\n model: { ...initialModel, snap: { ...initialModel.snap, ...config.snap } },\n hydration: { status: 'loading' },\n chrome: mergeChrome(DEFAULT_CHROME, config.chrome ?? {}),\n toolGhost: null,\n stampArmEpoch: 0,\n textSelection: null,\n});\n\nexport const annotationReducer = (\n state: AnnotationState,\n action: AnnotationAction,\n): AnnotationState => {\n switch (action.type) {\n case 'SET_MODEL':\n return { ...state, model: action.model };\n case 'SET_HYDRATION':\n return { ...state, hydration: action.hydration };\n case 'SET_CHROME':\n return { ...state, chrome: mergeChrome(state.chrome, action.patch) };\n case 'SET_TOOL_GHOST':\n return { ...state, toolGhost: action.ghost };\n case 'SET_TEXT_SELECTION':\n return { ...state, textSelection: action.selection };\n case 'STAMP_ARM_CHANGED':\n // A new (or dropped) payload invalidates any ghost drawn for the old one.\n return { ...state, stampArmEpoch: state.stampArmEpoch + 1, toolGhost: null };\n default:\n return state;\n }\n};\n","import { definePlugin } from '@embedpdf/core';\nimport { ActionsToken as PublicActionsToken } from '@embedpdf/plugin-actions/contract';\nimport { ActionsToken as ActionsHostToken } from '@embedpdf/plugin-actions/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract/host';\nimport { createAnnotationCapability } from './capability';\nimport { registerAnnotationEffects } from './effects';\nimport {\n createDrawHandler,\n createEditHandler,\n createGhostHandler,\n createMarqueeHandler,\n createPlaceHandler,\n} from './handler';\nimport { wireMarkup } from './markup';\nimport { annotationReducer, initialAnnotationState } from './reducer';\nimport { ARMED_STAMP_TOOL_ID, isTouchDirect } from './tools';\nimport { AnnotationToken } from './types';\nimport type {\n AnnotationAction,\n AnnotationConfig,\n AnnotationHostCapability,\n AnnotationState,\n} from './types';\n\n/**\n * The annotation plugin. Document-scoped; requires the interaction hub and\n * OPTIONALLY uses the selection plugin. Shapes/ink work with no selection; text\n * markup lights up only when a selection plugin is present.\n */\nexport const annotationPlugin = (config: AnnotationConfig = {}) =>\n definePlugin<AnnotationState, AnnotationAction, AnnotationHostCapability>({\n id: 'annotation',\n token: AnnotationToken,\n scope: 'document',\n requires: [InteractionToken],\n optional: [SelectionToken, PublicActionsToken],\n initialState: () => initialAnnotationState(config),\n reduce: annotationReducer,\n // The capability owns the resolved tool registry (built-ins + config `tools`),\n // so it needs the config too — not just the reducer state.\n capability: (ctx) => createAnnotationCapability(ctx, config),\n // Fold in remote collaborators' edits (own edits flow through the capability).\n effects: registerAnnotationEffects,\n init: (ctx) => {\n const interaction = ctx.get(InteractionToken);\n const annotation = ctx.get(AnnotationToken);\n const selection = ctx.tryGet(SelectionToken);\n\n // The actions plane's session-visibility door (Hide actions,\n // `annot.hidden`): resolve annotation object numbers to loaded model\n // ids (the `obj:` refKey seam — O(1), cross-page) and write the\n // session overlay. Session state only — never an engine write.\n const actions = ctx.tryGet(ActionsHostToken);\n if (actions) {\n ctx.cleanup(\n actions.registerAnnotCommitSink((entries) => annotation.commitScriptEffects(entries)),\n );\n }\n\n // Register every resolved tool (shapes, lines, ink, free-text, markup, stamp,\n // plus anything the embedder added via config `tools`) and seed its defaults.\n // A tool is a named preset over a subtype — see `tools.ts`. Markup / caret\n // tools ride the selection plugin's `text-select` gesture, so they stay\n // inert (skipped) when no selection plugin is installed.\n for (const tool of annotation.tools()) {\n if (tool.enables.has('text-select') && !selection) continue;\n interaction.registerTool({\n id: tool.id,\n cursor: tool.cursor,\n enables: tool.enables,\n // drag-create tools own single-finger touch; click-place tools don't\n touchDirect: isTouchDirect(tool.enables),\n });\n if (tool.defaults) annotation.setDefaults(tool.preset, tool.defaults);\n }\n\n interaction.registerHandler(createPlaceHandler(annotation));\n interaction.registerHandler(createGhostHandler(annotation, interaction));\n interaction.registerHandler(createEditHandler(annotation, interaction));\n interaction.registerHandler(createMarqueeHandler(annotation));\n interaction.registerHandler(createDrawHandler(annotation, interaction));\n interaction.onToolChange(() => {\n annotation.cancel();\n annotation.clearGhost(); // a footprint belongs to the tool that computed it\n // Engagement follows the tool: annotations whose Behavior just engaged\n // (form widgets under a fill tool) drop out of the selection — no\n // stranded chrome on a fill control.\n annotation.pruneEngagedSelection();\n // Leaving the armed stamp's own tool drops the payload — bytes are tool\n // state, not document state. It has to be the TOOL, not a capability\n // tag: `armStamp` activates ARMED_STAMP_TOOL_ID and every built-in\n // stamp tool carries `annotation-place`, so tag-matching either\n // disarmed the payload on the very activation that armed it, or let it\n // survive onto a sibling preset whose own `source` it would then\n // hijack. The legacy `annotation-stamp` tag still holds a payload, for\n // embedder tools written before the tags were unified.\n const active = interaction.activeTool();\n if (active.id !== ARMED_STAMP_TOOL_ID && !active.enables.has('annotation-stamp')) {\n annotation.disarmStamp();\n }\n });\n\n // Markup is opt-in: wire the selection→annotation BRIDGE only when a\n // selection plugin is present (the markup TOOLS were registered above).\n if (selection) wireMarkup(annotation, selection, interaction);\n },\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["annotationKey","annotationKey","annotationKey","ActionsHostToken","annotationKey","coreChrome","coreSelectionAnchor","annotationKey","corePageItems","annotationKey","RenderHostToken","annotationKey","annotationKey","NO_RECORDS","InteractionToken","annotationKey","annotationKey","annotationKey","annotationKey","propertiesOf","kindNamed","annotationKey","resolveClickPlacement","gesturePlacement","annotationKey","annotationKey","SelectionPublicToken","annotationKey","PublicActionsToken","annotationKey","InteractionToken","annotationKey","AnnotationToken","PublicActionsToken"],"sources":["../src/write/outcomes.ts","../src/comments/comments.ts","../src/comments/threads.ts","../src/tools/handlers.ts","../src/tools/markup-bridge.ts","../src/connect.ts","../src/model.ts","../src/read/annotations.ts","../src/services/geometry.ts","../src/read/chrome.ts","../src/rich-text.ts","../src/read/property-values.ts","../src/read/properties.ts","../src/text-item.ts","../src/read/render.ts","../src/services/authority.ts","../src/read/view.ts","../src/services/events.ts","../src/services/file-picker.ts","../src/services/lending.ts","../src/services/object-numbers.ts","../src/services/selection-history.ts","../src/sync/records.ts","../src/services/staging.ts","../src/services/store.ts","../src/tools/behaviors.ts","../src/tools/registry.ts","../src/write/after-create.ts","../src/services/index.ts","../src/services/announce.ts","../src/sync/confirmed.ts","../src/write/placement.ts","../src/tools/ghost.ts","../src/write/crud.ts","../src/write/drafts.ts","../src/write/icons.ts","../src/write/links.ts","../src/write/markup.ts","../src/write/measurement.ts","../src/write/ops.ts","../src/tools/hover-feed.ts","../src/write/pointer.ts","../src/write/script-effects.ts","../src/write/selection.ts","../src/write/stamps.ts","../src/write/text-editing.ts","../src/controller.ts","../src/annotation.plugin.ts"],"sourcesContent":["/**\n * What a verb returns once the engine answered its change: a `BatchResult`\n * over the annotations it addressed, the ref of the record it created, or the\n * refusal as an error.\n */\nimport { PluginError, toPluginError, toPluginErrorInfo, type BatchResult } from '@embedpdf/core';\nimport { annotationKey, type Annotation, type AnnotationRef } from '@embedpdf/engine-core/runtime';\n\nimport type { Applied, AppliedOutcome, Commit, Written } from '../services/store';\n\n/** The outcome over the refs a selection verb addressed: each applied, or failed with the refusal. */\nexport function batchResultOf(\n refs: readonly AnnotationRef[],\n outcome: Pick<Written, 'failed'>,\n): BatchResult<AnnotationRef, AnnotationRef> {\n const errors = new Map<string, PluginError>();\n for (const { ids, error } of outcome.failed) for (const id of ids) errors.set(id, error);\n const failed = refs.flatMap((ref) => {\n const error = errors.get(annotationKey(ref));\n return error ? [{ ref, error: toPluginErrorInfo(error) }] : [];\n });\n return {\n applied: refs.filter((ref) => !errors.has(annotationKey(ref))),\n skipped: [],\n failed,\n };\n}\n\n/** Reject with the refusal, for verbs whose promise fails when their change does. */\nexport function throwIfFailed(outcome: Pick<Written, 'failed'>): void {\n const [first] = outcome.failed;\n if (first) throw first.error;\n}\n\nconst notCreated = (): PluginError =>\n new PluginError('operation-failed', 'annotation', 'the annotation could not be created');\n\n/** The annotation the engine created for record `id`, from its answer. */\nconst createdIn = (outcome: Written, id: string): Annotation | null => {\n for (const item of outcome.result?.items ?? []) {\n if (item.type === 'annotations.create' && annotationKey(item.annotation.ref) === id) {\n return item.annotation as Annotation;\n }\n }\n return null;\n};\n\n/** The ref of the record a create message made (its first), once the engine wrote it. */\nexport async function createdRefOf(commit: Commit): Promise<AnnotationRef> {\n const effect = commit.effects.find((candidate) => candidate.type === 'create');\n const outcome = await commit.written;\n throwIfFailed(outcome);\n const created = effect?.type === 'create' ? createdIn(outcome, effect.id) : null;\n if (!created) throw notCreated();\n return created.ref;\n}\n\n/** Wait for stated changes to be written; rejects with the first refusal. */\nexport async function appliedOrThrow(applied: Applied): Promise<AppliedOutcome> {\n const outcome = await applied.written;\n throwIfFailed(outcome);\n return outcome;\n}\n\n/**\n * What the engine wrote for stated change `index`: the annotation its create\n * or update left, as the engine read it back; `null` when the change wrote\n * nothing. Rejects with the first refusal.\n */\nexport async function appliedAnnotationOf(applied: Applied, index = 0): Promise<Annotation | null> {\n const outcome = await appliedOrThrow(applied);\n return outcome.annotations[index] ?? null;\n}\n\n/** The ref of the record a stated create made, once the engine wrote it. */\nexport async function appliedRefOf(applied: Applied, index = 0): Promise<AnnotationRef> {\n const annotation = await appliedAnnotationOf(applied, index);\n if (!annotation) throw notCreated();\n return annotation.ref;\n}\n\n/** Run a verb per item, in order, folding refusals into a `BatchResult`. */\nexport async function batchOver<Item>(\n items: readonly Item[],\n run: (item: Item) => Promise<AnnotationRef | void>,\n refOf: (item: Item, out: AnnotationRef | void) => AnnotationRef | null,\n): Promise<BatchResult<AnnotationRef, Item>> {\n const applied: AnnotationRef[] = [];\n const failed: { ref: Item; error: ReturnType<typeof toPluginErrorInfo> }[] = [];\n for (const item of items) {\n try {\n const out = await run(item);\n const resolved = refOf(item, out);\n if (resolved) applied.push(resolved);\n } catch (error) {\n failed.push({ ref: item, error: toPluginErrorInfo(toPluginError('annotation', error)) });\n }\n }\n return { applied, skipped: [], failed };\n}\n","import { PluginError } from '@embedpdf/core';\nimport { annotContentsEditable, refOf } from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n isDimension,\n toPageRef,\n type Annotation,\n type AnnotationDraft,\n type AnnotationPatch,\n type AnnotationRef,\n type PageBox,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { CommentsApi, ThreadDeleteResult } from '../contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { ThreadIndex } from './threads';\nimport type { Crud } from '../write/crud';\nimport { appliedAnnotationOf, appliedOrThrow, appliedRefOf } from '../write/outcomes';\n\n// Screen-anchored like a sticky note (it prints by the engine's default).\nconst REPLY_FLAGS = { 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).\nconst STATUS_FLAGS = { hidden: true, noZoom: true, noRotate: true };\n\n/** Where a reply or a state sits: the usual 20 × 20 icon at its root's top-left corner. */\nconst replyRect = (root: PageBox): PageBox => ({ x: root.x, y: root.y, width: 20, height: 20 });\n\n/**\n * The conversation plane's verbs: every one compiles down to plain\n * annotation creates / patches / deletes (one write path), and each announces the thread it touched (its root, as it\n * was before the change).\n */\nexport function createComments(\n ctx: Pick<AnnotationContext, 'doc' | 'assertAllowed' | 'cancellable'>,\n { store, authority, events }: Pick<AnnotationServices, 'store' | 'authority' | 'events'>,\n threads: ThreadIndex,\n crud: Pick<Crud, 'update'>,\n) {\n /** Create a conversation annotation (a reply or a review state): shown at once, then confirmed. */\n const createConversationAnnot = (\n pageObjectNumber: number,\n draft: AnnotationDraft,\n ): Promise<AnnotationRef> =>\n store\n .applyWhenNumbered([{ type: 'create', page: toPageRef(pageObjectNumber), draft }])\n .then((applied) => appliedRefOf(applied));\n\n const deleteOne = async (ref: AnnotationRef, signal?: AbortSignal): Promise<void> => {\n await ctx.cancellable(signal, appliedOrThrow(store.apply([{ type: 'delete', ref }])));\n };\n\n /** Whether this comment's text can change: the user's update right and its `lockedContents`. */\n const canSetText = (ref: AnnotationRef): boolean => {\n const record = store.model().byId[annotationKey(ref)];\n return !!record && !isDimension(record.annotation) && annotContentsEditable(record);\n };\n\n const announce = (\n root: AnnotationRef,\n change: 'reply' | 'text' | 'status' | 'marked' | 'deleted',\n ) => events.threadChanged.emit({ rootRef: root, change });\n\n const comments: CommentsApi = {\n listThreads: () => threads.index().threads,\n getThread: (ref) => threads.index().byMember.get(annotationKey(ref)) ?? null,\n onThreadChanged: events.threadChanged.on,\n\n reply: async (ref, text, options = {}) => {\n ctx.assertAllowed('annotations:create', 'annotation.comments.reply');\n const root = threads.rootRefOf(ref);\n const thread = threads.threadOf(ref);\n const applied = await store.applyWhenNumbered([\n {\n type: 'create',\n page: toPageRef(thread.page.objectNumber),\n draft: {\n subtype: 'text',\n rect: replyRect(thread.root.rect),\n icon: 'comment',\n contents: text,\n reply: { to: thread.root.ref },\n ...REPLY_FLAGS,\n },\n },\n ]);\n const annotation: Annotation | null = await ctx.cancellable(\n options.signal,\n appliedAnnotationOf(applied),\n );\n announce(root, 'reply');\n if (!annotation) {\n throw new PluginError('operation-failed', 'annotation', 'the reply could not be created');\n }\n return { annotation };\n },\n\n setText: async (ref, text, options = {}) => {\n const root = threads.rootRefOf(ref);\n const record = store.model().byId[annotationKey(ref)];\n if (record && isDimension(record.annotation)) {\n throw new PluginError(\n 'invalid-input',\n 'annotation',\n \"a measurement's text is worked out from its points\",\n );\n }\n if (!refOf(record)) {\n throw new PluginError('not-found', 'annotation', `no annotation ${annotationKey(ref)}`);\n }\n await crud.update(\n ref,\n { subtype: record.annotation.subtype, contents: text } as AnnotationPatch,\n undefined,\n options,\n );\n announce(root, 'text');\n },\n\n setStatus: async (ref, state, options = {}) => {\n ctx.assertAllowed('annotations:create', 'annotation.comments.setStatus');\n const root = threads.rootRefOf(ref);\n const thread = threads.threadOf(ref);\n const userId = threads.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 ? thread.review.byReviewer[userId] : undefined;\n await ctx.cancellable(\n options.signal,\n createConversationAnnot(thread.page.objectNumber, {\n subtype: 'text',\n rect: replyRect(thread.root.rect),\n reply: { to: previous?.ref ?? thread.root.ref },\n state,\n stateModel: 'review',\n ...STATUS_FLAGS,\n }),\n );\n announce(root, 'status');\n },\n\n setMarked: async (ref, marked, options = {}) => {\n ctx.assertAllowed('annotations:create', 'annotation.comments.setMarked');\n const root = threads.rootRefOf(ref);\n const thread = threads.threadOf(ref);\n await ctx.cancellable(\n options.signal,\n createConversationAnnot(thread.page.objectNumber, {\n subtype: 'text',\n rect: replyRect(thread.root.rect),\n reply: { to: thread.root.ref },\n state: marked ? 'marked' : 'unmarked',\n stateModel: 'marked',\n ...STATUS_FLAGS,\n }),\n );\n announce(root, 'marked');\n },\n\n delete: async (ref, options = {}) => {\n const root = threads.rootRefOf(ref);\n await deleteOne(ref, options.signal);\n announce(root, 'deleted');\n },\n\n deleteThread: async (ref, options = {}): Promise<ThreadDeleteResult> => {\n const root = threads.rootRefOf(ref);\n const thread = threads.threadOf(ref);\n const members = threads.memberRefsOf(thread);\n // A courtesy preflight: all or nothing, as the engine decides it.\n const blocked = members.filter((ref) => !authority.canDelete(ref));\n if (blocked.length > 0) {\n announce(root, 'deleted');\n return {\n deleted: [],\n failed: blocked.map((ref) => ({ ref: ref, error: new Error('delete not permitted') })),\n };\n }\n // Deleting the root deletes the thread, in one change: the engine\n // checks every member again and deletes all of them or none.\n try {\n await deleteOne(root, options.signal);\n return { deleted: members, failed: [] };\n } catch (error) {\n return { deleted: [], failed: [{ ref: root, error }] };\n } finally {\n announce(root, 'deleted');\n }\n },\n\n // Replying and setting a review state or a check mark create new\n // annotations: gated on the user's own identity, not the target's owner.\n canReply: () => authority.canCreate(),\n canSetStatus: () => authority.canCreate(),\n canSetMarked: () => authority.canCreate(),\n canSetText,\n canDelete: (ref) => authority.canDelete(ref),\n canDeleteThread: (ref) => {\n const thread = threads.index().byMember.get(annotationKey(ref)) ?? null;\n return thread !== null && threads.memberRefsOf(thread).every(authority.canDelete);\n },\n };\n\n return { api: { comments } };\n}\n","import type { Id, Model } from '@embedpdf/core-annotation';\nimport { refOf } from '@embedpdf/core-annotation';\nimport {\n compareIsoDateTime,\n annotationKey,\n buildCommentThreads,\n type Annotation,\n type AnnotationRef,\n type CommentThread,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext, AnnotationServices } from '../services';\n\ninterface ThreadsIndex {\n threads: CommentThread[];\n byMember: Map<Id, CommentThread>;\n}\n\n/**\n * The comments lens's index: a derived, memoized threads index over the\n * substrate. Because every path — this session's changes, engine\n * confirmations, remote events, reloads — lands in the model, the sidebar\n * updates with zero extra wiring. The memo keys on the model's annotation content (byId/order\n * — hover and drafts don't invalidate) plus the layout (display order is\n * computed fresh against the live pages) and the session identity.\n */\nexport function createThreadIndex(\n ctx: Pick<AnnotationContext, 'doc' | 'document'>,\n { store }: Pick<AnnotationServices, 'store'>,\n) {\n const currentUserId = (): string | undefined => ctx.doc?.security.identity?.userId;\n\n let memo:\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((pageInfo) => pageInfo.ref.objectNumber).join(',');\n\n const computeIndex = (): ThreadsIndex => {\n const model = store.model();\n // Confirmed records only: a new annotation joins the index once the\n // engine confirms its create.\n const dtos: Annotation[] = [];\n for (const id of model.order) {\n const record = model.byId[id];\n if (record && refOf(record)) dtos.push(record.annotation);\n }\n const threads = buildCommentThreads(dtos, { currentUserId: currentUserId() });\n\n // Display order: page position first (live layout), then from the top of\n // the page down, then creation.\n const pages = ctx.document()?.pages ?? [];\n const displayIndex = new Map(pages.map((pageInfo, i) => [pageInfo.ref.objectNumber, i]));\n threads.sort((left, right) => {\n const pa = displayIndex.get(left.page.objectNumber) ?? Number.MAX_SAFE_INTEGER;\n const pb = displayIndex.get(right.page.objectNumber) ?? Number.MAX_SAFE_INTEGER;\n if (pa !== pb) return pa - pb;\n if (left.root.rect.y !== right.root.rect.y) return left.root.rect.y - right.root.rect.y;\n const leftCreated = left.root.createdAt;\n const rightCreated = right.root.createdAt;\n if (leftCreated === null || rightCreated === null) {\n return leftCreated === rightCreated ? 0 : leftCreated === null ? -1 : 1;\n }\n return compareIsoDateTime(leftCreated, rightCreated);\n });\n\n const byMember = new Map<Id, CommentThread>();\n for (const thread of threads) {\n byMember.set(annotationKey(thread.root.ref), thread);\n for (const dto of thread.replies) byMember.set(annotationKey(dto.ref), thread);\n for (const dto of thread.groupedParts) byMember.set(annotationKey(dto.ref), thread);\n for (const ref of thread.review.statusRefs) byMember.set(annotationKey(ref), thread);\n }\n return { threads, byMember };\n };\n\n const index = (): ThreadsIndex => {\n const model = store.model();\n const layout = layoutSignature();\n const userId = currentUserId();\n if (\n memo &&\n memo.byId === model.byId &&\n memo.order === model.order &&\n memo.layout === layout &&\n memo.userId === userId\n ) {\n return memo;\n }\n memo = { ...computeIndex(), byId: model.byId, order: model.order, layout, userId };\n return memo;\n };\n\n const threadOf = (ref: AnnotationRef): CommentThread => {\n const thread = index().byMember.get(annotationKey(ref));\n if (!thread) throw new Error('[annotation] no comment thread contains this ref');\n return thread;\n };\n const rootRefOf = (ref: AnnotationRef): AnnotationRef =>\n index().byMember.get(annotationKey(ref))?.root.ref ?? ref;\n const memberRefsOf = (thread: CommentThread): AnnotationRef[] => [\n ...thread.replies.map((dto) => dto.ref),\n ...thread.groupedParts.map((dto) => dto.ref),\n ...thread.review.statusRefs,\n thread.root.ref, // root LAST — children first keeps foreign readers coherent\n ];\n\n return { currentUserId, index, threadOf, rootRefOf, memberRefsOf };\n}\n\nexport type ThreadIndex = ReturnType<typeof createThreadIndex>;\n","import type { PluginClock } from '@embedpdf/core';\nimport type { KindName, Point } from '@embedpdf/core-annotation';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport type { PageRef } from '@embedpdf/engine-core/runtime';\nimport type {\n InteractionHostCapability,\n InteractionHandler,\n PointerSample,\n} from '@embedpdf/plugin-interaction/contract/host';\n\nimport type { AnnotationHostCapability } from '../host-contract';\nimport {\n ANNOTATION_DRAW_PRIORITY,\n ANNOTATION_EDIT_PRIORITY,\n ANNOTATION_MARQUEE_PRIORITY,\n ANNOTATION_PLACE_PRIORITY,\n} from '../priorities';\n\nconst MARQUEE_DRAG_THRESHOLD_PX = 4;\nconst isPolyTool = (subtype: KindName): boolean => subtype === 'polygon' || subtype === 'polyline';\nconst isCalloutTool = (subtype: KindName): boolean => subtype === 'free-text-callout';\n\n/**\n * Resolve a sample against a gesture's home page. Annotation gestures are\n * page-anchored: they track the page they started on, even when the cursor\n * wanders off it — `s.page` re-resolves per event (a page-2 point is a\n * different coordinate frame, the teleport bug), so prefer the source's\n * unclamped projection and fall back to the page hit only when it's the same\n * page. Null → this sample can't speak for the home page; ignore it.\n */\nconst pointOn = (sample: PointerSample, page: PageRef): Point | null =>\n sample.project?.(page) ??\n (sample.page?.ref.objectNumber === page.objectNumber ? sample.page.point : null);\n\n/**\n * The tool's ghost follows the hover of the handler that would take the\n * click (see tools/ghost.ts): it shows what a click here makes, so only where\n * the click would reach that handler — nothing above it claims the pointer\n * (an annotation, text) — and the user may create. Off the page it clears.\n */\nfunction followGhost(\n anno: AnnotationHostCapability,\n interaction: InteractionHostCapability,\n sample: PointerSample,\n): void {\n if (sample.page && anno.canCreate() && !interaction.hasCursorClaim()) {\n anno.hoverGhostAt(\n interaction.getActiveToolId(),\n sample.page.ref,\n sample.page.point,\n sample.page.rotation,\n sample.page.zoom,\n );\n } else {\n anno.clearGhost();\n }\n}\n\n/**\n * Click-to-place for every payload-carrying tool (stamp / note / file\n * attachment). Each click places one annotation centred on the point (the\n * tool stays active for repeat placement, like a rubber stamp); the\n * capability's `placeAt` routes by the active tool's kind: armed stamp bytes,\n * a stamp/attachment prompt (pick the spot first, the payload second), or an\n * immediate note. No drag gesture — placement size comes from the content\n * (stamp aspect / the fixed icon box), not the pointer. Its hover shows the\n * tool's ghost where the click lands; the ghost clears when the click ends.\n *\n * Priority is deliberately below the edit handler (100): a click over an\n * existing annotation selects it; placement happens on empty page space.\n */\nexport function createPlaceHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionHostCapability,\n): InteractionHandler {\n return {\n id: 'annotation-place',\n // `annotation-stamp` is honoured as a legacy alias for embedder tool\n // configs written before the tags were unified.\n priority: ANNOTATION_PLACE_PRIORITY,\n enabledFor: (tool) =>\n tool.enables.has('annotation-place') || tool.enables.has('annotation-stamp'),\n onDown: (sample) => {\n if (!sample.page) return false;\n // The click sample's display rotation drives the tool's `upright` policy —\n // the placement lands reading horizontally on a rotated page/view.\n return anno.placeAt(\n sample.page.ref,\n sample.page.point,\n sample.page.rotation,\n sample.page.zoom,\n );\n },\n onUp: () => anno.clearGhost(),\n onCancel: () => anno.clearGhost(),\n onHover: (sample) => followGhost(anno, interaction, sample),\n };\n}\n\n/**\n * Ambient editing: live under the `annotation-edit` tag, which both the pointer\n * and pan tools enable — so you select/move/resize in any navigation mode (Adobe\n * behaviour). It captures only over an annotation/handle; over empty it\n * deselects and declines (so text-selection / pan still work). Hover drives the\n * cursor (move / pointer / resize) via a priority cursor claim.\n */\nexport function createEditHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionHostCapability,\n): InteractionHandler {\n // The gesture's home page + last resolved point, armed on down. Every\n // move/up resolves against this page (the annotation slides along its edge\n // when the cursor overshoots — the core clamps), never against whatever\n // page the sample happens to hit. `downPoint` keeps the untouched origin so\n // an aborted gesture (second finger → pinch) can revert instead of leaving\n // the annotation half-moved. `touch` rides the whole gesture so every phase\n // grabs with the same finger-sized zones the down resolved with.\n let origin: { page: PageRef; point: Point; downPoint: Point; touch: boolean } | null = null;\n return {\n id: 'annotation-edit',\n priority: ANNOTATION_EDIT_PRIORITY,\n enabledFor: (tool) => tool.enables.has('annotation-edit'),\n // Touch consent: a finger owns a tool drag only over the selection's own\n // chrome or a selected annotation's body (see claimsTouchAt) — unselected\n // bodies keep scrolling, matching the Markup convention.\n claimsTouch: (sample) =>\n !!sample.page &&\n anno.claimsTouchAt(\n sample.page.ref,\n sample.page.point,\n sample.page.scale,\n sample.page.rotation,\n sample.page.zoom,\n ),\n onDown: (sample) => {\n if (!sample.page) return false;\n // The final distance-placement click belongs to its creation draft even\n // when it lands over an existing annotation.\n if (anno.distanceCreationPage?.() != null) return false;\n const touch = sample.pointerType === 'touch';\n // While a free-text box is being edited it owns its own pointer events, so a\n // down that reaches the hub at all is a click outside the editor — commit and\n // leave text edit. This makes exit hub-driven (deterministic) rather than\n // relying on a DOM blur, which races the focus-steal of the entering gesture.\n const wasEditing = anno.getEditingId() != null;\n if (wasEditing) void anno.text.end();\n if (\n anno.getHitKind(\n sample.page.ref,\n sample.page.point,\n sample.page.scale,\n sample.page.rotation,\n sample.page.zoom,\n touch,\n ) === 'empty'\n ) {\n // Plain empty click drops the selection. Shift-empty preserves it so the\n // lower-priority marquee handler can additive/toggle-select.\n if (!sample.modifiers.shift) anno.selection.clear();\n // A click that dismissed an active edit is consumed: its sole job was to\n // leave edit mode, so the draw tool doesn't also spawn a new annotation.\n // Only when nothing was being edited do we decline, letting\n // pan / text-selection / draw act on the empty click.\n return wasEditing;\n }\n // Double-click / long-press over a free-text box → enter text edit (not\n // a move). Over any other annotation the attempt reports false and the\n // press falls through to the normal path below (select / arm a move) —\n // so a long-press on a highlight selects it instead of the gesture\n // being swallowed by a no-op edit attempt.\n if ((sample.clickCount ?? 1) >= 2) {\n if (\n anno.beginTextEditAt(\n sample.page.ref,\n sample.page.point,\n sample.page.scale,\n sample.page.rotation,\n sample.page.zoom,\n )\n ) {\n return true;\n }\n }\n anno.editPointer(\n 'down',\n sample.page.ref,\n sample.page.point,\n sample.modifiers.shift,\n sample.page.scale,\n sample.page.rotation,\n sample.page.zoom,\n touch,\n );\n origin = {\n page: sample.page.ref,\n point: sample.page.point,\n downPoint: sample.page.point,\n touch,\n };\n return true;\n },\n onMove: (sample) => {\n if (!origin) return;\n const point = pointOn(sample, origin.page);\n if (!point) return;\n origin.point = point;\n // The sample's scale/rotation ride along (uniform across pages), so a\n // screen-anchored member page-clamps at its effective footprint mid-drag.\n anno.editPointer(\n 'move',\n origin.page,\n point,\n sample.modifiers.shift,\n sample.page?.scale,\n sample.page?.rotation,\n sample.page?.zoom,\n origin.touch,\n );\n },\n onUp: (sample) => {\n if (!origin) return;\n // Always close the gesture — a release over a page gap or outside the\n // window must still commit (a dangling draft leaves a ghost that snaps\n // back on the next interaction). `editUp` doesn't read the point.\n anno.editPointer(\n 'up',\n origin.page,\n pointOn(sample, origin.page) ?? origin.point,\n false,\n undefined,\n undefined,\n undefined,\n origin.touch,\n );\n origin = null;\n },\n onCancel: () => {\n if (!origin) return;\n // Aborted (second finger → pinch): Revert, don't commit — replay the\n // gesture back to its own down point (every transform is delta-from-\n // down, so this restores the original geometry), then close it there.\n const { page, downPoint, touch } = origin;\n origin = null;\n anno.editPointer('move', page, downPoint, false, undefined, undefined, undefined, touch);\n anno.editPointer('up', page, downPoint, false, undefined, undefined, undefined, touch);\n },\n onHover: (sample) => {\n // priority 20 → beats text-select's 'text' (10) over an annotation; null clears.\n interaction.claimCursor(\n 'annotation',\n sample.page\n ? anno.getCursorAt(\n sample.page.ref,\n sample.page.point,\n sample.page.scale,\n sample.page.rotation,\n sample.page.zoom,\n )\n : null,\n 20,\n );\n // Hover state for scene affordances (redact preview) — rides the same\n // per-move sample; the capability dispatches on change only.\n anno.hoverAt(\n sample.page\n ? {\n page: sample.page.ref,\n point: sample.page.point,\n scale: sample.page.scale,\n rotation: sample.page.rotation,\n zoom: sample.page.zoom,\n }\n : null,\n );\n },\n };\n}\n\n/**\n * Empty-page drag selection. Lower priority than annotation edit and text\n * selection, so it only owns drags that begin on empty, non-text page space.\n */\nexport function createMarqueeHandler(anno: AnnotationHostCapability): InteractionHandler {\n let anchor: {\n page: PageRef;\n point: Point;\n vx: number;\n vy: number;\n shift: boolean;\n } | null = null;\n let last: { page: PageRef; point: Point } | null = null;\n let dragging = false;\n\n // The marquee page's view env at the down sample — the `up` intersects\n // screen-anchored annotations at their effective footprint with it.\n let view: { scale?: number; rotation?: PageRotation; zoom?: number } = {};\n return {\n id: 'annotation-marquee',\n priority: ANNOTATION_MARQUEE_PRIORITY,\n enabledFor: (tool) => tool.enables.has('annotation-marquee'),\n onDown: (sample) => {\n if (!sample.page) return false;\n anchor = {\n page: sample.page.ref,\n point: sample.page.point,\n vx: sample.viewport.x,\n vy: sample.viewport.y,\n shift: sample.modifiers.shift,\n };\n last = { page: sample.page.ref, point: sample.page.point };\n view = { scale: sample.page.scale, rotation: sample.page.rotation, zoom: sample.page.zoom };\n dragging = false;\n return true;\n },\n onMove: (sample) => {\n if (!anchor) return;\n // Anchored to the page the drag started on; the projected point keeps the\n // marquee growing along the page edge when the cursor overshoots (the\n // core clamps it to the page box).\n const point = pointOn(sample, anchor.page);\n if (!point) return;\n last = { page: anchor.page, point };\n if (!dragging) {\n if (\n Math.hypot(sample.viewport.x - anchor.vx, sample.viewport.y - anchor.vy) <\n MARQUEE_DRAG_THRESHOLD_PX\n ) {\n return;\n }\n dragging = true;\n anno.marqueePointer(\n 'down',\n anchor.page,\n anchor.point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n }\n anno.marqueePointer(\n 'move',\n anchor.page,\n point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n },\n onUp: () => {\n if (dragging && anchor && last) {\n anno.marqueePointer(\n 'up',\n anchor.page,\n last.point,\n anchor.shift,\n view.scale,\n view.rotation,\n view.zoom,\n );\n }\n anchor = null;\n last = null;\n dragging = false;\n },\n onCancel: () => {\n // Abort without committing a selection; the core's cancel message clears\n // the marquee draft so no rectangle lingers. (Touch can't currently\n // reach the marquee — this is symmetry and future-proofing.)\n anchor = null;\n last = null;\n dragging = false;\n anno.draft.cancel();\n },\n };\n}\n\n/**\n * Drawing: live under `annotation-draw` (the square / circle / line tools).\n * Its hover shows the tool's ghost where a click lands; the ghost stays while\n * the press is still a click, and clears when the gesture ends.\n */\nexport function createDrawHandler(\n anno: AnnotationHostCapability,\n interaction: InteractionHostCapability,\n clock: Pick<PluginClock, 'after'>,\n onSettle?: (flush: () => void) => void,\n): InteractionHandler {\n // The active tool id + its routing subtype. The id is what `createPointer` takes\n // (it resolves the defaults preset — arrow vs line); the subtype is what the\n // poly/callout gesture checks read (arrow → `line`, a polygon preset → `polygon`).\n const toolId = () => interaction.getActiveToolId();\n const subtypeOf = (id: string): KindName => anno.getToolSubtype(id);\n let drawingPoly = false;\n // A callout is mid-creation between its tip/knee/box clicks; while it is, hover\n // (no button) must still drive the leader/box preview, like a poly's vertices.\n let drawingCallout = false;\n // Home page of a between-clicks preview (polygon, polyline, callout). The drag\n // `origin` dies on pointer-up, but the preview does not: hover keeps projecting\n // onto this page, and the core pins the point, so the rubber-band slides along\n // the edge when the cursor leaves the page.\n let followPage: PageRef | null = null;\n // The active drag's home page (down→up): moves/ups resolve against it, so a\n // shape keeps sizing along the page edge when the cursor overshoots.\n let origin: { page: PageRef; point: Point } | null = null;\n // An ink drawing waiting for its next stroke, and the cancel of that wait.\n let pendingInk: {\n tool: string;\n page: PageRef;\n cancelWait: () => void;\n } | null = null;\n const flushPendingInk = () => {\n if (!pendingInk) return;\n pendingInk.cancelWait();\n pendingInk = null;\n anno.finishInkDraft();\n };\n // A download finishes the drawing waiting for its next stroke. A stroke still\n // being drawn is left alone: it's not what the user sees yet.\n onSettle?.(flushPendingInk);\n interaction.onToolChanged(() => {\n flushPendingInk();\n drawingPoly = false;\n drawingCallout = false;\n followPage = null;\n origin = null;\n });\n return {\n id: 'annotation-draw',\n // The gesture cascade — relative order is the composition policy:\n // 100 annotation-edit existing annotations own their gestures\n // 95 annotation-place click-to-place armed tools\n // 60 text-select claims text only (self-gates via isOverText,\n // yields everywhere else)\n // 55 annotation-draw drag-create takes whatever text didn't claim\n // 50 annotation-marquee empty-space selection, the final fallback\n // Draw sits below text-select so a composed tool (redact: text-select +\n // annotation-draw) lets text claim text — over a paragraph the drag makes\n // per-line quad marks, anywhere else it drag-creates. Priority only breaks\n // ties between simultaneously-eligible handlers, and draw-only tools\n // (square/ink/arrow…) never co-enable text-select, so they are unaffected.\n priority: ANNOTATION_DRAW_PRIORITY,\n enabledFor: (tool) => tool.enables.has('annotation-draw'),\n onDown: (sample) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n const distancePage = anno.distanceCreationPage?.();\n if (distancePage != null) {\n const point = pointOn(sample, distancePage);\n if (point) {\n anno.createPointer(tool, 'down', distancePage, point);\n }\n // This click commits on down. Its up must not start another draft.\n origin = null;\n return true;\n }\n if (!sample.page) return false;\n if (st === 'ink' && pendingInk) {\n if (\n pendingInk.tool === tool &&\n pendingInk.page.objectNumber === sample.page.ref.objectNumber\n ) {\n pendingInk.cancelWait();\n pendingInk = null;\n } else {\n flushPendingInk();\n }\n }\n // A down is a fresh intent — it may legitimately start on another page\n // (the core restarts the draft there), so it re-anchors the gesture.\n origin = { page: sample.page.ref, point: sample.page.point };\n if (isPolyTool(st)) {\n const finish = (sample.clickCount ?? 1) >= 2;\n anno.createPointer(tool, 'down', sample.page.ref, sample.page.point, finish);\n // A double-click commits the poly; the rubber-band ends with it.\n drawingPoly = !finish;\n followPage = finish ? null : sample.page.ref;\n return true;\n }\n drawingPoly = false;\n // Each callout click advances the core's tip → knee → box state machine; the\n // final box click/drag commits and clears the draft (so `drawingCallout`\n // resets on the next tool change or simply idles harmlessly).\n if (isCalloutTool(st)) {\n drawingCallout = true;\n followPage = sample.page.ref;\n } else {\n followPage = null;\n }\n // The down sample's display rotation rides along for the tool's `upright`\n // policy; the core captures it on the draft (later phases don't carry it).\n anno.createPointer(\n tool,\n 'down',\n sample.page.ref,\n sample.page.point,\n false,\n sample.page.rotation,\n );\n return true;\n },\n onMove: (sample) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n // Drag-moves (button down): rect/line/ink/free-text size their box, and a\n // callout (a non-poly tool) sizes its text box during the box step. Poly\n // tools take vertices by click, so they ignore drag-moves.\n if (!origin || (isPolyTool(st) && !drawingPoly)) return;\n const point = pointOn(sample, origin.page);\n if (!point) return;\n origin.point = point;\n anno.createPointer(tool, 'move', origin.page, point);\n },\n onUp: (sample) => {\n const tool = toolId();\n const st = subtypeOf(tool);\n if (origin && !isPolyTool(st)) {\n // Always commit the drag, even released off-page (point pins in core).\n anno.createPointer(tool, 'up', origin.page, pointOn(sample, origin.page) ?? origin.point);\n if (st === 'ink') {\n const groupStrokesMs = anno.getResolvedTool(tool)?.ink?.groupStrokesMs ?? 0;\n if (groupStrokesMs > 0) {\n const page = origin.page;\n const cancelWait = clock.after(groupStrokesMs, () => {\n pendingInk = null;\n anno.finishInkDraft();\n });\n pendingInk = { tool, page, cancelWait };\n }\n }\n }\n origin = null;\n anno.clearGhost();\n },\n onCancel: () => {\n // Aborted (second finger → pinch, or a system cancel): the draft dies,\n // nothing commits — without this, the up-fallback would commit a shape\n // whose final point teleports to the second finger. For an ink group\n // this drops the whole in-window draft (there is no partial discard);\n // a cancel is a cancel, and the grouping window is sub-second.\n if (pendingInk) {\n pendingInk.cancelWait();\n pendingInk = null;\n }\n drawingPoly = false;\n drawingCallout = false;\n followPage = null;\n origin = null;\n anno.draft.cancel();\n anno.clearGhost();\n },\n onHover: (sample) => {\n followGhost(anno, interaction, sample);\n const tool = toolId();\n const st = subtypeOf(tool);\n const distancePage = anno.distanceCreationPage?.();\n if (distancePage != null) {\n const point = pointOn(sample, distancePage);\n if (point) {\n anno.createPointer(tool, 'move', distancePage, point);\n }\n return;\n }\n // Between clicks the button is up, so there is no drag origin. The preview\n // stays on the page the series started on: project onto it even when the\n // cursor has left that page. The core pins the point, so the rubber-band\n // slides along the edge and picks the cursor back up inside the page.\n if (\n followPage &&\n ((drawingPoly && isPolyTool(st)) || (drawingCallout && isCalloutTool(st)))\n ) {\n const point = pointOn(sample, followPage);\n if (point) anno.createPointer(tool, 'move', followPage, point);\n }\n },\n };\n}\n","/**\n * Text-selection authoring: the bridge that turns a text selection into markup\n * or a text-edit annotation (Insert / Replace). These tools have no gesture of\n * their own — they enable the selection plugin's `text-select` gesture, and this\n * module consumes its typed events (`onCommitted` to create, `onChanged` to preview)\n * and the tool changes (a tool picked with text already selected creates too).\n * Selection is the producer; annotation the consumer — selection never knows\n * annotation exists. Kept out of the plugin-definition file so that stays lean.\n */\nimport type { InteractionCapability } from '@embedpdf/plugin-interaction/contract';\nimport type { SelectionHostCapability } from '@embedpdf/plugin-selection/contract/host';\n\nimport type { AnnotationHostCapability } from '../host-contract';\n\n/**\n * Wire the selection → annotation bridge. The markup / caret tools and their\n * defaults are registered by the plugin `init` from the tool registry; this\n * function only consumes the selection plugin's typed signals — so call it from\n * `init` only when a selection plugin is present. Selection is the producer,\n * annotation the consumer; selection never knows annotation exists.\n */\nexport function wireMarkup(\n annotation: AnnotationHostCapability,\n selection: SelectionHostCapability,\n interaction: InteractionCapability,\n): void {\n // Keep the live preview + the selection's own visual in sync with (active tool,\n // selection). While a markup tool is active the blue highlight is suppressed and\n // the in-progress selection renders as a markup ghost instead.\n const sync = () => {\n const tool = annotation.getResolvedTool(interaction.getActiveToolId());\n const authoring = tool?.selection;\n const previewSubtype =\n authoring?.kind === 'markup'\n ? tool!.subtype\n : authoring?.kind === 'text-edit' && authoring.operation === 'replace'\n ? 'strikeout'\n : null;\n selection.setHighlightVisible(previewSubtype == null);\n if (previewSubtype && tool && selection.hasSelection()) {\n const quadsByPage: Record<\n number,\n ReturnType<typeof selection.listSegments>[number]['quad'][]\n > = {};\n for (const entry of selection.getSnapshot().pages) {\n quadsByPage[entry.page.objectNumber] = entry.segments.map((segment) => segment.quad);\n }\n annotation.previewMarkup(previewSubtype, quadsByPage, tool.preset);\n } else {\n annotation.clearMarkupPreview();\n }\n };\n selection.onChanged(sync); // drag-extend → live preview\n\n // A text tool turns the selection into its markup, and stays active: when\n // a selection is committed while the tool is active, and when the tool\n // becomes active while a selection is there (not mid-drag: the drag's end\n // commits it). Selecting with the pointer tool leaves the selection (copy).\n selection.onCommitted(() => {\n annotation.applyToolToSelection(interaction.getActiveToolId());\n });\n interaction.onToolChanged(() => {\n if (!selection.isSelecting()) annotation.applyToolToSelection(interaction.getActiveToolId());\n sync(); // entering/leaving a markup tool → restore blue / clear ghost\n });\n}\n","/**\n * The annotation plugin's wiring, run once every capability exists: its tools\n * and pointer handlers on the interaction hub, the markup bridge to the\n * selection plugin, and the annotation commit sink on the actions plugin.\n * Every registration is released with the document.\n */\nimport { ActionsToken as ActionsHostToken } from '@embedpdf/plugin-actions/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract/host';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract/host';\n\nimport type { AnnotationHostCapability } from './host-contract';\nimport type { AnnotationContext } from './services';\nimport { ARMED_STAMP_TOOL_ID, toolTouchOf } from './tools/definitions';\nimport {\n createDrawHandler,\n createEditHandler,\n createMarqueeHandler,\n createPlaceHandler,\n} from './tools/handlers';\nimport { wireMarkup } from './tools/markup-bridge';\n\nexport function connectAnnotation(\n ctx: AnnotationContext,\n annotation: AnnotationHostCapability,\n): void {\n const interaction = ctx.get(InteractionToken);\n const selection = ctx.tryGet(SelectionToken);\n\n // Script effects that hide or show annotations are written through this plugin.\n const actions = ctx.tryGet(ActionsHostToken);\n if (actions) {\n ctx.cleanup(\n actions.registerAnnotCommitSink((entries) => annotation.commitScriptEffects(entries)),\n );\n }\n\n // Register every resolved tool (built-ins plus the embedder's; the registry\n // seeded their defaults). Markup and caret tools ride the selection plugin's\n // text-select gesture, so they are skipped when there is no selection\n // plugin. A tool a sibling already registered on the hub (the form palette)\n // is left alone.\n for (const tool of annotation.listResolvedTools()) {\n if (tool.enables.has('text-select') && !selection) continue;\n if (interaction.hasTool(tool.id)) continue;\n ctx.cleanup(\n interaction.registerTool({\n id: tool.id,\n cursor: tool.cursor,\n enables: tool.enables,\n // Drag-create tools own single-finger touch; click-place tools do not.\n touch: toolTouchOf(tool.enables),\n }),\n );\n }\n\n for (const handler of [\n createPlaceHandler(annotation, interaction),\n createEditHandler(annotation, interaction),\n createMarqueeHandler(annotation),\n createDrawHandler(annotation, interaction, ctx.clock, (flush) => ctx.onSettle(flush)),\n ]) {\n ctx.cleanup(interaction.registerHandler(handler));\n }\n\n ctx.listen(interaction.onToolChanged, () => {\n annotation.cancel();\n // A ghost belongs to the tool that showed it.\n annotation.clearGhost();\n // Annotations whose behavior just engaged (form widgets under a fill\n // tool) leave the selection, so no chrome is stranded on a fill control.\n annotation.pruneEngagedSelection();\n // Leaving the armed stamp's own tool drops the payload: the bytes belong\n // to the tool, not the document. The legacy-free check is the tool id;\n // embedder tools tagged 'annotation-stamp' also hold a payload.\n const active = interaction.getActiveTool();\n if (active.id !== ARMED_STAMP_TOOL_ID && !active.enables.has('annotation-stamp')) {\n annotation.stamps.disarm();\n }\n });\n\n // The selection → markup bridge exists only when a selection plugin does.\n if (selection) wireMarkup(annotation, selection, interaction);\n}\n","/**\n * The annotation plugin's state and its transitions.\n *\n * Three kinds of data make up what the user sees, and each has one owner:\n *\n * confirmed the engine's records the records mirror (sync/records.ts)\n * pending this session's changes the the kernel's change queue (`ctx.changes`);\n * engine hasn't answered the records mirror predicts them\n * session selection, gestures, settings `session` below, produced by the core's `update`\n *\n * The view (read/view.ts) composes the session with the records as the\n * mirror shows them (`records.view()`) into the core's `Model`.\n */\nimport { initialSession, sameSession } from '@embedpdf/core-annotation';\nimport type { EditableKinds, Id, Point, Session, SnapSettings } from '@embedpdf/core-annotation';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport type { PageRef } from '@embedpdf/engine-core/runtime';\n\nimport type { TextSelection } from './rich-text';\n\n/** Where the active tool's ghost is: the pointer on a page, and how that page shows there. */\nexport interface GhostPointer {\n readonly toolId: string;\n readonly page: PageRef;\n readonly point: Point;\n /** The page's display rotation at the pointer (an upright tool lays its click out as seen). */\n readonly displayRotation?: PageRotation;\n /** The page's zoom at the pointer (a screen-sized icon's size depends on it). */\n readonly zoom?: number;\n}\n\n/** A sibling plugin's placement gesture with one of this plugin's tools: its press, and the pointer now. */\nexport interface ForeignPlacement {\n readonly toolId: string;\n readonly page: PageRef;\n readonly from: Point;\n readonly to: Point;\n}\n\nexport interface AnnotationState {\n /** The core's session: selection, hover, the gesture in progress, tool settings. */\n readonly session: Session;\n /**\n * Records this session renders from their description instead of the\n * engine's raster: the ones it edited or created. Another session's edit\n * hands a record back to the raster (see sync/confirmed.ts).\n */\n readonly vector: Readonly<Record<Id, true>>;\n /**\n * Where the active tool's ghost is: the pointer, while a click there would\n * make something. Only the pointer is state; what the ghost paints is\n * derived from it and the tool's live defaults (tools/ghost.ts).\n */\n readonly ghostAt: GhostPointer | null;\n /**\n * A placement a sibling plugin's gesture is making with one of this\n * plugin's tools (the form palette's drag-to-place). Once it is a drag it\n * paints as a drawing in progress (tools/ghost.ts).\n */\n readonly placing: ForeignPlacement | null;\n /**\n * The text editor's selection inside the annotation being edited (flat\n * offsets over its plain text), or null. It is state because the property\n * surface reads it: while a range is held, the text style keys report and\n * change the runs, not the whole body.\n */\n readonly textSelection: TextSelection | null;\n}\n\n/** The initial state. The session's snapping and editable rule come from the settings (`withSnap`, `withEditable`). */\nexport const initialAnnotationState = (): AnnotationState => ({\n session: initialSession,\n vector: {},\n ghostAt: null,\n placing: null,\n textSelection: null,\n});\n\n/** The session snaps as the settings say. */\nexport const withSnap = (state: AnnotationState, snap: SnapSettings): AnnotationState =>\n state.session.snap === snap ? state : { ...state, session: { ...state.session, snap } };\n\n/** People change by hand what the settings' `editable` rule lets them. */\nexport const withEditable = (state: AnnotationState, editable: EditableKinds): AnnotationState =>\n state.session.editable === editable\n ? state\n : { ...state, session: { ...state.session, editable } };\n\n/* ── the session and render preferences ──────────────────────────────── */\n\n/**\n * Record one message's session. The records it changed and drew live\n * (`vector`) render live from now on: this session's appearance is the one\n * its own painter draws.\n */\nexport function withSession(\n state: AnnotationState,\n session: Session,\n vector: readonly Id[] = [],\n): AnnotationState {\n const next = sameSession(state.session, session) ? state : { ...state, session };\n return preferVector(next, vector);\n}\n\n/** The session holds these object numbers too, for the records it creates next. */\nexport const withObjectNumbers = (\n state: AnnotationState,\n numbers: readonly number[],\n): AnnotationState =>\n numbers.length\n ? {\n ...state,\n session: {\n ...state.session,\n objectNumbers: [...state.session.objectNumbers, ...numbers],\n },\n }\n : state;\n\n/** The session lost these object numbers: the engine refuses a create that names one. */\nexport function withoutObjectNumbers(\n state: AnnotationState,\n lost: readonly number[],\n): AnnotationState {\n const gone = new Set(lost);\n const objectNumbers = state.session.objectNumbers.filter((number) => !gone.has(number));\n return objectNumbers.length === state.session.objectNumbers.length\n ? state\n : { ...state, session: { ...state.session, objectNumbers } };\n}\n\n/** Render these records live from their description. */\nexport function preferVector(state: AnnotationState, ids: readonly Id[]): AnnotationState {\n const added = ids.filter((id) => !state.vector[id]);\n if (!added.length) return state;\n const vector = { ...state.vector };\n for (const id of added) vector[id] = true;\n return { ...state, vector };\n}\n\n/** Render these records from the engine's raster again. */\nexport function preferBaked(state: AnnotationState, ids: readonly Id[]): AnnotationState {\n const removed = ids.filter((id) => state.vector[id]);\n if (!removed.length) return state;\n const vector = { ...state.vector };\n for (const id of removed) delete vector[id];\n return { ...state, vector };\n}\n\n/* ── ghost and text selection ─────────────────────────────────────────────── */\n\nexport const setGhostAt = (\n state: AnnotationState,\n ghostAt: GhostPointer | null,\n): AnnotationState => (state.ghostAt === ghostAt ? state : { ...state, ghostAt });\n\nexport const setPlacing = (\n state: AnnotationState,\n placing: ForeignPlacement | null,\n): AnnotationState => (state.placing === placing ? state : { ...state, placing });\n\nexport const setTextSelection = (\n state: AnnotationState,\n textSelection: TextSelection | null,\n): AnnotationState => (state.textSelection === textSelection ? state : { ...state, textSelection });\n","import { PluginError } from '@embedpdf/core';\nimport { isEditableByHand, type ModelAnnotation, type Model } from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type Annotation,\n type AnnotationRef,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationFilter } from '../contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\n\n/**\n * The public reads: the engine's records as the user sees them. Each is the\n * annotation a record in the view holds (the engine's read, with this\n * session's pending changes applied as the engine will apply them), so a read\n * is reference-stable until its annotation changes, and a new annotation\n * reads before the engine confirms it. A lent record (a form widget in design\n * mode) reads by its ref and in the selection, and lists with its owner's.\n */\nexport function createAnnotationReads(\n ctx: Pick<AnnotationContext, 'getPage'>,\n { store, records, lending }: Pick<AnnotationServices, 'store' | 'records' | 'lending'>,\n) {\n const get = (ref: AnnotationRef): Annotation | null =>\n store.model().byId[annotationKey(ref)]?.annotation ?? null;\n\n /** Whether a change of this session to it waits for the engine: it shows other than the engine has it. */\n const isPending = (ref: AnnotationRef): boolean => {\n const key = annotationKey(ref);\n return records.view().byKey[key] !== records.get().byKey[key];\n };\n\n /**\n * The object numbers of the pages a filter names; `null` without a page\n * filter. A page that isn't in the document names none: its list is empty.\n */\n const pagesOf = (filter?: AnnotationFilter): ReadonlySet<number> | null => {\n if (!filter?.pages) return null;\n const numbers = new Set<number>();\n for (const page of filter.pages) {\n const info = ctx.getPage(page);\n if (info) numbers.add(info.ref.objectNumber);\n }\n return numbers;\n };\n\n const listAnnots = (filter?: AnnotationFilter): ModelAnnotation[] => {\n const model = store.model();\n const pages = pagesOf(filter);\n return model.order\n .map((id) => model.byId[id])\n .filter((record): record is ModelAnnotation => record !== undefined)\n .filter(\n (record) =>\n !lending.owns(record.id) &&\n (!pages || pages.has(record.annotation.page.objectNumber)) &&\n (!filter?.subtype || record.annotation.subtype === filter.subtype),\n );\n };\n const annotationsOf = (records: readonly ModelAnnotation[]): Annotation[] =>\n records.map((record) => record.annotation);\n\n // Unfiltered and one-page lists are what layers subscribe to: memoized per model.\n let listMemo: { model: Model; v: readonly Annotation[] } | null = null;\n const pageListMemo = new Map<number, { model: Model; v: readonly Annotation[] }>();\n const list = (filter?: AnnotationFilter): readonly Annotation[] => {\n const model = store.model();\n if (!filter || (!filter.pages && filter.subtype === undefined)) {\n if (listMemo?.model !== model) listMemo = { model, v: annotationsOf(listAnnots()) };\n return listMemo.v;\n }\n const page = filter.pages?.length === 1 ? ctx.getPage(filter.pages[0]!) : null;\n if (page && filter.subtype === undefined) {\n const pageObjectNumber = page.ref.objectNumber;\n const hit = pageListMemo.get(pageObjectNumber);\n if (hit?.model === model) return hit.v;\n const pageList = annotationsOf(listAnnots(filter));\n pageListMemo.set(pageObjectNumber, { model, v: pageList });\n return pageList;\n }\n return annotationsOf(listAnnots(filter));\n };\n\n let selectedMemo: { model: Model; v: readonly Annotation[] } | null = null;\n const listSelected = (): readonly Annotation[] => {\n const model = store.model();\n if (selectedMemo?.model !== model) {\n selectedMemo = {\n model,\n v: annotationsOf(\n model.selected\n .map((id) => model.byId[id])\n .filter((record): record is ModelAnnotation => !!record),\n ),\n };\n }\n return selectedMemo.v;\n };\n\n /** The page a ref lives on: where the record was read, else the ref's own page. */\n const pageOf = (ref: AnnotationRef): PageRef =>\n store.model().byId[annotationKey(ref)]?.annotation.page ?? ref.page;\n\n const loadedOrThrow = (ref: AnnotationRef): ModelAnnotation => {\n const record = store.model().byId[annotationKey(ref)];\n if (!record) {\n throw new PluginError('not-found', 'annotation', 'annotation is not loaded in this document');\n }\n return record;\n };\n /** The records in the current selection. */\n const selectedRecords = (): ModelAnnotation[] => {\n const model = store.model();\n return model.selected\n .map((id) => model.byId[id])\n .filter((record): record is ModelAnnotation => !!record);\n };\n\n /** The annotation under the pointer, as the user sees it. */\n const getHovered = (): Annotation | null => {\n const model = store.model();\n return model.hovered ? (model.byId[model.hovered]?.annotation ?? null) : null;\n };\n\n /** The text box being typed in. */\n const getEditing = (): Annotation | null => {\n const model = store.model();\n return model.editing ? (model.byId[model.editing]?.annotation ?? null) : null;\n };\n\n /** Whether the `editable` setting lets people change it by hand. */\n const isEditable = (ref: AnnotationRef): boolean => {\n const model = store.model();\n const record = model.byId[annotationKey(ref)];\n return !!record && isEditableByHand(model, record.annotation);\n };\n\n const api = { get, list, isPending, getHovered, isEditable };\n\n return {\n get,\n listAnnots,\n listSelected,\n getEditing,\n loadedOrThrow,\n selectedRecords,\n pageOf,\n api,\n };\n}\n\nexport type AnnotationReads = ReturnType<typeof createAnnotationReads>;\n","import type { Rect, ViewEnv } from '@embedpdf/core-annotation';\nimport type { PdfRect, PdfSize } from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext } from './context';\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). */\nexport const viewEnv = (zoom?: number, rotation?: number): ViewEnv | undefined =>\n zoom != null || rotation != null\n ? { zoom: zoom ?? 1, rotation: (rotation ?? 0) as ViewEnv['rotation'] }\n : undefined;\n\n/** Each page's size and crop box, as the document registry reports them. */\nexport function createPageLookup(ctx: Pick<AnnotationContext, 'document'>) {\n const layoutOf = (pageObjectNumber: number) =>\n ctx.document()?.pages.find((pageInfo) => pageInfo.ref.objectNumber === pageObjectNumber);\n const sizeOf = (pageObjectNumber: number): PdfSize | null =>\n layoutOf(pageObjectNumber)?.size ?? null;\n /** The crop box in the file's numbers, for Acrobat scripts, which speak them. */\n const cropOf = (pageObjectNumber: number): PdfRect | null =>\n layoutOf(pageObjectNumber)?.pdfCropBox ?? null;\n /** The page's box — the box pointer gestures clamp to, so annotations stay\n * page-bound. */\n const pageBoxOf = (pageObjectNumber: number): Rect | undefined => {\n const size = sizeOf(pageObjectNumber);\n return size ? { x: 0, y: 0, ...size } : undefined;\n };\n return { sizeOf, cropOf, pageBoxOf };\n}\n\nexport type PageLookup = ReturnType<typeof createPageLookup>;\n","import {\n anchorModeOf,\n annotationAnchor,\n canMove,\n chrome as coreChrome,\n type ChromeGeometry,\n type ChromeNode,\n cursorAt,\n hitTest,\n type Id,\n isOnTextBox,\n type Model,\n type Point,\n type Rect,\n rotationAnchor,\n type RotationAnchor,\n selectionAnchor as coreSelectionAnchor,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type Annotation,\n type AnnotationRef,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationAnchor, AnnotationSelectionAnchor, ChromeSettings } from '../contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { viewEnv } from '../services/geometry';\n\n/** The view a pointer sample arrives in: px per page unit, display rotation, relative zoom. */\nexport interface HitView {\n scale?: number;\n rotation?: number;\n zoom?: number;\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. */\nexport const TOUCH_GRAB_BOOST = 2;\n\n/**\n * Selection chrome and hit-testing: the chrome nodes a page paints, the\n * selection anchor, and every \"what is under this point\" question, all\n * projected through the live chrome settings and the page's view scale.\n */\nexport function createChromeReads(\n ctx: Pick<AnnotationContext, 'getPage'>,\n {\n store,\n geometry,\n behaviors,\n settings,\n }: Pick<AnnotationServices, 'store' | 'geometry' | 'behaviors' | 'settings'>,\n) {\n const chromeSettings = (): ChromeSettings => settings.get().chrome;\n\n /** The CSS-px chrome settings converted to content units by the page's view\n * scale (px per page 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): ChromeGeometry => {\n const cs = chromeSettings();\n const effectiveScale = scale || 1;\n return {\n handleTol: (cs.handles.hitSize / 2 / effectiveScale) * boost,\n knobTol: (cs.rotationHandle.hitSize / 2 / effectiveScale) * boost,\n knobOffset: cs.rotationHandle.offset / effectiveScale,\n rotationHandle: cs.rotationHandle.enabled,\n };\n };\n const grabBoost = (touch?: boolean): number => (touch ? TOUCH_GRAB_BOOST : 1);\n /** The hit margin, a screen-pixel setting, in content units at the view scale. */\n const hitMarginAt = (scale?: number): number => store.model().hitMargin / (scale || 1);\n\n /** The core hit-test with this plugin's inputs filled in: chrome geometry\n * at the view scale, the page box, and the engaged (inert) ids. Pass\n * `inert: null` to test with no inert set at all. */\n const hitAt = (\n page: PageRef,\n point: Point,\n view: HitView = {},\n boost = 1,\n inert: ReadonlySet<Id> | null | undefined = undefined,\n ) => {\n const model = store.model();\n const pageObjectNumber = page.objectNumber;\n return hitTest(\n model,\n page,\n point,\n chromeGeomAt(view.scale, boost),\n hitMarginAt(view.scale),\n geometry.pageBoxOf(pageObjectNumber),\n inert === undefined ? behaviors.engagedIdsOn(pageObjectNumber) : (inert ?? undefined),\n viewEnv(view.zoom, view.rotation),\n );\n };\n\n /**\n * The text box whose box is under `point`: where a double-click edits its\n * text. Its body or a resize handle on its border counts; a callout's line,\n * its tip and knee, and the empty rest of its frame don't.\n */\n const textBoxAt = (page: PageRef, point: Point, view: HitView = {}): Id | null => {\n const target = hitAt(page, point, view, 1, null);\n const id = target.kind === 'annot' || target.kind === 'handle' ? target.id : null;\n const record = id != null ? store.model().byId[id] : undefined;\n const onBox =\n !!record &&\n isOnTextBox(\n record,\n point,\n chromeGeomAt(view.scale).handleTol,\n viewEnv(view.zoom, view.rotation),\n );\n return onBox ? id : null;\n };\n\n // Memoize the derived per-page arrays by input identity, so a selector returns\n // a stable reference between dispatches (useSyncExternalStore needs this — the\n // model object only changes when `update` produces a new one; chrome also keys\n // on the settings object + the page scale it was projected with).\n const 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 chromeNodesOf = (\n page: PageRef,\n scale?: number,\n rotation?: number,\n zoom?: number,\n ): ChromeNode[] => {\n const pageObjectNumber = page.objectNumber;\n const model = store.model();\n const cs = chromeSettings();\n const cached = chromeCache.get(pageObjectNumber);\n if (\n cached &&\n cached.model === model &&\n cached.cs === cs &&\n cached.scale === scale &&\n cached.rotation === rotation &&\n cached.zoom === zoom\n )\n return cached.v;\n let nodes = coreChrome(\n model,\n page,\n geometry.pageBoxOf(pageObjectNumber),\n chromeGeomAt(scale).knobOffset,\n viewEnv(zoom, rotation),\n );\n // `guides.enabled` and `rotationHandle.enabled` are presentation\n // settings, filtered here so the emitted chrome stays authoritative for\n // every painter (default and headless alike). A disabled rotation handle\n // can't be grabbed either (`chromeGeomAt`).\n if (!cs.guides.enabled) nodes = nodes.filter((node) => node.kind !== 'rotate-guides');\n if (!cs.rotationHandle.enabled) nodes = nodes.filter((node) => node.kind !== 'rotate-knob');\n chromeCache.set(pageObjectNumber, { model: model, cs, scale, rotation, zoom, v: nodes });\n return nodes;\n };\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: AnnotationSelectionAnchor | null;\n } | null = null;\n const selectionAnchorOf = (\n scale?: number,\n rotation?: number,\n zoom?: number,\n ): AnnotationSelectionAnchor | null => {\n const model = store.model();\n const cs = chromeSettings();\n if (\n anchorCache &&\n anchorCache.model === model &&\n anchorCache.cs === cs &&\n anchorCache.scale === scale &&\n anchorCache.rotation === rotation &&\n anchorCache.zoom === zoom\n )\n return anchorCache.v;\n const found = coreSelectionAnchor(\n model,\n (page) => geometry.pageBoxOf(page.objectNumber),\n () => chromeGeomAt(scale).knobOffset,\n () => viewEnv(zoom, rotation),\n );\n // Without a rotation handle, a menu has nothing to stay clear of.\n const anchor: AnnotationSelectionAnchor | null = found\n ? {\n page: found.page,\n bounds: found.bounds,\n ...(found.knob && cs.rotationHandle.enabled ? { rotationHandle: found.knob } : {}),\n }\n : null;\n anchorCache = { model: model, cs, scale, rotation, zoom, v: anchor };\n return anchor;\n };\n\n // One annotation's anchor, by ref and view: a new object only when it moved.\n const anchors = new Map<string, { model: Model; view?: ViewEnv; v: AnnotationAnchor | null }>();\n // A screen-anchored annotation's box in a view, read from the live model:\n // one function per annotation, so its anchor stays the same object while\n // people zoom.\n const boundsInByKey = new Map<string, (view: ViewEnv) => Rect | null>();\n const boundsInOf = (key: string, ref: AnnotationRef) => {\n let boundsIn = boundsInByKey.get(key);\n if (!boundsIn) {\n boundsIn = (view: ViewEnv) => {\n const model = store.model();\n const record = model.byId[annotationKey(ref)];\n return record ? (annotationAnchor(model, record.id, view)?.bounds ?? null) : null;\n };\n boundsInByKey.set(key, boundsIn);\n }\n return boundsIn;\n };\n const annotationAnchorOf = (ref: AnnotationRef, view?: ViewEnv): AnnotationAnchor | null => {\n const model = store.model();\n const key = annotationKey(ref);\n const cached = anchors.get(key);\n if (\n cached &&\n cached.model === model &&\n cached.view?.zoom === view?.zoom &&\n cached.view?.rotation === view?.rotation\n )\n return cached.v;\n const record = model.byId[annotationKey(ref)];\n if (!record) boundsInByKey.delete(key);\n const box = record ? annotationAnchor(model, record.id, view) : null;\n // Without a view, a note that keeps its size on screen says where it is in any view.\n const found: AnnotationAnchor | null =\n box && record && !view && anchorModeOf(record)\n ? { ...box, boundsIn: boundsInOf(key, ref) }\n : box;\n const previous = cached?.v ?? null;\n const anchor =\n found &&\n previous &&\n previous.page.objectNumber === found.page.objectNumber &&\n previous.bounds.x === found.bounds.x &&\n previous.bounds.y === found.bounds.y &&\n previous.bounds.width === found.bounds.width &&\n previous.bounds.height === found.bounds.height &&\n previous.boundsIn === found.boundsIn\n ? previous\n : found;\n anchors.set(key, { model, view, v: anchor });\n return anchor;\n };\n\n /**\n * The topmost annotation at a page point: the one under it, or the\n * selection's first when the point is on its handles; `null` on a page that\n * isn't in the document.\n */\n const annotationAt = (page: PageRef | number, point: Point): Annotation | null => {\n const info = ctx.getPage(page);\n if (!info) return null;\n const model = store.model();\n const target = hitAt(info.ref, point);\n if (target.kind === 'annot') return model.byId[target.id]?.annotation ?? null;\n if (target.kind === 'empty') return null;\n // A handle or the rotation handle belongs to the selection.\n const first = model.selected[0];\n return first ? (model.byId[first]?.annotation ?? null) : null;\n };\n\n /** The rotation in progress, cached per model: the same object until it changes. */\n let rotationCache: { model: Model; v: RotationAnchor | null } | null = null;\n const rotationOf = (): RotationAnchor | null => {\n const model = store.model();\n if (rotationCache && rotationCache.model === model) return rotationCache.v;\n const rotation = rotationAnchor(model);\n rotationCache = { model, v: rotation };\n return rotation;\n };\n\n const api = {\n listChromeNodes: (page: PageRef, scale?: number, rotation?: number, zoom?: number) =>\n chromeNodesOf(page, scale, rotation, zoom),\n getSelectionAnchorIn: (view: HitView) =>\n selectionAnchorOf(view.scale, view.rotation, view.zoom),\n getAnnotationAnchor: (ref: AnnotationRef, view?: ViewEnv) => annotationAnchorOf(ref, view),\n getHitKind: (\n page: PageRef,\n point: Point,\n scale?: number,\n rotation?: number,\n zoom?: number,\n touch?: boolean,\n ) => hitAt(page, point, { scale, rotation, zoom }, grabBoost(touch)).kind,\n claimsTouchAt: (\n page: PageRef,\n point: Point,\n scale?: number,\n rotation?: number,\n zoom?: number,\n ) => {\n const model = store.model();\n const target = hitAt(page, point, { scale, rotation, zoom }, TOUCH_GRAB_BOOST);\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 (target.kind === 'handle' || target.kind === 'rotate' || target.kind === 'group-handle')\n 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 (target.kind === 'annot') {\n return (\n model.selected.includes(target.id) && model.selected.every((id) => canMove(model, id))\n );\n }\n return false;\n },\n getCursorAt: (\n page: PageRef,\n point: Point,\n scale?: number,\n rotation?: number,\n zoom?: number,\n ) => {\n const pageObjectNumber = page.objectNumber;\n const model = store.model();\n return cursorAt(\n model,\n page,\n point,\n chromeGeomAt(scale),\n hitMarginAt(scale),\n geometry.pageBoxOf(pageObjectNumber),\n behaviors.engagedIdsOn(pageObjectNumber),\n viewEnv(zoom, rotation),\n );\n },\n };\n\n return {\n chromeSettings,\n chromeGeomAt,\n grabBoost,\n hitAt,\n textBoxAt,\n annotationAt,\n selectionAnchor: () => selectionAnchorOf(),\n rotationAnchor: () => rotationOf(),\n api,\n };\n}\n\nexport type ChromeReads = ReturnType<typeof createChromeReads>;\n","/**\n * Rich text policy — what the annotation plugin decides about a free-text\n * annotation's rich document, kept pure so every framework's editor glue\n * behaves identically (the mechanics live in `@embedpdf/web`'s binding; the\n * run algebra, an annotation's rich document and a font's face in the core):\n *\n * • a flat props patch → the run delta it means for a text range (font,\n * size, colour, bold/italic/underline) and the keys left for the body\n * • what a range reads back for those keys (agree → the value, else mixed)\n * • faces: the DTO font a face names, and a CSS family list for either\n * • the commit rule: a document nothing overrides on a plain annotation\n * commits as `contents`; anything else as `richText`\n */\nimport {\n faceForFont,\n mountedFontFamily,\n STANDARD_FONT_STACKS,\n type FieldValues,\n type FontLookup,\n locateOffset,\n type ModelAnnotation,\n richDocOf,\n type RichTextRange,\n type RichTextStyleDelta,\n} from '@embedpdf/core-annotation';\nimport {\n STANDARD_FACES,\n type RichTextBody,\n type RichTextDocument,\n type RichTextParagraph,\n type RichTextRunStyle,\n} from '@embedpdf/engine-core/runtime';\n\nexport type TextFormat = 'bold' | 'italic' | 'underline';\n\n/** The editor's selection inside one free-text annotation: flat offsets over\n * the plain projection (paragraphs joined by `\\r`). */\nexport interface TextSelection extends RichTextRange {\n id: string;\n}\n\n/** The face a run or a body names. */\nexport interface Face {\n family: string;\n weight?: number;\n italic?: boolean;\n}\n\n/** The fields a text range takes as run deltas: its font, size and colour, and the formats. */\nexport const RANGE_KEYS: readonly string[] = [\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'bold',\n 'italic',\n 'underline',\n];\n\n// ---- Faces ---------------------------------------------------------------------\n\ntype StandardFamily = (typeof STANDARD_FACES)[keyof typeof STANDARD_FACES]['family'];\n\n/** Family names compare without case, spaces, hyphens, underscores and\n * quotes — the engine's own rule. */\nexport function familyKey(family: string): string {\n return family.toLowerCase().replace(/[\\s\\-_'\"]/g, '');\n}\n\nconst STANDARD_FAMILY_KEYS: Record<string, StandardFamily> = {\n helvetica: 'Helvetica',\n arial: 'Helvetica',\n arialmt: 'Helvetica',\n sansserif: 'Helvetica',\n times: 'Times',\n timesroman: 'Times',\n timesnewroman: 'Times',\n timesnewromanpsmt: 'Times',\n serif: 'Times',\n courier: 'Courier',\n couriernew: 'Courier',\n couriernewpsmt: 'Courier',\n monospace: 'Courier',\n symbol: 'Symbol',\n zapfdingbats: 'ZapfDingbats',\n dingbats: 'ZapfDingbats',\n};\n\n/** The DTO font for a face: the registered key whose identity matches (the\n * closest weight, italic first), else the standard kebab name, else the\n * family itself. The inverse of {@link faceForFont}. */\nexport function fontForFace(face: Face, fonts?: FontLookup): string {\n const wanted = familyKey(face.family);\n const weight = face.weight ?? 400;\n const italic = face.italic ?? false;\n let best: { key: string; score: number } | undefined;\n for (const handle of fonts?.() ?? []) {\n if (familyKey(handle.familyName) !== wanted) continue;\n const score = Math.abs(handle.weight - weight) + (handle.italic === italic ? 0 : 1000);\n if (!best || score < best.score) best = { key: handle.key, score };\n }\n if (best) return best.key;\n const standard = STANDARD_FAMILY_KEYS[wanted];\n if (standard) {\n const bold = weight >= 600;\n for (const [name, spec] of Object.entries(STANDARD_FACES)) {\n if (spec.family === standard && spec.weight >= 600 === bold && spec.italic === italic) {\n return name;\n }\n }\n for (const [name, spec] of Object.entries(STANDARD_FACES)) {\n if (spec.family === standard) return name; // Symbol/ZapfDingbats: one face\n }\n }\n return face.family;\n}\n\n/** The CSS family list for a face family: a standard family's web stack, a\n * registered family's mounted `@font-face` ({@link mountedFontFamily}), else\n * the family itself with a generic fallback. A DTO font's list is\n * `cssFontFamilyForFont`'s, in `@embedpdf/core-annotation`. */\nexport function cssFontFamilyForFace(family: string, fonts?: FontLookup): string {\n const standard = STANDARD_FAMILY_KEYS[familyKey(family)];\n if (standard) return STANDARD_FONT_STACKS[standard];\n const wanted = familyKey(family);\n const registered = fonts?.().find((handle) => familyKey(handle.familyName) === wanted);\n if (registered) return mountedFontFamily(registered.key);\n return `\"${family}\", sans-serif`;\n}\n\n// ---- Documents -----------------------------------------------------------------\n\nconst hex = (css: string): string => css.trim().toUpperCase();\n\n/**\n * The write a text edit commits: the rich paragraphs, with paragraph\n * properties equal to the body's stripped (they are inherited, not\n * overrides) and the body omitted — it stays what the props path last\n * wrote. One engine, one path: plain and formatted text alike.\n */\nexport function textCommitPatch(\n record: ModelAnnotation,\n paragraphs: RichTextParagraph[],\n fonts?: FontLookup,\n): { richText: { paragraphs: RichTextParagraph[] } } {\n return {\n richText: {\n paragraphs: stripBodyDefaults(paragraphs, richDocOf(record.annotation, fonts).body),\n },\n };\n}\n\n/**\n * Paragraph alignment/direction equal to the body's are not overrides: the\n * engine echoes them resolved, the editor renders them as inline styles and\n * serialises them back, and the commit rule must see through that (a plain\n * `/Contents` annotation must not grow an `/RC` from typing).\n */\nexport function stripBodyDefaults(\n paragraphs: RichTextParagraph[],\n body: Pick<RichTextBody, 'align' | 'dir'>,\n): RichTextParagraph[] {\n return paragraphs.map((paragraph) => {\n if (\n (paragraph.align === undefined || paragraph.align !== body.align) &&\n (paragraph.dir === undefined || paragraph.dir !== body.dir)\n ) {\n return paragraph;\n }\n const { align, dir, ...rest } = paragraph;\n return {\n ...rest,\n ...(align !== undefined && align !== body.align ? { align } : {}),\n ...(dir !== undefined && dir !== body.dir ? { dir } : {}),\n };\n });\n}\n\n// ---- Props ↔ runs --------------------------------------------------------------\n\n/**\n * Split a patch for an annotation whose editor holds a text range: the run\n * delta the range takes (font → face, size, colour, and the formats: bold →\n * weight, italic, underline → decoration) and the fields that still go to the\n * annotation.\n */\nexport function runDeltaForFields(\n patch: FieldValues,\n fonts?: FontLookup,\n): { delta: RichTextStyleDelta; rest: Record<string, unknown> } {\n const delta: RichTextStyleDelta = {};\n const rest: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue;\n switch (key) {\n case 'fontFamily': {\n const face = faceForFont(value as string, fonts);\n delta.family = face.family;\n if (face.weight !== undefined) delta.weight = face.weight;\n if (face.italic !== undefined) delta.italic = face.italic;\n break;\n }\n case 'fontSize':\n delta.size = value as number;\n break;\n case 'fontColor':\n delta.color = hex(value as string);\n break;\n case 'bold':\n delta.weight = value ? 700 : 400;\n break;\n case 'italic':\n delta.italic = value as boolean;\n break;\n case 'underline':\n delta.decoration = value ? ['underline'] : [];\n break;\n default:\n rest[key] = value;\n }\n }\n return { delta, rest };\n}\n\n/** The style deltas of every non-empty run a range overlaps. */\nexport function runsInRange(\n doc: { paragraphs: readonly RichTextParagraph[] },\n range: RichTextRange,\n): RichTextStyleDelta[] {\n const start = Math.min(range.start, range.end);\n const end = Math.max(range.start, range.end);\n if (end <= start) return [];\n const from = locateOffset(doc, start);\n const to = locateOffset(doc, end);\n const out: RichTextStyleDelta[] = [];\n for (let index = from.paragraph; index <= to.paragraph; index++) {\n const paragraph = doc.paragraphs[index]!;\n const localStart = index === from.paragraph ? from.offset : 0;\n const localEnd =\n index === to.paragraph\n ? to.offset\n : paragraph.runs.reduce((total, run) => total + run.text.length, 0);\n let pos = 0;\n for (const run of paragraph.runs) {\n const runEnd = pos + run.text.length;\n if (runEnd > localStart && pos < localEnd && run.text.length > 0) out.push(run.style ?? {});\n pos = runEnd;\n }\n }\n return out;\n}\n\n/** The values a range reads back for the range keys — resolved against the\n * body, one value where every run agrees, `mixed` where they don't. */\nexport function rangeProps(\n doc: RichTextDocument,\n range: RichTextRange,\n fonts?: FontLookup,\n): { values: Record<string, unknown>; mixed: string[] } {\n const runs = runsInRange(doc, range);\n const body = doc.body;\n const resolve = (delta: RichTextStyleDelta): Partial<RichTextRunStyle> => ({\n family: delta.family ?? body.family,\n weight: delta.weight ?? body.weight,\n italic: delta.italic ?? body.italic,\n size: delta.size ?? body.size,\n color: delta.color ?? body.color,\n decoration: delta.decoration ?? body.decoration,\n });\n const styles = (runs.length ? runs : [{}]).map(resolve);\n const values: Record<string, unknown> = {};\n const mixed: string[] = [];\n const read = (key: string, of: (style: Partial<RichTextRunStyle>) => unknown) => {\n const first = of(styles[0]!);\n values[key] = first;\n if (styles.some((style) => JSON.stringify(of(style)) !== JSON.stringify(first)))\n mixed.push(key);\n };\n // The family reads back at the body's weight/italic: a run's own weight\n // and italic are the bold/italic toggles, not a different font (\"Helvetica\"\n // stays \"helvetica\" while bold, never flips to \"helvetica-bold\").\n read('fontFamily', (style) =>\n fontForFace({ family: style.family!, weight: body.weight, italic: body.italic }, fonts),\n );\n read('fontSize', (style) => style.size);\n read('fontColor', (style) => style.color!.toLowerCase());\n read('bold', (style) => (style.weight ?? 400) >= 600);\n read('italic', (style) => !!style.italic);\n read('underline', (style) => (style.decoration ?? []).includes('underline'));\n return { values, mixed };\n}\n","/**\n * The values a style panel shows for a list of properties: the annotation's\n * (or a tool's defaults') engine fields by name. Three read differently: the\n * border's value is `borderStyle`, `dashArray` and `cloudyIntensity`; a text's\n * font, size, colour, alignment and formats read as the text shows them; and\n * the link is an attached link's target, not a field.\n */\nimport type { AnnotationProperty, FieldValues, TextStyle } from '@embedpdf/core-annotation';\n\n/** The fields a text shows resolved: a free text's colour follows `color` when it has no `fontColor`. */\nconst TEXT_KEYS: ReadonlySet<string> = new Set([\n 'fontFamily',\n 'fontSize',\n 'fontColor',\n 'textAlign',\n 'bold',\n 'italic',\n 'underline',\n]);\n\nconst FORMATS: ReadonlySet<string> = new Set(['bold', 'italic', 'underline']);\n\n/** What a panel reads beside the engine fields. */\nexport interface PropertySources {\n /** The engine fields, by name. */\n readonly data: FieldValues;\n /** The text as it shows, for a kind with text. */\n readonly text?: TextStyle;\n /** Where it links to, `null` for nowhere. */\n readonly link?: unknown;\n}\n\n/** One property's value, by its key (the border's is its three fields). */\nexport function propertyValue(\n spec: AnnotationProperty,\n { data, text, link }: PropertySources,\n): unknown {\n if (spec.key === 'link') return link ?? null;\n if (spec.key === 'borderStyle') {\n return {\n borderStyle: data.borderStyle ?? 'solid',\n dashArray: data.dashArray ?? null,\n cloudyIntensity: data.cloudyIntensity ?? null,\n };\n }\n if (text && TEXT_KEYS.has(spec.key)) {\n // A format the text doesn't set is off.\n return text[spec.key as keyof TextStyle] ?? (FORMATS.has(spec.key) ? false : undefined);\n }\n return data[spec.key];\n}\n\n/** Every property's value, by key: the border spreads into its three fields. */\nexport function propertyValues(\n properties: readonly AnnotationProperty[],\n sources: PropertySources,\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n for (const spec of properties) {\n const value = propertyValue(spec, sources);\n if (spec.key === 'borderStyle') Object.assign(values, value);\n else values[spec.key] = value;\n }\n return values;\n}\n","import {\n isEditableByHand,\n kindOf,\n linkOf,\n type Model,\n type ModelAnnotation,\n richDocOf,\n sharedProperties,\n textOf,\n} from '@embedpdf/core-annotation';\n\nimport type { AnnotationProperties } from '../contract';\nimport { RANGE_KEYS, rangeProps, type TextSelection } from '../rich-text';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { propertyValue, propertyValues, type PropertySources } from './property-values';\n\n/**\n * The selection's style-panel properties, flags included, memoized by model\n * identity so a subscribed panel re-renders only when the model changed. Only\n * the members people may change by hand count (the `editable` setting): a\n * selection of frozen annotations has nothing to restyle.\n */\nexport function createPropertyReads(\n ctx: Pick<AnnotationContext, 'state'>,\n { store, fonts }: Pick<AnnotationServices, 'store' | 'fonts'>,\n) {\n /** The editor's text range inside the annotation being edited, or null\n * (no editor selection, a bare caret, or a selection left behind by a\n * previous edit). The one condition that routes the range properties to runs. */\n const activeTextRange = (model: Model): TextSelection | null => {\n const ts = ctx.state.get().textSelection;\n return ts && model.editing === ts.id && ts.end > ts.start && model.byId[ts.id] ? ts : null;\n };\n\n /** What a panel reads of one member: its fields, its text as shown, and its link. */\n const sourcesOf = (model: Model, record: ModelAnnotation): PropertySources => {\n const annotation = record.annotation;\n const text = textOf(annotation);\n return {\n data: annotation as unknown as Record<string, unknown>,\n ...(text ? { text } : {}),\n // Parents store no link: the committed children are the truth, read\n // through the lens. A link annotation reads its own target.\n link: annotation.subtype === 'link' ? (annotation.target ?? null) : linkOf(model, record.id),\n };\n };\n\n let cache: { model: Model; range: TextSelection | null; v: AnnotationProperties } | null = null;\n const selectionPropertiesOf = (): AnnotationProperties => {\n const model = store.model();\n const range = activeTextRange(model);\n if (cache && cache.model === model && cache.range === range) return cache.v;\n const members = model.selected\n .map((id) => model.byId[id])\n .filter(\n (record): record is ModelAnnotation =>\n !!record && isEditableByHand(model, record.annotation),\n );\n const properties = sharedProperties(members.map((record) => kindOf(record.annotation)));\n const sources = members.map((record) => sourcesOf(model, record));\n const values = sources.length ? propertyValues(properties, sources[0]!) : {};\n const mixed: string[] = [];\n for (const spec of properties) {\n const first = JSON.stringify(propertyValue(spec, sources[0]!));\n if (sources.some((source) => JSON.stringify(propertyValue(spec, source)) !== first))\n mixed.push(spec.key);\n }\n // While the editor holds a range in the (sole) selected free text, the\n // range properties report the runs it covers, resolved against the body:\n // the same values `selection.update` would restyle.\n if (range && members.length === 1 && members[0]!.id === range.id) {\n const rp = rangeProps(richDocOf(members[0]!.annotation, fonts), range, fonts);\n for (const spec of properties) {\n if (!RANGE_KEYS.includes(spec.key)) continue;\n values[spec.key] = rp.values[spec.key];\n const index = mixed.indexOf(spec.key);\n if (index >= 0) mixed.splice(index, 1);\n if (rp.mixed.includes(spec.key)) mixed.push(spec.key);\n }\n }\n const result: AnnotationProperties = { properties, values, mixed };\n cache = { model, range, v: result };\n return result;\n };\n\n return { activeTextRange, selectionPropertiesOf };\n}\n\nexport type PropertyReads = ReturnType<typeof createPropertyReads>;\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, shared across\n * every web framework; the font's CSS family is the core's `cssFontFamilyForFont`.\n */\nimport {\n cssFontFamilyForFont,\n initialTextStyle,\n type Model,\n refOf,\n richDocOf,\n textBoxes,\n textPlateInset,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport type { PageRef } from '@embedpdf/engine-core/runtime';\n\nimport type { TextItem } from './contract';\nimport { stripBodyDefaults } from './rich-text';\nimport { styleOf, textOf } from '@embedpdf/core-annotation';\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(model: Model, page: PageRef, view?: ViewEnv): TextItem[] {\n return textBoxes(model, page, view).map((tb) => {\n const record = model.byId[tb.id];\n // The text shows the user's pending change (a props edit lands here\n // before the engine confirms it), so the editor restyles instantly.\n const style = (record && textOf(record.annotation)) ?? initialTextStyle;\n // Match the engine's text plate inset. Browser font metrics and line\n // heights belong to the shared editor binding.\n const sw = record ? styleOf(record.annotation).strokeWidth : 0;\n const doc = record ? richDocOf(record.annotation) : null;\n return {\n id: tb.id,\n ref: refOf(record),\n box: tb.box,\n contents: record?.annotation.contents ?? '',\n // Paragraph alignment/direction equal to the body's is inherited, not\n // an override: the element carries the body's (`css.align`), so a\n // block must not pin itself to a resolved value — or the Align\n // buttons (which move the body) would stop moving the text.\n richText: {\n paragraphs: doc ? stripBodyDefaults(doc.paragraphs, doc.body) : [{ runs: [{ text: '' }] }],\n },\n editing: tb.editing,\n ...(tb.rot ? { rot: tb.rot } : {}),\n css: {\n fontFamily: cssFontFamilyForFont(style.fontFamily),\n fontSize: style.fontSize,\n color: style.fontColor,\n fontWeight: style.bold ? 700 : 400,\n fontStyle: style.italic ? 'italic' : 'normal',\n textDecoration: style.underline ? 'underline' : 'none',\n align: style.textAlign,\n padding: textPlateInset(sw),\n },\n };\n });\n}\n","import {\n groupOf,\n isSubstrateOnly,\n type Model,\n pageItems as corePageItems,\n refOf,\n type RenderItem,\n shapeOf,\n viewable,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n imageSourceOfBytes,\n type AnnotationRef,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\nimport {\n RenderToken as RenderHostToken,\n type AppearanceFamily,\n type AppearanceItem,\n} from '@embedpdf/plugin-render/contract/host';\n\nimport type { LinkNavItem, TextItem } from '../contract';\nimport type { AnnotationAppearancePicture } from '../host-contract';\nimport type { AnnotationState } from '../model';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { buildTextItems } from '../text-item';\nimport type { Ghost } from '../tools/ghost';\nimport type { Stamps } from '../write/stamps';\n\n/**\n * What a page paints: the vector items (drafts, previews and the tool's\n * ghost ride the same pipeline), the editable text items, the navigable link\n * areas, and the baked-appearance seam (epoch and pictures). The engine's\n * pictures come through the render plugin, which shares and keeps them. A\n * stamp this session placed shows the preview it was placed with until the\n * engine's picture of it exists, and an annotation an undo brings back the\n * picture it had.\n */\nexport function createRenderReads(\n ctx: Pick<AnnotationContext, 'state' | 'document' | 'doc' | 'tryGet'>,\n { view: { pageModel }, lending }: Pick<AnnotationServices, 'view' | 'lending'>,\n ghost: Pick<Ghost, 'itemsOn'>,\n stamps: Pick<Stamps, 'lookOf'>,\n) {\n const itemsCache = new Map<\n number,\n {\n model: Model;\n ghostAt: AnnotationState['ghostAt'];\n placing: AnnotationState['placing'];\n zoom: number | undefined;\n rotation: number | undefined;\n v: RenderItem[];\n }\n >();\n const pageItemsOf = (page: PageRef, view?: ViewEnv): RenderItem[] => {\n const pageObjectNumber = page.objectNumber;\n const model = pageModel(pageObjectNumber);\n // The ghost and a sibling's placement count for their own page only, so\n // a ghost following the pointer recomputes that page alone.\n const state = ctx.state.get();\n const ghostAt = state.ghostAt?.page.objectNumber === pageObjectNumber ? state.ghostAt : null;\n const placing = state.placing?.page.objectNumber === pageObjectNumber ? state.placing : null;\n const cached = itemsCache.get(pageObjectNumber);\n if (\n cached &&\n cached.model === model &&\n cached.ghostAt === ghostAt &&\n cached.placing === placing &&\n cached.zoom === view?.zoom &&\n cached.rotation === view?.rotation\n )\n return cached.v;\n // The tool's ghost and a sibling's placement paint on top, as the\n // annotations they will be (tools/ghost.ts).\n const items = [\n ...corePageItems(model, page, view),\n ...ghost.itemsOn(pageObjectNumber, model, view),\n ];\n itemsCache.set(pageObjectNumber, {\n model,\n ghostAt,\n placing,\n zoom: view?.zoom,\n rotation: view?.rotation,\n v: items,\n });\n return items;\n };\n\n const textsCache = new Map<\n number,\n { model: Model; zoom: number | undefined; rotation: number | undefined; v: TextItem[] }\n >();\n const textItemsOf = (page: PageRef, view?: ViewEnv): TextItem[] => {\n const pageObjectNumber = page.objectNumber;\n const model = pageModel(pageObjectNumber);\n const cached = textsCache.get(pageObjectNumber);\n if (\n cached &&\n cached.model === model &&\n cached.zoom === view?.zoom &&\n cached.rotation === view?.rotation\n )\n return cached.v;\n const items = buildTextItems(model, page, view);\n textsCache.set(pageObjectNumber, {\n model: model,\n zoom: view?.zoom,\n rotation: view?.rotation,\n v: items,\n });\n return items;\n };\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 the page's slice of the model for selector use.\n const linkItemsCache = new Map<number, { model: Model; v: LinkNavItem[] }>();\n const linkItemsOf = (pageObjectNumber: number): LinkNavItem[] => {\n const model = pageModel(pageObjectNumber);\n const cached = linkItemsCache.get(pageObjectNumber);\n if (cached && cached.model === model) return cached.v;\n const items: LinkNavItem[] = [];\n for (const id of model.order) {\n const record = model.byId[id];\n const annotation = record?.annotation;\n if (\n !annotation ||\n annotation.page.objectNumber !== pageObjectNumber ||\n annotation.subtype !== 'link'\n )\n continue;\n if (!viewable(annotation, false)) continue; // hidden links don't navigate\n // A standalone link and an attached child both carry their own target.\n // Rects are the link's own committed geometry — anchors render only in\n // view contexts, where nothing is mid-gesture, so no live\n // parent-derivation is needed.\n const target = annotation.target ?? null;\n const geometry = shapeOf(annotation);\n if (target == null || geometry.kind !== 'box') continue;\n const activate = annotation.actions?.activate;\n const ref = refOf(record) ?? undefined;\n const hoverEnter = Boolean(annotation.actions?.cursorEnter?.root);\n const hoverExit = Boolean(annotation.actions?.cursorExit?.root);\n items.push({\n id,\n bounds: geometry.box,\n target,\n attached: groupOf(annotation) !== undefined,\n ...(activate ? { activate } : {}),\n ...(ref ? { ref } : {}),\n ...(hoverEnter || hoverExit ? { hoverEvents: { enter: hoverEnter, exit: hoverExit } } : {}),\n });\n }\n linkItemsCache.set(pageObjectNumber, { model: model, v: items });\n return items;\n };\n\n const api = {\n listPageItems: (page: PageRef, view?: ViewEnv) => pageItemsOf(page, view),\n listTextItems: (page: PageRef, view?: ViewEnv) => textItemsOf(page, view),\n listLinkItems: (page: PageRef) => linkItemsOf(page.objectNumber),\n getAppearanceEpoch: (page: PageRef) => {\n const { engine, placed, lent } = epochOf(page);\n const drawn = engine\n .map((item) => `${annotationKey(item.ref)}@${item.version}`)\n .sort()\n .join('|');\n return [drawn, placed, lent].filter(Boolean).join('|');\n },\n renderAppearances: (\n page: PageRef,\n scale: number,\n signal?: AbortSignal,\n ): Promise<AnnotationAppearancePicture[]> =>\n Promise.all([\n enginePictures(page, scale, epochOf(page).engine, signal),\n lentPictures(page, scale, signal),\n ownPictures(page, scale),\n ]).then(([theirs, lent, placed]) => [...theirs, ...lent, ...placed]),\n };\n\n /**\n * What a page's pictures depend on, and nothing else. `engine`: the\n * annotations the engine draws on it, each at its picture version\n * (`pictureVersion`, which advances when the engine confirms a re-bake).\n * `placed`: the stamps this session placed that the engine hasn't written\n * yet, which show the preview they were placed with, and the records an\n * undo brought back, which show the pictures kept of them. Position,\n * rotation and the state shown are absent: the blit translates (`apBox`)\n * and turns (`apRot`) the same pixels, and every state is held, so a move,\n * a spin or a switch costs no new picture. `lent`: the lender's epoch for\n * its records' pictures, when the page shows any of them.\n */\n const epochOf = (page: PageRef): { engine: AppearanceItem[]; placed: string; lent: string } => {\n const pageObjectNumber = page.objectNumber;\n const model = pageModel(pageObjectNumber);\n const engine: AppearanceItem[] = [];\n const placed: string[] = [];\n let lentShown = false;\n for (const id of model.order) {\n const record = model.byId[id];\n if (\n !record ||\n record.annotation.page.objectNumber !== pageObjectNumber ||\n record.source !== 'baked'\n )\n 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(record)) continue;\n if (record.unconfirmed) {\n if (stamps.lookOf(record)) placed.push(`${id}@placed`);\n else if (keptOf(id, record.annotation.ref).length) placed.push(`${id}@kept`);\n continue;\n }\n if (lending.owns(id)) {\n lentShown = true;\n continue;\n }\n engine.push({ ref: record.annotation.ref, version: record.pictureVersion ?? 0 });\n }\n const lender = lending.lender();\n return {\n engine,\n placed: placed.sort().join('|'),\n lent: lentShown && lender ? `lent:${lender.pictureEpoch(page)}` : '',\n };\n };\n\n /** The lender's pictures of its records on `page`, in every state, at their picture versions. */\n const lentPictures = (\n page: PageRef,\n scale: number,\n signal?: AbortSignal,\n ): Promise<readonly AnnotationAppearancePicture[]> => {\n const lender = lending.lender();\n const model = pageModel(page.objectNumber);\n const lends = model.order.some((id) => lending.owns(id) && !model.byId[id]!.unconfirmed);\n if (!lender || !lends) return Promise.resolve([]);\n return lender.renderAppearances(page, scale, signal).catch(() => []);\n };\n\n /** The engine's pictures of the page's annotations, through the render plugin; none without it. */\n const enginePictures = (\n page: PageRef,\n scale: number,\n items: readonly AppearanceItem[],\n signal?: AbortSignal,\n ): Promise<readonly AnnotationAppearancePicture[]> => {\n const render = ctx.tryGet(RenderHostToken);\n if (!render || !ctx.doc || items.length === 0) return Promise.resolve([]);\n return render\n .renderAppearances(page, {\n family: 'annotations',\n scale,\n items,\n ...(signal ? { signal } : {}),\n })\n .catch(() => []);\n };\n\n /** The family whose pictures a record's are: the lender's widgets, or annotations. */\n const familyOf = (id: string): AppearanceFamily => (lending.owns(id) ? 'widgets' : 'annotations');\n\n /** The engine's last pictures of a record, kept a while after it left its page. */\n const keptOf = (id: string, ref: AnnotationRef) =>\n ctx.tryGet(RenderHostToken)?.keptAppearances(familyOf(id), ref) ?? [];\n\n /**\n * The pictures of what shows on `page` that the engine hasn't written yet:\n * a stamp this session placed shows its preview, at the size the page shows\n * it, in its box (before its turn, which the layer puts back, as for the\n * engine's); an annotation an undo brings back shows the picture it had.\n */\n const ownPictures = async (\n page: PageRef,\n scale: number,\n ): Promise<AnnotationAppearancePicture[]> => {\n const model = pageModel(page.objectNumber);\n const pictures = model.order.map(async (id): Promise<AnnotationAppearancePicture[]> => {\n const record = model.byId[id]!;\n if (!record.unconfirmed) return [];\n const version = record.pictureVersion ?? 0;\n const look = stamps.lookOf(record);\n // Brought back as it was: the pictures kept of it are its look.\n if (!look) return keptOf(id, record.annotation.ref).map((kept) => ({ ...kept, version }));\n const rect = record.apBox;\n if (!rect) return [];\n const preview = await look(rect.width * scale);\n if (!preview) return [];\n return [\n {\n ref: record.annotation.ref,\n mode: 'normal',\n state: null,\n rect,\n image: imageSourceOfBytes(preview.bytes, preview.mimeType ?? 'image/png'),\n version,\n },\n ];\n });\n return (await Promise.all(pictures)).flat();\n };\n\n return { api };\n}\n","import { annotDeletable, annotTransformable } from '@embedpdf/core-annotation';\nimport { annotationKey, type AnnotationRef } from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext } from './context';\nimport type { AnnotationStore } from './store';\n\n/**\n * Authorization: the engine's own collab resolver, mirrored. `canCreate` asks\n * about the caller's own identity; the mutation checks ask about the target's\n * stamped owner, built from the record's EMBD metadata. An unstamped record\n * yields `{}`, which any narrowed grant denies — matching the engine, so a\n * control gated here never disagrees with the write's outcome.\n */\nexport function createAuthority(\n ctx: Pick<AnnotationContext, 'doc' | 'allows'>,\n store: AnnotationStore,\n) {\n const canRead = (): boolean => ctx.allows('doc.annotate.read');\n // What `ctx.assertAllowed('annotations:create', …)` refuses on, so the twin and the verbs agree.\n const canCreate = (): boolean => ctx.allows('annotations:create');\n\n const mutationTarget = (ref: AnnotationRef): { userId?: string; groupId?: string } => {\n const dto = store.model().byId[annotationKey(ref)]?.annotation;\n return {\n ...(dto?.userId != null ? { userId: dto.userId } : {}),\n ...(dto?.groupId != null ? { groupId: dto.groupId } : {}),\n };\n };\n const allowsMutation = (action: 'update' | 'delete', ref: AnnotationRef): boolean =>\n ctx.doc?.security.allowsAnnotation(action, mutationTarget(ref)) ?? false;\n\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 const canUpdate = (ref: AnnotationRef): boolean => {\n const record = store.model().byId[annotationKey(ref)];\n return !!record && annotTransformable(record);\n };\n const canDelete = (ref: AnnotationRef): boolean => {\n const record = store.model().byId[annotationKey(ref)];\n return !!record && annotDeletable(record);\n };\n\n return { canRead, canCreate, canUpdate, canDelete, allowsMutation };\n}\n\nexport type Authority = ReturnType<typeof createAuthority>;\n","/**\n * The view: what the user sees, as one pure function of the records and the\n * session.\n *\n * records.get() what the engine confirmed\n * records.view() that, with this session's pending changes on top (the\n * mirror replays them: `predictRecords`)\n * → AnnotationView, each record drawn as the change on it says\n * AnnotationView + session → Model\n *\n * Every read and every gesture takes this `Model`. It is memoized, and each\n * record keeps its identity until its own inputs change, so a hover or a\n * change to one record does not recompute the others.\n *\n * A lender's records (services/lending.ts) come after the annotations, so on\n * each page they paint above them, as form widgets do.\n */\nimport { memo, type Mirror } from '@embedpdf/core';\nimport {\n type AnnotationView,\n drawnAfter,\n fromDTO,\n type Id,\n type Model,\n type ModelAnnotation,\n sourceOfConfirmed,\n sourceOfNew,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n annotationPatchBetween,\n type Annotation,\n type AnnotationPatch,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationLender } from '../host-contract';\nimport type { AnnotationContext } from '../services/context';\nimport type { Lending } from '../services/lending';\nimport type { AnnotationRecord, AnnotationRecords } from '../sync/records';\n\n/**\n * This session's authority over a record (permissions.md): the same collab\n * mirrors the engine enforces with, asked about the record's stamped owner.\n * No security context (bare local engines, tests): unstamped, so allowed.\n */\nexport const authorityOf = (\n ctx: Pick<AnnotationContext, 'doc'>,\n dto: Annotation,\n): ModelAnnotation['authority'] => {\n const security = ctx.doc?.security;\n if (!security) return undefined;\n const target = {\n ...(dto.userId != null ? { userId: dto.userId } : {}),\n ...(dto.groupId != null ? { groupId: dto.groupId } : {}),\n };\n return {\n update: security.allowsAnnotation('update', target),\n delete: security.allowsAnnotation('delete', target),\n };\n};\n\nexport function createView(\n ctx: Pick<AnnotationContext, 'state' | 'doc' | 'document'>,\n records: Mirror<AnnotationRecords>,\n lending: Pick<Lending, 'lender' | 'records'>,\n) {\n /** A confirmed record as the model has it, cached per stored version and render preference. */\n const confirmed = new WeakMap<AnnotationRecord, { vector: boolean; record: ModelAnnotation }>();\n const confirmedRecord = (stored: AnnotationRecord, vector: boolean): ModelAnnotation => {\n const cached = confirmed.get(stored);\n if (cached && cached.vector === vector) return cached.record;\n const projected = fromDTO(stored.dto);\n const record: ModelAnnotation = {\n ...projected,\n source: sourceOfConfirmed(projected.annotation, vector),\n pictureVersion: stored.pictureVersion,\n authority: authorityOf(ctx, stored.dto),\n };\n confirmed.set(stored, { vector, record });\n return record;\n };\n\n /**\n * A record a pending change made or changed, cached per shown version, the\n * confirmed one it was made from and the render preference.\n */\n const predicted = new WeakMap<\n AnnotationRecord,\n { truth: AnnotationRecord | undefined; vector: boolean; record: ModelAnnotation }\n >();\n\n /**\n * How a record shows while a pending change is on it:\n * - one this session creates: drawn as a new record is, with no raster\n * from the engine yet;\n * - a confirmed one: its predicted annotation, drawn as the change says\n * (core `drawnAfter`, the engine's verdict on it): its raster moved, or\n * live, as with no change pending. Its appearance version and\n * authority stay the engine's.\n */\n const predictedRecord = (\n shown: AnnotationRecord,\n truth: AnnotationRecord | undefined,\n vector: boolean,\n ): ModelAnnotation => {\n const cached = predicted.get(shown);\n if (cached && cached.truth === truth && cached.vector === vector) return cached.record;\n let record: ModelAnnotation;\n if (!truth) {\n record = { ...fromDTO(shown.dto), unconfirmed: true, source: sourceOfNew(shown.dto) };\n } else {\n const base = confirmedRecord(truth, vector);\n const patch = {\n ...annotationPatchBetween(truth.dto, shown.dto),\n subtype: truth.dto.subtype,\n } as AnnotationPatch;\n record = { ...base, annotation: shown.dto, ...drawnAfter(base, patch) };\n }\n predicted.set(shown, { truth, vector, record });\n return record;\n };\n\n /** The lender's live drawing of a record it shows, when it draws one. */\n const painterOf = (\n shown: Annotation,\n lender: AnnotationLender,\n ): Pick<ModelAnnotation, 'painter'> => {\n const painter = lender.painter(shown);\n return painter ? { painter } : {};\n };\n\n /** A lent record as the model has it, cached per shown row and the confirmed row it was made from. */\n const lent = new WeakMap<\n Annotation,\n { truth: Annotation | undefined; record: ModelAnnotation }\n >();\n const lentRecord = (\n shown: Annotation,\n truth: Annotation | undefined,\n lender: AnnotationLender,\n ): ModelAnnotation => {\n const cached = lent.get(shown);\n if (cached && cached.truth === truth) return cached.record;\n let record: ModelAnnotation;\n if (!truth) {\n // Only shown: one an undo brings back draws the picture it had (the\n // render reads keep it); a new one (a field just placed) draws live, as\n // the tool's ghost drew it, until the engine has its picture.\n record = {\n ...fromDTO(shown),\n unconfirmed: true,\n source: confirmedOnce.has(annotationKey(shown.ref)) ? 'baked' : 'vector',\n pictureVersion: lender.pictureVersion(shown.ref),\n authority: lender.authority(shown),\n ...painterOf(shown, lender),\n };\n } else {\n // The lender's picture is drawn where its shape is; its painter draws it live while a\n // gesture or a change reshapes or restyles it, as a square is drawn.\n const base: ModelAnnotation = {\n ...fromDTO(truth),\n source: sourceOfConfirmed(truth, false),\n pictureVersion: lender.pictureVersion(truth.ref),\n authority: lender.authority(truth),\n ...painterOf(shown, lender),\n };\n const patch = { ...annotationPatchBetween(truth, shown), subtype: truth.subtype };\n record =\n shown === truth\n ? base\n : { ...base, annotation: shown, ...drawnAfter(base, patch as AnnotationPatch) };\n // A new look the lender made itself (a setting, a value): drawn live until its picture is there.\n if (lender.pending(shown.ref)) record = { ...record, source: 'vector' };\n }\n lent.set(shown, { truth, record });\n return record;\n };\n\n /** The confirmed lent rows by key, once per list; and every key ever confirmed. */\n const confirmedLent = new WeakMap<readonly Annotation[], Map<Id, Annotation>>();\n const confirmedOnce = new Set<Id>();\n const confirmedByKey = (rows: readonly Annotation[]): Map<Id, Annotation> => {\n let byKey = confirmedLent.get(rows);\n if (!byKey) {\n byKey = new Map(rows.map((row) => [annotationKey(row.ref), row]));\n for (const key of byKey.keys()) confirmedOnce.add(key);\n confirmedLent.set(rows, byKey);\n }\n return byKey;\n };\n\n const view = memo(\n () =>\n [\n records.get(),\n records.view(),\n ctx.state.get().vector,\n ctx.document(),\n lending.records(),\n ] as const,\n (truths, shown, vector, _document, lentRecords): AnnotationView => {\n const byId: Record<Id, ModelAnnotation> = {};\n for (const key of shown.order) {\n const stored = shown.byKey[key]!;\n const truth = truths.byKey[key];\n byId[key] =\n stored === truth\n ? confirmedRecord(stored, key in vector)\n : predictedRecord(stored, truth, key in vector);\n }\n // The document's order, then the records this session created, then the lent ones.\n const order = [...shown.order];\n const lender = lending.lender();\n if (lentRecords && lender) {\n const confirmed = confirmedByKey(lentRecords.confirmed);\n for (const row of lentRecords.shown) {\n const key = annotationKey(row.ref);\n if (key in byId) continue;\n byId[key] = lentRecord(row, confirmed.get(key), lender);\n order.push(key);\n }\n }\n return { byId, order };\n },\n );\n\n const model = memo(\n () => [ctx.state.get().session, view()] as const,\n (session, current): Model => ({ ...session, ...current }),\n );\n\n /** Each page's records in paint order, grouped once per model. */\n const recordsByPage = memo(\n () => [model()] as const,\n (whole) => {\n const pages = new Map<number, ModelAnnotation[]>();\n for (const id of whole.order) {\n const record = whole.byId[id]!;\n const list = pages.get(record.annotation.page.objectNumber);\n if (list) list.push(record);\n else pages.set(record.annotation.page.objectNumber, [record]);\n }\n return pages;\n },\n );\n\n const pageSlices = new Map<number, { whole: Model; parts: PageParts; model: Model }>();\n\n /**\n * One page's slice of the model: its records, and the selection, hover,\n * text editing, gesture and markup preview that concern it. It keeps its\n * identity while nothing on the page changed, so a page's reads recompute\n * only for changes on that page.\n */\n const pageModel = (pageObjectNumber: number): Model => {\n const whole = model();\n const cached = pageSlices.get(pageObjectNumber);\n if (cached?.whole === whole) return cached.model;\n const records = recordsByPage().get(pageObjectNumber) ?? NO_RECORDS;\n const onPage = (id: Id) => whole.byId[id]?.annotation.page.objectNumber === pageObjectNumber;\n const draft = whole.draft;\n const parts: PageParts = {\n records,\n selected: whole.selected.filter(onPage),\n hovered: whole.hovered !== null && onPage(whole.hovered) ? whole.hovered : null,\n editing: whole.editing !== null && onPage(whole.editing) ? whole.editing : null,\n draft:\n draft &&\n ('page' in draft\n ? draft.page.objectNumber === pageObjectNumber\n : 'ids' in draft\n ? draft.ids.some(onPage)\n : onPage(draft.id))\n ? draft\n : null,\n preview: whole.preview?.byPage[pageObjectNumber] ? whole.preview : null,\n settings: [whole.defaults, whole.hitMargin, whole.snap, whole.editable],\n };\n if (cached && samePageParts(cached.parts, parts)) {\n pageSlices.set(pageObjectNumber, { whole, parts: cached.parts, model: cached.model });\n return cached.model;\n }\n const slice: Model = {\n ...whole,\n byId: Object.fromEntries(records.map((record) => [record.id, record])),\n order: records.map((record) => record.id),\n selected: [...parts.selected],\n hovered: parts.hovered,\n editing: parts.editing,\n draft: parts.draft,\n preview: parts.preview,\n };\n pageSlices.set(pageObjectNumber, { whole, parts, model: slice });\n return slice;\n };\n\n return { view, model, pageModel };\n}\n\nconst NO_RECORDS: readonly ModelAnnotation[] = [];\n\n/** What one page's slice of the model is made of; compared item by item. */\ninterface PageParts {\n readonly records: readonly ModelAnnotation[];\n readonly selected: readonly Id[];\n readonly hovered: Id | null;\n readonly editing: Id | null;\n readonly draft: Model['draft'];\n readonly preview: Model['preview'];\n readonly settings: readonly unknown[];\n}\n\nconst sameItems = (left: readonly unknown[], right: readonly unknown[]): boolean =>\n left.length === right.length && left.every((item, index) => Object.is(item, right[index]));\n\nconst samePageParts = (left: PageParts, right: PageParts): boolean =>\n sameItems(left.records, right.records) &&\n sameItems(left.selected, right.selected) &&\n left.hovered === right.hovered &&\n left.editing === right.editing &&\n left.draft === right.draft &&\n left.preview === right.preview &&\n sameItems(left.settings, right.settings);\n\nexport type View = ReturnType<typeof createView>;\n","import type { MirrorChange } from '@embedpdf/core';\n\nimport type {\n AnnotationCreatedEvent,\n AnnotationDeletedEvent,\n AnnotationDraftChangedEvent,\n AnnotationEditingChangedEvent,\n AnnotationHoverChangedEvent,\n AnnotationReorderedEvent,\n AnnotationResyncedEvent,\n AnnotationSelectionChangedEvent,\n AnnotationUpdatedEvent,\n AnnotationWriteFailedEvent,\n CommentThreadChangedEvent,\n ToolDefaultsChangedEvent,\n} from '../contract';\nimport type { CapturedAnnotationDraft } from '../host-contract';\nimport type { AnnotationContext } from './context';\nimport type { AnnotationRecords } from '../sync/records';\n\n/**\n * The plugin's events. Record events (created, updated, deleted, reordered,\n * resynced) fire when the records mirror confirms a change (sync/confirmed.ts);\n * selection, draft, editing and hover events are derived from state changes\n * in the store service; `writeFailed` fires when the engine refuses a change\n * the user made; the rest fire where their operation completes.\n * `recordsChanged` is internal: every change the records mirror applied.\n */\nexport function createAnnotationEvents(ctx: Pick<AnnotationContext, 'events'>) {\n return {\n created: ctx.events.source<AnnotationCreatedEvent>(),\n updated: ctx.events.source<AnnotationUpdatedEvent>(),\n deleted: ctx.events.source<AnnotationDeletedEvent>(),\n reordered: ctx.events.source<AnnotationReorderedEvent>(),\n resynced: ctx.events.source<AnnotationResyncedEvent>(),\n selectionChanged: ctx.events.source<AnnotationSelectionChangedEvent>(),\n draftChanged: ctx.events.source<AnnotationDraftChangedEvent>(),\n editingChanged: ctx.events.source<AnnotationEditingChangedEvent>(),\n hoverChanged: ctx.events.source<AnnotationHoverChangedEvent>(),\n toolDefaultsChanged: ctx.events.source<ToolDefaultsChangedEvent>(),\n threadChanged: ctx.events.source<CommentThreadChangedEvent>(),\n draftCaptured: ctx.events.source<CapturedAnnotationDraft>(),\n writeFailed: ctx.events.source<AnnotationWriteFailedEvent>(),\n recordsChanged: ctx.events.source<MirrorChange<AnnotationRecords>>(),\n };\n}\n\nexport type AnnotationEvents = ReturnType<typeof createAnnotationEvents>;\n","import type { Point } from '@embedpdf/core-annotation';\nimport { toPageRef, type AttachmentFileSource } from '@embedpdf/engine-core/runtime';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\n\nimport type { FilePickerProvider, FilePromptRequest } from '../contract';\nimport type { AnnotationContext } from './context';\nimport type { ResolvedTool } from '../tools/definitions';\n\n/**\n * The one file-picker port (a DOM file dialog, wired by the framework\n * adapter): every click-then-pick tool — a stamp `'prompt'` source, the file\n * attachment tool — resolves its bytes through this slot. See\n * {@link FilePickerProvider}.\n */\nexport function createFilePickerPort(ctx: Pick<AnnotationContext, 'doc' | 'tryGet'>) {\n let provider: FilePickerProvider | null = null;\n\n const set = (next: FilePickerProvider | null) => {\n provider = next;\n return () => {\n if (provider === next) provider = null;\n };\n };\n\n /**\n * Run the installed provider for a click-then-pick tool, with the shared\n * expiry rule: the placement is dropped if the picker cancels, or if the\n * 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 promptAt = (\n tool: ResolvedTool,\n pageObjectNumber: number,\n point: Point,\n place: (picked: AttachmentFileSource) => void,\n ): boolean => {\n const current = provider;\n if (!current) return false;\n const spec = tool.source;\n const request: FilePromptRequest = {\n toolId: tool.id,\n subtype: tool.subtype,\n accept: spec?.kind === 'prompt' ? spec.accept : undefined,\n page: toPageRef(pageObjectNumber),\n point,\n };\n const docAtClick = ctx.doc;\n current(request).then(\n (picked) => {\n if (!picked) return; // cancelled\n if (ctx.doc !== docAtClick) return; // document changed underneath\n if (ctx.tryGet(InteractionToken)?.getActiveToolId() !== tool.id) return; // tool changed\n place(picked);\n },\n (error) => console.error('[annotation] file-picker provider failed:', error),\n );\n return true;\n };\n\n return { set, promptAt };\n}\n\nexport type FilePickerPort = ReturnType<typeof createFilePickerPort>;\n","/**\n * Lending: a sibling plugin's records shown and edited as annotations (the\n * form plugin lends its widgets in design mode; host-contract.ts,\n * `AnnotationLender`). This holds the lender, and says which records are\n * lent: the view shows them, the store writes their edits as the lender's ops.\n */\nimport { memo, PluginError, type Unsubscribe } from '@embedpdf/core';\nimport type { Id } from '@embedpdf/core-annotation';\nimport {\n anchorOf,\n annotationKey,\n type Annotation,\n type AnnotationRef,\n type ChangeOp,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationLender } from '../host-contract';\nimport type { StoreChange } from './store';\n\n/** The lent records now: as the engine confirmed them, and as they show. */\nexport interface LentRecords {\n readonly confirmed: readonly Annotation[];\n readonly shown: readonly Annotation[];\n}\n\nexport interface Lending {\n /** The lender, or `null`. */\n lender(): AnnotationLender | null;\n /** Its records now, or `null` while it lends none. */\n records(): LentRecords | null;\n /** Whether the record is lent. */\n owns(id: Id): boolean;\n lend(lender: AnnotationLender): Unsubscribe;\n}\n\nconst NONE: ReadonlySet<Id> = new Set();\n\nexport function createLending(notify: () => void): Lending {\n let current: AnnotationLender | null = null;\n const records = (): LentRecords | null => current?.records() ?? null;\n const lent = memo(\n () => [records()?.shown] as const,\n (shown): ReadonlySet<Id> =>\n shown ? new Set(shown.map((record) => annotationKey(record.ref))) : NONE,\n );\n return {\n lender: () => current,\n records,\n owns: (id) => lent().has(id),\n lend(lender) {\n current = lender;\n notify();\n return () => {\n if (current !== lender) return;\n current = null;\n notify();\n };\n },\n };\n}\n\n/** A lent record's change stated in code: refused, naming its owner. */\nexport function refuseLent(lending: Pick<Lending, 'owns' | 'lender'>, ref: AnnotationRef): void {\n if (!lending.owns(annotationKey(ref))) return;\n const owner = lending.lender()?.owner ?? 'its own';\n throw new PluginError(\n 'invalid-input',\n 'annotation',\n `${annotationKey(ref)} belongs to the ${owner} plugin: change it there`,\n );\n}\n\ntype Reorder = Extract<StoreChange, { type: 'reorder' }>;\n\n/**\n * A reorder stated in code, split by owner: lent records go through their\n * lender (their ops into `lent`), and the rest is returned; `null` when none\n * of it is this plugin's. Lent records keep their own drawing order, so a\n * neighbour of the other owner can't be theirs.\n */\nexport function ownReorder(\n lending: Pick<Lending, 'owns' | 'lender'>,\n change: Reorder,\n lent: ChangeOp[],\n): Reorder | null {\n const lender = lending.lender();\n const isLent = (ref: AnnotationRef) => lending.owns(annotationKey(ref));\n const lentRefs = change.refs.filter(isLent);\n if (!lender || !lentRefs.length) return change;\n const ownRefs = change.refs.filter((ref) => !isLent(ref));\n const anchor = anchorOf(change.position);\n if (anchor && (ownRefs.length || !isLent(anchor))) {\n throw new PluginError(\n 'invalid-input',\n 'annotation',\n `${lender.owner} records move among their own: ${annotationKey(anchor)} can't be their neighbour`,\n );\n }\n lent.push(...lender.reorderOps(change.page, lentRefs, change.position));\n return ownRefs.length ? { ...change, refs: ownRefs } : null;\n}\n","/**\n * The object numbers new records take: the session holds a few for the next\n * creates (`Session.objectNumbers`), taken from the document's pool\n * (`ctx.changes`) as a message needs them. A number the engine reclaims\n * leaves the session too.\n */\nimport type { ChangeOp } from '@embedpdf/engine-core/runtime';\n\nimport { withObjectNumbers, withoutObjectNumbers } from '../model';\nimport type { AnnotationContext } from './context';\n\nexport function createObjectNumbers(ctx: Pick<AnnotationContext, 'state' | 'changes' | 'doc'>) {\n let watchingLost = false;\n /** Numbers the engine reclaimed leave the session too: a create naming one would be refused. */\n const watchLost = (): void => {\n if (watchingLost || !ctx.doc) return;\n watchingLost = true;\n ctx.doc.objectNumbers.onLost(({ numbers }) => ctx.state.update(withoutObjectNumbers, numbers));\n };\n\n /** Make the session hold `count` object numbers, from the document's pool; false when it has too few. */\n const hold = (count: number): boolean => {\n const held = ctx.state.get().session.objectNumbers.length;\n if (held >= count) return true;\n watchLost();\n const taken: number[] = [];\n while (held + taken.length < count) {\n const number = ctx.changes.takeObjectNumber();\n if (number === null) break;\n taken.push(number);\n }\n if (taken.length) ctx.state.update(withObjectNumbers, taken);\n return held + taken.length >= count;\n };\n\n /** Take `count` numbers the session holds, for creates stated in code; `null` when it can't hold that many. */\n const take = (count: number): number[] | null => {\n if (!hold(count)) return null;\n const { objectNumbers } = ctx.state.get().session;\n ctx.state.update((state) => ({\n ...state,\n session: { ...state.session, objectNumbers: objectNumbers.slice(count) },\n }));\n return objectNumbers.slice(0, count);\n };\n\n /**\n * `ops` with a number for every create that has none (a link's child): one\n * of `held`, the numbers the session holds, or one from the pool; without\n * one, the engine names it. Also what the session holds after.\n */\n const named = (\n ops: readonly ChangeOp[],\n held: readonly number[],\n ): { ops: ChangeOp[]; held: readonly number[] } => {\n let left = held;\n const withNumbers = ops.map((op): ChangeOp => {\n if (op.type !== 'annotations.create' || op.objectNumber !== undefined) return op;\n const [first, ...rest] = left;\n const objectNumber = first ?? ctx.changes.takeObjectNumber();\n if (first !== undefined) left = rest;\n return objectNumber === null ? op : { ...op, objectNumber };\n });\n return { ops: withNumbers, held: left };\n };\n\n return { hold, take, named };\n}\n","/**\n * The selection follows undo and redo. Each change the store stages keeps\n * the selection from before and after it. When a change that undoes it is\n * staged (by the history, or by any code), the selection goes back to what it\n * was before, as far as those records still show; the undo keeps the pair the\n * other way round, so undoing the undo (a redo) brings back what it was after.\n * This works because a record's key never changes.\n */\nimport type { Id, Message, Model } from '@embedpdf/core-annotation';\n\nimport type { AnnotationContext } from './context';\n\n/** How many changes keep their selections: the history keeps fewer steps than this. */\nconst KEPT = 200;\n\ninterface Selections {\n readonly before: readonly Id[];\n readonly after: readonly Id[];\n}\n\nexport function createSelectionHistory(\n ctx: Pick<AnnotationContext, 'changes'>,\n store: { model(): Model; commit(message: Message): unknown },\n) {\n /** The selections around each change, by its `opId`, oldest first. */\n const kept = new Map<string, Selections>();\n\n /** Keep the selection from before and after the change `opId`. */\n const remember = (opId: string, before: readonly Id[], after: readonly Id[]): void => {\n kept.set(opId, { before, after });\n if (kept.size > KEPT) kept.delete(kept.keys().next().value!);\n };\n\n ctx.changes.onStaged((change) => {\n if (change.undoOf === null) return;\n const undone = kept.get(change.undoOf);\n if (!undone) return;\n remember(change.opId, undone.after, undone.before);\n // The undo shows already: select what of the earlier selection still shows.\n const model = store.model();\n const ids = undone.before.filter((id) => id in model.byId);\n store.commit(ids.length ? { type: 'select', ids } : { type: 'deselect' });\n });\n\n return { remember };\n}\n\nexport type SelectionHistory = ReturnType<typeof createSelectionHistory>;\n","/**\n * The records: every annotation the engine confirmed, held in a mirror. It is\n * loaded whole once, kept current by folding confirmed events from every\n * origin, and re-reads a page only when an event describes it too coarsely (a\n * redaction, an inserted page). Form fields' widgets aren't annotation\n * records: they come with the form, and so do their events.\n *\n * Two pure functions change the records, side by side here:\n *\n * foldRecords what the engine confirmed: `records.get()`\n * predictRecords what this session asked for and the engine hasn't\n * answered yet, op by op: `records.view()` shows it on top\n *\n * What happens when a change is confirmed (render preferences, record\n * events) is in sync/confirmed.ts.\n */\nimport {\n reload,\n type DocumentEvent,\n type Mirror,\n type PageRef,\n type PredictedOp,\n} from '@embedpdf/core';\nimport { annotationAfter, annotationOfNew } from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n annotationPatchBetween,\n deletedWith,\n reorderedList,\n reorderPart,\n type Annotation,\n type AnnotationDraft,\n type AnnotationPatch,\n type AnnotationRef,\n type ChangeOp,\n type ListPosition,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext } from '../services/context';\nimport type { AnnotationEvents } from '../services/events';\n\n/** One confirmed annotation. */\nexport interface AnnotationRecord {\n readonly dto: Annotation;\n /**\n * Revision of the engine-baked appearance. It advances when the engine\n * reports new raster content (a re-bake, a reload), and\n * only then: the page's rasters are fetched again exactly when it changes.\n */\n readonly pictureVersion: number;\n}\n\n/** Every confirmed annotation of the document, by annotation key. */\nexport interface AnnotationRecords {\n readonly byKey: Readonly<Record<string, AnnotationRecord>>;\n /** Document order: pages as loaded with each page's `/Annots` order, then records confirmed later. */\n readonly order: readonly string[];\n}\n\nexport const NO_RECORDS: AnnotationRecords = { byKey: {}, order: [] };\n\n/* ── pure updates of the records ─────────────────────────────────────────── */\n\n/**\n * Add or replace these records, advancing their appearance version when\n * `bump` is set. A record keeps its key for life (an annotation's ref is its\n * name for life), so a replaced record keeps its place.\n */\nfunction put(\n records: AnnotationRecords,\n dtos: readonly Annotation[],\n bump: boolean,\n): AnnotationRecords {\n if (!dtos.length) return records;\n const byKey = { ...records.byKey };\n const added: string[] = [];\n for (const dto of dtos) {\n const key = annotationKey(dto.ref);\n const previous = byKey[key];\n if (!previous) added.push(key);\n byKey[key] = { dto, pictureVersion: (previous?.pictureVersion ?? 0) + (bump ? 1 : 0) };\n }\n return { byKey, order: added.length ? [...records.order, ...added] : records.order };\n}\n\nfunction drop(records: AnnotationRecords, keys: readonly string[]): AnnotationRecords {\n const present = keys.filter((key) => key in records.byKey);\n if (!present.length) return records;\n const gone = new Set(present);\n const byKey = { ...records.byKey };\n for (const key of present) delete byKey[key];\n return { byKey, order: records.order.filter((key) => !gone.has(key)) };\n}\n\nconst keysOnPages = (records: AnnotationRecords, pages: readonly PageRef[]): string[] => {\n const wanted = new Set(pages.map((page) => page.objectNumber));\n return records.order.filter((key) => wanted.has(records.byKey[key]!.dto.page.objectNumber));\n};\n\n/**\n * A fresh read of the whole document. Every record's appearance version moves\n * past the one it had, so a reload after a desync re-fetches every raster\n * (the appearances may have changed while the event stream was not trusted).\n */\nfunction fromSnapshot(current: AnnotationRecords, dtos: readonly Annotation[]): AnnotationRecords {\n const byKey: Record<string, AnnotationRecord> = {};\n const order: string[] = [];\n for (const dto of dtos) {\n const key = annotationKey(dto.ref);\n const previous = current.byKey[key];\n if (!(key in byKey)) order.push(key);\n byKey[key] = { dto, pictureVersion: previous ? previous.pictureVersion + 1 : 0 };\n }\n return { byKey, order };\n}\n\n/** Some pages were read again: their records are replaced, and their rasters re-fetched. */\nfunction withPages(\n records: AnnotationRecords,\n pages: readonly PageRef[],\n dtos: readonly Annotation[],\n): AnnotationRecords {\n const read = new Set(dtos.map((dto) => annotationKey(dto.ref)));\n const stale = keysOnPages(records, pages).filter((key) => !read.has(key));\n return put(drop(records, stale), dtos, true);\n}\n\n/** Apply one confirmed document event to the records. Pure, and the same for every origin. */\nexport function foldRecords(\n records: AnnotationRecords,\n event: DocumentEvent,\n): AnnotationRecords | ReturnType<typeof reload> {\n switch (event.type) {\n // A new record comes with a freshly baked appearance; the engine says\n // whether an update changed one.\n case 'annotations.created':\n return put(records, [event.annotation], true);\n case 'annotations.updated':\n return put(records, [event.annotation], event.appearance.changed);\n case 'annotations.reordered': {\n // The page's records take the new order in their slots.\n const page = event.page.objectNumber;\n return {\n ...records,\n order: reorderPart(\n records.order,\n (key) => records.byKey[key]?.dto.page.objectNumber === page,\n event.order.map(annotationKey),\n (key) => key,\n ),\n };\n }\n case 'annotations.deleted':\n return drop(records, event.deleted.map(annotationKey));\n // An undo brought deleted annotations back, each in the place it had:\n // the event doesn't say where, so the page is read again.\n case 'annotations.restored':\n return reload({ pages: [event.page] });\n case 'pages.deleted':\n return drop(records, keysOnPages(records, event.pages));\n case 'pages.inserted':\n return event.insertedPages.length ? reload({ pages: event.insertedPages }) : records;\n // These paint annotations into the page content and remove them.\n case 'redaction.applied':\n case 'pages.flattened': {\n const pages = event.results\n .filter((result) => result.status === 'applied')\n .map((result) => result.page);\n return pages.length ? reload({ pages }) : records;\n }\n case 'annotations.flattened':\n return event.results.some((result) => result.status === 'applied')\n ? reload({ pages: [event.page] })\n : records;\n default:\n return records;\n }\n}\n\n/* ── what this session asked for ─────────────────────────────────────────── */\n\n/**\n * The annotation a create writes, as the engine reads it back. The\n * annotations it links to (the one it answers, the one a popup shows) are the\n * engine's to look up as it writes: it is read without them, then they are\n * stated. Throws for a draft the engine refuses without its schemas\n * (`annotationOfDraft`); one whose values it refuses shows until it answers.\n */\nexport function annotationOfCreate(draft: AnnotationDraft, ref: AnnotationRef): Annotation {\n const { reply, parent, ...fields } = draft as AnnotationDraft & {\n reply?: { to: AnnotationRef; type?: 'reply' | 'group' } | null;\n parent?: AnnotationRef | null;\n };\n return {\n ...annotationOfNew(fields as AnnotationDraft, { ref }),\n ...(reply ? { reply: { to: reply.to, type: reply.type ?? 'reply' } } : {}),\n ...(parent ? { parent } : {}),\n } as Annotation;\n}\n\n/**\n * The record keys of one page in a new drawing order: `keys` moved to\n * `position` among the page's others, in the order given, as the engine\n * reorders. Other pages keep their places. Unchanged when the engine would\n * refuse it (a key or the neighbour no longer on the page).\n */\nfunction reorderedKeys(\n records: AnnotationRecords,\n page: number,\n keys: readonly string[],\n position: ListPosition<string>,\n): readonly string[] {\n const onPage = (key: string) => records.byKey[key]?.dto.page.objectNumber === page;\n try {\n const order = reorderedList(records.order.filter(onPage), keys, position, (key) => key);\n return reorderPart(records.order, onPage, order, (key) => key);\n } catch {\n return records.order;\n }\n}\n\n/** The page's annotations, in drawing order. */\nconst annotationsOn = (records: AnnotationRecords, page: number): Annotation[] =>\n records.order\n .map((key) => records.byKey[key]!.dto)\n .filter((dto) => dto.page.objectNumber === page);\n\n/**\n * One op of this session's pending changes, applied to the records as the\n * engine will apply it; `records.view()` replays them, in staging order, over\n * what the engine confirmed. Pure and absolute: an op whose answer the\n * records hold already changes nothing, and so does an op the engine would\n * refuse (its annotation gone, a patch it no longer takes). A record it\n * changes keeps its appearance version: the engine's raster is the one it\n * had until the answer brings a new one.\n */\nexport function predictRecords(records: AnnotationRecords, op: PredictedOp): AnnotationRecords {\n switch (op.type) {\n case 'annotations.create': {\n // A create the engine names has no key to show it by until it answers.\n if (op.objectNumber === undefined) return records;\n const ref: AnnotationRef = {\n kind: 'objectNumber',\n page: op.page,\n objectNumber: op.objectNumber,\n };\n if (annotationKey(ref) in records.byKey) return records;\n try {\n return put(records, [annotationOfCreate(op.data, ref)], false);\n } catch {\n return records;\n }\n }\n case 'annotations.update': {\n const stored = records.byKey[annotationKey(op.ref)];\n if (!stored) return records;\n let dto: Annotation;\n try {\n dto = annotationAfter(stored.dto, op.patch);\n } catch {\n return records;\n }\n return put(records, [dto], false);\n }\n case 'annotations.delete': {\n // What goes with it goes too: its replies and grouped parts, their popups.\n const page = annotationsOn(records, op.ref.page.objectNumber);\n return drop(\n records,\n deletedWith(page, op.ref).map((annotation) => annotationKey(annotation.ref)),\n );\n }\n case 'annotations.reorder': {\n const order = reorderedKeys(\n records,\n op.page.objectNumber,\n op.refs.map(annotationKey),\n typeof op.position === 'object'\n ? 'before' in op.position\n ? { before: annotationKey(op.position.before) }\n : { after: annotationKey(op.position.after) }\n : op.position,\n );\n return order === records.order ? records : { ...records, order };\n }\n case 'annotations.restore': {\n const key = annotationKey(op.annotation.ref);\n if (key in records.byKey) return records;\n // Back in its place among the page's annotations.\n const page = op.annotation.page.objectNumber;\n const onPage = records.order.filter(\n (each) => records.byKey[each]!.dto.page.objectNumber === page,\n );\n const before = onPage[op.index];\n const at = before === undefined ? records.order.length : records.order.indexOf(before);\n return {\n byKey: { ...records.byKey, [key]: { dto: op.annotation, pictureVersion: 0 } },\n order: [...records.order.slice(0, at), key, ...records.order.slice(at)],\n };\n }\n default:\n return records;\n }\n}\n\n/** What undoing one op looks like, over the records it applies to. */\nfunction undoOfOp(records: AnnotationRecords, op: ChangeOp): PredictedOp[] {\n switch (op.type) {\n case 'annotations.create':\n return op.objectNumber === undefined\n ? []\n : [\n {\n type: 'annotations.delete',\n ref: { kind: 'objectNumber', page: op.page, objectNumber: op.objectNumber },\n },\n ];\n case 'annotations.update': {\n const stored = records.byKey[annotationKey(op.ref)];\n if (!stored) return [];\n let after: Annotation;\n try {\n after = annotationAfter(stored.dto, op.patch);\n } catch {\n return [];\n }\n const patch = {\n ...annotationPatchBetween(after, stored.dto),\n subtype: stored.dto.subtype,\n } as AnnotationPatch;\n return [{ type: 'annotations.update', ref: op.ref, patch }];\n }\n case 'annotations.delete': {\n // Everything that went with it comes back, each in its place.\n const page = annotationsOn(records, op.ref.page.objectNumber);\n const gone = new Set(deletedWith(page, op.ref));\n return page.flatMap((annotation, index): PredictedOp[] =>\n gone.has(annotation) ? [{ type: 'annotations.restore', annotation, index }] : [],\n );\n }\n case 'annotations.reorder':\n // The page's whole order as it was.\n return [\n {\n type: 'annotations.reorder',\n page: op.page,\n refs: annotationsOn(records, op.page.objectNumber).map((annotation) => annotation.ref),\n position: 'start',\n },\n ];\n default:\n return [];\n }\n}\n\n/**\n * What undoing `ops` looks like, read off the records they apply to, each\n * over what the ones before it left: the ops that bring the records back,\n * the last op's first. It is drawing only: the engine undoes a change by\n * its own record of it.\n */\nexport function undoOf(records: AnnotationRecords, ops: readonly ChangeOp[]): PredictedOp[] {\n const undo: PredictedOp[][] = [];\n let current = records;\n for (const op of ops) {\n undo.push(undoOfOp(current, op));\n current = predictRecords(current, op);\n }\n return undo.reverse().flat();\n}\n\n/* ── the mirror ──────────────────────────────────────────────────────────── */\n\n/**\n * The records mirror. Every change it applies is published on the internal\n * `recordsChanged` event, where sync/confirmed.ts reacts to it.\n */\nexport function createRecordsMirror(\n ctx: Pick<AnnotationContext, 'mirror' | 'doc'>,\n events: Pick<AnnotationEvents, 'recordsChanged'>,\n): Mirror<AnnotationRecords> {\n const records: Mirror<AnnotationRecords> = ctx.mirror<AnnotationRecords>({\n name: 'records',\n initial: () => NO_RECORDS,\n // Without `doc.annotate.read` the bulk read would be refused: skip it\n // and report `forbidden`; a later refresh checks again.\n readable: () => ctx.doc?.security.allows('doc.annotate.read') ?? true,\n load: async (doc) => {\n const list = await doc.annotations.list();\n return {\n value: fromSnapshot(records.get(), list.annotations),\n cursor: list.auditHead ?? null,\n };\n },\n fold: foldRecords,\n predict: predictRecords,\n loadPages: async (doc, pages) => {\n const { annotations } = await doc.annotations.list({ pages });\n return (current) => withPages(current, pages, annotations);\n },\n changed: (change) => events.recordsChanged.emit(change),\n });\n return records;\n}\n","/**\n * How the store puts one change together from ops, whichever door they came\n * through: a change stated in code, checked, as its op; what follows an\n * update; the deletes another delete covers; the records it names and what it\n * is called. Pure functions.\n */\nimport { PluginError, type ChangeLabel } from '@embedpdf/core';\nimport {\n drawnAfter,\n fromDTO,\n sourceOfNew,\n type Id,\n type Model,\n type ModelAnnotation,\n type UpdateResult,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n deletedWith,\n resolveAnnotationPatch,\n type AnnotationRef,\n type ChangeOp,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { StoreChange } from './store';\nimport { annotationOfCreate, type AnnotationRecords } from '../sync/records';\n\n/**\n * What an update brings along in the same change (an annotation's attached\n * link children), read from the model the change leaves. Called for every\n * update either door stages.\n */\nexport type FollowUp = (\n op: Extract<ChangeOp, { type: 'annotations.update' }>,\n model: Model,\n) => readonly ChangeOp[];\n\n/**\n * A stated change as its op, as given: what an op builder adds for changes\n * worked out in the engine's terms (a link's children).\n */\nexport const opOfStated = (change: StoreChange): ChangeOp => {\n switch (change.type) {\n case 'create':\n return {\n type: 'annotations.create',\n page: change.page,\n data: change.draft,\n ...(change.resources ? { resources: change.resources } : {}),\n };\n case 'update':\n return {\n type: 'annotations.update',\n ref: change.ref,\n patch: change.patch,\n ...(change.resources ? { resources: change.resources } : {}),\n };\n case 'delete':\n return { type: 'annotations.delete', ref: change.ref };\n case 'reorder':\n return {\n type: 'annotations.reorder',\n page: change.page,\n refs: change.refs,\n position: change.position,\n };\n }\n};\n\n/** The record keys an op names. */\nconst keysOf = (op: ChangeOp): string[] => {\n switch (op.type) {\n case 'annotations.create':\n return op.objectNumber === undefined ? [] : [`obj:${op.objectNumber}`];\n case 'annotations.update':\n case 'annotations.delete':\n return [annotationKey(op.ref)];\n case 'annotations.reorder':\n return op.refs.map(annotationKey);\n // A lent record's ops (form widgets).\n case 'forms.updateWidget':\n case 'forms.deleteWidget':\n return [annotationKey(op.widget)];\n case 'forms.reorderWidgets':\n return op.widgets.map(annotationKey);\n default:\n return [];\n }\n};\n\n/** The records a change names, each once. */\nexport const idsOf = (ops: readonly ChangeOp[]): Id[] => [...new Set(ops.flatMap(keysOf))];\n\n/**\n * What a change is called, from what it does: one kind of op (`annotation.move`,\n * or a lent record's own, `form.updateWidget`), or several (`annotation.change`).\n * History and refusals show it.\n */\nexport const labelOf = (ops: readonly ChangeOp[]): ChangeLabel => {\n const kinds = new Set(ops.map((op) => op.type));\n const [only] = kinds;\n const [plane, verb] = kinds.size === 1 && only ? only.split('.') : ['annotations', 'change'];\n const owner = plane === 'annotations' ? 'annotation' : plane === 'forms' ? 'form' : plane;\n return { key: `${owner}.${verb}`, count: idsOf(ops).length };\n};\n\n/**\n * The ops without the deletes another delete of them already covers: an\n * annotation goes with its replies, grouped parts and popups, and an op\n * naming one already gone would refuse the whole change.\n */\nexport function withoutCoveredDeletes(\n records: AnnotationRecords,\n ops: readonly ChangeOp[],\n): readonly ChangeOp[] {\n const deleted = ops.flatMap((op) => (op.type === 'annotations.delete' ? [op.ref] : []));\n if (deleted.length < 2) return ops;\n const covered = new Set<string>();\n for (const ref of deleted) {\n const page = records.order\n .map((key) => records.byKey[key]!.dto)\n .filter((dto) => dto.page.objectNumber === ref.page.objectNumber);\n for (const annotation of deletedWith(page, ref)) {\n if (annotationKey(annotation.ref) !== annotationKey(ref)) {\n covered.add(annotationKey(annotation.ref));\n }\n }\n }\n return ops.filter(\n (op) => op.type !== 'annotations.delete' || !covered.has(annotationKey(op.ref)),\n );\n}\n\n/**\n * `ops` with what follows each update right after it (`FollowUp`): one\n * change writes both.\n */\nexport const withFollowUps = (\n ops: readonly ChangeOp[],\n followUp: FollowUp | null,\n model: Model,\n): ChangeOp[] =>\n ops.flatMap((op) =>\n op.type === 'annotations.update' && followUp ? [op, ...followUp(op, model)] : [op],\n );\n\n/**\n * `before` with the records as `shown` holds them: the model a change stated\n * in code leaves. A record it didn't touch keeps its identity.\n */\nexport function modelOver(\n before: Model,\n previous: AnnotationRecords,\n shown: AnnotationRecords,\n): Model {\n const byId: Record<Id, ModelAnnotation> = {};\n for (const key of shown.order) {\n const stored = shown.byKey[key]!;\n const kept = previous.byKey[key] === stored ? before.byId[key] : undefined;\n byId[key] = kept ?? { ...fromDTO(stored.dto), source: 'vector' };\n }\n return { ...before, byId, order: [...shown.order] };\n}\n\n/** `before`'s records with a message's change set laid over them, and its session: the model its effects read. */\nexport function modelAfter(before: Model, result: UpdateResult): Model {\n if (!result.change.put.length && !result.change.drop.length) {\n return { ...before, ...result.session };\n }\n const byId = { ...before.byId };\n for (const id of result.change.drop) delete byId[id];\n for (const record of result.change.put) byId[record.id] = record;\n const added = result.change.put.map((record) => record.id).filter((id) => !(id in before.byId));\n const order = [...before.order.filter((id) => id in byId), ...added];\n return { ...result.session, byId, order };\n}\n\nconst notFound = (ref: AnnotationRef): PluginError =>\n new PluginError('not-found', 'annotation', `no annotation ${annotationKey(ref)}`);\n\n/**\n * One stated change as its op, resolved by the engine's own rules against\n * `current`: what shows is what the engine will write, and a change those\n * rules refuse throws. The engine checks the values against its schemas when\n * the change reaches it. `live`: the record draws live from now on.\n */\nexport function checkedOpOf(\n change: StoreChange,\n current: AnnotationRecords,\n taken: number[],\n recordOf: (id: Id) => ModelAnnotation | undefined,\n): { id: Id; op: ChangeOp | null; live?: boolean } {\n if (change.type === 'create') {\n const objectNumber = taken.shift()!;\n const ref: AnnotationRef = { kind: 'objectNumber', page: change.page, objectNumber };\n const annotation = annotationOfCreate(change.draft, ref);\n return {\n id: annotationKey(ref),\n op: {\n type: 'annotations.create',\n page: change.page,\n data: change.draft,\n objectNumber,\n ...(change.resources ? { resources: change.resources } : {}),\n },\n live: sourceOfNew(annotation) === 'vector',\n };\n }\n if (change.type === 'reorder') {\n for (const ref of change.refs) {\n if (!(annotationKey(ref) in current.byKey)) throw notFound(ref);\n }\n return {\n id: annotationKey(change.refs[0]!),\n op: {\n type: 'annotations.reorder',\n page: change.page,\n refs: change.refs,\n position: change.position,\n },\n };\n }\n const id = annotationKey(change.ref);\n const stored = current.byKey[id];\n if (!stored) throw notFound(change.ref);\n if (change.type === 'delete') return { id, op: { type: 'annotations.delete', ref: change.ref } };\n const noFields = Object.keys(change.patch).every((name) => name === 'subtype');\n // A patch that says nothing, with no bytes, is no write at all.\n if (noFields && !change.resources) return { id, op: null };\n // The engine's resolve rules, run now: a patch they refuse throws before\n // anything shows. Values its schemas refuse show until the engine answers.\n resolveAnnotationPatch(stored.dto, change.patch);\n const record = recordOf(id);\n return {\n id,\n op: {\n type: 'annotations.update',\n ref: change.ref,\n patch: change.patch,\n ...(change.resources ? { resources: change.resources } : {}),\n },\n live: !!record && drawnAfter(record, change.patch).source === 'vector',\n };\n}\n","/**\n * The store: the two doors every change goes through, and one path behind them.\n *\n * commit(message) a gesture or a selection verb\n * → update(model, message) the core: next session, change set, effects\n * → op builders each effect becomes the engine's ops\n *\n * apply(changes) a change stated in code (the API, comments, links…)\n * → each change checked by the engine's own rules, as its op\n *\n * → ctx.changes.stage(…) one door, one change: the view shows it at once\n * (the records mirror predicts it), and the queue\n * sends it after everything staged before it\n *\n * A change leaves the view once the engine answered: applied, the records\n * hold it; refused, the view shows the engine's records again. New records\n * are named by the object numbers they take, so a record keeps its key from\n * its first frame, and a later change to it is simply staged after its create.\n *\n * A lent record (a form widget in design mode, services/lending.ts) is\n * edited like any other, and its effects become its lender's ops in the same\n * change: a drag of two fields and a stamp is one change. Changes stated in\n * code keep to this plugin's own records, except a reorder, which reorders\n * lent records through their lender in the same change.\n *\n * The model it hands out is the view's (read/view.ts).\n */\nimport {\n PluginError,\n toPluginError,\n toPluginErrorInfo,\n type ChangeLabel,\n type HeldChange,\n type HoldOptions,\n type Mirror,\n type PendingChange,\n} from '@embedpdf/core';\nimport {\n creationDraftAnchor,\n type Effect,\n type Id,\n type Message,\n type Model,\n newRecordsAtMost,\n refOf,\n update,\n type UpdateResult,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type Annotation,\n type AnnotationDraft,\n type AnnotationPatch,\n type AnnotationPosition,\n type AnnotationRef,\n type AnnotationResources,\n type ChangeOp,\n type ChangeResult,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext } from './context';\nimport type { AnnotationEvents } from './events';\nimport { ownReorder, refuseLent, type Lending } from './lending';\nimport { createObjectNumbers } from './object-numbers';\nimport { createSelectionHistory } from './selection-history';\nimport {\n checkedOpOf,\n idsOf,\n labelOf,\n modelAfter,\n modelOver,\n withFollowUps,\n withoutCoveredDeletes,\n type FollowUp,\n} from './staging';\nimport { withSession } from '../model';\nimport type { View } from '../read/view';\nimport { predictRecords, undoOf, type AnnotationRecords } from '../sync/records';\n\n/**\n * Turns one kind of effect into the engine's ops, reading the records it\n * names from `model`, the message's result (a record it deleted is in\n * `before`). Registered by the area that owns the kind; one that writes\n * nothing (a captured drawing) returns nothing. A create it adds without an\n * object number gets one from the store.\n */\nexport type OpBuilder<K extends Effect['type']> = (\n effect: Extract<Effect, { type: K }>,\n model: Model,\n before: Model,\n) => readonly ChangeOp[] | void;\n\n/** How a change the store staged settled. Never a rejection: a refusal is data. */\nexport interface Written {\n /** The engine's refusal, with the records the change named; empty when it applied or wrote nothing. */\n readonly failed: readonly { readonly ids: readonly Id[]; readonly error: PluginError }[];\n /** What the engine answered, one item per op; `null` when it was refused or wrote nothing. */\n readonly result: ChangeResult | null;\n}\n\n/** What committing a message started. */\nexport interface Commit {\n readonly effects: readonly Effect[];\n /** Settles when the engine answered the message's change. */\n readonly written: Promise<Written>;\n}\n\n/**\n * A change stated in code, in the engine's own terms. A create takes an\n * object number, its record is keyed by it, and a later change in the same\n * call can name it.\n */\nexport type StoreChange =\n | {\n readonly type: 'create';\n readonly page: PageRef;\n readonly draft: AnnotationDraft;\n readonly resources?: AnnotationResources;\n }\n | {\n readonly type: 'update';\n readonly ref: AnnotationRef;\n readonly patch: AnnotationPatch;\n readonly resources?: AnnotationResources;\n }\n | { readonly type: 'delete'; readonly ref: AnnotationRef }\n /** Drawing order: the annotations go together to `position` among the page's others. */\n | {\n readonly type: 'reorder';\n readonly page: PageRef;\n readonly refs: readonly AnnotationRef[];\n readonly position: AnnotationPosition;\n };\n\nexport interface ApplyOptions {\n readonly select?: boolean;\n}\n\n/** What applying stated changes started: the record each change names, in order. */\nexport interface Applied {\n readonly ids: readonly Id[];\n /** Settles when the engine answered. */\n readonly written: Promise<AppliedOutcome>;\n}\n\n/** How stated changes settled, and what the engine wrote for each. */\nexport interface AppliedOutcome extends Written {\n /**\n * The annotation each create or update left, as the engine read it back, in\n * the order of the changes. `null` for a delete, a reorder, a change with\n * nothing to write, and a refused one.\n */\n readonly annotations: readonly (Annotation | null)[];\n}\n\n/**\n * A change still being made, as typing is: every commit into it replaces its\n * ops, and nothing is sent until it is (after a pause), or until anything\n * else is staged.\n */\nexport interface StoreHold {\n /** Whether a commit can still go into it. Once it was sent, typing goes on in a new one. */\n readonly open: boolean;\n send(): void;\n cancel(): void;\n}\n\nexport interface AnnotationStore {\n /** The current model: what every read and gesture works on. */\n model(): Model;\n /**\n * Run one message through the core and stage its change: it shows at once\n * and is sent in turn. Throws, before anything shows, for a message the\n * engine would refuse (a `rect` with a new shape), as `apply` does.\n * `adjust` changes the core's result before it shows: a tool's\n * `afterCreate` decides whether what it just made is selected\n * (write/after-create.ts). `into` makes the message part of a change still\n * being made (typing).\n *\n * A message that may create needs object numbers. When the document's pool\n * has none left (rare: it refills as it goes), the message runs once it\n * has; its commit then reports no effects, and `written` settles after it ran.\n */\n commit(\n message: Message,\n options?: { adjust?: (result: UpdateResult) => UpdateResult; into?: StoreHold },\n ): Commit;\n /**\n * Show changes stated in code at once, as one change, exactly like a\n * gesture's. Throws, before anything shows, for a change the engine refuses\n * without its schemas (`resolveAnnotationPatch`), a record the view doesn't\n * have, or, when the document's pool is\n * out of object numbers, a create (`applyWhenNumbered` waits for them).\n * `select`: the records it names are selected as they show.\n */\n apply(changes: readonly StoreChange[], options?: ApplyOptions): Applied;\n /** `apply`, once the object numbers its creates take are there: at once, in this call, when they are. */\n applyWhenNumbered(changes: readonly StoreChange[], options?: ApplyOptions): Promise<Applied>;\n /**\n * A change that later commits go into (`commit(…, { into })`); its label names it in history,\n * and consecutive holds with the same `merge` key are one step of it.\n */\n hold(label: ChangeLabel, options?: HoldOptions): StoreHold;\n /** Claim the ops of one kind of effect (one builder per kind; last wins). */\n onEffect<K extends Effect['type']>(kind: K, build: OpBuilder<K>): void;\n /** Claim what follows an update (one; last wins). */\n onUpdate(followUp: FollowUp): void;\n /** Resolves once every change staged so far has its answer. */\n whenWritten(): Promise<void>;\n}\n\n/** The refs behind a list of model ids. */\nexport const refsOfIn = (model: Model, ids: readonly Id[]): AnnotationRef[] =>\n ids.map((id) => refOf(model.byId[id])).filter((ref): ref is AnnotationRef => ref != null);\n\nconst sameIds = (left: readonly Id[], right: readonly Id[]): boolean =>\n left === right || (left.length === right.length && left.every((id, i) => id === right[i]));\n\nconst NOTHING_WRITTEN: Written = { failed: [], result: null };\n\nconst noNumbers = (): PluginError =>\n new PluginError(\n 'not-ready',\n 'annotation',\n 'the document holds no object number for a new annotation right now',\n );\n\nexport function createStore(\n ctx: Pick<AnnotationContext, 'state' | 'changes' | 'doc' | 'watch'>,\n view: View,\n records: Pick<Mirror<AnnotationRecords>, 'view'>,\n events: AnnotationEvents,\n lending: Pick<Lending, 'lender' | 'owns'>,\n): AnnotationStore {\n let followUp: FollowUp | null = null;\n // Keyed by effect type, so a builder only ever receives effects of its own kind.\n const builders = new Map<\n Effect['type'],\n (effect: Effect, model: Model, before: Model) => readonly ChangeOp[] | void\n >();\n const model = view.model;\n\n /** The changes this plugin staged that the engine hasn't answered: their refusals are reported. */\n const mine = new Set<string>();\n ctx.changes.onSettled((settled) => {\n if (!mine.delete(settled.change.opId) || settled.status !== 'refused') return;\n if (settled.error.code === 'operation-cancelled' || settled.error.code === 'instance-closed') {\n return;\n }\n const refs = settled.change.shows.flatMap((op) =>\n op.type === 'annotations.create' && op.objectNumber !== undefined\n ? [{ kind: 'objectNumber' as const, page: op.page, objectNumber: op.objectNumber }]\n : op.type === 'annotations.update' || op.type === 'annotations.delete'\n ? [op.ref]\n : op.type === 'forms.updateWidget' || op.type === 'forms.deleteWidget'\n ? [op.widget]\n : op.type === 'annotations.reorder'\n ? [...op.refs]\n : op.type === 'forms.reorderWidgets'\n ? [...op.widgets]\n : [],\n );\n events.writeFailed.emit({ refs, error: toPluginErrorInfo(settled.error) });\n });\n\n /** How a staged change settles, for the records it names. */\n const writtenOf = (change: PendingChange, ids: readonly Id[]): Promise<Written> =>\n change.result.then(\n (result): Written => ({ failed: [], result }),\n (error: unknown): Written => ({\n failed: [{ ids, error: toPluginError('annotation', error) }],\n result: null,\n }),\n );\n\n /**\n * Stage this plugin's ops and its lender's as one change. Undoing it undoes\n * the lent ops first: they come last.\n */\n const stage = (\n ops: readonly ChangeOp[],\n before: AnnotationRecords,\n lent: readonly ChangeOp[] = [],\n ): PendingChange => {\n const all = [...ops, ...lent];\n const undo = [\n ...(lent.length ? (lending.lender()?.undoOf(lent) ?? []) : []),\n ...undoOf(before, ops),\n ];\n const change = ctx.changes.stage({ label: labelOf(all), ops: all, undo });\n mine.add(change.opId);\n return change;\n };\n\n const numbers = createObjectNumbers(ctx);\n const selections = createSelectionHistory(ctx, { model, commit: (message) => commit(message) });\n\n /* ── the doors ───────────────────────────────────────────────────────── */\n\n /** A change being made, and the records from before its first commit (what undoing it brings back). */\n interface Hold extends StoreHold {\n readonly held: HeldChange;\n base: AnnotationRecords | null;\n }\n\n const hold = (label: ChangeLabel, options?: HoldOptions): StoreHold => {\n const held = ctx.changes.hold(label, options);\n const entry: Hold = {\n held,\n base: null,\n get open() {\n return held.open;\n },\n send: () => void held.send(),\n cancel: () => {\n if (held.change) mine.delete(held.change.opId);\n held.cancel();\n },\n };\n return entry;\n };\n\n const commit: AnnotationStore['commit'] = (message, options = {}) => {\n const needed = newRecordsAtMost(message);\n if (needed > 0 && !numbers.hold(needed)) return commitWhenNumbered(message, options, needed);\n const before = model();\n // A message the engine would refuse (a `rect` with a new shape) throws\n // before anything shows, as a stated change does.\n let result: UpdateResult;\n try {\n result = update(before, message);\n } catch (error) {\n throw toPluginError('annotation', error);\n }\n if (options.adjust) result = options.adjust(result);\n const after = modelAfter(before, result);\n const shown = records.view();\n // A lent record's effects are its lender's to write.\n const lender = lending.lender();\n const isLent = (effect: Effect): boolean =>\n lender !== null && 'id' in effect && lending.owns(effect.id);\n const lentEffects = result.effects.filter(isLent);\n const built = withFollowUps(\n result.effects\n .filter((effect) => !isLent(effect))\n .flatMap((effect) => builders.get(effect.type)?.(effect, after, before) ?? []),\n followUp,\n after,\n );\n const lent = lentEffects.length && lender ? lender.opsOf(lentEffects, after, before) : [];\n const named = numbers.named(built, result.session.objectNumbers);\n const ops = withoutCoveredDeletes(shown, named.ops);\n if (named.held !== result.session.objectNumbers) {\n result = { ...result, session: { ...result.session, objectNumbers: named.held } };\n }\n let written = Promise.resolve(NOTHING_WRITTEN);\n if (lent.length && !options.into) {\n const change = stage(ops, shown, lent);\n selections.remember(change.opId, before.selected, result.session.selected);\n written = writtenOf(change, idsOf([...ops, ...lent]));\n } else if (ops.length) {\n const into = options.into as Hold | undefined;\n if (into) {\n // Typing: the change keeps its place, its ops are the latest, and\n // undoing it brings back what was there before its first keystroke.\n into.base ??= shown;\n into.held.set(ops, undoOf(into.base, ops));\n const change = into.held.change;\n if (change) {\n mine.add(change.opId);\n selections.remember(change.opId, before.selected, result.session.selected);\n written = writtenOf(change, idsOf(ops));\n }\n } else {\n const change = stage(ops, shown);\n selections.remember(change.opId, before.selected, result.session.selected);\n written = writtenOf(change, idsOf(ops));\n }\n }\n // The records this message drew live render live from now on.\n const vector = result.change.put\n .filter((record) => record.source === 'vector')\n .map((record) => record.id);\n ctx.state.update(withSession, result.session, vector);\n return { effects: result.effects, written };\n };\n\n /** A message that may create, run once the pool has the numbers it needs. */\n const commitWhenNumbered = (\n message: Message,\n options: Parameters<AnnotationStore['commit']>[1],\n needed: number,\n ): Commit => {\n // A gesture that moved on meanwhile (another press) made nothing to finish.\n const draft = model().draft;\n const written = ctx.changes.reserveObjectNumbers(needed).then(\n () => (model().draft === draft ? commit(message, options).written : NOTHING_WRITTEN),\n (error: unknown): Written => ({\n failed: [{ ids: [], error: toPluginError('annotation', error) }],\n result: null,\n }),\n );\n return { effects: [], written };\n };\n\n const apply: AnnotationStore['apply'] = (changes, options = {}) => {\n // Everything is worked out before anything shows: one refused change\n // stages none. Each change is worked out against the ones before it, as\n // the engine will apply them.\n const shown = records.view();\n const creates = changes.filter((change) => change.type === 'create').length;\n const taken = creates ? numbers.take(creates) : [];\n if (!taken) throw noNumbers();\n const ops: ChangeOp[] = [];\n /** Lent records reordered: their lender's ops, last in the change. */\n const lent: ChangeOp[] = [];\n /** Where each change's op is among `ops`, or -1 for a change that writes nothing. */\n const opIndex: number[] = [];\n const ids: Id[] = [];\n const vector: Id[] = [];\n let current = shown;\n try {\n for (const stated of changes) {\n if (stated.type === 'update' || stated.type === 'delete') refuseLent(lending, stated.ref);\n const change = stated.type === 'reorder' ? ownReorder(lending, stated, lent) : stated;\n if (!change) {\n ids.push(annotationKey((stated as Extract<StoreChange, { type: 'reorder' }>).refs[0]!));\n opIndex.push(-1);\n continue;\n }\n const op = checkedOpOf(change, current, taken, (id) => model().byId[id]);\n ids.push(op.id);\n opIndex.push(op.op ? ops.length : -1);\n if (!op.op) continue;\n ops.push(op.op);\n if (op.live) vector.push(op.id);\n current = predictRecords(current, op.op);\n }\n } catch (error) {\n throw toPluginError('annotation', error);\n }\n if (!ops.length && !lent.length) {\n return {\n ids,\n written: Promise.resolve({ ...NOTHING_WRITTEN, annotations: changes.map(() => null) }),\n };\n }\n // What follows each update joins the change, after the ops stated (the\n // answer's items stay in the order of the changes).\n const following = numbers.named(\n withFollowUps(ops, followUp, modelOver(model(), shown, current)).filter(\n (op) => !ops.includes(op),\n ),\n ctx.state.get().session.objectNumbers,\n );\n if (following.held !== ctx.state.get().session.objectNumbers) {\n ctx.state.update((state) => ({\n ...state,\n session: { ...state.session, objectNumbers: following.held },\n }));\n }\n const selected = model().selected;\n const change = stage(withoutCoveredDeletes(shown, [...ops, ...following.ops]), shown, lent);\n selections.remember(change.opId, selected, options.select ? ids : selected);\n if (vector.length) ctx.state.update(withSession, ctx.state.get().session, vector);\n if (options.select) commit({ type: 'select', ids });\n const written = writtenOf(change, idsOf([...ops, ...lent])).then(\n (outcome): AppliedOutcome => ({\n ...outcome,\n annotations: opIndex.map((index) => {\n const item = index < 0 ? undefined : outcome.result?.items[index];\n return item && 'annotation' in item ? (item.annotation as Annotation) : null;\n }),\n }),\n );\n return { ids, written };\n };\n\n const applyWhenNumbered: AnnotationStore['applyWhenNumbered'] = async (changes, options) => {\n const creates = changes.filter((change) => change.type === 'create').length;\n while (!numbers.hold(creates)) await ctx.changes.reserveObjectNumbers(creates);\n return apply(changes, options);\n };\n\n // Session references follow the view. A record that left the view (deleted\n // elsewhere, a refused create, a page read again) leaves the selection, the\n // hover and the text editor, and a gesture on it ends.\n ctx.watch(view.view, (next, previous) => {\n const gone = previous.order.filter((id) => !(id in next.byId));\n if (gone.length) commit({ type: 'forget', ids: gone });\n });\n\n // The selection, draft and editing events, derived from each change of the\n // model's session (a record leaving the view changes the session too, via `forget`).\n let announced = model();\n ctx.state.onChange(() => {\n const next = model();\n const previous = announced;\n announced = next;\n if (!sameIds(previous.selected, next.selected)) {\n events.selectionChanged.emit({\n refs: refsOfIn(next, next.selected),\n previousRefs: refsOfIn(previous, previous.selected),\n });\n }\n if (previous.draft !== next.draft)\n events.draftChanged.emit({ draft: creationDraftAnchor(next) });\n if (previous.editing !== next.editing) {\n events.editingChanged.emit({\n ref: next.editing ? refOf(next.byId[next.editing]) : null,\n });\n }\n if (previous.hovered !== next.hovered) {\n events.hoverChanged.emit({\n ref: next.hovered ? refOf(next.byId[next.hovered]) : null,\n });\n }\n });\n\n return {\n model,\n commit,\n apply,\n applyWhenNumbered,\n hold,\n onUpdate: (next) => {\n followUp = next;\n },\n onEffect: (kind, build) => {\n builders.set(kind, (effect, current, before) =>\n build(effect as Extract<Effect, { type: typeof kind }>, current, before),\n );\n },\n whenWritten: () => ctx.changes.whenSettled(),\n };\n}\n","import type { Annotation } from '@embedpdf/engine-core/runtime';\nimport type { Id } from '@embedpdf/core-annotation';\n\nimport type { Behavior } from '../contract';\nimport type { AnnotationStore } from '../services/store';\n\n/**\n * Behaviors: a sibling plugin (forms, links) or an interactive renderer marks\n * some annotations as interactive. While a behavior is engaged its\n * annotations render their own DOM and are not geometry-editable: hit-test,\n * marquee and the selection must not see them.\n */\nexport function createBehaviors(store: AnnotationStore) {\n const behaviors: Behavior[] = [];\n\n /** The behavior that owns the annotation now: one that matches it and is engaged. */\n const owner = (annotation: Annotation): Behavior | undefined =>\n behaviors.find((behavior) => behavior.matches(annotation) && behavior.engaged(annotation));\n\n /**\n * Ids on a page whose Behavior is currently engaged (form widgets under a\n * fill tool). Resolved per event: engagement follows the active tool live.\n */\n const engagedIdsOn = (pageObjectNumber: number): ReadonlySet<Id> | undefined => {\n if (!behaviors.length) return undefined;\n const model = store.model();\n let out: Set<Id> | undefined;\n for (const id of model.order) {\n const record = model.byId[id];\n if (!record || record.annotation.page.objectNumber !== pageObjectNumber) continue;\n if (owner(record.annotation)) (out ??= new Set()).add(id);\n }\n return out;\n };\n\n const api = {\n registerBehavior: (behavior: Behavior) => {\n behaviors.push(behavior);\n return () => {\n const index = behaviors.indexOf(behavior);\n if (index >= 0) behaviors.splice(index, 1);\n };\n },\n getBehaviorFor: (annotation: Annotation) => owner(annotation) ?? null,\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 model = store.model();\n const drop = model.selected.filter((id) => {\n const record = model.byId[id];\n return !!record && !!owner(record.annotation);\n });\n if (drop.length) store.commit({ type: 'deselect', ids: drop });\n },\n };\n\n return { engagedIdsOn, api };\n}\n\nexport type Behaviors = ReturnType<typeof createBehaviors>;\n","import {\n defaultsFor,\n kindNamed,\n propertiesOf,\n readOfDefaults,\n textOf,\n uprightRotation,\n type FieldValues,\n type KindName,\n} from '@embedpdf/core-annotation';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract/host';\n\nimport {\n buildToolRegistry,\n toolTouchOf,\n type AnnotationToolInput,\n type ResolvedTool,\n} from './definitions';\nimport type { AnnotationProperties, AnnotationTool, ToolDefaults } from '../contract';\nimport { propertyValues } from '../read/property-values';\nimport type { AnnotationContext } from '../services/context';\nimport type { AnnotationEvents } from '../services/events';\nimport type { AnnotationStore } from '../services/store';\n\n/**\n * The resolved tool table (built-ins + the `tools` setting). A tool is a named\n * authoring preset: it maps its id → a routing subtype, a `defaults` key\n * (`preset`), the kind whose properties it shows, and, for stamps, a source\n * spec. The setting's tools are kept so `tools.register` can re-resolve\n * `extends` against the same base pool.\n */\nexport function createToolRegistry(\n ctx: Pick<AnnotationContext, 'tryGet'>,\n settingTools: readonly AnnotationToolInput[],\n store: AnnotationStore,\n events: Pick<AnnotationEvents, 'toolDefaultsChanged'>,\n) {\n const configTools = [...settingTools];\n const registry = buildToolRegistry(configTools);\n // Every tool's next annotation starts from its defaults.\n for (const tool of registry.values()) {\n if (tool.defaults) {\n store.commit({ type: 'setDefaults', preset: tool.preset, patch: tool.defaults });\n }\n }\n\n const get = (id: string): ResolvedTool | undefined => registry.get(id);\n const values = (): ResolvedTool[] => [...registry.values()];\n\n /** The hub's active tool, resolved through this registry (undefined when\n * no interaction plugin is present or the id is not an annotation tool). */\n const activeTool = (): ResolvedTool | undefined => {\n const ix = ctx.tryGet(InteractionToken);\n return ix ? registry.get(ix.getActiveToolId()) : undefined;\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 tool = activeTool();\n return tool?.upright ? uprightRotation(displayRotation) : 0;\n };\n\n /**\n * A tool's defaults over the engine's for its kind, and the properties its\n * style panel edits with their values. Cached per tool while its defaults\n * stay the same object, so a subscribed panel re-renders only when they change.\n */\n const toolProperties = new Map<\n string,\n { own: FieldValues; defaults: FieldValues; properties: AnnotationProperties }\n >();\n const toolPropertiesOf = (toolId: string) => {\n const tool = registry.get(toolId);\n const kind = tool?.subtype ?? toolId;\n const own = defaultsFor(store.model(), tool?.preset ?? toolId);\n const cached = toolProperties.get(toolId);\n if (cached?.own === own) return cached;\n const read = readOfDefaults(kind, own);\n const { subtype: _kind, ...defaults } = read as unknown as Record<string, unknown>;\n // A tool's style panel edits its kind's properties: an arrow edits a line's.\n // The registry holds that mapping.\n const properties = propertiesOf(kindNamed(tool?.fieldsKind ?? toolId));\n const text = textOf(read);\n const target = read.subtype === 'link' ? (read.target ?? null) : null;\n const entry = {\n own,\n defaults,\n properties: {\n properties,\n values: propertyValues(properties, { data: defaults, text, link: target }),\n mixed: [],\n },\n };\n toolProperties.set(toolId, entry);\n return entry;\n };\n\n /** Merge fields into a tool's defaults, and say so; a change to the values they have changes nothing. */\n const updateDefaults = (toolId: string, changes: FieldValues): void => {\n const own = toolPropertiesOf(toolId).own;\n const changed = Object.entries(changes).some(\n ([key, value]) => JSON.stringify(own[key]) !== JSON.stringify(value),\n );\n if (!changed) return;\n store.commit({\n type: 'setDefaults',\n preset: registry.get(toolId)?.preset ?? toolId,\n patch: changes,\n });\n events.toolDefaultsChanged.emit({ toolId, defaults: toolPropertiesOf(toolId).defaults });\n };\n\n const toolProjections = new WeakMap<ResolvedTool, AnnotationTool>();\n const projectTool = (tool: ResolvedTool): AnnotationTool => {\n let hit = toolProjections.get(tool);\n if (!hit) {\n hit = {\n id: tool.id,\n subtype: tool.subtype,\n preset: tool.preset,\n cursor: tool.cursor,\n enables: [...tool.enables],\n ...(tool.defaults ? { defaults: tool.defaults } : {}),\n ghost: tool.ghost,\n ...(tool.meta ? { meta: tool.meta } : {}),\n };\n toolProjections.set(tool, hit);\n }\n return hit;\n };\n\n const register = (definition: AnnotationToolInput) => {\n // Re-resolve against the same base pool so `extends` can reach built-ins /\n // setting tools, then register just this one with the hub + seed its defaults.\n const resolved = buildToolRegistry([...configTools, definition]).get(definition.id);\n if (!resolved) throw new Error(`[annotation] could not resolve tool '${definition.id}'`);\n registry.set(resolved.id, resolved);\n const un = ctx.tryGet(InteractionToken)?.registerTool(\n {\n id: resolved.id,\n cursor: resolved.cursor,\n enables: resolved.enables,\n touch: toolTouchOf(resolved.enables),\n },\n { replace: true },\n );\n if (resolved.defaults)\n store.commit({ type: 'setDefaults', preset: resolved.preset, patch: resolved.defaults });\n return () => {\n registry.delete(resolved.id);\n un?.();\n };\n };\n\n /** The `tools` noun. */\n const tools = {\n list: () => values().map(projectTool),\n get: (id: string) => {\n const tool = registry.get(id);\n return tool ? projectTool(tool) : null;\n },\n register,\n getDefaults: (toolId: string): ToolDefaults => toolPropertiesOf(toolId).defaults,\n updateDefaults,\n getProperties: (toolId: string): AnnotationProperties => toolPropertiesOf(toolId).properties,\n onDefaultsChanged: events.toolDefaultsChanged.on,\n };\n\n const api = {\n listResolvedTools: () => values(),\n getResolvedTool: (id: string) => registry.get(id) ?? null,\n getToolSubtype: (id: string) => registry.get(id)?.subtype ?? (id as KindName),\n };\n\n return { get, values, activeTool, uprightRotFor, tools, api };\n}\n\nexport type ToolRegistry = ReturnType<typeof createToolRegistry>;\n","/**\n * What happens after a tool creates an annotation (the `afterCreate` setting,\n * and a tool's own over it): whether the new annotation is selected, whether a\n * new text box opens for typing, and whether the tool stays active. Code that\n * creates never selects unless it asks (`create(…, { select: true })`), so\n * this applies only to what a tool makes.\n */\nimport type { Id, UpdateResult } from '@embedpdf/core-annotation';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract/host';\n\nimport type { AfterCreateSettings } from '../contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\n\n/** The records a message created. */\nconst createdIds = (result: UpdateResult): Id[] =>\n result.effects.flatMap((effect) => (effect.type === 'create' ? [effect.id] : []));\n\nexport function createAfterCreate(\n ctx: Pick<AnnotationContext, 'tryGet'>,\n { settings, tools, store }: Pick<AnnotationServices, 'settings' | 'tools' | 'store'>,\n) {\n /** The policy for a tool: its own `afterCreate` over the setting. */\n const policyOf = (toolId: string | undefined): AfterCreateSettings => ({\n ...settings.get().afterCreate,\n ...(toolId ? tools.get(toolId)?.afterCreate : undefined),\n });\n\n /**\n * A tool's create, as the policy shows it: the core selects what it made\n * and opens a new text box for typing. Without `editText` the box doesn't\n * open; without `select` nothing is selected, except a box being typed in.\n */\n const shape =\n (toolId: string | undefined) =>\n (result: UpdateResult): UpdateResult => {\n const created = createdIds(result);\n if (!created.length) return result;\n const policy = policyOf(toolId);\n let session = result.session;\n if (!policy.editText && session.editing !== null && created.includes(session.editing)) {\n session = { ...session, editing: null };\n }\n const typing = session.editing !== null && created.includes(session.editing);\n if (!policy.select && !typing) session = { ...session, selected: [] };\n return session === result.session ? result : { ...result, session };\n };\n\n /** After a tool's create: go back to the default tool when the policy says so. */\n const done = (toolId: string | undefined, result: { effects: readonly { type: string }[] }) => {\n if (!result.effects.some((effect) => effect.type === 'create')) return;\n if (policyOf(toolId).tool !== 'default') return;\n ctx.tryGet(InteractionToken)?.activateDefaultTool();\n };\n\n /** A click-placed create (a note, a stamp, a file): select it as the policy says, then `done`. */\n const placed = (toolId: string | undefined, ids: readonly Id[]): void => {\n if (policyOf(toolId).select) store.commit({ type: 'select', ids: [...ids] });\n if (policyOf(toolId).tool === 'default') ctx.tryGet(InteractionToken)?.activateDefaultTool();\n };\n\n return { shape, done, placed };\n}\n\nexport type AfterCreate = ReturnType<typeof createAfterCreate>;\n","import type { Mirror, Settings } from '@embedpdf/core';\nimport type { FontLookup } from '@embedpdf/core-annotation';\nimport { isLocalEngine } from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationSettings } from '../contract';\nimport { createAuthority, type Authority } from './authority';\nimport { createView, type View } from '../read/view';\nimport type { AnnotationContext } from './context';\nimport { createAnnotationEvents, type AnnotationEvents } from './events';\nimport { createFilePickerPort, type FilePickerPort } from './file-picker';\nimport { createPageLookup, type PageLookup } from './geometry';\nimport { createLending, type Lending } from './lending';\nimport { createStore, type AnnotationStore } from './store';\nimport { createRecordsMirror, type AnnotationRecords } from '../sync/records';\nimport { createBehaviors, type Behaviors } from '../tools/behaviors';\nimport { createToolRegistry, type ToolRegistry } from '../tools/registry';\nimport { createAfterCreate, type AfterCreate } from '../write/after-create';\n\nexport type { AnnotationContext } from './context';\n\n/**\n * The plugin-private helpers every area is built on. Created once by the\n * controller and handed to the areas, which declare the members they use.\n * Nothing here belongs to the kernel: these are annotation-specific\n * wrappers over `ctx`.\n */\nexport interface AnnotationServices {\n /** The plugin's settings, shared by every document: read `get()` where a setting is used. */\n readonly settings: Settings<AnnotationSettings>;\n readonly events: AnnotationEvents;\n /** The records: what the engine confirmed (`get`), with this session's pending changes on top (`view`). */\n readonly records: Mirror<AnnotationRecords>;\n /** The records as shown, each drawn as its pending change says, composed with the session. */\n readonly view: View;\n /** A sibling's records shown and edited as annotations (the form plugin's widgets). */\n readonly lending: Lending;\n /** The one door user actions go through. */\n readonly store: AnnotationStore;\n readonly geometry: PageLookup;\n readonly authority: Authority;\n readonly filePicker: FilePickerPort;\n /** The registered fonts, for face ↔ key mapping (the local engine's list;\n * the cloud engine registers none). */\n readonly fonts: FontLookup;\n readonly tools: ToolRegistry;\n readonly behaviors: Behaviors;\n /** What happens after a tool creates an annotation (`afterCreate`). */\n readonly afterCreate: AfterCreate;\n}\n\nexport function createServices(ctx: AnnotationContext): AnnotationServices {\n const settings = ctx.settings();\n const events = createAnnotationEvents(ctx);\n const geometry = createPageLookup(ctx);\n const records = createRecordsMirror(ctx, events);\n const lending = createLending(() => ctx.notify());\n const view = createView(ctx, records, lending);\n const store = createStore(ctx, view, records, events, lending);\n // The tools a document has are read once, when it opens.\n const tools = createToolRegistry(ctx, settings.get().tools, store, events);\n return {\n settings,\n events,\n records,\n view,\n lending,\n store,\n geometry,\n authority: createAuthority(ctx, store),\n filePicker: createFilePickerPort(ctx),\n fonts: () => (isLocalEngine(ctx.engine) ? ctx.engine.fonts.list() : []),\n tools,\n behaviors: createBehaviors(store),\n afterCreate: createAfterCreate(ctx, { settings, tools, store }),\n };\n}\n","import type { EventOrigin } from '@embedpdf/core';\nimport type { Annotation, AnnotationRef, PageRef } from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationEvents } from './events';\n\n/**\n * Announces confirmed record changes: the engine's record, whoever caused the\n * change (an API verb, a gesture, a remote session).\n */\nexport function createAnnouncer(events: AnnotationEvents) {\n return {\n created: (annotation: Annotation, origin: EventOrigin) =>\n events.created.emit({ annotation, origin }),\n updated: (annotation: Annotation, origin: EventOrigin) =>\n events.updated.emit({ annotation, origin }),\n deleted: (refs: readonly AnnotationRef[], page: PageRef, origin: EventOrigin) =>\n events.deleted.emit({ refs, page, origin }),\n reordered: (page: PageRef, order: readonly AnnotationRef[], origin: EventOrigin) =>\n events.reordered.emit({ page, order, origin }),\n };\n}\n\nexport type Announcer = ReturnType<typeof createAnnouncer>;\n","/**\n * What happens when the engine confirms a change, whoever made it:\n *\n * - how the record renders follows who changed it: this session's creates\n * render live from their description, another session's changes render\n * from the engine's raster (their appearance is the truth it baked);\n * - the record events fire: created, updated, deleted, moved, and\n * resynced after a load.\n *\n * The data itself is already in the records mirror when this runs.\n */\nimport type { MirrorChange } from '@embedpdf/core';\nimport { annotationKey } from '@embedpdf/engine-core/runtime';\n\nimport { preferBaked, preferVector } from '../model';\nimport type { AnnotationRecords } from './records';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Announcer } from '../services/announce';\n\nexport function followConfirmedChanges(\n ctx: Pick<AnnotationContext, 'state'>,\n { events }: Pick<AnnotationServices, 'events'>,\n announce: Announcer,\n): void {\n events.recordsChanged.on((change) => follow(change));\n\n function follow(change: MirrorChange<AnnotationRecords>): void {\n if (change.cause === 'load') {\n events.resynced.emit({ pages: change.pages ?? 'all' });\n return;\n }\n const event = change.event;\n if (!event || !('origin' in event)) return;\n const { origin } = event;\n const remote = origin.kind === 'remote';\n switch (event.type) {\n case 'annotations.created': {\n const { annotation: created } = event;\n const key = annotationKey(created.ref);\n ctx.state.update(remote ? preferBaked : preferVector, [key]);\n announce.created(created, origin);\n return;\n }\n case 'annotations.updated':\n if (remote) ctx.state.update(preferBaked, [annotationKey(event.annotation.ref)]);\n announce.updated(event.annotation, origin);\n return;\n case 'annotations.deleted':\n // A note goes with its thread and popups: one event names them all, the note first.\n announce.deleted(event.deleted, event.page, origin);\n return;\n case 'annotations.reordered':\n announce.reordered(event.page, event.order, origin);\n return;\n default:\n return;\n }\n }\n}\n","import {\n anchoredGeom,\n anchorModeOf,\n fitStampBox,\n toolAnnotation,\n unanchoredGeom,\n type BoxShape,\n type FieldValues,\n type KindName,\n type Model,\n type Point,\n type Rect,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport type {\n AnnotationDraft,\n Annotation,\n AnnotationFlags,\n AnnotationResources,\n AttachmentFileSource,\n PageBox,\n} from '@embedpdf/engine-core/runtime';\n\n/**\n * Per-kind code for the click-to-place icon kinds (note / file attachment)\n * — the `props.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 their usual size: the icon fills its rect, so the\n * tool's 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: KindName): subtype is IconPlaceKind =>\n subtype === 'text' || subtype === 'file-attachment';\n\n/**\n * What a tool creates, read as an annotation before it has a shape: its\n * defaults and its `/F` seed. Its placement, its ghost and its commit all\n * start from it.\n */\nexport const annotationOfTool = (\n model: Model,\n tool: { subtype: KindName; preset: string; flags?: Partial<AnnotationFlags> },\n): Annotation =>\n ({ ...toolAnnotation(model, tool.subtype, tool.preset), ...tool.flags }) as Annotation;\n\n/**\n * Where an icon placed at `point` goes, at the view the user sees. An icon is\n * screen-anchored (`noZoom`, `noRotate`): it shows upright and at its usual\n * size, hanging from its rect's upper-left corner. So the placement starts\n * from how it shows, the icon centred on the pointer and kept on the page\n * (`shown`, what the ghost draws), and stores the rect whose own display is\n * exactly that (`rect`, through `unanchoredGeom`, the inverse gestures use).\n * `annotation` is what the tool creates, read for its flags. Without a view\n * the two are the same box.\n */\nexport function iconPlaceAt(\n annotation: Annotation,\n point: Point,\n page: { width: number; height: number },\n view: ViewEnv | undefined,\n): { shown: BoxShape; rect: Rect } {\n const mode = anchorModeOf({ annotation });\n // How an icon at its usual size shows at this view: its size and its turn.\n const usual: BoxShape = {\n kind: 'box',\n box: { x: 0, y: 0, ...ICON_PLACE_SIZE },\n rotation: 0,\n ellipse: false,\n };\n const { box: size, rotation } = anchoredGeom(usual, mode, view) as BoxShape;\n const shown: BoxShape = {\n kind: 'box',\n box: fitStampBox(point, { width: size.width, height: size.height }, page, rotation),\n rotation,\n ellipse: false,\n };\n return { shown, rect: (unanchoredGeom(shown, mode, view) as BoxShape).box };\n}\n\n/**\n * Build the engine create for a placed icon annotation: its data, and for a\n * file attachment the file's bytes as the `file` resource. `geometry` is the\n * icon's `rect`; `defaults` are the tool's (`defaultsFor`): its icon, colour\n * and opacity. What they leave out takes the engine's defaults.\n */\nexport function iconPlacement(\n subtype: IconPlaceKind,\n geometry: { rect: PageBox },\n defaults: FieldValues,\n flags: Partial<AnnotationFlags> | undefined,\n file: AttachmentFileSource | null,\n): { data: AnnotationDraft; resources?: AnnotationResources } {\n // The tool's seed (the note/attachment tools pass noZoom + noRotate); a\n // new annotation prints by the engine's default.\n const shared = { ...defaults, ...geometry, ...flags };\n if (subtype === 'text') return { data: { ...shared, subtype: 'text' } as AnnotationDraft };\n if (!file) {\n throw new Error('[annotation] a file-attachment placement requires a file payload');\n }\n return {\n data: {\n ...shared,\n subtype: 'file-attachment',\n file: attachmentMetadataOf(file),\n } as AnnotationDraft,\n resources: { file: file.data instanceof ArrayBuffer ? new Uint8Array(file.data) : file.data },\n };\n}\n\n/** A picked file's name, MIME type and description: from the source, else from a browser `File`. */\nfunction attachmentMetadataOf(file: AttachmentFileSource): {\n name: string;\n mimeType?: string;\n description?: string;\n} {\n const blob = typeof Blob !== 'undefined' && file.data instanceof Blob ? file.data : null;\n const name = file.name ?? (blob as File | null)?.name;\n if (!name) {\n throw new Error('[annotation] an attached file needs a name: pass { data, name } or a File');\n }\n const mimeType = file.mimeType ?? (blob?.type || undefined);\n return {\n name,\n ...(mimeType !== undefined ? { mimeType } : {}),\n ...(file.description !== undefined ? { description: file.description } : {}),\n };\n}\n","import {\n fitStampBox,\n gesturePlacement,\n isDrag,\n placedShape,\n resolveClickPlacement,\n unmadeItem,\n type Draft,\n type Model,\n type Point,\n type RenderItem,\n type Shape,\n type ViewEnv,\n} from '@embedpdf/core-annotation';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport type { PageRef } from '@embedpdf/engine-core/runtime';\n\nimport type { ImageGhost } from '../contract';\nimport { setGhostAt, setPlacing, type ForeignPlacement, type GhostPointer } from '../model';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { ResolvedTool } from './definitions';\nimport { viewEnv } from '../services/geometry';\nimport { annotationOfTool, iconPlaceAt, isIconPlaceKind } from '../write/placement';\nimport type { Stamps } from '../write/stamps';\n\n/** The render ids of the tool's ghost and of a sibling plugin's placement in progress. */\nconst GHOST_ID = 'tool-ghost';\nconst PLACING_ID = 'tool-placing';\n\n/**\n * Whether the gesture in progress, if any, is still a click, so the ghost\n * still shows what its release makes. A box or a line being drawn is, until\n * it is a drag; any other gesture (a move, a polygon's clicks) is not.\n */\nfunction stillAClick(draft: Draft | null, placing: ForeignPlacement | null): boolean {\n if (placing && isDrag('box', placing.from, placing.to)) return false;\n if (!draft) return true;\n if (draft.kind === 'create-rect') return !isDrag('box', draft.from, draft.to);\n if (draft.kind === 'create-line') return !isDrag('segment', draft.from, draft.to);\n return false;\n}\n\n/**\n * The active tool's ghost: what a click at the pointer would make, painted\n * see-through where it will land.\n *\n * A create tool answers one question: if the gesture ended now, what would\n * exist? The ghost is that answer before the press, so it comes from the very\n * calls the commit makes: a click-create tool's `resolveClickPlacement` and\n * `placedShape` (what the core's commit of a click makes), a note's or an\n * attachment's `iconPlaceAt` (the icon placement), an armed stamp's\n * `fitStampBox` (the stamp placement). It paints through `unmadeItem`, as the\n * made annotation will. The state holds only the pointer (`ghostAt`); the\n * ghost is derived from it and the tool's live defaults, so a new color shows\n * without a new hover.\n *\n * When it shows is the handlers' call (tools/handlers.ts): the handler that\n * would take the click shows it on hover, only where nothing above it claims\n * the pointer (an annotation, text) and the user may create, and clears it\n * when its gesture ends. While the press is still a click it stays; once the\n * gesture is a drag, the drawing in progress takes over.\n *\n * A sibling plugin's gesture with one of this plugin's tools (the form\n * palette's drag-to-place) reports itself through `previewPlacement`, and\n * once it is a drag it paints as a drawing in progress, the same way.\n */\nexport function createGhost(\n ctx: Pick<AnnotationContext, 'state'>,\n { store, geometry, tools }: Pick<AnnotationServices, 'store' | 'geometry' | 'tools'>,\n stamps: Pick<Stamps, 'armed'>,\n) {\n const clearGhost = (): void => {\n ctx.state.update(setGhostAt, null);\n };\n\n /** Whether a click with `tool` places something: an armed stamp, an icon, or its click default. */\n const clickPlaces = (tool: ResolvedTool): boolean =>\n stamps.armed() !== null || isIconPlaceKind(tool.subtype) || tool.clickCreate !== false;\n\n /** Put the tool's ghost at a hover, or clear it for a tool that shows none there. */\n const hoverGhostAt = (\n toolId: string,\n page: PageRef,\n point: Point,\n displayRotation?: PageRotation,\n zoom?: number,\n ): void => {\n const tool = tools.get(toolId);\n if (\n !tool ||\n tool.ghost === false ||\n !clickPlaces(tool) ||\n !geometry.sizeOf(page.objectNumber)\n ) {\n clearGhost();\n return;\n }\n const pointer: GhostPointer = {\n toolId,\n page,\n point,\n ...(displayRotation !== undefined ? { displayRotation } : {}),\n ...(zoom !== undefined ? { zoom } : {}),\n };\n ctx.state.update(setGhostAt, pointer);\n };\n\n /**\n * The shape a click with `tool` at the pointer makes, as it will be stored:\n * a note's or an attachment's icon (`iconPlaceAt`, the icon placement), or\n * the tool's click default (`resolveClickPlacement`, the core's click commit).\n */\n const clickShape = (tool: ResolvedTool, pointer: GhostPointer, model: Model): Shape | null => {\n const pageObjectNumber = pointer.page.objectNumber;\n const page = geometry.sizeOf(pageObjectNumber);\n if (!page) return null;\n const annotation = annotationOfTool(model, tool);\n if (isIconPlaceKind(tool.subtype)) {\n const view = viewEnv(pointer.zoom, pointer.displayRotation);\n const { rect } = iconPlaceAt(annotation, pointer.point, page, view);\n return placedShape(annotation, { kind: 'box', rect, rot: 0 });\n }\n if (!tool.clickCreate) return null;\n const placement = resolveClickPlacement(pointer.point, tool.clickCreate, {\n pageBox: geometry.pageBoxOf(pageObjectNumber),\n upright: tool.upright,\n displayRotation: pointer.displayRotation,\n });\n return placedShape(annotation, placement);\n };\n\n /**\n * What the ghost and a sibling plugin's placement paint on a page, at the\n * view the page shows: the click's annotation at the pointer (`ghost`), and\n * the placement once it is a drag (`draft`). An armed stamp's ghost is an\n * image instead ({@link getImageGhost}).\n */\n const itemsOn = (pageObjectNumber: number, model: Model, view?: ViewEnv): RenderItem[] => {\n const { ghostAt, placing } = ctx.state.get();\n const items: RenderItem[] = [];\n const tool = ghostAt && tools.get(ghostAt.toolId);\n if (\n ghostAt?.page.objectNumber === pageObjectNumber &&\n tool?.ghost &&\n stamps.armed() === null &&\n stillAClick(model.draft, placing)\n ) {\n const shape = clickShape(tool, ghostAt, model);\n if (shape) {\n items.push({\n ...unmadeItem(GHOST_ID, annotationOfTool(model, tool), shape, 'ghost', view),\n ghostOpacity: tool.ghost.opacity,\n });\n }\n }\n const placingTool = placing && tools.get(placing.toolId);\n if (\n placing?.page.objectNumber === pageObjectNumber &&\n placingTool &&\n isDrag('box', placing.from, placing.to)\n ) {\n // The box the sibling's commit places: the same call, the same page box.\n const placement = gesturePlacement('box', placing.from, placing.to, placingTool.clickCreate, {\n pageBox: geometry.pageBoxOf(pageObjectNumber),\n });\n const annotation = annotationOfTool(model, placingTool);\n const shape = placement && placedShape(annotation, placement);\n if (shape) items.push(unmadeItem(PLACING_ID, annotation, shape, 'draft', view));\n }\n return items;\n };\n\n /**\n * The armed stamp's ghost: its image in the box a click would place it in\n * (`fitStampBox` with the tool's upright turn, as the stamp placement fits\n * it). The same object while nothing it depends on changes.\n */\n let imageGhost: {\n ghostAt: GhostPointer;\n armed: object;\n value: ImageGhost | null;\n } | null = null;\n const getImageGhost = (page: PageRef): ImageGhost | null => {\n const { ghostAt, placing } = ctx.state.get();\n const armed = stamps.armed();\n if (!ghostAt || !armed || ghostAt.page.objectNumber !== page.objectNumber) return null;\n if (!stillAClick(store.model().draft, placing)) return null;\n if (imageGhost?.ghostAt !== ghostAt || imageGhost.armed !== armed) {\n const tool = tools.get(ghostAt.toolId);\n const size = geometry.sizeOf(page.objectNumber);\n const rot = tools.uprightRotFor(ghostAt.displayRotation);\n const value =\n tool?.ghost && size\n ? {\n page,\n box: fitStampBox(ghostAt.point, armed, size, rot),\n rot,\n opacity: tool.ghost.opacity,\n }\n : null;\n imageGhost = { ghostAt, armed, value };\n }\n return imageGhost.value;\n };\n\n const api = {\n hoverGhostAt,\n clearGhost,\n previewPlacement: (toolId: string, page: PageRef, from: Point, to: Point) => {\n ctx.state.update(setPlacing, { toolId, page, from, to });\n },\n clearPlacementPreview: () => {\n ctx.state.update(setPlacing, null);\n },\n getImageGhost,\n };\n\n return { itemsOn, api };\n}\n\nexport type Ghost = ReturnType<typeof createGhost>;\n","/**\n * Create, update, delete and reorder: the public verbs, in the engine's own\n * terms, and the transfers (export, import, a resource's bytes). Each change\n * states itself through `store.apply`, so it shows at once and is sent,\n * answered and refused exactly like a gesture's, and each resolves with what\n * the engine wrote for it: its own change's answer, never another change\n * still on its way.\n */\nimport { PluginError, type OperationOptions } from '@embedpdf/core';\nimport { defaultsFor } from '@embedpdf/core-annotation';\nimport {\n ANNOTATION_FIELD_NAMES,\n anchorOf,\n annotationKey,\n type Annotation,\n type AnnotationBundle,\n type AnnotationDraft,\n type AnnotationImportOptions,\n type AnnotationPatch,\n type AnnotationPosition,\n type AnnotationRef,\n type AnnotationResourceRole,\n type AnnotationResources,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationExportSelection, AnnotationImportResult } from '../contract';\nimport type { AnnotationReads } from '../read/annotations';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { appliedAnnotationOf, appliedOrThrow } from './outcomes';\n\nexport function createCrud(\n ctx: Pick<AnnotationContext, 'doc' | 'pageOf' | 'assertAllowed' | 'cancellable'>,\n { store, tools, records }: Pick<AnnotationServices, 'store' | 'tools' | 'records'>,\n annotations: Pick<AnnotationReads, 'get' | 'pageOf'>,\n /** Write what is held back (typed text) and wait for every write on its way. */\n settle: () => Promise<void>,\n) {\n /** The annotation `ref` names, as the view holds it: for a change that wrote nothing. */\n const current = (ref: AnnotationRef): { annotation: Annotation } => {\n const annotation = annotations.get(ref);\n if (!annotation) {\n throw new PluginError('not-found', 'annotation', `no annotation ${annotationKey(ref)}`);\n }\n return { annotation };\n };\n\n /**\n * `draft` over a tool's defaults and flags: what it leaves out, the tool\n * fills in, and the engine's defaults the rest. The tool's text body is\n * left out: it formats text drawn with the tool, and a draft brings its own.\n */\n const withTool = (draft: AnnotationDraft, toolId: string): AnnotationDraft => {\n const tool = tools.get(toolId);\n if (!tool) throw new PluginError('not-found', 'annotation', `no tool '${toolId}'`);\n const declared = ANNOTATION_FIELD_NAMES[draft.subtype];\n const defaults = Object.entries(defaultsFor(store.model(), tool.preset)).filter(\n ([name]) => name !== 'richText' && declared.includes(name),\n );\n return { ...tool.flags, ...Object.fromEntries(defaults), ...draft } as AnnotationDraft;\n };\n\n const create = async (\n page: PageRef | number,\n fields: AnnotationDraft | Annotation,\n resources?: AnnotationResources,\n options: OperationOptions & { tool?: string; select?: boolean } = {},\n ): Promise<{ annotation: Annotation }> => {\n ctx.assertAllowed('annotations:create', 'annotation.create');\n const { ref } = ctx.pageOf(page);\n // A read is a create too (a copy): the engine writes only its own fields,\n // and refuses a value a write can't make. A kind it doesn't know has none.\n if (fields.subtype === 'unsupported') {\n throw new PluginError(\n 'invalid-input',\n 'annotation',\n \"a kind the engine doesn't know can't be created\",\n );\n }\n const draft = fields as AnnotationDraft;\n const stated = options.tool ? withTool(draft, options.tool) : draft;\n const applied = await store.applyWhenNumbered(\n [{ type: 'create', page: ref, draft: stated, ...(resources ? { resources } : {}) }],\n { select: options.select },\n );\n const annotation = await ctx.cancellable(options.signal, appliedAnnotationOf(applied));\n if (!annotation) {\n throw new PluginError(\n 'operation-failed',\n 'annotation',\n 'the annotation could not be created',\n );\n }\n return { annotation };\n };\n\n const update = async (\n ref: AnnotationRef,\n patch: AnnotationPatch,\n resources?: AnnotationResources,\n options: OperationOptions = {},\n ): Promise<{ annotation: Annotation }> => {\n const annotation = await ctx.cancellable(\n options.signal,\n appliedAnnotationOf(\n store.apply([{ type: 'update', ref, patch, ...(resources ? { resources } : {}) }]),\n ),\n );\n return annotation ? { annotation } : current(ref);\n };\n\n const remove = async (ref: AnnotationRef, options: OperationOptions = {}): Promise<void> => {\n await ctx.cancellable(options.signal, appliedOrThrow(store.apply([{ type: 'delete', ref }])));\n };\n\n /**\n * Move annotations on one page to a new place in its drawing order, next to\n * a neighbour or to the bottom or top. The new order shows at once, and goes\n * away if the engine refuses it.\n */\n const reorder = async (\n refs: readonly AnnotationRef[],\n position: AnnotationPosition,\n options: OperationOptions = {},\n ): Promise<void> => {\n if (!refs.length) return;\n const model = store.model();\n const recordOf = (ref: AnnotationRef) => {\n const record = model.byId[annotationKey(ref)];\n if (!record) {\n throw new PluginError('not-found', 'annotation', `no annotation ${annotationKey(ref)}`);\n }\n return record;\n };\n const moving = refs.map(recordOf);\n const anchor = anchorOf(position);\n const neighbour = anchor ? recordOf(anchor) : null;\n const page = moving[0]!.annotation.page;\n const onOtherPage = (record: { annotation: { page: PageRef } }) =>\n record.annotation.page.objectNumber !== page.objectNumber;\n if (moving.some(onOtherPage) || (neighbour && onOtherPage(neighbour))) {\n throw new PluginError(\n 'invalid-input',\n 'annotation',\n 'a reorder stays on one page: the annotations and their neighbour',\n );\n }\n await ctx.cancellable(\n options.signal,\n appliedOrThrow(\n store.apply([\n {\n type: 'reorder',\n page,\n refs: moving.map((record) => record.annotation.ref),\n position,\n },\n ]),\n ),\n );\n };\n\n /** The pages a selection names, as refs: an index becomes its page's ref. */\n const pageRefsOf = (pages: readonly (PageRef | number)[] | undefined): PageRef[] | undefined =>\n pages?.map((page) => ctx.pageOf(page).ref);\n\n const exportBundle = async (\n selection: AnnotationExportSelection = {},\n options: OperationOptions = {},\n ): Promise<AnnotationBundle> => {\n ctx.assertAllowed('doc.download', 'annotation.export');\n const pages = pageRefsOf(selection.pages);\n // What the user sees is what the bundle carries: typed text and pending writes land first.\n await ctx.cancellable(options.signal, settle());\n return ctx.cancellable(\n options.signal,\n ctx.doc.annotations.export({\n ...(selection.refs ? { refs: selection.refs } : {}),\n ...(pages ? { pages } : {}),\n }),\n );\n };\n\n const importBundle = async (\n bundle: AnnotationBundle,\n options: AnnotationImportOptions & OperationOptions = {},\n ): Promise<AnnotationImportResult> => {\n ctx.assertAllowed('annotations:create', 'annotation.import');\n const { signal, ...importOptions } = options;\n const result = await ctx.cancellable(signal, ctx.doc.annotations.import(bundle, importOptions));\n // The engine published one `annotations.created` per annotation: once the\n // records hold them, `list()` shows them.\n await records.settled();\n return { annotations: result.annotations, refMap: result.refMap, dropped: result.dropped };\n };\n\n const downloadResource = async (\n ref: AnnotationRef,\n role: AnnotationResourceRole,\n options: OperationOptions = {},\n ): Promise<Uint8Array> => {\n ctx.assertAllowed('doc.download', 'annotation.downloadResource');\n current(ref);\n return ctx.cancellable(\n options.signal,\n ctx.doc.page(annotations.pageOf(ref)).annotations.downloadResource(ref, role),\n );\n };\n\n const api = {\n create,\n update,\n delete: remove,\n reorder,\n export: exportBundle,\n import: importBundle,\n downloadResource,\n };\n\n return { update, api };\n}\n\nexport type Crud = ReturnType<typeof createCrud>;\n","import {\n creationDraftAnchor,\n type CreationDraftAnchor,\n type Model,\n} from '@embedpdf/core-annotation';\nimport type { Annotation } from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationReads } from '../read/annotations';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { createdRefOf } from './outcomes';\n\n/**\n * Creation drafts: the polygon or polyline a click per point builds (and the\n * buffered ink strokes), its finish and cancel doors, and the captured-draft\n * seam the measurement plugin calibrates from.\n */\nexport function createDrafts(\n ctx: Pick<AnnotationContext, 'cancellable'>,\n {\n store,\n events,\n tools,\n afterCreate,\n }: Pick<AnnotationServices, 'store' | 'events' | 'tools' | 'afterCreate'>,\n annotations: Pick<AnnotationReads, 'get'>,\n) {\n let anchorCache: { model: Model; v: CreationDraftAnchor | null } | null = null;\n const draftAnchorOf = (): CreationDraftAnchor | null => {\n const model = store.model();\n if (anchorCache && anchorCache.model === model) return anchorCache.v;\n const anchor = creationDraftAnchor(model);\n anchorCache = { model: model, v: anchor };\n return anchor;\n };\n\n // A capture-only tool (the measurement calibration line) reports its draft\n // instead of creating anything.\n store.onEffect('captured', (effect) => {\n if (effect.geometry.kind === 'line') {\n events.draftCaptured.emit({\n tool: effect.tool,\n page: effect.page,\n from: effect.geometry.linePoints.start,\n to: effect.geometry.linePoints.end,\n });\n }\n });\n\n /** End the draft as a double-click does, through the active tool's `afterCreate`. */\n const finish = async (\n options: { signal?: AbortSignal } = {},\n ): Promise<{ annotation: Annotation } | null> => {\n const draft = store.model().draft;\n if (!draft || !draft.kind.startsWith('create-')) return null;\n const toolId = tools.activeTool()?.id;\n const commit = store.commit(\n { type: draft.kind === 'create-ink' ? 'finishInkDraft' : 'finishCreationDraft' },\n { adjust: afterCreate.shape(toolId) },\n );\n afterCreate.done(toolId, commit);\n if (!commit.effects.some((effect) => effect.type === 'create')) return null;\n const ref = await ctx.cancellable(options.signal, createdRefOf(commit));\n const annotation = annotations.get(ref);\n return annotation ? { annotation } : null;\n };\n\n /** The `draft` noun. */\n const draftApi = {\n get: () => draftAnchorOf(),\n finish,\n cancel: () => {\n store.commit({ type: 'cancel' });\n },\n };\n\n const api = {\n finishInkDraft: () => {\n const toolId = tools.activeTool()?.id;\n afterCreate.done(\n toolId,\n store.commit({ type: 'finishInkDraft' }, { adjust: afterCreate.shape(toolId) }),\n );\n },\n cancel: () => {\n store.commit({ type: 'cancel' });\n },\n distanceCreationPage: () => {\n const draft = store.model().draft;\n return draft?.kind === 'create-distance' && draft.step === 'offset' ? draft.page : null;\n },\n onDraftCaptured: events.draftCaptured.on,\n };\n\n return { draft: draftApi, api };\n}\n","import { defaultsFor, type Point, type ViewEnv } from '@embedpdf/core-annotation';\nimport {\n toPageRef,\n type AnnotationDraft,\n type AnnotationResources,\n type AttachmentFileSource,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\n\nimport { annotationOfTool, iconPlaceAt, iconPlacement, isIconPlaceKind } from './placement';\nimport type { FilePickerProvider } from '../contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { viewEnv } from '../services/geometry';\nimport { appliedOrThrow } from './outcomes';\nimport type { Stamps } from './stamps';\nimport type { ResolvedTool } from '../tools/definitions';\n\n/**\n * Icon annotations (sticky notes, file attachments): fixed-size placement at\n * a click, and the one click-to-place entry the place handler forwards every\n * down to.\n */\nexport function createIcons(\n ctx: Pick<AnnotationContext, 'doc'>,\n {\n store,\n geometry,\n tools,\n filePicker,\n afterCreate,\n }: Pick<AnnotationServices, 'store' | 'geometry' | 'tools' | 'filePicker' | 'afterCreate'>,\n stamps: Pick<Stamps, 'placeArmedStamp' | 'requestStampAt'>,\n) {\n /**\n * Create an icon annotation with a tool's click: its `afterCreate` says\n * whether it is selected (the anchor for its menu and comment popup).\n */\n const createIcon = (\n tool: ResolvedTool,\n pageObjectNumber: number,\n { data, resources }: { data: AnnotationDraft; resources?: AnnotationResources },\n ): Promise<unknown> =>\n store\n .applyWhenNumbered([\n { type: 'create', page: toPageRef(pageObjectNumber), draft: data, resources },\n ])\n .then((applied) => {\n afterCreate.placed(tool.id, applied.ids);\n return appliedOrThrow(applied);\n });\n\n /** Place an icon annotation (note / file attachment) at its usual size,\n * shown centred on a page point at the view the user sees (`iconPlaceAt`,\n * the same box the ghost drew) — the icon-kind sibling of the stamp\n * placement. The engine draws the icon from /C + /Name, filling /Rect. */\n const placeIconAt = (\n tool: ResolvedTool,\n pageObjectNumber: number,\n point: Point,\n view: ViewEnv | undefined,\n file: AttachmentFileSource | null,\n ): boolean => {\n const doc = ctx.doc;\n const page = geometry.sizeOf(pageObjectNumber);\n if (!doc || !page || !isIconPlaceKind(tool.subtype)) return false;\n const { rect } = iconPlaceAt(annotationOfTool(store.model(), tool), point, page, view);\n const placement = iconPlacement(\n tool.subtype,\n { rect },\n defaultsFor(store.model(), tool.preset),\n tool.flags,\n file,\n );\n void createIcon(tool, pageObjectNumber, placement).catch((error) =>\n console.error('[annotation] icon placement failed:', error),\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 = (\n pageObjectNumber: number,\n point: Point,\n displayRotation?: number,\n zoom?: number,\n ): boolean => {\n if (stamps.placeArmedStamp(pageObjectNumber, point, displayRotation)) return true;\n const tool = tools.activeTool();\n if (!tool) return false;\n if (tool.subtype === 'stamp')\n return stamps.requestStampAt(pageObjectNumber, point, displayRotation);\n if (!isIconPlaceKind(tool.subtype)) return false;\n // The view at the click: an attachment lands after its file is picked,\n // where the click showed it.\n const view = viewEnv(zoom, displayRotation);\n if (tool.subtype === 'text') return placeIconAt(tool, pageObjectNumber, point, view, null);\n return filePicker.promptAt(tool, pageObjectNumber, point, (picked) =>\n placeIconAt(tool, pageObjectNumber, point, view, picked),\n );\n };\n\n const api = {\n placeAt: (page: PageRef, point: Point, displayRotation?: number, zoom?: number) =>\n placeAt(page.objectNumber, point, displayRotation, zoom),\n setFilePickerProvider: (provider: FilePickerProvider | null) => filePicker.set(provider),\n };\n\n return { api };\n}\n","import type { OperationOptions } from '@embedpdf/core';\nimport {\n type Id,\n kindOf,\n linkChildrenOf,\n linkChildRects,\n linkOf,\n type Model,\n refOf,\n shapeOf,\n styleOf,\n writableTarget,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type AnnotationDraft,\n type AnnotationRef,\n type PdfLinkTarget,\n} from '@embedpdf/engine-core/runtime';\n\nimport { appliedOrThrow } from './outcomes';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { opOfStated } from '../services/staging';\nimport type { StoreChange } from '../services/store';\n\n/**\n * Attached links (a Link child riding an editable annotation): the one\n * reconciler that creates, retargets, re-rects and deletes link children. Its\n * changes join the change that made them needed: a restyle that set a link,\n * a move of the parent.\n */\nexport function createLinkWrites(\n ctx: Pick<AnnotationContext, 'cancellable'>,\n { store }: Pick<AnnotationServices, 'store'>,\n) {\n /**\n * The changes that bring the attached link children of `id` to `desired`,\n * read from `model`. Declarative: desired state = `desired` target + the\n * parent's geometry (`linkChildRects`); current state is read straight from\n * the records (`linkChildrenOf`), new children included: no join-key\n * ledger. Idempotent: foreign inconsistencies heal on the next local edit.\n */\n const childChanges = (id: Id, desired: PdfLinkTarget | null, model: Model): StoreChange[] => {\n const record = model.byId[id];\n const parent = refOf(record);\n if (!record || !parent || kindOf(record.annotation).name === 'link') return [];\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 =\n desired == null ? [] : linkChildRects(shapeOf(record.annotation), styleOf(record.annotation));\n const current = linkChildrenOf(model, id);\n const changes: StoreChange[] = [];\n const paired = Math.min(current.length, rects.length);\n for (let i = 0; i < paired; i++) {\n changes.push({\n type: 'update',\n ref: current[i].annotation.ref,\n patch: { subtype: 'link', rect: rects[i], ...(target ? { target } : {}) },\n });\n }\n for (let i = current.length; i < rects.length; i++) {\n changes.push({\n type: 'create',\n page: record.annotation.page,\n draft: {\n subtype: 'link',\n rect: rects[i],\n target,\n reply: { to: parent, type: 'group' },\n } as AnnotationDraft,\n });\n }\n for (let i = rects.length; i < current.length; i++) {\n changes.push({ type: 'delete', ref: current[i].annotation.ref });\n }\n return changes;\n };\n\n /** Set or clear a parent's link from code: its children's changes, as one change. */\n const setLink = async (\n ref: AnnotationRef,\n target: PdfLinkTarget | null,\n options: OperationOptions,\n ): Promise<void> => {\n const changes = childChanges(annotationKey(ref), target, store.model());\n if (!changes.length) return;\n await ctx.cancellable(options.signal, store.applyWhenNumbered(changes).then(appliedOrThrow));\n };\n\n // A restyle that set or cleared a link: the children's changes join it.\n store.onEffect('syncLink', (effect, model) =>\n childChanges(effect.id, effect.target, model).map(opOfStated),\n );\n\n // An update of a parent, from either door: its children follow its new\n // shape, toward the target they hold, in the same change.\n store.onUpdate((op, model) => {\n const id = annotationKey(op.ref);\n if (!linkChildrenOf(model, id).length) return [];\n return childChanges(id, linkOf(model, id), model).map(opOfStated);\n });\n\n const api = {\n links: {\n get: (ref: AnnotationRef) => {\n const model = store.model();\n const record = model.byId[annotationKey(ref)];\n if (!record) return null;\n const annotation = record.annotation;\n return annotation.subtype === 'link'\n ? (annotation.target ?? null)\n : linkOf(model, record.id);\n },\n // Resolve once the engine answered: `get` reads the new value at once,\n // and still does then.\n set: (ref: AnnotationRef, target: PdfLinkTarget, options: OperationOptions = {}) =>\n setLink(ref, target, options),\n clear: (ref: AnnotationRef, options: OperationOptions = {}) => setLink(ref, null, options),\n },\n };\n\n return { childChanges, api };\n}\n\nexport type LinkWrites = ReturnType<typeof createLinkWrites>;\n","import { PluginError, pageRefsEqual, type OperationOptions } from '@embedpdf/core';\nimport type { KindName, TextEndAnchor, Quad, UpdateResult } from '@embedpdf/core-annotation';\nimport type { Annotation, PageRef } from '@embedpdf/engine-core/runtime';\nimport {\n SelectionToken as SelectionPublicToken,\n type SelectionSnapshot,\n} from '@embedpdf/plugin-selection/contract';\n\nimport type { AnnotationReads } from '../read/annotations';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Commit } from '../services/store';\nimport type { ResolvedTool } from '../tools/definitions';\nimport { createdRefOf } from './outcomes';\n\n/**\n * What a text tool makes of the text selection: markup (highlight, underline,\n * strikeout, squiggly, a text redaction) over the selected text, a caret at\n * its end (insert text), or a caret and strikeout pair (replace text).\n */\ntype SelectionMarkup =\n | { kind: 'markup'; subtype: KindName }\n | { kind: 'insert' }\n | { kind: 'replace' };\n\n/** What the tool makes of a text selection; `null` for a tool that makes nothing of one. */\nconst selectionMarkupOf = (tool: ResolvedTool): SelectionMarkup | null => {\n const authoring = tool.selection;\n if (!authoring) return null;\n if (authoring.kind === 'markup') return { kind: 'markup', subtype: tool.subtype };\n return { kind: authoring.operation };\n};\n\n/**\n * Text markup, carets and replace-text pairs, created over text and shown at\n * once: the text tools' path (`applyToolToSelection`, when a selection meets\n * a text tool) and the programmatic `createFromSelection`.\n */\nexport function createMarkupWrites(\n ctx: Pick<AnnotationContext, 'tryGet' | 'assertAllowed' | 'cancellable'>,\n {\n store,\n authority,\n tools,\n afterCreate,\n }: Pick<AnnotationServices, 'store' | 'authority' | 'tools' | 'afterCreate'>,\n annotations: Pick<AnnotationReads, 'get'>,\n) {\n /** How a create's result shows: a tool's `afterCreate`, or code's (nothing selected changes). */\n type Adjust = (result: UpdateResult) => UpdateResult;\n\n // A markup tool's `/F` seed rides along (the preset is the tool id).\n const commitMarkup = (\n subtype: KindName,\n page: PageRef,\n quads: Quad[],\n preset?: string,\n adjust?: Adjust,\n ) =>\n store.commit(\n {\n type: 'createMarkup',\n subtype,\n page,\n quads,\n preset,\n flags: preset ? tools.get(preset)?.flags : undefined,\n },\n { adjust },\n );\n const commitCaret = (page: PageRef, anchor: TextEndAnchor, adjust?: Adjust) =>\n store.commit({ type: 'createCaret', page, anchor }, { adjust });\n const commitReplaceText = (\n page: PageRef,\n quads: Quad[],\n anchor: TextEndAnchor,\n preset?: string,\n adjust?: Adjust,\n ) => store.commit({ type: 'createReplaceText', page, quads, anchor, preset }, { adjust });\n\n /**\n * The selection as `markup`: one annotation per page, over the page's\n * selected text; an insert's caret at the selection's end. `/IRT` ties are\n * page-local, so a selection across pages makes one self-contained Caret +\n * StrikeOut pair per page: the true glyph-cell anchor exists only on the\n * selection's end page, other pages anchor at their last segment's\n * trailing edge. The caller has checked the create authority.\n */\n const markupFromSelection = (\n markup: SelectionMarkup,\n snapshot: SelectionSnapshot,\n preset: string | undefined,\n adjust: Adjust,\n ): Commit[] => {\n const end = snapshot.end;\n if (markup.kind === 'insert') {\n return end\n ? [commitCaret(end.page, { glyphQuad: end.glyphQuad, advance: end.advance }, adjust)]\n : [];\n }\n const commits: Commit[] = [];\n for (const entry of snapshot.pages) {\n const last = entry.segments[entry.segments.length - 1];\n if (!last) continue;\n const quads = entry.segments.map((segment) => segment.quad);\n if (markup.kind === 'markup') {\n commits.push(commitMarkup(markup.subtype, entry.page, quads, preset, adjust));\n continue;\n }\n const anchor =\n end && pageRefsEqual(end.page, entry.page)\n ? { glyphQuad: end.glyphQuad, advance: end.advance }\n : { glyphQuad: last.quad, advance: last.advance };\n commits.push(commitReplaceText(entry.page, quads, anchor, preset, adjust));\n }\n return commits;\n };\n\n const api = {\n createMarkup: (subtype: KindName, page: PageRef, quads: Quad[], preset?: string) => {\n // Optimistic create — the same self-refusal `createPointer` has.\n if (!authority.canCreate()) return;\n commitMarkup(subtype, page, quads, preset);\n },\n createCaret: (page: PageRef, anchor: TextEndAnchor) => {\n if (!authority.canCreate()) return;\n commitCaret(page, anchor);\n },\n createReplaceText: (page: PageRef, quads: Quad[], anchor: TextEndAnchor, preset?: string) => {\n if (!authority.canCreate()) return;\n commitReplaceText(page, quads, anchor, preset);\n },\n /**\n * Turn the text selection into what the tool makes of it, then clear the\n * selection. Nothing, and `false`, for a tool that makes nothing of a\n * selection, without create authority, or without a selection.\n */\n applyToolToSelection: (toolId: string): boolean => {\n const tool = tools.get(toolId);\n const markup = tool && selectionMarkupOf(tool);\n if (!tool || !markup || !authority.canCreate()) return false;\n const selection = ctx.tryGet(SelectionPublicToken);\n if (!selection || !selection.hasSelection()) return false;\n const commits = markupFromSelection(\n markup,\n selection.getSnapshot(),\n tool.preset,\n afterCreate.shape(tool.id),\n );\n selection.clear();\n for (const commit of commits) afterCreate.done(tool.id, commit);\n return true;\n },\n previewMarkup: (subtype: KindName, quadsByPage: Record<number, Quad[]>, preset?: string) => {\n store.commit({ type: 'setMarkupPreview', subtype, quadsByPage, preset });\n },\n clearMarkupPreview: () => {\n store.commit({ type: 'clearMarkupPreview' });\n },\n createFromSelection: async (\n toolId: string,\n options: OperationOptions & { clear?: boolean } = {},\n ): Promise<{ annotations: readonly Annotation[] }> => {\n ctx.assertAllowed('annotations:create', 'annotation.createFromSelection');\n const tool = tools.get(toolId);\n const markup = tool && selectionMarkupOf(tool);\n if (!tool || !markup) {\n throw new PluginError(\n 'not-found',\n 'annotation',\n `no tool '${toolId}' that makes something of selected text`,\n );\n }\n const selection = ctx.tryGet(SelectionPublicToken);\n if (!selection || !selection.hasSelection()) return { annotations: [] };\n // Code never changes the annotation selection: what the core selects goes.\n const before = store.model();\n const keepSelection: Adjust = (result) => ({\n ...result,\n session: { ...result.session, selected: before.selected, editing: before.editing },\n });\n const commits = markupFromSelection(\n markup,\n selection.getSnapshot(),\n tool.preset,\n keepSelection,\n );\n if (options.clear !== false) selection.clear();\n const refs = await ctx.cancellable(\n options.signal,\n Promise.all(\n commits.filter((commit) => commit.effects.length).map((commit) => createdRefOf(commit)),\n ),\n );\n return {\n annotations: refs\n .map((ref) => annotations.get(ref))\n .filter((annotation): annotation is Annotation => annotation !== null),\n };\n },\n };\n\n return { api };\n}\n","import { annotContentsEditable, annotTransformable } from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n isDimension,\n isReadout,\n measurementReadout,\n serializeError,\n type AnnotationPatch,\n type PageMeasurementViewport,\n type PageRef,\n type PdfMeasure,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { RecalibrationReport } from '../host-contract';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Crud } from './crud';\n\n/**\n * The measurement seam: the per-page viewports (scale regions) the\n * measurement plugin supplies for dimension drafts, and recalibration of a\n * page's dimensions to a new scale.\n */\nexport function createMeasurement(\n ctx: Pick<AnnotationContext, 'cleanup'>,\n { store, records }: Pick<AnnotationServices, 'store' | 'records'>,\n crud: Pick<Crud, 'update'>,\n) {\n const pageViewports = new Map<\n number,\n {\n viewports: PageMeasurementViewport[] | undefined;\n fallback: PdfMeasure;\n }\n >();\n ctx.cleanup(() => {\n pageViewports.clear();\n });\n\n const api = {\n setPageViewports: (\n page: PageRef,\n viewports: PageMeasurementViewport[] | undefined,\n fallback: PdfMeasure,\n ) => {\n pageViewports.set(page.objectNumber, { viewports, fallback });\n },\n remeasurePage: async (page: PageRef, scale: PdfMeasure) => {\n const pageObjectNumber = page.objectNumber;\n // Recalibration needs every dimension on the page: retry a failed load,\n // and wait for any load or page reload still running.\n if (records.getStatus() !== 'ready') {\n await records.refresh().catch(() => {});\n }\n await records.settled();\n const report: RecalibrationReport = { page, scale, updated: [], skipped: [], failed: [] };\n if (records.getStatus() !== 'ready') {\n report.error = serializeError(new Error('the annotations of this document are not loaded'));\n return report;\n }\n // The confirmed dimensions of the page, each with how this session sees\n // it (one the user just deleted is not in the view, and is left alone).\n const model = store.model();\n const candidates = Object.values(records.get().byKey).flatMap(({ dto }) => {\n const record = model.byId[annotationKey(dto.ref)];\n return record && dto.page.objectNumber === pageObjectNumber && isDimension(dto)\n ? [{ dto, annotation: record }]\n : [];\n });\n for (const { dto, annotation } of candidates) {\n const ref = dto.ref;\n const reason =\n annotation.authority?.update === false\n ? 'no-authority'\n : !annotTransformable(annotation) || !annotContentsEditable(annotation)\n ? 'locked'\n : 'measure' in dto && dto.measure && dto.measure.subtype !== 'rectilinear'\n ? 'foreign-measure'\n : !isReadout(measurementReadout({ ...dto, measure: scale }))\n ? 'unavailable'\n : null;\n if (reason) {\n report.skipped.push({ ref, reason });\n continue;\n }\n try {\n await crud.update(ref, { subtype: dto.subtype, measure: scale } as AnnotationPatch);\n report.updated.push(ref);\n } catch (error) {\n report.failed.push({ ref, error: serializeError(error) });\n }\n }\n return report;\n },\n };\n\n return { viewportsOf: (pageObjectNumber: number) => pageViewports.get(pageObjectNumber), api };\n}\n\nexport type Measurement = ReturnType<typeof createMeasurement>;\n","/**\n * The op builders: how the core's effects become the engine's ops. Each is a\n * pure function of an effect and the model the message left (its new\n * records included; a deleted one is in the model before it); the store\n * stages a message's ops as one change (services/store.ts).\n *\n * The text builder lives with text editing, the link builder with links, and\n * the capture handler with creation drafts.\n */\nimport { refOf } from '@embedpdf/core-annotation';\n\nimport type { AnnotationServices } from '../services';\n\nexport function registerOpBuilders({ store }: Pick<AnnotationServices, 'store'>): void {\n // A drawn record: written from the draft its annotation was read from, under its number.\n store.onEffect('create', (effect, model) => {\n const ref = refOf(model.byId[effect.id]);\n if (ref?.kind !== 'objectNumber') return;\n return [\n {\n type: 'annotations.create',\n page: ref.page,\n data: effect.draft,\n objectNumber: ref.objectNumber,\n },\n ];\n });\n\n // What a record's change means to the engine, as the core worked it out.\n // (Its attached link children follow it: write/links.ts.)\n store.onEffect('patch', (effect, model) => {\n const ref = refOf(model.byId[effect.id]);\n return ref ? [{ type: 'annotations.update', ref, patch: effect.patch }] : undefined;\n });\n\n // The record is gone from the model the message left: its ref is the one it had.\n store.onEffect('delete', (effect, _model, before) => {\n const ref = refOf(before.byId[effect.id]);\n return ref ? [{ type: 'annotations.delete', ref }] : undefined;\n });\n}\n","import { kindOf, refOf, type ModelAnnotation } from '@embedpdf/core-annotation';\nimport { createHoverPump } from '@embedpdf/plugin-actions/contract';\nimport type { ActionsCapability, HoverTarget } from '@embedpdf/plugin-actions/contract';\n\nexport interface AnnotationHoverFeed {\n /** Report the pointer-driven hover target (the hoverAt diff's new id). */\n hover(id: string | null): void;\n}\n\n/**\n * The annotation plane's E/X trigger feed — a thin adapter from the one\n * pointer-driven hover seam (the `hoverAt` diff) onto the shared hover pump.\n *\n * Anti-cascade is structural and lives in the caller's seam placement:\n * reducer-side hover clears (session-hide, remove, reload) never pass\n * through `hoverAt`, so an effect-induced hover loss can never masquerade as\n * a cursor exit. This module only decides who is hoverable here:\n *\n * - A record the engine hasn't written yet has no /AA it could run there — skipped.\n * - Widgets and links belong to their own event planes (fill controls /\n * LinkLayer anchors own their pixels). When they are hit-testable on this\n * plane, an authoring tool owns them — firing hover actions while editing\n * would be wrong — so they are skipped unconditionally.\n * - Tree-less annotations are free: no target, no dispatch, and per-event\n * flags keep a lone /E or /X from dispatching its inert twin.\n */\nexport function createAnnotationHoverFeed(\n actions: ActionsCapability,\n annotOf: (id: string) => ModelAnnotation | null,\n): AnnotationHoverFeed {\n const pump = createHoverPump(actions.dispatch);\n\n const targetOf = (id: string | null): HoverTarget | null => {\n if (!id) return null;\n const record = annotOf(id);\n const ref = record ? refOf(record) : null;\n if (!record || !ref || record.unconfirmed) return null;\n const kind = kindOf(record.annotation).name;\n if (kind.startsWith('widget') || kind === 'link') return null;\n const enter = Boolean(record.annotation.actions?.cursorEnter?.root);\n const exit = Boolean(record.annotation.actions?.cursorExit?.root);\n if (!enter && !exit) return null;\n return { ref, page: record.annotation.page, events: { enter, exit } };\n };\n\n return {\n hover: (id) => pump.hover(targetOf(id)),\n };\n}\n","import {\n defaultsFor,\n type MeasurementAppearance,\n type KindName,\n type Point,\n} from '@embedpdf/core-annotation';\nimport type { PageRotation } from '@embedpdf/core-geometry';\nimport {\n isDimension,\n isReadout,\n measurementReadout,\n viewportForPoint,\n type LineLeader,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\nimport { ActionsToken as PublicActionsToken } from '@embedpdf/plugin-actions/contract';\n\nimport type { ChromeReads } from '../read/chrome';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Measurement } from './measurement';\nimport { createAnnotationHoverFeed } from '../tools/hover-feed';\n\ntype Phase = 'down' | 'move' | 'up';\n\n/**\n * Pointer intents: the gesture samples the interaction handlers forward\n * (edit, marquee, create, hover), each folded into the pure core with this\n * plugin's inputs filled in (page box, chrome geometry, engaged ids, view).\n */\nexport function createPointer(\n ctx: Pick<AnnotationContext, 'doc' | 'tryGet'>,\n {\n store,\n geometry,\n authority,\n tools,\n behaviors,\n afterCreate,\n }: Pick<\n AnnotationServices,\n 'store' | 'geometry' | 'authority' | 'tools' | 'behaviors' | 'afterCreate'\n >,\n chrome: Pick<ChromeReads, 'chromeGeomAt' | 'grabBoost' | 'hitAt'>,\n measurement: Pick<Measurement, 'viewportsOf'>,\n) {\n // The E/X trigger feed (actions plugin present): driven only from the\n // pointer-driven hoverAt diff below — see hover-feed.ts for the law.\n const actionsForHover = ctx.tryGet(PublicActionsToken);\n const hoverFeed = actionsForHover\n ? createAnnotationHoverFeed(actionsForHover, (id) => store.model().byId[id] ?? null)\n : null;\n\n const api = {\n editPointer: (\n phase: Phase,\n page: PageRef,\n point: Point,\n shift: boolean,\n scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n touch?: boolean,\n ) => {\n store.commit({\n type: 'editPointer',\n phase,\n in: {\n page,\n point,\n shift,\n pageBox: geometry.pageBoxOf(page.objectNumber),\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: chrome.chromeGeomAt(scale, chrome.grabBoost(touch)),\n // Screen-pixel settings (the alignment threshold) convert by it.\n ...(scale ? { scale } : {}),\n inert: behaviors.engagedIdsOn(page.objectNumber),\n // the view env (screen-anchored bodies hit/clamp at their footprint)\n ...(zoom != null ? { zoom } : {}),\n ...(rotation != null ? { displayRotation: rotation } : {}),\n },\n });\n },\n marqueePointer: (\n phase: Phase,\n page: PageRef,\n point: Point,\n shift: boolean,\n _scale?: number,\n rotation?: PageRotation,\n zoom?: number,\n ) => {\n store.commit({\n type: 'marqueePointer',\n phase,\n in: {\n page,\n point,\n shift,\n pageBox: geometry.pageBoxOf(page.objectNumber),\n inert: behaviors.engagedIdsOn(page.objectNumber),\n ...(zoom != null ? { zoom } : {}),\n ...(rotation != null ? { displayRotation: rotation } : {}),\n },\n });\n },\n createPointer: (\n tool: string,\n phase: Phase,\n page: PageRef,\n point: Point,\n finish = false,\n displayRotation?: PageRotation,\n ) => {\n const pageObjectNumber = page.objectNumber;\n // No create authority → creation gestures are inert: no ghost, no\n // draft, no doomed 403. The engine enforces; this keeps pixels honest.\n const resolvedTool = tools.get(tool);\n if (\n resolvedTool?.capture === true\n ? !ctx.doc?.security.allows('doc.annotate.modify')\n : !authority.canCreate()\n )\n 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 laidOut = geometry.sizeOf(pageObjectNumber) !== null;\n const cache = measurement.viewportsOf(pageObjectNumber);\n const draft = store.model().draft;\n const continuingMeasurement =\n (draft?.kind === 'create-distance' || draft?.kind === 'create-poly') &&\n draft.page.objectNumber === pageObjectNumber &&\n draft.preset === (resolvedTool?.preset ?? tool);\n // A tool's intent, caption and leader are among its defaults (the user's changes included).\n const own = resolvedTool ? defaultsFor(store.model(), resolvedTool.preset) : {};\n const intent = own.intent as string | undefined;\n const dimension = resolvedTool && isDimension({ subtype: resolvedTool.subtype, intent });\n if (\n dimension &&\n phase === 'down' &&\n !continuingMeasurement &&\n (!laidOut || !cache?.viewports)\n ) {\n return;\n }\n const viewport =\n laidOut && cache?.viewports ? viewportForPoint(cache.viewports, point) : undefined;\n const scale = viewport ? (viewport.measure ?? null) : cache?.fallback;\n const captionEnabled = (own.captionEnabled as boolean | null | undefined) ?? true;\n const measure: MeasurementAppearance | undefined =\n dimension && laidOut && cache\n ? intent === 'line-dimension'\n ? {\n intent,\n measure: scale ?? null,\n captionEnabled,\n captionPosition: (own.captionPosition as 'inline' | 'top' | undefined) ?? 'inline',\n captionOffset: null,\n leader: (own.leader as LineLeader | undefined) ?? null,\n contents: '',\n }\n : {\n intent: intent as 'polyline-dimension' | 'polygon-dimension',\n measure: scale ?? null,\n captionEnabled,\n contents: '',\n }\n : undefined;\n // Resolve the scale at the first point. Subsequent points retain the\n // draft's snapshot, even when the pointer crosses another viewport.\n if (\n measure &&\n phase === 'down' &&\n !continuingMeasurement &&\n !isReadout(\n measurementReadout({\n subtype: resolvedTool!.subtype,\n intent: measure.intent,\n measure: measure.measure,\n linePoints: { start: { x: 0, y: 0 }, end: { x: 1, y: 0 } },\n vertices: [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 1, y: 1 },\n ],\n }),\n )\n )\n return;\n const committed = store.commit(\n {\n type: 'createPointer',\n measure,\n capture: resolvedTool?.capture === true ? tool : undefined,\n phase,\n subtype: resolvedTool?.subtype ?? (tool as KindName),\n preset: resolvedTool?.preset ?? tool,\n intent: intent === 'ink-highlight' ? intent : undefined,\n clickCreate: resolvedTool?.clickCreate,\n flags: resolvedTool?.flags,\n deferInkCommit: (resolvedTool?.ink?.groupStrokesMs ?? 0) > 0,\n straightenInk: resolvedTool?.ink?.straighten,\n in: {\n page,\n point,\n shift: false,\n finish,\n pageBox: geometry.pageBoxOf(pageObjectNumber),\n displayRotation,\n upright: resolvedTool?.upright,\n },\n },\n { adjust: afterCreate.shape(resolvedTool?.id) },\n );\n afterCreate.done(resolvedTool?.id, committed);\n },\n hoverAt: (\n at: { page: PageRef; point: Point; scale?: number; rotation?: number; zoom?: number } | null,\n ) => {\n const model = store.model();\n let id: string | null = null;\n if (at) {\n const target = chrome.hitAt(at.page, at.point, {\n scale: at.scale,\n rotation: at.rotation,\n zoom: at.zoom,\n });\n if (target.kind === 'annot') id = target.id;\n }\n // Diff here so the reducer sees enter/leave transitions only. The E/X\n // feed hangs off this seam alone: reducer-side hover clears\n // (session-hide, remove, reload) bypass it, so effect-induced hover\n // loss never fires a cursor exit (the anti-cascade law).\n if (model.hovered !== id) {\n hoverFeed?.hover(id);\n store.commit({ type: 'hover', id });\n }\n },\n };\n\n return { api };\n}\n","import { scriptColorToRgb } from '@embedpdf/core-acrojs';\nimport type { ScriptAnnotEffect, ScriptColorArray } from '@embedpdf/core-acrojs';\nimport { refOf } from '@embedpdf/core-annotation';\nimport {\n colorOf,\n pageBoxOf,\n toPageRef,\n type AnnotationPatch,\n type PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport type { AnnotCommitEntry, AnnotCommitResult } from '@embedpdf/plugin-actions/contract/host';\n\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport { appliedOrThrow } from './outcomes';\n\n/** Script patch → the engine's per-kind patch vocabulary. Colors cross the\n * Acrobat-array → engine {r,g,b}/255 boundary here; a script's rect, in the\n * file's numbers as Acrobat's JavaScript keeps it, is the annotation's\n * `rect` in page space for every kind, which puts its shape there as in\n * Acrobat (`shapeForRect`); everything else maps one-to-one (the VM's\n * validity matrix already scoped keys per kind). `crop` is the page's\n * `pdfCropBox`. */\nconst engineScriptPatch = (\n subtype: string,\n patch: ScriptAnnotEffect['patch'],\n crop: PdfRect | null,\n): AnnotationPatch | Error => {\n const out: Record<string, unknown> = { subtype };\n const toEngineColor = (color: ScriptColorArray) => {\n const rgb = scriptColorToRgb(color);\n return rgb ? colorOf(rgb.r * 255, rgb.g * 255, rgb.b * 255) : null;\n };\n if (patch.strokeColor) {\n const color = toEngineColor(patch.strokeColor);\n if (!color) return new Error('transparent stroke colours are not supported');\n out.color = color;\n }\n if (patch.fillColor) out.interiorColor = toEngineColor(patch.fillColor);\n if (patch.opacity !== undefined) out.opacity = patch.opacity;\n if (patch.width !== undefined) out.strokeWidth = patch.width;\n if (patch.borderStyle) out.borderStyle = patch.borderStyle === 'D' ? 'dashed' : 'solid';\n if (patch.dash) out.dashArray = patch.dash;\n if (patch.rect) {\n if (!crop) return new Error('annotation page not loaded');\n // Acrobat's [x1, y1, x2, y2] names two corners, in either order.\n const [x1, y1, x2, y2] = patch.rect;\n out.rect = pageBoxOf(\n {\n left: Math.min(x1, x2),\n bottom: Math.min(y1, y2),\n right: Math.max(x1, x2),\n top: Math.max(y1, y2),\n },\n crop,\n );\n }\n if (patch.contents !== undefined) out.contents = patch.contents;\n // Each `/F` flag is its own engine field.\n if (patch.flags) Object.assign(out, patch.flags);\n // Assembled key by key: the script VM already limited the keys to the ones\n // this kind accepts, and the engine validates the patch against the subtype.\n return out as unknown as AnnotationPatch;\n};\n\n/**\n * The actions plugin's commit sink: document JavaScript patches annotations\n * through this plugin, which owns them. Each confirmed write reaches the model\n * through the records mirror.\n */\nexport function createScriptEffects(\n ctx: Pick<AnnotationContext, 'doc'>,\n { store, geometry }: Pick<AnnotationServices, 'store' | 'geometry'>,\n) {\n const api = {\n commitScriptEffects: async (entries: AnnotCommitEntry[]): Promise<AnnotCommitResult> => {\n const doc = ctx.doc;\n const results: AnnotCommitResult['results'] = [];\n let failed = false;\n for (const entry of entries) {\n if (failed) {\n results.push({ annotObjectNumber: entry.annotObjectNumber, status: 'skipped' });\n continue;\n }\n const loaded = store.model().byId[`obj:${entry.annotObjectNumber}`];\n const pageObjectNumber = loaded?.annotation.page.objectNumber ?? entry.page?.objectNumber;\n let ref = refOf(loaded);\n let subtype: string | undefined = loaded?.annotation.subtype;\n if ((!ref || !subtype) && pageObjectNumber !== undefined) {\n // Read the page from the engine when the model does not have the annotation.\n try {\n const { annotations } = await doc.page(toPageRef(pageObjectNumber)).annotations.list();\n const dto = annotations.find(\n (candidate) =>\n candidate.ref.kind === 'objectNumber' &&\n candidate.ref.objectNumber === entry.annotObjectNumber,\n );\n if (dto) {\n ref = dto.ref;\n subtype = dto.subtype;\n }\n } catch {\n /* resolved as a failure below */\n }\n }\n if (pageObjectNumber === undefined || !ref || !subtype) {\n results.push({\n annotObjectNumber: entry.annotObjectNumber,\n status: 'failed',\n error: 'annotation not resolved (page not loaded)',\n });\n continue;\n }\n const patch = engineScriptPatch(subtype, entry.patch, geometry.cropOf(pageObjectNumber));\n if (patch instanceof Error) {\n results.push({\n annotObjectNumber: entry.annotObjectNumber,\n status: 'failed',\n error: patch.message,\n });\n continue;\n }\n try {\n await appliedOrThrow(store.apply([{ type: 'update', ref, patch }]));\n results.push({ annotObjectNumber: entry.annotObjectNumber, status: 'applied' });\n } catch (error) {\n // Stop on the first failure: a refused entry (for example a\n // permission refusal) fails, and every later entry is skipped.\n failed = true;\n results.push({\n annotObjectNumber: entry.annotObjectNumber,\n status: 'failed',\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return { results };\n },\n };\n\n return { api };\n}\n","import type { OperationOptions } from '@embedpdf/core';\nimport {\n applyStyleToRange,\n expandGroups,\n type FieldValues,\n groupKeyOf,\n groupOf,\n type Id,\n isSelectable,\n type ModelAnnotation,\n type Rect,\n refOf,\n richDocOf,\n selectionInBox,\n} from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type Annotation,\n type AnnotationPatch,\n type AnnotationRef,\n type PageRef,\n type PdfLinkTarget,\n} from '@embedpdf/engine-core/runtime';\n\nimport type { AnnotationContext } from '../services';\nimport type { AnnotationReads } from '../read/annotations';\nimport type { ChromeReads } from '../read/chrome';\nimport type { PropertyReads } from '../read/properties';\nimport { runDeltaForFields, type TextFormat } from '../rich-text';\nimport type { AnnotationServices } from '../services';\nimport { appliedOrThrow, batchResultOf, throwIfFailed } from './outcomes';\nimport type { TextEditing } from './text-editing';\nimport { refsOfIn, type Commit, type StoreChange } from '../services/store';\n\n/**\n * The selection: what is selected, and the verbs that change its fields,\n * link, delete, rotate, group and ungroup it as one, every member through the\n * same `update → patch effect` path a gesture takes. Each verb is one change.\n */\nexport function createSelectionWrites(\n ctx: Pick<AnnotationContext, 'pageOf' | 'getPage' | 'cancellable'>,\n {\n store,\n authority,\n fonts,\n behaviors,\n lending,\n }: Pick<AnnotationServices, 'store' | 'authority' | 'fonts' | 'behaviors' | 'lending'>,\n annotations: Pick<AnnotationReads, 'selectedRecords' | 'listSelected'>,\n properties: Pick<PropertyReads, 'activeTextRange' | 'selectionPropertiesOf'>,\n chrome: Pick<ChromeReads, 'selectionAnchor' | 'rotationAnchor'>,\n text: Pick<TextEditing, 'type'>,\n) {\n const selectedRefs = () => refsOfIn(store.model(), store.model().selected);\n\n /** Commit a selection message; resolves with its outcome over the refs that were selected. */\n const commitOverSelection = async (commit: () => Commit[], signal?: AbortSignal) => {\n const refs = selectedRefs();\n const outcomes = await ctx.cancellable(\n signal,\n Promise.all(commit().map((committed) => committed.written)),\n );\n return batchResultOf(refs, { failed: outcomes.flatMap((outcome) => outcome.failed) });\n };\n\n /**\n * Change the selection's fields, a patch per member (a function patches\n * each relative to itself), through the pure core like every gesture: each\n * member takes the fields its kind has, and the change shows at once, as\n * one change. While the text editor holds a range, the font, size, colour\n * and formats restyle the runs it covers (a delta over the body, through\n * the pure run algebra) as part of the typing, and the rest goes to the\n * annotation: its change sends the typing first, so the body it writes is\n * the latest.\n */\n const restyle = (patch: FieldValues | ((annotation: Annotation) => FieldValues)): Commit[] => {\n const model = store.model();\n const range = properties.activeTextRange(model);\n const commits: Commit[] = [];\n const patches: Record<Id, FieldValues> = {};\n for (const id of model.selected) {\n const record = model.byId[id];\n if (!record) continue;\n const own = typeof patch === 'function' ? patch(record.annotation) : patch;\n if (range?.id !== id) {\n patches[id] = own;\n continue;\n }\n const { delta, rest } = runDeltaForFields(own, fonts);\n if (Object.keys(delta).length) {\n const next = applyStyleToRange(\n { paragraphs: richDocOf(record.annotation, fonts).paragraphs },\n range,\n delta,\n );\n commits.push(text.type(id, { type: 'setRichText', id, doc: next }));\n }\n patches[id] = rest;\n }\n if (Object.values(patches).some((fields) => Object.keys(fields).length)) {\n commits.push(store.commit({ type: 'setFields', patches }));\n }\n return commits;\n };\n\n /** Select by refs, group-aware; `add` keeps the current selection. */\n const select = (refs: readonly AnnotationRef[], add: boolean): void => {\n store.commit({ type: 'select', ids: refs.map((ref) => annotationKey(ref)), add });\n };\n\n /**\n * Bold, italic or underline on or off: the words selected while typing, or\n * the whole of each selected text box once the text being typed has landed.\n */\n const toggleFormat = async (format: TextFormat, options: OperationOptions = {}) => {\n const on = properties.selectionPropertiesOf().values[format] !== true;\n const range = properties.activeTextRange(store.model());\n const commits = range\n ? restyle({ [format]: on })\n : [store.commit({ type: 'setTextFormat', format, on })];\n const outcomes = await ctx.cancellable(\n options.signal,\n Promise.all(commits.map((commit) => commit.written)),\n );\n outcomes.forEach(throwIfFailed);\n };\n\n /** The `selection` noun (its reads come from the property and chrome reads). */\n const selection = {\n // `set([])` selects nothing, as its name says: the reducer leaves an empty `select` alone,\n // so an `add` of nothing stays a no-op.\n set: (refs: readonly AnnotationRef[]) =>\n refs.length ? select(refs, false) : void store.commit({ type: 'deselect' }),\n add: (refs: readonly AnnotationRef[]) => select(refs, true),\n selectAll: (page?: PageRef | number) => {\n // A page that isn't in the document has nothing to select.\n const only = page === undefined ? null : ctx.getPage(page);\n if (page !== undefined && !only) {\n store.commit({ type: 'deselect' });\n return;\n }\n const model = store.model();\n const ids = model.order.filter((id) => {\n const record = model.byId[id];\n return (\n !!record &&\n (!only || record.annotation.page.objectNumber === only.ref.objectNumber) &&\n isSelectable(model, id)\n );\n });\n store.commit({ type: 'select', ids });\n },\n selectInRect: (page: PageRef | number, rect: Rect) => {\n const { ref } = ctx.pageOf(page);\n const engaged = behaviors.engagedIdsOn(ref.objectNumber);\n store.commit({ type: 'select', ids: selectionInBox(store.model(), ref, rect, engaged) });\n },\n clear: () => {\n store.commit({ type: 'deselect' });\n },\n list: () => annotations.listSelected(),\n update: (\n changes: AnnotationPatch | ((annotation: Annotation) => AnnotationPatch),\n options: OperationOptions = {},\n ) => commitOverSelection(() => restyle(changes as FieldValues), options.signal),\n updateLink: (target: PdfLinkTarget | null, options: OperationOptions = {}) =>\n commitOverSelection(() => [store.commit({ type: 'setLink', target })], options.signal),\n getProperties: () => properties.selectionPropertiesOf(),\n delete: (options: OperationOptions = {}) =>\n commitOverSelection(() => [store.commit({ type: 'delete' })], options.signal),\n rotateBy: async (degrees: 90 | -90, options: OperationOptions = {}) => {\n const commit = store.commit({ type: 'rotateSelection', degrees });\n throwIfFailed(await ctx.cancellable(options.signal, commit.written));\n },\n resetRotation: async (options: OperationOptions = {}) => {\n const commit = store.commit({ type: 'resetRotation' });\n throwIfFailed(await ctx.cancellable(options.signal, commit.written));\n },\n getAnchor: () => chrome.selectionAnchor(),\n getRotationAnchor: () => chrome.rotationAnchor(),\n // Grouping writes a relationship (`/IRT` + `/RT /Group`) onto every\n // subordinate; ungrouping clears it, so each member becomes top-level\n // again. Either is one change; geometry and style are left alone, so no\n // appearance is baked again.\n group: async (options: OperationOptions = {}): Promise<void> => {\n const model = store.model();\n const members = annotations.selectedRecords();\n // Lent records (form widgets) belong to their owner's structure, not a group.\n if (members.length < 2 || members.some((record) => lending.owns(record.id))) return;\n const pageObjectNumber = members[0].annotation.page.objectNumber;\n if (members.some((record) => record.annotation.page.objectNumber !== pageObjectNumber))\n return; // groups are page-local\n const ordered = [...members].sort(\n (left, right) => model.order.indexOf(left.id) - model.order.indexOf(right.id),\n );\n const [primary, ...rest] = ordered;\n const primaryRef = refOf(primary);\n if (!primaryRef) return;\n await writeRelationships(rest, { to: primaryRef, type: 'group' }, options);\n },\n ungroup: async (options: OperationOptions = {}): Promise<void> => {\n const model = store.model();\n const subs = expandGroups(model, model.selected)\n .map((id) => model.byId[id])\n .filter((record): record is ModelAnnotation => !!record && !!groupOf(record.annotation));\n await writeRelationships(subs, null, options);\n },\n canGroup: (): boolean => {\n const model = store.model();\n const members = annotations.selectedRecords();\n if (members.length < 2 || members.some((record) => lending.owns(record.id))) return false;\n if (\n members.some(\n (record) =>\n record.annotation.page.objectNumber !== members[0].annotation.page.objectNumber,\n )\n )\n return false;\n // Grouping writes a relationship onto every member — each must\n // pass the per-record update check.\n if (\n !members.every((record) => {\n const ref = refOf(record);\n return ref != null && authority.allowsMutation('update', ref);\n })\n )\n return false;\n // Already exactly one complete group → nothing to do.\n const keys = new Set(model.selected.map((id) => groupKeyOf(model, id)));\n if (keys.size === 1 && !keys.has(null)) return false;\n return true;\n },\n canUngroup: (): boolean => {\n const model = store.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(model, model.selected)\n .map((id) => model.byId[id])\n .filter((record): record is ModelAnnotation => !!record && !!groupOf(record.annotation));\n return (\n subs.length > 0 &&\n subs.every((record) => {\n const ref = refOf(record);\n return ref != null && authority.allowsMutation('update', ref);\n })\n );\n },\n };\n\n /** One relationship (`/IRT` + `/RT`) written onto every record, as one change. */\n const writeRelationships = async (\n targets: readonly ModelAnnotation[],\n reply: { to: AnnotationRef; type: 'group' } | null,\n options: OperationOptions,\n ): Promise<void> => {\n const changes = targets.flatMap((record): StoreChange[] => {\n const ref = refOf(record);\n if (!ref) return [];\n const patch = { subtype: record.annotation.subtype, reply } as AnnotationPatch;\n return [{ type: 'update', ref, patch }];\n });\n if (changes.length) {\n await ctx.cancellable(options.signal, appliedOrThrow(store.apply(changes)));\n }\n };\n\n return { selection, toggleFormat };\n}\n","import { PluginError, type OperationOptions } from '@embedpdf/core';\nimport {\n fitStampBox,\n type Id,\n type ModelAnnotation,\n type Rect,\n type Point,\n} from '@embedpdf/core-annotation';\nimport {\n resolveBinarySource,\n sniffBinaryMetadata,\n toPageRef,\n type Annotation,\n type BinarySource,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\n\nimport {\n type ArmedStampPreview,\n type StampInput,\n type StampPlacement,\n type StampPreviewProvider,\n} from '../contract';\nimport type { ArmedStampInfo } from '../contract';\nimport { previewBucket } from '../host-contract';\nimport { setGhostAt } from '../model';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Applied } from '../services/store';\nimport { appliedAnnotationOf } from './outcomes';\nimport { ARMED_STAMP_TOOL_ID } from '../tools/definitions';\n\n/** Bytes that aren't a picture a stamp can show. */\nconst notAPicture = (): PluginError =>\n new PluginError(\n 'invalid-input',\n 'annotation',\n 'a stamp must be PNG, JPEG, or one-page PDF bytes',\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. `preview` is the\n * browser-paintable render for the hover ghost, and the look of each stamp\n * it places until the engine's picture of it exists.\n */\ninterface ArmedStamp {\n source: BinarySource;\n /** The desired placement size (PDF points, pre page-clamp). */\n width: number;\n height: number;\n /** Resolution-aware ghost source, one render per bucket for this arm; null = no ghost. */\n preview: StampPreviewProvider | null;\n name?: string;\n subject?: string;\n}\n\n/** The bytes of a stamp source; its declared type and name don't matter, the engine sniffs. */\nconst bytesOf = (source: BinarySource): Uint8Array | Blob =>\n source instanceof Uint8Array || !('data' in source) ? source : source.data;\n\n/** Fixed bytes as a provider: the same image at every size. */\nconst fixedPreview = (bytes: Uint8Array, mimeType?: string): StampPreviewProvider => {\n const preview: ArmedStampPreview = { bytes, ...(mimeType ? { mimeType } : {}) };\n return async () => preview;\n};\n\n/**\n * `provider`, asked once per size bucket (`previewBucket`): a zoom asks for\n * no new render inside a bucket. A render that fails is logged, and is none.\n */\nconst cachedPreview = (provider: StampPreviewProvider): StampPreviewProvider => {\n const renders = new Map<number, Promise<ArmedStampPreview | null>>();\n return (devicePixelWidth) => {\n const bucket = previewBucket(devicePixelWidth);\n let render = renders.get(bucket);\n if (!render) {\n render = provider(bucket).catch((error) => {\n console.error('[annotation] stamp preview failed:', error);\n return null;\n });\n renders.set(bucket, render);\n }\n return render;\n };\n};\n\n/**\n * What a stamp source looks like on this device, before the engine draws\n * it: an explicit `preview` (the only way for PDF sources: browsers can't\n * paint those), else a raster source's own bytes. `null`: no look.\n */\nasync function previewOf(\n input: Pick<StampInput, 'preview'>,\n bytes: ArrayBuffer,\n mimeType: string,\n): Promise<StampPreviewProvider | null> {\n if (typeof input.preview === 'function') return cachedPreview(input.preview);\n if (input.preview) {\n const resolved = await resolveBinarySource(input.preview);\n return fixedPreview(new Uint8Array(resolved.bytes), resolved.mimeType);\n }\n return mimeType === 'application/pdf' ? null : fixedPreview(new Uint8Array(bytes), mimeType);\n}\n\n/**\n * The desired stamp size (PDF points) from sniffed bytes: the image's\n * Intrinsic pixel dimensions taken 1:1 as points (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 */\nconst 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/**\n * Stamps: arming a payload for the next click, and the one engine write\n * both the armed and the click-to-place paths funnel through.\n */\nexport function createStamps(\n ctx: Pick<\n AnnotationContext,\n 'doc' | 'state' | 'notify' | 'tryGet' | 'pageOf' | 'assertAllowed' | 'cancellable'\n >,\n {\n store,\n geometry,\n tools,\n filePicker,\n afterCreate,\n }: Pick<AnnotationServices, 'store' | 'geometry' | 'tools' | 'filePicker' | 'afterCreate'>,\n) {\n let armed: ArmedStamp | null = null;\n /**\n * The look of each stamp this session placed whose create the engine\n * hasn't answered: the preview it was placed with. The engine's picture\n * replaces it (read/render.ts).\n */\n const looks = new Map<Id, StampPreviewProvider>();\n\n /** What a stamp looks like before the engine's picture of it exists; `null` once it does. */\n const lookOf = (record: ModelAnnotation): StampPreviewProvider | null => {\n if (record.unconfirmed) return looks.get(record.id) ?? null;\n looks.delete(record.id);\n return null;\n };\n /** The public face of the armed payload: a new object on every arm, null when disarmed. */\n let armedInfo: ArmedStampInfo | null = null;\n /** A new or dropped payload invalidates the ghost drawn for the old one, and wakes readers. */\n const armChanged = (): void => {\n ctx.state.update(setGhostAt, null);\n ctx.notify();\n };\n\n const armStamp = async (input: StampInput, options: OperationOptions = {}): 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 // the engine normalizes it again from scratch.\n const resolved = await ctx.cancellable(options.signal, resolveBinarySource(input.source));\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) throw notAPicture();\n const preview = await previewOf(input, resolved.bytes, meta.mimeType);\n armed = {\n source: input.source,\n ...desiredStampSize(meta, input.targetWidth, input.intrinsicSize),\n preview,\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.subject !== undefined ? { subject: input.subject } : {}),\n };\n armedInfo = {\n width: armed.width,\n height: armed.height,\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.subject !== undefined ? { subject: input.subject } : {}),\n };\n armChanged();\n ctx.tryGet(InteractionToken)?.activateTool(ARMED_STAMP_TOOL_ID);\n };\n\n const disarmStamp = (): void => {\n if (!armed) return;\n armed = null;\n armedInfo = null;\n armChanged();\n };\n\n /** Place a stamp of `desired` PDF-point size centred on a page 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 (the 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 * becomes the box's `rotation` — the engine bakes the tilted\n * /AP exactly as an interactively rotated stamp round-trips, and the fit uses\n * the rotated footprint. Shown at once, unless the document is out of\n * object numbers for a moment. Returns null when the page/document isn't ready. */\n const createStampAt = (\n pageObjectNumber: number,\n point: Point,\n source: BinarySource,\n desired: { width: number; height: number },\n look: StampPreviewProvider | null,\n rotCW = 0,\n identity: { name?: string; subject?: string } = {},\n select = false,\n ): Promise<Applied> | null => {\n const doc = ctx.doc;\n const page = geometry.sizeOf(pageObjectNumber);\n if (!doc || !page) return null;\n const box: Rect = fitStampBox(point, desired, page, rotCW);\n const placed = store.applyWhenNumbered(\n [\n {\n type: 'create',\n page: toPageRef(pageObjectNumber),\n draft: {\n subtype: 'stamp',\n // Its box before any turn, and the turn (`null` upright, so none is kept).\n box,\n rotation: rotCW || null,\n fit: 'contain',\n ...(identity.name !== undefined ? { name: identity.name } : {}),\n ...(identity.subject !== undefined ? { subject: identity.subject } : {}),\n },\n resources: { appearance: bytesOf(source) },\n },\n ],\n { select },\n );\n // It shows its drawing at once: the preview it was placed with.\n if (look) {\n void placed.then(({ ids: [id] }) => {\n if (id === undefined) return;\n looks.set(id, look);\n ctx.notify();\n });\n }\n return placed;\n };\n\n /**\n * The click path's fire-and-forget wrapper: the tool's `afterCreate` says\n * whether the stamp is selected; a rejected placement is logged, never\n * thrown into the gesture.\n */\n const stageStampAt = (\n pageObjectNumber: number,\n point: Point,\n source: BinarySource,\n desired: { width: number; height: number },\n look: StampPreviewProvider | null,\n rotCW = 0,\n identity: { name?: string; subject?: string } = {},\n ): boolean => {\n const placed = createStampAt(pageObjectNumber, point, source, desired, look, rotCW, identity);\n if (!placed) return false;\n const toolId = tools.activeTool()?.id;\n placed\n .then((applied) => {\n afterCreate.placed(toolId, applied.ids as Id[]);\n return appliedAnnotationOf(applied);\n })\n .catch((error) => console.error('[annotation] stamp placement failed:', error));\n return true;\n };\n\n /** Placement from code: the same law as a click, awaited; selected only when asked. */\n const placeStamp = async (\n input: StampInput,\n placement: StampPlacement,\n options: OperationOptions = {},\n ): Promise<{ annotation: Annotation }> => {\n ctx.assertAllowed('annotations:create', 'annotation.stamps.place');\n const { ref: page } = ctx.pageOf(placement.page);\n const resolved = await ctx.cancellable(options.signal, resolveBinarySource(input.source));\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) throw notAPicture();\n const look = await ctx.cancellable(\n options.signal,\n previewOf(input, resolved.bytes, meta.mimeType),\n );\n const placed = createStampAt(\n page.objectNumber,\n placement.center,\n input.source,\n desiredStampSize(meta, placement.targetWidth ?? input.targetWidth, input.intrinsicSize),\n look,\n placement.rotation ?? 0,\n {\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.subject !== undefined ? { subject: input.subject } : {}),\n },\n placement.select ?? false,\n );\n if (!placed) {\n throw new PluginError(\n 'not-ready',\n 'annotation',\n `page ${page.objectNumber} isn't laid out yet`,\n );\n }\n const annotation = await ctx.cancellable(\n options.signal,\n placed.then((applied) => appliedAnnotationOf(applied)),\n );\n if (!annotation) {\n throw new PluginError('operation-failed', 'annotation', 'the stamp could not be placed');\n }\n return { annotation };\n };\n\n const placeArmedStamp = (\n pageObjectNumber: number,\n point: Point,\n displayRotation?: number,\n ): boolean => {\n const payload = armed;\n if (!payload) return false;\n return stageStampAt(\n pageObjectNumber,\n point,\n payload.source,\n { width: payload.width, height: payload.height },\n payload.preview,\n tools.uprightRotFor(displayRotation),\n {\n ...(payload.name !== undefined ? { name: payload.name } : {}),\n ...(payload.subject !== undefined ? { subject: payload.subject } : {}),\n },\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 pageObjectNumber: number,\n point: Point,\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]', notAPicture().message);\n return;\n }\n const look = await previewOf({}, resolved.bytes, meta.mimeType);\n stageStampAt(pageObjectNumber, point, source, desiredStampSize(meta, targetWidth), look, 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 = (\n pageObjectNumber: number,\n point: Point,\n displayRotation?: number,\n ): boolean => {\n const tool = tools.activeTool();\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 = tools.uprightRotFor(tool.upright ? displayRotation : undefined);\n if (spec.kind === 'bytes') {\n void placeStampSource(pageObjectNumber, point, spec.source, rotCW);\n return true;\n }\n // kind === 'prompt' — needs the environment: the one file-picker port.\n return filePicker.promptAt(\n tool,\n pageObjectNumber,\n point,\n (picked) =>\n void placeStampSource(\n pageObjectNumber,\n point,\n picked.data instanceof ArrayBuffer ? new Uint8Array(picked.data) : picked.data,\n rotCW,\n ),\n );\n };\n\n /** The `stamps` noun. */\n const stamps = {\n arm: armStamp,\n disarm: disarmStamp,\n isArmed: () => armed != null,\n place: placeStamp,\n };\n\n const api = {\n placeArmedStamp: (page: PageRef, point: Point, displayRotation?: number) =>\n placeArmedStamp(page.objectNumber, point, displayRotation),\n requestStampAt: (page: PageRef, point: Point, displayRotation?: number) =>\n requestStampAt(page.objectNumber, point, displayRotation),\n getArmedStamp: () => armedInfo,\n renderArmedStampPreview: (devicePixelWidth?: number) =>\n armed?.preview?.(devicePixelWidth ?? 0) ?? Promise.resolve(null),\n };\n\n return { armed: () => armed, lookOf, placeArmedStamp, requestStampAt, stamps, api };\n}\n\nexport type Stamps = ReturnType<typeof createStamps>;\n","/**\n * Free-text editing. Every keystroke is an ordinary commit of the core's\n * `setText` / `setRichText`, into one change that is still being made (a\n * hold): the view shows the text at once, and the change keeps its place in\n * line holding the latest text. It is sent after a pause in typing, when\n * editing ends, when anything else is staged, and before a download; what is\n * typed after that goes into a new one.\n */\nimport { refOf, type Id, type Message, type Point, richDocOf } from '@embedpdf/core-annotation';\nimport {\n annotationKey,\n type AnnotationRef,\n type PageRef,\n type RichTextParagraph,\n} from '@embedpdf/engine-core/runtime';\n\nimport { setTextSelection } from '../model';\nimport type { ChromeReads } from '../read/chrome';\nimport { cssFontFamilyForFace, textCommitPatch, type TextSelection } from '../rich-text';\nimport type { AnnotationContext, AnnotationServices } from '../services';\nimport type { Commit, StoreHold, Written } from '../services/store';\n\nconst TEXT_WRITE_DELAY_MS = 250;\n\nexport function createTextEditing(\n ctx: Pick<AnnotationContext, 'state' | 'clock' | 'cancellable'>,\n { store, fonts }: Pick<AnnotationServices, 'store' | 'fonts'>,\n chrome: Pick<ChromeReads, 'textBoxAt'>,\n) {\n /** What is being typed: the record, the change it goes into, how it settles, and the pause before it is sent. */\n let typing: {\n readonly id: Id;\n readonly hold: StoreHold;\n written: Promise<Written> | null;\n cancelPause: () => void;\n } | null = null;\n\n /** Send what was typed now. Resolves once the engine answered it; never rejects. */\n const sendTyping = async (): Promise<void> => {\n const sent = typing;\n if (!sent) return;\n typing = null;\n sent.cancelPause();\n sent.hold.send();\n await sent.written;\n };\n\n /**\n * One edit of the record's text (a keystroke, or a format on the words\n * selected while typing) into its typing, sent once typing pauses.\n */\n const type = (id: Id, message: Message): Commit => {\n if (typing && (typing.id !== id || !typing.hold.open)) void sendTyping();\n typing ??= {\n id,\n // Every pause of typing into one text box is one step of the history.\n hold: store.hold({ key: 'annotation.text' }, { merge: `annotation.text:${id}` }),\n written: null,\n cancelPause: () => {},\n };\n const current = typing;\n const commit = store.commit(message, { into: current.hold });\n current.written = commit.written;\n current.cancelPause();\n current.cancelPause = ctx.clock.after(TEXT_WRITE_DELAY_MS, () => {\n if (typing === current) void sendTyping();\n });\n return commit;\n };\n\n // A record's text, as the engine writes it: its plain and rich text.\n store.onEffect('text', (effect, model) => {\n const record = model.byId[effect.id];\n const ref = refOf(record);\n if (!record || !ref) return;\n const patch = textCommitPatch(record, richDocOf(record.annotation, fonts).paragraphs, fonts);\n return [{ type: 'annotations.update', ref, patch: { subtype: 'free-text', ...patch } }];\n });\n\n /** The `text` noun (its `getEditing` and `toggleFormat` come from the reads and the selection). */\n const text = {\n begin: (ref: AnnotationRef) => {\n store.commit({ type: 'beginTextEdit', id: annotationKey(ref) });\n },\n end: async (options: { signal?: AbortSignal } = {}) => {\n const sent = sendTyping();\n if (ctx.state.get().textSelection) {\n ctx.state.update(setTextSelection, null);\n }\n store.commit({ type: 'endTextEdit' });\n await ctx.cancellable(options.signal, sent);\n },\n };\n\n const api = {\n beginTextEditAt: (\n page: PageRef,\n point: Point,\n scale?: number,\n rotation?: number,\n zoom?: number,\n ) => {\n const id = chrome.textBoxAt(page, point, { scale, rotation, zoom });\n if (id != null) {\n store.commit({ type: 'beginTextEdit', id });\n // A box whose text may not change (`lockedContents`, the `editable`\n // setting) stays out of the editor.\n if (store.model().editing === id) 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 getEditingId: () => store.model().editing,\n draftContents: (ref: AnnotationRef, text: string) => {\n const id = annotationKey(ref);\n type(id, { type: 'setText', id, text });\n },\n draftRichText: (ref: AnnotationRef, doc: { paragraphs: RichTextParagraph[] }) => {\n const id = annotationKey(ref);\n type(id, { type: 'setRichText', id, doc: { paragraphs: doc.paragraphs } });\n },\n setTextSelection: (ref: AnnotationRef, range: { start: number; end: number } | null) => {\n const id = annotationKey(ref);\n const previous = ctx.state.get().textSelection;\n const next: TextSelection | null = range ? { id, start: range.start, end: range.end } : null;\n if (\n (previous === null) === (next === null) &&\n (!previous ||\n !next ||\n (previous.id === next.id && previous.start === next.start && previous.end === next.end))\n ) {\n return;\n }\n ctx.state.update(setTextSelection, next);\n },\n getCssFontFamily: (family: string) => cssFontFamilyForFace(family, fonts),\n };\n\n return { type, sendTyping, text, api };\n}\n\nexport type TextEditing = ReturnType<typeof createTextEditing>;\n","/**\n * The annotation controller: the composition root. It builds the plugin's\n * services once, wires each area with the services it declares, and\n * assembles the host capability from the areas' API slices and nouns. No\n * behavior lives here: every verb and read has a home in `read/`, `write/`,\n * `sync/`, `comments/` or `tools/`. How the pieces fit is in README.md.\n */\nimport { composeApi } from '@embedpdf/core';\nimport { isContentsEditableByHand, isTransformableByHand } from '@embedpdf/core-annotation';\n\nimport { createComments } from './comments/comments';\nimport { createThreadIndex } from './comments/threads';\nimport { connectAnnotation } from './connect';\nimport type { AnnotationHostCapability } from './host-contract';\nimport { withEditable, withSnap } from './model';\nimport { createAnnotationReads } from './read/annotations';\nimport { createChromeReads } from './read/chrome';\nimport { createPropertyReads } from './read/properties';\nimport { createRenderReads } from './read/render';\nimport { createServices, type AnnotationContext } from './services';\nimport { createAnnouncer } from './services/announce';\nimport { followConfirmedChanges } from './sync/confirmed';\nimport { createGhost } from './tools/ghost';\nimport { createCrud } from './write/crud';\nimport { createDrafts } from './write/drafts';\nimport { createIcons } from './write/icons';\nimport { createLinkWrites } from './write/links';\nimport { createMarkupWrites } from './write/markup';\nimport { createMeasurement } from './write/measurement';\nimport { registerOpBuilders } from './write/ops';\nimport { createPointer } from './write/pointer';\nimport { createScriptEffects } from './write/script-effects';\nimport { createSelectionWrites } from './write/selection';\nimport { createStamps } from './write/stamps';\nimport { createTextEditing } from './write/text-editing';\n\nexport function createAnnotationController(ctx: AnnotationContext) {\n const services = createServices(ctx);\n const { events, records, view, authority, tools, behaviors, settings } = services;\n\n // The session snaps, and lets people change by hand, as the settings say,\n // and follows them when they change.\n ctx.state.update(withSnap, settings.get().snap);\n ctx.state.update(withEditable, settings.get().editable);\n settings.api.onSettingsChanged(({ settings: next, changed }) => {\n if (changed.includes('snap')) ctx.state.update(withSnap, next.snap);\n if (changed.includes('editable')) ctx.state.update(withEditable, next.editable);\n });\n\n // Reads: pure projections of the model.\n const annotations = createAnnotationReads(ctx, services);\n const chrome = createChromeReads(ctx, services);\n const properties = createPropertyReads(ctx, services);\n\n // Sync: what follows when the engine confirms a change.\n followConfirmedChanges(ctx, services, createAnnouncer(events));\n\n // Writes: every change goes through the store, a gesture's through `commit`,\n // one stated in code through `apply`, and each is one change on the queue.\n const text = createTextEditing(ctx, services, chrome);\n // Before an export reads the document, send the words typed in the last\n // moment, and wait for every change on its way. (A download does the same\n // through the kernel's queue.)\n const settle = async (): Promise<void> => {\n await text.sendTyping();\n await services.store.whenWritten();\n };\n // A text box, or a gesture, on an annotation the `editable` rule now freezes ends.\n settings.api.onSettingsChanged(({ changed }) => {\n if (!changed.includes('editable')) return;\n const model = services.store.model();\n const editing = model.editing === null ? undefined : model.byId[model.editing];\n if (editing && !isContentsEditableByHand(model, editing)) void text.text.end();\n const draft = model.draft;\n const ids = draft && 'ids' in draft ? draft.ids : draft && 'id' in draft ? [draft.id] : [];\n if (ids.some((id) => model.byId[id] && !isTransformableByHand(model, model.byId[id]))) {\n services.store.commit({ type: 'cancel' });\n }\n });\n const links = createLinkWrites(ctx, services);\n registerOpBuilders(services);\n const crud = createCrud(ctx, services, annotations, settle);\n const stamps = createStamps(ctx, services);\n // The tool's ghost: what a click would make, which the page's items paint.\n const ghost = createGhost(ctx, services, stamps);\n const render = createRenderReads(ctx, services, ghost, stamps);\n const icons = createIcons(ctx, services, stamps);\n const selection = createSelectionWrites(ctx, services, annotations, properties, chrome, text);\n const measurement = createMeasurement(ctx, services, crud);\n const pointer = createPointer(ctx, services, chrome, measurement);\n const drafts = createDrafts(ctx, services, annotations);\n const markup = createMarkupWrites(ctx, services, annotations);\n const scripts = createScriptEffects(ctx, services);\n\n // Comments: the conversation lens over the same substrate.\n const threads = createThreadIndex(ctx, services);\n const comments = createComments(ctx, services, threads, crud);\n\n const api: AnnotationHostCapability = composeApi('annotation', [\n settings.api,\n annotations.api,\n chrome.api,\n render.api,\n tools.api,\n behaviors.api,\n text.api,\n links.api,\n crud.api,\n stamps.api,\n ghost.api,\n icons.api,\n measurement.api,\n pointer.api,\n drafts.api,\n markup.api,\n scripts.api,\n comments.api,\n {\n getAt: chrome.annotationAt,\n selection: selection.selection,\n draft: drafts.draft,\n text: {\n ...text.text,\n getEditing: annotations.getEditing,\n toggleFormat: selection.toggleFormat,\n },\n tools: tools.tools,\n stamps: stamps.stamps,\n lend: services.lending.lend,\n // Authority twins, the records mirror and the events are services, not areas.\n getStatus: records.getStatus,\n refresh: (options?: { signal?: AbortSignal }) =>\n ctx.cancellable(options?.signal, records.refresh()),\n whenSynced: () => records.settled(),\n onResynced: events.resynced.on,\n canRead: authority.canRead,\n canCreate: authority.canCreate,\n canUpdate: authority.canUpdate,\n canDelete: authority.canDelete,\n onCreated: events.created.on,\n onUpdated: events.updated.on,\n onDeleted: events.deleted.on,\n onReordered: events.reordered.on,\n onSelectionChanged: events.selectionChanged.on,\n onDraftChanged: events.draftChanged.on,\n onEditingChanged: events.editingChanged.on,\n onHoverChanged: events.hoverChanged.on,\n onWriteFailed: events.writeFailed.on,\n },\n ]);\n return {\n api,\n connect: () => connectAnnotation(ctx, api),\n /** The composed model every read and gesture works on (for the plugin's tests). */\n model: view.model,\n /** The door for gestures and selection verbs (for the plugin's tests). */\n commit: services.store.commit,\n /** The door for changes stated in code (for the plugin's tests). */\n apply: services.store.apply,\n };\n}\n","import { definePlugin } from '@embedpdf/core';\nimport { ActionsToken as PublicActionsToken } from '@embedpdf/plugin-actions/contract';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract/host';\nimport { RenderToken } from '@embedpdf/plugin-render/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract/host';\n\nimport { ANNOTATION_DEFAULTS, type AnnotationConfig } from './contract';\nimport { createAnnotationController } from './controller';\nimport { AnnotationToken } from './host-contract';\nimport { initialAnnotationState } from './model';\n\n/**\n * The annotation plugin. Document-scoped; requires the interaction hub and\n * optionally uses the selection plugin: shapes and ink work without it, text\n * markup lights up only when it is present. The engine's pictures of its\n * annotations come through the render plugin; without it, what draws live\n * still draws. `config` is the settings the app\n * registers, over {@link ANNOTATION_DEFAULTS}.\n */\nexport const annotationPlugin = (config?: AnnotationConfig) =>\n definePlugin({\n id: 'annotation',\n token: AnnotationToken,\n scope: 'document',\n requires: [InteractionToken],\n optional: [SelectionToken, PublicActionsToken, RenderToken],\n state: initialAnnotationState,\n settings: { defaults: ANNOTATION_DEFAULTS, registered: config },\n create: createAnnotationController,\n });\n"],"mappings":"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"}