@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
@@ -0,0 +1,708 @@
1
+ import { C as useOptionalSelector, D as useViewerSettings, E as useSelector, O as devWarn, S as useOptionalCapability, f as useCapability, h as useDocumentId, p as useCapabilityEvent, u as shallowArray, w as usePage, x as useKernelValue } from "./runtime-B6xcPsEb.js";
2
+ import { n as stateHook, t as settingsHook } from "./state-CbgxhwLA.js";
3
+ import { Anchored, useProjectorBinding } from "./anchored.js";
4
+ import { n as usePaintsPagePart } from "./page-layers-Bkaaz8Zf.js";
5
+ import { t as INERT } from "./inert-D8fkennb.js";
6
+ import { t as SvgShapes } from "./svg-shapes-Dm1yTR1b.js";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { annotationChromePaint, annotationDrawingOf, bakedAppearanceOf, chromeInPixels, createShownUrls, createTextBoxEditorFollower, editingTextKeyOf, enrichCommentThreads, frameInPixels, ghostOpacity, installFilePickerProvider, layerTextBoxesOf, loadAppearanceUrls, loadObjectUrl, lookFrameOf, paint, paintDefault, pickRequestedFile, pictureOrPainting, rasterInFrame, rectInPixels, registerRendererBehaviors, sameAnnotationAnchor, sameCreationDraftAnchor, sameRotationAnchor, sameSelectionAnchor, sceneViewBox, shownAppearance, svgShapesOf, textBoxEditorScaleOf, textBoxStyleOf, textPlateInPixels } from "@embedpdf/web";
9
+ import * as React$1 from "react";
10
+ import { useEffect, useRef, useState } from "react";
11
+ import { InteractionToken } from "@embedpdf/plugin-interaction/contract";
12
+ import { RenderToken } from "@embedpdf/plugin-render/contract/host";
13
+ import { AnnotationToken, annotationKey } from "@embedpdf/plugin-annotation";
14
+ import { MITER_LIMIT, hasLiveDrawing, scene } from "@embedpdf/core-annotation";
15
+ import { AnnotationToken as AnnotationToken$1, previewBucket } from "@embedpdf/plugin-annotation/contract/host";
16
+ import { AnnotationToken as AnnotationToken$2, annotationState } from "@embedpdf/plugin-annotation/contract";
17
+ //#region src/annotation-hooks.ts
18
+ /**
19
+ * The annotation hooks other feature entries use too (the form plugin reads
20
+ * the selection), kept apart so they don't import the whole annotation
21
+ * feature: the state and the settings, each from its declaration.
22
+ */
23
+ /**
24
+ * The annotation state: `status` (`'loading'` until every annotation is in,
25
+ * then `'ready'`), the `selected` annotations, the one `hovered` under the
26
+ * pointer and the text box being typed in (`editing`). Re-renders only when a
27
+ * field changes, or the value `select` picks. Empty without a document.
28
+ */
29
+ const useAnnotationState = stateHook(annotationState);
30
+ /**
31
+ * The annotation settings (`snap`, `chrome`, `afterCreate`, `tools`), or the
32
+ * value `select` picks. They belong to the plugin, so they read without a
33
+ * document; change them with `useAnnotation().updateSettings()`.
34
+ */
35
+ const useAnnotationSettings = settingsHook(AnnotationToken$2);
36
+ //#endregion
37
+ //#region src/annotation-menu.tsx
38
+ /**
39
+ * Your own menu next to the selection (one anchor, also for a selection over
40
+ * several pages), clear of the rotation handle. It hides while the selection
41
+ * is dragged, resized or turned. What's in it is yours: build it from
42
+ * `useAnnotation()` and `useAnnotationState()`.
43
+ */
44
+ function AnnotationMenu({ children, gap = 15, placement = "top" }) {
45
+ const { projector } = useProjectorBinding();
46
+ const anchor = useOptionalSelector(AnnotationToken$1, (annotation) => {
47
+ const selectionAnchor = annotation.selection.getAnchor();
48
+ if (!selectionAnchor) return null;
49
+ const env = projector.viewEnv(selectionAnchor.page);
50
+ return env ? annotation.getSelectionAnchorIn(env) : selectionAnchor;
51
+ }, null, sameSelectionAnchor);
52
+ if (!anchor) return null;
53
+ return /* @__PURE__ */ jsx(Anchored, {
54
+ anchor: {
55
+ page: anchor.page,
56
+ bounds: anchor.bounds,
57
+ ...anchor.rotationHandle ? { avoid: [anchor.rotationHandle] } : {}
58
+ },
59
+ placement,
60
+ gap,
61
+ children
62
+ });
63
+ }
64
+ /** Floats over a live multi-click creation draft (polygon, polyline, …). */
65
+ function AnnotationDraftMenu({ children, gap = 8, placement = "top" }) {
66
+ const anchor = useOptionalSelector(AnnotationToken$2, (annotation) => annotation.draft.get(), null, sameCreationDraftAnchor);
67
+ if (!anchor) return null;
68
+ return /* @__PURE__ */ jsx(Anchored, {
69
+ anchor,
70
+ placement,
71
+ gap,
72
+ children: children(anchor)
73
+ });
74
+ }
75
+ /**
76
+ * Follows the pointer while a selection is being turned, upright however the
77
+ * page is shown: it floats over the page like the menus, not in it. Shows
78
+ * nothing when no rotation is in progress.
79
+ */
80
+ function AnnotationRotationBadge({ children, gap = 16, placement = "right" }) {
81
+ const rotation = useOptionalSelector(AnnotationToken$2, (annotation) => annotation.selection.getRotationAnchor(), null, sameRotationAnchor);
82
+ const readout = useAnnotationSettings((settings) => settings.chrome.readout);
83
+ if (!rotation || !children && !readout.enabled) return null;
84
+ return /* @__PURE__ */ jsx(Anchored, {
85
+ anchor: {
86
+ page: rotation.page,
87
+ bounds: {
88
+ ...rotation.at,
89
+ width: 0,
90
+ height: 0
91
+ }
92
+ },
93
+ placement,
94
+ gap,
95
+ children: children ? children(rotation) : /* @__PURE__ */ jsxs("div", {
96
+ style: {
97
+ pointerEvents: "none",
98
+ whiteSpace: "nowrap",
99
+ borderRadius: 4,
100
+ padding: "2px 6px",
101
+ fontFamily: paintDefault("font-mono"),
102
+ fontSize: 12,
103
+ background: paint("readout-background", readout.background),
104
+ color: paint("readout-color", readout.color)
105
+ },
106
+ children: [rotation.angle, "°"]
107
+ })
108
+ });
109
+ }
110
+ //#endregion
111
+ //#region src/annotation.tsx
112
+ /** How much the layer scales the look around it: 1 outside a look, or in one drawn at its size on screen. */
113
+ const LookScaleContext = React$1.createContext(1);
114
+ /**
115
+ * The box an annotation draws into, placed, sized and turned like the
116
+ * annotation (`item.frame`) inside the page layer, which the page itself
117
+ * turns. The annotation's own drawing and any look of yours draw inside it.
118
+ */
119
+ function AnnotationFrame({ item, page, interactive = false, inert = false, children }) {
120
+ const box = frameInPixels(item.frame, page.transform);
121
+ return /* @__PURE__ */ jsx("div", {
122
+ ...inert ? INERT : {},
123
+ style: {
124
+ position: "absolute",
125
+ left: box.left,
126
+ top: box.top,
127
+ width: box.width,
128
+ height: box.height,
129
+ transform: box.transform,
130
+ transformOrigin: "center",
131
+ mixBlendMode: item.blend,
132
+ pointerEvents: interactive ? "auto" : "none"
133
+ },
134
+ children
135
+ });
136
+ }
137
+ /** SVG attribute names as React props: `stroke-width` is `strokeWidth`. */
138
+ /**
139
+ * The scene, filling the item's frame: drawn upright in it, the frame turns
140
+ * it. The core computed the box and the painted scene; `@embedpdf/web`
141
+ * describes each scene node as one SVG element, so there is no per-kind
142
+ * logic and no bounds math here.
143
+ */
144
+ function Shape({ item }) {
145
+ const viewBox = sceneViewBox(item.box);
146
+ if (!viewBox) return null;
147
+ return /* @__PURE__ */ jsx("svg", {
148
+ viewBox,
149
+ style: {
150
+ position: "absolute",
151
+ left: 0,
152
+ top: 0,
153
+ width: "100%",
154
+ height: "100%",
155
+ overflow: "visible",
156
+ pointerEvents: "none",
157
+ ...item.source === "ghost" ? { opacity: ghostOpacity(item.ghostOpacity ?? .5) } : {}
158
+ },
159
+ children: /* @__PURE__ */ jsx(SvgShapes, { shapes: svgShapesOf(scene(item), { miterLimit: MITER_LIMIT }) })
160
+ });
161
+ }
162
+ /** The engine's raster inside the item's frame, where `item.raster` puts it, at any frame size. */
163
+ function BakedImage({ url, box }) {
164
+ return /* @__PURE__ */ jsx("img", {
165
+ src: url,
166
+ alt: "",
167
+ draggable: false,
168
+ style: {
169
+ position: "absolute",
170
+ left: box.left,
171
+ top: box.top,
172
+ width: box.width,
173
+ height: box.height,
174
+ maxWidth: "none",
175
+ maxHeight: "none",
176
+ pointerEvents: "none",
177
+ transform: box.transform,
178
+ transformOrigin: "center"
179
+ }
180
+ });
181
+ }
182
+ /**
183
+ * The armed stamp's ghost: a see-through render of the payload drawn in the
184
+ * exact box a click would place it (the plugin computes it with the same fit
185
+ * + clamp as placement). Every other tool's ghost rides `pageItems` like a
186
+ * drawing in progress. The preview bytes live in the capability closure; this
187
+ * layer owns only the object-URL lifetime, keyed on the armed stamp — a new
188
+ * arm swaps the image, a disarm (or tool change) drops it.
189
+ */
190
+ function ToolGhostImage({ page }) {
191
+ const anno = useCapability(AnnotationToken$1);
192
+ const ghost = useSelector(AnnotationToken$1, (annotation) => annotation.getImageGhost(page.ref));
193
+ const armed = useSelector(AnnotationToken$1, (annotation) => annotation.getArmedStamp());
194
+ const [url, setUrl] = useState(null);
195
+ const bucket = ghost ? previewBucket(ghost.box.width * page.transform.renderScale) : 0;
196
+ useEffect(() => {
197
+ if (!bucket) {
198
+ setUrl(null);
199
+ return;
200
+ }
201
+ return loadObjectUrl(() => anno.renderArmedStampPreview(bucket), setUrl);
202
+ }, [
203
+ anno,
204
+ armed,
205
+ bucket
206
+ ]);
207
+ if (!ghost || !url) return null;
208
+ const frame = rectInPixels(ghost.box, page.transform);
209
+ return /* @__PURE__ */ jsx("img", {
210
+ src: url,
211
+ alt: "",
212
+ draggable: false,
213
+ style: {
214
+ position: "absolute",
215
+ left: frame.left,
216
+ top: frame.top,
217
+ width: frame.width,
218
+ height: frame.height,
219
+ maxWidth: "none",
220
+ maxHeight: "none",
221
+ pointerEvents: "none",
222
+ opacity: ghostOpacity(ghost.opacity),
223
+ ...ghost.rot ? {
224
+ transform: `rotate(${ghost.rot}deg)`,
225
+ transformOrigin: "center"
226
+ } : {}
227
+ }
228
+ });
229
+ }
230
+ /** The chrome settings, painted: follows the settings and the viewer's accent live. */
231
+ function useChromePaint() {
232
+ const chrome = useAnnotationSettings((settings) => settings.chrome);
233
+ const accent = useViewerSettings((settings) => settings.accent);
234
+ return {
235
+ chrome,
236
+ painted: React$1.useMemo(() => annotationChromePaint(chrome, accent), [chrome, accent])
237
+ };
238
+ }
239
+ /** A handle as the layer draws it: a square or a circle, `size` px across. */
240
+ function DefaultHandle({ at, size, rotation, shape, style }) {
241
+ if (shape === "circle") return /* @__PURE__ */ jsx("circle", {
242
+ cx: at.x,
243
+ cy: at.y,
244
+ r: size / 2,
245
+ strokeWidth: 1.5,
246
+ style
247
+ });
248
+ return /* @__PURE__ */ jsx("rect", {
249
+ x: at.x - size / 2,
250
+ y: at.y - size / 2,
251
+ width: size,
252
+ height: size,
253
+ strokeWidth: 1.5,
254
+ style,
255
+ ...rotation ? { transform: `rotate(${rotation} ${at.x} ${at.y})` } : {}
256
+ });
257
+ }
258
+ function Chrome({ page, components }) {
259
+ const scale = page.transform.viewScale;
260
+ const rotation = page.transform.rotation;
261
+ const zoom = page.transform.zoom;
262
+ const nodes = useSelector(AnnotationToken$1, (annotation) => annotation.listChromeNodes(page.ref, scale, rotation, zoom), shallowArray);
263
+ const { chrome, painted } = useChromePaint();
264
+ const Handle = components?.Handle;
265
+ const RotationHandle = components?.RotationHandle;
266
+ const custom = [];
267
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("svg", {
268
+ style: {
269
+ position: "absolute",
270
+ inset: 0,
271
+ overflow: "visible",
272
+ pointerEvents: "none"
273
+ },
274
+ children: chromeInPixels(nodes, page.transform).map((node, i) => {
275
+ switch (node.kind) {
276
+ case "handle":
277
+ if (Handle) {
278
+ custom.push(/* @__PURE__ */ jsx(Handle, {
279
+ at: node.at,
280
+ size: chrome.handles.size,
281
+ rotation: node.rotation,
282
+ kind: node.role,
283
+ active: node.active
284
+ }, i));
285
+ return null;
286
+ }
287
+ return /* @__PURE__ */ jsx(DefaultHandle, {
288
+ at: node.at,
289
+ size: chrome.handles.size,
290
+ rotation: node.rotation,
291
+ shape: chrome.handles.shape,
292
+ style: painted.handle
293
+ }, i);
294
+ case "guide": return /* @__PURE__ */ jsx("line", {
295
+ x1: node.from.x,
296
+ y1: node.from.y,
297
+ x2: node.to.x,
298
+ y2: node.to.y,
299
+ shapeRendering: "crispEdges",
300
+ style: painted.guide
301
+ }, i);
302
+ case "turned-outline": return /* @__PURE__ */ jsx("polygon", {
303
+ points: node.points,
304
+ fill: "none",
305
+ style: painted.outline
306
+ }, i);
307
+ case "rotation-guides": return /* @__PURE__ */ jsx("g", { children: node.lines.map((line, j) => /* @__PURE__ */ jsx("line", {
308
+ x1: line.from.x,
309
+ y1: line.from.y,
310
+ x2: line.to.x,
311
+ y2: line.to.y,
312
+ opacity: line.opacity,
313
+ style: painted.rotationGuide
314
+ }, j)) }, i);
315
+ case "rotation-handle":
316
+ if (RotationHandle) {
317
+ custom.push(/* @__PURE__ */ jsx(RotationHandle, {
318
+ at: node.at,
319
+ from: node.from,
320
+ size: chrome.rotationHandle.size,
321
+ rotation: 0,
322
+ active: false
323
+ }, i));
324
+ return null;
325
+ }
326
+ return /* @__PURE__ */ jsxs("g", { children: [chrome.rotationHandle.stalk && /* @__PURE__ */ jsx("line", {
327
+ x1: node.from.x,
328
+ y1: node.from.y,
329
+ x2: node.at.x,
330
+ y2: node.at.y,
331
+ strokeWidth: 1,
332
+ style: { stroke: painted.rotationHandle.stroke }
333
+ }), /* @__PURE__ */ jsx("circle", {
334
+ cx: node.at.x,
335
+ cy: node.at.y,
336
+ r: chrome.rotationHandle.size / 2,
337
+ strokeWidth: 1.5,
338
+ style: painted.rotationHandle
339
+ })] }, i);
340
+ case "marquee": return /* @__PURE__ */ jsx("rect", {
341
+ x: node.box.left,
342
+ y: node.box.top,
343
+ width: node.box.width,
344
+ height: node.box.height,
345
+ strokeWidth: 1,
346
+ strokeDasharray: "4 3",
347
+ style: painted.marquee
348
+ }, i);
349
+ case "outline": return /* @__PURE__ */ jsx("rect", {
350
+ x: node.box.left,
351
+ y: node.box.top,
352
+ width: node.box.width,
353
+ height: node.box.height,
354
+ fill: "none",
355
+ style: painted.outline
356
+ }, i);
357
+ }
358
+ })
359
+ }), custom.length > 0 && /* @__PURE__ */ jsx("div", {
360
+ style: {
361
+ position: "absolute",
362
+ inset: 0,
363
+ pointerEvents: "none"
364
+ },
365
+ children: custom
366
+ })] });
367
+ }
368
+ /**
369
+ * Make an element the editor of a text box: `@embedpdf/web`'s text box
370
+ * editor binds it (rich text, focus and `contentEditable` following
371
+ * `item.editing`, presses kept inside), and its follower attaches again for
372
+ * another element or document and hands it the item and the scale. Returns
373
+ * the ref callback for the element.
374
+ */
375
+ function useTextBoxEditor(item, scale) {
376
+ const anno = useCapability(AnnotationToken$1);
377
+ const [element, setElement] = useState(null);
378
+ const [follower] = useState(() => createTextBoxEditorFollower());
379
+ useEffect(() => follower.follow(element, anno, item, scale), [
380
+ follower,
381
+ anno,
382
+ element,
383
+ item,
384
+ scale
385
+ ]);
386
+ useEffect(() => () => follower.detach(), [follower]);
387
+ return setElement;
388
+ }
389
+ /** A free text annotation: the same styled element for reading and typing. */
390
+ function FreeText({ item, page }) {
391
+ const plate = textPlateInPixels(item, page.transform);
392
+ const ref = useTextBoxEditor(item, plate.scale);
393
+ const { painted } = useChromePaint();
394
+ return /* @__PURE__ */ jsx("div", {
395
+ ref,
396
+ suppressContentEditableWarning: true,
397
+ style: {
398
+ position: "absolute",
399
+ left: plate.left,
400
+ top: plate.top,
401
+ width: plate.width,
402
+ height: plate.height,
403
+ ...textBoxStyleOf(item.css, plate.scale),
404
+ boxSizing: "border-box",
405
+ background: "transparent",
406
+ whiteSpace: "pre-wrap",
407
+ overflowWrap: "break-word",
408
+ overflowY: item.editing ? "auto" : "hidden",
409
+ overflowX: "hidden",
410
+ outline: item.editing ? `1px solid ${painted.textOutline}` : "none",
411
+ cursor: item.editing ? "text" : "default",
412
+ ...item.rot ? {
413
+ transform: `rotate(${item.rot}deg)`,
414
+ transformOrigin: "center"
415
+ } : {},
416
+ pointerEvents: item.editing ? "auto" : "none"
417
+ }
418
+ });
419
+ }
420
+ const NO_STYLE = {};
421
+ /**
422
+ * Make your own element the editor of a text box you draw yourself (a
423
+ * renderer for free text): it draws the runs, turns typing back into runs,
424
+ * keeps the caret when the style changes, and handles pasting, input methods
425
+ * and the format shortcuts. The formatting calls (`text.toggleFormat`,
426
+ * `selection.update`) work on it as they do on the built-in one.
427
+ */
428
+ function useRichTextEditor(annotation) {
429
+ const page = usePage();
430
+ const zoom = page.transform.zoom;
431
+ const rotation = page.transform.rotation;
432
+ const key = annotationKey(annotation.ref);
433
+ const item = useOptionalSelector(AnnotationToken$1, (anno) => anno.listTextItems(page.ref, {
434
+ zoom,
435
+ rotation
436
+ }).find((text) => text.ref !== null && annotationKey(text.ref) === key) ?? null, null);
437
+ const scale = textBoxEditorScaleOf(item, page.transform, React$1.useContext(LookScaleContext));
438
+ return {
439
+ ref: useTextBoxEditor(item, scale),
440
+ style: React$1.useMemo(() => item ? {
441
+ ...textBoxStyleOf(item.css, scale),
442
+ ...item.editing ? { pointerEvents: "auto" } : {}
443
+ } : NO_STYLE, [item, scale]),
444
+ editing: item?.editing ?? false
445
+ };
446
+ }
447
+ /**
448
+ * Register the behaviors this layer's `interactive` renderers need, through
449
+ * `@embedpdf/web`'s `registerRendererBehaviors`: counted per capability and
450
+ * entry, since the layer mounts once per page. Entry identity is the key,
451
+ * hence the "define entries outside render" rule on {@link AnnotationRenderer}.
452
+ * Once they are registered the layer draws again: its drawings ask them.
453
+ */
454
+ function useRendererBehaviors(anno, activeToolId, renderers) {
455
+ const toolRef = useRef(activeToolId);
456
+ toolRef.current = activeToolId;
457
+ const [, setRegistrations] = useState(0);
458
+ useEffect(() => {
459
+ if (!renderers) return;
460
+ const release = registerRendererBehaviors(anno, renderers, () => toolRef.current());
461
+ setRegistrations((count) => count + 1);
462
+ return release;
463
+ }, [anno, renderers]);
464
+ }
465
+ /**
466
+ * Draws a page's annotations, the selection's outline and handles, the tool's
467
+ * preview and the text boxes being typed in. Put it above the rendered page:
468
+ * while it's there, the render layer leaves the annotations out of the
469
+ * page's picture.
470
+ */
471
+ function AnnotationLayer({ renderers, components } = {}) {
472
+ const page = usePage();
473
+ const anno = useCapability(AnnotationToken$1);
474
+ useOptionalSelector(InteractionToken, (interaction) => interaction.getActiveToolId(), "");
475
+ const interaction = useOptionalCapability(InteractionToken);
476
+ const viewZoom = page.transform.zoom;
477
+ const viewRotation = page.transform.rotation;
478
+ const items = useSelector(AnnotationToken$1, (annotation) => annotation.listPageItems(page.ref, {
479
+ zoom: viewZoom,
480
+ rotation: viewRotation
481
+ }), shallowArray);
482
+ const texts = useSelector(AnnotationToken$1, (annotation) => annotation.listTextItems(page.ref, {
483
+ zoom: viewZoom,
484
+ rotation: viewRotation
485
+ }), shallowArray);
486
+ const [urls, setUrls] = useState(null);
487
+ const [shown] = useState(createShownUrls);
488
+ useEffect(() => () => shown.release(), [shown]);
489
+ useRendererBehaviors(anno, () => interaction?.getActiveToolId() ?? "", renderers);
490
+ usePaintsPagePart(page.ref, "annotations");
491
+ const previousRenderers = useRef(renderers);
492
+ if (renderers && previousRenderers.current && renderers !== previousRenderers.current && shallowArray(renderers, previousRenderers.current)) devWarn("annotation-renderers-inline", "<AnnotationLayer renderers> was given a new array with the same entries — define it outside render (module scope or useMemo), because entry identity keys the behavior registration.");
493
+ previousRenderers.current = renderers;
494
+ const bakedKey = useSelector(AnnotationToken$1, (annotation) => annotation.getAppearanceEpoch(page.ref));
495
+ const bakeScale = useOptionalSelector(RenderToken, (render) => render.getAppearanceScale(page.transform.renderScale), page.transform.renderScale);
496
+ useEffect(() => loadAppearanceUrls(shown, (signal) => anno.renderAppearances(page.ref, bakeScale, signal), annotationKey, setUrls), [
497
+ shown,
498
+ anno,
499
+ page.ref,
500
+ bakeScale,
501
+ bakedKey
502
+ ]);
503
+ /** The text box being typed in, by key. */
504
+ const editingKey = editingTextKeyOf(texts, annotationKey);
505
+ return /* @__PURE__ */ jsxs("div", {
506
+ style: {
507
+ position: "absolute",
508
+ inset: 0,
509
+ pointerEvents: "none"
510
+ },
511
+ children: [
512
+ items.map((item) => {
513
+ const state = item.annotation?.appearanceState ?? null;
514
+ const shows = pictureOrPainting({
515
+ pending: item.source !== "baked",
516
+ picture: urls && shownAppearance(urls, item.id, state),
517
+ version: item.pictureVersion ?? 0,
518
+ loaded: urls !== null,
519
+ paint: () => hasLiveDrawing(item) ? item : null
520
+ });
521
+ const native = shows?.kind === "painting" ? /* @__PURE__ */ jsx(Shape, { item }) : shows?.kind === "picture" && item.raster ? /* @__PURE__ */ jsx(BakedImage, {
522
+ url: shows.picture.url,
523
+ box: rasterInFrame(item.raster, item.frame)
524
+ }) : null;
525
+ const framed = (content, options) => /* @__PURE__ */ jsx(AnnotationFrame, {
526
+ item,
527
+ page,
528
+ ...options,
529
+ children: content
530
+ }, item.id);
531
+ const annotation = item.annotation;
532
+ if (!annotation) return framed(native);
533
+ /** Your look in the frame: drawn at the annotation's 100% size and scaled with the page, unless it opts out. */
534
+ const look = (entry, interactive) => {
535
+ const pixels = frameInPixels(item.frame, page.transform);
536
+ const scaled = entry.scale !== false;
537
+ const Look = entry.component;
538
+ const drawn = /* @__PURE__ */ jsx(Look, {
539
+ annotation,
540
+ frame: lookFrameOf(pixels, scaled),
541
+ native,
542
+ appearance: urls && bakedAppearanceOf(urls, item.id, state),
543
+ hovered: item.hovered ?? false,
544
+ selected: item.selected,
545
+ interactive
546
+ });
547
+ if (!scaled) return drawn;
548
+ return /* @__PURE__ */ jsx("div", {
549
+ style: {
550
+ position: "absolute",
551
+ left: 0,
552
+ top: 0,
553
+ width: pixels.design.width,
554
+ height: pixels.design.height,
555
+ transform: `scale(${pixels.scale})`,
556
+ transformOrigin: "0 0"
557
+ },
558
+ children: /* @__PURE__ */ jsx(LookScaleContext.Provider, {
559
+ value: pixels.scale,
560
+ children: drawn
561
+ })
562
+ });
563
+ };
564
+ const typing = editingKey !== null && annotationKey(annotation.ref) === editingKey;
565
+ const drawing = annotationDrawingOf(annotation, anno, renderers, typing);
566
+ switch (drawing.kind) {
567
+ case "owned": {
568
+ const Owner = drawing.entry.component;
569
+ return /* @__PURE__ */ jsx(Owner, {
570
+ annotation,
571
+ item,
572
+ page,
573
+ native: framed(native),
574
+ hovered: item.hovered ?? false,
575
+ selected: item.selected,
576
+ interactive: true
577
+ }, item.id);
578
+ }
579
+ case "look": return framed(look(drawing.entry, drawing.interactive), {
580
+ interactive: drawing.interactive,
581
+ inert: drawing.inert
582
+ });
583
+ case "native": return framed(native, { inert: drawing.inert });
584
+ }
585
+ }),
586
+ layerTextBoxesOf(texts, items, renderers, annotationKey).map((text) => /* @__PURE__ */ jsx(FreeText, {
587
+ item: text,
588
+ page
589
+ }, text.id)),
590
+ /* @__PURE__ */ jsx(ToolGhostImage, { page }),
591
+ /* @__PURE__ */ jsx(Chrome, {
592
+ page,
593
+ components
594
+ })
595
+ ]
596
+ });
597
+ }
598
+ /**
599
+ * The default file-picker provider: the built-in file dialog (from
600
+ * `@embedpdf/web`), honouring the tool's `accept` filter. This is the adapter
601
+ * fulfilling the plugin's DOM-free port — the dialog lives in the framework
602
+ * layer, never in the plugin.
603
+ */
604
+ const filePickerProvider = pickRequestedFile;
605
+ /**
606
+ * Install the file-picker provider for the active document — the one port
607
+ * behind every click-then-pick tool (a stamp `'prompt'` source, the file-
608
+ * attachment tool). Call once at a document-scoped spot (not inside
609
+ * `<AnnotationLayer>`, which is per page). Defaults to
610
+ * {@link filePickerProvider}, so a bare `useFilePickerProvider()` makes all of
611
+ * them work out of the box; pass a custom provider (asset library, cloud
612
+ * drive — switch on `req.subtype` / `req.toolId`) or `null` to make
613
+ * click-then-pick tools inert. Cleared on unmount.
614
+ */
615
+ function useFilePickerProvider(provider = filePickerProvider) {
616
+ const anno = useOptionalCapability(AnnotationToken);
617
+ useEffect(() => {
618
+ if (!anno) return;
619
+ return installFilePickerProvider(anno, provider, () => devWarn("file-picker-provider-twice", "useFilePickerProvider() is called from two mounted components for the same document — the later one wins. Call it once, at a document-scoped spot."));
620
+ }, [anno, provider]);
621
+ }
622
+ function useAnnotation() {
623
+ return useCapability(AnnotationToken);
624
+ }
625
+ /** Listen to one annotation event while the component is mounted: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */
626
+ function useAnnotationEvent(select, handler) {
627
+ useCapabilityEvent(AnnotationToken, select, handler);
628
+ }
629
+ const NO_ANNOTATIONS = [];
630
+ /**
631
+ * The annotations matching `filter` (some pages, one kind), in drawing order,
632
+ * as the user sees them; the same array while they stay the same. Empty
633
+ * without a document.
634
+ */
635
+ function useAnnotationList(filter) {
636
+ const key = filter ? `${(filter.pages ?? []).map((page) => typeof page === "number" ? `#${page}` : page.objectNumber).join(",")}|${filter.pages ? "p" : ""}|${filter.subtype ?? ""}` : "";
637
+ const stable = React$1.useMemo(() => filter, [key]);
638
+ return useOptionalSelector(AnnotationToken, (annotation) => annotation.list(stable), NO_ANNOTATIONS, shallowArray);
639
+ }
640
+ const NO_DEFAULTS = {};
641
+ /**
642
+ * A tool's defaults: the fields its next annotation starts with, over the
643
+ * engine's. The component re-renders when they change, so a color picker
644
+ * always shows the current color. Empty without a document.
645
+ */
646
+ function useAnnotationDefaults(toolId) {
647
+ return useOptionalSelector(AnnotationToken, (annotation) => annotation.tools.getDefaults(toolId), NO_DEFAULTS);
648
+ }
649
+ const NO_PROPERTIES = {
650
+ properties: [],
651
+ values: {},
652
+ mixed: []
653
+ };
654
+ /**
655
+ * What a style panel shows: the selection's properties (`selection.getProperties()`),
656
+ * or, given a tool id, the tool's (`tools.getProperties(id)`). The component
657
+ * re-renders when they change. Empty without a document.
658
+ */
659
+ function useAnnotationProperties(toolId) {
660
+ return useOptionalSelector(AnnotationToken, (annotation) => toolId === void 0 ? annotation.selection.getProperties() : annotation.tools.getProperties(toolId), NO_PROPERTIES);
661
+ }
662
+ /**
663
+ * An anchor for `<Anchored>` that keeps a card or a badge attached to one
664
+ * annotation: its page and the box around what it shows, following a move
665
+ * as it happens. `null` for `null`, or an annotation that isn't here. The
666
+ * component re-renders when the annotation moves, not while people scroll or
667
+ * zoom: a note that keeps its size on screen hands `<Anchored>` its
668
+ * `boundsIn`.
669
+ */
670
+ function useAnnotationAnchor(ref) {
671
+ const key = ref ? annotationKey(ref) : null;
672
+ const stable = React$1.useMemo(() => ref, [key]);
673
+ return useOptionalSelector(AnnotationToken$1, (annotation) => stable ? annotation.getAnnotationAnchor(stable) : null, null, sameAnnotationAnchor);
674
+ }
675
+ /** The comments API: the `comments` part of `useAnnotation()`. Pair it with
676
+ * {@link useCommentThreads} for the threads to show. */
677
+ function useComments() {
678
+ return useCapability(AnnotationToken).comments;
679
+ }
680
+ const EMPTY_PAGES = [];
681
+ const NO_THREADS = [];
682
+ /**
683
+ * Every comment thread in the document, display-ordered (page position →
684
+ * top of page → creation date) and enriched with `pageIndex`/`pageLabel`.
685
+ * Subscribed to both stores: annotation writes (own, remote, hydration)
686
+ * recompute the threads; page moves/deletes re-run the join. Reference-
687
+ * stable between changes — safe to memo child renders on the array.
688
+ */
689
+ function useCommentThreads() {
690
+ const docId = useDocumentId();
691
+ const threads = useOptionalSelector(AnnotationToken, (annotation) => annotation.comments.listThreads(), NO_THREADS);
692
+ const pages = useKernelValue((kernel) => docId ? kernel.documents.listPages(docId) : EMPTY_PAGES);
693
+ return React$1.useMemo(() => enrichCommentThreads(threads, pages), [threads, pages]);
694
+ }
695
+ /** The enriched thread containing any member ref (root, reply, grouped part,
696
+ * state annotation), or null. */
697
+ function useCommentThread(ref) {
698
+ const views = useCommentThreads();
699
+ const api = useOptionalCapability(AnnotationToken);
700
+ if (ref == null || !api) return null;
701
+ const thread = api.comments.getThread(ref);
702
+ if (!thread) return null;
703
+ return views.find((view) => annotationKey(view.root.ref) === annotationKey(thread.root.ref)) ?? null;
704
+ }
705
+ //#endregion
706
+ export { useAnnotationSettings as _, useAnnotationDefaults as a, useAnnotationProperties as c, useComments as d, useFilePickerProvider as f, AnnotationRotationBadge as g, AnnotationMenu as h, useAnnotationAnchor as i, useCommentThread as l, AnnotationDraftMenu as m, filePickerProvider as n, useAnnotationEvent as o, useRichTextEditor as p, useAnnotation as r, useAnnotationList as s, AnnotationLayer as t, useCommentThreads as u, useAnnotationState as v };
707
+
708
+ //# sourceMappingURL=annotation-C1ttM8Wj.js.map