@embedpdf/react 3.0.0-next.0

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 (141) hide show
  1. package/LICENSE +192 -0
  2. package/dist/AnnotationListSnapshot-W0RCsyDE-dWna4TTJ.d.cts +2593 -0
  3. package/dist/AnnotationListSnapshot-W0RCsyDE-dWna4TTJ.d.ts +2593 -0
  4. package/dist/annotation-B6jwfTCh.d.cts +173 -0
  5. package/dist/annotation-Ct6dFtzJ.cjs +913 -0
  6. package/dist/annotation-Ct6dFtzJ.cjs.map +1 -0
  7. package/dist/annotation-DjGWJljY.js +829 -0
  8. package/dist/annotation-DjGWJljY.js.map +1 -0
  9. package/dist/annotation-menu.cjs +115 -0
  10. package/dist/annotation-menu.cjs.map +1 -0
  11. package/dist/annotation-menu.d.cts +7 -0
  12. package/dist/annotation-menu.d.ts +7 -0
  13. package/dist/annotation-menu.js +99 -0
  14. package/dist/annotation-menu.js.map +1 -0
  15. package/dist/annotation-nUMefyjw.d.ts +173 -0
  16. package/dist/annotation.cjs +25 -0
  17. package/dist/annotation.d.cts +3 -0
  18. package/dist/annotation.d.ts +3 -0
  19. package/dist/annotation.js +4 -0
  20. package/dist/commands.cjs +59 -0
  21. package/dist/commands.cjs.map +1 -0
  22. package/dist/commands.d.cts +20 -0
  23. package/dist/commands.d.ts +20 -0
  24. package/dist/commands.js +47 -0
  25. package/dist/commands.js.map +1 -0
  26. package/dist/form.cjs +560 -0
  27. package/dist/form.cjs.map +1 -0
  28. package/dist/form.d.cts +52 -0
  29. package/dist/form.d.ts +52 -0
  30. package/dist/form.js +545 -0
  31. package/dist/form.js.map +1 -0
  32. package/dist/i18n.cjs +52 -0
  33. package/dist/i18n.cjs.map +1 -0
  34. package/dist/i18n.d.cts +30 -0
  35. package/dist/i18n.d.ts +30 -0
  36. package/dist/i18n.js +42 -0
  37. package/dist/i18n.js.map +1 -0
  38. package/dist/index.cjs +240 -0
  39. package/dist/index.d.cts +37 -0
  40. package/dist/index.d.ts +37 -0
  41. package/dist/index.js +37 -0
  42. package/dist/interaction.cjs +152 -0
  43. package/dist/interaction.cjs.map +1 -0
  44. package/dist/interaction.d.cts +46 -0
  45. package/dist/interaction.d.ts +46 -0
  46. package/dist/interaction.js +139 -0
  47. package/dist/interaction.js.map +1 -0
  48. package/dist/link.cjs +108 -0
  49. package/dist/link.cjs.map +1 -0
  50. package/dist/link.d.cts +16 -0
  51. package/dist/link.d.ts +16 -0
  52. package/dist/link.js +98 -0
  53. package/dist/link.js.map +1 -0
  54. package/dist/metadata.cjs +25 -0
  55. package/dist/metadata.cjs.map +1 -0
  56. package/dist/metadata.d.cts +11 -0
  57. package/dist/metadata.d.ts +11 -0
  58. package/dist/metadata.js +16 -0
  59. package/dist/metadata.js.map +1 -0
  60. package/dist/page-edit.cjs +20 -0
  61. package/dist/page-edit.cjs.map +1 -0
  62. package/dist/page-edit.d.cts +7 -0
  63. package/dist/page-edit.d.ts +7 -0
  64. package/dist/page-edit.js +11 -0
  65. package/dist/page-edit.js.map +1 -0
  66. package/dist/page-view.cjs +107 -0
  67. package/dist/page-view.cjs.map +1 -0
  68. package/dist/page-view.d.cts +23 -0
  69. package/dist/page-view.d.ts +23 -0
  70. package/dist/page-view.js +95 -0
  71. package/dist/page-view.js.map +1 -0
  72. package/dist/redaction.cjs +35 -0
  73. package/dist/redaction.cjs.map +1 -0
  74. package/dist/redaction.d.cts +14 -0
  75. package/dist/redaction.d.ts +14 -0
  76. package/dist/redaction.js +25 -0
  77. package/dist/redaction.js.map +1 -0
  78. package/dist/render.cjs +142 -0
  79. package/dist/render.cjs.map +1 -0
  80. package/dist/render.d.cts +32 -0
  81. package/dist/render.d.ts +32 -0
  82. package/dist/render.js +131 -0
  83. package/dist/render.js.map +1 -0
  84. package/dist/rolldown-runtime-DDXJien1.cjs +50 -0
  85. package/dist/runtime-CMxIuF2O.d.cts +195 -0
  86. package/dist/runtime-DV98q7I0.d.ts +195 -0
  87. package/dist/runtime.cjs +314 -0
  88. package/dist/runtime.cjs.map +1 -0
  89. package/dist/runtime.d.cts +3 -0
  90. package/dist/runtime.d.ts +3 -0
  91. package/dist/runtime.js +287 -0
  92. package/dist/runtime.js.map +1 -0
  93. package/dist/scrollbar.cjs +241 -0
  94. package/dist/scrollbar.cjs.map +1 -0
  95. package/dist/scrollbar.d.cts +42 -0
  96. package/dist/scrollbar.d.ts +42 -0
  97. package/dist/scrollbar.js +213 -0
  98. package/dist/scrollbar.js.map +1 -0
  99. package/dist/search.cjs +70 -0
  100. package/dist/search.cjs.map +1 -0
  101. package/dist/search.d.cts +35 -0
  102. package/dist/search.d.ts +35 -0
  103. package/dist/search.js +58 -0
  104. package/dist/search.js.map +1 -0
  105. package/dist/selection.cjs +60 -0
  106. package/dist/selection.cjs.map +1 -0
  107. package/dist/selection.d.cts +12 -0
  108. package/dist/selection.d.ts +12 -0
  109. package/dist/selection.js +49 -0
  110. package/dist/selection.js.map +1 -0
  111. package/dist/shell.cjs +57 -0
  112. package/dist/shell.cjs.map +1 -0
  113. package/dist/shell.d.cts +27 -0
  114. package/dist/shell.d.ts +27 -0
  115. package/dist/shell.js +46 -0
  116. package/dist/shell.js.map +1 -0
  117. package/dist/stage.cjs +343 -0
  118. package/dist/stage.cjs.map +1 -0
  119. package/dist/stage.d.cts +104 -0
  120. package/dist/stage.d.ts +104 -0
  121. package/dist/stage.js +327 -0
  122. package/dist/stage.js.map +1 -0
  123. package/dist/stamp.cjs +76 -0
  124. package/dist/stamp.cjs.map +1 -0
  125. package/dist/stamp.d.cts +28 -0
  126. package/dist/stamp.d.ts +28 -0
  127. package/dist/stamp.js +63 -0
  128. package/dist/stamp.js.map +1 -0
  129. package/dist/toolbar.cjs +515 -0
  130. package/dist/toolbar.cjs.map +1 -0
  131. package/dist/toolbar.d.cts +100 -0
  132. package/dist/toolbar.d.ts +100 -0
  133. package/dist/toolbar.js +505 -0
  134. package/dist/toolbar.js.map +1 -0
  135. package/dist/views.cjs +35 -0
  136. package/dist/views.cjs.map +1 -0
  137. package/dist/views.d.cts +21 -0
  138. package/dist/views.d.ts +21 -0
  139. package/dist/views.js +26 -0
  140. package/dist/views.js.map +1 -0
  141. package/package.json +158 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction.js","names":[],"sources":["../src/redaction.tsx"],"sourcesContent":["import { RedactionToken } from '@embedpdf/plugin-redaction';\nimport type {\n RedactionApplyResult,\n RedactionCapability,\n RedactionPendingItem,\n} from '@embedpdf/plugin-redaction';\nimport { useCapability, useSelector } from './runtime';\n\n/**\n * Redaction for the surrounding `DocumentScope`: the pending-marks view plus\n * the destructive apply. Marking rides the annotation plane (the composed\n * `redact` tool); `useRedaction` surfaces the workflow around it.\n *\n * const redaction = useRedaction();\n * redaction.toggleRedact();\n * await redaction.applyAll(); // irreversible — confirm first\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-redaction';\n\nexport function useRedaction(): RedactionCapability & {\n applying: boolean;\n lastApplyResult: RedactionApplyResult | null;\n} {\n const cap = useCapability(RedactionToken);\n const applying = useSelector(RedactionToken, (c) => c.isApplying());\n const lastApplyResult = useSelector(RedactionToken, (c) => c.lastResult());\n return { ...cap, applying, lastApplyResult };\n}\n\n/** The pending marks, reactive against the annotation plane. Note the view\n * covers LOADED pages — call `preparePending()` (e.g. on panel open) to load\n * the whole document. */\nexport function usePendingRedactions(): RedactionPendingItem[] {\n return useSelector(RedactionToken, (c) => c.getPending(), pendingEqual);\n}\n\nconst pendingEqual = (a: RedactionPendingItem[], b: RedactionPendingItem[]): boolean =>\n a.length === b.length &&\n a.every((item, i) => item.id === b[i]!.id && item.overlayText === b[i]!.overlayText);\n"],"mappings":";;;;AAqBA,SAAgB,eAGd;CACA,MAAM,MAAM,cAAc,cAAc;CACxC,MAAM,WAAW,YAAY,iBAAiB,MAAM,EAAE,WAAW,CAAC;CAClE,MAAM,kBAAkB,YAAY,iBAAiB,MAAM,EAAE,WAAW,CAAC;CACzE,OAAO;EAAE,GAAG;EAAK;EAAU;CAAgB;AAC7C;;;;AAKA,SAAgB,uBAA+C;CAC7D,OAAO,YAAY,iBAAiB,MAAM,EAAE,WAAW,GAAG,YAAY;AACxE;AAEA,MAAM,gBAAgB,GAA2B,MAC/C,EAAE,WAAW,EAAE,UACf,EAAE,OAAO,MAAM,MAAM,KAAK,OAAO,EAAE,EAAE,CAAE,MAAM,KAAK,gBAAgB,EAAE,EAAE,CAAE,WAAW"}
@@ -0,0 +1,142 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_rolldown_runtime = require("./rolldown-runtime-DDXJien1.cjs");
3
+ const require_runtime = require("./runtime.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ let react = require("react");
6
+ react = require_rolldown_runtime.__toESM(react, 1);
7
+ let _embedpdf_plugin_render = require("@embedpdf/plugin-render");
8
+ //#region src/render.tsx
9
+ function RenderLayer({ annotations = true } = {}) {
10
+ const page = require_runtime.usePage();
11
+ const render = require_runtime.useCapability(_embedpdf_plugin_render.RenderToken);
12
+ const ref = (0, react.useRef)(null);
13
+ const sourceKey = require_runtime.useSelector(_embedpdf_plugin_render.RenderToken, (c) => c.renderSourceKey(page.pon, {
14
+ scale: page.transform.renderScale,
15
+ includeAnnotations: annotations
16
+ }));
17
+ (0, react.useEffect)(() => {
18
+ const controller = new AbortController();
19
+ let revoke;
20
+ (async () => {
21
+ try {
22
+ const obj = await (await render.renderPage(page.pon, {
23
+ scale: page.transform.renderScale,
24
+ includeAnnotations: annotations,
25
+ signal: controller.signal
26
+ })).objectUrl(controller.signal);
27
+ if (controller.signal.aborted) {
28
+ obj.revoke();
29
+ return;
30
+ }
31
+ revoke = obj.revoke;
32
+ if (ref.current) ref.current.src = obj.url;
33
+ } catch {}
34
+ })();
35
+ return () => {
36
+ controller.abort();
37
+ revoke?.();
38
+ };
39
+ }, [
40
+ render,
41
+ page.pon,
42
+ sourceKey
43
+ ]);
44
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
45
+ ref,
46
+ alt: "",
47
+ draggable: false,
48
+ style: {
49
+ position: "absolute",
50
+ inset: 0,
51
+ width: "100%",
52
+ height: "100%",
53
+ pointerEvents: "none"
54
+ }
55
+ });
56
+ }
57
+ /**
58
+ * TileLayer — the sharp plane above the base rung.
59
+ *
60
+ * Mounting it is the per-lens OPT-IN; whether it spends anything is demand
61
+ * arithmetic (a thumbnail rail's demand never engages). The paint list is the
62
+ * plugin's retention-safe plan: keyed <img>s inside ONE container that carries
63
+ * the page scale as a single transform (one rounding context — no tile seams),
64
+ * with `onLoad` reporting the decode boundary back so retained coarser
65
+ * generations release only when their replacement is truly on screen.
66
+ */
67
+ function TileLayer({ annotations = true } = {}) {
68
+ const page = require_runtime.usePage();
69
+ const render = require_runtime.useCapability(_embedpdf_plugin_render.RenderToken);
70
+ const demand = page.getViewDemand?.() ?? { desiredDeviceWidth: page.transform.deviceWidth };
71
+ const plan = require_runtime.useSelector(_embedpdf_plugin_render.RenderToken, (c) => c.tilePlan(page.pon, demand, { includeAnnotations: annotations }));
72
+ (0, react.useEffect)(() => () => render.releaseTiles(page.pon), [render, page.pon]);
73
+ if (plan.paint.length === 0) return null;
74
+ const t = page.transform;
75
+ const scale = t.viewScale;
76
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
77
+ style: {
78
+ position: "absolute",
79
+ left: 0,
80
+ top: 0,
81
+ width: t.contentWidth / scale,
82
+ height: t.contentHeight / scale,
83
+ transform: `scale(${scale})`,
84
+ transformOrigin: "0 0",
85
+ pointerEvents: "none"
86
+ },
87
+ children: plan.paint.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TileImg, {
88
+ source,
89
+ onPainted: () => render.tilePainted(page.pon, source.key)
90
+ }, source.key))
91
+ });
92
+ }
93
+ /** One tile: object-URL lifecycle + the painted (decode-boundary) report. */
94
+ function TileImg({ source, onPainted }) {
95
+ const ref = (0, react.useRef)(null);
96
+ (0, react.useEffect)(() => {
97
+ const controller = new AbortController();
98
+ let revoke;
99
+ (async () => {
100
+ try {
101
+ const obj = await source.handle.objectUrl(controller.signal);
102
+ if (controller.signal.aborted) {
103
+ obj.revoke();
104
+ return;
105
+ }
106
+ revoke = obj.revoke;
107
+ if (ref.current) ref.current.src = obj.url;
108
+ } catch {}
109
+ })();
110
+ return () => {
111
+ controller.abort();
112
+ revoke?.();
113
+ };
114
+ }, [source.handle]);
115
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
116
+ ref,
117
+ alt: "",
118
+ draggable: false,
119
+ onLoad: onPainted,
120
+ style: {
121
+ position: "absolute",
122
+ left: source.rect.x,
123
+ top: source.rect.y,
124
+ width: source.rect.width,
125
+ height: source.rect.height,
126
+ zIndex: source.z
127
+ }
128
+ });
129
+ }
130
+ //#endregion
131
+ exports.RenderLayer = RenderLayer;
132
+ exports.TileLayer = TileLayer;
133
+ Object.keys(_embedpdf_plugin_render).forEach(function(k) {
134
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
135
+ enumerable: true,
136
+ get: function() {
137
+ return _embedpdf_plugin_render[k];
138
+ }
139
+ });
140
+ });
141
+
142
+ //# sourceMappingURL=render.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.cjs","names":["usePage","useCapability","RenderToken","useSelector"],"sources":["../src/render.tsx"],"sourcesContent":["/**\n * RenderLayer + TileLayer — the React views of @embedpdf/plugin-render.\n *\n * RenderLayer paints the BASE rung to an <img> from the engine's ENCODED\n * image() (identical for local & cloud). TileLayer paints the tile paint-plan\n * ABOVE it when the deployment lattice caps the base below the demand — mount\n * it per lens (the main stage yes, a thumbnail rail no); where the demand is\n * small it engages nothing. Both are dumb painters: every decision (policy\n * conformance, want sets, retention, release) is plugin-render's.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-render';\nimport * as React from 'react';\nimport { useEffect, useRef } from 'react';\nimport { RenderToken } from '@embedpdf/plugin-render';\nimport type { PageViewDemand, TilePaintSource } from '@embedpdf/plugin-render';\nimport { useCapability, usePage, useSelector } from './runtime';\n\nexport interface RenderLayerProps {\n /**\n * Bake annotations into the page bitmap (default true). Pass false when an\n * <AnnotationLayer> owns annotation rendering, so they aren't drawn twice.\n */\n annotations?: boolean;\n}\n\nexport function RenderLayer({ annotations = true }: RenderLayerProps = {}) {\n const page = usePage();\n const render = useCapability(RenderToken);\n const ref = useRef<HTMLImageElement>(null);\n // ONE dependency: the raster's canonical identity — conformed viewport +\n // annotations flag + epoch. Inside a lattice\n // rung, zoom changes don't move it: no refetch, no DOM churn — the stage's\n // CSS transform does the scaling. It changes exactly at rung crossings and\n // on CONFIRMED mutations (epoch bumps at commit, never mid-gesture). Under\n // `continuous` it embeds the exact scale — v2 behavior byte-for-byte. The\n // policy behind it is a document fact the kernel materialized before\n // publish, so the key is always computable.\n const sourceKey = useSelector(RenderToken, (c) =>\n c.renderSourceKey(page.pon, {\n scale: page.transform.renderScale,\n includeAnnotations: annotations,\n }),\n );\n useEffect(() => {\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n (async () => {\n try {\n // The capability conforms this to the policy (lattice → ladder width,\n // continuous → this exact scale) and collapses same-key asks in its\n // raster store. A stale-closure scale is harmless by construction:\n // any scale in this rung produces this key's canonical request.\n const image = await render.renderPage(page.pon, {\n scale: page.transform.renderScale,\n includeAnnotations: annotations,\n signal: controller.signal,\n });\n const obj = await image.objectUrl(controller.signal);\n if (controller.signal.aborted) {\n obj.revoke();\n return;\n }\n revoke = obj.revoke;\n if (ref.current) ref.current.src = obj.url;\n } catch {\n /* aborted (camera moved / unmounted) or render failed */\n }\n })();\n return () => {\n controller.abort();\n revoke?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- sourceKey IS the\n // render identity; scale/annotations/epoch are folded into it upstream.\n }, [render, page.pon, sourceKey]);\n return (\n <img\n ref={ref}\n alt=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n }}\n />\n );\n}\n\nexport interface TileLayerProps {\n /**\n * Bake annotations into tile bitmaps (default true). Pass false when an\n * <AnnotationLayer> owns annotation rendering — the composition that keeps\n * tile artifacts annotation-version-free (CDN-stable across edits).\n */\n annotations?: boolean;\n}\n\n/**\n * TileLayer — the sharp plane above the base rung.\n *\n * Mounting it is the per-lens OPT-IN; whether it spends anything is demand\n * arithmetic (a thumbnail rail's demand never engages). The paint list is the\n * plugin's retention-safe plan: keyed <img>s inside ONE container that carries\n * the page scale as a single transform (one rounding context — no tile seams),\n * with `onLoad` reporting the decode boundary back so retained coarser\n * generations release only when their replacement is truly on screen.\n */\nexport function TileLayer({ annotations = true }: TileLayerProps = {}) {\n const page = usePage();\n const render = useCapability(RenderToken);\n // Demand: the host's live camera view (Stage) or whole-page (PageView).\n const demand: PageViewDemand = page.getViewDemand?.() ?? {\n desiredDeviceWidth: page.transform.deviceWidth,\n };\n const plan = useSelector(RenderToken, (c) =>\n c.tilePlan(page.pon, demand, { includeAnnotations: annotations }),\n );\n // Lens unmounted: stop in-flight tile fetches; resolved bytes stay cached.\n useEffect(() => () => render.releaseTiles(page.pon), [render, page.pon]);\n if (plan.paint.length === 0) return null;\n const t = page.transform;\n const scale = t.viewScale;\n return (\n <div\n style={{\n position: 'absolute',\n left: 0,\n top: 0,\n width: t.contentWidth / scale,\n height: t.contentHeight / scale,\n transform: `scale(${scale})`,\n transformOrigin: '0 0',\n pointerEvents: 'none',\n }}\n >\n {plan.paint.map((source) => (\n <TileImg\n key={source.key}\n source={source}\n onPainted={() => render.tilePainted(page.pon, source.key)}\n />\n ))}\n </div>\n );\n}\n\n/** One tile: object-URL lifecycle + the painted (decode-boundary) report. */\nfunction TileImg({ source, onPainted }: { source: TilePaintSource; onPainted: () => void }) {\n const ref = useRef<HTMLImageElement>(null);\n useEffect(() => {\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n (async () => {\n try {\n const obj = await source.handle.objectUrl(controller.signal);\n if (controller.signal.aborted) {\n obj.revoke();\n return;\n }\n revoke = obj.revoke;\n if (ref.current) ref.current.src = obj.url;\n } catch {\n /* aborted (plan moved on) */\n }\n })();\n return () => {\n controller.abort();\n revoke?.();\n };\n }, [source.handle]);\n return (\n <img\n ref={ref}\n alt=\"\"\n draggable={false}\n onLoad={onPainted}\n style={{\n position: 'absolute',\n left: source.rect.x,\n top: source.rect.y,\n width: source.rect.width,\n height: source.rect.height,\n zIndex: source.z,\n }}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export * from "@embedpdf/plugin-render";
2
+ //#region src/render.d.ts
3
+ interface RenderLayerProps {
4
+ /**
5
+ * Bake annotations into the page bitmap (default true). Pass false when an
6
+ * <AnnotationLayer> owns annotation rendering, so they aren't drawn twice.
7
+ */
8
+ annotations?: boolean;
9
+ }
10
+ declare function RenderLayer({ annotations }?: RenderLayerProps): import("react/jsx-runtime").JSX.Element;
11
+ interface TileLayerProps {
12
+ /**
13
+ * Bake annotations into tile bitmaps (default true). Pass false when an
14
+ * <AnnotationLayer> owns annotation rendering — the composition that keeps
15
+ * tile artifacts annotation-version-free (CDN-stable across edits).
16
+ */
17
+ annotations?: boolean;
18
+ }
19
+ /**
20
+ * TileLayer — the sharp plane above the base rung.
21
+ *
22
+ * Mounting it is the per-lens OPT-IN; whether it spends anything is demand
23
+ * arithmetic (a thumbnail rail's demand never engages). The paint list is the
24
+ * plugin's retention-safe plan: keyed <img>s inside ONE container that carries
25
+ * the page scale as a single transform (one rounding context — no tile seams),
26
+ * with `onLoad` reporting the decode boundary back so retained coarser
27
+ * generations release only when their replacement is truly on screen.
28
+ */
29
+ declare function TileLayer({ annotations }?: TileLayerProps): import("react/jsx-runtime").JSX.Element | null;
30
+ //#endregion
31
+ export { RenderLayer, RenderLayerProps, TileLayer, TileLayerProps };
32
+ //# sourceMappingURL=render.d.cts.map
@@ -0,0 +1,32 @@
1
+ export * from "@embedpdf/plugin-render";
2
+ //#region src/render.d.ts
3
+ interface RenderLayerProps {
4
+ /**
5
+ * Bake annotations into the page bitmap (default true). Pass false when an
6
+ * <AnnotationLayer> owns annotation rendering, so they aren't drawn twice.
7
+ */
8
+ annotations?: boolean;
9
+ }
10
+ declare function RenderLayer({ annotations }?: RenderLayerProps): import("react/jsx-runtime").JSX.Element;
11
+ interface TileLayerProps {
12
+ /**
13
+ * Bake annotations into tile bitmaps (default true). Pass false when an
14
+ * <AnnotationLayer> owns annotation rendering — the composition that keeps
15
+ * tile artifacts annotation-version-free (CDN-stable across edits).
16
+ */
17
+ annotations?: boolean;
18
+ }
19
+ /**
20
+ * TileLayer — the sharp plane above the base rung.
21
+ *
22
+ * Mounting it is the per-lens OPT-IN; whether it spends anything is demand
23
+ * arithmetic (a thumbnail rail's demand never engages). The paint list is the
24
+ * plugin's retention-safe plan: keyed <img>s inside ONE container that carries
25
+ * the page scale as a single transform (one rounding context — no tile seams),
26
+ * with `onLoad` reporting the decode boundary back so retained coarser
27
+ * generations release only when their replacement is truly on screen.
28
+ */
29
+ declare function TileLayer({ annotations }?: TileLayerProps): import("react/jsx-runtime").JSX.Element | null;
30
+ //#endregion
31
+ export { RenderLayer, RenderLayerProps, TileLayer, TileLayerProps };
32
+ //# sourceMappingURL=render.d.ts.map
package/dist/render.js ADDED
@@ -0,0 +1,131 @@
1
+ import { useCapability, usePage, useSelector } from "./runtime.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ import { RenderToken } from "@embedpdf/plugin-render";
5
+ export * from "@embedpdf/plugin-render";
6
+ //#region src/render.tsx
7
+ function RenderLayer({ annotations = true } = {}) {
8
+ const page = usePage();
9
+ const render = useCapability(RenderToken);
10
+ const ref = useRef(null);
11
+ const sourceKey = useSelector(RenderToken, (c) => c.renderSourceKey(page.pon, {
12
+ scale: page.transform.renderScale,
13
+ includeAnnotations: annotations
14
+ }));
15
+ useEffect(() => {
16
+ const controller = new AbortController();
17
+ let revoke;
18
+ (async () => {
19
+ try {
20
+ const obj = await (await render.renderPage(page.pon, {
21
+ scale: page.transform.renderScale,
22
+ includeAnnotations: annotations,
23
+ signal: controller.signal
24
+ })).objectUrl(controller.signal);
25
+ if (controller.signal.aborted) {
26
+ obj.revoke();
27
+ return;
28
+ }
29
+ revoke = obj.revoke;
30
+ if (ref.current) ref.current.src = obj.url;
31
+ } catch {}
32
+ })();
33
+ return () => {
34
+ controller.abort();
35
+ revoke?.();
36
+ };
37
+ }, [
38
+ render,
39
+ page.pon,
40
+ sourceKey
41
+ ]);
42
+ return /* @__PURE__ */ jsx("img", {
43
+ ref,
44
+ alt: "",
45
+ draggable: false,
46
+ style: {
47
+ position: "absolute",
48
+ inset: 0,
49
+ width: "100%",
50
+ height: "100%",
51
+ pointerEvents: "none"
52
+ }
53
+ });
54
+ }
55
+ /**
56
+ * TileLayer — the sharp plane above the base rung.
57
+ *
58
+ * Mounting it is the per-lens OPT-IN; whether it spends anything is demand
59
+ * arithmetic (a thumbnail rail's demand never engages). The paint list is the
60
+ * plugin's retention-safe plan: keyed <img>s inside ONE container that carries
61
+ * the page scale as a single transform (one rounding context — no tile seams),
62
+ * with `onLoad` reporting the decode boundary back so retained coarser
63
+ * generations release only when their replacement is truly on screen.
64
+ */
65
+ function TileLayer({ annotations = true } = {}) {
66
+ const page = usePage();
67
+ const render = useCapability(RenderToken);
68
+ const demand = page.getViewDemand?.() ?? { desiredDeviceWidth: page.transform.deviceWidth };
69
+ const plan = useSelector(RenderToken, (c) => c.tilePlan(page.pon, demand, { includeAnnotations: annotations }));
70
+ useEffect(() => () => render.releaseTiles(page.pon), [render, page.pon]);
71
+ if (plan.paint.length === 0) return null;
72
+ const t = page.transform;
73
+ const scale = t.viewScale;
74
+ return /* @__PURE__ */ jsx("div", {
75
+ style: {
76
+ position: "absolute",
77
+ left: 0,
78
+ top: 0,
79
+ width: t.contentWidth / scale,
80
+ height: t.contentHeight / scale,
81
+ transform: `scale(${scale})`,
82
+ transformOrigin: "0 0",
83
+ pointerEvents: "none"
84
+ },
85
+ children: plan.paint.map((source) => /* @__PURE__ */ jsx(TileImg, {
86
+ source,
87
+ onPainted: () => render.tilePainted(page.pon, source.key)
88
+ }, source.key))
89
+ });
90
+ }
91
+ /** One tile: object-URL lifecycle + the painted (decode-boundary) report. */
92
+ function TileImg({ source, onPainted }) {
93
+ const ref = useRef(null);
94
+ useEffect(() => {
95
+ const controller = new AbortController();
96
+ let revoke;
97
+ (async () => {
98
+ try {
99
+ const obj = await source.handle.objectUrl(controller.signal);
100
+ if (controller.signal.aborted) {
101
+ obj.revoke();
102
+ return;
103
+ }
104
+ revoke = obj.revoke;
105
+ if (ref.current) ref.current.src = obj.url;
106
+ } catch {}
107
+ })();
108
+ return () => {
109
+ controller.abort();
110
+ revoke?.();
111
+ };
112
+ }, [source.handle]);
113
+ return /* @__PURE__ */ jsx("img", {
114
+ ref,
115
+ alt: "",
116
+ draggable: false,
117
+ onLoad: onPainted,
118
+ style: {
119
+ position: "absolute",
120
+ left: source.rect.x,
121
+ top: source.rect.y,
122
+ width: source.rect.width,
123
+ height: source.rect.height,
124
+ zIndex: source.z
125
+ }
126
+ });
127
+ }
128
+ //#endregion
129
+ export { RenderLayer, TileLayer };
130
+
131
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","names":[],"sources":["../src/render.tsx"],"sourcesContent":["/**\n * RenderLayer + TileLayer — the React views of @embedpdf/plugin-render.\n *\n * RenderLayer paints the BASE rung to an <img> from the engine's ENCODED\n * image() (identical for local & cloud). TileLayer paints the tile paint-plan\n * ABOVE it when the deployment lattice caps the base below the demand — mount\n * it per lens (the main stage yes, a thumbnail rail no); where the demand is\n * small it engages nothing. Both are dumb painters: every decision (policy\n * conformance, want sets, retention, release) is plugin-render's.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-render';\nimport * as React from 'react';\nimport { useEffect, useRef } from 'react';\nimport { RenderToken } from '@embedpdf/plugin-render';\nimport type { PageViewDemand, TilePaintSource } from '@embedpdf/plugin-render';\nimport { useCapability, usePage, useSelector } from './runtime';\n\nexport interface RenderLayerProps {\n /**\n * Bake annotations into the page bitmap (default true). Pass false when an\n * <AnnotationLayer> owns annotation rendering, so they aren't drawn twice.\n */\n annotations?: boolean;\n}\n\nexport function RenderLayer({ annotations = true }: RenderLayerProps = {}) {\n const page = usePage();\n const render = useCapability(RenderToken);\n const ref = useRef<HTMLImageElement>(null);\n // ONE dependency: the raster's canonical identity — conformed viewport +\n // annotations flag + epoch. Inside a lattice\n // rung, zoom changes don't move it: no refetch, no DOM churn — the stage's\n // CSS transform does the scaling. It changes exactly at rung crossings and\n // on CONFIRMED mutations (epoch bumps at commit, never mid-gesture). Under\n // `continuous` it embeds the exact scale — v2 behavior byte-for-byte. The\n // policy behind it is a document fact the kernel materialized before\n // publish, so the key is always computable.\n const sourceKey = useSelector(RenderToken, (c) =>\n c.renderSourceKey(page.pon, {\n scale: page.transform.renderScale,\n includeAnnotations: annotations,\n }),\n );\n useEffect(() => {\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n (async () => {\n try {\n // The capability conforms this to the policy (lattice → ladder width,\n // continuous → this exact scale) and collapses same-key asks in its\n // raster store. A stale-closure scale is harmless by construction:\n // any scale in this rung produces this key's canonical request.\n const image = await render.renderPage(page.pon, {\n scale: page.transform.renderScale,\n includeAnnotations: annotations,\n signal: controller.signal,\n });\n const obj = await image.objectUrl(controller.signal);\n if (controller.signal.aborted) {\n obj.revoke();\n return;\n }\n revoke = obj.revoke;\n if (ref.current) ref.current.src = obj.url;\n } catch {\n /* aborted (camera moved / unmounted) or render failed */\n }\n })();\n return () => {\n controller.abort();\n revoke?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- sourceKey IS the\n // render identity; scale/annotations/epoch are folded into it upstream.\n }, [render, page.pon, sourceKey]);\n return (\n <img\n ref={ref}\n alt=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n }}\n />\n );\n}\n\nexport interface TileLayerProps {\n /**\n * Bake annotations into tile bitmaps (default true). Pass false when an\n * <AnnotationLayer> owns annotation rendering — the composition that keeps\n * tile artifacts annotation-version-free (CDN-stable across edits).\n */\n annotations?: boolean;\n}\n\n/**\n * TileLayer — the sharp plane above the base rung.\n *\n * Mounting it is the per-lens OPT-IN; whether it spends anything is demand\n * arithmetic (a thumbnail rail's demand never engages). The paint list is the\n * plugin's retention-safe plan: keyed <img>s inside ONE container that carries\n * the page scale as a single transform (one rounding context — no tile seams),\n * with `onLoad` reporting the decode boundary back so retained coarser\n * generations release only when their replacement is truly on screen.\n */\nexport function TileLayer({ annotations = true }: TileLayerProps = {}) {\n const page = usePage();\n const render = useCapability(RenderToken);\n // Demand: the host's live camera view (Stage) or whole-page (PageView).\n const demand: PageViewDemand = page.getViewDemand?.() ?? {\n desiredDeviceWidth: page.transform.deviceWidth,\n };\n const plan = useSelector(RenderToken, (c) =>\n c.tilePlan(page.pon, demand, { includeAnnotations: annotations }),\n );\n // Lens unmounted: stop in-flight tile fetches; resolved bytes stay cached.\n useEffect(() => () => render.releaseTiles(page.pon), [render, page.pon]);\n if (plan.paint.length === 0) return null;\n const t = page.transform;\n const scale = t.viewScale;\n return (\n <div\n style={{\n position: 'absolute',\n left: 0,\n top: 0,\n width: t.contentWidth / scale,\n height: t.contentHeight / scale,\n transform: `scale(${scale})`,\n transformOrigin: '0 0',\n pointerEvents: 'none',\n }}\n >\n {plan.paint.map((source) => (\n <TileImg\n key={source.key}\n source={source}\n onPainted={() => render.tilePainted(page.pon, source.key)}\n />\n ))}\n </div>\n );\n}\n\n/** One tile: object-URL lifecycle + the painted (decode-boundary) report. */\nfunction TileImg({ source, onPainted }: { source: TilePaintSource; onPainted: () => void }) {\n const ref = useRef<HTMLImageElement>(null);\n useEffect(() => {\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n (async () => {\n try {\n const obj = await source.handle.objectUrl(controller.signal);\n if (controller.signal.aborted) {\n obj.revoke();\n return;\n }\n revoke = obj.revoke;\n if (ref.current) ref.current.src = obj.url;\n } catch {\n /* aborted (plan moved on) */\n }\n })();\n return () => {\n controller.abort();\n revoke?.();\n };\n }, [source.handle]);\n return (\n <img\n ref={ref}\n alt=\"\"\n draggable={false}\n onLoad={onPainted}\n style={{\n position: 'absolute',\n left: source.rect.x,\n top: source.rect.y,\n width: source.rect.width,\n height: source.rect.height,\n zIndex: source.z,\n }}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
+ return target;
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
19
+ key = keys[i];
20
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
21
+ get: ((k) => from[k]).bind(null, key),
22
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
23
+ });
24
+ }
25
+ return to;
26
+ };
27
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ //#endregion
33
+ Object.defineProperty(exports, "__exportAll", {
34
+ enumerable: true,
35
+ get: function() {
36
+ return __exportAll;
37
+ }
38
+ });
39
+ Object.defineProperty(exports, "__reExport", {
40
+ enumerable: true,
41
+ get: function() {
42
+ return __reExport;
43
+ }
44
+ });
45
+ Object.defineProperty(exports, "__toESM", {
46
+ enumerable: true,
47
+ get: function() {
48
+ return __toESM;
49
+ }
50
+ });
@@ -0,0 +1,195 @@
1
+ import * as React from "react";
2
+ import { AnyPlugin, CapabilityToken, Engine, EngineFactory, InitialDocument, Kernel } from "@embedpdf/core";
3
+ import { PageFrame, PageTransform, Point, Rect } from "@embedpdf/core-geometry";
4
+ import { PageViewDemand } from "@embedpdf/plugin-render";
5
+ //#region src/runtime.d.ts
6
+ declare function useKernel(): Kernel;
7
+ declare const shallowArray: <T>(a: readonly T[], b: readonly T[]) => boolean;
8
+ /** Read a value derived from the kernel, cached by equality (no tearing loop). */
9
+ declare function useKernelValue<R>(select: (k: Kernel) => R, isEqual?: (a: R, b: R) => boolean): R;
10
+ declare function useActiveDocumentId(): string | null;
11
+ /** The document id for this subtree: the nearest <DocumentScope>, else the active doc. */
12
+ declare function useDocumentId(): string | null;
13
+ interface DocumentScopeProps {
14
+ id: string;
15
+ children: React.ReactNode;
16
+ }
17
+ /** Bind a subtree to a specific document (panes, comparison). */
18
+ declare function DocumentScope({ id, children }: DocumentScopeProps): import("react/jsx-runtime").JSX.Element;
19
+ interface DocumentGateProps {
20
+ /** Shown while this subtree has NO document (empty workspace, docs still opening). */
21
+ fallback?: React.ReactNode;
22
+ children: React.ReactNode;
23
+ }
24
+ /**
25
+ * Render children only while this subtree has a READY document — the
26
+ * structural way to say "this UI is defined over a document". An empty
27
+ * workspace is a legitimate, designable state (the Viewer no longer blocks on
28
+ * documents so chrome can render at t≈0): workspace-scoped UI (toolbars,
29
+ * commands, i18n) lives OUTSIDE the gate; document-scoped UI (Stage, panels,
30
+ * page chrome) lives inside it, or reads through `useOptionalSelector`.
31
+ * A `loading`/`locked`/`error` tab renders `fallback` — so the gate's
32
+ * fallback doubles as the per-tab boot state; richer chrome (a password
33
+ * prompt, an error pane) branches on `useDocumentStatus()` beside the gate.
34
+ * Sibling of <DocumentScope>, which picks WHICH document; this one handles
35
+ * WHETHER.
36
+ */
37
+ declare function DocumentGate({ fallback, children }: DocumentGateProps): import("react/jsx-runtime").JSX.Element;
38
+ /** Lifecycle status of this subtree's document (loading/locked/ready/error),
39
+ * or null with no document. The password prompt and error panes key off it. */
40
+ declare function useDocumentStatus(): import("@embedpdf/core").DocStatus | null;
41
+ /**
42
+ * Resolve a capability by token, binding document-scoped ones to this
43
+ * subtree's document. Resolution is a REACTIVE read (`tryCapability` through
44
+ * the kernel's one change stream), not a memoized call — under the
45
+ * request-time lifecycle a document can become resolvable while its id stays
46
+ * the same, so any id-keyed cache goes stale; subscribing makes staleness
47
+ * structurally impossible. Fail-fast: while unresolvable, this re-runs the
48
+ * strict resolver so the kernel's truthful reason (`no capability` / `no
49
+ * document` / `document is loading|locked`) is what throws.
50
+ */
51
+ declare function useCapability<T>(token: CapabilityToken<T>): T;
52
+ /** Like `useCapability`, but null while the token can't resolve (no plugin,
53
+ * no document, or a document that isn't ready yet). */
54
+ declare function useOptionalCapability<T>(token: CapabilityToken<T>): T | null;
55
+ /** Subscribe to a selector over a (document-resolved) capability. */
56
+ declare function useSelector<C, R>(token: CapabilityToken<C>, select: (cap: C) => R, isEqual?: (a: R, b: R) => boolean): R;
57
+ /**
58
+ * Null-safe `useSelector`: `fallback` whenever the token can't resolve — no
59
+ * provider, or a document-scoped token with no document. For chrome that stays
60
+ * mounted across the empty-workspace state (a zoom readout, a mode band).
61
+ * `useSelector` stays strict (fail-fast) for code that KNOWS a document exists
62
+ * — e.g. anything inside a <DocumentGate>.
63
+ *
64
+ * The `select` guard also swallows reads through a capability whose document
65
+ * closed between the store notification and this render — that teardown race
66
+ * resolves to `fallback` for one frame, then re-renders against the new state.
67
+ */
68
+ declare function useOptionalSelector<C, R>(token: CapabilityToken<C>, select: (cap: C) => R, fallback: R, isEqual?: (a: R, b: R) => boolean): R;
69
+ /** The document registry (open/close/active/list), reactive. */
70
+ declare function useDocuments(): {
71
+ docs: import("@embedpdf/core").DocInfo[];
72
+ activeId: string | null;
73
+ open: (input: import("@embedpdf/core").OpenSource, options?: import("@embedpdf/core").OpenDocumentOptions) => Promise<string>;
74
+ unlock: (id: string, input: {
75
+ password: string;
76
+ }) => Promise<void>;
77
+ close: (id: string) => Promise<void>;
78
+ setActive: (id: string) => void;
79
+ move: (id: string, toIndex: number) => void;
80
+ swap: (a: string, b: string) => void;
81
+ download: (id?: string, opts?: {
82
+ mode?: import("@embedpdf/core").PdfSaveMode;
83
+ }) => Promise<Uint8Array>;
84
+ downloadLayer: (id?: string) => Promise<Uint8Array>;
85
+ };
86
+ interface ViewerProps {
87
+ /**
88
+ * The engine, as an instance or a thunk. Engines construct synchronously and
89
+ * boot lazily (`localEngine()` allocates nothing until first use), so
90
+ * ownership follows the SHAPE of what you pass:
91
+ *
92
+ * - An **instance** (`engine={engine}`) is BORROWED: the Viewer uses it and
93
+ * never destroys it, because you acquired it and therefore own it. The
94
+ * common path — a module-scope `const engine = localEngine()` shared
95
+ * across viewers and route changes. The Viewer calls `engine.warmup?.()`
96
+ * on mount so the boot overlaps app initialization.
97
+ * - A **thunk** (`engine={() => localEngine()}`) is VIEWER-OWNED: the
98
+ * Viewer calls it on mount and `destroy()`s the result on unmount. Use it
99
+ * for per-mount isolation (StrictMode/HMR-clean teardown, independent
100
+ * multi-viewer engines).
101
+ *
102
+ * Init-only: captured on first render; later identity changes are ignored (dev warns).
103
+ */
104
+ engine: Engine | EngineFactory;
105
+ /** Init-only: captured on first render; later identity changes are ignored (dev warns). */
106
+ plugins: AnyPlugin[];
107
+ /** Documents to open on startup (with optional tab names). Init-only. */
108
+ initialDocuments?: InitialDocument[];
109
+ fallback?: React.ReactNode;
110
+ /** Rendered when kernel construction or `start()` fails. Without it a boot
111
+ * failure renders nothing — but never a silent forever-fallback. */
112
+ renderError?: (error: unknown) => React.ReactNode;
113
+ children: React.ReactNode;
114
+ }
115
+ /**
116
+ * Owns the kernel as an EFFECT-scoped resource: each effect setup creates and
117
+ * starts exactly one kernel; each cleanup destroys exactly that one. That is
118
+ * the contract StrictMode exercises (two kernels in dev, the first fully
119
+ * destroyed) — the kernel itself is never restarted after destroy.
120
+ *
121
+ * The kernel is published to context the moment it exists — before `start()`
122
+ * resolves — so the `fallback` can use workspace capabilities (i18n copy on a
123
+ * loading screen) exactly as before. The one exception is the very first
124
+ * render, which happens before the effect: it renders nothing. Children mount
125
+ * once `start()` resolves — which never touches the engine, so the shell is
126
+ * alive while WASM compiles or the transport connects. `initialDocuments`
127
+ * open in the BACKGROUND and stream into the registry (`useDocuments()` is
128
+ * reactive); per-document loading UI is the Stage's job, not a root gate.
129
+ *
130
+ * ENGINE OWNERSHIP. When `engine` is a thunk, the Viewer OWNS it: each effect
131
+ * setup constructs one engine (construction is synchronous and inert — boot
132
+ * happens lazily inside the engine) and each cleanup destroys exactly that one
133
+ * — after the kernel, so handles close first. When `engine` is an instance it
134
+ * is BORROWED and never destroyed here; the Viewer only calls `warmup?.()` so
135
+ * the WASM/transport boot overlaps plugin initialization. StrictMode's
136
+ * double-mount therefore constructs two independent thunk engines and tears
137
+ * the first fully down, matching the kernel's own effect-scoped lifecycle.
138
+ * That means dev-only double resource use (two worker spawns, two font
139
+ * fetches, briefly overlapping) — deliberate, because it is exactly the
140
+ * leak-detection contract StrictMode exists to exercise; production mounts
141
+ * once and boots once.
142
+ */
143
+ declare function Viewer({ engine, plugins, initialDocuments, fallback, renderError, children }: ViewerProps): import("react/jsx-runtime").JSX.Element | null;
144
+ declare const EmbedPDF: typeof Viewer;
145
+ /**
146
+ * PageContext — the seam. A layer depends ONLY on this, never on the Stage. So the
147
+ * same layer works inside a virtualized Stage and in a standalone <PageView>.
148
+ */
149
+ interface PageContextValue {
150
+ documentId: string;
151
+ /** Durable page identity (PDF object number) — use for keys / render / annotations. */
152
+ pon: number;
153
+ /** Display index (page N) — use for ordering / human-facing page numbers. */
154
+ pageIndex: number;
155
+ /**
156
+ * Reserved chrome bands around the page (screen px per side). The page-chrome
157
+ * slot renders into the outer box (content + frame); these thicknesses size
158
+ * the bands — a label in the bottom band is `bottom:0; height: frame.bottom`.
159
+ */
160
+ frame: PageFrame;
161
+ /**
162
+ * The single bridge between PDF points, view px, and device px for this page.
163
+ * Layers do ALL coordinate work through it — `pageToContent` to place content-
164
+ * space overlays, `renderScale`/`deviceWidth` to render, `contentWidth` for
165
+ * page-relative sizing. Never re-derive `x * scale` or `* dpr`.
166
+ */
167
+ transform: PageTransform;
168
+ /** Client (screen) point → PDF point — the one platform-bound hit-test. */
169
+ toPagePoint(clientX: number, clientY: number): Point;
170
+ /** PDF/content point → client (screen) px — the exact inverse of `toPagePoint`
171
+ * (rotation applied). Lets viewport-space UI (e.g. a selection menu) anchor to a
172
+ * page point WITHOUT a Stage camera, so it works the same in `<PageView>`. */
173
+ toClientPoint(p: Point): Point;
174
+ /** PDF/content rect → client (screen) px AABB. Rect analog of `toClientPoint`
175
+ * for upright viewport-space UI that frames a selected page region. */
176
+ toClientRect(rect: Rect): Rect;
177
+ /**
178
+ * The page-view DEMAND for raster planning uses dependency inversion:
179
+ * plugin-render defines the shape; the host that CREATED this
180
+ * context fills it — as a PULL. The Stage host's getter closes over the
181
+ * stage capability and reads `VisiblePage.visibleRect` live at call time
182
+ * (visibility is the STAGE's data; adapters never re-derive camera math or
183
+ * cache a copy). Three states, three meanings: a real sub-rect (visible),
184
+ * a ZERO rect (stage host, page currently off-screen — want nothing), and
185
+ * an undefined getter (stage-less `<PageView>` — whole page visible, which
186
+ * a thumbnail-sized demand turns into "never engages" by arithmetic).
187
+ */
188
+ getViewDemand?: () => PageViewDemand;
189
+ }
190
+ declare const PageProvider: React.Provider<PageContextValue | null>;
191
+ declare function usePage(): PageContextValue;
192
+ declare function makePageContext(documentId: string, pon: number, pageIndex: number, frame: PageFrame, transform: PageTransform, getRect: () => DOMRect, getViewDemand?: () => PageViewDemand): PageContextValue;
193
+ //#endregion
194
+ export { useSelector as S, useKernel as _, EmbedPDF as a, useOptionalSelector as b, Viewer as c, shallowArray as d, useActiveDocumentId as f, useDocuments as g, useDocumentStatus as h, DocumentScopeProps as i, ViewerProps as l, useDocumentId as m, DocumentGateProps as n, PageContextValue as o, useCapability as p, DocumentScope as r, PageProvider as s, DocumentGate as t, makePageContext as u, useKernelValue as v, usePage as x, useOptionalCapability as y };
195
+ //# sourceMappingURL=runtime-CMxIuF2O.d.cts.map