@embedpdf/svelte 0.0.0-stage → 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 (261) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +312 -2
  3. package/dist/actions/readers.svelte.d.ts +29 -0
  4. package/dist/actions/readers.svelte.js +55 -0
  5. package/dist/actions.d.ts +13 -0
  6. package/dist/actions.js +13 -0
  7. package/dist/anchored/Anchored.svelte +24 -0
  8. package/dist/anchored/Anchored.svelte.d.ts +4 -0
  9. package/dist/anchored/PlacedAnchored.svelte +97 -0
  10. package/dist/anchored/PlacedAnchored.svelte.d.ts +4 -0
  11. package/dist/anchored/context.d.ts +31 -0
  12. package/dist/anchored/context.js +36 -0
  13. package/dist/anchored/props.d.ts +29 -0
  14. package/dist/anchored/props.js +1 -0
  15. package/dist/anchored.d.ts +12 -0
  16. package/dist/anchored.js +2 -0
  17. package/dist/annotation/AnnotationChrome.svelte +173 -0
  18. package/dist/annotation/AnnotationChrome.svelte.d.ts +11 -0
  19. package/dist/annotation/AnnotationDraftMenu.svelte +27 -0
  20. package/dist/annotation/AnnotationDraftMenu.svelte.d.ts +4 -0
  21. package/dist/annotation/AnnotationFrame.svelte +46 -0
  22. package/dist/annotation/AnnotationFrame.svelte.d.ts +15 -0
  23. package/dist/annotation/AnnotationLayer.svelte +241 -0
  24. package/dist/annotation/AnnotationLayer.svelte.d.ts +4 -0
  25. package/dist/annotation/AnnotationLook.svelte +67 -0
  26. package/dist/annotation/AnnotationLook.svelte.d.ts +21 -0
  27. package/dist/annotation/AnnotationMenu.svelte +47 -0
  28. package/dist/annotation/AnnotationMenu.svelte.d.ts +4 -0
  29. package/dist/annotation/AnnotationRotationBadge.svelte +52 -0
  30. package/dist/annotation/AnnotationRotationBadge.svelte.d.ts +4 -0
  31. package/dist/annotation/AnnotationScene.svelte +27 -0
  32. package/dist/annotation/AnnotationScene.svelte.d.ts +7 -0
  33. package/dist/annotation/FreeTextBox.svelte +55 -0
  34. package/dist/annotation/FreeTextBox.svelte.d.ts +9 -0
  35. package/dist/annotation/NativeDrawing.svelte +61 -0
  36. package/dist/annotation/NativeDrawing.svelte.d.ts +10 -0
  37. package/dist/annotation/StampGhost.svelte +79 -0
  38. package/dist/annotation/StampGhost.svelte.d.ts +7 -0
  39. package/dist/annotation/chrome-paint.svelte.d.ts +30 -0
  40. package/dist/annotation/chrome-paint.svelte.js +27 -0
  41. package/dist/annotation/props.d.ts +181 -0
  42. package/dist/annotation/props.js +1 -0
  43. package/dist/annotation/readers.svelte.d.ts +59 -0
  44. package/dist/annotation/readers.svelte.js +136 -0
  45. package/dist/annotation/state.d.ts +18 -0
  46. package/dist/annotation/state.js +20 -0
  47. package/dist/annotation/text-box.svelte.d.ts +27 -0
  48. package/dist/annotation/text-box.svelte.js +94 -0
  49. package/dist/annotation.d.ts +32 -0
  50. package/dist/annotation.js +31 -0
  51. package/dist/commands/readers.svelte.d.ts +50 -0
  52. package/dist/commands/readers.svelte.js +83 -0
  53. package/dist/commands.d.ts +9 -0
  54. package/dist/commands.js +9 -0
  55. package/dist/form/ButtonControl.svelte +38 -0
  56. package/dist/form/ButtonControl.svelte.d.ts +11 -0
  57. package/dist/form/ComboControl.svelte +52 -0
  58. package/dist/form/ComboControl.svelte.d.ts +11 -0
  59. package/dist/form/FieldPictures.svelte +145 -0
  60. package/dist/form/FieldPictures.svelte.d.ts +3 -0
  61. package/dist/form/FormFocusRing.svelte +25 -0
  62. package/dist/form/FormFocusRing.svelte.d.ts +8 -0
  63. package/dist/form/FormLayer.svelte +98 -0
  64. package/dist/form/FormLayer.svelte.d.ts +3 -0
  65. package/dist/form/ListControl.svelte +49 -0
  66. package/dist/form/ListControl.svelte.d.ts +11 -0
  67. package/dist/form/NativeListBox.svelte +57 -0
  68. package/dist/form/NativeListBox.svelte.d.ts +4 -0
  69. package/dist/form/SignatureControl.svelte +53 -0
  70. package/dist/form/SignatureControl.svelte.d.ts +11 -0
  71. package/dist/form/TextControl.svelte +107 -0
  72. package/dist/form/TextControl.svelte.d.ts +11 -0
  73. package/dist/form/ToggleControl.svelte +50 -0
  74. package/dist/form/ToggleControl.svelte.d.ts +11 -0
  75. package/dist/form/WidgetBox.svelte +82 -0
  76. package/dist/form/WidgetBox.svelte.d.ts +15 -0
  77. package/dist/form/props.d.ts +21 -0
  78. package/dist/form/props.js +1 -0
  79. package/dist/form/readers.svelte.d.ts +46 -0
  80. package/dist/form/readers.svelte.js +52 -0
  81. package/dist/form/widget.d.ts +16 -0
  82. package/dist/form/widget.js +20 -0
  83. package/dist/form.d.ts +11 -0
  84. package/dist/form.js +12 -0
  85. package/dist/history/readers.d.ts +22 -0
  86. package/dist/history/readers.js +21 -0
  87. package/dist/history.d.ts +10 -0
  88. package/dist/history.js +11 -0
  89. package/dist/i18n/readers.svelte.d.ts +32 -0
  90. package/dist/i18n/readers.svelte.js +30 -0
  91. package/dist/i18n.d.ts +8 -0
  92. package/dist/i18n.js +9 -0
  93. package/dist/index.d.ts +28 -0
  94. package/dist/index.js +28 -0
  95. package/dist/interaction/PagePointerSource.svelte +37 -0
  96. package/dist/interaction/PagePointerSource.svelte.d.ts +3 -0
  97. package/dist/interaction/readers.svelte.d.ts +26 -0
  98. package/dist/interaction/readers.svelte.js +47 -0
  99. package/dist/interaction.d.ts +11 -0
  100. package/dist/interaction.js +13 -0
  101. package/dist/link/LinkLayer.svelte +164 -0
  102. package/dist/link/LinkLayer.svelte.d.ts +4 -0
  103. package/dist/link/props.d.ts +17 -0
  104. package/dist/link/props.js +1 -0
  105. package/dist/link/readers.svelte.d.ts +18 -0
  106. package/dist/link/readers.svelte.js +38 -0
  107. package/dist/link.d.ts +11 -0
  108. package/dist/link.js +11 -0
  109. package/dist/measurement/readers.d.ts +44 -0
  110. package/dist/measurement/readers.js +46 -0
  111. package/dist/measurement.d.ts +12 -0
  112. package/dist/measurement.js +13 -0
  113. package/dist/metadata/readers.d.ts +22 -0
  114. package/dist/metadata/readers.js +22 -0
  115. package/dist/metadata.d.ts +12 -0
  116. package/dist/metadata.js +13 -0
  117. package/dist/page-edit/readers.d.ts +7 -0
  118. package/dist/page-edit/readers.js +11 -0
  119. package/dist/page-edit.d.ts +12 -0
  120. package/dist/page-edit.js +13 -0
  121. package/dist/page-view/PageView.svelte +192 -0
  122. package/dist/page-view/PageView.svelte.d.ts +4 -0
  123. package/dist/page-view/props.d.ts +32 -0
  124. package/dist/page-view/props.js +1 -0
  125. package/dist/page-view.d.ts +8 -0
  126. package/dist/page-view.js +7 -0
  127. package/dist/redaction/readers.d.ts +37 -0
  128. package/dist/redaction/readers.js +38 -0
  129. package/dist/redaction.d.ts +12 -0
  130. package/dist/redaction.js +13 -0
  131. package/dist/render/RenderLayer.svelte +116 -0
  132. package/dist/render/RenderLayer.svelte.d.ts +4 -0
  133. package/dist/render/TileImage.svelte +65 -0
  134. package/dist/render/TileImage.svelte.d.ts +11 -0
  135. package/dist/render/TilePlane.svelte +88 -0
  136. package/dist/render/TilePlane.svelte.d.ts +7 -0
  137. package/dist/render/props.d.ts +16 -0
  138. package/dist/render/props.js +1 -0
  139. package/dist/render/readers.svelte.d.ts +9 -0
  140. package/dist/render/readers.svelte.js +13 -0
  141. package/dist/render.d.ts +10 -0
  142. package/dist/render.js +10 -0
  143. package/dist/runtime/DocumentGate.svelte +26 -0
  144. package/dist/runtime/DocumentGate.svelte.d.ts +4 -0
  145. package/dist/runtime/DocumentScope.svelte +14 -0
  146. package/dist/runtime/DocumentScope.svelte.d.ts +4 -0
  147. package/dist/runtime/KernelProvider.svelte +33 -0
  148. package/dist/runtime/KernelProvider.svelte.d.ts +4 -0
  149. package/dist/runtime/SvgShapes.svelte +30 -0
  150. package/dist/runtime/SvgShapes.svelte.d.ts +8 -0
  151. package/dist/runtime/Viewer.svelte +124 -0
  152. package/dist/runtime/Viewer.svelte.d.ts +4 -0
  153. package/dist/runtime/binding.svelte.d.ts +33 -0
  154. package/dist/runtime/binding.svelte.js +71 -0
  155. package/dist/runtime/capability-handle.d.ts +6 -0
  156. package/dist/runtime/capability-handle.js +71 -0
  157. package/dist/runtime/dev.d.ts +10 -0
  158. package/dist/runtime/dev.js +23 -0
  159. package/dist/runtime/documents.svelte.d.ts +34 -0
  160. package/dist/runtime/documents.svelte.js +49 -0
  161. package/dist/runtime/page-layers.svelte.d.ts +20 -0
  162. package/dist/runtime/page-layers.svelte.js +40 -0
  163. package/dist/runtime/page.d.ts +10 -0
  164. package/dist/runtime/page.js +23 -0
  165. package/dist/runtime/props.d.ts +63 -0
  166. package/dist/runtime/props.js +1 -0
  167. package/dist/runtime/readers.svelte.d.ts +47 -0
  168. package/dist/runtime/readers.svelte.js +122 -0
  169. package/dist/runtime/state.svelte.d.ts +35 -0
  170. package/dist/runtime/state.svelte.js +90 -0
  171. package/dist/runtime/theme.d.ts +12 -0
  172. package/dist/runtime/theme.js +15 -0
  173. package/dist/runtime/values.svelte.d.ts +28 -0
  174. package/dist/runtime/values.svelte.js +51 -0
  175. package/dist/runtime.d.ts +26 -0
  176. package/dist/runtime.js +25 -0
  177. package/dist/search/SearchLayer.svelte +94 -0
  178. package/dist/search/SearchLayer.svelte.d.ts +4 -0
  179. package/dist/search/props.d.ts +11 -0
  180. package/dist/search/props.js +1 -0
  181. package/dist/search/readers.svelte.d.ts +41 -0
  182. package/dist/search/readers.svelte.js +40 -0
  183. package/dist/search.d.ts +11 -0
  184. package/dist/search.js +11 -0
  185. package/dist/selection/SelectionClipboard.svelte +35 -0
  186. package/dist/selection/SelectionClipboard.svelte.d.ts +4 -0
  187. package/dist/selection/SelectionHandles.svelte +192 -0
  188. package/dist/selection/SelectionHandles.svelte.d.ts +4 -0
  189. package/dist/selection/SelectionLayer.svelte +67 -0
  190. package/dist/selection/SelectionLayer.svelte.d.ts +3 -0
  191. package/dist/selection/SelectionMenu.svelte +36 -0
  192. package/dist/selection/SelectionMenu.svelte.d.ts +4 -0
  193. package/dist/selection/props.d.ts +26 -0
  194. package/dist/selection/props.js +1 -0
  195. package/dist/selection/readers.svelte.d.ts +31 -0
  196. package/dist/selection/readers.svelte.js +26 -0
  197. package/dist/selection.d.ts +16 -0
  198. package/dist/selection.js +18 -0
  199. package/dist/shell/readers.svelte.d.ts +40 -0
  200. package/dist/shell/readers.svelte.js +40 -0
  201. package/dist/shell/surface-focus.svelte.d.ts +16 -0
  202. package/dist/shell/surface-focus.svelte.js +33 -0
  203. package/dist/shell.d.ts +12 -0
  204. package/dist/shell.js +11 -0
  205. package/dist/signature/readers.svelte.d.ts +43 -0
  206. package/dist/signature/readers.svelte.js +46 -0
  207. package/dist/signature.d.ts +15 -0
  208. package/dist/signature.js +16 -0
  209. package/dist/stage/PageSurface.svelte +126 -0
  210. package/dist/stage/PageSurface.svelte.d.ts +18 -0
  211. package/dist/stage/Scrollbar.svelte +148 -0
  212. package/dist/stage/Scrollbar.svelte.d.ts +4 -0
  213. package/dist/stage/Stage.svelte +181 -0
  214. package/dist/stage/Stage.svelte.d.ts +4 -0
  215. package/dist/stage/StageScope.svelte +14 -0
  216. package/dist/stage/StageScope.svelte.d.ts +9 -0
  217. package/dist/stage/props.d.ts +71 -0
  218. package/dist/stage/props.js +1 -0
  219. package/dist/stage/readers.svelte.d.ts +39 -0
  220. package/dist/stage/readers.svelte.js +84 -0
  221. package/dist/stage/stage-scope.d.ts +18 -0
  222. package/dist/stage/stage-scope.js +35 -0
  223. package/dist/stage/two-way.svelte.d.ts +13 -0
  224. package/dist/stage/two-way.svelte.js +26 -0
  225. package/dist/stage.d.ts +17 -0
  226. package/dist/stage.js +15 -0
  227. package/dist/stamp/readers.svelte.d.ts +50 -0
  228. package/dist/stamp/readers.svelte.js +76 -0
  229. package/dist/stamp.d.ts +16 -0
  230. package/dist/stamp.js +18 -0
  231. package/dist/toolbar/DefaultCollapsed.svelte +39 -0
  232. package/dist/toolbar/DefaultCollapsed.svelte.d.ts +9 -0
  233. package/dist/toolbar/DefaultCommand.svelte +33 -0
  234. package/dist/toolbar/DefaultCommand.svelte.d.ts +8 -0
  235. package/dist/toolbar/DefaultGroupTrigger.svelte +39 -0
  236. package/dist/toolbar/DefaultGroupTrigger.svelte.d.ts +9 -0
  237. package/dist/toolbar/DefaultOverflowMenu.svelte +106 -0
  238. package/dist/toolbar/DefaultOverflowMenu.svelte.d.ts +9 -0
  239. package/dist/toolbar/DefaultOverflowTrigger.svelte +25 -0
  240. package/dist/toolbar/DefaultOverflowTrigger.svelte.d.ts +7 -0
  241. package/dist/toolbar/Measured.svelte +46 -0
  242. package/dist/toolbar/Measured.svelte.d.ts +11 -0
  243. package/dist/toolbar/NativeSlotSocket.svelte +43 -0
  244. package/dist/toolbar/NativeSlotSocket.svelte.d.ts +11 -0
  245. package/dist/toolbar/Toolbar.svelte +314 -0
  246. package/dist/toolbar/Toolbar.svelte.d.ts +4 -0
  247. package/dist/toolbar/paint.d.ts +3 -0
  248. package/dist/toolbar/paint.js +9 -0
  249. package/dist/toolbar/props.d.ts +48 -0
  250. package/dist/toolbar/props.js +1 -0
  251. package/dist/toolbar/strip.svelte.d.ts +14 -0
  252. package/dist/toolbar/strip.svelte.js +35 -0
  253. package/dist/toolbar/views.d.ts +14 -0
  254. package/dist/toolbar/views.js +1 -0
  255. package/dist/toolbar.d.ts +16 -0
  256. package/dist/toolbar.js +12 -0
  257. package/dist/view-manager/readers.d.ts +19 -0
  258. package/dist/view-manager/readers.js +17 -0
  259. package/dist/view-manager.d.ts +11 -0
  260. package/dist/view-manager.js +12 -0
  261. package/package.json +195 -3
@@ -0,0 +1,79 @@
1
+ <!--
2
+ The armed stamp's ghost: a see-through picture of the stamp in the exact box a click would place
3
+ it (the plugin computes it with the same fit and clamp as placing it). Every other tool's ghost
4
+ rides the page items like a drawing in progress. The picture's bytes stay in the plugin; this
5
+ owns only the object URL, keyed on the armed stamp: a new arm swaps the picture, a disarm (or
6
+ another tool) drops it.
7
+ -->
8
+ <script lang="ts">
9
+ import { untrack } from 'svelte';
10
+ import {
11
+ AnnotationToken as AnnotationHostToken,
12
+ previewBucket,
13
+ } from '@embedpdf/plugin-annotation/contract/host';
14
+ import { ghostOpacity, loadObjectUrl, rectInPixels } from '@embedpdf/web';
15
+ import type { PageContextValue } from '../runtime/page.js';
16
+ import { useOptionalCapability, useOptionalSelector } from '../runtime/readers.svelte.js';
17
+
18
+ let { page }: { page: PageContextValue } = $props();
19
+
20
+ const capability = useOptionalCapability(AnnotationHostToken);
21
+ const ghost = useOptionalSelector(
22
+ AnnotationHostToken,
23
+ (annotation) => annotation.getImageGhost(page.ref),
24
+ null,
25
+ );
26
+ const armed = useOptionalSelector(
27
+ AnnotationHostToken,
28
+ (annotation) => annotation.getArmedStamp(),
29
+ null,
30
+ );
31
+ // The ghost is a picture of vector artwork, right at one size: ask for the bucket that covers
32
+ // the box's device width (points × device pixels per point), so it stays sharp at every zoom
33
+ // and density. The plugin keeps one picture per bucket.
34
+ const bucket = $derived(
35
+ ghost.current ? previewBucket(ghost.current.box.width * page.transform.renderScale) : 0,
36
+ );
37
+
38
+ let url = $state<string | null>(null);
39
+
40
+ $effect(() => {
41
+ const annotation = capability.current;
42
+ const size = bucket;
43
+ void armed.current;
44
+ if (!annotation || !size) {
45
+ url = null;
46
+ return;
47
+ }
48
+ // The previous bucket's picture stays up until this one arrives: no flicker while a zoom
49
+ // crosses a bucket boundary.
50
+ return untrack(() =>
51
+ loadObjectUrl(
52
+ () => annotation.renderArmedStampPreview(size),
53
+ (next) => (url = next),
54
+ ),
55
+ );
56
+ });
57
+
58
+ const frame = $derived(ghost.current ? rectInPixels(ghost.current.box, page.transform) : null);
59
+ </script>
60
+
61
+ {#if ghost.current && frame && url}
62
+ <!-- The same explicit size as a baked appearance: a global img reset must never clamp it. -->
63
+ <img
64
+ src={url}
65
+ alt=""
66
+ draggable="false"
67
+ style:position="absolute"
68
+ style:left="{frame.left}px"
69
+ style:top="{frame.top}px"
70
+ style:width="{frame.width}px"
71
+ style:height="{frame.height}px"
72
+ style:max-width="none"
73
+ style:max-height="none"
74
+ style:pointer-events="none"
75
+ style:opacity={ghostOpacity(ghost.current.opacity)}
76
+ style:transform={ghost.current.rot ? `rotate(${ghost.current.rot}deg)` : undefined}
77
+ style:transform-origin={ghost.current.rot ? 'center' : undefined}
78
+ />
79
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { PageContextValue } from '../runtime/page.js';
2
+ type $$ComponentProps = {
3
+ page: PageContextValue;
4
+ };
5
+ declare const StampGhost: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type StampGhost = ReturnType<typeof StampGhost>;
7
+ export default StampGhost;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The selection chrome's paint, following the annotation settings and the viewer's accent live:
3
+ * every color, width and dash as CSS text for a `style` attribute (`annotationChromePaint` from
4
+ * `@embedpdf/web` gives them as records, each its `--epdf-annotation-*` variable first).
5
+ */
6
+ import type { ChromeSettings } from '@embedpdf/plugin-annotation';
7
+ /** The painted chrome, as CSS text per part. */
8
+ export interface ChromePaintCss {
9
+ /** The selection box. */
10
+ outline: string;
11
+ /** The resize and point handles. */
12
+ handle: string;
13
+ /** The rotation handle. */
14
+ rotationHandle: string;
15
+ /** The rotation handle's stalk: the handle's stroke. */
16
+ rotationStalk: string;
17
+ /** A snapped move's alignment guide. */
18
+ guide: string;
19
+ /** The reference cross and the angle line while turning. */
20
+ rotationGuide: string;
21
+ /** The box dragged to select. */
22
+ marquee: string;
23
+ /** The outline color of a text box while someone types in it. */
24
+ textOutline: string;
25
+ }
26
+ /** The chrome settings and their paint; call it while a component is created. */
27
+ export declare function useChromePaint(): {
28
+ readonly chrome: ChromeSettings;
29
+ readonly css: ChromePaintCss;
30
+ };
@@ -0,0 +1,27 @@
1
+ import { annotationChromePaint, cssText } from '@embedpdf/web';
2
+ import { useViewerSettings } from '../runtime/documents.svelte.js';
3
+ import { useAnnotationSettings } from './state.js';
4
+ const asCss = (painted) => ({
5
+ outline: cssText(painted.outline),
6
+ handle: cssText(painted.handle),
7
+ rotationHandle: cssText(painted.rotationHandle),
8
+ rotationStalk: cssText({ stroke: painted.rotationHandle.stroke }),
9
+ guide: cssText(painted.guide),
10
+ rotationGuide: cssText(painted.rotationGuide),
11
+ marquee: cssText(painted.marquee),
12
+ textOutline: painted.textOutline,
13
+ });
14
+ /** The chrome settings and their paint; call it while a component is created. */
15
+ export function useChromePaint() {
16
+ const chrome = useAnnotationSettings((settings) => settings.chrome);
17
+ const accent = useViewerSettings((settings) => settings.accent);
18
+ const css = $derived(asCss(annotationChromePaint(chrome.current, accent.current)));
19
+ return {
20
+ get chrome() {
21
+ return chrome.current;
22
+ },
23
+ get css() {
24
+ return css;
25
+ },
26
+ };
27
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * The types an app writes against when it draws annotations its own way: a renderer (which
3
+ * annotations, with which component), the props that component gets, what the layer's `handle`
4
+ * and `rotationHandle` snippets get, the props of the layer and the menus, and what
5
+ * `useRichTextEditor()` and `useCommentThreads()` return.
6
+ */
7
+ import type { Component, Snippet } from 'svelte';
8
+ import type { Attachment } from 'svelte/attachments';
9
+ import type { CreationDraftAnchor, Point, RenderItem, RotationAnchor } from '@embedpdf/core-annotation';
10
+ import type { Annotation, CommentThread, HandleRole } from '@embedpdf/plugin-annotation';
11
+ import type { AnchoredPlacement } from '@embedpdf/web';
12
+ import type { PageContextValue } from '../runtime/page.js';
13
+ /** The box a renderer draws into: the size to draw at, how it's turned, and how it's scaled. */
14
+ export interface AnnotationFrame {
15
+ /** Its width in pixels at the annotation's 100% size, before its turn: draw at this. */
16
+ width: number;
17
+ /** Its height in pixels at the annotation's 100% size, before its turn: draw at this. */
18
+ height: number;
19
+ /**
20
+ * How it's turned on screen, degrees clockwise: the page's turn and the annotation's own. 0 is
21
+ * upright; turn your content by `-rotation` to keep it upright.
22
+ */
23
+ rotation: number;
24
+ /**
25
+ * How much the layer scales what you draw, with the page: the zoom, or for an annotation that
26
+ * keeps its size on screen, the zoom up to 1.
27
+ */
28
+ scale: number;
29
+ }
30
+ /**
31
+ * What a renderer's component gets as props: the annotation, the frame to draw into, and the
32
+ * layer's own drawing of it to keep or wrap. The layer keeps handling the pointer (select, move,
33
+ * resize) unless the renderer is `interactive`.
34
+ */
35
+ export interface AnnotationRendererProps {
36
+ /** The annotation, as `get()` returns it. */
37
+ annotation: Annotation;
38
+ /**
39
+ * The box you draw into. The layer places, turns and scales it like the annotation's own
40
+ * drawing, also during a drag, a resize or a turn. Fill it (`width: 100%; height: 100%`) and
41
+ * draw at the annotation's 100% size: your text and borders scale with the page.
42
+ */
43
+ frame: AnnotationFrame;
44
+ /** The layer's own drawing of it, filling the frame: `{@render native()}` keeps the original look, to add to it. */
45
+ native: Snippet;
46
+ /** The engine's picture of the annotation as an image (`url`), or `null`. `native` draws it in place. */
47
+ appearance: {
48
+ url: string;
49
+ } | null;
50
+ /** True while the pointer is over it. */
51
+ hovered: boolean;
52
+ /** True while it's selected. */
53
+ selected: boolean;
54
+ /** True when what you draw takes the pointer (see `interactive` on the renderer). */
55
+ interactive: boolean;
56
+ }
57
+ /**
58
+ * What a sibling plugin's renderer gets for the annotations its behavior owns (the form plugin's
59
+ * fill controls). It places its own controls: `item` is the layer's projection of the annotation
60
+ * (its box, style, text and raster box, in page coordinates), and `page.transform.toPixels()`
61
+ * turns those into the layer's pixels.
62
+ */
63
+ export interface BehaviorRendererProps {
64
+ annotation: Annotation;
65
+ item: RenderItem;
66
+ page: PageContextValue;
67
+ /** The layer's own drawing of it, in its frame where the layer draws it: `{@render native()}`. */
68
+ native: Snippet;
69
+ hovered: boolean;
70
+ selected: boolean;
71
+ interactive: boolean;
72
+ }
73
+ /** What an `interactive` function is asked: the annotation, and the active tool. */
74
+ export interface AnnotationInteractiveContext {
75
+ annotation: Annotation;
76
+ toolId: string;
77
+ }
78
+ /**
79
+ * One rule: "draw these annotations with this component". `for` gets the annotation with all its
80
+ * fields; the first renderer that matches wins. Without `interactive` the component only draws:
81
+ * the layer keeps handling the pointer. With `interactive` (or a function asked whenever it
82
+ * matters) the component takes the pointer, and the annotation can't be selected or moved while
83
+ * it does.
84
+ *
85
+ * Define the list once, in `<script>`: the layer registers each entry, and a list written inline
86
+ * in the markup is a new one whenever the markup runs again.
87
+ *
88
+ * `{ behavior, component }` draws what a sibling plugin's behavior owns (the form plugin's fill
89
+ * controls); the plugin decides when it's engaged.
90
+ */
91
+ export type AnnotationRenderer = {
92
+ behavior: string;
93
+ component: Component<BehaviorRendererProps>;
94
+ } | {
95
+ /** A stable id for the registration (optional; generated). */
96
+ id?: string;
97
+ for: (annotation: Annotation) => boolean;
98
+ component: Component<AnnotationRendererProps>;
99
+ interactive?: boolean | ((context: AnnotationInteractiveContext) => boolean);
100
+ /**
101
+ * Scale what you draw with the page (the default): you draw at the annotation's 100% size.
102
+ * `false`: you draw at its size on screen, and size things yourself from `frame.scale`.
103
+ */
104
+ scale?: boolean;
105
+ };
106
+ /** What the layer's `handle` snippet gets: one handle to draw. */
107
+ export interface HandleProps {
108
+ /** The handle's center, in pixels on the page. */
109
+ at: Point;
110
+ /** The `size` from the settings, px. */
111
+ size: number;
112
+ /** The selection's rotation (degrees clockwise), so a square handle can turn with it. */
113
+ rotation: number;
114
+ /** A box's `'corner'` or `'side'`, or one `'point'` of a line or a polygon. */
115
+ kind: HandleRole;
116
+ /** True while it's being dragged. */
117
+ active: boolean;
118
+ }
119
+ /** What the layer's `rotationHandle` snippet gets: a handle's props, and where its stalk starts on the box. */
120
+ export interface RotationHandleProps extends Omit<HandleProps, 'kind'> {
121
+ /** Where the stalk starts on the box, in pixels on the page. */
122
+ from: Point;
123
+ }
124
+ export interface AnnotationLayerProps {
125
+ /** Your own look for some annotations ({@link AnnotationRenderer}). Define the list once, in `<script>`. */
126
+ renderers?: AnnotationRenderer[];
127
+ /** Draw each handle yourself, in place of the layer's. The viewer still decides where it can be grabbed. */
128
+ handle?: Snippet<[handle: HandleProps]>;
129
+ /** Draw the rotation handle yourself, in place of the layer's. */
130
+ rotationHandle?: Snippet<[handle: RotationHandleProps]>;
131
+ }
132
+ /** What `useRichTextEditor()` gives the element you draw a text box with. */
133
+ export interface RichTextEditor {
134
+ /** Put it on your element (`{@attach editor.attach}`): it becomes the editor. Render nothing inside it. */
135
+ readonly attach: Attachment<HTMLElement>;
136
+ /** The box's body style as CSS (`style={editor.style}`): font, size, color and alignment. While typing it takes the pointer too. */
137
+ readonly style: string;
138
+ /** True while someone types in the box. */
139
+ readonly editing: boolean;
140
+ }
141
+ /**
142
+ * A {@link CommentThread} with where its page is shown now. Identity stays `page` (like every
143
+ * annotation surface); these two fields are presentation, following page moves and deletes.
144
+ */
145
+ export interface CommentThreadView extends CommentThread {
146
+ /** Current 0-based display index of the thread's page; `-1` when the page is no longer in the document (for the one update before it goes). */
147
+ pageIndex: number;
148
+ /** The page's `/PageLabels` label when the PDF declares one ("iv", "A-2"), else the 1-based position as a string: print it as it is. */
149
+ pageLabel: string;
150
+ }
151
+ export interface AnnotationMenuProps {
152
+ /** The menu: buttons that call `useAnnotation()`, built from `useAnnotationState()`. */
153
+ children: Snippet;
154
+ /** The gap in screen pixels between the selection box and the menu. Default 15. */
155
+ gap?: number;
156
+ /** Where the menu sits next to the selection box. Default `'top'`. */
157
+ placement?: AnchoredPlacement;
158
+ }
159
+ export interface AnnotationDraftMenuProps {
160
+ /**
161
+ * The menu, given the shape being drawn (`subtype`, `pointCount`, `minPoints`, `canFinish`, …).
162
+ * The verbs are capability calls: `useAnnotation().draft.finish()` and `.draft.cancel()`.
163
+ */
164
+ children: Snippet<[draft: CreationDraftAnchor]>;
165
+ /** The gap in screen pixels between the shape being drawn and the menu. Default 8. */
166
+ gap?: number;
167
+ /** Where the menu sits next to the shape being drawn. Default `'top'`. */
168
+ placement?: AnchoredPlacement;
169
+ }
170
+ export interface AnnotationRotationBadgeProps {
171
+ /**
172
+ * The badge, given the rotation in progress (`angle`, degrees clockwise, as the commit will
173
+ * apply it). Without it, the badge shows the angle in the `chrome.readout` colors, when
174
+ * `chrome.readout.enabled`.
175
+ */
176
+ children?: Snippet<[rotation: RotationAnchor]>;
177
+ /** The gap in screen pixels between the pointer and the badge. Default 16. */
178
+ gap?: number;
179
+ /** Where the badge sits next to the pointer. Default `'right'`. */
180
+ placement?: AnchoredPlacement;
181
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ import type { EventHook } from '@embedpdf/core';
2
+ import { type Annotation, type AnnotationAnchor, type AnnotationCapability, type AnnotationFilter, type AnnotationProperties, type AnnotationRef, type CommentsApi, type FilePickerProvider, type ToolDefaults } from '@embedpdf/plugin-annotation';
3
+ import { type CurrentValue, type MaybeGetter } from '../runtime/values.svelte.js';
4
+ import type { CommentThreadView } from './props.js';
5
+ /** The API: a handle, always the capability of the document in scope. */
6
+ export declare function useAnnotation(): AnnotationCapability;
7
+ /** Listen to one annotation event while the component lives: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */
8
+ export declare function useAnnotationEvent<T>(select: (annotation: AnnotationCapability) => EventHook<T>, handler: (event: T) => void): void;
9
+ /**
10
+ * The annotations matching `filter` (some pages, one kind), in drawing order, as the user sees
11
+ * them: `list.current`, the same array while they stay the same. Empty without a document.
12
+ */
13
+ export declare function useAnnotationList(filter?: MaybeGetter<AnnotationFilter | undefined>): CurrentValue<readonly Annotation[]>;
14
+ /**
15
+ * A tool's defaults (`defaults.current`): the fields its next annotation starts with, over the
16
+ * engine's. It updates when they change, so a color picker always shows the current color. Empty
17
+ * without a document.
18
+ */
19
+ export declare function useAnnotationDefaults(toolId: MaybeGetter<string>): CurrentValue<ToolDefaults>;
20
+ /**
21
+ * What a style panel shows (`panel.current`): the selection's properties
22
+ * (`selection.getProperties()`), or, given a tool id, the tool's (`tools.getProperties(id)`). It
23
+ * updates when they change. Empty without a document.
24
+ */
25
+ export declare function useAnnotationProperties(toolId?: MaybeGetter<string | undefined>): CurrentValue<AnnotationProperties>;
26
+ /**
27
+ * An anchor for `<Anchored>` that keeps a card or a badge attached to one annotation
28
+ * (`anchor.current`): its page and the box around what it shows, following a move as it happens.
29
+ * `null` for `null`, or an annotation that isn't here. It updates when the annotation moves, not
30
+ * while people scroll or zoom: a note that keeps its size on screen hands `<Anchored>` its
31
+ * `boundsIn`.
32
+ */
33
+ export declare function useAnnotationAnchor(ref: MaybeGetter<AnnotationRef | null>): CurrentValue<AnnotationAnchor | null>;
34
+ /** The comments API: the `comments` part of `useAnnotation()`. Pair it with {@link useCommentThreads} for the threads to show. */
35
+ export declare function useComments(): CommentsApi;
36
+ /**
37
+ * Every comment thread in the document (`threads.current`), in display order (page position, top
38
+ * of page, creation date), each with its page's `pageIndex` and `pageLabel`. Annotation writes
39
+ * (your own, remote ones, the first load) and page moves or deletes update it; the same array
40
+ * between changes.
41
+ */
42
+ export declare function useCommentThreads(): CurrentValue<CommentThreadView[]>;
43
+ /** The thread holding any of its annotations (the comment, a reply, a state), or `null`: `thread.current`. */
44
+ export declare function useCommentThread(ref: MaybeGetter<AnnotationRef | null>): CurrentValue<CommentThreadView | null>;
45
+ /**
46
+ * The default file-picker provider: the browser's file dialog (from `@embedpdf/web`), honouring
47
+ * the tool's `accept` filter. The adapter fulfils the plugin's DOM-free port; the dialog lives
48
+ * here, never in the plugin.
49
+ */
50
+ export declare const filePickerProvider: FilePickerProvider;
51
+ /**
52
+ * Install the file-picker provider for the document in scope: the one port behind every
53
+ * click-then-pick tool (a stamp's `'prompt'` source, the file-attachment tool). Call it once, in a
54
+ * component around the pages (not in a page layer). Without an argument it installs
55
+ * {@link filePickerProvider}, so those tools work out of the box; pass your own provider (an
56
+ * asset library, a cloud drive: switch on `request.subtype` / `request.toolId`), or `null` to
57
+ * make them do nothing. Removed when the component goes away. The provider is read once.
58
+ */
59
+ export declare function useFilePickerProvider(provider?: FilePickerProvider | null): void;
@@ -0,0 +1,136 @@
1
+ /**
2
+ * The annotation plugin's readers: the API (`useAnnotation()`), its events, and the reads a
3
+ * component follows on their own, each `{ current }`: the annotations of a filter, a tool's
4
+ * defaults, a style panel's properties, an annotation's anchor, and the comment threads.
5
+ * `useFilePickerProvider()` installs the file dialog behind click-then-pick tools.
6
+ *
7
+ * An argument that changes is a function (`useAnnotationAnchor(() => note.ref)`), read again
8
+ * whenever the value is.
9
+ */
10
+ import { untrack } from 'svelte';
11
+ import { AnnotationToken, annotationKey, } from '@embedpdf/plugin-annotation';
12
+ // The anchor of one annotation is a host read (the same runtime token, typed wider).
13
+ import { AnnotationToken as AnnotationHostToken } from '@embedpdf/plugin-annotation/contract/host';
14
+ import { enrichCommentThreads, installFilePickerProvider, pickRequestedFile, sameAnnotationAnchor, } from '@embedpdf/web';
15
+ import { devWarn } from '../runtime/dev.js';
16
+ import { shallowArray, useCapability, useCapabilityEvent, useDocumentId, useKernelValue, useOptionalCapability, useOptionalSelector, } from '../runtime/readers.svelte.js';
17
+ import { currentOf, derivedValue, valueOf, } from '../runtime/values.svelte.js';
18
+ /** The API: a handle, always the capability of the document in scope. */
19
+ export function useAnnotation() {
20
+ return useCapability(AnnotationToken);
21
+ }
22
+ /** Listen to one annotation event while the component lives: `useAnnotationEvent((annotation) => annotation.onCreated, handler)`. */
23
+ export function useAnnotationEvent(select, handler) {
24
+ useCapabilityEvent(AnnotationToken, select, handler);
25
+ }
26
+ const NO_ANNOTATIONS = Object.freeze([]);
27
+ /**
28
+ * The annotations matching `filter` (some pages, one kind), in drawing order, as the user sees
29
+ * them: `list.current`, the same array while they stay the same. Empty without a document.
30
+ */
31
+ export function useAnnotationList(filter) {
32
+ return useOptionalSelector(AnnotationToken, (annotation) => annotation.list(valueOf(filter)), NO_ANNOTATIONS, shallowArray);
33
+ }
34
+ const NO_DEFAULTS = Object.freeze({});
35
+ /**
36
+ * A tool's defaults (`defaults.current`): the fields its next annotation starts with, over the
37
+ * engine's. It updates when they change, so a color picker always shows the current color. Empty
38
+ * without a document.
39
+ */
40
+ export function useAnnotationDefaults(toolId) {
41
+ return useOptionalSelector(AnnotationToken, (annotation) => annotation.tools.getDefaults(valueOf(toolId)), NO_DEFAULTS);
42
+ }
43
+ const NO_PROPERTIES = Object.freeze({
44
+ properties: [],
45
+ values: {},
46
+ mixed: [],
47
+ });
48
+ /**
49
+ * What a style panel shows (`panel.current`): the selection's properties
50
+ * (`selection.getProperties()`), or, given a tool id, the tool's (`tools.getProperties(id)`). It
51
+ * updates when they change. Empty without a document.
52
+ */
53
+ export function useAnnotationProperties(toolId) {
54
+ return useOptionalSelector(AnnotationToken, (annotation) => {
55
+ const tool = valueOf(toolId);
56
+ return tool === undefined
57
+ ? annotation.selection.getProperties()
58
+ : annotation.tools.getProperties(tool);
59
+ }, NO_PROPERTIES);
60
+ }
61
+ /**
62
+ * An anchor for `<Anchored>` that keeps a card or a badge attached to one annotation
63
+ * (`anchor.current`): its page and the box around what it shows, following a move as it happens.
64
+ * `null` for `null`, or an annotation that isn't here. It updates when the annotation moves, not
65
+ * while people scroll or zoom: a note that keeps its size on screen hands `<Anchored>` its
66
+ * `boundsIn`.
67
+ */
68
+ export function useAnnotationAnchor(ref) {
69
+ return useOptionalSelector(AnnotationHostToken, (annotation) => {
70
+ const target = valueOf(ref);
71
+ return target ? annotation.getAnnotationAnchor(target) : null;
72
+ }, null, sameAnnotationAnchor);
73
+ }
74
+ // ── comments ─────────────────────────────────────────────────────────────────
75
+ /** The comments API: the `comments` part of `useAnnotation()`. Pair it with {@link useCommentThreads} for the threads to show. */
76
+ export function useComments() {
77
+ return useCapability(AnnotationToken).comments;
78
+ }
79
+ const NO_PAGES = Object.freeze([]);
80
+ const NO_THREADS = Object.freeze([]);
81
+ /**
82
+ * Every comment thread in the document (`threads.current`), in display order (page position, top
83
+ * of page, creation date), each with its page's `pageIndex` and `pageLabel`. Annotation writes
84
+ * (your own, remote ones, the first load) and page moves or deletes update it; the same array
85
+ * between changes.
86
+ */
87
+ export function useCommentThreads() {
88
+ const documentId = useDocumentId();
89
+ const threads = useOptionalSelector(AnnotationToken, (annotation) => annotation.comments.listThreads(), NO_THREADS);
90
+ const pages = useKernelValue((kernel) => documentId.current ? kernel.documents.listPages(documentId.current) : NO_PAGES);
91
+ return currentOf(derivedValue(() => enrichCommentThreads(threads.current, pages.current)));
92
+ }
93
+ /** The thread holding any of its annotations (the comment, a reply, a state), or `null`: `thread.current`. */
94
+ export function useCommentThread(ref) {
95
+ const views = useCommentThreads();
96
+ const capability = useOptionalCapability(AnnotationToken);
97
+ return currentOf(derivedValue(() => {
98
+ // Read first: every annotation write gives new threads, so this runs again.
99
+ const shown = views.current;
100
+ const target = valueOf(ref);
101
+ const annotation = capability.current;
102
+ if (target == null || !annotation)
103
+ return null;
104
+ const thread = annotation.comments.getThread(target);
105
+ if (!thread)
106
+ return null;
107
+ const root = annotationKey(thread.root.ref);
108
+ return shown.find((view) => annotationKey(view.root.ref) === root) ?? null;
109
+ }));
110
+ }
111
+ // ── the file picker ──────────────────────────────────────────────────────────
112
+ /**
113
+ * The default file-picker provider: the browser's file dialog (from `@embedpdf/web`), honouring
114
+ * the tool's `accept` filter. The adapter fulfils the plugin's DOM-free port; the dialog lives
115
+ * here, never in the plugin.
116
+ */
117
+ export const filePickerProvider = pickRequestedFile;
118
+ /**
119
+ * Install the file-picker provider for the document in scope: the one port behind every
120
+ * click-then-pick tool (a stamp's `'prompt'` source, the file-attachment tool). Call it once, in a
121
+ * component around the pages (not in a page layer). Without an argument it installs
122
+ * {@link filePickerProvider}, so those tools work out of the box; pass your own provider (an
123
+ * asset library, a cloud drive: switch on `request.subtype` / `request.toolId`), or `null` to
124
+ * make them do nothing. Removed when the component goes away. The provider is read once.
125
+ */
126
+ export function useFilePickerProvider(provider = filePickerProvider) {
127
+ const capability = useOptionalCapability(AnnotationToken);
128
+ $effect(() => {
129
+ const annotation = capability.current;
130
+ if (!annotation)
131
+ return;
132
+ // One port per document: a second caller silently replaces the first.
133
+ return untrack(() => installFilePickerProvider(annotation, provider, () => devWarn('file-picker-provider-twice', 'useFilePickerProvider() is called from two mounted components for the same document — ' +
134
+ 'the later one wins. Call it once, in a component around the pages.')));
135
+ });
136
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The annotation state: `status` (`'loading'` until every annotation is in, then `'ready'`), the
3
+ * `selected` annotations, the one `hovered` under the pointer and the text box being typed in
4
+ * (`editing`). A reactive object (`state.selected`), each field updating on its own; with a
5
+ * selector, the value it picks as `{ current }`. Empty without a document.
6
+ */
7
+ export declare const useAnnotationState: import("../index.js").StateReader<{
8
+ status: import("@embedpdf/core").ResourceStatus;
9
+ selected: readonly import("@embedpdf/plugin-annotation").Annotation[];
10
+ hovered: import("@embedpdf/plugin-annotation").Annotation | null;
11
+ editing: import("@embedpdf/plugin-annotation").Annotation | null;
12
+ }>;
13
+ /**
14
+ * The annotation settings (`snap`, `chrome`, `afterCreate`, `tools`), or the value `select` picks
15
+ * as `{ current }`. They belong to the plugin, so they read without a document; change them with
16
+ * `useAnnotation().updateSettings()`.
17
+ */
18
+ export declare const useAnnotationSettings: import("../index.js").SettingsReader<import("@embedpdf/plugin-annotation").AnnotationSettings & object>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The annotation readers other feature entries use too (the form plugin reads the selection),
3
+ * kept apart so they don't import the whole annotation entry: the state and the settings, each
4
+ * from its declaration.
5
+ */
6
+ import { AnnotationToken, annotationState } from '@embedpdf/plugin-annotation/contract';
7
+ import { settingsReader, stateReader } from '../runtime/state.svelte.js';
8
+ /**
9
+ * The annotation state: `status` (`'loading'` until every annotation is in, then `'ready'`), the
10
+ * `selected` annotations, the one `hovered` under the pointer and the text box being typed in
11
+ * (`editing`). A reactive object (`state.selected`), each field updating on its own; with a
12
+ * selector, the value it picks as `{ current }`. Empty without a document.
13
+ */
14
+ export const useAnnotationState = stateReader(annotationState);
15
+ /**
16
+ * The annotation settings (`snap`, `chrome`, `afterCreate`, `tools`), or the value `select` picks
17
+ * as `{ current }`. They belong to the plugin, so they read without a document; change them with
18
+ * `useAnnotation().updateSettings()`.
19
+ */
20
+ export const useAnnotationSettings = settingsReader(AnnotationToken);
@@ -0,0 +1,27 @@
1
+ import type { Attachment } from 'svelte/attachments';
2
+ import type { Annotation, TextItem } from '@embedpdf/plugin-annotation';
3
+ import { type MaybeGetter } from '../runtime/values.svelte.js';
4
+ import type { RichTextEditor } from './props.js';
5
+ /**
6
+ * An attachment that makes its element the editor of the text box `item()` gives, at `scale()`
7
+ * pixels per point. Call it while a component is created. The element must stay empty in the
8
+ * markup: the editor owns what's inside it.
9
+ */
10
+ export declare function textBoxEditor(item: () => TextItem | null, scale: () => number): Attachment<HTMLElement>;
11
+ /** For the layer, around a look it scales: how much it scales what the look draws. */
12
+ export declare function setLookScale(scale: () => number): void;
13
+ /**
14
+ * Make your own element the editor of a text box you draw yourself (a renderer for free text):
15
+ * it draws the runs, turns typing back into runs, keeps the caret when the style changes, and
16
+ * handles pasting, input methods and the format shortcuts. The formatting calls
17
+ * (`text.toggleFormat`, `selection.update`) work on it as they do on the layer's own.
18
+ *
19
+ * ```svelte
20
+ * const editor = useRichTextEditor(() => annotation);
21
+ * <div {@attach editor.attach} class={['box', editor.editing && 'editing']} style={editor.style}></div>
22
+ * ```
23
+ *
24
+ * `attach` goes on your element (render nothing inside it: the editor owns what's in it); `style`
25
+ * and `editing` follow the box.
26
+ */
27
+ export declare function useRichTextEditor(annotation: MaybeGetter<Annotation>): RichTextEditor;