@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,16 @@
1
+ /** The props of `<RenderLayer>`. */
2
+ export interface RenderLayerProps {
3
+ /**
4
+ * Draw the annotations into the page's picture (`true`) or leave them out (`false`). Left
5
+ * unset, the picture leaves them to an `<AnnotationLayer>` on the page, and otherwise draws them
6
+ * when the user may read them.
7
+ */
8
+ annotations?: boolean;
9
+ /** The same for the form fields, which a `<FormLayer>` paints. */
10
+ formFields?: boolean;
11
+ /**
12
+ * Mount the tile plane (default true). Whether it spends anything is the render plugin's
13
+ * arithmetic: leave it on, and pass false only for a view that must never tile.
14
+ */
15
+ tiles?: boolean;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ /** The render plugin's readers: its API, its settings and its events. */
2
+ import type { EventHook } from '@embedpdf/core';
3
+ import type { RenderCapability } from '@embedpdf/plugin-render';
4
+ /** The render API (`renderPage`, `renderThumbnail`, invalidation, settings), for app code. */
5
+ export declare function useRender(): RenderCapability;
6
+ /** The render settings (`fullPage`, `tiles`, `format`, …), with or without a document. */
7
+ export declare const useRenderSettings: import("../index.js").SettingsReader<import("@embedpdf/plugin-render").RenderSettings & object>;
8
+ /** Subscribe to one render event while the component lives: `useRenderEvent((render) => render.onInvalidated, handler)`. */
9
+ export declare function useRenderEvent<T>(select: (render: RenderCapability) => EventHook<T>, handler: (event: T) => void): void;
@@ -0,0 +1,13 @@
1
+ import { RenderToken } from '@embedpdf/plugin-render';
2
+ import { useCapability, useCapabilityEvent } from '../runtime/readers.svelte.js';
3
+ import { settingsReader } from '../runtime/state.svelte.js';
4
+ /** The render API (`renderPage`, `renderThumbnail`, invalidation, settings), for app code. */
5
+ export function useRender() {
6
+ return useCapability(RenderToken);
7
+ }
8
+ /** The render settings (`fullPage`, `tiles`, `format`, …), with or without a document. */
9
+ export const useRenderSettings = settingsReader(RenderToken);
10
+ /** Subscribe to one render event while the component lives: `useRenderEvent((render) => render.onInvalidated, handler)`. */
11
+ export function useRenderEvent(select, handler) {
12
+ useCapabilityEvent(RenderToken, select, handler);
13
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @embedpdf/svelte/render — the page raster.
3
+ *
4
+ * `<RenderLayer>` draws a page's picture inside a `<Stage>` page or a `<PageView>`; the readers
5
+ * are the render plugin's API, settings and events, for thumbnails and previews of your own.
6
+ */
7
+ export * from '@embedpdf/plugin-render';
8
+ export { default as RenderLayer } from './render/RenderLayer.svelte';
9
+ export type { RenderLayerProps } from './render/props.js';
10
+ export { useRender, useRenderEvent, useRenderSettings } from './render/readers.svelte.js';
package/dist/render.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @embedpdf/svelte/render — the page raster.
3
+ *
4
+ * `<RenderLayer>` draws a page's picture inside a `<Stage>` page or a `<PageView>`; the readers
5
+ * are the render plugin's API, settings and events, for thumbnails and previews of your own.
6
+ */
7
+ // Registration travels with the UI.
8
+ export * from '@embedpdf/plugin-render';
9
+ export { default as RenderLayer } from './render/RenderLayer.svelte';
10
+ export { useRender, useRenderEvent, useRenderSettings } from './render/readers.svelte.js';
@@ -0,0 +1,26 @@
1
+ <!--
2
+ Renders its content only while this subtree has a ready document: the structural way to say
3
+ "this UI is defined over a document". Workspace UI (toolbars, commands, translations) lives
4
+ outside the gate; document UI (the Stage, panels, page chrome) inside it. A document that waits
5
+ for its password, or failed, shows `locked` or `error` with it, or else `fallback`.
6
+ `<DocumentScope>` picks which document; this decides whether there is one.
7
+ -->
8
+ <script lang="ts">
9
+ import type { FailedDocumentInfo, LockedDocumentInfo } from '@embedpdf/core';
10
+ import { useDocument } from './documents.svelte.js';
11
+ import type { DocumentGateProps } from './props.js';
12
+
13
+ let { fallback, locked, error, children }: DocumentGateProps = $props();
14
+
15
+ const document = useDocument((info) => info);
16
+ </script>
17
+
18
+ {#if document.current.status === 'ready'}
19
+ {@render children?.()}
20
+ {:else if document.current.status === 'locked' && locked}
21
+ {@render locked(document.current as LockedDocumentInfo)}
22
+ {:else if document.current.status === 'error' && error}
23
+ {@render error(document.current as FailedDocumentInfo)}
24
+ {:else}
25
+ {@render fallback?.()}
26
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { DocumentGateProps } from './props.js';
2
+ declare const DocumentGate: import("svelte").Component<DocumentGateProps, {}, "">;
3
+ type DocumentGate = ReturnType<typeof DocumentGate>;
4
+ export default DocumentGate;
@@ -0,0 +1,14 @@
1
+ <!--
2
+ Binds everything inside to one document, for panes and side-by-side comparison: the readers and
3
+ `use<Plugin>()` handles inside talk to `id`, not the active document.
4
+ -->
5
+ <script lang="ts">
6
+ import { setDocumentScope } from './binding.svelte.js';
7
+ import type { DocumentScopeProps } from './props.js';
8
+
9
+ let { id, children }: DocumentScopeProps = $props();
10
+
11
+ setDocumentScope(() => id);
12
+ </script>
13
+
14
+ {@render children?.()}
@@ -0,0 +1,4 @@
1
+ import type { DocumentScopeProps } from './props.js';
2
+ declare const DocumentScope: import("svelte").Component<DocumentScopeProps, {}, "">;
3
+ type DocumentScope = ReturnType<typeof DocumentScope>;
4
+ export default DocumentScope;
@@ -0,0 +1,33 @@
1
+ <!--
2
+ Gives everything inside a kernel someone else created and owns, so every reader in it works
3
+ against that kernel: the full viewer's wrapper puts the components it shows in the viewer inside
4
+ one. It never starts or destroys the kernel; `<Viewer>` is the component that owns one.
5
+
6
+ The kernel is read once, like `<Viewer>`'s engine: to give a subtree another kernel, mount a new
7
+ provider (`{#key kernel}`).
8
+ -->
9
+ <script lang="ts">
10
+ import { onDestroy, untrack } from 'svelte';
11
+ import { KernelBinding, setKernelHolder } from './binding.svelte.js';
12
+ import { devWarn } from './dev.js';
13
+ import type { KernelProviderProps } from './props.js';
14
+
15
+ let { kernel, children }: KernelProviderProps = $props();
16
+
17
+ const binding = new KernelBinding(untrack(() => kernel));
18
+ setKernelHolder({ binding });
19
+ // The provider stops following the kernel; the kernel keeps running for its owner.
20
+ onDestroy(() => binding.dispose());
21
+
22
+ $effect(() => {
23
+ if (kernel !== binding.kernel) {
24
+ devWarn(
25
+ 'kernel-provider-kernel',
26
+ '<KernelProvider> reads kernel once; a new value is ignored. To give the subtree another ' +
27
+ 'kernel, mount a new <KernelProvider>, for example inside a {#key kernel} block.',
28
+ );
29
+ }
30
+ });
31
+ </script>
32
+
33
+ {@render children?.()}
@@ -0,0 +1,4 @@
1
+ import type { KernelProviderProps } from './props.js';
2
+ declare const KernelProvider: import("svelte").Component<KernelProviderProps, {}, "">;
3
+ type KernelProvider = ReturnType<typeof KernelProvider>;
4
+ export default KernelProvider;
@@ -0,0 +1,30 @@
1
+ <!--
2
+ Scene shapes as SVG elements: `@embedpdf/web`'s element descriptions (`svgShapesOf`), one
3
+ element each, a clipping `svg` with its children, and the faces their text draws in mounted
4
+ while they show. The annotation and form layers draw their scenes through it, inside an `<svg>`.
5
+ -->
6
+ <svelte:options namespace="svg" />
7
+
8
+ <script lang="ts">
9
+ import { createFontMounts, type SvgShape } from '@embedpdf/web';
10
+ import SvgShapes from './SvgShapes.svelte';
11
+
12
+ let { shapes }: { shapes: readonly SvgShape[] } = $props();
13
+
14
+ // The faces of this level's text: a clipping `svg` mounts its own children's.
15
+ const mounts = createFontMounts();
16
+ $effect(() => () => mounts.release());
17
+ $effect(() => {
18
+ mounts.mount(shapes.flatMap((shape) => (shape.program ? [shape.program] : [])));
19
+ });
20
+ </script>
21
+
22
+ {#each shapes as shape, index (index)}
23
+ <svelte:element this={shape.tag} {...shape.attributes} style:mix-blend-mode={shape.blend}>
24
+ {#if shape.children}
25
+ <SvgShapes shapes={shape.children} />
26
+ {:else if shape.text !== undefined}
27
+ {shape.text}
28
+ {/if}
29
+ </svelte:element>
30
+ {/each}
@@ -0,0 +1,8 @@
1
+ import { type SvgShape } from '@embedpdf/web';
2
+ import SvgShapes from './SvgShapes.svelte';
3
+ type $$ComponentProps = {
4
+ shapes: readonly SvgShape[];
5
+ };
6
+ declare const SvgShapes: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type SvgShapes = ReturnType<typeof SvgShapes>;
8
+ export default SvgShapes;
@@ -0,0 +1,130 @@
1
+ <!--
2
+ The viewer: owns the kernel for as long as it is mounted, and gives it to everything inside.
3
+
4
+ The kernel is made in the browser only, when the viewer mounts (an effect, so server rendering
5
+ makes nothing). Its fallback shows from then on, with the kernel already in context, so a
6
+ loading screen can use workspace plugins. The content mounts once `start()` resolves, which
7
+ never touches the engine: the shell is alive while WASM compiles or the transport connects.
8
+ `initialDocuments` then open in the background; per-document loading is `<DocumentGate>`'s job.
9
+
10
+ Engine ownership follows the shape of `engine`: a function is the viewer's own (made on mount,
11
+ destroyed after the kernel on unmount), an instance is borrowed (warmed up, never destroyed).
12
+ -->
13
+ <script lang="ts">
14
+ import { untrack } from 'svelte';
15
+ import { createKernel, isLocalEngine, viewerSettingsOf } from '@embedpdf/core';
16
+ import type { Engine, EngineFactory, Kernel, ViewerSettings } from '@embedpdf/core';
17
+ import { browserClock, browserPrinter } from '@embedpdf/web';
18
+ import { KernelBinding, setKernelHolder } from './binding.svelte.js';
19
+ import { isDev } from './dev.js';
20
+ import type { ViewerProps } from './props.js';
21
+
22
+ let {
23
+ engine,
24
+ plugins,
25
+ initialDocuments,
26
+ onReady,
27
+ identity,
28
+ scope,
29
+ accent,
30
+ page,
31
+ fallback,
32
+ error: renderError,
33
+ children,
34
+ }: ViewerProps = $props();
35
+
36
+ type Boot =
37
+ | { phase: 'booting'; binding: KernelBinding | null }
38
+ | { phase: 'ready'; binding: KernelBinding }
39
+ | { phase: 'error'; error: unknown };
40
+
41
+ let boot = $state.raw<Boot>({ phase: 'booting', binding: null });
42
+ setKernelHolder({
43
+ get binding() {
44
+ return boot.phase === 'error' ? null : boot.binding;
45
+ },
46
+ });
47
+
48
+ // The viewer's settings as the props give them: a prop left out is its default.
49
+ const settings = $derived<ViewerSettings>(viewerSettingsOf({ identity, scope, accent, page }));
50
+
51
+ // One kernel per mount. Everything is read untracked, so nothing a prop does later runs this
52
+ // again: `engine`, `plugins` and `initialDocuments` are read once.
53
+ $effect(() =>
54
+ untrack(() => {
55
+ const ownsEngine = typeof engine === 'function';
56
+ const created: Engine = ownsEngine ? (engine as EngineFactory)() : (engine as Engine);
57
+ if (isLocalEngine(created)) created.warmup();
58
+ let kernel: Kernel;
59
+ try {
60
+ kernel = createKernel({
61
+ engine: created,
62
+ plugins,
63
+ settings,
64
+ clock: browserClock(),
65
+ printer: browserPrinter(),
66
+ });
67
+ } catch (error) {
68
+ // A plugin graph that can't be built shows `error`, not an exception mid-render.
69
+ boot = { phase: 'error', error };
70
+ if (ownsEngine) void created.destroy();
71
+ return;
72
+ }
73
+ const binding = new KernelBinding(kernel);
74
+ const documents = initialDocuments ?? [];
75
+ let alive = true;
76
+ boot = { phase: 'booting', binding };
77
+ kernel.start().then(
78
+ () => {
79
+ if (!alive) return; // unmounted while starting: open nothing
80
+ onReady?.(kernel);
81
+ boot = { phase: 'ready', binding };
82
+ // Every tab appears at once in order; the `active` entry (else the first) is selected,
83
+ // and a failure shows as that tab's status.
84
+ kernel.documents.openAll(documents);
85
+ },
86
+ (error: unknown) => {
87
+ if (alive) boot = { phase: 'error', error };
88
+ },
89
+ );
90
+ return () => {
91
+ alive = false;
92
+ binding.dispose();
93
+ // The kernel first (it closes every document handle), then the engine we own.
94
+ void kernel.destroy().then(() => {
95
+ if (ownsEngine) void created.destroy();
96
+ });
97
+ };
98
+ }),
99
+ );
100
+
101
+ // Later settings reach the kernel as they change; settings that didn't change change nothing.
102
+ $effect(() => {
103
+ const next = settings;
104
+ if (boot.phase !== 'error') boot.binding?.kernel.updateSettings(next);
105
+ });
106
+
107
+ // `engine` and `plugins` are read once: say so when they change after the viewer mounted.
108
+ const mounted = untrack(() => ({ engine, plugins }));
109
+ let warned = false;
110
+ $effect(() => {
111
+ if (warned || !isDev()) return;
112
+ if (engine !== mounted.engine || plugins !== mounted.plugins) {
113
+ warned = true;
114
+ console.warn(
115
+ '[embedpdf] <Viewer> reads engine and plugins once, when it mounts; a new value is ignored. ' +
116
+ 'To use other ones, mount a new <Viewer>, for example inside a {#key} block.',
117
+ );
118
+ }
119
+ });
120
+ </script>
121
+
122
+ {#if boot.phase === 'error'}
123
+ {@render renderError?.(boot.error)}
124
+ {:else if boot.binding}
125
+ {#if boot.phase === 'ready'}
126
+ {@render children?.()}
127
+ {:else}
128
+ {@render fallback?.()}
129
+ {/if}
130
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { ViewerProps } from './props.js';
2
+ declare const Viewer: import("svelte").Component<ViewerProps, {}, "">;
3
+ type Viewer = ReturnType<typeof Viewer>;
4
+ export default Viewer;
@@ -0,0 +1,33 @@
1
+ import type { Kernel } from '@embedpdf/core';
2
+ export declare class KernelBinding {
3
+ #private;
4
+ readonly kernel: Kernel;
5
+ constructor(kernel: Kernel);
6
+ /** Read inside a `$derived` or an effect to run it again after every kernel change. */
7
+ track(): void;
8
+ /** Stop following the kernel; the viewer calls it when it unmounts. */
9
+ dispose(): void;
10
+ }
11
+ /** What `<Viewer>` and `<KernelProvider>` provide: the binding, once the kernel exists. */
12
+ export interface KernelHolder {
13
+ readonly binding: KernelBinding | null;
14
+ }
15
+ /** For `<Viewer>` and `<KernelProvider>`: provide the kernel to everything inside it. */
16
+ export declare function setKernelHolder(holder: KernelHolder): void;
17
+ /**
18
+ * The binding of the nearest `<Viewer>` or `<KernelProvider>`. Everything inside one is created
19
+ * after its kernel, so the binding is there whenever a component inside asks.
20
+ */
21
+ export declare function useKernelBinding(): KernelBinding;
22
+ /**
23
+ * The kernel of the nearest `<Viewer>` or `<KernelProvider>`: for code that needs it whole
24
+ * (`onReady` gives it too).
25
+ */
26
+ export declare function useKernel(): Kernel;
27
+ /** For `<DocumentScope>`: bind a subtree to the document `id()` names. */
28
+ export declare function setDocumentScope(id: () => string): void;
29
+ /**
30
+ * The document the nearest `<DocumentScope>` names, as a function readers call each time (so a
31
+ * changed `id` reaches them), or one that answers null: follow the active document.
32
+ */
33
+ export declare function documentScopeOf(): () => string | null;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The kernel as Svelte sees it, and the two contexts every reader starts from.
3
+ *
4
+ * The kernel has one change stream (`kernel.subscribe`). {@link KernelBinding} turns it into one
5
+ * signal: a version that moves on every change. A reader reads that version inside a `$derived`,
6
+ * so it computes again after any change and passes a value on only when it differs. The binding
7
+ * subscribes for the kernel's whole life, so a reader works the same inside a template, an effect
8
+ * or an event handler.
9
+ *
10
+ * `<Viewer>` puts the binding in context (`<KernelProvider>` too, for a kernel it doesn't own);
11
+ * `<DocumentScope>` puts the document a subtree talks to.
12
+ */
13
+ import { getContext, hasContext, setContext, untrack } from 'svelte';
14
+ export class KernelBinding {
15
+ kernel;
16
+ #version = $state(0);
17
+ #unsubscribe;
18
+ constructor(kernel) {
19
+ this.kernel = kernel;
20
+ // `untrack`: a change can be announced while a reaction runs (a verb called from an effect),
21
+ // and the version is a counter nobody reads to decide what to write.
22
+ this.#unsubscribe = kernel.subscribe(() => untrack(() => this.#version++));
23
+ }
24
+ /** Read inside a `$derived` or an effect to run it again after every kernel change. */
25
+ track() {
26
+ void this.#version;
27
+ }
28
+ /** Stop following the kernel; the viewer calls it when it unmounts. */
29
+ dispose() {
30
+ this.#unsubscribe();
31
+ }
32
+ }
33
+ const KERNEL = Symbol('embedpdf.kernel');
34
+ const DOCUMENT_SCOPE = Symbol('embedpdf.document-scope');
35
+ /** For `<Viewer>` and `<KernelProvider>`: provide the kernel to everything inside it. */
36
+ export function setKernelHolder(holder) {
37
+ setContext(KERNEL, holder);
38
+ }
39
+ /**
40
+ * The binding of the nearest `<Viewer>` or `<KernelProvider>`. Everything inside one is created
41
+ * after its kernel, so the binding is there whenever a component inside asks.
42
+ */
43
+ export function useKernelBinding() {
44
+ // Untracked: the binding never changes for a component's lifetime, so nothing re-runs on it.
45
+ const binding = hasContext(KERNEL)
46
+ ? untrack(() => getContext(KERNEL).binding)
47
+ : null;
48
+ if (!binding) {
49
+ throw new Error('[embedpdf] This must be used inside <Viewer> or <KernelProvider>.');
50
+ }
51
+ return binding;
52
+ }
53
+ /**
54
+ * The kernel of the nearest `<Viewer>` or `<KernelProvider>`: for code that needs it whole
55
+ * (`onReady` gives it too).
56
+ */
57
+ export function useKernel() {
58
+ return useKernelBinding().kernel;
59
+ }
60
+ /** For `<DocumentScope>`: bind a subtree to the document `id()` names. */
61
+ export function setDocumentScope(id) {
62
+ setContext(DOCUMENT_SCOPE, id);
63
+ }
64
+ const ACTIVE = () => null;
65
+ /**
66
+ * The document the nearest `<DocumentScope>` names, as a function readers call each time (so a
67
+ * changed `id` reaches them), or one that answers null: follow the active document.
68
+ */
69
+ export function documentScopeOf() {
70
+ return hasContext(DOCUMENT_SCOPE) ? getContext(DOCUMENT_SCOPE) : ACTIVE;
71
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A handle over `resolve()`. Members are cached by name, so `stage.zoomIn` is the same function
3
+ * every time, and a namespace (`annotation.comments`) is itself a handle. A member that is a
4
+ * plain value is read as it is now.
5
+ */
6
+ export declare function capabilityHandle<T>(resolve: () => unknown, track: () => void): T;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * What `useStage()`, `useDocuments()` and every other `use<Plugin>()` return: a handle that is
3
+ * always the capability of the document in scope.
4
+ *
5
+ * A component calls `use<Plugin>()` once, when it is created, but the document it talks to can
6
+ * change (another tab becomes active, a `<DocumentScope id>` changes) and can be missing (none is
7
+ * open yet). So the handle resolves the capability again on every call. Without a ready document
8
+ * it reaches the plugin's stand-in (`standInFor` from `@embedpdf/core`), whose calls refuse with
9
+ * `not-ready`: a method that returns a promise rejects, the others throw.
10
+ *
11
+ * Reads follow the capability vocabulary (docs/conventions/naming.md): a member named `get*`,
12
+ * `list*`, `is*`, `has*` or `can*` reads state, so calling it in a template or a `$derived`
13
+ * subscribes to the kernel: `{#if annotation.canCreate()}` updates when the answer changes. Every
14
+ * other member is a verb or an event and subscribes to nothing: an effect that calls
15
+ * `stage.reveal(index)` runs again only when `index` changes.
16
+ */
17
+ import { untrack } from 'svelte';
18
+ import { isReadMember } from '@embedpdf/core';
19
+ /**
20
+ * A handle over `resolve()`. Members are cached by name, so `stage.zoomIn` is the same function
21
+ * every time, and a namespace (`annotation.comments`) is itself a handle. A member that is a
22
+ * plain value is read as it is now.
23
+ */
24
+ export function capabilityHandle(resolve, track) {
25
+ return memberHandle(resolve, track, null);
26
+ }
27
+ function memberHandle(resolve, track, call) {
28
+ const members = new Map();
29
+ // A function target, so a member can be called and can have members of its own.
30
+ const target = call ? function member() { } : {};
31
+ return new Proxy(target, {
32
+ apply: (_target, _this, args) => call(args),
33
+ has(_target, key) {
34
+ const value = untrack(resolve);
35
+ return (typeof value === 'object' || typeof value === 'function') && value !== null
36
+ ? key in value
37
+ : false;
38
+ },
39
+ get(_target, key) {
40
+ // Not a thenable, and inspecting it never resolves anything.
41
+ if (typeof key === 'symbol' || key === 'then')
42
+ return undefined;
43
+ const value = untrack(() => resolve()?.[key]);
44
+ if (typeof value !== 'function' && (typeof value !== 'object' || value === null)) {
45
+ return value;
46
+ }
47
+ let member = members.get(key);
48
+ if (!member) {
49
+ const resolveMember = () => resolve()[key];
50
+ member = memberHandle(resolveMember, track, (args) => invoke(resolve, key, args, track));
51
+ members.set(key, member);
52
+ }
53
+ return member;
54
+ },
55
+ });
56
+ }
57
+ /**
58
+ * Call `key` on what `resolve()` gives now, with it as `this`. `Reflect.apply`, not `.apply`: a
59
+ * stand-in's member answers every property, `apply` too.
60
+ */
61
+ function invoke(resolve, key, args, track) {
62
+ if (isReadMember(key)) {
63
+ track();
64
+ const owner = resolve();
65
+ return Reflect.apply(owner[key], owner, args);
66
+ }
67
+ return untrack(() => {
68
+ const owner = resolve();
69
+ return Reflect.apply(owner[key], owner, args);
70
+ });
71
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Whether this is a development build: `DEV` from `esm-env`, as Svelte and SvelteKit read it.
3
+ * The app's bundler picks it by its `development` or `production` condition, so in a production
4
+ * build this is `false` and the warnings behind it compile out.
5
+ */
6
+ export declare const isDev: () => boolean;
7
+ /** Warn once per key. No-op in production. */
8
+ export declare function devWarn(key: string, message: string): void;
9
+ /** Forget every warning, so a test can assert one fires again. */
10
+ export declare function resetDevWarnings(): void;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Development-time guardrails. Every warning fires once per process (keyed), says what is wrong
3
+ * and what to do instead, and compiles out of production builds ({@link isDev}).
4
+ */
5
+ import { DEV } from 'esm-env';
6
+ const warned = new Set();
7
+ /**
8
+ * Whether this is a development build: `DEV` from `esm-env`, as Svelte and SvelteKit read it.
9
+ * The app's bundler picks it by its `development` or `production` condition, so in a production
10
+ * build this is `false` and the warnings behind it compile out.
11
+ */
12
+ export const isDev = () => DEV;
13
+ /** Warn once per key. No-op in production. */
14
+ export function devWarn(key, message) {
15
+ if (!isDev() || warned.has(key))
16
+ return;
17
+ warned.add(key);
18
+ console.warn(`[embedpdf] ${message}`);
19
+ }
20
+ /** Forget every warning, so a test can assert one fires again. */
21
+ export function resetDevWarnings() {
22
+ warned.clear();
23
+ }
@@ -0,0 +1,34 @@
1
+ import type { DocumentInfo, DocumentsCapability, DocumentsState, EventHook, PageInfo, ViewerSettings } from '@embedpdf/core';
2
+ import { type CurrentValue } from './values.svelte.js';
3
+ /**
4
+ * The documents API: open, close, unlock, download, and the tabs. Inside a `<DocumentScope>`, the
5
+ * calls that leave out the document use that one, so `download()` without an id downloads the
6
+ * document in scope. What to show comes from `useDocument()` and `useDocumentsState()`.
7
+ */
8
+ export declare function useDocuments(): DocumentsCapability;
9
+ /**
10
+ * The document this component talks to: the one its `<DocumentScope>` names, or else the active
11
+ * one. Its `id`, `name`, `status`, `pageCount`, `hasUnsavedChanges`, and why it's locked or
12
+ * failed. With no document, an empty one that reads as still opening.
13
+ */
14
+ export declare function useDocument(): Readonly<DocumentInfo>;
15
+ export declare function useDocument<Selected>(select: (document: DocumentInfo) => Selected): CurrentValue<Selected>;
16
+ /** Every open document, in tab order (loading, locked and failed ones too), and the active one's id. */
17
+ export declare function useDocumentsState(): Readonly<DocumentsState>;
18
+ export declare function useDocumentsState<Selected>(select: (state: DocumentsState) => Selected): CurrentValue<Selected>;
19
+ /** Subscribe to one documents event while the component lives: `useDocumentsEvent((documents) => documents.onOpened, handler)`. */
20
+ export declare function useDocumentsEvent<T>(select: (documents: DocumentsCapability) => EventHook<T>, handler: (event: T) => void): void;
21
+ /**
22
+ * The pages of the document this component talks to, in order: each with its `ref`, `index`,
23
+ * `label`, size and rotation. Needs no Stage. The same array until a page is added, removed,
24
+ * moved or rotated; empty with no document.
25
+ */
26
+ export declare function usePageList(): CurrentValue<readonly PageInfo[]>;
27
+ /**
28
+ * The viewer's own settings (`<Viewer identity scope accent page>`), or the value `select` picks
29
+ * from them: the accent every part without a color of its own follows, and how pages look. What
30
+ * paints a page or an accent reads it here, through `paint()` from `@embedpdf/web`, so a CSS
31
+ * variable still wins.
32
+ */
33
+ export declare function useViewerSettings(): Readonly<ViewerSettings>;
34
+ export declare function useViewerSettings<Selected>(select: (settings: ViewerSettings) => Selected): CurrentValue<Selected>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The documents and the viewer's own settings, for components: the documents API, the document
3
+ * in scope, every open document, its pages, and the settings `<Viewer>` takes as props.
4
+ */
5
+ import { DocumentsToken, documentState, documentsState, shallowEqual } from '@embedpdf/core';
6
+ import { useKernelBinding } from './binding.svelte.js';
7
+ import { useCapability, useCapabilityEvent, useDocumentId, useKernelValue } from './readers.svelte.js';
8
+ import { declaredState, readRecord } from './state.svelte.js';
9
+ import { derivedValue } from './values.svelte.js';
10
+ /**
11
+ * The documents API: open, close, unlock, download, and the tabs. Inside a `<DocumentScope>`, the
12
+ * calls that leave out the document use that one, so `download()` without an id downloads the
13
+ * document in scope. What to show comes from `useDocument()` and `useDocumentsState()`.
14
+ */
15
+ export function useDocuments() {
16
+ return useCapability(DocumentsToken);
17
+ }
18
+ export function useDocument(select) {
19
+ const binding = useKernelBinding();
20
+ const whole = declaredState(binding, DocumentsToken, documentState.read, documentState.empty);
21
+ return readRecord(whole, Object.keys(documentState.empty), select);
22
+ }
23
+ export function useDocumentsState(select) {
24
+ const binding = useKernelBinding();
25
+ const whole = declaredState(binding, DocumentsToken, documentsState.read, documentsState.empty);
26
+ return readRecord(whole, Object.keys(documentsState.empty), select);
27
+ }
28
+ /** Subscribe to one documents event while the component lives: `useDocumentsEvent((documents) => documents.onOpened, handler)`. */
29
+ export function useDocumentsEvent(select, handler) {
30
+ useCapabilityEvent(DocumentsToken, select, handler);
31
+ }
32
+ const NO_PAGES = Object.freeze([]);
33
+ /**
34
+ * The pages of the document this component talks to, in order: each with its `ref`, `index`,
35
+ * `label`, size and rotation. Needs no Stage. The same array until a page is added, removed,
36
+ * moved or rotated; empty with no document.
37
+ */
38
+ export function usePageList() {
39
+ const documentId = useDocumentId();
40
+ return useKernelValue((kernel) => documentId.current ? kernel.documents.listPages(documentId.current) : NO_PAGES);
41
+ }
42
+ export function useViewerSettings(select) {
43
+ const binding = useKernelBinding();
44
+ const whole = derivedValue(() => {
45
+ binding.track();
46
+ return binding.kernel.getSettings();
47
+ }, shallowEqual);
48
+ return readRecord(whole, ['identity', 'scope', 'accent', 'page'], select);
49
+ }