@embedpdf/svelte 0.0.0-stage → 3.0.0-next.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) 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 +51 -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 +28 -0
  48. package/dist/annotation/text-box.svelte.js +87 -0
  49. package/dist/annotation.d.ts +32 -0
  50. package/dist/annotation.js +31 -0
  51. package/dist/attachment/readers.d.ts +23 -0
  52. package/dist/attachment/readers.js +21 -0
  53. package/dist/attachment.d.ts +13 -0
  54. package/dist/attachment.js +14 -0
  55. package/dist/commands/readers.svelte.d.ts +50 -0
  56. package/dist/commands/readers.svelte.js +83 -0
  57. package/dist/commands.d.ts +9 -0
  58. package/dist/commands.js +9 -0
  59. package/dist/form/ButtonControl.svelte +38 -0
  60. package/dist/form/ButtonControl.svelte.d.ts +11 -0
  61. package/dist/form/ComboControl.svelte +52 -0
  62. package/dist/form/ComboControl.svelte.d.ts +11 -0
  63. package/dist/form/FieldPictures.svelte +145 -0
  64. package/dist/form/FieldPictures.svelte.d.ts +3 -0
  65. package/dist/form/FormFocusRing.svelte +25 -0
  66. package/dist/form/FormFocusRing.svelte.d.ts +8 -0
  67. package/dist/form/FormLayer.svelte +98 -0
  68. package/dist/form/FormLayer.svelte.d.ts +3 -0
  69. package/dist/form/ListControl.svelte +49 -0
  70. package/dist/form/ListControl.svelte.d.ts +11 -0
  71. package/dist/form/NativeListBox.svelte +57 -0
  72. package/dist/form/NativeListBox.svelte.d.ts +4 -0
  73. package/dist/form/SignatureControl.svelte +53 -0
  74. package/dist/form/SignatureControl.svelte.d.ts +11 -0
  75. package/dist/form/TextControl.svelte +107 -0
  76. package/dist/form/TextControl.svelte.d.ts +11 -0
  77. package/dist/form/ToggleControl.svelte +50 -0
  78. package/dist/form/ToggleControl.svelte.d.ts +11 -0
  79. package/dist/form/WidgetBox.svelte +82 -0
  80. package/dist/form/WidgetBox.svelte.d.ts +15 -0
  81. package/dist/form/props.d.ts +21 -0
  82. package/dist/form/props.js +1 -0
  83. package/dist/form/readers.svelte.d.ts +46 -0
  84. package/dist/form/readers.svelte.js +52 -0
  85. package/dist/form/widget.d.ts +16 -0
  86. package/dist/form/widget.js +20 -0
  87. package/dist/form.d.ts +11 -0
  88. package/dist/form.js +12 -0
  89. package/dist/history/readers.d.ts +22 -0
  90. package/dist/history/readers.js +21 -0
  91. package/dist/history.d.ts +10 -0
  92. package/dist/history.js +11 -0
  93. package/dist/i18n/readers.svelte.d.ts +32 -0
  94. package/dist/i18n/readers.svelte.js +30 -0
  95. package/dist/i18n.d.ts +8 -0
  96. package/dist/i18n.js +9 -0
  97. package/dist/index.d.ts +30 -0
  98. package/dist/index.js +30 -0
  99. package/dist/interaction/PagePointerSource.svelte +37 -0
  100. package/dist/interaction/PagePointerSource.svelte.d.ts +3 -0
  101. package/dist/interaction/readers.svelte.d.ts +26 -0
  102. package/dist/interaction/readers.svelte.js +47 -0
  103. package/dist/interaction.d.ts +11 -0
  104. package/dist/interaction.js +13 -0
  105. package/dist/link/LinkLayer.svelte +164 -0
  106. package/dist/link/LinkLayer.svelte.d.ts +4 -0
  107. package/dist/link/props.d.ts +17 -0
  108. package/dist/link/props.js +1 -0
  109. package/dist/link/readers.svelte.d.ts +18 -0
  110. package/dist/link/readers.svelte.js +38 -0
  111. package/dist/link.d.ts +11 -0
  112. package/dist/link.js +11 -0
  113. package/dist/measurement/readers.d.ts +44 -0
  114. package/dist/measurement/readers.js +46 -0
  115. package/dist/measurement.d.ts +12 -0
  116. package/dist/measurement.js +13 -0
  117. package/dist/metadata/readers.d.ts +22 -0
  118. package/dist/metadata/readers.js +22 -0
  119. package/dist/metadata.d.ts +12 -0
  120. package/dist/metadata.js +13 -0
  121. package/dist/outline/readers.d.ts +26 -0
  122. package/dist/outline/readers.js +22 -0
  123. package/dist/outline.d.ts +12 -0
  124. package/dist/outline.js +13 -0
  125. package/dist/page-edit/readers.d.ts +17 -0
  126. package/dist/page-edit/readers.js +18 -0
  127. package/dist/page-edit.d.ts +12 -0
  128. package/dist/page-edit.js +13 -0
  129. package/dist/page-view/PageView.svelte +192 -0
  130. package/dist/page-view/PageView.svelte.d.ts +4 -0
  131. package/dist/page-view/props.d.ts +32 -0
  132. package/dist/page-view/props.js +1 -0
  133. package/dist/page-view.d.ts +8 -0
  134. package/dist/page-view.js +7 -0
  135. package/dist/redaction/readers.d.ts +37 -0
  136. package/dist/redaction/readers.js +38 -0
  137. package/dist/redaction.d.ts +12 -0
  138. package/dist/redaction.js +13 -0
  139. package/dist/render/RenderLayer.svelte +116 -0
  140. package/dist/render/RenderLayer.svelte.d.ts +4 -0
  141. package/dist/render/TileImage.svelte +65 -0
  142. package/dist/render/TileImage.svelte.d.ts +11 -0
  143. package/dist/render/TilePlane.svelte +88 -0
  144. package/dist/render/TilePlane.svelte.d.ts +7 -0
  145. package/dist/render/props.d.ts +16 -0
  146. package/dist/render/props.js +1 -0
  147. package/dist/render/readers.svelte.d.ts +9 -0
  148. package/dist/render/readers.svelte.js +13 -0
  149. package/dist/render.d.ts +10 -0
  150. package/dist/render.js +10 -0
  151. package/dist/runtime/DocumentGate.svelte +26 -0
  152. package/dist/runtime/DocumentGate.svelte.d.ts +4 -0
  153. package/dist/runtime/DocumentScope.svelte +14 -0
  154. package/dist/runtime/DocumentScope.svelte.d.ts +4 -0
  155. package/dist/runtime/KernelProvider.svelte +33 -0
  156. package/dist/runtime/KernelProvider.svelte.d.ts +4 -0
  157. package/dist/runtime/SvgShapes.svelte +30 -0
  158. package/dist/runtime/SvgShapes.svelte.d.ts +8 -0
  159. package/dist/runtime/Viewer.svelte +130 -0
  160. package/dist/runtime/Viewer.svelte.d.ts +4 -0
  161. package/dist/runtime/binding.svelte.d.ts +33 -0
  162. package/dist/runtime/binding.svelte.js +71 -0
  163. package/dist/runtime/capability-handle.d.ts +6 -0
  164. package/dist/runtime/capability-handle.js +71 -0
  165. package/dist/runtime/dev.d.ts +10 -0
  166. package/dist/runtime/dev.js +23 -0
  167. package/dist/runtime/documents.svelte.d.ts +34 -0
  168. package/dist/runtime/documents.svelte.js +49 -0
  169. package/dist/runtime/page-layers.svelte.d.ts +20 -0
  170. package/dist/runtime/page-layers.svelte.js +40 -0
  171. package/dist/runtime/page.d.ts +10 -0
  172. package/dist/runtime/page.js +23 -0
  173. package/dist/runtime/props.d.ts +63 -0
  174. package/dist/runtime/props.js +1 -0
  175. package/dist/runtime/readers.svelte.d.ts +47 -0
  176. package/dist/runtime/readers.svelte.js +122 -0
  177. package/dist/runtime/state.svelte.d.ts +35 -0
  178. package/dist/runtime/state.svelte.js +90 -0
  179. package/dist/runtime/theme.d.ts +12 -0
  180. package/dist/runtime/theme.js +15 -0
  181. package/dist/runtime/values.svelte.d.ts +28 -0
  182. package/dist/runtime/values.svelte.js +51 -0
  183. package/dist/runtime.d.ts +26 -0
  184. package/dist/runtime.js +25 -0
  185. package/dist/search/SearchLayer.svelte +94 -0
  186. package/dist/search/SearchLayer.svelte.d.ts +4 -0
  187. package/dist/search/props.d.ts +11 -0
  188. package/dist/search/props.js +1 -0
  189. package/dist/search/readers.svelte.d.ts +41 -0
  190. package/dist/search/readers.svelte.js +40 -0
  191. package/dist/search.d.ts +11 -0
  192. package/dist/search.js +11 -0
  193. package/dist/selection/SelectionClipboard.svelte +35 -0
  194. package/dist/selection/SelectionClipboard.svelte.d.ts +4 -0
  195. package/dist/selection/SelectionHandles.svelte +192 -0
  196. package/dist/selection/SelectionHandles.svelte.d.ts +4 -0
  197. package/dist/selection/SelectionLayer.svelte +67 -0
  198. package/dist/selection/SelectionLayer.svelte.d.ts +3 -0
  199. package/dist/selection/SelectionMenu.svelte +36 -0
  200. package/dist/selection/SelectionMenu.svelte.d.ts +4 -0
  201. package/dist/selection/props.d.ts +26 -0
  202. package/dist/selection/props.js +1 -0
  203. package/dist/selection/readers.svelte.d.ts +31 -0
  204. package/dist/selection/readers.svelte.js +26 -0
  205. package/dist/selection.d.ts +16 -0
  206. package/dist/selection.js +18 -0
  207. package/dist/shell/readers.svelte.d.ts +40 -0
  208. package/dist/shell/readers.svelte.js +40 -0
  209. package/dist/shell/surface-focus.svelte.d.ts +16 -0
  210. package/dist/shell/surface-focus.svelte.js +33 -0
  211. package/dist/shell.d.ts +12 -0
  212. package/dist/shell.js +11 -0
  213. package/dist/signature/readers.svelte.d.ts +43 -0
  214. package/dist/signature/readers.svelte.js +46 -0
  215. package/dist/signature.d.ts +15 -0
  216. package/dist/signature.js +16 -0
  217. package/dist/stage/PageSurface.svelte +126 -0
  218. package/dist/stage/PageSurface.svelte.d.ts +18 -0
  219. package/dist/stage/Scrollbar.svelte +148 -0
  220. package/dist/stage/Scrollbar.svelte.d.ts +4 -0
  221. package/dist/stage/Stage.svelte +181 -0
  222. package/dist/stage/Stage.svelte.d.ts +4 -0
  223. package/dist/stage/StageScope.svelte +14 -0
  224. package/dist/stage/StageScope.svelte.d.ts +9 -0
  225. package/dist/stage/props.d.ts +71 -0
  226. package/dist/stage/props.js +1 -0
  227. package/dist/stage/readers.svelte.d.ts +39 -0
  228. package/dist/stage/readers.svelte.js +84 -0
  229. package/dist/stage/stage-scope.d.ts +18 -0
  230. package/dist/stage/stage-scope.js +35 -0
  231. package/dist/stage/two-way.svelte.d.ts +13 -0
  232. package/dist/stage/two-way.svelte.js +26 -0
  233. package/dist/stage.d.ts +17 -0
  234. package/dist/stage.js +15 -0
  235. package/dist/stamp/readers.svelte.d.ts +50 -0
  236. package/dist/stamp/readers.svelte.js +76 -0
  237. package/dist/stamp.d.ts +16 -0
  238. package/dist/stamp.js +18 -0
  239. package/dist/toolbar/DefaultCollapsed.svelte +39 -0
  240. package/dist/toolbar/DefaultCollapsed.svelte.d.ts +9 -0
  241. package/dist/toolbar/DefaultCommand.svelte +33 -0
  242. package/dist/toolbar/DefaultCommand.svelte.d.ts +8 -0
  243. package/dist/toolbar/DefaultGroupTrigger.svelte +39 -0
  244. package/dist/toolbar/DefaultGroupTrigger.svelte.d.ts +9 -0
  245. package/dist/toolbar/DefaultOverflowMenu.svelte +106 -0
  246. package/dist/toolbar/DefaultOverflowMenu.svelte.d.ts +9 -0
  247. package/dist/toolbar/DefaultOverflowTrigger.svelte +25 -0
  248. package/dist/toolbar/DefaultOverflowTrigger.svelte.d.ts +7 -0
  249. package/dist/toolbar/Measured.svelte +46 -0
  250. package/dist/toolbar/Measured.svelte.d.ts +11 -0
  251. package/dist/toolbar/NativeSlotSocket.svelte +43 -0
  252. package/dist/toolbar/NativeSlotSocket.svelte.d.ts +11 -0
  253. package/dist/toolbar/Toolbar.svelte +314 -0
  254. package/dist/toolbar/Toolbar.svelte.d.ts +4 -0
  255. package/dist/toolbar/paint.d.ts +3 -0
  256. package/dist/toolbar/paint.js +9 -0
  257. package/dist/toolbar/props.d.ts +48 -0
  258. package/dist/toolbar/props.js +1 -0
  259. package/dist/toolbar/strip.svelte.d.ts +14 -0
  260. package/dist/toolbar/strip.svelte.js +35 -0
  261. package/dist/toolbar/views.d.ts +14 -0
  262. package/dist/toolbar/views.js +1 -0
  263. package/dist/toolbar.d.ts +16 -0
  264. package/dist/toolbar.js +12 -0
  265. package/dist/view-manager/readers.d.ts +19 -0
  266. package/dist/view-manager/readers.js +17 -0
  267. package/dist/view-manager.d.ts +11 -0
  268. package/dist/view-manager.js +12 -0
  269. package/package.json +207 -3
@@ -0,0 +1,97 @@
1
+ <!--
2
+ Anchored content on a page that is shown: it follows the camera. The position is computed from
3
+ the surface's projection (the shared, framework-free `projectAnchoredTarget`) whenever the
4
+ projection, the anchor or the measured size changes. A click inside never reaches the
5
+ surface's own pointer listener, which would read it as a click outside.
6
+ -->
7
+ <script lang="ts">
8
+ import { untrack } from 'svelte';
9
+ import {
10
+ isolatePointerDown,
11
+ observeAnchoredFit,
12
+ projectAnchoredTarget,
13
+ sameAnchoredFit,
14
+ type AnchoredFit,
15
+ } from '@embedpdf/web';
16
+ import { useProjectorBinding } from './context.js';
17
+ import type { AnchoredProps } from './props.js';
18
+
19
+ let { anchor, placement = 'top', gap = 8, pinned = false, children }: AnchoredProps = $props();
20
+
21
+ const binding = useProjectorBinding();
22
+ let element: HTMLDivElement | undefined = $state();
23
+ // The content's size and the view's: measured once it's in the DOM, and again when either
24
+ // resizes. A camera move changes neither.
25
+ let fit = $state.raw<AnchoredFit | null>(null);
26
+ // Changes no state announces: a `<PageView>` that moved because the document scrolled, and the
27
+ // first pass of a client-space surface, which can only measure once it's in the DOM.
28
+ let browserMoves = $state(0);
29
+
30
+ $effect(() => {
31
+ const subscribe = binding().subscribe;
32
+ if (!subscribe) return;
33
+ return subscribe(() => untrack(() => browserMoves++));
34
+ });
35
+ $effect(() => {
36
+ if (binding().projector.space !== 'client') return;
37
+ void anchor;
38
+ untrack(() => browserMoves++);
39
+ });
40
+
41
+ $effect(() => {
42
+ const target = element;
43
+ const space = binding().projector.space;
44
+ if (!target) return;
45
+ return observeAnchoredFit(target, space, (next) => {
46
+ if (
47
+ !sameAnchoredFit(
48
+ untrack(() => fit),
49
+ next,
50
+ )
51
+ )
52
+ fit = next;
53
+ });
54
+ });
55
+
56
+ // A native listener: Svelte delegates `onpointerdown` to the root, which the press reaches
57
+ // only after the surface's own listener saw it.
58
+ $effect(() => {
59
+ if (!element) return;
60
+ return isolatePointerDown(element);
61
+ });
62
+
63
+ const projector = $derived(binding().projector);
64
+ const position = $derived.by(() => {
65
+ void binding().revision;
66
+ void browserMoves;
67
+ if (!anchor?.bounds) return null;
68
+ return projectAnchoredTarget(
69
+ projector,
70
+ { ...anchor, bounds: anchor.bounds },
71
+ { placement, gap, pinned },
72
+ fit,
73
+ );
74
+ });
75
+
76
+ /** Client-space content lives on the body, where no ancestor's overflow clips it. */
77
+ function portal(node: HTMLElement) {
78
+ if (projector.space !== 'client') return;
79
+ node.ownerDocument.body.appendChild(node);
80
+ return () => node.remove();
81
+ }
82
+ </script>
83
+
84
+ {#if position}
85
+ <div
86
+ bind:this={element}
87
+ {@attach portal}
88
+ style:position={projector.space === 'client' ? 'fixed' : 'absolute'}
89
+ style:left="{position.left}px"
90
+ style:top="{position.top}px"
91
+ style:width="max-content"
92
+ style:transform={position.transform}
93
+ style:pointer-events="auto"
94
+ >
95
+ {@render children?.()}
96
+ </div>
97
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { AnchoredProps } from './props.js';
2
+ declare const PlacedAnchored: import("svelte").Component<AnchoredProps, {}, "">;
3
+ type PlacedAnchored = ReturnType<typeof PlacedAnchored>;
4
+ export default PlacedAnchored;
@@ -0,0 +1,31 @@
1
+ import type { ViewProjector } from '@embedpdf/web';
2
+ export interface ProjectorBinding {
3
+ projector: ViewProjector;
4
+ /**
5
+ * Changes whenever projection may have changed for a state reason; the Stage uses its visible
6
+ * pages (a value that already folds camera, viewport, scene and pixel ratio). Readers read it
7
+ * so they compute again; nothing looks inside it.
8
+ */
9
+ revision: unknown;
10
+ /**
11
+ * For changes no state announces, such as a `<PageView>` moving because the document
12
+ * scrolled (see `observeClientGeometry`). The Stage provides none.
13
+ */
14
+ subscribe?: (callback: () => void) => () => void;
15
+ }
16
+ /**
17
+ * The pages a surface shows right now, by object number. A value of its own, next to the
18
+ * projection, because it changes only when a page comes on screen or leaves it: anchored UI on
19
+ * the other pages reads only this, so it sits out every camera frame.
20
+ */
21
+ export type ShownPages = ReadonlySet<number>;
22
+ /** For page surfaces: provide the projection to the anchored UI inside. */
23
+ export declare function setProjectorBinding(binding: () => ProjectorBinding): void;
24
+ /** For page surfaces: provide the pages shown. */
25
+ export declare function setShownPages(shown: () => ShownPages): void;
26
+ /** The surface's projection, or null outside any page surface, for chrome that degrades instead of throwing. */
27
+ export declare function useOptionalProjectorBinding(): (() => ProjectorBinding) | null;
28
+ /** The surface's projection. Throws outside a page surface. */
29
+ export declare function useProjectorBinding(): () => ProjectorBinding;
30
+ /** The pages the surface shows, or null outside one (then every page counts as shown). */
31
+ export declare function useShownPages(): (() => ShownPages) | null;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * What a page surface (`<Stage>`, `<PageView>`) gives the anchored UI inside it: the projection,
3
+ * and the pages it shows. The projection snapshot and the placement math are framework-free, in
4
+ * `@embedpdf/web` ({@link ViewProjector}, `projectAnchoredTarget`).
5
+ *
6
+ * Both are provided as functions that return the current value. A Stage's projection changes on
7
+ * every camera frame (its binding is a `$derived` of the visible pages), so the surface and its
8
+ * overlay update in the same flush and never paint a frame apart.
9
+ */
10
+ import { getContext, hasContext, setContext } from 'svelte';
11
+ const PROJECTOR = Symbol('embedpdf.projector');
12
+ const SHOWN_PAGES = Symbol('embedpdf.shown-pages');
13
+ /** For page surfaces: provide the projection to the anchored UI inside. */
14
+ export function setProjectorBinding(binding) {
15
+ setContext(PROJECTOR, binding);
16
+ }
17
+ /** For page surfaces: provide the pages shown. */
18
+ export function setShownPages(shown) {
19
+ setContext(SHOWN_PAGES, shown);
20
+ }
21
+ /** The surface's projection, or null outside any page surface, for chrome that degrades instead of throwing. */
22
+ export function useOptionalProjectorBinding() {
23
+ return hasContext(PROJECTOR) ? getContext(PROJECTOR) : null;
24
+ }
25
+ /** The surface's projection. Throws outside a page surface. */
26
+ export function useProjectorBinding() {
27
+ const binding = useOptionalProjectorBinding();
28
+ if (!binding) {
29
+ throw new Error('[embedpdf] No ViewProjector in scope: put anchored UI in a <Stage> (its overlay snippet) or a <PageView>.');
30
+ }
31
+ return binding;
32
+ }
33
+ /** The pages the surface shows, or null outside one (then every page counts as shown). */
34
+ export function useShownPages() {
35
+ return hasContext(SHOWN_PAGES) ? getContext(SHOWN_PAGES) : null;
36
+ }
@@ -0,0 +1,29 @@
1
+ /** The props of `<Anchored>`. */
2
+ import type { Snippet } from 'svelte';
3
+ import type { AnchoredPlacement, AnchoredRect, AnchorTarget } from '@embedpdf/web';
4
+ export interface AnchoredProps {
5
+ /**
6
+ * The box on a page to sit next to, in page coordinates: `{ page, bounds }`, with `avoid`
7
+ * points to keep clear of. `null`, or a target without `bounds` (a search match with no
8
+ * geometry), hides it.
9
+ */
10
+ anchor: (Omit<AnchorTarget, 'bounds'> & {
11
+ bounds?: AnchoredRect;
12
+ }) | null;
13
+ /**
14
+ * Where to sit: a side of the box, centred, or lined up with the side's start or end
15
+ * (`'top-end'`). Default `'top'`.
16
+ */
17
+ placement?: AnchoredPlacement;
18
+ /**
19
+ * The gap in screen pixels between the box and the content, and between the content and the
20
+ * view's edge. Negative overlaps the box. Default 8.
21
+ */
22
+ gap?: number;
23
+ /**
24
+ * Stay where `placement` puts it: never flip to the other side, never move to stay in view,
25
+ * and scroll away with the box. For badges and status; menus leave it off. Default false.
26
+ */
27
+ pinned?: boolean;
28
+ children?: Snippet;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @embedpdf/svelte/anchored — UI that floats over page content.
3
+ *
4
+ * Plugins give anchors (a page-space box on a page, and points to keep clear of); `<Anchored>`
5
+ * places content next to one, on whichever page surface it's in: a `<Stage>`'s overlay, or a
6
+ * `<PageView>`. The placement math is framework-free, in `@embedpdf/web`.
7
+ */
8
+ export type { AnchoredPlacement, AnchoredSide, AnchorTarget, PageViewEnv, ViewProjector, } from '@embedpdf/web';
9
+ export { default as Anchored } from './anchored/Anchored.svelte';
10
+ export type { AnchoredProps } from './anchored/props.js';
11
+ export { setProjectorBinding, setShownPages, useOptionalProjectorBinding, useProjectorBinding, useShownPages, } from './anchored/context.js';
12
+ export type { ProjectorBinding, ShownPages } from './anchored/context.js';
@@ -0,0 +1,2 @@
1
+ export { default as Anchored } from './anchored/Anchored.svelte';
2
+ export { setProjectorBinding, setShownPages, useOptionalProjectorBinding, useProjectorBinding, useShownPages, } from './anchored/context.js';
@@ -0,0 +1,173 @@
1
+ <!--
2
+ The selection's chrome on one page: its outline (turned with a turned selection), the resize
3
+ and point handles, the rotation handle, a snapped move's guides, a turn's guides and the box
4
+ dragged to select. The plugin lists the parts in page points; `@embedpdf/web` puts them in
5
+ pixels and paints them, so their `--epdf-annotation-*` CSS variables win. The layer's handles
6
+ are SVG; your `handle` and `rotationHandle` snippets draw as HTML over the page instead.
7
+ -->
8
+ <script lang="ts">
9
+ import type { Snippet } from 'svelte';
10
+ import type { ChromeNode } from '@embedpdf/core-annotation';
11
+ // The chrome is a host read (the same runtime token, typed wider).
12
+ import { AnnotationToken as AnnotationHostToken } from '@embedpdf/plugin-annotation/contract/host';
13
+ import { chromeInPixels } from '@embedpdf/web';
14
+ import type { PageContextValue } from '../runtime/page.js';
15
+ import { shallowArray, useOptionalSelector } from '../runtime/readers.svelte.js';
16
+ import { useChromePaint } from './chrome-paint.svelte.js';
17
+ import type { HandleProps, RotationHandleProps } from './props.js';
18
+
19
+ let {
20
+ page,
21
+ handle,
22
+ rotationHandle,
23
+ }: {
24
+ page: PageContextValue;
25
+ handle?: Snippet<[handle: HandleProps]>;
26
+ rotationHandle?: Snippet<[handle: RotationHandleProps]>;
27
+ } = $props();
28
+
29
+ const NO_NODES: readonly ChromeNode[] = Object.freeze([]);
30
+
31
+ // The page's view scale turns the screen-pixel chrome settings into page units inside the
32
+ // plugin (the rotation handle's offset, the grab zones): constant on screen at every zoom.
33
+ // What this draws is in screen pixels already.
34
+ const nodes = useOptionalSelector(
35
+ AnnotationHostToken,
36
+ (annotation) =>
37
+ annotation.listChromeNodes(
38
+ page.ref,
39
+ page.transform.viewScale,
40
+ page.transform.rotation,
41
+ page.transform.zoom,
42
+ ),
43
+ NO_NODES,
44
+ shallowArray,
45
+ );
46
+ const paint = useChromePaint();
47
+ const parts = $derived(chromeInPixels(nodes.current, page.transform));
48
+ const yours = $derived(
49
+ parts.filter(
50
+ (part) =>
51
+ (part.kind === 'handle' && handle) || (part.kind === 'rotation-handle' && rotationHandle),
52
+ ),
53
+ );
54
+ </script>
55
+
56
+ <svg style="position: absolute; inset: 0; overflow: visible; pointer-events: none">
57
+ {#each parts as part, index (index)}
58
+ {#if part.kind === 'handle' && !handle}
59
+ {@const size = paint.chrome.handles.size}
60
+ {#if paint.chrome.handles.shape === 'circle'}
61
+ <circle
62
+ cx={part.at.x}
63
+ cy={part.at.y}
64
+ r={size / 2}
65
+ stroke-width="1.5"
66
+ style={paint.css.handle}
67
+ />
68
+ {:else}
69
+ <!-- The square rides a turned box's orientation (it spins about itself). -->
70
+ <rect
71
+ x={part.at.x - size / 2}
72
+ y={part.at.y - size / 2}
73
+ width={size}
74
+ height={size}
75
+ stroke-width="1.5"
76
+ style={paint.css.handle}
77
+ transform={part.rotation
78
+ ? `rotate(${part.rotation} ${part.at.x} ${part.at.y})`
79
+ : undefined}
80
+ />
81
+ {/if}
82
+ {:else if part.kind === 'guide'}
83
+ <line
84
+ x1={part.from.x}
85
+ y1={part.from.y}
86
+ x2={part.to.x}
87
+ y2={part.to.y}
88
+ shape-rendering="crispEdges"
89
+ style={paint.css.guide}
90
+ />
91
+ {:else if part.kind === 'turned-outline'}
92
+ <polygon points={part.points} fill="none" style={paint.css.outline} />
93
+ {:else if part.kind === 'rotation-guides'}
94
+ <g>
95
+ {#each part.lines as line, lineIndex (lineIndex)}
96
+ <line
97
+ x1={line.from.x}
98
+ y1={line.from.y}
99
+ x2={line.to.x}
100
+ y2={line.to.y}
101
+ opacity={line.opacity}
102
+ style={paint.css.rotationGuide}
103
+ />
104
+ {/each}
105
+ </g>
106
+ {:else if part.kind === 'rotation-handle' && !rotationHandle}
107
+ <g>
108
+ {#if paint.chrome.rotationHandle.stalk}
109
+ <line
110
+ x1={part.from.x}
111
+ y1={part.from.y}
112
+ x2={part.at.x}
113
+ y2={part.at.y}
114
+ stroke-width="1"
115
+ style={paint.css.rotationStalk}
116
+ />
117
+ {/if}
118
+ <circle
119
+ cx={part.at.x}
120
+ cy={part.at.y}
121
+ r={paint.chrome.rotationHandle.size / 2}
122
+ stroke-width="1.5"
123
+ style={paint.css.rotationHandle}
124
+ />
125
+ </g>
126
+ {:else if part.kind === 'marquee'}
127
+ <!-- The box dragged to select keeps its own look (a see-through accent fill, always
128
+ dashed); the selection outline follows the settings. -->
129
+ <rect
130
+ x={part.box.left}
131
+ y={part.box.top}
132
+ width={part.box.width}
133
+ height={part.box.height}
134
+ stroke-width="1"
135
+ stroke-dasharray="4 3"
136
+ style={paint.css.marquee}
137
+ />
138
+ {:else if part.kind === 'outline'}
139
+ <rect
140
+ x={part.box.left}
141
+ y={part.box.top}
142
+ width={part.box.width}
143
+ height={part.box.height}
144
+ fill="none"
145
+ style={paint.css.outline}
146
+ />
147
+ {/if}
148
+ {/each}
149
+ </svg>
150
+ {#if yours.length > 0}
151
+ <div style="position: absolute; inset: 0; pointer-events: none">
152
+ {#each yours as part, index (index)}
153
+ {#if part.kind === 'handle'}
154
+ {@render handle?.({
155
+ at: part.at,
156
+ size: paint.chrome.handles.size,
157
+ rotation: part.rotation,
158
+ kind: part.role,
159
+ active: part.active,
160
+ })}
161
+ {:else if part.kind === 'rotation-handle'}
162
+ <!-- Your rotation handle stands still while it's dragged: the badge shows the angle. -->
163
+ {@render rotationHandle?.({
164
+ at: part.at,
165
+ from: part.from,
166
+ size: paint.chrome.rotationHandle.size,
167
+ rotation: 0,
168
+ active: false,
169
+ })}
170
+ {/if}
171
+ {/each}
172
+ </div>
173
+ {/if}
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { PageContextValue } from '../runtime/page.js';
3
+ import type { HandleProps, RotationHandleProps } from './props.js';
4
+ type $$ComponentProps = {
5
+ page: PageContextValue;
6
+ handle?: Snippet<[handle: HandleProps]>;
7
+ rotationHandle?: Snippet<[handle: RotationHandleProps]>;
8
+ };
9
+ declare const AnnotationChrome: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type AnnotationChrome = ReturnType<typeof AnnotationChrome>;
11
+ export default AnnotationChrome;
@@ -0,0 +1,27 @@
1
+ <!--
2
+ A menu over a shape being drawn click by click (a polygon, a polyline): the `children` snippet
3
+ gets the shape (`canFinish`, `pointCount`, …). The verbs are the API's:
4
+ `useAnnotation().draft.finish()` and `.draft.cancel()`.
5
+ -->
6
+ <script lang="ts">
7
+ import { AnnotationToken } from '@embedpdf/plugin-annotation';
8
+ import { sameCreationDraftAnchor } from '@embedpdf/web';
9
+ import Anchored from '../anchored/Anchored.svelte';
10
+ import { useOptionalSelector } from '../runtime/readers.svelte.js';
11
+ import type { AnnotationDraftMenuProps } from './props.js';
12
+
13
+ let { children, gap = 8, placement = 'top' }: AnnotationDraftMenuProps = $props();
14
+
15
+ const draft = useOptionalSelector(
16
+ AnnotationToken,
17
+ (annotation) => annotation.draft.get(),
18
+ null,
19
+ sameCreationDraftAnchor,
20
+ );
21
+ </script>
22
+
23
+ {#if draft.current}
24
+ <Anchored anchor={draft.current} {placement} {gap}>
25
+ {@render children(draft.current)}
26
+ </Anchored>
27
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { AnnotationDraftMenuProps } from './props.js';
2
+ declare const AnnotationDraftMenu: import("svelte").Component<AnnotationDraftMenuProps, {}, "">;
3
+ type AnnotationDraftMenu = ReturnType<typeof AnnotationDraftMenu>;
4
+ export default AnnotationDraftMenu;
@@ -0,0 +1,46 @@
1
+ <!--
2
+ The box an annotation draws into, placed, sized and turned like the annotation (`item.frame`)
3
+ inside the page layer, which the page itself turns. The annotation's own drawing and any look
4
+ of yours draw inside it.
5
+ -->
6
+ <script lang="ts">
7
+ import type { Snippet } from 'svelte';
8
+ import type { RenderItem } from '@embedpdf/core-annotation';
9
+ import { frameInPixels } from '@embedpdf/web';
10
+ import type { PageContextValue } from '../runtime/page.js';
11
+
12
+ let {
13
+ item,
14
+ page,
15
+ interactive = false,
16
+ inert = false,
17
+ children,
18
+ }: {
19
+ item: RenderItem;
20
+ page: PageContextValue;
21
+ /** An interactive renderer takes the pointer: the layer's own `none` ends here. */
22
+ interactive?: boolean;
23
+ /** No pointer and no focus for anything inside: a look that only draws. */
24
+ inert?: boolean;
25
+ children: Snippet;
26
+ } = $props();
27
+
28
+ const box = $derived(frameInPixels(item.frame, page.transform));
29
+ </script>
30
+
31
+ <!-- The blend is on the frame: a turned frame groups what is inside it, so blending on an inner
32
+ element would stop blending with the page. -->
33
+ <div
34
+ {inert}
35
+ style:position="absolute"
36
+ style:left="{box.left}px"
37
+ style:top="{box.top}px"
38
+ style:width="{box.width}px"
39
+ style:height="{box.height}px"
40
+ style:transform={box.transform}
41
+ style:transform-origin="center"
42
+ style:mix-blend-mode={item.blend}
43
+ style:pointer-events={interactive ? 'auto' : 'none'}
44
+ >
45
+ {@render children()}
46
+ </div>
@@ -0,0 +1,15 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { RenderItem } from '@embedpdf/core-annotation';
3
+ import type { PageContextValue } from '../runtime/page.js';
4
+ type $$ComponentProps = {
5
+ item: RenderItem;
6
+ page: PageContextValue;
7
+ /** An interactive renderer takes the pointer: the layer's own `none` ends here. */
8
+ interactive?: boolean;
9
+ /** No pointer and no focus for anything inside: a look that only draws. */
10
+ inert?: boolean;
11
+ children: Snippet;
12
+ };
13
+ declare const AnnotationFrame: import("svelte").Component<$$ComponentProps, {}, "">;
14
+ type AnnotationFrame = ReturnType<typeof AnnotationFrame>;
15
+ export default AnnotationFrame;