@embedpdf/react 3.0.0-next.13 → 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 (232) hide show
  1. package/dist/AnnotationList-CkijRHet-HEFNUIZe.d.cts +877 -0
  2. package/dist/AnnotationList-CkijRHet-HEFNUIZe.d.ts +877 -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-B48UT2ln.d.ts +302 -0
  18. package/dist/annotation-C1ttM8Wj.js +708 -0
  19. package/dist/annotation-C1ttM8Wj.js.map +1 -0
  20. package/dist/annotation-C9dVwo9b.d.cts +302 -0
  21. package/dist/annotation-Dex5EBda.cjs +830 -0
  22. package/dist/annotation-Dex5EBda.cjs.map +1 -0
  23. package/dist/annotation.cjs +20 -783
  24. package/dist/annotation.d.cts +2 -2
  25. package/dist/annotation.d.ts +2 -2
  26. package/dist/annotation.js +2 -768
  27. package/dist/commands.cjs +68 -28
  28. package/dist/commands.cjs.map +1 -1
  29. package/dist/commands.d.cts +37 -10
  30. package/dist/commands.d.ts +37 -10
  31. package/dist/commands.js +68 -31
  32. package/dist/commands.js.map +1 -1
  33. package/dist/form-55izw0jS.js +511 -0
  34. package/dist/form-55izw0jS.js.map +1 -0
  35. package/dist/form-BNqQfGGH.cjs +548 -0
  36. package/dist/form-BNqQfGGH.cjs.map +1 -0
  37. package/dist/form.cjs +5 -5
  38. package/dist/form.d.cts +32 -25
  39. package/dist/form.d.ts +32 -25
  40. package/dist/form.js +2 -3
  41. package/dist/history.cjs +38 -0
  42. package/dist/history.cjs.map +1 -0
  43. package/dist/history.d.cts +27 -0
  44. package/dist/history.d.ts +27 -0
  45. package/dist/history.js +27 -0
  46. package/dist/history.js.map +1 -0
  47. package/dist/i18n.cjs +26 -30
  48. package/dist/i18n.cjs.map +1 -1
  49. package/dist/i18n.d.cts +24 -21
  50. package/dist/i18n.d.ts +24 -21
  51. package/dist/i18n.js +24 -31
  52. package/dist/i18n.js.map +1 -1
  53. package/dist/index.cjs +213 -57
  54. package/dist/index.d.cts +32 -31
  55. package/dist/index.d.ts +32 -31
  56. package/dist/index.js +33 -29
  57. package/dist/inert-CmBEbKCn.cjs +19 -0
  58. package/dist/inert-CmBEbKCn.cjs.map +1 -0
  59. package/dist/inert-D8fkennb.js +14 -0
  60. package/dist/inert-D8fkennb.js.map +1 -0
  61. package/dist/interaction.cjs +48 -102
  62. package/dist/interaction.cjs.map +1 -1
  63. package/dist/interaction.d.cts +23 -32
  64. package/dist/interaction.d.ts +23 -32
  65. package/dist/interaction.js +33 -102
  66. package/dist/interaction.js.map +1 -1
  67. package/dist/link.cjs +65 -104
  68. package/dist/link.cjs.map +1 -1
  69. package/dist/link.d.cts +21 -16
  70. package/dist/link.d.ts +22 -17
  71. package/dist/link.js +67 -107
  72. package/dist/link.js.map +1 -1
  73. package/dist/measurement.cjs +56 -0
  74. package/dist/measurement.cjs.map +1 -0
  75. package/dist/measurement.d.cts +38 -0
  76. package/dist/measurement.d.ts +38 -0
  77. package/dist/measurement.js +42 -0
  78. package/dist/measurement.js.map +1 -0
  79. package/dist/metadata.cjs +20 -7
  80. package/dist/metadata.cjs.map +1 -1
  81. package/dist/metadata.d.cts +22 -7
  82. package/dist/metadata.d.ts +22 -7
  83. package/dist/metadata.js +20 -10
  84. package/dist/metadata.js.map +1 -1
  85. package/dist/page-edit.cjs +7 -3
  86. package/dist/page-edit.cjs.map +1 -1
  87. package/dist/page-edit.d.cts +6 -2
  88. package/dist/page-edit.d.ts +6 -2
  89. package/dist/page-edit.js +7 -4
  90. package/dist/page-edit.js.map +1 -1
  91. package/dist/page-layers-Bkaaz8Zf.js +26 -0
  92. package/dist/page-layers-Bkaaz8Zf.js.map +1 -0
  93. package/dist/page-layers-BloZDoOV.cjs +37 -0
  94. package/dist/page-layers-BloZDoOV.cjs.map +1 -0
  95. package/dist/page-view.cjs +89 -82
  96. package/dist/page-view.cjs.map +1 -1
  97. package/dist/page-view.d.cts +14 -7
  98. package/dist/page-view.d.ts +18 -11
  99. package/dist/page-view.js +86 -81
  100. package/dist/page-view.js.map +1 -1
  101. package/dist/redaction.cjs +30 -15
  102. package/dist/redaction.cjs.map +1 -1
  103. package/dist/redaction.d.cts +27 -9
  104. package/dist/redaction.d.ts +27 -9
  105. package/dist/redaction.js +29 -18
  106. package/dist/redaction.js.map +1 -1
  107. package/dist/render.cjs +71 -46
  108. package/dist/render.cjs.map +1 -1
  109. package/dist/render.d.cts +17 -5
  110. package/dist/render.d.ts +17 -5
  111. package/dist/render.js +70 -49
  112. package/dist/render.js.map +1 -1
  113. package/dist/runtime-B6xcPsEb.js +398 -0
  114. package/dist/runtime-B6xcPsEb.js.map +1 -0
  115. package/dist/runtime-DBEBlpQV.d.cts +237 -0
  116. package/dist/runtime-V3MVMb91.d.ts +237 -0
  117. package/dist/runtime-fzpGv78v.cjs +555 -0
  118. package/dist/runtime-fzpGv78v.cjs.map +1 -0
  119. package/dist/runtime.cjs +45 -324
  120. package/dist/runtime.d.cts +2 -2
  121. package/dist/runtime.d.ts +2 -2
  122. package/dist/runtime.js +2 -306
  123. package/dist/search.cjs +81 -50
  124. package/dist/search.cjs.map +1 -1
  125. package/dist/search.d.cts +36 -24
  126. package/dist/search.d.ts +36 -24
  127. package/dist/search.js +81 -53
  128. package/dist/search.js.map +1 -1
  129. package/dist/selection.cjs +105 -108
  130. package/dist/selection.cjs.map +1 -1
  131. package/dist/selection.d.cts +54 -26
  132. package/dist/selection.d.ts +56 -28
  133. package/dist/selection.js +103 -110
  134. package/dist/selection.js.map +1 -1
  135. package/dist/shell.cjs +36 -21
  136. package/dist/shell.cjs.map +1 -1
  137. package/dist/shell.d.cts +32 -17
  138. package/dist/shell.d.ts +32 -17
  139. package/dist/shell.js +36 -24
  140. package/dist/shell.js.map +1 -1
  141. package/dist/signature.cjs +29 -48
  142. package/dist/signature.cjs.map +1 -1
  143. package/dist/signature.d.cts +26 -26
  144. package/dist/signature.d.ts +26 -26
  145. package/dist/signature.js +30 -48
  146. package/dist/signature.js.map +1 -1
  147. package/dist/stage-BIG6aeVd.cjs +369 -0
  148. package/dist/stage-BIG6aeVd.cjs.map +1 -0
  149. package/dist/stage-ByFPD-Fv.d.cts +117 -0
  150. package/dist/stage-DaboaheR.d.ts +117 -0
  151. package/dist/stage-DoVekb83.js +302 -0
  152. package/dist/stage-DoVekb83.js.map +1 -0
  153. package/dist/stage-scope-CQgCuf1w.cjs +46 -0
  154. package/dist/stage-scope-CQgCuf1w.cjs.map +1 -0
  155. package/dist/stage-scope-D7ZeNduT.js +23 -0
  156. package/dist/stage-scope-D7ZeNduT.js.map +1 -0
  157. package/dist/stage.cjs +12 -235
  158. package/dist/stage.d.cts +2 -116
  159. package/dist/stage.d.ts +2 -116
  160. package/dist/stage.js +3 -228
  161. package/dist/stamp.cjs +41 -35
  162. package/dist/stamp.cjs.map +1 -1
  163. package/dist/stamp.d.cts +25 -18
  164. package/dist/stamp.d.ts +25 -18
  165. package/dist/stamp.js +40 -37
  166. package/dist/stamp.js.map +1 -1
  167. package/dist/state-0K1I5cM4.d.cts +29 -0
  168. package/dist/state-0K1I5cM4.d.ts +29 -0
  169. package/dist/state-CbgxhwLA.js +62 -0
  170. package/dist/state-CbgxhwLA.js.map +1 -0
  171. package/dist/state-CsfZy_Eq.cjs +73 -0
  172. package/dist/state-CsfZy_Eq.cjs.map +1 -0
  173. package/dist/svg-shapes-Dm1yTR1b.js +40 -0
  174. package/dist/svg-shapes-Dm1yTR1b.js.map +1 -0
  175. package/dist/svg-shapes-zo0GNkc9.cjs +53 -0
  176. package/dist/svg-shapes-zo0GNkc9.cjs.map +1 -0
  177. package/dist/toolbar.cjs +297 -295
  178. package/dist/toolbar.cjs.map +1 -1
  179. package/dist/toolbar.d.cts +58 -68
  180. package/dist/toolbar.d.ts +67 -77
  181. package/dist/toolbar.js +271 -293
  182. package/dist/toolbar.js.map +1 -1
  183. package/dist/view-manager.cjs +34 -0
  184. package/dist/view-manager.cjs.map +1 -0
  185. package/dist/view-manager.d.cts +21 -0
  186. package/dist/view-manager.d.ts +21 -0
  187. package/dist/view-manager.js +23 -0
  188. package/dist/view-manager.js.map +1 -0
  189. package/package.json +41 -38
  190. package/dist/AnnotationListSnapshot-D3mFut1e-C_GMpK25.d.cts +0 -546
  191. package/dist/AnnotationListSnapshot-D3mFut1e-C_GMpK25.d.ts +0 -546
  192. package/dist/annotation-BCED_p9H.d.cts +0 -160
  193. package/dist/annotation-anchors-CetwM1g7.js +0 -15
  194. package/dist/annotation-anchors-CetwM1g7.js.map +0 -1
  195. package/dist/annotation-anchors-DuYRBJLl.cjs +0 -26
  196. package/dist/annotation-anchors-DuYRBJLl.cjs.map +0 -1
  197. package/dist/annotation-hooks-BB5ZhPpf.cjs +0 -16
  198. package/dist/annotation-hooks-BB5ZhPpf.cjs.map +0 -1
  199. package/dist/annotation-hooks-Df8EmzDO.js +0 -11
  200. package/dist/annotation-hooks-Df8EmzDO.js.map +0 -1
  201. package/dist/annotation-k38KDlIZ.d.ts +0 -160
  202. package/dist/annotation-menu.cjs +0 -64
  203. package/dist/annotation-menu.cjs.map +0 -1
  204. package/dist/annotation-menu.d.cts +0 -33
  205. package/dist/annotation-menu.d.ts +0 -33
  206. package/dist/annotation-menu.js +0 -48
  207. package/dist/annotation-menu.js.map +0 -1
  208. package/dist/annotation.cjs.map +0 -1
  209. package/dist/annotation.js.map +0 -1
  210. package/dist/form-BVumS7up.cjs +0 -926
  211. package/dist/form-BVumS7up.cjs.map +0 -1
  212. package/dist/form-CK3mp99m.js +0 -895
  213. package/dist/form-CK3mp99m.js.map +0 -1
  214. package/dist/rolldown-runtime-BBjsoOtd.js +0 -27
  215. package/dist/runtime-DE76hlnl.d.ts +0 -216
  216. package/dist/runtime-umHA_xHt.d.cts +0 -216
  217. package/dist/runtime.cjs.map +0 -1
  218. package/dist/runtime.js.map +0 -1
  219. package/dist/scrollbar.cjs +0 -241
  220. package/dist/scrollbar.cjs.map +0 -1
  221. package/dist/scrollbar.d.cts +0 -42
  222. package/dist/scrollbar.d.ts +0 -42
  223. package/dist/scrollbar.js +0 -213
  224. package/dist/scrollbar.js.map +0 -1
  225. package/dist/stage.cjs.map +0 -1
  226. package/dist/stage.js.map +0 -1
  227. package/dist/views.cjs +0 -35
  228. package/dist/views.cjs.map +0 -1
  229. package/dist/views.d.cts +0 -21
  230. package/dist/views.d.ts +0 -21
  231. package/dist/views.js +0 -27
  232. package/dist/views.js.map +0 -1
@@ -1,45 +1,2 @@
1
- import * as React from "react";
2
- import { AnchorTarget, AnchorTarget as AnchorTarget$1, AnchoredPlacement, AnchoredPlacement as AnchoredPlacement$1, ViewProjector, ViewProjector as ViewProjector$1 } from "@embedpdf/web";
3
- //#region src/anchored.d.ts
4
- /**
5
- * What a page surface provides via context: the pure projection snapshot,
6
- * bound to React's reactivity.
7
- */
8
- interface ProjectorBinding {
9
- projector: ViewProjector$1;
10
- /**
11
- * Changes identity exactly when projection may have changed for
12
- * STATE-driven reasons — the Stage uses its `visiblePages()` value (a
13
- * stable reference that already folds camera, viewport, scene and DPR).
14
- * Consumers re-render because the binding's identity changes with it;
15
- * nothing reads this field, but it is what makes the memoized binding
16
- * change, so do not "optimize" it away.
17
- */
18
- revision: unknown;
19
- /** Browser-driven invalidation ONLY (PageView scroll/resize — see
20
- * `observeClientGeometry`). The Stage deliberately provides none. */
21
- subscribe?: (callback: () => void) => () => void;
22
- }
23
- /** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */
24
- declare const ProjectorProvider: React.Provider<ProjectorBinding | null>;
25
- /** The surface's projector binding. Reading it subscribes the caller to
26
- * projection changes (the binding's identity IS the revision). */
27
- declare function useProjectorBinding(): ProjectorBinding;
28
- interface AnchoredProps {
29
- anchor: AnchorTarget$1 | null;
30
- /** Which side of the anchor to sit on. Default 'top'. */
31
- placement?: AnchoredPlacement$1;
32
- /** Gap in screen px between the anchor box and the content. Default 8. */
33
- gap?: number;
34
- children: React.ReactNode;
35
- }
36
- /**
37
- * Position `children` around a content-space anchor, on whichever page
38
- * surface is in scope. Projection runs during render from the shared pure
39
- * helper; pointer isolation keeps a click inside anchored UI from reaching
40
- * the surface's own listener (which would read it as click-outside).
41
- */
42
- declare function Anchored({ anchor, placement, gap, children }: AnchoredProps): import("react/jsx-runtime").JSX.Element | null;
43
- //#endregion
44
- export { type AnchorTarget, Anchored, type AnchoredPlacement, AnchoredProps, ProjectorBinding, ProjectorProvider, type ViewProjector, useProjectorBinding };
45
- //# sourceMappingURL=anchored.d.ts.map
1
+ import { a as AnchoredSide, c as ProjectorProvider, d as ViewProjector, f as useOptionalProjectorBinding, i as AnchoredProps, l as ShownPages, n as Anchored, o as PageViewEnv, p as useProjectorBinding, r as AnchoredPlacement, s as ProjectorBinding, t as AnchorTarget, u as ShownPagesProvider } from "./anchored-DeX95xSd.js";
2
+ export { type AnchorTarget, Anchored, type AnchoredPlacement, AnchoredProps, type AnchoredSide, type PageViewEnv, ProjectorBinding, ProjectorProvider, ShownPages, ShownPagesProvider, type ViewProjector, useOptionalProjectorBinding, useProjectorBinding };
package/dist/anchored.js CHANGED
@@ -1,48 +1,85 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useEffect, useLayoutEffect, useReducer, useRef } from "react";
2
+ import { observeAnchoredFit, projectAnchoredTarget, sameAnchoredFit } from "@embedpdf/web";
3
+ import { createContext, useContext, useEffect, useLayoutEffect, useReducer, useState } from "react";
3
4
  import { createPortal } from "react-dom";
4
- import { projectAnchoredTarget } from "@embedpdf/web";
5
5
  //#region src/anchored.tsx
6
6
  const ProjectorContext = createContext(null);
7
7
  /** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */
8
8
  const ProjectorProvider = ProjectorContext.Provider;
9
+ const ShownPagesContext = createContext(null);
10
+ /** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */
11
+ const ShownPagesProvider = ShownPagesContext.Provider;
12
+ /** The surface's projector binding, or null outside any page surface — for
13
+ * chrome that degrades (and warns) instead of throwing. */
14
+ function useOptionalProjectorBinding() {
15
+ return useContext(ProjectorContext);
16
+ }
9
17
  /** The surface's projector binding. Reading it subscribes the caller to
10
- * projection changes (the binding's identity IS the revision). */
18
+ * projection changes (the binding's identity is the revision). */
11
19
  function useProjectorBinding() {
12
20
  const binding = useContext(ProjectorContext);
13
21
  if (!binding) throw new Error("No ViewProjector in scope: mount anchored UI under <Stage> (overlay slot) or <PageView>.");
14
22
  return binding;
15
23
  }
16
24
  /**
17
- * Position `children` around a content-space anchor, on whichever page
18
- * surface is in scope. Projection runs during render from the shared pure
19
- * helper; pointer isolation keeps a click inside anchored UI from reaching
20
- * the surface's own listener (which would read it as click-outside).
25
+ * Position `children` around a page-space anchor, on whichever page surface
26
+ * is in scope. Projection runs during render from the shared pure helper.
27
+ * Once the content's size is measured, it flips to the opposite side when
28
+ * the chosen one has no room, and stays inside the view, unless `pinned`.
29
+ * Its wrapper's `data-placement` is where it sits now: `placement`, or the
30
+ * opposite side after a flip, so what opens from the content can open away
31
+ * from the box.
32
+ * Pointer isolation keeps a click inside anchored UI from reaching the
33
+ * surface's own listener (which would read it as a click outside).
34
+ *
35
+ * Anchored UI on a page that isn't shown renders nothing and reads only the
36
+ * pages on screen, so a document with hundreds of badges costs only the ones
37
+ * in view while people scroll and zoom.
21
38
  */
22
- function Anchored({ anchor, placement = "top", gap = 8, children }) {
39
+ function Anchored(props) {
40
+ const shown = useContext(ShownPagesContext);
41
+ if (!props.anchor?.bounds) return null;
42
+ if (shown && !shown.has(props.anchor.page.objectNumber)) return null;
43
+ return /* @__PURE__ */ jsx(PlacedAnchored, { ...props });
44
+ }
45
+ /** Anchored UI on a page that is shown: it follows the camera. */
46
+ function PlacedAnchored({ anchor, placement = "top", gap = 8, pinned = false, children }) {
23
47
  const { projector, subscribe } = useProjectorBinding();
48
+ const [element, setElement] = useState(null);
49
+ const [fit, setFit] = useState(null);
24
50
  const [, force] = useReducer((x) => x + 1, 0);
25
51
  useLayoutEffect(() => subscribe ? subscribe(force) : void 0, [subscribe]);
26
52
  useLayoutEffect(() => {
27
53
  if (projector.space === "client") force();
28
54
  }, [projector, anchor]);
29
- const ref = useRef(null);
55
+ useLayoutEffect(() => {
56
+ if (!element) return;
57
+ return observeAnchoredFit(element, projector.space, (next) => setFit((current) => sameAnchoredFit(current, next) ? current : next));
58
+ }, [element, projector.space]);
30
59
  useEffect(() => {
31
- const el = ref.current;
32
- if (!el) return;
33
- const stop = (e) => e.stopPropagation();
34
- el.addEventListener("pointerdown", stop);
35
- return () => el.removeEventListener("pointerdown", stop);
36
- });
37
- if (!anchor) return null;
38
- const pos = projectAnchoredTarget(projector, anchor, placement, gap);
60
+ if (!element) return;
61
+ const stop = (event) => event.stopPropagation();
62
+ element.addEventListener("pointerdown", stop);
63
+ return () => element.removeEventListener("pointerdown", stop);
64
+ }, [element]);
65
+ if (!anchor?.bounds) return null;
66
+ const pos = projectAnchoredTarget(projector, {
67
+ ...anchor,
68
+ bounds: anchor.bounds
69
+ }, {
70
+ placement,
71
+ gap,
72
+ pinned
73
+ }, fit);
39
74
  if (!pos) return null;
40
75
  const node = /* @__PURE__ */ jsx("div", {
41
- ref,
76
+ ref: setElement,
77
+ "data-placement": pos.placement,
42
78
  style: {
43
79
  position: projector.space === "client" ? "fixed" : "absolute",
44
80
  left: pos.left,
45
81
  top: pos.top,
82
+ width: "max-content",
46
83
  transform: pos.transform,
47
84
  pointerEvents: "auto"
48
85
  },
@@ -55,6 +92,6 @@ function Anchored({ anchor, placement = "top", gap = 8, children }) {
55
92
  return node;
56
93
  }
57
94
  //#endregion
58
- export { Anchored, ProjectorProvider, useProjectorBinding };
95
+ export { Anchored, ProjectorProvider, ShownPagesProvider, useOptionalProjectorBinding, useProjectorBinding };
59
96
 
60
97
  //# sourceMappingURL=anchored.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"anchored.js","names":[],"sources":["../src/anchored.tsx"],"sourcesContent":["/**\n * Anchored overlays — ONE primitive for every piece of UI that floats over\n * page content (selection menus, draft menus, future popovers).\n *\n * The factoring:\n * - PLUGINS produce anchors (a content-space rect on a page, plus points\n * to dodge) as capability reads.\n * - The projection SNAPSHOT contract and the placement math are shared,\n * framework-neutral, in `@embedpdf/web` ({@link ViewProjector},\n * `projectAnchoredTarget`).\n * - SURFACES (<Stage>, <PageView>) provide a {@link ProjectorBinding}:\n * the snapshot plus REACT's way of knowing when it changed.\n * - <Anchored> renders at the projected position, isolates pointer\n * events, and portals when the space demands it.\n *\n * THE SCHEDULING LAW (this is what keeps menus glued to the content): a\n * state-driven projection change (the Stage camera) reaches consumers as a\n * NEW BINDING IDENTITY through context — surface and overlay re-render in\n * the SAME React commit, so they can never paint a frame apart. No\n * listener sets, no post-commit notifications, no second menu-only render.\n * `subscribe` exists ONLY for genuinely browser-driven invalidation (a\n * PageView moving because the document scrolled), where no state change\n * announces the move.\n */\nimport * as React from 'react';\nimport { createContext, useContext, useEffect, useLayoutEffect, useReducer, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n projectAnchoredTarget,\n type AnchoredPlacement,\n type AnchorTarget,\n type ViewProjector,\n} from '@embedpdf/web';\n\nexport type { AnchoredPlacement, AnchorTarget, ViewProjector } from '@embedpdf/web';\n\n/**\n * What a page surface provides via context: the pure projection snapshot,\n * bound to React's reactivity.\n */\nexport interface ProjectorBinding {\n projector: ViewProjector;\n /**\n * Changes identity exactly when projection may have changed for\n * STATE-driven reasons — the Stage uses its `visiblePages()` value (a\n * stable reference that already folds camera, viewport, scene and DPR).\n * Consumers re-render because the binding's identity changes with it;\n * nothing reads this field, but it is what makes the memoized binding\n * change, so do not \"optimize\" it away.\n */\n revision: unknown;\n /** Browser-driven invalidation ONLY (PageView scroll/resize — see\n * `observeClientGeometry`). The Stage deliberately provides none. */\n subscribe?: (callback: () => void) => () => void;\n}\n\nconst ProjectorContext = createContext<ProjectorBinding | null>(null);\n\n/** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */\nexport const ProjectorProvider = ProjectorContext.Provider;\n\n/** The surface's projector binding. Reading it subscribes the caller to\n * projection changes (the binding's identity IS the revision). */\nexport function useProjectorBinding(): ProjectorBinding {\n const binding = useContext(ProjectorContext);\n if (!binding) {\n throw new Error(\n 'No ViewProjector in scope: mount anchored UI under <Stage> (overlay slot) or <PageView>.',\n );\n }\n return binding;\n}\n\nexport interface AnchoredProps {\n anchor: AnchorTarget | null;\n /** Which side of the anchor to sit on. Default 'top'. */\n placement?: AnchoredPlacement;\n /** Gap in screen px between the anchor box and the content. Default 8. */\n gap?: number;\n children: React.ReactNode;\n}\n\n/**\n * Position `children` around a content-space anchor, on whichever page\n * surface is in scope. Projection runs during render from the shared pure\n * helper; pointer isolation keeps a click inside anchored UI from reaching\n * the surface's own listener (which would read it as click-outside).\n */\nexport function Anchored({ anchor, placement = 'top', gap = 8, children }: AnchoredProps) {\n const { projector, subscribe } = useProjectorBinding();\n\n // Browser-driven invalidation only (PageView). State-driven changes come\n // through the binding identity — no local bump involved.\n const [, force] = useReducer((x: number) => x + 1, 0);\n useLayoutEffect(() => (subscribe ? subscribe(force) : undefined), [subscribe]);\n // Client-space surfaces measure the DOM, which does not exist during the\n // surface's first render — force one post-commit pass so the position\n // appears as soon as it is measurable. (Solves measurability, not\n // reactivity.)\n useLayoutEffect(() => {\n if (projector.space === 'client') force();\n }, [projector, anchor]);\n\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n return () => el.removeEventListener('pointerdown', stop);\n });\n\n if (!anchor) return null;\n const pos = projectAnchoredTarget(projector, anchor, placement, gap);\n if (!pos) return null;\n\n const node = (\n <div\n ref={ref}\n style={{\n position: projector.space === 'client' ? 'fixed' : 'absolute',\n left: pos.left,\n top: pos.top,\n transform: pos.transform,\n pointerEvents: 'auto',\n }}\n >\n {children}\n </div>\n );\n if (projector.space === 'client') {\n if (typeof document === 'undefined') return null;\n return createPortal(node, document.body);\n }\n return node;\n}\n"],"mappings":";;;;;AAwDA,MAAM,mBAAmB,cAAuC,IAAI;;AAGpE,MAAa,oBAAoB,iBAAiB;;;AAIlD,SAAgB,sBAAwC;CACtD,MAAM,UAAU,WAAW,gBAAgB;CAC3C,IAAI,CAAC,SACH,MAAM,IAAI,MACR,0FACF;CAEF,OAAO;AACT;;;;;;;AAiBA,SAAgB,SAAS,EAAE,QAAQ,YAAY,OAAO,MAAM,GAAG,YAA2B;CACxF,MAAM,EAAE,WAAW,cAAc,oBAAoB;CAIrD,MAAM,GAAG,SAAS,YAAY,MAAc,IAAI,GAAG,CAAC;CACpD,sBAAuB,YAAY,UAAU,KAAK,IAAI,KAAA,GAAY,CAAC,SAAS,CAAC;CAK7E,sBAAsB;EACpB,IAAI,UAAU,UAAU,UAAU,MAAM;CAC1C,GAAG,CAAC,WAAW,MAAM,CAAC;CAEtB,MAAM,MAAM,OAAuB,IAAI;CACvC,gBAAgB;EACd,MAAM,KAAK,IAAI;EACf,IAAI,CAAC,IAAI;EACT,MAAM,QAAQ,MAAa,EAAE,gBAAgB;EAC7C,GAAG,iBAAiB,eAAe,IAAI;EACvC,aAAa,GAAG,oBAAoB,eAAe,IAAI;CACzD,CAAC;CAED,IAAI,CAAC,QAAQ,OAAO;CACpB,MAAM,MAAM,sBAAsB,WAAW,QAAQ,WAAW,GAAG;CACnE,IAAI,CAAC,KAAK,OAAO;CAEjB,MAAM,OACJ,oBAAC,OAAD;EACO;EACL,OAAO;GACL,UAAU,UAAU,UAAU,WAAW,UAAU;GACnD,MAAM,IAAI;GACV,KAAK,IAAI;GACT,WAAW,IAAI;GACf,eAAe;EACjB;EAEC;CACE,CAAA;CAEP,IAAI,UAAU,UAAU,UAAU;EAChC,IAAI,OAAO,aAAa,aAAa,OAAO;EAC5C,OAAO,aAAa,MAAM,SAAS,IAAI;CACzC;CACA,OAAO;AACT"}
1
+ {"version":3,"file":"anchored.js","names":[],"sources":["../src/anchored.tsx"],"sourcesContent":["/**\n * Anchored overlays — one primitive for every piece of UI that floats over\n * page content (selection menus, draft menus, future popovers).\n *\n * The factoring:\n * - plugins produce anchors (a page-space rect on a page, plus points\n * to dodge) as capability reads.\n * - The projection snapshot contract and the placement math are shared,\n * framework-neutral, in `@embedpdf/web` ({@link ViewProjector},\n * `projectAnchoredTarget`).\n * - surfaces (<Stage>, <PageView>) provide a {@link ProjectorBinding}:\n * the snapshot plus react's way of knowing when it changed.\n * - <Anchored> renders at the projected position, flips to the other\n * side and stays inside the view once it knows its size (unless\n * pinned), says where it sits in `data-placement`, isolates pointer\n * events, and portals when the space demands it. On a page that isn't\n * shown it renders nothing and doesn't follow the camera at all (see\n * {@link ShownPages}).\n *\n * The scheduling law (this is what keeps menus glued to the content): a\n * state-driven projection change (the Stage camera) reaches consumers as a\n * new binding identity through context — surface and overlay re-render in\n * the same React commit, so they can never paint a frame apart. No\n * listener sets, no post-commit notifications, no second menu-only render.\n * `subscribe` exists only for genuinely browser-driven invalidation (a\n * PageView moving because the document scrolled), where no state change\n * announces the move.\n */\nimport * as React from 'react';\nimport { createContext, useContext, useEffect, useLayoutEffect, useReducer, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n observeAnchoredFit,\n projectAnchoredTarget,\n sameAnchoredFit,\n type AnchoredFit,\n type AnchoredPlacement,\n type AnchoredRect,\n type AnchorTarget,\n type ViewProjector,\n} from '@embedpdf/web';\n\nexport type {\n AnchoredPlacement,\n AnchoredSide,\n AnchorTarget,\n PageViewEnv,\n ViewProjector,\n} from '@embedpdf/web';\n\n/**\n * What a page surface provides via context: the pure projection snapshot,\n * bound to React's reactivity.\n */\nexport interface ProjectorBinding {\n projector: ViewProjector;\n /**\n * Changes identity exactly when projection may have changed for\n * state-driven reasons — the Stage uses its `visiblePages()` value (a\n * stable reference that already folds camera, viewport, scene and DPR).\n * Consumers re-render because the binding's identity changes with it;\n * nothing reads this field, but it is what makes the memoized binding\n * change, so do not \"optimize\" it away.\n */\n revision: unknown;\n /** Browser-driven invalidation only (PageView scroll/resize — see\n * `observeClientGeometry`). The Stage deliberately provides none. */\n subscribe?: (callback: () => void) => () => void;\n}\n\nconst ProjectorContext = createContext<ProjectorBinding | null>(null);\n\n/** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */\nexport const ProjectorProvider = ProjectorContext.Provider;\n\n/**\n * The pages a surface shows right now, by object number. It is a value of its\n * own, next to the projection, because it changes only when a page comes on\n * screen or leaves it: anchored UI on other pages reads only this, so it\n * isn't rendered again on every camera frame.\n */\nexport type ShownPages = ReadonlySet<number>;\n\nconst ShownPagesContext = createContext<ShownPages | null>(null);\n\n/** Installed by page surfaces (<Stage>, <PageView>) — not by app code. */\nexport const ShownPagesProvider = ShownPagesContext.Provider;\n\n/** The surface's projector binding, or null outside any page surface — for\n * chrome that degrades (and warns) instead of throwing. */\nexport function useOptionalProjectorBinding(): ProjectorBinding | null {\n return useContext(ProjectorContext);\n}\n\n/** The surface's projector binding. Reading it subscribes the caller to\n * projection changes (the binding's identity is the revision). */\nexport function useProjectorBinding(): ProjectorBinding {\n const binding = useContext(ProjectorContext);\n if (!binding) {\n throw new Error(\n 'No ViewProjector in scope: mount anchored UI under <Stage> (overlay slot) or <PageView>.',\n );\n }\n return binding;\n}\n\nexport interface AnchoredProps {\n /**\n * The box on a page to sit next to, in page coordinates: `{ page, bounds }`,\n * with `avoid` points to keep clear of. `null`, or a target without\n * `bounds` (a search match with no geometry), hides it.\n */\n anchor: (Omit<AnchorTarget, 'bounds'> & { bounds?: AnchoredRect }) | null;\n /**\n * Where to sit: a side of the box, centred, or lined up with the side's\n * start or end (`'top-end'`). Default 'top'.\n */\n placement?: AnchoredPlacement;\n /**\n * Gap in screen px between the box and the content, and between the content\n * and the view's edge. Negative overlaps the box. Default 8.\n */\n gap?: number;\n /**\n * Stay where `placement` puts it: never flip to the other side, never move\n * to stay in view, and scroll away with the box. For badges and status;\n * menus leave it off. Default false.\n */\n pinned?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Position `children` around a page-space anchor, on whichever page surface\n * is in scope. Projection runs during render from the shared pure helper.\n * Once the content's size is measured, it flips to the opposite side when\n * the chosen one has no room, and stays inside the view, unless `pinned`.\n * Its wrapper's `data-placement` is where it sits now: `placement`, or the\n * opposite side after a flip, so what opens from the content can open away\n * from the box.\n * Pointer isolation keeps a click inside anchored UI from reaching the\n * surface's own listener (which would read it as a click outside).\n *\n * Anchored UI on a page that isn't shown renders nothing and reads only the\n * pages on screen, so a document with hundreds of badges costs only the ones\n * in view while people scroll and zoom.\n */\nexport function Anchored(props: AnchoredProps) {\n const shown = useContext(ShownPagesContext);\n if (!props.anchor?.bounds) return null;\n if (shown && !shown.has(props.anchor.page.objectNumber)) return null;\n return <PlacedAnchored {...props} />;\n}\n\n/** Anchored UI on a page that is shown: it follows the camera. */\nfunction PlacedAnchored({\n anchor,\n placement = 'top',\n gap = 8,\n pinned = false,\n children,\n}: AnchoredProps) {\n const { projector, subscribe } = useProjectorBinding();\n const [element, setElement] = useState<HTMLDivElement | null>(null);\n // The content's size and the view's: measured after the first commit, and\n // again whenever either resizes. A camera move changes neither.\n const [fit, setFit] = useState<AnchoredFit | null>(null);\n\n // Browser-driven invalidation only (PageView). State-driven changes come\n // through the binding identity — no local bump involved.\n const [, force] = useReducer((x: number) => x + 1, 0);\n useLayoutEffect(() => (subscribe ? subscribe(force) : undefined), [subscribe]);\n // Client-space surfaces measure the DOM, which does not exist during the\n // surface's first render — force one post-commit pass so the position\n // appears as soon as it is measurable. (Solves measurability, not\n // reactivity.)\n useLayoutEffect(() => {\n if (projector.space === 'client') force();\n }, [projector, anchor]);\n\n useLayoutEffect(() => {\n if (!element) return;\n return observeAnchoredFit(element, projector.space, (next) =>\n setFit((current) => (sameAnchoredFit(current, next) ? current : next)),\n );\n }, [element, projector.space]);\n\n useEffect(() => {\n if (!element) return;\n const stop = (event: Event) => event.stopPropagation();\n element.addEventListener('pointerdown', stop);\n return () => element.removeEventListener('pointerdown', stop);\n }, [element]);\n\n if (!anchor?.bounds) return null;\n const pos = projectAnchoredTarget(\n projector,\n { ...anchor, bounds: anchor.bounds },\n { placement, gap, pinned },\n fit,\n );\n if (!pos) return null;\n\n const node = (\n <div\n ref={setElement}\n data-placement={pos.placement}\n style={{\n position: projector.space === 'client' ? 'fixed' : 'absolute',\n left: pos.left,\n top: pos.top,\n // Its own width, wherever it sits: the size the placement measured.\n width: 'max-content',\n transform: pos.transform,\n pointerEvents: 'auto',\n }}\n >\n {children}\n </div>\n );\n if (projector.space === 'client') {\n if (typeof document === 'undefined') return null;\n return createPortal(node, document.body);\n }\n return node;\n}\n"],"mappings":";;;;;AAsEA,MAAM,mBAAmB,cAAuC,IAAI;;AAGpE,MAAa,oBAAoB,iBAAiB;AAUlD,MAAM,oBAAoB,cAAiC,IAAI;;AAG/D,MAAa,qBAAqB,kBAAkB;;;AAIpD,SAAgB,8BAAuD;CACrE,OAAO,WAAW,gBAAgB;AACpC;;;AAIA,SAAgB,sBAAwC;CACtD,MAAM,UAAU,WAAW,gBAAgB;CAC3C,IAAI,CAAC,SACH,MAAM,IAAI,MACR,0FACF;CAEF,OAAO;AACT;;;;;;;;;;;;;;;;AA2CA,SAAgB,SAAS,OAAsB;CAC7C,MAAM,QAAQ,WAAW,iBAAiB;CAC1C,IAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO;CAClC,IAAI,SAAS,CAAC,MAAM,IAAI,MAAM,OAAO,KAAK,YAAY,GAAG,OAAO;CAChE,OAAO,oBAAC,gBAAD,EAAgB,GAAI,MAAQ,CAAA;AACrC;;AAGA,SAAS,eAAe,EACtB,QACA,YAAY,OACZ,MAAM,GACN,SAAS,OACT,YACgB;CAChB,MAAM,EAAE,WAAW,cAAc,oBAAoB;CACrD,MAAM,CAAC,SAAS,cAAc,SAAgC,IAAI;CAGlE,MAAM,CAAC,KAAK,UAAU,SAA6B,IAAI;CAIvD,MAAM,GAAG,SAAS,YAAY,MAAc,IAAI,GAAG,CAAC;CACpD,sBAAuB,YAAY,UAAU,KAAK,IAAI,KAAA,GAAY,CAAC,SAAS,CAAC;CAK7E,sBAAsB;EACpB,IAAI,UAAU,UAAU,UAAU,MAAM;CAC1C,GAAG,CAAC,WAAW,MAAM,CAAC;CAEtB,sBAAsB;EACpB,IAAI,CAAC,SAAS;EACd,OAAO,mBAAmB,SAAS,UAAU,QAAQ,SACnD,QAAQ,YAAa,gBAAgB,SAAS,IAAI,IAAI,UAAU,IAAK,CACvE;CACF,GAAG,CAAC,SAAS,UAAU,KAAK,CAAC;CAE7B,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,QAAQ,UAAiB,MAAM,gBAAgB;EACrD,QAAQ,iBAAiB,eAAe,IAAI;EAC5C,aAAa,QAAQ,oBAAoB,eAAe,IAAI;CAC9D,GAAG,CAAC,OAAO,CAAC;CAEZ,IAAI,CAAC,QAAQ,QAAQ,OAAO;CAC5B,MAAM,MAAM,sBACV,WACA;EAAE,GAAG;EAAQ,QAAQ,OAAO;CAAO,GACnC;EAAE;EAAW;EAAK;CAAO,GACzB,GACF;CACA,IAAI,CAAC,KAAK,OAAO;CAEjB,MAAM,OACJ,oBAAC,OAAD;EACE,KAAK;EACL,kBAAgB,IAAI;EACpB,OAAO;GACL,UAAU,UAAU,UAAU,WAAW,UAAU;GACnD,MAAM,IAAI;GACV,KAAK,IAAI;GAET,OAAO;GACP,WAAW,IAAI;GACf,eAAe;EACjB;EAEC;CACE,CAAA;CAEP,IAAI,UAAU,UAAU,UAAU;EAChC,IAAI,OAAO,aAAa,aAAa,OAAO;EAC5C,OAAO,aAAa,MAAM,SAAS,IAAI;CACzC;CACA,OAAO;AACT"}
@@ -0,0 +1,302 @@
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
+ /** The box's body style as CSS: font, size, color and alignment. While typing it takes the pointer too. */
205
+ style: React$1.CSSProperties;
206
+ /** True while someone types in the box. */
207
+ editing: boolean;
208
+ }
209
+ /**
210
+ * Make your own element the editor of a text box you draw yourself (a
211
+ * renderer for free text): it draws the runs, turns typing back into runs,
212
+ * keeps the caret when the style changes, and handles pasting, input methods
213
+ * and the format shortcuts. The formatting calls (`text.toggleFormat`,
214
+ * `selection.update`) work on it as they do on the built-in one.
215
+ */
216
+ declare function useRichTextEditor(annotation: Annotation): RichTextEditor;
217
+ /**
218
+ * Draws a page's annotations, the selection's outline and handles, the tool's
219
+ * preview and the text boxes being typed in. Put it above the rendered page:
220
+ * while it's there, the render layer leaves the annotations out of the
221
+ * page's picture.
222
+ */
223
+ declare function AnnotationLayer({ renderers, components }?: AnnotationLayerProps): import("react/jsx-runtime").JSX.Element;
224
+ /**
225
+ * The default file-picker provider: the built-in file dialog (from
226
+ * `@embedpdf/web`), honouring the tool's `accept` filter. This is the adapter
227
+ * fulfilling the plugin's DOM-free port — the dialog lives in the framework
228
+ * layer, never in the plugin.
229
+ */
230
+ declare const filePickerProvider: FilePickerProvider;
231
+ /**
232
+ * Install the file-picker provider for the active document — the one port
233
+ * behind every click-then-pick tool (a stamp `'prompt'` source, the file-
234
+ * attachment tool). Call once at a document-scoped spot (not inside
235
+ * `<AnnotationLayer>`, which is per page). Defaults to
236
+ * {@link filePickerProvider}, so a bare `useFilePickerProvider()` makes all of
237
+ * them work out of the box; pass a custom provider (asset library, cloud
238
+ * drive — switch on `req.subtype` / `req.toolId`) or `null` to make
239
+ * click-then-pick tools inert. Cleared on unmount.
240
+ */
241
+ declare function useFilePickerProvider(provider?: FilePickerProvider | null): void;
242
+ declare function useAnnotation(): AnnotationCapability;
243
+ /** Listen to one annotation event while the component is mounted: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */
244
+ declare function useAnnotationEvent<T>(select: (annotation: AnnotationCapability) => EventHook<T>, handler: (event: T) => void): void;
245
+ /**
246
+ * The annotations matching `filter` (some pages, one kind), in drawing order,
247
+ * as the user sees them; the same array while they stay the same. Empty
248
+ * without a document.
249
+ */
250
+ declare function useAnnotationList(filter?: AnnotationFilter): readonly Annotation[];
251
+ /**
252
+ * A tool's defaults: the fields its next annotation starts with, over the
253
+ * engine's. The component re-renders when they change, so a color picker
254
+ * always shows the current color. Empty without a document.
255
+ */
256
+ declare function useAnnotationDefaults(toolId: string): ToolDefaults;
257
+ /**
258
+ * What a style panel shows: the selection's properties (`selection.getProperties()`),
259
+ * or, given a tool id, the tool's (`tools.getProperties(id)`). The component
260
+ * re-renders when they change. Empty without a document.
261
+ */
262
+ declare function useAnnotationProperties(toolId?: string): AnnotationProperties;
263
+ /**
264
+ * An anchor for `<Anchored>` that keeps a card or a badge attached to one
265
+ * annotation: its page and the box around what it shows, following a move
266
+ * as it happens. `null` for `null`, or an annotation that isn't here. The
267
+ * component re-renders when the annotation moves, not while people scroll or
268
+ * zoom: a note that keeps its size on screen hands `<Anchored>` its
269
+ * `boundsIn`.
270
+ */
271
+ declare function useAnnotationAnchor(ref: AnnotationRef | null): AnnotationAnchor | null;
272
+ /**
273
+ * A {@link CommentThread} enriched with its page's live display position —
274
+ * the framework-layer join (`enrichCommentThreads` in `@embedpdf/web`).
275
+ * Identity stays `page` (like every annotation surface); these two fields
276
+ * are presentation, tracking page moves and deletes.
277
+ */
278
+ interface CommentThreadView extends CommentThread {
279
+ /** Current 0-based display index of the thread's page; `-1` when the page
280
+ * is no longer in the document (one-frame teardown race on delete). */
281
+ pageIndex: number;
282
+ /** The page's `/PageLabels` label when the PDF declares one ("iv", "A-2"),
283
+ * else the 1-based position as a string — print it verbatim. */
284
+ pageLabel: string;
285
+ }
286
+ /** The comments API: the `comments` part of `useAnnotation()`. Pair it with
287
+ * {@link useCommentThreads} for the threads to show. */
288
+ declare function useComments(): CommentsApi;
289
+ /**
290
+ * Every comment thread in the document, display-ordered (page position →
291
+ * top of page → creation date) and enriched with `pageIndex`/`pageLabel`.
292
+ * Subscribed to both stores: annotation writes (own, remote, hydration)
293
+ * recompute the threads; page moves/deletes re-run the join. Reference-
294
+ * stable between changes — safe to memo child renders on the array.
295
+ */
296
+ declare function useCommentThreads(): CommentThreadView[];
297
+ /** The enriched thread containing any member ref (root, reply, grouped part,
298
+ * state annotation), or null. */
299
+ declare function useCommentThread(ref: AnnotationRef | null): CommentThreadView | null;
300
+ //#endregion
301
+ 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 };
302
+ //# sourceMappingURL=annotation-B48UT2ln.d.ts.map