@embedpdf/react 3.0.0-next.14 → 3.0.0-next.16

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 (244) hide show
  1. package/dist/AnnotationList-DcyhF2kU-CiBFOq1z.d.cts +878 -0
  2. package/dist/AnnotationList-DcyhF2kU-CiBFOq1z.d.ts +878 -0
  3. package/dist/actions.cjs +25 -5
  4. package/dist/actions.cjs.map +1 -1
  5. package/dist/actions.d.cts +18 -5
  6. package/dist/actions.d.ts +18 -5
  7. package/dist/actions.js +22 -6
  8. package/dist/actions.js.map +1 -1
  9. package/dist/anchored-DeX95xSd.d.ts +85 -0
  10. package/dist/anchored-DzN3JywS.d.cts +85 -0
  11. package/dist/anchored.cjs +71 -28
  12. package/dist/anchored.cjs.map +1 -1
  13. package/dist/anchored.d.cts +2 -45
  14. package/dist/anchored.d.ts +2 -45
  15. package/dist/anchored.js +56 -19
  16. package/dist/anchored.js.map +1 -1
  17. package/dist/annotation-3UvABfJm.d.cts +305 -0
  18. package/dist/annotation-BNHQpMKv.cjs +806 -0
  19. package/dist/annotation-BNHQpMKv.cjs.map +1 -0
  20. package/dist/annotation-CDI8CFb3.js +684 -0
  21. package/dist/annotation-CDI8CFb3.js.map +1 -0
  22. package/dist/annotation-DhEfs0pH.d.ts +305 -0
  23. package/dist/annotation.cjs +20 -784
  24. package/dist/annotation.d.cts +2 -2
  25. package/dist/annotation.d.ts +2 -2
  26. package/dist/annotation.js +2 -769
  27. package/dist/attachment.cjs +39 -0
  28. package/dist/attachment.cjs.map +1 -0
  29. package/dist/attachment.d.cts +29 -0
  30. package/dist/attachment.d.ts +29 -0
  31. package/dist/attachment.js +28 -0
  32. package/dist/attachment.js.map +1 -0
  33. package/dist/commands.cjs +68 -28
  34. package/dist/commands.cjs.map +1 -1
  35. package/dist/commands.d.cts +37 -10
  36. package/dist/commands.d.ts +37 -10
  37. package/dist/commands.js +68 -31
  38. package/dist/commands.js.map +1 -1
  39. package/dist/form-BSGvjA5D.js +511 -0
  40. package/dist/form-BSGvjA5D.js.map +1 -0
  41. package/dist/form-BgztZyOK.cjs +548 -0
  42. package/dist/form-BgztZyOK.cjs.map +1 -0
  43. package/dist/form.cjs +5 -5
  44. package/dist/form.d.cts +41 -2
  45. package/dist/form.d.ts +41 -2
  46. package/dist/form.js +2 -3
  47. package/dist/history.cjs +38 -0
  48. package/dist/history.cjs.map +1 -0
  49. package/dist/history.d.cts +27 -0
  50. package/dist/history.d.ts +27 -0
  51. package/dist/history.js +27 -0
  52. package/dist/history.js.map +1 -0
  53. package/dist/i18n.cjs +26 -30
  54. package/dist/i18n.cjs.map +1 -1
  55. package/dist/i18n.d.cts +24 -21
  56. package/dist/i18n.d.ts +24 -21
  57. package/dist/i18n.js +24 -31
  58. package/dist/i18n.js.map +1 -1
  59. package/dist/index.cjs +227 -57
  60. package/dist/index.d.cts +35 -32
  61. package/dist/index.d.ts +35 -32
  62. package/dist/index.js +36 -30
  63. package/dist/inert-CmBEbKCn.cjs +19 -0
  64. package/dist/inert-CmBEbKCn.cjs.map +1 -0
  65. package/dist/inert-D8fkennb.js +14 -0
  66. package/dist/inert-D8fkennb.js.map +1 -0
  67. package/dist/interaction.cjs +48 -102
  68. package/dist/interaction.cjs.map +1 -1
  69. package/dist/interaction.d.cts +23 -32
  70. package/dist/interaction.d.ts +23 -32
  71. package/dist/interaction.js +33 -102
  72. package/dist/interaction.js.map +1 -1
  73. package/dist/link.cjs +65 -104
  74. package/dist/link.cjs.map +1 -1
  75. package/dist/link.d.cts +21 -16
  76. package/dist/link.d.ts +22 -17
  77. package/dist/link.js +67 -107
  78. package/dist/link.js.map +1 -1
  79. package/dist/measurement.cjs +36 -11
  80. package/dist/measurement.cjs.map +1 -1
  81. package/dist/measurement.d.cts +33 -7
  82. package/dist/measurement.d.ts +33 -7
  83. package/dist/measurement.js +35 -14
  84. package/dist/measurement.js.map +1 -1
  85. package/dist/metadata.cjs +20 -7
  86. package/dist/metadata.cjs.map +1 -1
  87. package/dist/metadata.d.cts +22 -7
  88. package/dist/metadata.d.ts +22 -7
  89. package/dist/metadata.js +20 -10
  90. package/dist/metadata.js.map +1 -1
  91. package/dist/outline.cjs +39 -0
  92. package/dist/outline.cjs.map +1 -0
  93. package/dist/outline.d.cts +31 -0
  94. package/dist/outline.d.ts +31 -0
  95. package/dist/outline.js +28 -0
  96. package/dist/outline.js.map +1 -0
  97. package/dist/page-edit.cjs +15 -3
  98. package/dist/page-edit.cjs.map +1 -1
  99. package/dist/page-edit.d.cts +17 -2
  100. package/dist/page-edit.d.ts +17 -2
  101. package/dist/page-edit.js +15 -5
  102. package/dist/page-edit.js.map +1 -1
  103. package/dist/page-layers-Bkaaz8Zf.js +26 -0
  104. package/dist/page-layers-Bkaaz8Zf.js.map +1 -0
  105. package/dist/page-layers-BloZDoOV.cjs +37 -0
  106. package/dist/page-layers-BloZDoOV.cjs.map +1 -0
  107. package/dist/page-view.cjs +89 -82
  108. package/dist/page-view.cjs.map +1 -1
  109. package/dist/page-view.d.cts +14 -7
  110. package/dist/page-view.d.ts +18 -11
  111. package/dist/page-view.js +86 -81
  112. package/dist/page-view.js.map +1 -1
  113. package/dist/redaction.cjs +30 -15
  114. package/dist/redaction.cjs.map +1 -1
  115. package/dist/redaction.d.cts +27 -9
  116. package/dist/redaction.d.ts +27 -9
  117. package/dist/redaction.js +29 -18
  118. package/dist/redaction.js.map +1 -1
  119. package/dist/render.cjs +71 -46
  120. package/dist/render.cjs.map +1 -1
  121. package/dist/render.d.cts +17 -5
  122. package/dist/render.d.ts +17 -5
  123. package/dist/render.js +70 -49
  124. package/dist/render.js.map +1 -1
  125. package/dist/runtime-BfnpyfY0.cjs +556 -0
  126. package/dist/runtime-BfnpyfY0.cjs.map +1 -0
  127. package/dist/runtime-DBEBlpQV.d.cts +237 -0
  128. package/dist/runtime-V3MVMb91.d.ts +237 -0
  129. package/dist/runtime-tD5iJU83.js +399 -0
  130. package/dist/runtime-tD5iJU83.js.map +1 -0
  131. package/dist/runtime.cjs +45 -324
  132. package/dist/runtime.d.cts +2 -2
  133. package/dist/runtime.d.ts +2 -2
  134. package/dist/runtime.js +2 -306
  135. package/dist/search.cjs +81 -50
  136. package/dist/search.cjs.map +1 -1
  137. package/dist/search.d.cts +37 -24
  138. package/dist/search.d.ts +37 -24
  139. package/dist/search.js +81 -53
  140. package/dist/search.js.map +1 -1
  141. package/dist/selection.cjs +105 -108
  142. package/dist/selection.cjs.map +1 -1
  143. package/dist/selection.d.cts +54 -26
  144. package/dist/selection.d.ts +56 -28
  145. package/dist/selection.js +103 -110
  146. package/dist/selection.js.map +1 -1
  147. package/dist/shell.cjs +36 -21
  148. package/dist/shell.cjs.map +1 -1
  149. package/dist/shell.d.cts +32 -17
  150. package/dist/shell.d.ts +32 -17
  151. package/dist/shell.js +36 -24
  152. package/dist/shell.js.map +1 -1
  153. package/dist/signature.cjs +29 -48
  154. package/dist/signature.cjs.map +1 -1
  155. package/dist/signature.d.cts +26 -26
  156. package/dist/signature.d.ts +26 -26
  157. package/dist/signature.js +30 -48
  158. package/dist/signature.js.map +1 -1
  159. package/dist/stage-B7BG2e8Q.cjs +369 -0
  160. package/dist/stage-B7BG2e8Q.cjs.map +1 -0
  161. package/dist/stage-BqfBjDu6.js +302 -0
  162. package/dist/stage-BqfBjDu6.js.map +1 -0
  163. package/dist/stage-ByFPD-Fv.d.cts +117 -0
  164. package/dist/stage-DaboaheR.d.ts +117 -0
  165. package/dist/stage-scope-CQgCuf1w.cjs +46 -0
  166. package/dist/stage-scope-CQgCuf1w.cjs.map +1 -0
  167. package/dist/stage-scope-D7ZeNduT.js +23 -0
  168. package/dist/stage-scope-D7ZeNduT.js.map +1 -0
  169. package/dist/stage.cjs +12 -235
  170. package/dist/stage.d.cts +2 -116
  171. package/dist/stage.d.ts +2 -116
  172. package/dist/stage.js +3 -228
  173. package/dist/stamp.cjs +41 -35
  174. package/dist/stamp.cjs.map +1 -1
  175. package/dist/stamp.d.cts +25 -18
  176. package/dist/stamp.d.ts +25 -18
  177. package/dist/stamp.js +40 -37
  178. package/dist/stamp.js.map +1 -1
  179. package/dist/state-0K1I5cM4.d.cts +29 -0
  180. package/dist/state-0K1I5cM4.d.ts +29 -0
  181. package/dist/state-CzI2KlZb.js +62 -0
  182. package/dist/state-CzI2KlZb.js.map +1 -0
  183. package/dist/state-Dtf8HAue.cjs +73 -0
  184. package/dist/state-Dtf8HAue.cjs.map +1 -0
  185. package/dist/svg-shapes-Dm1yTR1b.js +40 -0
  186. package/dist/svg-shapes-Dm1yTR1b.js.map +1 -0
  187. package/dist/svg-shapes-zo0GNkc9.cjs +53 -0
  188. package/dist/svg-shapes-zo0GNkc9.cjs.map +1 -0
  189. package/dist/toolbar.cjs +297 -295
  190. package/dist/toolbar.cjs.map +1 -1
  191. package/dist/toolbar.d.cts +58 -68
  192. package/dist/toolbar.d.ts +67 -77
  193. package/dist/toolbar.js +271 -293
  194. package/dist/toolbar.js.map +1 -1
  195. package/dist/view-manager.cjs +34 -0
  196. package/dist/view-manager.cjs.map +1 -0
  197. package/dist/view-manager.d.cts +21 -0
  198. package/dist/view-manager.d.ts +21 -0
  199. package/dist/view-manager.js +23 -0
  200. package/dist/view-manager.js.map +1 -0
  201. package/package.json +47 -39
  202. package/dist/annotation-BCED_p9H.d.cts +0 -160
  203. package/dist/annotation-anchors-CetwM1g7.js +0 -15
  204. package/dist/annotation-anchors-CetwM1g7.js.map +0 -1
  205. package/dist/annotation-anchors-DuYRBJLl.cjs +0 -26
  206. package/dist/annotation-anchors-DuYRBJLl.cjs.map +0 -1
  207. package/dist/annotation-hooks-BB5ZhPpf.cjs +0 -16
  208. package/dist/annotation-hooks-BB5ZhPpf.cjs.map +0 -1
  209. package/dist/annotation-hooks-Df8EmzDO.js +0 -11
  210. package/dist/annotation-hooks-Df8EmzDO.js.map +0 -1
  211. package/dist/annotation-k38KDlIZ.d.ts +0 -160
  212. package/dist/annotation-menu.cjs +0 -64
  213. package/dist/annotation-menu.cjs.map +0 -1
  214. package/dist/annotation-menu.d.cts +0 -33
  215. package/dist/annotation-menu.d.ts +0 -33
  216. package/dist/annotation-menu.js +0 -48
  217. package/dist/annotation-menu.js.map +0 -1
  218. package/dist/annotation.cjs.map +0 -1
  219. package/dist/annotation.js.map +0 -1
  220. package/dist/form-BVumS7up.cjs +0 -926
  221. package/dist/form-BVumS7up.cjs.map +0 -1
  222. package/dist/form-Bdjk0Z3T.d.cts +0 -537
  223. package/dist/form-CK3mp99m.js +0 -895
  224. package/dist/form-CK3mp99m.js.map +0 -1
  225. package/dist/form-CYRYgthn.d.ts +0 -537
  226. package/dist/rolldown-runtime-BBjsoOtd.js +0 -27
  227. package/dist/runtime-DE76hlnl.d.ts +0 -216
  228. package/dist/runtime-umHA_xHt.d.cts +0 -216
  229. package/dist/runtime.cjs.map +0 -1
  230. package/dist/runtime.js.map +0 -1
  231. package/dist/scrollbar.cjs +0 -241
  232. package/dist/scrollbar.cjs.map +0 -1
  233. package/dist/scrollbar.d.cts +0 -42
  234. package/dist/scrollbar.d.ts +0 -42
  235. package/dist/scrollbar.js +0 -213
  236. package/dist/scrollbar.js.map +0 -1
  237. package/dist/stage.cjs.map +0 -1
  238. package/dist/stage.js.map +0 -1
  239. package/dist/views.cjs +0 -35
  240. package/dist/views.cjs.map +0 -1
  241. package/dist/views.d.cts +0 -21
  242. package/dist/views.d.ts +0 -21
  243. package/dist/views.js +0 -27
  244. package/dist/views.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotation-CDI8CFb3.js","names":["AnnotationToken","AnnotationHostToken","AnnotationToken","React","AnnotationHostToken"],"sources":["../src/annotation-hooks.ts","../src/annotation-menu.tsx","../src/annotation.tsx"],"sourcesContent":["/**\n * The annotation hooks other feature entries use too (the form plugin reads\n * the selection), kept apart so they don't import the whole annotation\n * feature: the state and the settings, each from its declaration.\n */\nimport { AnnotationToken, annotationState } from '@embedpdf/plugin-annotation/contract';\n\nimport { settingsHook, stateHook } from './state';\n\n/**\n * The annotation state: `status` (`'loading'` until every annotation is in,\n * then `'ready'`), the `selected` annotations, the one `hovered` under the\n * pointer and the text box being typed in (`editing`). Re-renders only when a\n * field changes, or the value `select` picks. Empty without a document.\n */\nexport const useAnnotationState = stateHook(annotationState);\n\n/**\n * The annotation settings (`snap`, `chrome`, `afterCreate`, `tools`), or the\n * value `select` picks. They belong to the plugin, so they read without a\n * document; change them with `useAnnotation().updateSettings()`.\n */\nexport const useAnnotationSettings = settingsHook(AnnotationToken);\n","/**\n * Annotation menus: thin anchor plumbing over the one `<Anchored>` primitive.\n * They come from `/annotation`; this module stays apart so it doesn't pull\n * in the layer.\n *\n * These work identically under `<Stage>` (mount in the overlay slot; the\n * camera projects, no DOM reads) and `<PageView>` (measured and portalled):\n * the surface provides the projector, the menu doesn't care.\n *\n * No action bags: actions come from `useAnnotation()` and the state hooks,\n * which subscribe properly and compose across plugins. Render props carry\n * only the anchor's data (the draft menu's progress); the selection menu\n * takes plain children.\n */\nimport * as React from 'react';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { AnnotationToken as AnnotationHostToken } from '@embedpdf/plugin-annotation/contract/host';\nimport type { CreationDraftAnchor, RotationAnchor } from '@embedpdf/core-annotation';\nimport {\n paint,\n paintDefault,\n sameCreationDraftAnchor,\n sameRotationAnchor,\n sameSelectionAnchor,\n} from '@embedpdf/web';\nimport { Anchored, useProjectorBinding, type AnchoredPlacement } from './anchored';\nimport { useAnnotationSettings } from './annotation-hooks';\nimport { useOptionalSelector } from './runtime';\n\nexport interface AnnotationMenuProps {\n children: React.ReactNode;\n /** Gap in screen px between the selection box and the menu (default 15). */\n gap?: number;\n /** Where to place the menu relative to the selection box. Default 'top'. */\n placement?: AnchoredPlacement;\n}\n\n/**\n * Your own menu next to the selection (one anchor, also for a selection over\n * several pages), clear of the rotation handle. It hides while the selection\n * is dragged, resized or turned. What's in it is yours: build it from\n * `useAnnotation()` and `useAnnotationState()`.\n */\nexport function AnnotationMenu({ children, gap = 15, placement = 'top' }: AnnotationMenuProps) {\n // Reading the binding subscribes this component to projection changes\n // (its identity is the revision), so the anchor read below re-runs with\n // fresh view facts in the same commit as the surface: the rotation\n // handle's offset is screen-constant, so its page-space position depends\n // on the page's live view scale.\n const { projector } = useProjectorBinding();\n const anchor = useOptionalSelector(\n AnnotationHostToken,\n (annotation) => {\n const selectionAnchor = annotation.selection.getAnchor();\n if (!selectionAnchor) return null;\n const env = projector.viewEnv(selectionAnchor.page);\n return env ? annotation.getSelectionAnchorIn(env) : selectionAnchor;\n },\n null,\n sameSelectionAnchor,\n );\n if (!anchor) return null;\n return (\n <Anchored\n anchor={{\n page: anchor.page,\n bounds: anchor.bounds,\n ...(anchor.rotationHandle ? { avoid: [anchor.rotationHandle] } : {}),\n }}\n placement={placement}\n gap={gap}\n >\n {children}\n </Anchored>\n );\n}\n\nexport interface AnnotationDraftMenuProps {\n /** Render prop receiving the shape being drawn (`subtype`, `pointCount`,\n * `minPoints`, `canFinish`, …). The verbs are capability calls:\n * `useAnnotation().draft.finish()` and `.draft.cancel()`. */\n children: (anchor: CreationDraftAnchor) => React.ReactNode;\n /** Gap in screen px between the draft anchor and the menu (default 8). */\n gap?: number;\n /** Where to place the menu relative to the draft anchor. Default 'top'. */\n placement?: AnchoredPlacement;\n}\n\n/** Floats over a live multi-click creation draft (polygon, polyline, …). */\nexport function AnnotationDraftMenu({\n children,\n gap = 8,\n placement = 'top',\n}: AnnotationDraftMenuProps) {\n const anchor = useOptionalSelector(\n AnnotationToken,\n (annotation) => annotation.draft.get(),\n null,\n sameCreationDraftAnchor,\n );\n if (!anchor) return null;\n return (\n <Anchored anchor={anchor} placement={placement} gap={gap}>\n {children(anchor)}\n </Anchored>\n );\n}\n\nexport interface AnnotationRotationBadgeProps {\n /** Render prop receiving the rotation in progress (`angle`, degrees\n * clockwise, as the commit will apply it). Without it, the badge shows the\n * angle in the `chrome.readout` colors, when `chrome.readout.enabled`. */\n children?: (rotation: RotationAnchor) => React.ReactNode;\n /** Gap in screen px between the pointer and the badge (default 16). */\n gap?: number;\n /** Where to place the badge relative to the pointer. Default 'right'. */\n placement?: AnchoredPlacement;\n}\n\n/**\n * Follows the pointer while a selection is being turned, upright however the\n * page is shown: it floats over the page like the menus, not in it. Shows\n * nothing when no rotation is in progress.\n */\nexport function AnnotationRotationBadge({\n children,\n gap = 16,\n placement = 'right',\n}: AnnotationRotationBadgeProps) {\n const rotation = useOptionalSelector(\n AnnotationToken,\n (annotation) => annotation.selection.getRotationAnchor(),\n null,\n sameRotationAnchor,\n );\n const readout = useAnnotationSettings((settings) => settings.chrome.readout);\n if (!rotation || (!children && !readout.enabled)) return null;\n return (\n <Anchored\n anchor={{ page: rotation.page, bounds: { ...rotation.at, width: 0, height: 0 } }}\n placement={placement}\n gap={gap}\n >\n {children ? (\n children(rotation)\n ) : (\n <div\n style={{\n pointerEvents: 'none',\n whiteSpace: 'nowrap',\n borderRadius: 4,\n padding: '2px 6px',\n fontFamily: paintDefault('font-mono'),\n fontSize: 12,\n background: paint('readout-background', readout.background),\n color: paint('readout-color', readout.color),\n }}\n >\n {rotation.angle}°\n </div>\n )}\n </Anchored>\n );\n}\n","/**\n * The React view of @embedpdf/plugin-annotation.\n *\n * Pure paint: it reads the per-page render items and chrome and draws them.\n * Pointer events arrive through the interaction hub (the Stage's forwarding),\n * and the cursor is driven by the hub too (the edit handler claims\n * move/pointer/resize on hover). Each annotation resolves to one native node:\n * a vector scene, the engine's baked /AP <img>, or a registered behavior; a\n * renderer may wrap or replace it. Every chrome color is a setting painted\n * through `paint()`, so its `--epdf-annotation-*` CSS variable wins.\n *\n * What isn't React lives in `@embedpdf/web`, the same for every framework:\n * the scene as SVG elements, the chrome's paint and pixels, the text box\n * editor, which drawing each annotation gets and the behaviors renderers\n * register, and the object URLs of baked appearances and the stamp ghost.\n *\n * The hooks follow every plugin's four: `useAnnotation()` (the API),\n * `useAnnotationState()` (status, selected, hovered, editing),\n * `useAnnotationEvent()` and `useAnnotationSettings()`; the reads a component\n * follows on their own are `useAnnotationList()`, `useAnnotationDefaults()`,\n * `useAnnotationProperties()` and `useAnnotationAnchor()`.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-annotation';\nimport type { EventHook, PageRef } from '@embedpdf/core';\nimport {\n hasLiveDrawing,\n scene,\n MITER_LIMIT,\n type FieldValues,\n type Point,\n type RenderItem,\n} from '@embedpdf/core-annotation';\nimport {\n AnnotationToken,\n annotationKey,\n type Annotation,\n type AnnotationAnchor,\n type AnnotationCapability,\n type AnnotationFilter,\n type AnnotationProperties,\n type AnnotationRef,\n type ChromeSettings,\n type CommentsApi,\n type CommentThread,\n type FilePickerProvider,\n type HandleRole,\n type TextItem,\n type ToolDefaults,\n} from '@embedpdf/plugin-annotation';\n// The render layer is framework code, so it resolves the full host lens\n// (page items, chrome, appearances…). Same runtime token as the public one,\n// only the type differs. App code never imports this.\nimport {\n AnnotationToken as AnnotationHostToken,\n previewBucket,\n} from '@embedpdf/plugin-annotation/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { RenderToken } from '@embedpdf/plugin-render/contract/host';\nimport {\n annotationChromePaint,\n annotationDrawingOf,\n bakedAppearanceOf,\n chromeInPixels,\n createShownUrls,\n createTextBoxEditorFollower,\n editingTextKeyOf,\n enrichCommentThreads,\n frameInPixels,\n freeTextBoxOf,\n ghostOpacity,\n installFilePickerProvider,\n layerTextBoxesOf,\n loadAppearanceUrls,\n loadObjectUrl,\n lookFrameOf,\n ownTextBoxOf,\n pickRequestedFile,\n pictureOrPainting,\n rasterInFrame,\n rectInPixels,\n registerRendererBehaviors,\n sameAnnotationAnchor,\n sceneViewBox,\n shownAppearance,\n svgShapesOf,\n textBoxEditorScaleOf,\n type AnnotationChromePaint,\n type AppearanceUrl,\n type FrameFraction,\n} from '@embedpdf/web';\nimport { useEffect, useRef, useState } from 'react';\nimport * as React from 'react';\n\nexport type {\n CreationDraftAnchor,\n RenderItem,\n LineEnding,\n LineEndings,\n Style,\n AnnotationFlags,\n FieldValues,\n TextAlign,\n TextStyle,\n} from '@embedpdf/core-annotation';\nimport { devWarn } from './dev';\nimport { usePaintsPagePart } from './page-layers';\nimport { useAnnotationSettings } from './annotation-hooks';\nimport { INERT } from './inert';\nimport {\n shallowArray,\n useCapability,\n useCapabilityEvent,\n useDocumentId,\n useKernelValue,\n useOptionalCapability,\n useOptionalSelector,\n usePage,\n useSelector,\n useViewerSettings,\n} from './runtime';\nimport type { PageContextValue, PageLayout } from './runtime';\nimport { SvgShapes } from './svg-shapes';\n\nexport { useAnnotationSettings, useAnnotationState } from './annotation-hooks';\nexport {\n AnnotationDraftMenu,\n AnnotationMenu,\n AnnotationRotationBadge,\n type AnnotationDraftMenuProps,\n type AnnotationMenuProps,\n type AnnotationRotationBadgeProps,\n} from './annotation-menu';\n\n// ── renderers ────────────────────────────────────────────────────────────────\n\n/** The box a renderer draws into: the size to draw at, how it's turned, and how it's scaled. */\nexport interface AnnotationFrame {\n /** Its width in pixels at the annotation's 100% size, before its turn: draw at this. */\n width: number;\n /** Its height in pixels at the annotation's 100% size, before its turn: draw at this. */\n height: number;\n /**\n * How it's turned on screen, degrees clockwise: the page's turn and the\n * annotation's own. 0 is upright; turn your content by `-rotation` to keep\n * it upright.\n */\n rotation: number;\n /**\n * How much the layer scales what you draw, with the page: the zoom, or for\n * an annotation that keeps its size on screen, the zoom up to 1.\n */\n scale: number;\n}\n\n/**\n * What a renderer's component gets: the annotation, the frame to draw into,\n * and the layer's own drawing of it to keep or wrap. The layer keeps handling\n * the pointer (select, move, resize) unless the renderer is `interactive`.\n */\nexport interface AnnotationRendererProps {\n /** The annotation, as `get()` returns it. */\n annotation: Annotation;\n /**\n * The box you draw into. The layer places, turns and scales it like the\n * annotation's own drawing, also during a drag, a resize or a turn. Fill it\n * (`width: 100%; height: 100%`) and draw at the annotation's 100% size: your\n * text and borders scale with the page.\n */\n frame: AnnotationFrame;\n /** The layer's own drawing of it, filling the frame. Render it to keep the original look and add to it. */\n native: React.ReactNode;\n /** The engine's picture of the annotation as an image (`url`), or `null`. `native` draws it in place. */\n appearance: { url: string } | null;\n /** True while the pointer is over it. */\n hovered: boolean;\n /** True while it's selected. */\n selected: boolean;\n /** True when what you draw takes the pointer (see `interactive` on the renderer). */\n interactive: boolean;\n}\n\n/**\n * What a sibling plugin's renderer gets for the annotations its behavior owns\n * (the form plugin's fill controls). It places its own controls: `item` is the\n * layer's projection of the annotation (its box, style, text and raster box,\n * in page coordinates), and `page.transform.toPixels()` turns those into the\n * layer's pixels.\n */\nexport interface BehaviorRendererProps {\n annotation: Annotation;\n item: RenderItem;\n page: PageContextValue;\n /** The layer's own drawing of it, where the layer draws it. */\n native: React.ReactNode;\n hovered: boolean;\n selected: boolean;\n interactive: boolean;\n}\n\n/** What an `interactive` function is asked: the annotation, and the active tool. */\nexport interface AnnotationInteractiveContext {\n annotation: Annotation;\n toolId: string;\n}\n\n/**\n * One rule: \"draw these annotations with this component\". `for` gets the\n * annotation with all its fields; the first renderer that matches wins.\n * Without `interactive` the component only draws: the layer keeps handling\n * the pointer. With `interactive` (or a function asked whenever it matters)\n * the component takes the pointer, and the annotation can't be selected or\n * moved while it does.\n *\n * Define the list once, outside your component or in `useMemo`: the layer\n * registers each entry, and a new list every render registers them again.\n *\n * `{ behavior, component }` draws what a sibling plugin's behavior owns (the\n * form plugin's fill controls); the plugin decides when it's engaged.\n */\nexport type AnnotationRenderer =\n | { behavior: string; component: React.ComponentType<BehaviorRendererProps> }\n | {\n /** A stable id for the registration (optional; generated). */\n id?: string;\n for: (annotation: Annotation) => boolean;\n component: React.ComponentType<AnnotationRendererProps>;\n interactive?: boolean | ((context: AnnotationInteractiveContext) => boolean);\n /**\n * Scale what you draw with the page (the default): you draw at the\n * annotation's 100% size. `false`: you draw at its size on screen, and\n * size things yourself from `frame.scale`.\n */\n scale?: boolean;\n };\n\n/** What a handle component you draw yourself gets. */\nexport interface HandleProps {\n /** The handle's center, in pixels on the page. */\n at: Point;\n /** The `size` from the settings, px. */\n size: number;\n /** The selection's rotation (degrees clockwise), so a square handle can turn with it. */\n rotation: number;\n /** A box's `'corner'` or `'side'`, or one `'point'` of a line or a polygon. */\n kind: HandleRole;\n /** True while it's being dragged. */\n active: boolean;\n}\n\n/** What a rotation handle component gets: a handle's props, and where its stalk starts on the box. */\nexport interface RotationHandleProps extends Omit<HandleProps, 'kind'> {\n /** Where the stalk starts on the box, in pixels on the page. */\n from: Point;\n}\n\n/** Your own handles, drawn in place of the layer's. The viewer still decides where they can be grabbed. */\nexport interface AnnotationLayerComponents {\n Handle?: React.ComponentType<HandleProps>;\n RotationHandle?: React.ComponentType<RotationHandleProps>;\n}\n\nexport interface AnnotationLayerProps {\n /** Your own look for some annotations ({@link AnnotationRenderer}). */\n renderers?: AnnotationRenderer[];\n /** Your own handles and rotation handle. */\n components?: AnnotationLayerComponents;\n}\n\n/** How much the layer scales the look around it: 1 outside a look, or in one drawn at its size on screen. */\nconst LookScaleContext = React.createContext(1);\n\n/**\n * The box an annotation draws into, placed, sized and turned like the\n * annotation (`item.frame`) inside the page layer, which the page itself\n * turns. The annotation's own drawing and any look of yours draw inside it.\n */\nfunction AnnotationFrame({\n item,\n page,\n interactive = false,\n inert = false,\n children,\n}: {\n item: RenderItem;\n page: PageContextValue;\n interactive?: boolean;\n inert?: boolean;\n children: React.ReactNode;\n}) {\n const box = frameInPixels(item.frame, page.transform);\n return (\n <div\n {...(inert ? INERT : {})}\n style={{\n position: 'absolute',\n left: box.left,\n top: box.top,\n width: box.width,\n height: box.height,\n transform: box.transform,\n transformOrigin: 'center',\n // On the frame: a turned frame groups what is inside it, so blending on\n // an inner element would stop blending with the page.\n mixBlendMode: item.blend,\n // An interactive renderer takes the pointer: the layer's own `none` ends here.\n pointerEvents: interactive ? 'auto' : 'none',\n }}\n >\n {children}\n </div>\n );\n}\n\n/** SVG attribute names as React props: `stroke-width` is `strokeWidth`. */\n/**\n * The scene, filling the item's frame: drawn upright in it, the frame turns\n * it. The core computed the box and the painted scene; `@embedpdf/web`\n * describes each scene node as one SVG element, so there is no per-kind\n * logic and no bounds math here.\n */\nfunction Shape({ item }: { item: RenderItem }) {\n // Nothing to draw until the annotation has area (the 0×0 draft at mouse-down).\n const viewBox = sceneViewBox(item.box);\n if (!viewBox) return null;\n return (\n <svg\n viewBox={viewBox}\n style={{\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n overflow: 'visible',\n pointerEvents: 'none',\n // A ghost is see-through as a whole, so its fill and stroke don't stack.\n ...(item.source === 'ghost' ? { opacity: ghostOpacity(item.ghostOpacity ?? 0.5) } : {}),\n }}\n >\n <SvgShapes shapes={svgShapesOf(scene(item), { miterLimit: MITER_LIMIT })} />\n </svg>\n );\n}\n\n/** The engine's raster inside the item's frame, where `item.raster` puts it, at any frame size. */\nfunction BakedImage({ url, box }: { url: string; box: FrameFraction }) {\n return (\n <img\n src={url}\n alt=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n left: box.left,\n top: box.top,\n width: box.width,\n height: box.height,\n // The AP box is sized in content units; a global `img { max-width: 100% }`\n // reset would otherwise clamp it to the containing block and distort the\n // aspect. This bites specifically when the box is wider than that block —\n // a landscape stamp whose unrotated box overhangs a view-rotated (portrait)\n // page — so honour the explicit size.\n maxWidth: 'none',\n maxHeight: 'none',\n pointerEvents: 'none',\n // The turn the engine took out of the raster, put back about its middle.\n transform: box.transform,\n transformOrigin: 'center',\n }}\n />\n );\n}\n\n/**\n * The armed stamp's ghost: a see-through render of the payload drawn in the\n * exact box a click would place it (the plugin computes it with the same fit\n * + clamp as placement). Every other tool's ghost rides `pageItems` like a\n * drawing in progress. The preview bytes live in the capability closure; this\n * layer owns only the object-URL lifetime, keyed on the armed stamp — a new\n * arm swaps the image, a disarm (or tool change) drops it.\n */\nfunction ToolGhostImage({ page }: { page: PageContextValue }) {\n const anno = useCapability(AnnotationHostToken);\n const ghost = useSelector(AnnotationHostToken, (annotation) =>\n annotation.getImageGhost(page.ref),\n );\n const armed = useSelector(AnnotationHostToken, (annotation) => annotation.getArmedStamp());\n const [url, setUrl] = useState<string | null>(null);\n // The ghost is a bitmap of vector artwork, right at one size: ask for the\n // bucket that covers the box's device width (points × device px per point),\n // so it stays sharp at every zoom and density. The plugin caches per bucket.\n const bucket = ghost ? previewBucket(ghost.box.width * page.transform.renderScale) : 0;\n\n useEffect(() => {\n if (!bucket) {\n setUrl(null);\n return;\n }\n // The previous bucket's image stays up until this one resolves: no\n // flicker while a zoom crosses a bucket boundary.\n return loadObjectUrl(() => anno.renderArmedStampPreview(bucket), setUrl);\n }, [anno, armed, bucket]);\n\n if (!ghost || !url) return null;\n const frame = rectInPixels(ghost.box, page.transform);\n return (\n <img\n src={url}\n alt=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n left: frame.left,\n top: frame.top,\n width: frame.width,\n height: frame.height,\n // Same explicit-size rule as BakedImage: never let a global img reset\n // clamp the box and distort the aspect.\n maxWidth: 'none',\n maxHeight: 'none',\n pointerEvents: 'none',\n opacity: ghostOpacity(ghost.opacity),\n ...(ghost.rot ? { transform: `rotate(${ghost.rot}deg)`, transformOrigin: 'center' } : {}),\n }}\n />\n );\n}\n\n// ── the selection's chrome ───────────────────────────────────────────────────\n\n/** The chrome settings, painted: follows the settings and the viewer's accent live. */\nfunction useChromePaint(): { chrome: ChromeSettings; painted: AnnotationChromePaint } {\n const chrome = useAnnotationSettings((settings) => settings.chrome);\n const accent = useViewerSettings((settings) => settings.accent);\n const painted = React.useMemo(() => annotationChromePaint(chrome, accent), [chrome, accent]);\n return { chrome, painted };\n}\n\n/** A handle as the layer draws it: a square or a circle, `size` px across. */\nfunction DefaultHandle({\n at,\n size,\n rotation,\n shape,\n style,\n}: {\n at: Point;\n size: number;\n rotation: number;\n shape: 'square' | 'circle';\n style: React.CSSProperties;\n}) {\n if (shape === 'circle') {\n return <circle cx={at.x} cy={at.y} r={size / 2} strokeWidth={1.5} style={style} />;\n }\n return (\n <rect\n x={at.x - size / 2}\n y={at.y - size / 2}\n width={size}\n height={size}\n strokeWidth={1.5}\n style={style}\n // The square rides a rotated box's orientation (spin about itself).\n {...(rotation ? { transform: `rotate(${rotation} ${at.x} ${at.y})` } : {})}\n />\n );\n}\n\nfunction Chrome({\n page,\n components,\n}: {\n page: PageContextValue;\n components?: AnnotationLayerComponents;\n}) {\n // The page's view scale converts the screen-pixel chrome settings into\n // content units inside the plugin (rotation handle offset, grab zones):\n // screen-constant at every zoom. What this draws is in screen pixels already.\n const scale = page.transform.viewScale;\n const rotation = page.transform.rotation;\n const zoom = page.transform.zoom;\n const nodes = useSelector(\n AnnotationHostToken,\n (annotation) => annotation.listChromeNodes(page.ref, scale, rotation, zoom),\n shallowArray,\n );\n const { chrome, painted } = useChromePaint();\n const Handle = components?.Handle;\n const RotationHandle = components?.RotationHandle;\n // Your own handles draw as HTML over the page; the layer's as SVG.\n const custom: React.ReactNode[] = [];\n const svg = chromeInPixels(nodes, page.transform).map((node, i) => {\n switch (node.kind) {\n case 'handle':\n if (Handle) {\n custom.push(\n <Handle\n key={i}\n at={node.at}\n size={chrome.handles.size}\n rotation={node.rotation}\n kind={node.role}\n active={node.active}\n />,\n );\n return null;\n }\n return (\n <DefaultHandle\n key={i}\n at={node.at}\n size={chrome.handles.size}\n rotation={node.rotation}\n shape={chrome.handles.shape}\n style={painted.handle}\n />\n );\n case 'guide':\n return (\n <line\n key={i}\n x1={node.from.x}\n y1={node.from.y}\n x2={node.to.x}\n y2={node.to.y}\n shapeRendering=\"crispEdges\"\n style={painted.guide}\n />\n );\n case 'turned-outline':\n return <polygon key={i} points={node.points} fill=\"none\" style={painted.outline} />;\n case 'rotation-guides':\n return (\n <g key={i}>\n {node.lines.map((line, j) => (\n <line\n key={j}\n x1={line.from.x}\n y1={line.from.y}\n x2={line.to.x}\n y2={line.to.y}\n opacity={line.opacity}\n style={painted.rotationGuide}\n />\n ))}\n </g>\n );\n case 'rotation-handle':\n if (RotationHandle) {\n custom.push(\n <RotationHandle\n key={i}\n at={node.at}\n from={node.from}\n size={chrome.rotationHandle.size}\n rotation={0}\n active={false}\n />,\n );\n return null;\n }\n return (\n <g key={i}>\n {chrome.rotationHandle.stalk && (\n <line\n x1={node.from.x}\n y1={node.from.y}\n x2={node.at.x}\n y2={node.at.y}\n strokeWidth={1}\n style={{ stroke: painted.rotationHandle.stroke }}\n />\n )}\n <circle\n cx={node.at.x}\n cy={node.at.y}\n r={chrome.rotationHandle.size / 2}\n strokeWidth={1.5}\n style={painted.rotationHandle}\n />\n </g>\n );\n // The box dragged to select keeps its own look (a see-through accent\n // fill, always dashed); the selection outline follows the settings.\n case 'marquee':\n return (\n <rect\n key={i}\n x={node.box.left}\n y={node.box.top}\n width={node.box.width}\n height={node.box.height}\n strokeWidth={1}\n strokeDasharray=\"4 3\"\n style={painted.marquee}\n />\n );\n case 'outline':\n return (\n <rect\n key={i}\n x={node.box.left}\n y={node.box.top}\n width={node.box.width}\n height={node.box.height}\n fill=\"none\"\n style={painted.outline}\n />\n );\n }\n });\n return (\n <>\n <svg style={{ position: 'absolute', inset: 0, overflow: 'visible', pointerEvents: 'none' }}>\n {svg}\n </svg>\n {custom.length > 0 && (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>{custom}</div>\n )}\n </>\n );\n}\n\n// ── text boxes ───────────────────────────────────────────────────────────────\n\n/**\n * Make an element the editor of a text box: `@embedpdf/web`'s text box\n * editor binds it (rich text, focus and `contentEditable` following\n * `item.editing`, presses kept inside), and its follower attaches again for\n * another element or document and hands it the item and the scale. Returns\n * the ref callback for the element.\n */\nfunction useTextBoxEditor(\n item: TextItem | null,\n scale: number,\n): (element: HTMLElement | null) => void {\n const anno = useCapability(AnnotationHostToken);\n const [element, setElement] = useState<HTMLElement | null>(null);\n const [follower] = useState(() => createTextBoxEditorFollower<AnnotationRef>());\n // On every item or scale change too: the editor redraws only when the text differs.\n useEffect(\n () => follower.follow(element, anno, item, scale),\n [follower, anno, element, item, scale],\n );\n useEffect(() => () => follower.detach(), [follower]);\n return setElement;\n}\n\n/** A free text annotation: the same styled element for reading and typing. */\nfunction FreeText({ item, page }: { item: TextItem; page: PageContextValue }) {\n const { painted } = useChromePaint();\n // On the engine's text plate (the box inset by its padding), laid out at a legible size.\n const box = freeTextBoxOf(item, page.transform, painted.textOutline);\n const ref = useTextBoxEditor(item, box.scale);\n return <div ref={ref} suppressContentEditableWarning style={box.style} />;\n}\n\n/** What `useRichTextEditor()` gives the element you draw a text box with. */\nexport interface RichTextEditor {\n /** Put it on your element: it becomes the editor. */\n ref: (element: HTMLElement | null) => void;\n /**\n * The box's body style as CSS (font, size, color and alignment), filling the element's parent\n * at a legible size: draw the box's frame on the parent. While typing it takes the pointer too.\n */\n style: React.CSSProperties;\n /** True while someone types in the box. */\n editing: boolean;\n}\n\nconst NO_STYLE: React.CSSProperties = {};\n\n/**\n * Make your own element the editor of a text box you draw yourself (a\n * renderer for free text): it draws the runs, turns typing back into runs,\n * keeps the caret when the style changes, and handles pasting, input methods\n * and the format shortcuts. The formatting calls (`text.toggleFormat`,\n * `selection.update`) work on it as they do on the built-in one.\n */\nexport function useRichTextEditor(annotation: Annotation): RichTextEditor {\n const page = usePage();\n const zoom = page.transform.zoom;\n const rotation = page.transform.rotation;\n // Saved and idle too: your element draws its text, no engine picture does.\n const item = useOptionalSelector(\n AnnotationHostToken,\n (anno) => anno.getTextItem(annotation.ref, { zoom, rotation }),\n null,\n );\n // Pixels per point where the element is: inside a scaled look, at the\n // annotation's 100% size; the look's scale does the rest.\n const scale = textBoxEditorScaleOf(item, page.transform, React.useContext(LookScaleContext));\n const own = React.useMemo(() => (item ? ownTextBoxOf(item, scale) : null), [item, scale]);\n const ref = useTextBoxEditor(item, own?.scale ?? scale);\n return { ref, style: own?.style ?? NO_STYLE, editing: item?.editing ?? false };\n}\n\n// ── renderers that take the pointer ──────────────────────────────────────────\n\n/**\n * Register the behaviors this layer's `interactive` renderers need, through\n * `@embedpdf/web`'s `registerRendererBehaviors`: counted per capability and\n * entry, since the layer mounts once per page. Entry identity is the key,\n * hence the \"define entries outside render\" rule on {@link AnnotationRenderer}.\n * Once they are registered the layer draws again: its drawings ask them.\n */\nfunction useRendererBehaviors(\n anno: Parameters<typeof registerRendererBehaviors<Annotation>>[0],\n activeToolId: () => string,\n renderers?: AnnotationRenderer[],\n): void {\n const toolRef = useRef(activeToolId);\n toolRef.current = activeToolId;\n const [, setRegistrations] = useState(0);\n useEffect(() => {\n if (!renderers) return;\n const release = registerRendererBehaviors(anno, renderers, () => toolRef.current());\n setRegistrations((count) => count + 1);\n return release;\n }, [anno, renderers]);\n}\n\n/**\n * Draws a page's annotations, the selection's outline and handles, the tool's\n * preview and the text boxes being typed in. Put it above the rendered page:\n * while it's there, the render layer leaves the annotations out of the\n * page's picture.\n */\nexport function AnnotationLayer({ renderers, components }: AnnotationLayerProps = {}) {\n const page = usePage();\n const anno = useCapability(AnnotationHostToken);\n // The active tool decides which interactive renderers take the pointer, so\n // a tool change repaints the layer (`interactive` functions read it live).\n useOptionalSelector(InteractionToken, (interaction) => interaction.getActiveToolId(), '');\n const interaction = useOptionalCapability(InteractionToken);\n // The page's view env (relative zoom + total display rotation) projects\n // screen-anchored (`noZoom`/`noRotate`) annotations to their effective\n // footprint inside the plugin: no flag logic lives in the framework.\n // `transform.zoom` (not `viewScale`): 1 = the page's physical 100%.\n const viewZoom = page.transform.zoom;\n const viewRotation = page.transform.rotation;\n const items = useSelector(\n AnnotationHostToken,\n (annotation) => annotation.listPageItems(page.ref, { zoom: viewZoom, rotation: viewRotation }),\n shallowArray,\n );\n const texts = useSelector(\n AnnotationHostToken,\n (annotation) => annotation.listTextItems(page.ref, { zoom: viewZoom, rotation: viewRotation }),\n shallowArray,\n );\n // `null` until the page's first pictures arrive.\n const [urls, setUrls] = useState<Record<string, AppearanceUrl> | null>(null);\n // The pictures shown stay valid until the next ones are shown.\n const [shown] = useState(createShownUrls);\n useEffect(() => () => shown.release(), [shown]);\n useRendererBehaviors(anno, () => (interaction?.getActiveToolId() as string) ?? '', renderers);\n usePaintsPagePart(page.ref, 'annotations');\n // Entry identity keys the behavior registration, so an inline `renderers`\n // array registers again on every render. Detect it once: a fresh array\n // whose entries are the previous ones.\n const previousRenderers = useRef(renderers);\n if (\n renderers &&\n previousRenderers.current &&\n renderers !== previousRenderers.current &&\n shallowArray(renderers, previousRenderers.current)\n ) {\n devWarn(\n 'annotation-renderers-inline',\n '<AnnotationLayer renderers> was given a new array with the same entries — define it ' +\n 'outside render (module scope or useMemo), because entry identity keys the behavior registration.',\n );\n }\n previousRenderers.current = renderers;\n\n // Baked annotations render from engine rasters: fetch again when the\n // page's baked set or an /AP version changes (a freshly placed stamp, a\n // resize whose re-bake resolved), and at appearance-scale crossings. A move\n // or a turn leaves the epoch as it is (the blit repositions the same\n // pixels), and live gestures don't touch it either: no mid-drag fetches.\n const bakedKey = useSelector(AnnotationHostToken, (annotation) =>\n annotation.getAppearanceEpoch(page.ref),\n );\n // The appearance scale follows the document's render policy: zoom ticks\n // inside an appearance-lattice rung re-bake nothing; crossing 1→2 re-bakes\n // once. Without the render plugin, only this session's pictures load.\n const bakeScale = useOptionalSelector(\n RenderToken,\n (render) => render.getAppearanceScale(page.transform.renderScale),\n page.transform.renderScale,\n );\n\n useEffect(\n () =>\n loadAppearanceUrls(\n shown,\n (signal) => anno.renderAppearances(page.ref, bakeScale, signal),\n annotationKey,\n setUrls,\n ),\n [shown, anno, page.ref, bakeScale, bakedKey],\n );\n\n /** The text box being typed in, by key. */\n const editingKey = editingTextKeyOf(texts, annotationKey);\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((item) => {\n // The default look, inside the item's frame: the engine's raster where\n // the core places it (following a move as it happens), or the scene.\n const state = item.annotation?.appearanceState ?? null;\n const shows = pictureOrPainting({\n pending: item.source !== 'baked',\n picture: urls && shownAppearance(urls, item.id, state),\n version: item.pictureVersion ?? 0,\n loaded: urls !== null,\n paint: () => (hasLiveDrawing(item) ? item : null),\n });\n const native: React.ReactNode =\n shows?.kind === 'painting' ? (\n // shapes, cloudy, markup: all painted via scene()\n <Shape item={item} />\n ) : shows?.kind === 'picture' && item.raster ? (\n <BakedImage url={shows.picture.url} box={rasterInFrame(item.raster, item.frame)} />\n ) : null;\n const framed = (\n content: React.ReactNode,\n options?: { interactive?: boolean; inert?: boolean },\n ) => (\n <AnnotationFrame key={item.id} item={item} page={page} {...options}>\n {content}\n </AnnotationFrame>\n );\n const annotation = item.annotation;\n if (!annotation) return framed(native);\n /** Your look in the frame: drawn at the annotation's 100% size and scaled with the page, unless it opts out. */\n const look = (\n entry: Extract<AnnotationRenderer, { for: unknown }>,\n interactive: boolean,\n ): React.ReactNode => {\n const pixels = frameInPixels(item.frame, page.transform);\n const scaled = entry.scale !== false;\n const Look = entry.component;\n const drawn = (\n <Look\n annotation={annotation}\n frame={lookFrameOf(pixels, scaled)}\n native={native}\n appearance={urls && bakedAppearanceOf(urls, item.id, state)}\n hovered={item.hovered ?? false}\n selected={item.selected}\n interactive={interactive}\n />\n );\n if (!scaled) return drawn;\n return (\n <div\n style={{\n position: 'absolute',\n left: 0,\n top: 0,\n width: pixels.design.width,\n height: pixels.design.height,\n transform: `scale(${pixels.scale})`,\n transformOrigin: '0 0',\n }}\n >\n <LookScaleContext.Provider value={pixels.scale}>{drawn}</LookScaleContext.Provider>\n </div>\n );\n };\n\n // Ownership beats looks: an engaged behavior's renderer is\n // authoritative (form fill controls own their DOM); `for` rules apply\n // only to what the layer owns, and draw without the pointer. While its\n // text box is typed in, a look's editor (`useRichTextEditor`) takes\n // the keys: an inert subtree can't.\n const typing = editingKey !== null && annotationKey(annotation.ref) === editingKey;\n const drawing = annotationDrawingOf(annotation, anno, renderers, typing);\n switch (drawing.kind) {\n case 'owned': {\n // Its controls place themselves in the layer; the native drawing keeps its frame.\n const Owner = drawing.entry.component;\n return (\n <Owner\n key={item.id}\n annotation={annotation}\n item={item}\n page={page}\n native={framed(native)}\n hovered={item.hovered ?? false}\n selected={item.selected}\n interactive\n />\n );\n }\n case 'look':\n return framed(look(drawing.entry, drawing.interactive), {\n interactive: drawing.interactive,\n inert: drawing.inert,\n });\n case 'native':\n // Inert when an engaged behavior has no renderer of yours: its\n // plugin owns the input (a link's anchor takes the click), and the\n // annotation keeps its own look.\n return framed(native, { inert: drawing.inert });\n }\n })}\n {/* A text box your renderer draws is edited there (`useRichTextEditor`). */}\n {layerTextBoxesOf(texts, items, renderers, annotationKey).map((text) => (\n <FreeText key={text.id} item={text} page={page} />\n ))}\n <ToolGhostImage page={page} />\n <Chrome page={page} components={components} />\n </div>\n );\n}\n\n/**\n * The default file-picker provider: the built-in file dialog (from\n * `@embedpdf/web`), honouring the tool's `accept` filter. This is the adapter\n * fulfilling the plugin's DOM-free port — the dialog lives in the framework\n * layer, never in the plugin.\n */\nexport const filePickerProvider: FilePickerProvider = pickRequestedFile;\n\n/**\n * Install the file-picker provider for the active document — the one port\n * behind every click-then-pick tool (a stamp `'prompt'` source, the file-\n * attachment tool). Call once at a document-scoped spot (not inside\n * `<AnnotationLayer>`, which is per page). Defaults to\n * {@link filePickerProvider}, so a bare `useFilePickerProvider()` makes all of\n * them work out of the box; pass a custom provider (asset library, cloud\n * drive — switch on `req.subtype` / `req.toolId`) or `null` to make\n * click-then-pick tools inert. Cleared on unmount.\n */\nexport function useFilePickerProvider(\n provider: FilePickerProvider | null = filePickerProvider,\n): void {\n const anno = useOptionalCapability(AnnotationToken);\n useEffect(() => {\n if (!anno) return;\n // One port per document: a second caller silently replaces the first.\n return installFilePickerProvider(anno, provider, () =>\n devWarn(\n 'file-picker-provider-twice',\n 'useFilePickerProvider() is called from two mounted components for the same document — ' +\n 'the later one wins. Call it once, at a document-scoped spot.',\n ),\n );\n }, [anno, provider]);\n}\n\nexport function useAnnotation(): AnnotationCapability {\n return useCapability(AnnotationToken);\n}\n\n/** Listen to one annotation event while the component is mounted: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */\nexport function useAnnotationEvent<T>(\n select: (annotation: AnnotationCapability) => EventHook<T>,\n handler: (event: T) => void,\n): void {\n useCapabilityEvent(AnnotationToken, select, handler);\n}\n\nconst NO_ANNOTATIONS: readonly Annotation[] = [];\n\n/**\n * The annotations matching `filter` (some pages, one kind), in drawing order,\n * as the user sees them; the same array while they stay the same. Empty\n * without a document.\n */\nexport function useAnnotationList(filter?: AnnotationFilter): readonly Annotation[] {\n const key = filter\n ? `${(filter.pages ?? [])\n .map((page) => (typeof page === 'number' ? `#${page}` : page.objectNumber))\n .join(',')}|${filter.pages ? 'p' : ''}|${filter.subtype ?? ''}`\n : '';\n // Keyed by value, so an inline filter object never subscribes again.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const stable = React.useMemo(() => filter, [key]);\n return useOptionalSelector(\n AnnotationToken,\n (annotation) => annotation.list(stable),\n NO_ANNOTATIONS,\n shallowArray,\n );\n}\n\nconst NO_DEFAULTS: ToolDefaults = {};\n\n/**\n * A tool's defaults: the fields its next annotation starts with, over the\n * engine's. The component re-renders when they change, so a color picker\n * always shows the current color. Empty without a document.\n */\nexport function useAnnotationDefaults(toolId: string): ToolDefaults {\n return useOptionalSelector(\n AnnotationToken,\n (annotation) => annotation.tools.getDefaults(toolId),\n NO_DEFAULTS,\n );\n}\n\nconst NO_PROPERTIES: AnnotationProperties = { properties: [], values: {}, mixed: [] };\n\n/**\n * What a style panel shows: the selection's properties (`selection.getProperties()`),\n * or, given a tool id, the tool's (`tools.getProperties(id)`). The component\n * re-renders when they change. Empty without a document.\n */\nexport function useAnnotationProperties(toolId?: string): AnnotationProperties {\n return useOptionalSelector(\n AnnotationToken,\n (annotation) =>\n toolId === undefined\n ? annotation.selection.getProperties()\n : annotation.tools.getProperties(toolId),\n NO_PROPERTIES,\n );\n}\n\n/**\n * An anchor for `<Anchored>` that keeps a card or a badge attached to one\n * annotation: its page and the box around what it shows, following a move\n * as it happens. `null` for `null`, or an annotation that isn't here. The\n * component re-renders when the annotation moves, not while people scroll or\n * zoom: a note that keeps its size on screen hands `<Anchored>` its\n * `boundsIn`.\n */\nexport function useAnnotationAnchor(ref: AnnotationRef | null): AnnotationAnchor | null {\n const key = ref ? annotationKey(ref) : null;\n // Keyed by value, so an inline ref never subscribes again.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const stable = React.useMemo(() => ref, [key]);\n return useOptionalSelector(\n AnnotationHostToken,\n (annotation) => (stable ? annotation.getAnnotationAnchor(stable) : null),\n null,\n sameAnnotationAnchor,\n );\n}\n\n// ── Comments (the conversation plane) ────────────────────────────────────────\n\n/**\n * A {@link CommentThread} enriched with its page's live display position —\n * the framework-layer join (`enrichCommentThreads` in `@embedpdf/web`).\n * Identity stays `page` (like every annotation surface); these two fields\n * are presentation, tracking page moves and deletes.\n */\nexport interface CommentThreadView extends CommentThread {\n /** Current 0-based display index of the thread's page; `-1` when the page\n * is no longer in the document (one-frame teardown race on delete). */\n pageIndex: number;\n /** The page's `/PageLabels` label when the PDF declares one (\"iv\", \"A-2\"),\n * else the 1-based position as a string — print it verbatim. */\n pageLabel: string;\n}\n\n/** The comments API: the `comments` part of `useAnnotation()`. Pair it with\n * {@link useCommentThreads} for the threads to show. */\nexport function useComments(): CommentsApi {\n return useCapability(AnnotationToken).comments;\n}\n\nconst EMPTY_PAGES: readonly PageLayout[] = [];\nconst NO_THREADS: readonly CommentThread[] = [];\n\n/**\n * Every comment thread in the document, display-ordered (page position →\n * top of page → creation date) and enriched with `pageIndex`/`pageLabel`.\n * Subscribed to both stores: annotation writes (own, remote, hydration)\n * recompute the threads; page moves/deletes re-run the join. Reference-\n * stable between changes — safe to memo child renders on the array.\n */\nexport function useCommentThreads(): CommentThreadView[] {\n const docId = useDocumentId();\n const threads = useOptionalSelector(\n AnnotationToken,\n (annotation) => annotation.comments.listThreads(),\n NO_THREADS,\n );\n const pages = useKernelValue((kernel) =>\n docId ? kernel.documents.listPages(docId) : EMPTY_PAGES,\n );\n return React.useMemo(() => enrichCommentThreads(threads, pages), [threads, pages]);\n}\n\n/** The enriched thread containing any member ref (root, reply, grouped part,\n * state annotation), or null. */\nexport function useCommentThread(ref: AnnotationRef | null): CommentThreadView | null {\n const views = useCommentThreads();\n const api = useOptionalCapability(AnnotationToken);\n if (ref == null || !api) return null;\n const thread = api.comments.getThread(ref);\n if (!thread) return null;\n return (\n views.find((view) => annotationKey(view.root.ref) === annotationKey(thread.root.ref)) ?? null\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,MAAa,qBAAqB,UAAU,eAAe;;;;;;AAO3D,MAAa,wBAAwB,aAAaA,iBAAe;;;;;;;;;ACqBjE,SAAgB,eAAe,EAAE,UAAU,MAAM,IAAI,YAAY,SAA8B;CAM7F,MAAM,EAAE,cAAc,oBAAoB;CAC1C,MAAM,SAAS,oBACbC,oBACC,eAAe;EACd,MAAM,kBAAkB,WAAW,UAAU,UAAU;EACvD,IAAI,CAAC,iBAAiB,OAAO;EAC7B,MAAM,MAAM,UAAU,QAAQ,gBAAgB,IAAI;EAClD,OAAO,MAAM,WAAW,qBAAqB,GAAG,IAAI;CACtD,GACA,MACA,mBACF;CACA,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,oBAAC,UAAD;EACE,QAAQ;GACN,MAAM,OAAO;GACb,QAAQ,OAAO;GACf,GAAI,OAAO,iBAAiB,EAAE,OAAO,CAAC,OAAO,cAAc,EAAE,IAAI,CAAC;EACpE;EACW;EACN;EAEJ;CACO,CAAA;AAEd;;AAcA,SAAgB,oBAAoB,EAClC,UACA,MAAM,GACN,YAAY,SACe;CAC3B,MAAM,SAAS,oBACbC,oBACC,eAAe,WAAW,MAAM,IAAI,GACrC,MACA,uBACF;CACA,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,oBAAC,UAAD;EAAkB;EAAmB;EAAgB;EAClD,UAAA,SAAS,MAAM;CACR,CAAA;AAEd;;;;;;AAkBA,SAAgB,wBAAwB,EACtC,UACA,MAAM,IACN,YAAY,WACmB;CAC/B,MAAM,WAAW,oBACfA,oBACC,eAAe,WAAW,UAAU,kBAAkB,GACvD,MACA,kBACF;CACA,MAAM,UAAU,uBAAuB,aAAa,SAAS,OAAO,OAAO;CAC3E,IAAI,CAAC,YAAa,CAAC,YAAY,CAAC,QAAQ,SAAU,OAAO;CACzD,OACE,oBAAC,UAAD;EACE,QAAQ;GAAE,MAAM,SAAS;GAAM,QAAQ;IAAE,GAAG,SAAS;IAAI,OAAO;IAAG,QAAQ;GAAE;EAAE;EACpE;EACN;EAEJ,UAAA,WACC,SAAS,QAAQ,IAEjB,qBAAC,OAAD;GACE,OAAO;IACL,eAAe;IACf,YAAY;IACZ,cAAc;IACd,SAAS;IACT,YAAY,aAAa,WAAW;IACpC,UAAU;IACV,YAAY,MAAM,sBAAsB,QAAQ,UAAU;IAC1D,OAAO,MAAM,iBAAiB,QAAQ,KAAK;GAC7C;GAVF,UAAA,CAYG,SAAS,OAAM,GACb;;CAEC,CAAA;AAEd;;;;AC4GA,MAAM,mBAAmBC,QAAM,cAAc,CAAC;;;;;;AAO9C,SAAS,gBAAgB,EACvB,MACA,MACA,cAAc,OACd,QAAQ,OACR,YAOC;CACD,MAAM,MAAM,cAAc,KAAK,OAAO,KAAK,SAAS;CACpD,OACE,oBAAC,OAAD;EACE,GAAK,QAAQ,QAAQ,CAAC;EACtB,OAAO;GACL,UAAU;GACV,MAAM,IAAI;GACV,KAAK,IAAI;GACT,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,WAAW,IAAI;GACf,iBAAiB;GAGjB,cAAc,KAAK;GAEnB,eAAe,cAAc,SAAS;EACxC;EAEC;CACE,CAAA;AAET;;;;;;;;AASA,SAAS,MAAM,EAAE,QAA8B;CAE7C,MAAM,UAAU,aAAa,KAAK,GAAG;CACrC,IAAI,CAAC,SAAS,OAAO;CACrB,OACE,oBAAC,OAAD;EACW;EACT,OAAO;GACL,UAAU;GACV,MAAM;GACN,KAAK;GACL,OAAO;GACP,QAAQ;GACR,UAAU;GACV,eAAe;GAEf,GAAI,KAAK,WAAW,UAAU,EAAE,SAAS,aAAa,KAAK,gBAAgB,EAAG,EAAE,IAAI,CAAC;EACvF;EAEA,UAAA,oBAAC,WAAD,EAAW,QAAQ,YAAY,MAAM,IAAI,GAAG,EAAE,YAAY,YAAY,CAAC,EAAI,CAAA;CACxE,CAAA;AAET;;AAGA,SAAS,WAAW,EAAE,KAAK,OAA4C;CACrE,OACE,oBAAC,OAAD;EACE,KAAK;EACL,KAAI;EACJ,WAAW;EACX,OAAO;GACL,UAAU;GACV,MAAM,IAAI;GACV,KAAK,IAAI;GACT,OAAO,IAAI;GACX,QAAQ,IAAI;GAMZ,UAAU;GACV,WAAW;GACX,eAAe;GAEf,WAAW,IAAI;GACf,iBAAiB;EACnB;CACD,CAAA;AAEL;;;;;;;;;AAUA,SAAS,eAAe,EAAE,QAAoC;CAC5D,MAAM,OAAO,cAAcC,iBAAmB;CAC9C,MAAM,QAAQ,YAAYA,oBAAsB,eAC9C,WAAW,cAAc,KAAK,GAAG,CACnC;CACA,MAAM,QAAQ,YAAYA,oBAAsB,eAAe,WAAW,cAAc,CAAC;CACzF,MAAM,CAAC,KAAK,UAAU,SAAwB,IAAI;CAIlD,MAAM,SAAS,QAAQ,cAAc,MAAM,IAAI,QAAQ,KAAK,UAAU,WAAW,IAAI;CAErF,gBAAgB;EACd,IAAI,CAAC,QAAQ;GACX,OAAO,IAAI;GACX;EACF;EAGA,OAAO,oBAAoB,KAAK,wBAAwB,MAAM,GAAG,MAAM;CACzE,GAAG;EAAC;EAAM;EAAO;CAAM,CAAC;CAExB,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO;CAC3B,MAAM,QAAQ,aAAa,MAAM,KAAK,KAAK,SAAS;CACpD,OACE,oBAAC,OAAD;EACE,KAAK;EACL,KAAI;EACJ,WAAW;EACX,OAAO;GACL,UAAU;GACV,MAAM,MAAM;GACZ,KAAK,MAAM;GACX,OAAO,MAAM;GACb,QAAQ,MAAM;GAGd,UAAU;GACV,WAAW;GACX,eAAe;GACf,SAAS,aAAa,MAAM,OAAO;GACnC,GAAI,MAAM,MAAM;IAAE,WAAW,UAAU,MAAM,IAAI;IAAO,iBAAiB;GAAS,IAAI,CAAC;EACzF;CACD,CAAA;AAEL;;AAKA,SAAS,iBAA6E;CACpF,MAAM,SAAS,uBAAuB,aAAa,SAAS,MAAM;CAClE,MAAM,SAAS,mBAAmB,aAAa,SAAS,MAAM;CAE9D,OAAO;EAAE;EAAQ,SADDD,QAAM,cAAc,sBAAsB,QAAQ,MAAM,GAAG,CAAC,QAAQ,MAAM,CACnE;CAAE;AAC3B;;AAGA,SAAS,cAAc,EACrB,IACA,MACA,UACA,OACA,SAOC;CACD,IAAI,UAAU,UACZ,OAAO,oBAAC,UAAD;EAAQ,IAAI,GAAG;EAAG,IAAI,GAAG;EAAG,GAAG,OAAO;EAAG,aAAa;EAAY;CAAQ,CAAA;CAEnF,OACE,oBAAC,QAAD;EACE,GAAG,GAAG,IAAI,OAAO;EACjB,GAAG,GAAG,IAAI,OAAO;EACjB,OAAO;EACP,QAAQ;EACR,aAAa;EACN;EAEP,GAAK,WAAW,EAAE,WAAW,UAAU,SAAS,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;CACzE,CAAA;AAEL;AAEA,SAAS,OAAO,EACd,MACA,cAIC;CAID,MAAM,QAAQ,KAAK,UAAU;CAC7B,MAAM,WAAW,KAAK,UAAU;CAChC,MAAM,OAAO,KAAK,UAAU;CAC5B,MAAM,QAAQ,YACZC,oBACC,eAAe,WAAW,gBAAgB,KAAK,KAAK,OAAO,UAAU,IAAI,GAC1E,YACF;CACA,MAAM,EAAE,QAAQ,YAAY,eAAe;CAC3C,MAAM,SAAS,YAAY;CAC3B,MAAM,iBAAiB,YAAY;CAEnC,MAAM,SAA4B,CAAC;CAyHnC,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,UAAU;GAAW,eAAe;EAAO;EA1HjF,UAAA,eAAe,OAAO,KAAK,SAAS,CAAC,CAAC,KAAK,MAAM,MAAM;GACjE,QAAQ,KAAK,MAAb;IACE,KAAK;KACH,IAAI,QAAQ;MACV,OAAO,KACL,oBAAC,QAAD;OAEE,IAAI,KAAK;OACT,MAAM,OAAO,QAAQ;OACrB,UAAU,KAAK;OACf,MAAM,KAAK;OACX,QAAQ,KAAK;MACd,GANM,CAMN,CACH;MACA,OAAO;KACT;KACA,OACE,oBAAC,eAAD;MAEE,IAAI,KAAK;MACT,MAAM,OAAO,QAAQ;MACrB,UAAU,KAAK;MACf,OAAO,OAAO,QAAQ;MACtB,OAAO,QAAQ;KAChB,GANM,CAMN;IAEL,KAAK,SACH,OACE,oBAAC,QAAD;KAEE,IAAI,KAAK,KAAK;KACd,IAAI,KAAK,KAAK;KACd,IAAI,KAAK,GAAG;KACZ,IAAI,KAAK,GAAG;KACZ,gBAAe;KACf,OAAO,QAAQ;IAChB,GAPM,CAON;IAEL,KAAK,kBACH,OAAO,oBAAC,WAAD;KAAiB,QAAQ,KAAK;KAAQ,MAAK;KAAO,OAAO,QAAQ;IAAU,GAA7D,CAA6D;IACpF,KAAK,mBACH,OACE,oBAAC,KAAD,EAAA,UACG,KAAK,MAAM,KAAK,MAAM,MACrB,oBAAC,QAAD;KAEE,IAAI,KAAK,KAAK;KACd,IAAI,KAAK,KAAK;KACd,IAAI,KAAK,GAAG;KACZ,IAAI,KAAK,GAAG;KACZ,SAAS,KAAK;KACd,OAAO,QAAQ;IAChB,GAPM,CAON,CACF,EACA,GAZK,CAYL;IAEP,KAAK;KACH,IAAI,gBAAgB;MAClB,OAAO,KACL,oBAAC,gBAAD;OAEE,IAAI,KAAK;OACT,MAAM,KAAK;OACX,MAAM,OAAO,eAAe;OAC5B,UAAU;OACV,QAAQ;MACT,GANM,CAMN,CACH;MACA,OAAO;KACT;KACA,OACE,qBAAC,KAAD,EAAA,UAAA,CACG,OAAO,eAAe,SACrB,oBAAC,QAAD;MACE,IAAI,KAAK,KAAK;MACd,IAAI,KAAK,KAAK;MACd,IAAI,KAAK,GAAG;MACZ,IAAI,KAAK,GAAG;MACZ,aAAa;MACb,OAAO,EAAE,QAAQ,QAAQ,eAAe,OAAO;KAChD,CAAA,GAEH,oBAAC,UAAD;MACE,IAAI,KAAK,GAAG;MACZ,IAAI,KAAK,GAAG;MACZ,GAAG,OAAO,eAAe,OAAO;MAChC,aAAa;MACb,OAAO,QAAQ;KAChB,CAAA,CACA,EAAA,GAlBK,CAkBL;IAIP,KAAK,WACH,OACE,oBAAC,QAAD;KAEE,GAAG,KAAK,IAAI;KACZ,GAAG,KAAK,IAAI;KACZ,OAAO,KAAK,IAAI;KAChB,QAAQ,KAAK,IAAI;KACjB,aAAa;KACb,iBAAgB;KAChB,OAAO,QAAQ;IAChB,GARM,CAQN;IAEL,KAAK,WACH,OACE,oBAAC,QAAD;KAEE,GAAG,KAAK,IAAI;KACZ,GAAG,KAAK,IAAI;KACZ,OAAO,KAAK,IAAI;KAChB,QAAQ,KAAK,IAAI;KACjB,MAAK;KACL,OAAO,QAAQ;IAChB,GAPM,CAON;GAEP;EACF,CAIS;CACA,CAAA,GACJ,OAAO,SAAS,KACf,oBAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EAAI,UAAA;CAAY,CAAA,CAEtF,EAAA,CAAA;AAEN;;;;;;;;AAWA,SAAS,iBACP,MACA,OACuC;CACvC,MAAM,OAAO,cAAcA,iBAAmB;CAC9C,MAAM,CAAC,SAAS,cAAc,SAA6B,IAAI;CAC/D,MAAM,CAAC,YAAY,eAAe,4BAA2C,CAAC;CAE9E,gBACQ,SAAS,OAAO,SAAS,MAAM,MAAM,KAAK,GAChD;EAAC;EAAU;EAAM;EAAS;EAAM;CAAK,CACvC;CACA,sBAAsB,SAAS,OAAO,GAAG,CAAC,QAAQ,CAAC;CACnD,OAAO;AACT;;AAGA,SAAS,SAAS,EAAE,MAAM,QAAoD;CAC5E,MAAM,EAAE,YAAY,eAAe;CAEnC,MAAM,MAAM,cAAc,MAAM,KAAK,WAAW,QAAQ,WAAW;CAEnE,OAAO,oBAAC,OAAD;EAAK,KADA,iBAAiB,MAAM,IAAI,KACpB;EAAG,gCAAA;EAA+B,OAAO,IAAI;CAAQ,CAAA;AAC1E;AAeA,MAAM,WAAgC,CAAC;;;;;;;;AASvC,SAAgB,kBAAkB,YAAwC;CACxE,MAAM,OAAO,QAAQ;CACrB,MAAM,OAAO,KAAK,UAAU;CAC5B,MAAM,WAAW,KAAK,UAAU;CAEhC,MAAM,OAAO,oBACXA,oBACC,SAAS,KAAK,YAAY,WAAW,KAAK;EAAE;EAAM;CAAS,CAAC,GAC7D,IACF;CAGA,MAAM,QAAQ,qBAAqB,MAAM,KAAK,WAAWD,QAAM,WAAW,gBAAgB,CAAC;CAC3F,MAAM,MAAMA,QAAM,cAAe,OAAO,aAAa,MAAM,KAAK,IAAI,MAAO,CAAC,MAAM,KAAK,CAAC;CAExF,OAAO;EAAE,KADG,iBAAiB,MAAM,KAAK,SAAS,KACtC;EAAG,OAAO,KAAK,SAAS;EAAU,SAAS,MAAM,WAAW;CAAM;AAC/E;;;;;;;;AAWA,SAAS,qBACP,MACA,cACA,WACM;CACN,MAAM,UAAU,OAAO,YAAY;CACnC,QAAQ,UAAU;CAClB,MAAM,GAAG,oBAAoB,SAAS,CAAC;CACvC,gBAAgB;EACd,IAAI,CAAC,WAAW;EAChB,MAAM,UAAU,0BAA0B,MAAM,iBAAiB,QAAQ,QAAQ,CAAC;EAClF,kBAAkB,UAAU,QAAQ,CAAC;EACrC,OAAO;CACT,GAAG,CAAC,MAAM,SAAS,CAAC;AACtB;;;;;;;AAQA,SAAgB,gBAAgB,EAAE,WAAW,eAAqC,CAAC,GAAG;CACpF,MAAM,OAAO,QAAQ;CACrB,MAAM,OAAO,cAAcC,iBAAmB;CAG9C,oBAAoB,mBAAmB,gBAAgB,YAAY,gBAAgB,GAAG,EAAE;CACxF,MAAM,cAAc,sBAAsB,gBAAgB;CAK1D,MAAM,WAAW,KAAK,UAAU;CAChC,MAAM,eAAe,KAAK,UAAU;CACpC,MAAM,QAAQ,YACZA,oBACC,eAAe,WAAW,cAAc,KAAK,KAAK;EAAE,MAAM;EAAU,UAAU;CAAa,CAAC,GAC7F,YACF;CACA,MAAM,QAAQ,YACZA,oBACC,eAAe,WAAW,cAAc,KAAK,KAAK;EAAE,MAAM;EAAU,UAAU;CAAa,CAAC,GAC7F,YACF;CAEA,MAAM,CAAC,MAAM,WAAW,SAA+C,IAAI;CAE3E,MAAM,CAAC,SAAS,SAAS,eAAe;CACxC,sBAAsB,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC;CAC9C,qBAAqB,YAAa,aAAa,gBAAgB,KAAgB,IAAI,SAAS;CAC5F,kBAAkB,KAAK,KAAK,aAAa;CAIzC,MAAM,oBAAoB,OAAO,SAAS;CAC1C,IACE,aACA,kBAAkB,WAClB,cAAc,kBAAkB,WAChC,aAAa,WAAW,kBAAkB,OAAO,GAEjD,QACE,+BACA,sLAEF;CAEF,kBAAkB,UAAU;CAO5B,MAAM,WAAW,YAAYA,oBAAsB,eACjD,WAAW,mBAAmB,KAAK,GAAG,CACxC;CAIA,MAAM,YAAY,oBAChB,cACC,WAAW,OAAO,mBAAmB,KAAK,UAAU,WAAW,GAChE,KAAK,UAAU,WACjB;CAEA,gBAEI,mBACE,QACC,WAAW,KAAK,kBAAkB,KAAK,KAAK,WAAW,MAAM,GAC9D,eACA,OACF,GACF;EAAC;EAAO;EAAM,KAAK;EAAK;EAAW;CAAQ,CAC7C;;CAGA,MAAM,aAAa,iBAAiB,OAAO,aAAa;CAExD,OACE,qBAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EAApE,UAAA;GACG,MAAM,KAAK,SAAS;IAGnB,MAAM,QAAQ,KAAK,YAAY,mBAAmB;IAClD,MAAM,QAAQ,kBAAkB;KAC9B,SAAS,KAAK,WAAW;KACzB,SAAS,QAAQ,gBAAgB,MAAM,KAAK,IAAI,KAAK;KACrD,SAAS,KAAK,kBAAkB;KAChC,QAAQ,SAAS;KACjB,aAAc,eAAe,IAAI,IAAI,OAAO;IAC9C,CAAC;IACD,MAAM,SACJ,OAAO,SAAS,aAEd,oBAAC,OAAD,EAAa,KAAO,CAAA,IAClB,OAAO,SAAS,aAAa,KAAK,SACpC,oBAAC,YAAD;KAAY,KAAK,MAAM,QAAQ;KAAK,KAAK,cAAc,KAAK,QAAQ,KAAK,KAAK;IAAI,CAAA,IAChF;IACN,MAAM,UACJ,SACA,YAEA,oBAAC,iBAAD;KAAqC;KAAY;KAAM,GAAI;KACxD,UAAA;IACc,GAFK,KAAK,EAEV;IAEnB,MAAM,aAAa,KAAK;IACxB,IAAI,CAAC,YAAY,OAAO,OAAO,MAAM;;IAErC,MAAM,QACJ,OACA,gBACoB;KACpB,MAAM,SAAS,cAAc,KAAK,OAAO,KAAK,SAAS;KACvD,MAAM,SAAS,MAAM,UAAU;KAC/B,MAAM,OAAO,MAAM;KACnB,MAAM,QACJ,oBAAC,MAAD;MACc;MACZ,OAAO,YAAY,QAAQ,MAAM;MACzB;MACR,YAAY,QAAQ,kBAAkB,MAAM,KAAK,IAAI,KAAK;MAC1D,SAAS,KAAK,WAAW;MACzB,UAAU,KAAK;MACF;KACd,CAAA;KAEH,IAAI,CAAC,QAAQ,OAAO;KACpB,OACE,oBAAC,OAAD;MACE,OAAO;OACL,UAAU;OACV,MAAM;OACN,KAAK;OACL,OAAO,OAAO,OAAO;OACrB,QAAQ,OAAO,OAAO;OACtB,WAAW,SAAS,OAAO,MAAM;OACjC,iBAAiB;MACnB;MAEA,UAAA,oBAAC,iBAAiB,UAAlB;OAA2B,OAAO,OAAO;OAAQ,UAAA;MAAiC,CAAA;KAC/E,CAAA;IAET;IAOA,MAAM,SAAS,eAAe,QAAQ,cAAc,WAAW,GAAG,MAAM;IACxE,MAAM,UAAU,oBAAoB,YAAY,MAAM,WAAW,MAAM;IACvE,QAAQ,QAAQ,MAAhB;KACE,KAAK,SAAS;MAEZ,MAAM,QAAQ,QAAQ,MAAM;MAC5B,OACE,oBAAC,OAAD;OAEc;OACN;OACA;OACN,QAAQ,OAAO,MAAM;OACrB,SAAS,KAAK,WAAW;OACzB,UAAU,KAAK;OACf,aAAA;MACD,GARM,KAAK,EAQX;KAEL;KACA,KAAK,QACH,OAAO,OAAO,KAAK,QAAQ,OAAO,QAAQ,WAAW,GAAG;MACtD,aAAa,QAAQ;MACrB,OAAO,QAAQ;KACjB,CAAC;KACH,KAAK,UAIH,OAAO,OAAO,QAAQ,EAAE,OAAO,QAAQ,MAAM,CAAC;IAClD;GACF,CAAC;GAEA,iBAAiB,OAAO,OAAO,WAAW,aAAa,CAAC,CAAC,KAAK,SAC7D,oBAAC,UAAD;IAAwB,MAAM;IAAY;GAAO,GAAlC,KAAK,EAA6B,CAClD;GACD,oBAAC,gBAAD,EAAsB,KAAO,CAAA;GAC7B,oBAAC,QAAD;IAAc;IAAkB;GAAa,CAAA;EAC1C;;AAET;;;;;;;AAQA,MAAa,qBAAyC;;;;;;;;;;;AAYtD,SAAgB,sBACd,WAAsC,oBAChC;CACN,MAAM,OAAO,sBAAsB,eAAe;CAClD,gBAAgB;EACd,IAAI,CAAC,MAAM;EAEX,OAAO,0BAA0B,MAAM,gBACrC,QACE,8BACA,oJAEF,CACF;CACF,GAAG,CAAC,MAAM,QAAQ,CAAC;AACrB;AAEA,SAAgB,gBAAsC;CACpD,OAAO,cAAc,eAAe;AACtC;;AAGA,SAAgB,mBACd,QACA,SACM;CACN,mBAAmB,iBAAiB,QAAQ,OAAO;AACrD;AAEA,MAAM,iBAAwC,CAAC;;;;;;AAO/C,SAAgB,kBAAkB,QAAkD;CAClF,MAAM,MAAM,SACR,IAAI,OAAO,SAAS,CAAC,EAAA,CAClB,KAAK,SAAU,OAAO,SAAS,WAAW,IAAI,SAAS,KAAK,YAAa,CAAC,CAC1E,KAAK,GAAG,EAAE,GAAG,OAAO,QAAQ,MAAM,GAAG,GAAG,OAAO,WAAW,OAC7D;CAGJ,MAAM,SAASD,QAAM,cAAc,QAAQ,CAAC,GAAG,CAAC;CAChD,OAAO,oBACL,kBACC,eAAe,WAAW,KAAK,MAAM,GACtC,gBACA,YACF;AACF;AAEA,MAAM,cAA4B,CAAC;;;;;;AAOnC,SAAgB,sBAAsB,QAA8B;CAClE,OAAO,oBACL,kBACC,eAAe,WAAW,MAAM,YAAY,MAAM,GACnD,WACF;AACF;AAEA,MAAM,gBAAsC;CAAE,YAAY,CAAC;CAAG,QAAQ,CAAC;CAAG,OAAO,CAAC;AAAE;;;;;;AAOpF,SAAgB,wBAAwB,QAAuC;CAC7E,OAAO,oBACL,kBACC,eACC,WAAW,KAAA,IACP,WAAW,UAAU,cAAc,IACnC,WAAW,MAAM,cAAc,MAAM,GAC3C,aACF;AACF;;;;;;;;;AAUA,SAAgB,oBAAoB,KAAoD;CACtF,MAAM,MAAM,MAAM,cAAc,GAAG,IAAI;CAGvC,MAAM,SAASA,QAAM,cAAc,KAAK,CAAC,GAAG,CAAC;CAC7C,OAAO,oBACLC,oBACC,eAAgB,SAAS,WAAW,oBAAoB,MAAM,IAAI,MACnE,MACA,oBACF;AACF;;;AAqBA,SAAgB,cAA2B;CACzC,OAAO,cAAc,eAAe,CAAC,CAAC;AACxC;AAEA,MAAM,cAAqC,CAAC;AAC5C,MAAM,aAAuC,CAAC;;;;;;;;AAS9C,SAAgB,oBAAyC;CACvD,MAAM,QAAQ,cAAc;CAC5B,MAAM,UAAU,oBACd,kBACC,eAAe,WAAW,SAAS,YAAY,GAChD,UACF;CACA,MAAM,QAAQ,gBAAgB,WAC5B,QAAQ,OAAO,UAAU,UAAU,KAAK,IAAI,WAC9C;CACA,OAAOD,QAAM,cAAc,qBAAqB,SAAS,KAAK,GAAG,CAAC,SAAS,KAAK,CAAC;AACnF;;;AAIA,SAAgB,iBAAiB,KAAqD;CACpF,MAAM,QAAQ,kBAAkB;CAChC,MAAM,MAAM,sBAAsB,eAAe;CACjD,IAAI,OAAO,QAAQ,CAAC,KAAK,OAAO;CAChC,MAAM,SAAS,IAAI,SAAS,UAAU,GAAG;CACzC,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,MAAM,MAAM,SAAS,cAAc,KAAK,KAAK,GAAG,MAAM,cAAc,OAAO,KAAK,GAAG,CAAC,KAAK;AAE7F"}
@@ -0,0 +1,305 @@
1
+ import { n as StateHook, t as SettingsHook } from "./state-0K1I5cM4.js";
2
+ import { r as AnchoredPlacement } from "./anchored-DeX95xSd.js";
3
+ import { c as PageContextValue } from "./runtime-V3MVMb91.js";
4
+ import { EventHook } from "@embedpdf/core";
5
+ import * as React$1 from "react";
6
+ import { Annotation, AnnotationAnchor, AnnotationCapability, AnnotationFilter, AnnotationProperties, AnnotationRef, CommentThread, CommentsApi, FilePickerProvider, HandleRole, ToolDefaults } from "@embedpdf/plugin-annotation";
7
+ import { AnnotationFlags, CreationDraftAnchor, CreationDraftAnchor as CreationDraftAnchor$1, FieldValues, LineEnding, LineEndings, Point, RenderItem, RenderItem as RenderItem$1, RotationAnchor, Style, TextAlign, TextStyle } from "@embedpdf/core-annotation";
8
+ //#region src/annotation-hooks.d.ts
9
+ /**
10
+ * The annotation state: `status` (`'loading'` until every annotation is in,
11
+ * then `'ready'`), the `selected` annotations, the one `hovered` under the
12
+ * pointer and the text box being typed in (`editing`). Re-renders only when a
13
+ * field changes, or the value `select` picks. Empty without a document.
14
+ */
15
+ declare const useAnnotationState: StateHook<{
16
+ status: import("@embedpdf/core").ResourceStatus;
17
+ selected: readonly import("@embedpdf/plugin-annotation").Annotation[];
18
+ hovered: import("@embedpdf/plugin-annotation").Annotation | null;
19
+ editing: import("@embedpdf/plugin-annotation").Annotation | null;
20
+ }>;
21
+ /**
22
+ * The annotation settings (`snap`, `chrome`, `afterCreate`, `tools`), or the
23
+ * value `select` picks. They belong to the plugin, so they read without a
24
+ * document; change them with `useAnnotation().updateSettings()`.
25
+ */
26
+ declare const useAnnotationSettings: SettingsHook<import("@embedpdf/plugin-annotation").AnnotationSettings>;
27
+ //#endregion
28
+ //#region src/annotation-menu.d.ts
29
+ interface AnnotationMenuProps {
30
+ children: React$1.ReactNode;
31
+ /** Gap in screen px between the selection box and the menu (default 15). */
32
+ gap?: number;
33
+ /** Where to place the menu relative to the selection box. Default 'top'. */
34
+ placement?: AnchoredPlacement;
35
+ }
36
+ /**
37
+ * Your own menu next to the selection (one anchor, also for a selection over
38
+ * several pages), clear of the rotation handle. It hides while the selection
39
+ * is dragged, resized or turned. What's in it is yours: build it from
40
+ * `useAnnotation()` and `useAnnotationState()`.
41
+ */
42
+ declare function AnnotationMenu({ children, gap, placement }: AnnotationMenuProps): import("react/jsx-runtime").JSX.Element | null;
43
+ interface AnnotationDraftMenuProps {
44
+ /** Render prop receiving the shape being drawn (`subtype`, `pointCount`,
45
+ * `minPoints`, `canFinish`, …). The verbs are capability calls:
46
+ * `useAnnotation().draft.finish()` and `.draft.cancel()`. */
47
+ children: (anchor: CreationDraftAnchor) => React$1.ReactNode;
48
+ /** Gap in screen px between the draft anchor and the menu (default 8). */
49
+ gap?: number;
50
+ /** Where to place the menu relative to the draft anchor. Default 'top'. */
51
+ placement?: AnchoredPlacement;
52
+ }
53
+ /** Floats over a live multi-click creation draft (polygon, polyline, …). */
54
+ declare function AnnotationDraftMenu({ children, gap, placement }: AnnotationDraftMenuProps): import("react/jsx-runtime").JSX.Element | null;
55
+ interface AnnotationRotationBadgeProps {
56
+ /** Render prop receiving the rotation in progress (`angle`, degrees
57
+ * clockwise, as the commit will apply it). Without it, the badge shows the
58
+ * angle in the `chrome.readout` colors, when `chrome.readout.enabled`. */
59
+ children?: (rotation: RotationAnchor) => React$1.ReactNode;
60
+ /** Gap in screen px between the pointer and the badge (default 16). */
61
+ gap?: number;
62
+ /** Where to place the badge relative to the pointer. Default 'right'. */
63
+ placement?: AnchoredPlacement;
64
+ }
65
+ /**
66
+ * Follows the pointer while a selection is being turned, upright however the
67
+ * page is shown: it floats over the page like the menus, not in it. Shows
68
+ * nothing when no rotation is in progress.
69
+ */
70
+ declare function AnnotationRotationBadge({ children, gap, placement }: AnnotationRotationBadgeProps): import("react/jsx-runtime").JSX.Element | null;
71
+ //#endregion
72
+ //#region src/annotation.d.ts
73
+ /** The box a renderer draws into: the size to draw at, how it's turned, and how it's scaled. */
74
+ interface AnnotationFrame {
75
+ /** Its width in pixels at the annotation's 100% size, before its turn: draw at this. */
76
+ width: number;
77
+ /** Its height in pixels at the annotation's 100% size, before its turn: draw at this. */
78
+ height: number;
79
+ /**
80
+ * How it's turned on screen, degrees clockwise: the page's turn and the
81
+ * annotation's own. 0 is upright; turn your content by `-rotation` to keep
82
+ * it upright.
83
+ */
84
+ rotation: number;
85
+ /**
86
+ * How much the layer scales what you draw, with the page: the zoom, or for
87
+ * an annotation that keeps its size on screen, the zoom up to 1.
88
+ */
89
+ scale: number;
90
+ }
91
+ /**
92
+ * What a renderer's component gets: the annotation, the frame to draw into,
93
+ * and the layer's own drawing of it to keep or wrap. The layer keeps handling
94
+ * the pointer (select, move, resize) unless the renderer is `interactive`.
95
+ */
96
+ interface AnnotationRendererProps {
97
+ /** The annotation, as `get()` returns it. */
98
+ annotation: Annotation;
99
+ /**
100
+ * The box you draw into. The layer places, turns and scales it like the
101
+ * annotation's own drawing, also during a drag, a resize or a turn. Fill it
102
+ * (`width: 100%; height: 100%`) and draw at the annotation's 100% size: your
103
+ * text and borders scale with the page.
104
+ */
105
+ frame: AnnotationFrame;
106
+ /** The layer's own drawing of it, filling the frame. Render it to keep the original look and add to it. */
107
+ native: React$1.ReactNode;
108
+ /** The engine's picture of the annotation as an image (`url`), or `null`. `native` draws it in place. */
109
+ appearance: {
110
+ url: string;
111
+ } | null;
112
+ /** True while the pointer is over it. */
113
+ hovered: boolean;
114
+ /** True while it's selected. */
115
+ selected: boolean;
116
+ /** True when what you draw takes the pointer (see `interactive` on the renderer). */
117
+ interactive: boolean;
118
+ }
119
+ /**
120
+ * What a sibling plugin's renderer gets for the annotations its behavior owns
121
+ * (the form plugin's fill controls). It places its own controls: `item` is the
122
+ * layer's projection of the annotation (its box, style, text and raster box,
123
+ * in page coordinates), and `page.transform.toPixels()` turns those into the
124
+ * layer's pixels.
125
+ */
126
+ interface BehaviorRendererProps {
127
+ annotation: Annotation;
128
+ item: RenderItem;
129
+ page: PageContextValue;
130
+ /** The layer's own drawing of it, where the layer draws it. */
131
+ native: React$1.ReactNode;
132
+ hovered: boolean;
133
+ selected: boolean;
134
+ interactive: boolean;
135
+ }
136
+ /** What an `interactive` function is asked: the annotation, and the active tool. */
137
+ interface AnnotationInteractiveContext {
138
+ annotation: Annotation;
139
+ toolId: string;
140
+ }
141
+ /**
142
+ * One rule: "draw these annotations with this component". `for` gets the
143
+ * annotation with all its fields; the first renderer that matches wins.
144
+ * Without `interactive` the component only draws: the layer keeps handling
145
+ * the pointer. With `interactive` (or a function asked whenever it matters)
146
+ * the component takes the pointer, and the annotation can't be selected or
147
+ * moved while it does.
148
+ *
149
+ * Define the list once, outside your component or in `useMemo`: the layer
150
+ * registers each entry, and a new list every render registers them again.
151
+ *
152
+ * `{ behavior, component }` draws what a sibling plugin's behavior owns (the
153
+ * form plugin's fill controls); the plugin decides when it's engaged.
154
+ */
155
+ type AnnotationRenderer = {
156
+ behavior: string;
157
+ component: React$1.ComponentType<BehaviorRendererProps>;
158
+ } | {
159
+ /** A stable id for the registration (optional; generated). */
160
+ id?: string;
161
+ for: (annotation: Annotation) => boolean;
162
+ component: React$1.ComponentType<AnnotationRendererProps>;
163
+ interactive?: boolean | ((context: AnnotationInteractiveContext) => boolean);
164
+ /**
165
+ * Scale what you draw with the page (the default): you draw at the
166
+ * annotation's 100% size. `false`: you draw at its size on screen, and
167
+ * size things yourself from `frame.scale`.
168
+ */
169
+ scale?: boolean;
170
+ };
171
+ /** What a handle component you draw yourself gets. */
172
+ interface HandleProps {
173
+ /** The handle's center, in pixels on the page. */
174
+ at: Point;
175
+ /** The `size` from the settings, px. */
176
+ size: number;
177
+ /** The selection's rotation (degrees clockwise), so a square handle can turn with it. */
178
+ rotation: number;
179
+ /** A box's `'corner'` or `'side'`, or one `'point'` of a line or a polygon. */
180
+ kind: HandleRole;
181
+ /** True while it's being dragged. */
182
+ active: boolean;
183
+ }
184
+ /** What a rotation handle component gets: a handle's props, and where its stalk starts on the box. */
185
+ interface RotationHandleProps extends Omit<HandleProps, 'kind'> {
186
+ /** Where the stalk starts on the box, in pixels on the page. */
187
+ from: Point;
188
+ }
189
+ /** Your own handles, drawn in place of the layer's. The viewer still decides where they can be grabbed. */
190
+ interface AnnotationLayerComponents {
191
+ Handle?: React$1.ComponentType<HandleProps>;
192
+ RotationHandle?: React$1.ComponentType<RotationHandleProps>;
193
+ }
194
+ interface AnnotationLayerProps {
195
+ /** Your own look for some annotations ({@link AnnotationRenderer}). */
196
+ renderers?: AnnotationRenderer[];
197
+ /** Your own handles and rotation handle. */
198
+ components?: AnnotationLayerComponents;
199
+ }
200
+ /** What `useRichTextEditor()` gives the element you draw a text box with. */
201
+ interface RichTextEditor {
202
+ /** Put it on your element: it becomes the editor. */
203
+ ref: (element: HTMLElement | null) => void;
204
+ /**
205
+ * The box's body style as CSS (font, size, color and alignment), filling the element's parent
206
+ * at a legible size: draw the box's frame on the parent. While typing it takes the pointer too.
207
+ */
208
+ style: React$1.CSSProperties;
209
+ /** True while someone types in the box. */
210
+ editing: boolean;
211
+ }
212
+ /**
213
+ * Make your own element the editor of a text box you draw yourself (a
214
+ * renderer for free text): it draws the runs, turns typing back into runs,
215
+ * keeps the caret when the style changes, and handles pasting, input methods
216
+ * and the format shortcuts. The formatting calls (`text.toggleFormat`,
217
+ * `selection.update`) work on it as they do on the built-in one.
218
+ */
219
+ declare function useRichTextEditor(annotation: Annotation): RichTextEditor;
220
+ /**
221
+ * Draws a page's annotations, the selection's outline and handles, the tool's
222
+ * preview and the text boxes being typed in. Put it above the rendered page:
223
+ * while it's there, the render layer leaves the annotations out of the
224
+ * page's picture.
225
+ */
226
+ declare function AnnotationLayer({ renderers, components }?: AnnotationLayerProps): import("react/jsx-runtime").JSX.Element;
227
+ /**
228
+ * The default file-picker provider: the built-in file dialog (from
229
+ * `@embedpdf/web`), honouring the tool's `accept` filter. This is the adapter
230
+ * fulfilling the plugin's DOM-free port — the dialog lives in the framework
231
+ * layer, never in the plugin.
232
+ */
233
+ declare const filePickerProvider: FilePickerProvider;
234
+ /**
235
+ * Install the file-picker provider for the active document — the one port
236
+ * behind every click-then-pick tool (a stamp `'prompt'` source, the file-
237
+ * attachment tool). Call once at a document-scoped spot (not inside
238
+ * `<AnnotationLayer>`, which is per page). Defaults to
239
+ * {@link filePickerProvider}, so a bare `useFilePickerProvider()` makes all of
240
+ * them work out of the box; pass a custom provider (asset library, cloud
241
+ * drive — switch on `req.subtype` / `req.toolId`) or `null` to make
242
+ * click-then-pick tools inert. Cleared on unmount.
243
+ */
244
+ declare function useFilePickerProvider(provider?: FilePickerProvider | null): void;
245
+ declare function useAnnotation(): AnnotationCapability;
246
+ /** Listen to one annotation event while the component is mounted: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */
247
+ declare function useAnnotationEvent<T>(select: (annotation: AnnotationCapability) => EventHook<T>, handler: (event: T) => void): void;
248
+ /**
249
+ * The annotations matching `filter` (some pages, one kind), in drawing order,
250
+ * as the user sees them; the same array while they stay the same. Empty
251
+ * without a document.
252
+ */
253
+ declare function useAnnotationList(filter?: AnnotationFilter): readonly Annotation[];
254
+ /**
255
+ * A tool's defaults: the fields its next annotation starts with, over the
256
+ * engine's. The component re-renders when they change, so a color picker
257
+ * always shows the current color. Empty without a document.
258
+ */
259
+ declare function useAnnotationDefaults(toolId: string): ToolDefaults;
260
+ /**
261
+ * What a style panel shows: the selection's properties (`selection.getProperties()`),
262
+ * or, given a tool id, the tool's (`tools.getProperties(id)`). The component
263
+ * re-renders when they change. Empty without a document.
264
+ */
265
+ declare function useAnnotationProperties(toolId?: string): AnnotationProperties;
266
+ /**
267
+ * An anchor for `<Anchored>` that keeps a card or a badge attached to one
268
+ * annotation: its page and the box around what it shows, following a move
269
+ * as it happens. `null` for `null`, or an annotation that isn't here. The
270
+ * component re-renders when the annotation moves, not while people scroll or
271
+ * zoom: a note that keeps its size on screen hands `<Anchored>` its
272
+ * `boundsIn`.
273
+ */
274
+ declare function useAnnotationAnchor(ref: AnnotationRef | null): AnnotationAnchor | null;
275
+ /**
276
+ * A {@link CommentThread} enriched with its page's live display position —
277
+ * the framework-layer join (`enrichCommentThreads` in `@embedpdf/web`).
278
+ * Identity stays `page` (like every annotation surface); these two fields
279
+ * are presentation, tracking page moves and deletes.
280
+ */
281
+ interface CommentThreadView extends CommentThread {
282
+ /** Current 0-based display index of the thread's page; `-1` when the page
283
+ * is no longer in the document (one-frame teardown race on delete). */
284
+ pageIndex: number;
285
+ /** The page's `/PageLabels` label when the PDF declares one ("iv", "A-2"),
286
+ * else the 1-based position as a string — print it verbatim. */
287
+ pageLabel: string;
288
+ }
289
+ /** The comments API: the `comments` part of `useAnnotation()`. Pair it with
290
+ * {@link useCommentThreads} for the threads to show. */
291
+ declare function useComments(): CommentsApi;
292
+ /**
293
+ * Every comment thread in the document, display-ordered (page position →
294
+ * top of page → creation date) and enriched with `pageIndex`/`pageLabel`.
295
+ * Subscribed to both stores: annotation writes (own, remote, hydration)
296
+ * recompute the threads; page moves/deletes re-run the join. Reference-
297
+ * stable between changes — safe to memo child renders on the array.
298
+ */
299
+ declare function useCommentThreads(): CommentThreadView[];
300
+ /** The enriched thread containing any member ref (root, reply, grouped part,
301
+ * state annotation), or null. */
302
+ declare function useCommentThread(ref: AnnotationRef | null): CommentThreadView | null;
303
+ //#endregion
304
+ export { useCommentThreads as A, useAnnotationSettings as B, useAnnotation as C, useAnnotationList as D, useAnnotationEvent as E, AnnotationDraftMenuProps as F, AnnotationMenu as I, AnnotationMenuProps as L, useFilePickerProvider as M, useRichTextEditor as N, useAnnotationProperties as O, AnnotationDraftMenu as P, AnnotationRotationBadge as R, filePickerProvider as S, useAnnotationDefaults as T, useAnnotationState as V, RichTextEditor as _, AnnotationLayerComponents as a, TextAlign as b, AnnotationRendererProps as c, CreationDraftAnchor$1 as d, FieldValues as f, RenderItem$1 as g, LineEndings as h, AnnotationLayer as i, useComments as j, useCommentThread as k, BehaviorRendererProps as l, LineEnding as m, AnnotationFrame as n, AnnotationLayerProps as o, HandleProps as p, AnnotationInteractiveContext as r, AnnotationRenderer as s, AnnotationFlags as t, CommentThreadView as u, RotationHandleProps as v, useAnnotationAnchor as w, TextStyle as x, Style as y, AnnotationRotationBadgeProps as z };
305
+ //# sourceMappingURL=annotation-DhEfs0pH.d.ts.map