@embedpdf/react 3.0.0-next.1 → 3.0.0-next.11

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 (132) hide show
  1. package/dist/AnnotationListSnapshot-C1U3XUxP-6kGwNoxy.d.cts +546 -0
  2. package/dist/AnnotationListSnapshot-C1U3XUxP-6kGwNoxy.d.ts +546 -0
  3. package/dist/actions.cjs +42 -0
  4. package/dist/actions.cjs.map +1 -0
  5. package/dist/actions.d.cts +18 -0
  6. package/dist/actions.d.ts +18 -0
  7. package/dist/actions.js +34 -0
  8. package/dist/actions.js.map +1 -0
  9. package/dist/anchored.cjs +89 -0
  10. package/dist/anchored.cjs.map +1 -0
  11. package/dist/anchored.d.cts +45 -0
  12. package/dist/anchored.d.ts +45 -0
  13. package/dist/anchored.js +60 -0
  14. package/dist/anchored.js.map +1 -0
  15. package/dist/{annotation-B6jwfTCh.d.cts → annotation-BCED_p9H.d.cts} +56 -69
  16. package/dist/annotation-anchors-CetwM1g7.js +15 -0
  17. package/dist/annotation-anchors-CetwM1g7.js.map +1 -0
  18. package/dist/annotation-anchors-DuYRBJLl.cjs +26 -0
  19. package/dist/annotation-anchors-DuYRBJLl.cjs.map +1 -0
  20. package/dist/annotation-hooks-BB5ZhPpf.cjs +16 -0
  21. package/dist/annotation-hooks-BB5ZhPpf.cjs.map +1 -0
  22. package/dist/annotation-hooks-Df8EmzDO.js +11 -0
  23. package/dist/annotation-hooks-Df8EmzDO.js.map +1 -0
  24. package/dist/{annotation-nUMefyjw.d.ts → annotation-k38KDlIZ.d.ts} +57 -70
  25. package/dist/annotation-menu.cjs +37 -88
  26. package/dist/annotation-menu.cjs.map +1 -1
  27. package/dist/annotation-menu.d.cts +28 -2
  28. package/dist/annotation-menu.d.ts +28 -2
  29. package/dist/annotation-menu.js +28 -79
  30. package/dist/annotation-menu.js.map +1 -1
  31. package/dist/annotation.cjs +738 -16
  32. package/dist/annotation.cjs.map +1 -0
  33. package/dist/annotation.d.cts +2 -2
  34. package/dist/annotation.d.ts +2 -2
  35. package/dist/annotation.js +723 -3
  36. package/dist/annotation.js.map +1 -0
  37. package/dist/commands.js +1 -0
  38. package/dist/commands.js.map +1 -1
  39. package/dist/form-BwrLFpKN.js +805 -0
  40. package/dist/form-BwrLFpKN.js.map +1 -0
  41. package/dist/form-D-ZSfGmB.cjs +836 -0
  42. package/dist/form-D-ZSfGmB.cjs.map +1 -0
  43. package/dist/form.cjs +8 -551
  44. package/dist/form.d.cts +4 -21
  45. package/dist/form.d.ts +4 -21
  46. package/dist/form.js +3 -544
  47. package/dist/index.cjs +49 -16
  48. package/dist/index.d.cts +17 -10
  49. package/dist/index.d.ts +17 -10
  50. package/dist/index.js +14 -9
  51. package/dist/interaction.cjs +17 -4
  52. package/dist/interaction.cjs.map +1 -1
  53. package/dist/interaction.d.cts +2 -2
  54. package/dist/interaction.d.ts +2 -2
  55. package/dist/interaction.js +7 -5
  56. package/dist/interaction.js.map +1 -1
  57. package/dist/link.cjs +70 -7
  58. package/dist/link.cjs.map +1 -1
  59. package/dist/link.d.cts +12 -3
  60. package/dist/link.d.ts +12 -3
  61. package/dist/link.js +73 -10
  62. package/dist/link.js.map +1 -1
  63. package/dist/metadata.js +1 -0
  64. package/dist/metadata.js.map +1 -1
  65. package/dist/page-edit.js +1 -0
  66. package/dist/page-edit.js.map +1 -1
  67. package/dist/page-view.cjs +62 -38
  68. package/dist/page-view.cjs.map +1 -1
  69. package/dist/page-view.js +59 -37
  70. package/dist/page-view.js.map +1 -1
  71. package/dist/redaction.js +1 -0
  72. package/dist/redaction.js.map +1 -1
  73. package/dist/render.cjs +67 -50
  74. package/dist/render.cjs.map +1 -1
  75. package/dist/render.d.cts +6 -19
  76. package/dist/render.d.ts +6 -19
  77. package/dist/render.js +71 -52
  78. package/dist/render.js.map +1 -1
  79. package/dist/rolldown-runtime-BBjsoOtd.js +27 -0
  80. package/dist/{runtime-CMxIuF2O.d.cts → runtime-DE76hlnl.d.ts} +32 -11
  81. package/dist/{runtime-DV98q7I0.d.ts → runtime-umHA_xHt.d.cts} +32 -11
  82. package/dist/runtime.cjs +25 -5
  83. package/dist/runtime.cjs.map +1 -1
  84. package/dist/runtime.d.cts +2 -2
  85. package/dist/runtime.d.ts +2 -2
  86. package/dist/runtime.js +26 -6
  87. package/dist/runtime.js.map +1 -1
  88. package/dist/scrollbar.cjs +3 -3
  89. package/dist/scrollbar.cjs.map +1 -1
  90. package/dist/scrollbar.d.cts +1 -1
  91. package/dist/scrollbar.d.ts +1 -1
  92. package/dist/scrollbar.js +1 -1
  93. package/dist/scrollbar.js.map +1 -1
  94. package/dist/search.cjs +36 -19
  95. package/dist/search.cjs.map +1 -1
  96. package/dist/search.d.cts +1 -1
  97. package/dist/search.d.ts +1 -1
  98. package/dist/search.js +36 -19
  99. package/dist/search.js.map +1 -1
  100. package/dist/selection.cjs +217 -22
  101. package/dist/selection.cjs.map +1 -1
  102. package/dist/selection.d.cts +60 -2
  103. package/dist/selection.d.ts +60 -2
  104. package/dist/selection.js +214 -27
  105. package/dist/selection.js.map +1 -1
  106. package/dist/shell.js +1 -0
  107. package/dist/shell.js.map +1 -1
  108. package/dist/stage.cjs +49 -148
  109. package/dist/stage.cjs.map +1 -1
  110. package/dist/stage.d.cts +18 -5
  111. package/dist/stage.d.ts +18 -5
  112. package/dist/stage.js +51 -149
  113. package/dist/stage.js.map +1 -1
  114. package/dist/stamp.js +1 -0
  115. package/dist/stamp.js.map +1 -1
  116. package/dist/toolbar.cjs +4 -4
  117. package/dist/toolbar.cjs.map +1 -1
  118. package/dist/toolbar.d.cts +1 -1
  119. package/dist/toolbar.d.ts +1 -1
  120. package/dist/toolbar.js +2 -1
  121. package/dist/toolbar.js.map +1 -1
  122. package/dist/views.js +1 -0
  123. package/dist/views.js.map +1 -1
  124. package/package.json +33 -26
  125. package/dist/AnnotationListSnapshot-W0RCsyDE-dWna4TTJ.d.cts +0 -2593
  126. package/dist/AnnotationListSnapshot-W0RCsyDE-dWna4TTJ.d.ts +0 -2593
  127. package/dist/annotation-Ct6dFtzJ.cjs +0 -913
  128. package/dist/annotation-Ct6dFtzJ.cjs.map +0 -1
  129. package/dist/annotation-DjGWJljY.js +0 -829
  130. package/dist/annotation-DjGWJljY.js.map +0 -1
  131. package/dist/form.cjs.map +0 -1
  132. package/dist/form.js.map +0 -1
package/dist/link.d.cts CHANGED
@@ -1,7 +1,16 @@
1
1
  import * as React from "react";
2
- import { LinkNavItem } from "@embedpdf/plugin-link";
2
+ import { LinkActivateContext, LinkActivation, LinkCapability, LinkNavItem, PdfLinkTarget } from "@embedpdf/plugin-link";
3
3
  export * from "@embedpdf/plugin-link";
4
4
  //#region src/link.d.ts
5
+ /**
6
+ * Resolve a target through the plugin and PERFORM the `uri` outcome — the ONE
7
+ * place in the codebase that turns a link target into a browser tab. The
8
+ * plugin owns resolution (goto → stage reveal, policy, analytics) and stays
9
+ * DOM-free; opening is this framework layer's job. Every click path — the nav
10
+ * anchors below, the selection menu's "Open link", the style editor's "Go to
11
+ * link" — goes through here, so none of them can drop the uri outcome again.
12
+ */
13
+ declare function openLinkTarget(link: LinkCapability, target: PdfLinkTarget, context?: LinkActivateContext): LinkActivation;
5
14
  interface LinkLayerProps {
6
15
  /** Wrap or replace a link's native anchor (badging, custom tooltips). */
7
16
  renderLink?: (args: {
@@ -10,7 +19,7 @@ interface LinkLayerProps {
10
19
  }) => React.ReactNode | undefined;
11
20
  }
12
21
  declare function LinkLayer({ renderLink }?: LinkLayerProps): import("react/jsx-runtime").JSX.Element | null;
13
- declare function useLink(): import("@embedpdf/plugin-link").LinkCapability;
22
+ declare function useLink(): LinkCapability;
14
23
  //#endregion
15
- export { LinkLayer, LinkLayerProps, useLink };
24
+ export { LinkLayer, LinkLayerProps, openLinkTarget, useLink };
16
25
  //# sourceMappingURL=link.d.cts.map
package/dist/link.d.ts CHANGED
@@ -1,7 +1,16 @@
1
1
  import * as React from "react";
2
- import { LinkNavItem } from "@embedpdf/plugin-link";
2
+ import { LinkActivateContext, LinkActivation, LinkCapability, LinkNavItem, PdfLinkTarget } from "@embedpdf/plugin-link";
3
3
  export * from "@embedpdf/plugin-link";
4
4
  //#region src/link.d.ts
5
+ /**
6
+ * Resolve a target through the plugin and PERFORM the `uri` outcome — the ONE
7
+ * place in the codebase that turns a link target into a browser tab. The
8
+ * plugin owns resolution (goto → stage reveal, policy, analytics) and stays
9
+ * DOM-free; opening is this framework layer's job. Every click path — the nav
10
+ * anchors below, the selection menu's "Open link", the style editor's "Go to
11
+ * link" — goes through here, so none of them can drop the uri outcome again.
12
+ */
13
+ declare function openLinkTarget(link: LinkCapability, target: PdfLinkTarget, context?: LinkActivateContext): LinkActivation;
5
14
  interface LinkLayerProps {
6
15
  /** Wrap or replace a link's native anchor (badging, custom tooltips). */
7
16
  renderLink?: (args: {
@@ -10,7 +19,7 @@ interface LinkLayerProps {
10
19
  }) => React.ReactNode | undefined;
11
20
  }
12
21
  declare function LinkLayer({ renderLink }?: LinkLayerProps): import("react/jsx-runtime").JSX.Element | null;
13
- declare function useLink(): import("@embedpdf/plugin-link").LinkCapability;
22
+ declare function useLink(): LinkCapability;
14
23
  //#endregion
15
- export { LinkLayer, LinkLayerProps, useLink };
24
+ export { LinkLayer, LinkLayerProps, openLinkTarget, useLink };
16
25
  //# sourceMappingURL=link.d.ts.map
package/dist/link.js CHANGED
@@ -1,19 +1,38 @@
1
- import { shallowArray, useCapability, usePage, useSelector } from "./runtime.js";
1
+ import "./rolldown-runtime-BBjsoOtd.js";
2
+ import { shallowArray, useCapability, useOptionalCapability, useOptionalSelector, usePage, useSelector } from "./runtime.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import * as React from "react";
4
- import { useEffect } from "react";
5
+ import { useEffect, useMemo } from "react";
5
6
  import { sanitizeExternalUri } from "@embedpdf/web";
7
+ import { InteractionToken } from "@embedpdf/plugin-interaction/contract";
6
8
  import { LinkToken } from "@embedpdf/plugin-link";
9
+ import { ActionsToken, createHoverPump } from "@embedpdf/plugin-actions/contract";
7
10
  export * from "@embedpdf/plugin-link";
8
11
  //#region src/link.tsx
12
+ /**
13
+ * Resolve a target through the plugin and PERFORM the `uri` outcome — the ONE
14
+ * place in the codebase that turns a link target into a browser tab. The
15
+ * plugin owns resolution (goto → stage reveal, policy, analytics) and stays
16
+ * DOM-free; opening is this framework layer's job. Every click path — the nav
17
+ * anchors below, the selection menu's "Open link", the style editor's "Go to
18
+ * link" — goes through here, so none of them can drop the uri outcome again.
19
+ */
20
+ function openLinkTarget(link, target, context) {
21
+ const activation = link.activate(target, context);
22
+ if (activation.outcome === "uri") {
23
+ const href = sanitizeExternalUri(activation.uri);
24
+ if (href && typeof window !== "undefined") window.open(href, "_blank", "noopener,noreferrer");
25
+ }
26
+ return activation;
27
+ }
9
28
  /** Content rect → view px (the page wrapper's own space) — the same idiom as
10
29
  * the annotation and form layers: never re-derive `x * scale`. */
11
30
  function boxOf(item, page) {
12
- const tl = page.transform.pageToContent({
31
+ const tl = page.transform.toPixels({
13
32
  x: item.rect.x,
14
33
  y: item.rect.y
15
34
  });
16
- const br = page.transform.pageToContent({
35
+ const br = page.transform.toPixels({
17
36
  x: item.rect.x + item.rect.width,
18
37
  y: item.rect.y + item.rect.height
19
38
  });
@@ -37,22 +56,49 @@ function labelOf(item) {
37
56
  function LinkLayer({ renderLink } = {}) {
38
57
  const page = usePage();
39
58
  const link = useCapability(LinkToken);
59
+ const actions = useOptionalCapability(ActionsToken);
60
+ const linkPump = useMemo(() => actions ? createHoverPump(actions.dispatch) : null, [actions]);
40
61
  const items = useSelector(LinkToken, (c) => c.linksOn(page.pon), shallowArray);
41
62
  const engaged = useSelector(LinkToken, (c) => c.engaged());
63
+ const editEnabled = useOptionalSelector(InteractionToken, (c) => c.activeTool()?.enables.has("annotation-edit") ?? false, false);
42
64
  useEffect(() => {
43
65
  link.ensurePage(page.pon);
44
66
  }, [link, page.pon]);
45
67
  if (!engaged || !items.length) return null;
68
+ const visible = editEnabled ? items.filter((i) => !i.attached) : items;
69
+ if (!visible.length) return null;
46
70
  return /* @__PURE__ */ jsx("div", {
47
71
  style: {
48
72
  position: "absolute",
49
73
  inset: 0,
50
74
  pointerEvents: "none"
51
75
  },
52
- children: items.map((item) => {
76
+ children: visible.map((item) => {
53
77
  const box = boxOf(item, page);
78
+ const chained = (item.activate?.root?.next.length ?? 0) > 0;
79
+ const href = item.target.kind === "uri" && !chained ? sanitizeExternalUri(item.target.uri) : null;
80
+ const context = {
81
+ activate: item.activate,
82
+ ref: item.ref,
83
+ pon: page.pon
84
+ };
85
+ const linkSource = item.ref ? {
86
+ kind: "link",
87
+ annotation: item.ref,
88
+ pon: page.pon
89
+ } : null;
90
+ const notify = (event) => {
91
+ if (!actions || !item.ref || !linkSource) return;
92
+ actions.dispatch({
93
+ scope: "annotation",
94
+ event,
95
+ ref: item.ref,
96
+ pon: page.pon,
97
+ source: linkSource
98
+ });
99
+ };
54
100
  const native = /* @__PURE__ */ jsx("a", {
55
- href: (item.target.kind === "uri" ? sanitizeExternalUri(item.target.uri) : null) ?? void 0,
101
+ href: href ?? void 0,
56
102
  target: "_blank",
57
103
  rel: "noopener noreferrer",
58
104
  role: "link",
@@ -61,16 +107,33 @@ function LinkLayer({ renderLink } = {}) {
61
107
  "aria-label": labelOf(item),
62
108
  onClick: (e) => {
63
109
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
110
+ if (href) return;
64
111
  e.preventDefault();
65
- link.activate(item.target);
112
+ openLinkTarget(link, item.target, context);
66
113
  },
67
114
  onKeyDown: (e) => {
68
115
  if (e.key === "Enter" || e.key === " ") {
69
116
  e.preventDefault();
70
- link.activate(item.target);
117
+ openLinkTarget(link, item.target, context);
71
118
  }
72
119
  },
73
- onPointerDown: (e) => e.stopPropagation(),
120
+ onPointerEnter: () => {
121
+ if (!linkPump || !item.ref || !item.hoverEvents) return;
122
+ linkPump.hover({
123
+ ref: item.ref,
124
+ pon: page.pon,
125
+ ...linkSource ? { source: linkSource } : {},
126
+ events: item.hoverEvents
127
+ });
128
+ },
129
+ onPointerLeave: () => linkPump?.hover(null),
130
+ onPointerUp: () => notify("mouseUp"),
131
+ onFocus: () => notify("focus"),
132
+ onBlur: () => notify("blur"),
133
+ onPointerDown: (e) => {
134
+ e.stopPropagation();
135
+ notify("mouseDown");
136
+ },
74
137
  style: {
75
138
  position: "absolute",
76
139
  left: box.left,
@@ -93,6 +156,6 @@ function useLink() {
93
156
  return useCapability(LinkToken);
94
157
  }
95
158
  //#endregion
96
- export { LinkLayer, useLink };
159
+ export { LinkLayer, openLinkTarget, useLink };
97
160
 
98
161
  //# sourceMappingURL=link.js.map
package/dist/link.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","names":[],"sources":["../src/link.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-link — the navigation plane's paint.\n *\n * One absolutely-positioned <a> per clickable link area, real anchors on\n * purpose: URIs get an `href` (middle-click, copy-link, status-bar preview\n * and keyboard focus for free), internal destinations activate through the\n * plugin (stage reveal). The layer stands down entirely while the active\n * tool doesn't enable `link-nav` — the annotation plane owns links then\n * (select / move / resize / retarget through the selection editor).\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-link';\nimport * as React from 'react';\nimport { useEffect } from 'react';\nimport { LinkToken, type LinkNavItem } from '@embedpdf/plugin-link';\nimport { sanitizeExternalUri } from '@embedpdf/web';\n\nimport { shallowArray, useCapability, usePage, useSelector } from './runtime';\nimport type { PageContextValue } from './runtime';\n\n/** Content rect → view px (the page wrapper's own space) — the same idiom as\n * the annotation and form layers: never re-derive `x * scale`. */\nfunction boxOf(item: LinkNavItem, page: PageContextValue) {\n const tl = page.transform.pageToContent({ x: item.rect.x, y: item.rect.y });\n const br = page.transform.pageToContent({\n x: item.rect.x + item.rect.width,\n y: item.rect.y + item.rect.height,\n });\n return { left: tl.x, top: tl.y, width: br.x - tl.x, height: br.y - tl.y };\n}\n\n/** A human label for the hover tooltip. Apps with i18n render their own via\n * `renderLink`; this is the sensible default. */\nfunction labelOf(item: LinkNavItem): string {\n switch (item.target.kind) {\n case 'uri':\n return item.target.uri;\n case 'goto':\n return 'Go to destination';\n case 'named':\n return item.target.name;\n default:\n return 'Link';\n }\n}\n\nexport interface LinkLayerProps {\n /** Wrap or replace a link's native anchor (badging, custom tooltips). */\n renderLink?: (args: {\n item: LinkNavItem;\n nativeComponent: React.ReactNode;\n }) => React.ReactNode | undefined;\n}\n\nexport function LinkLayer({ renderLink }: LinkLayerProps = {}) {\n const page = usePage();\n const link = useCapability(LinkToken);\n const items = useSelector(LinkToken, (c) => c.linksOn(page.pon), shallowArray);\n const engaged = useSelector(LinkToken, (c) => c.engaged());\n\n useEffect(() => {\n link.ensurePage(page.pon);\n }, [link, page.pon]);\n\n // An authoring tool is active → the annotation plane owns links (they're\n // plain editable rects there); no nav anchors, no swallowed pointer events.\n if (!engaged || !items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((item) => {\n const box = boxOf(item, page);\n // Real href ONLY for sanitized external URIs; blocked schemes and\n // internal targets activate through the plugin instead.\n const href = item.target.kind === 'uri' ? sanitizeExternalUri(item.target.uri) : null;\n const native = (\n <a\n href={href ?? undefined}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n tabIndex={0}\n title={labelOf(item)}\n aria-label={labelOf(item)}\n onClick={(e) => {\n // Plain left-click activates through the plugin (stage reveal /\n // policy / analytics). Modified clicks and middle-clicks on a\n // real href keep their native browser behaviour.\n if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n e.preventDefault();\n link.activate(item.target);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n link.activate(item.target);\n }\n }}\n // Keep the hub out of it: a down inside the anchor must not reach\n // the Stage's native listener (same isolation idiom as FreeText).\n onPointerDown={(e) => e.stopPropagation()}\n style={{\n position: 'absolute',\n left: box.left,\n top: box.top,\n width: box.width,\n height: box.height,\n cursor: 'pointer',\n pointerEvents: 'auto',\n }}\n />\n );\n const out = renderLink?.({ item, nativeComponent: native }) ?? native;\n return <React.Fragment key={item.id}>{out}</React.Fragment>;\n })}\n </div>\n );\n}\n\nexport function useLink() {\n return useCapability(LinkToken);\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAS,MAAM,MAAmB,MAAwB;CACxD,MAAM,KAAK,KAAK,UAAU,cAAc;EAAE,GAAG,KAAK,KAAK;EAAG,GAAG,KAAK,KAAK;CAAE,CAAC;CAC1E,MAAM,KAAK,KAAK,UAAU,cAAc;EACtC,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK;EAC3B,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK;CAC7B,CAAC;CACD,OAAO;EAAE,MAAM,GAAG;EAAG,KAAK,GAAG;EAAG,OAAO,GAAG,IAAI,GAAG;EAAG,QAAQ,GAAG,IAAI,GAAG;CAAE;AAC1E;;;AAIA,SAAS,QAAQ,MAA2B;CAC1C,QAAQ,KAAK,OAAO,MAApB;EACE,KAAK,OACH,OAAO,KAAK,OAAO;EACrB,KAAK,QACH,OAAO;EACT,KAAK,SACH,OAAO,KAAK,OAAO;EACrB,SACE,OAAO;CACX;AACF;AAUA,SAAgB,UAAU,EAAE,eAA+B,CAAC,GAAG;CAC7D,MAAM,OAAO,QAAQ;CACrB,MAAM,OAAO,cAAc,SAAS;CACpC,MAAM,QAAQ,YAAY,YAAY,MAAM,EAAE,QAAQ,KAAK,GAAG,GAAG,YAAY;CAC7E,MAAM,UAAU,YAAY,YAAY,MAAM,EAAE,QAAQ,CAAC;CAEzD,gBAAgB;EACd,KAAK,WAAW,KAAK,GAAG;CAC1B,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;CAInB,IAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,OAAO;CAEtC,OACE,oBAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EACjE,UAAA,MAAM,KAAK,SAAS;GACnB,MAAM,MAAM,MAAM,MAAM,IAAI;GAI5B,MAAM,SACJ,oBAAC,KAAD;IACE,OAHS,KAAK,OAAO,SAAS,QAAQ,oBAAoB,KAAK,OAAO,GAAG,IAAI,SAG/D,KAAA;IACd,QAAO;IACP,KAAI;IACJ,MAAK;IACL,UAAU;IACV,OAAO,QAAQ,IAAI;IACnB,cAAY,QAAQ,IAAI;IACxB,UAAU,MAAM;KAId,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ;KACtD,EAAE,eAAe;KACjB,KAAK,SAAS,KAAK,MAAM;IAC3B;IACA,YAAY,MAAM;KAChB,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;MACtC,EAAE,eAAe;MACjB,KAAK,SAAS,KAAK,MAAM;KAC3B;IACF;IAGA,gBAAgB,MAAM,EAAE,gBAAgB;IACxC,OAAO;KACL,UAAU;KACV,MAAM,IAAI;KACV,KAAK,IAAI;KACT,OAAO,IAAI;KACX,QAAQ,IAAI;KACZ,QAAQ;KACR,eAAe;IACjB;GACD,CAAA;GAEH,MAAM,MAAM,aAAa;IAAE;IAAM,iBAAiB;GAAO,CAAC,KAAK;GAC/D,OAAO,oBAAC,MAAM,UAAP,EAAA,UAA+B,IAAoB,GAA9B,KAAK,EAAyB;EAC5D,CAAC;CACE,CAAA;AAET;AAEA,SAAgB,UAAU;CACxB,OAAO,cAAc,SAAS;AAChC"}
1
+ {"version":3,"file":"link.js","names":[],"sources":["../src/link.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-link — the navigation plane's paint.\n *\n * One absolutely-positioned <a> per clickable link area, real anchors on\n * purpose: URIs get an `href` (middle-click, copy-link, status-bar preview\n * and keyboard focus for free), internal destinations activate through the\n * plugin (stage reveal). The layer stands down entirely while the active\n * tool doesn't enable `link-nav` — the annotation plane owns links then\n * (select / move / resize / retarget through the selection editor).\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-link';\nimport * as React from 'react';\nimport { useEffect, useMemo } from 'react';\nimport { ActionsToken, createHoverPump } from '@embedpdf/plugin-actions/contract';\nimport type {\n ActionSource,\n PdfAnnotationEventKind,\n} from '@embedpdf/plugin-actions/contract';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport {\n LinkToken,\n type LinkActivateContext,\n type LinkActivation,\n type LinkCapability,\n type LinkNavItem,\n type PdfLinkTarget,\n} from '@embedpdf/plugin-link';\nimport { sanitizeExternalUri } from '@embedpdf/web';\n\nimport {\n shallowArray,\n useCapability,\n useOptionalCapability,\n useOptionalSelector,\n usePage,\n useSelector,\n} from './runtime';\nimport type { PageContextValue } from './runtime';\n\n/**\n * Resolve a target through the plugin and PERFORM the `uri` outcome — the ONE\n * place in the codebase that turns a link target into a browser tab. The\n * plugin owns resolution (goto → stage reveal, policy, analytics) and stays\n * DOM-free; opening is this framework layer's job. Every click path — the nav\n * anchors below, the selection menu's \"Open link\", the style editor's \"Go to\n * link\" — goes through here, so none of them can drop the uri outcome again.\n */\nexport function openLinkTarget(\n link: LinkCapability,\n target: PdfLinkTarget,\n context?: LinkActivateContext,\n): LinkActivation {\n const activation = link.activate(target, context);\n if (activation.outcome === 'uri') {\n const href = sanitizeExternalUri(activation.uri);\n if (href && typeof window !== 'undefined') window.open(href, '_blank', 'noopener,noreferrer');\n }\n // 'dispatched': the action engine took it — the actions UI adapter owns any\n // URI open (the no-double-open rule); this opener must do NOTHING.\n return activation;\n}\n\n/** Content rect → view px (the page wrapper's own space) — the same idiom as\n * the annotation and form layers: never re-derive `x * scale`. */\nfunction boxOf(item: LinkNavItem, page: PageContextValue) {\n const tl = page.transform.toPixels({ x: item.rect.x, y: item.rect.y });\n const br = page.transform.toPixels({\n x: item.rect.x + item.rect.width,\n y: item.rect.y + item.rect.height,\n });\n return { left: tl.x, top: tl.y, width: br.x - tl.x, height: br.y - tl.y };\n}\n\n/** A human label for the hover tooltip. Apps with i18n render their own via\n * `renderLink`; this is the sensible default. */\nfunction labelOf(item: LinkNavItem): string {\n switch (item.target.kind) {\n case 'uri':\n return item.target.uri;\n case 'goto':\n return 'Go to destination';\n case 'named':\n return item.target.name;\n default:\n return 'Link';\n }\n}\n\nexport interface LinkLayerProps {\n /** Wrap or replace a link's native anchor (badging, custom tooltips). */\n renderLink?: (args: {\n item: LinkNavItem;\n nativeComponent: React.ReactNode;\n }) => React.ReactNode | undefined;\n}\n\nexport function LinkLayer({ renderLink }: LinkLayerProps = {}) {\n const page = usePage();\n const link = useCapability(LinkToken);\n // The link plane's /AA event feed: links are behavior-inert to the\n // annotation plane's hover feed while navigable (their pixels are THESE\n // anchors), so E/X/D/U/Fo/Bl can only fire from here. One shared pump per\n // layer — crossing layers still orders Exit before Enter because both\n // sides submit synchronously in DOM event order.\n const actions = useOptionalCapability(ActionsToken);\n const linkPump = useMemo(() => (actions ? createHoverPump(actions.dispatch) : null), [actions]);\n const items = useSelector(LinkToken, (c) => c.linksOn(page.pon), shallowArray);\n const engaged = useSelector(LinkToken, (c) => c.engaged());\n // One owner per pixel: an ATTACHED link is a property of its parent — while\n // the active tool can edit annotations, the parent owns those pixels and\n // the anchor stands down (select/move/resize work; no tooltip, no swallowed\n // pointer). Standalone document links navigate under any link-nav tool.\n const editEnabled = useOptionalSelector(\n InteractionToken,\n (c) => c.activeTool()?.enables.has('annotation-edit') ?? false,\n false,\n );\n\n useEffect(() => {\n link.ensurePage(page.pon);\n }, [link, page.pon]);\n\n // An authoring tool is active → the annotation plane owns links (they're\n // plain editable rects there); no nav anchors, no swallowed pointer events.\n if (!engaged || !items.length) return null;\n const visible = editEnabled ? items.filter((i) => !i.attached) : items;\n if (!visible.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {visible.map((item) => {\n const box = boxOf(item, page);\n // Real href ONLY for a chain-free sanitized external URI; blocked\n // schemes, internal targets, and chain-bearing trees (/Next after the\n // URI) activate through the plugin instead — a native navigation\n // would perform the first action and silently drop the rest.\n const chained = (item.activate?.root?.next.length ?? 0) > 0;\n const href =\n item.target.kind === 'uri' && !chained ? sanitizeExternalUri(item.target.uri) : null;\n const context: LinkActivateContext = { activate: item.activate, ref: item.ref, pon: page.pon };\n const linkSource: ActionSource | null = item.ref\n ? { kind: 'link', annotation: item.ref, pon: page.pon }\n : null;\n const notify = (event: Exclude<PdfAnnotationEventKind, 'cursorEnter' | 'cursorExit'>) => {\n if (!actions || !item.ref || !linkSource) return;\n void actions.dispatch({\n scope: 'annotation',\n event,\n ref: item.ref,\n pon: page.pon,\n source: linkSource,\n });\n };\n const native = (\n <a\n href={href ?? undefined}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n role=\"link\"\n tabIndex={0}\n title={labelOf(item)}\n aria-label={labelOf(item)}\n onClick={(e) => {\n // Modified clicks and middle-clicks on a real href keep their\n // native browser behaviour (new tab / copy link).\n if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n // A plain left-click on a real href: let the anchor be an\n // anchor — native navigation, target=_blank, status bar. Only\n // non-href targets (goto / named / blocked schemes) route\n // through the plugin, whose uri outcome the opener PERFORMS\n // (the old code preventDefault-ed AND dropped the outcome, so\n // clicking a URL link did nothing at all).\n if (href) return;\n e.preventDefault();\n openLinkTarget(link, item.target, context);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n openLinkTarget(link, item.target, context);\n }\n }}\n onPointerEnter={() => {\n if (!linkPump || !item.ref || !item.hoverEvents) return;\n linkPump.hover({\n ref: item.ref,\n pon: page.pon,\n ...(linkSource ? { source: linkSource } : {}),\n events: item.hoverEvents,\n });\n }}\n onPointerLeave={() => linkPump?.hover(null)}\n onPointerUp={() => notify('mouseUp')}\n onFocus={() => notify('focus')}\n onBlur={() => notify('blur')}\n // Keep the hub out of it: a down inside the anchor must not reach\n // the Stage's native listener (same isolation idiom as FreeText).\n onPointerDown={(e) => {\n e.stopPropagation();\n notify('mouseDown');\n }}\n style={{\n position: 'absolute',\n left: box.left,\n top: box.top,\n width: box.width,\n height: box.height,\n cursor: 'pointer',\n pointerEvents: 'auto',\n }}\n />\n );\n const out = renderLink?.({ item, nativeComponent: native }) ?? native;\n return <React.Fragment key={item.id}>{out}</React.Fragment>;\n })}\n </div>\n );\n}\n\nexport function useLink() {\n return useCapability(LinkToken);\n}\n"],"mappings":"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"}
package/dist/metadata.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./rolldown-runtime-BBjsoOtd.js";
1
2
  import { useCapability, useSelector } from "./runtime.js";
2
3
  import { MetadataToken } from "@embedpdf/plugin-metadata";
3
4
  export * from "@embedpdf/plugin-metadata";
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","names":[],"sources":["../src/metadata.ts"],"sourcesContent":["import { MetadataToken } from '@embedpdf/plugin-metadata';\nimport type { DocumentMetadata, MetadataPatch } from '@embedpdf/core';\nimport { useCapability, useSelector } from './runtime';\n\n/**\n * The document's metadata, bound to the surrounding `DocumentScope`. Reactive:\n * `metadata` updates from your own edits AND from remote (SSE) edits — the\n * plugin keeps it live off the document event stream.\n *\n * const { metadata, update } = useMetadata();\n * await update({ title: 'New title' }); // three-state patch; writes to the layer\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-metadata';\nexport function useMetadata(): {\n metadata: DocumentMetadata | null;\n update: (patch: MetadataPatch) => Promise<void>;\n canEdit: () => boolean;\n} {\n const cap = useCapability(MetadataToken);\n const metadata = useSelector(MetadataToken, (c) => c.current());\n return { metadata, update: cap.update, canEdit: cap.canEdit };\n}\n"],"mappings":";;;;AAeA,SAAgB,cAId;CACA,MAAM,MAAM,cAAc,aAAa;CAEvC,OAAO;EAAE,UADQ,YAAY,gBAAgB,MAAM,EAAE,QAAQ,CAC7C;EAAG,QAAQ,IAAI;EAAQ,SAAS,IAAI;CAAQ;AAC9D"}
1
+ {"version":3,"file":"metadata.js","names":[],"sources":["../src/metadata.ts"],"sourcesContent":["import { MetadataToken } from '@embedpdf/plugin-metadata';\nimport type { DocumentMetadata, MetadataPatch } from '@embedpdf/core';\nimport { useCapability, useSelector } from './runtime';\n\n/**\n * The document's metadata, bound to the surrounding `DocumentScope`. Reactive:\n * `metadata` updates from your own edits AND from remote (SSE) edits — the\n * plugin keeps it live off the document event stream.\n *\n * const { metadata, update } = useMetadata();\n * await update({ title: 'New title' }); // three-state patch; writes to the layer\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-metadata';\nexport function useMetadata(): {\n metadata: DocumentMetadata | null;\n update: (patch: MetadataPatch) => Promise<void>;\n canEdit: () => boolean;\n} {\n const cap = useCapability(MetadataToken);\n const metadata = useSelector(MetadataToken, (c) => c.current());\n return { metadata, update: cap.update, canEdit: cap.canEdit };\n}\n"],"mappings":";;;;;AAeA,SAAgB,cAId;CACA,MAAM,MAAM,cAAc,aAAa;CAEvC,OAAO;EAAE,UADQ,YAAY,gBAAgB,MAAM,EAAE,QAAQ,CAC7C;EAAG,QAAQ,IAAI;EAAQ,SAAS,IAAI;CAAQ;AAC9D"}
package/dist/page-edit.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./rolldown-runtime-BBjsoOtd.js";
1
2
  import { useCapability } from "./runtime.js";
2
3
  import { PageEditToken } from "@embedpdf/plugin-page-edit";
3
4
  export * from "@embedpdf/plugin-page-edit";
@@ -1 +1 @@
1
- {"version":3,"file":"page-edit.js","names":[],"sources":["../src/page-edit.ts"],"sourcesContent":["import { PageEditToken, type PageEditCapability } from '@embedpdf/plugin-page-edit';\nimport { useCapability } from './runtime';\n\n/**\n * The page-edit capability, bound to the surrounding `DocumentScope`.\n *\n * Thin idiomatic wrapper over `PageEditToken` — the relative→absolute rotation\n * and PON addressing live in the plugin, so this hook (and its Vue/Svelte/\n * Angular siblings) is pure binding sugar with no logic to drift.\n *\n * const editor = usePageEditor();\n * editor.rotateBy(page.pon, 90);\n * if (editor.canEdit()) { … }\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-page-edit';\nexport function usePageEditor(): PageEditCapability {\n return useCapability(PageEditToken);\n}\n"],"mappings":";;;;AAiBA,SAAgB,gBAAoC;CAClD,OAAO,cAAc,aAAa;AACpC"}
1
+ {"version":3,"file":"page-edit.js","names":[],"sources":["../src/page-edit.ts"],"sourcesContent":["import { PageEditToken, type PageEditCapability } from '@embedpdf/plugin-page-edit';\nimport { useCapability } from './runtime';\n\n/**\n * The page-edit capability, bound to the surrounding `DocumentScope`.\n *\n * Thin idiomatic wrapper over `PageEditToken` — the relative→absolute rotation\n * and PON addressing live in the plugin, so this hook (and its Vue/Svelte/\n * Angular siblings) is pure binding sugar with no logic to drift.\n *\n * const editor = usePageEditor();\n * editor.rotateBy(page.pon, 90);\n * if (editor.canEdit()) { … }\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-page-edit';\nexport function usePageEditor(): PageEditCapability {\n return useCapability(PageEditToken);\n}\n"],"mappings":";;;;;AAiBA,SAAgB,gBAAoC;CAClD,OAAO,cAAc,aAAa;AACpC"}
@@ -1,9 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-DDXJien1.cjs");
3
3
  const require_runtime = require("./runtime.cjs");
4
+ const require_anchored = require("./anchored.cjs");
4
5
  let react_jsx_runtime = require("react/jsx-runtime");
5
6
  let react = require("react");
6
7
  react = require_rolldown_runtime.__toESM(react, 1);
8
+ let _embedpdf_web = require("@embedpdf/web");
7
9
  let _embedpdf_core_geometry = require("@embedpdf/core-geometry");
8
10
  //#region src/page-view.tsx
9
11
  /**
@@ -12,8 +14,10 @@ let _embedpdf_core_geometry = require("@embedpdf/core-geometry");
12
14
  * Same layers + rotation + chrome frame as a `<Stage>` page, but no
13
15
  * camera/scroll/zoom and, crucially, NO dependency on `@embedpdf/plugin-stage`.
14
16
  * It builds its own `PageTransform` from a target content width and shares the
15
- * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer,
16
- * PageAnnotationMenu, …) works here identically.
17
+ * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer, …)
18
+ * works here identically — and it provides the measured `ViewProjector`, so
19
+ * anchored UI (`<AnnotationMenu>`, `<SelectionMenu>`) works here too, portalled
20
+ * and clipping-immune.
17
21
  */
18
22
  /** A single page surface with NO Stage — same layers + rotation + chrome frame,
19
23
  * no camera/scroll/zoom. */
@@ -47,13 +51,30 @@ function PageView({ page, documentId, width = 240, pageFrame = _embedpdf_core_ge
47
51
  width,
48
52
  dpr
49
53
  ]);
50
- const ctx = (0, react.useMemo)(() => require_runtime.makePageContext(docId ?? "", pon, page, pageFrame, transform, () => ref.current.getBoundingClientRect()), [
54
+ const viewId = (0, react.useId)();
55
+ const ctx = (0, react.useMemo)(() => require_runtime.makePageContext(docId ?? "", `page-view:${viewId}`, pon, page, pageFrame, transform, () => ref.current.getBoundingClientRect()), [
51
56
  docId,
52
57
  pon,
53
58
  page,
54
59
  pageFrame,
55
- transform
60
+ transform,
61
+ viewId
56
62
  ]);
63
+ const projector = (0, react.useMemo)(() => ({
64
+ space: "client",
65
+ toScreen: (p, rect) => p === ctx.pon && ref.current ? ctx.toClientRect(rect) : null,
66
+ toScreenPoint: (p, at) => p === ctx.pon && ref.current ? ctx.toClientPoint(at) : null,
67
+ viewEnv: (p) => p === ctx.pon ? {
68
+ scale: ctx.transform.viewScale,
69
+ rotation: ctx.transform.rotation,
70
+ zoom: ctx.transform.zoom
71
+ } : null
72
+ }), [ctx]);
73
+ const projectorBinding = (0, react.useMemo)(() => ({
74
+ projector,
75
+ revision: ctx,
76
+ subscribe: _embedpdf_web.observeClientGeometry
77
+ }), [projector, ctx]);
57
78
  if (!docId || !meta || !base) return null;
58
79
  const t = transform;
59
80
  const outerW = t.viewWidth + pageFrame.left + pageFrame.right;
@@ -62,41 +83,44 @@ function PageView({ page, documentId, width = 240, pageFrame = _embedpdf_core_ge
62
83
  const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;
63
84
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_runtime.DocumentScope, {
64
85
  id: docId,
65
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
66
- style: {
67
- position: "relative",
68
- width: outerW,
69
- height: outerH,
70
- ...style
71
- },
72
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_runtime.PageProvider, {
73
- value: ctx,
74
- children: [
75
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
76
- position: "absolute",
77
- left: pageFrame.left,
78
- top: pageFrame.top,
79
- width: t.viewWidth,
80
- height: t.viewHeight,
81
- boxShadow: "0 6px 18px rgba(0,0,0,.18)"
82
- } }),
83
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
84
- ref,
85
- style: {
86
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_anchored.ProjectorProvider, {
87
+ value: projectorBinding,
88
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
89
+ style: {
90
+ position: "relative",
91
+ width: outerW,
92
+ height: outerH,
93
+ ...style
94
+ },
95
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_runtime.PageProvider, {
96
+ value: ctx,
97
+ children: [
98
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
86
99
  position: "absolute",
87
- left: contentLeft,
88
- top: contentTop,
89
- width: t.contentWidth,
90
- height: t.contentHeight,
91
- background: "#fff",
92
- transform: rotation ? `rotate(${rotation}deg)` : void 0,
93
- userSelect: "none",
94
- WebkitUserSelect: "none"
95
- },
96
- children
97
- }),
98
- pageChrome
99
- ]
100
+ left: pageFrame.left,
101
+ top: pageFrame.top,
102
+ width: t.viewWidth,
103
+ height: t.viewHeight,
104
+ boxShadow: "var(--epdf-page-shadow, 0 6px 18px rgba(0,0,0,.18))"
105
+ } }),
106
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
107
+ ref,
108
+ style: {
109
+ position: "absolute",
110
+ left: contentLeft,
111
+ top: contentTop,
112
+ width: t.contentWidth,
113
+ height: t.contentHeight,
114
+ background: "#fff",
115
+ transform: rotation ? `rotate(${rotation}deg)` : void 0,
116
+ userSelect: "none",
117
+ WebkitUserSelect: "none"
118
+ },
119
+ children
120
+ }),
121
+ pageChrome
122
+ ]
123
+ })
100
124
  })
101
125
  })
102
126
  });
@@ -1 +1 @@
1
- {"version":3,"file":"page-view.cjs","names":["NO_FRAME","useKernel","useActiveDocumentId","makePageContext","DocumentScope","PageProvider"],"sources":["../src/page-view.tsx"],"sourcesContent":["/**\n * <PageView> — a single page surface with NO Stage.\n *\n * Same layers + rotation + chrome frame as a `<Stage>` page, but no\n * camera/scroll/zoom and, crucially, NO dependency on `@embedpdf/plugin-stage`.\n * It builds its own `PageTransform` from a target content width and shares the\n * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer,\n * PageAnnotationMenu, …) works here identically.\n */\nimport * as React from 'react';\nimport { useMemo, useRef } from 'react';\nimport { NO_FRAME, pageTransform, type PageFrame } from '@embedpdf/core-geometry';\nimport {\n DocumentScope,\n makePageContext,\n PageProvider,\n useActiveDocumentId,\n useKernel,\n} from './runtime';\n\nexport interface PageViewProps {\n page: number;\n /** Which document to show. Defaults to the active document. */\n documentId?: string;\n /** Target width for the page CONTENT; the display box is the rotated footprint. */\n width?: number;\n /** Reserved chrome bands around the page (screen px) — same model as `<Stage>`. */\n pageFrame?: PageFrame;\n /** Page-space content (rotates with the page). */\n children: React.ReactNode;\n /** Box-space chrome (label, border, …) — never rotated. Mirrors `<Stage pageChrome>`. */\n pageChrome?: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/** A single page surface with NO Stage — same layers + rotation + chrome frame,\n * no camera/scroll/zoom. */\nexport function PageView({\n page,\n documentId,\n width = 240,\n pageFrame = NO_FRAME,\n children,\n pageChrome,\n style,\n}: PageViewProps) {\n const kernel = useKernel();\n const active = useActiveDocumentId();\n const ref = useRef<HTMLDivElement>(null);\n const docId = documentId ?? active;\n const meta = docId ? kernel.getState().core.documents[docId] : undefined;\n const base = meta?.pages[page];\n const pon = base?.pageObjectNumber ?? page + 1;\n const rotation = base?.rotation ?? 0;\n const dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n // Standalone (no Stage/camera): build the page's transform from the target\n // content `width` directly. `scale` is view px per point = width / pageWidthPts.\n const transform = useMemo(\n () =>\n pageTransform({\n pageSize: base\n ? { width: base.size.width, height: base.size.height }\n : { width: 1, height: 1 },\n rotation,\n scale: base ? width / base.size.width : 1,\n // Physical 100% on the web: 1pt = 96/72 CSS px, times the page's\n // /UserUnit — so `transform.zoom` is meaningful even without a Stage\n // (a thumbnail-sized PageView reads as zoomed out, as it should).\n baseScale: (96 / 72) * (base?.userUnit ?? 1),\n dpr,\n }),\n [base?.size.width, base?.size.height, base?.userUnit, rotation, width, dpr],\n );\n const ctx = useMemo(\n () =>\n makePageContext(docId ?? '', pon, page, pageFrame, transform, () =>\n ref.current!.getBoundingClientRect(),\n ),\n [docId, pon, page, pageFrame, transform],\n );\n if (!docId || !meta || !base) return null;\n const t = transform;\n const outerW = t.viewWidth + pageFrame.left + pageFrame.right;\n const outerH = t.viewHeight + pageFrame.top + pageFrame.bottom;\n const contentLeft = pageFrame.left + (t.viewWidth - t.contentWidth) / 2;\n const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;\n return (\n <DocumentScope id={docId}>\n <div style={{ position: 'relative', width: outerW, height: outerH, ...style }}>\n <PageProvider value={ctx}>\n {/* drop shadow ONLY — transparent, axis-aligned, can't leak behind the bitmap */}\n <div\n style={{\n position: 'absolute',\n left: pageFrame.left,\n top: pageFrame.top,\n width: t.viewWidth,\n height: t.viewHeight,\n boxShadow: '0 6px 18px rgba(0,0,0,.18)',\n }}\n />\n {/* white backing + content as ONE box; rotation 0 carries no transform */}\n <div\n ref={ref}\n style={{\n position: 'absolute',\n left: contentLeft,\n top: contentTop,\n width: t.contentWidth,\n height: t.contentHeight,\n background: '#fff',\n transform: rotation ? `rotate(${rotation}deg)` : undefined,\n userSelect: 'none',\n WebkitUserSelect: 'none',\n }}\n >\n {children}\n </div>\n {pageChrome}\n </PageProvider>\n </div>\n </DocumentScope>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,SAAS,EACvB,MACA,YACA,QAAQ,KACR,YAAYA,wBAAAA,UACZ,UACA,YACA,SACgB;CAChB,MAAM,SAASC,gBAAAA,UAAU;CACzB,MAAM,SAASC,gBAAAA,oBAAoB;CACnC,MAAM,OAAA,GAAA,MAAA,OAAA,CAA6B,IAAI;CACvC,MAAM,QAAQ,cAAc;CAC5B,MAAM,OAAO,QAAQ,OAAO,SAAS,CAAC,CAAC,KAAK,UAAU,SAAS,KAAA;CAC/D,MAAM,OAAO,MAAM,MAAM;CACzB,MAAM,MAAM,MAAM,oBAAoB,OAAO;CAC7C,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,MAAM,OAAO,WAAW,cAAc,OAAO,oBAAoB,IAAI;CAG3E,MAAM,aAAA,GAAA,MAAA,QAAA,QAAA,GAAA,wBAAA,cAAA,CAEY;EACZ,UAAU,OACN;GAAE,OAAO,KAAK,KAAK;GAAO,QAAQ,KAAK,KAAK;EAAO,IACnD;GAAE,OAAO;GAAG,QAAQ;EAAE;EAC1B;EACA,OAAO,OAAO,QAAQ,KAAK,KAAK,QAAQ;EAIxC,WAAY,KAAK,MAAO,MAAM,YAAY;EAC1C;CACF,CAAC,GACH;EAAC,MAAM,KAAK;EAAO,MAAM,KAAK;EAAQ,MAAM;EAAU;EAAU;EAAO;CAAG,CAC5E;CACA,MAAM,OAAA,GAAA,MAAA,QAAA,OAEFC,gBAAAA,gBAAgB,SAAS,IAAI,KAAK,MAAM,WAAW,iBACjD,IAAI,QAAS,sBAAsB,CACrC,GACF;EAAC;EAAO;EAAK;EAAM;EAAW;CAAS,CACzC;CACA,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,OAAO;CACrC,MAAM,IAAI;CACV,MAAM,SAAS,EAAE,YAAY,UAAU,OAAO,UAAU;CACxD,MAAM,SAAS,EAAE,aAAa,UAAU,MAAM,UAAU;CACxD,MAAM,cAAc,UAAU,QAAQ,EAAE,YAAY,EAAE,gBAAgB;CACtE,MAAM,aAAa,UAAU,OAAO,EAAE,aAAa,EAAE,iBAAiB;CACtE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,gBAAAA,eAAD;EAAe,IAAI;EACjB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,OAAO;IAAE,UAAU;IAAY,OAAO;IAAQ,QAAQ;IAAQ,GAAG;GAAM;GAC1E,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAACC,gBAAAA,cAAD;IAAc,OAAO;IAArB,UAAA;KAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EACE,OAAO;MACL,UAAU;MACV,MAAM,UAAU;MAChB,KAAK,UAAU;MACf,OAAO,EAAE;MACT,QAAQ,EAAE;MACV,WAAW;KACb,EACD,CAAA;KAED,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MACO;MACL,OAAO;OACL,UAAU;OACV,MAAM;OACN,KAAK;OACL,OAAO,EAAE;OACT,QAAQ,EAAE;OACV,YAAY;OACZ,WAAW,WAAW,UAAU,SAAS,QAAQ,KAAA;OACjD,YAAY;OACZ,kBAAkB;MACpB;MAEC;KACE,CAAA;KACJ;IACW;;EACX,CAAA;CACQ,CAAA;AAEnB"}
1
+ {"version":3,"file":"page-view.cjs","names":["NO_FRAME","useKernel","useActiveDocumentId","makePageContext","observeClientGeometry","DocumentScope","ProjectorProvider","PageProvider"],"sources":["../src/page-view.tsx"],"sourcesContent":["/**\n * <PageView> — a single page surface with NO Stage.\n *\n * Same layers + rotation + chrome frame as a `<Stage>` page, but no\n * camera/scroll/zoom and, crucially, NO dependency on `@embedpdf/plugin-stage`.\n * It builds its own `PageTransform` from a target content width and shares the\n * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer, …)\n * works here identically — and it provides the measured `ViewProjector`, so\n * anchored UI (`<AnnotationMenu>`, `<SelectionMenu>`) works here too, portalled\n * and clipping-immune.\n */\nimport * as React from 'react';\nimport { useId, useMemo, useRef } from 'react';\nimport { NO_FRAME, pageTransform, type PageFrame } from '@embedpdf/core-geometry';\nimport { observeClientGeometry } from '@embedpdf/web';\nimport { ProjectorProvider, type ProjectorBinding, type ViewProjector } from './anchored';\nimport {\n DocumentScope,\n makePageContext,\n PageProvider,\n useActiveDocumentId,\n useKernel,\n} from './runtime';\n\nexport interface PageViewProps {\n page: number;\n /** Which document to show. Defaults to the active document. */\n documentId?: string;\n /** Target width for the page CONTENT; the display box is the rotated footprint. */\n width?: number;\n /** Reserved chrome bands around the page (screen px) — same model as `<Stage>`. */\n pageFrame?: PageFrame;\n /** Page-space content (rotates with the page). */\n children: React.ReactNode;\n /** Box-space chrome (label, border, …) — never rotated. Mirrors `<Stage pageChrome>`. */\n pageChrome?: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/** A single page surface with NO Stage — same layers + rotation + chrome frame,\n * no camera/scroll/zoom. */\nexport function PageView({\n page,\n documentId,\n width = 240,\n pageFrame = NO_FRAME,\n children,\n pageChrome,\n style,\n}: PageViewProps) {\n const kernel = useKernel();\n const active = useActiveDocumentId();\n const ref = useRef<HTMLDivElement>(null);\n const docId = documentId ?? active;\n const meta = docId ? kernel.getState().core.documents[docId] : undefined;\n const base = meta?.pages[page];\n const pon = base?.pageObjectNumber ?? page + 1;\n const rotation = base?.rotation ?? 0;\n const dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n // Standalone (no Stage/camera): build the page's transform from the target\n // content `width` directly. `scale` is view px per point = width / pageWidthPts.\n const transform = useMemo(\n () =>\n pageTransform({\n pageSize: base\n ? { width: base.size.width, height: base.size.height }\n : { width: 1, height: 1 },\n rotation,\n scale: base ? width / base.size.width : 1,\n // Physical 100% on the web: 1pt = 96/72 CSS px, times the page's\n // /UserUnit — so `transform.zoom` is meaningful even without a Stage\n // (a thumbnail-sized PageView reads as zoomed out, as it should).\n baseScale: (96 / 72) * (base?.userUnit ?? 1),\n dpr,\n }),\n [base?.size.width, base?.size.height, base?.userUnit, rotation, width, dpr],\n );\n // This instance's VIEW identity: two PageViews of the same page (a compare\n // strip) must plan rasters independently, like two stage lenses do.\n const viewId = useId();\n const ctx = useMemo(\n () =>\n makePageContext(\n docId ?? '',\n `page-view:${viewId}`,\n pon,\n page,\n pageFrame,\n transform,\n () => ref.current!.getBoundingClientRect(),\n ),\n [docId, pon, page, pageFrame, transform, viewId],\n );\n // The PageView's ViewProjector: no camera, so anchored UI positions by\n // MEASURING the DOM (client space → portal + position:fixed, immune to\n // ancestor overflow clipping). `toScreen` answers null until the page\n // element has committed — <Anchored> forces one post-commit pass to pick\n // it up. The binding's revision covers state-driven changes (a new\n // transform/page); `observeClientGeometry` covers the genuinely\n // browser-driven ones (document scroll, window resize) that no state\n // change announces.\n const projector = useMemo<ViewProjector>(\n () => ({\n space: 'client',\n toScreen: (p, rect) => (p === ctx.pon && ref.current ? ctx.toClientRect(rect) : null),\n toScreenPoint: (p, at) => (p === ctx.pon && ref.current ? ctx.toClientPoint(at) : null),\n viewEnv: (p) =>\n p === ctx.pon\n ? {\n scale: ctx.transform.viewScale,\n rotation: ctx.transform.rotation,\n zoom: ctx.transform.zoom,\n }\n : null,\n }),\n [ctx],\n );\n const projectorBinding = useMemo<ProjectorBinding>(\n () => ({ projector, revision: ctx, subscribe: observeClientGeometry }),\n [projector, ctx],\n );\n if (!docId || !meta || !base) return null;\n const t = transform;\n const outerW = t.viewWidth + pageFrame.left + pageFrame.right;\n const outerH = t.viewHeight + pageFrame.top + pageFrame.bottom;\n const contentLeft = pageFrame.left + (t.viewWidth - t.contentWidth) / 2;\n const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;\n return (\n <DocumentScope id={docId}>\n <ProjectorProvider value={projectorBinding}>\n <div style={{ position: 'relative', width: outerW, height: outerH, ...style }}>\n <PageProvider value={ctx}>\n {/* drop shadow ONLY — transparent, axis-aligned, can't leak behind the bitmap */}\n <div\n style={{\n position: 'absolute',\n left: pageFrame.left,\n top: pageFrame.top,\n width: t.viewWidth,\n height: t.viewHeight,\n boxShadow: 'var(--epdf-page-shadow, 0 6px 18px rgba(0,0,0,.18))',\n }}\n />\n {/* white backing + content as ONE box; rotation 0 carries no transform */}\n <div\n ref={ref}\n style={{\n position: 'absolute',\n left: contentLeft,\n top: contentTop,\n width: t.contentWidth,\n height: t.contentHeight,\n background: '#fff',\n transform: rotation ? `rotate(${rotation}deg)` : undefined,\n userSelect: 'none',\n WebkitUserSelect: 'none',\n }}\n >\n {children}\n </div>\n {pageChrome}\n </PageProvider>\n </div>\n </ProjectorProvider>\n </DocumentScope>\n );\n}\n"],"mappings":"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"}
package/dist/page-view.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { DocumentScope, PageProvider, makePageContext, useActiveDocumentId, useKernel } from "./runtime.js";
2
+ import { ProjectorProvider } from "./anchored.js";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useMemo, useRef } from "react";
4
+ import { useId, useMemo, useRef } from "react";
5
+ import { observeClientGeometry } from "@embedpdf/web";
4
6
  import { NO_FRAME, pageTransform } from "@embedpdf/core-geometry";
5
7
  //#region src/page-view.tsx
6
8
  /** A single page surface with NO Stage — same layers + rotation + chrome frame,
@@ -35,13 +37,30 @@ function PageView({ page, documentId, width = 240, pageFrame = NO_FRAME, childre
35
37
  width,
36
38
  dpr
37
39
  ]);
38
- const ctx = useMemo(() => makePageContext(docId ?? "", pon, page, pageFrame, transform, () => ref.current.getBoundingClientRect()), [
40
+ const viewId = useId();
41
+ const ctx = useMemo(() => makePageContext(docId ?? "", `page-view:${viewId}`, pon, page, pageFrame, transform, () => ref.current.getBoundingClientRect()), [
39
42
  docId,
40
43
  pon,
41
44
  page,
42
45
  pageFrame,
43
- transform
46
+ transform,
47
+ viewId
44
48
  ]);
49
+ const projector = useMemo(() => ({
50
+ space: "client",
51
+ toScreen: (p, rect) => p === ctx.pon && ref.current ? ctx.toClientRect(rect) : null,
52
+ toScreenPoint: (p, at) => p === ctx.pon && ref.current ? ctx.toClientPoint(at) : null,
53
+ viewEnv: (p) => p === ctx.pon ? {
54
+ scale: ctx.transform.viewScale,
55
+ rotation: ctx.transform.rotation,
56
+ zoom: ctx.transform.zoom
57
+ } : null
58
+ }), [ctx]);
59
+ const projectorBinding = useMemo(() => ({
60
+ projector,
61
+ revision: ctx,
62
+ subscribe: observeClientGeometry
63
+ }), [projector, ctx]);
45
64
  if (!docId || !meta || !base) return null;
46
65
  const t = transform;
47
66
  const outerW = t.viewWidth + pageFrame.left + pageFrame.right;
@@ -50,41 +69,44 @@ function PageView({ page, documentId, width = 240, pageFrame = NO_FRAME, childre
50
69
  const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;
51
70
  return /* @__PURE__ */ jsx(DocumentScope, {
52
71
  id: docId,
53
- children: /* @__PURE__ */ jsx("div", {
54
- style: {
55
- position: "relative",
56
- width: outerW,
57
- height: outerH,
58
- ...style
59
- },
60
- children: /* @__PURE__ */ jsxs(PageProvider, {
61
- value: ctx,
62
- children: [
63
- /* @__PURE__ */ jsx("div", { style: {
64
- position: "absolute",
65
- left: pageFrame.left,
66
- top: pageFrame.top,
67
- width: t.viewWidth,
68
- height: t.viewHeight,
69
- boxShadow: "0 6px 18px rgba(0,0,0,.18)"
70
- } }),
71
- /* @__PURE__ */ jsx("div", {
72
- ref,
73
- style: {
72
+ children: /* @__PURE__ */ jsx(ProjectorProvider, {
73
+ value: projectorBinding,
74
+ children: /* @__PURE__ */ jsx("div", {
75
+ style: {
76
+ position: "relative",
77
+ width: outerW,
78
+ height: outerH,
79
+ ...style
80
+ },
81
+ children: /* @__PURE__ */ jsxs(PageProvider, {
82
+ value: ctx,
83
+ children: [
84
+ /* @__PURE__ */ jsx("div", { style: {
74
85
  position: "absolute",
75
- left: contentLeft,
76
- top: contentTop,
77
- width: t.contentWidth,
78
- height: t.contentHeight,
79
- background: "#fff",
80
- transform: rotation ? `rotate(${rotation}deg)` : void 0,
81
- userSelect: "none",
82
- WebkitUserSelect: "none"
83
- },
84
- children
85
- }),
86
- pageChrome
87
- ]
86
+ left: pageFrame.left,
87
+ top: pageFrame.top,
88
+ width: t.viewWidth,
89
+ height: t.viewHeight,
90
+ boxShadow: "var(--epdf-page-shadow, 0 6px 18px rgba(0,0,0,.18))"
91
+ } }),
92
+ /* @__PURE__ */ jsx("div", {
93
+ ref,
94
+ style: {
95
+ position: "absolute",
96
+ left: contentLeft,
97
+ top: contentTop,
98
+ width: t.contentWidth,
99
+ height: t.contentHeight,
100
+ background: "#fff",
101
+ transform: rotation ? `rotate(${rotation}deg)` : void 0,
102
+ userSelect: "none",
103
+ WebkitUserSelect: "none"
104
+ },
105
+ children
106
+ }),
107
+ pageChrome
108
+ ]
109
+ })
88
110
  })
89
111
  })
90
112
  });
@@ -1 +1 @@
1
- {"version":3,"file":"page-view.js","names":[],"sources":["../src/page-view.tsx"],"sourcesContent":["/**\n * <PageView> — a single page surface with NO Stage.\n *\n * Same layers + rotation + chrome frame as a `<Stage>` page, but no\n * camera/scroll/zoom and, crucially, NO dependency on `@embedpdf/plugin-stage`.\n * It builds its own `PageTransform` from a target content width and shares the\n * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer,\n * PageAnnotationMenu, …) works here identically.\n */\nimport * as React from 'react';\nimport { useMemo, useRef } from 'react';\nimport { NO_FRAME, pageTransform, type PageFrame } from '@embedpdf/core-geometry';\nimport {\n DocumentScope,\n makePageContext,\n PageProvider,\n useActiveDocumentId,\n useKernel,\n} from './runtime';\n\nexport interface PageViewProps {\n page: number;\n /** Which document to show. Defaults to the active document. */\n documentId?: string;\n /** Target width for the page CONTENT; the display box is the rotated footprint. */\n width?: number;\n /** Reserved chrome bands around the page (screen px) — same model as `<Stage>`. */\n pageFrame?: PageFrame;\n /** Page-space content (rotates with the page). */\n children: React.ReactNode;\n /** Box-space chrome (label, border, …) — never rotated. Mirrors `<Stage pageChrome>`. */\n pageChrome?: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/** A single page surface with NO Stage — same layers + rotation + chrome frame,\n * no camera/scroll/zoom. */\nexport function PageView({\n page,\n documentId,\n width = 240,\n pageFrame = NO_FRAME,\n children,\n pageChrome,\n style,\n}: PageViewProps) {\n const kernel = useKernel();\n const active = useActiveDocumentId();\n const ref = useRef<HTMLDivElement>(null);\n const docId = documentId ?? active;\n const meta = docId ? kernel.getState().core.documents[docId] : undefined;\n const base = meta?.pages[page];\n const pon = base?.pageObjectNumber ?? page + 1;\n const rotation = base?.rotation ?? 0;\n const dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n // Standalone (no Stage/camera): build the page's transform from the target\n // content `width` directly. `scale` is view px per point = width / pageWidthPts.\n const transform = useMemo(\n () =>\n pageTransform({\n pageSize: base\n ? { width: base.size.width, height: base.size.height }\n : { width: 1, height: 1 },\n rotation,\n scale: base ? width / base.size.width : 1,\n // Physical 100% on the web: 1pt = 96/72 CSS px, times the page's\n // /UserUnit — so `transform.zoom` is meaningful even without a Stage\n // (a thumbnail-sized PageView reads as zoomed out, as it should).\n baseScale: (96 / 72) * (base?.userUnit ?? 1),\n dpr,\n }),\n [base?.size.width, base?.size.height, base?.userUnit, rotation, width, dpr],\n );\n const ctx = useMemo(\n () =>\n makePageContext(docId ?? '', pon, page, pageFrame, transform, () =>\n ref.current!.getBoundingClientRect(),\n ),\n [docId, pon, page, pageFrame, transform],\n );\n if (!docId || !meta || !base) return null;\n const t = transform;\n const outerW = t.viewWidth + pageFrame.left + pageFrame.right;\n const outerH = t.viewHeight + pageFrame.top + pageFrame.bottom;\n const contentLeft = pageFrame.left + (t.viewWidth - t.contentWidth) / 2;\n const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;\n return (\n <DocumentScope id={docId}>\n <div style={{ position: 'relative', width: outerW, height: outerH, ...style }}>\n <PageProvider value={ctx}>\n {/* drop shadow ONLY — transparent, axis-aligned, can't leak behind the bitmap */}\n <div\n style={{\n position: 'absolute',\n left: pageFrame.left,\n top: pageFrame.top,\n width: t.viewWidth,\n height: t.viewHeight,\n boxShadow: '0 6px 18px rgba(0,0,0,.18)',\n }}\n />\n {/* white backing + content as ONE box; rotation 0 carries no transform */}\n <div\n ref={ref}\n style={{\n position: 'absolute',\n left: contentLeft,\n top: contentTop,\n width: t.contentWidth,\n height: t.contentHeight,\n background: '#fff',\n transform: rotation ? `rotate(${rotation}deg)` : undefined,\n userSelect: 'none',\n WebkitUserSelect: 'none',\n }}\n >\n {children}\n </div>\n {pageChrome}\n </PageProvider>\n </div>\n </DocumentScope>\n );\n}\n"],"mappings":";;;;;;;AAqCA,SAAgB,SAAS,EACvB,MACA,YACA,QAAQ,KACR,YAAY,UACZ,UACA,YACA,SACgB;CAChB,MAAM,SAAS,UAAU;CACzB,MAAM,SAAS,oBAAoB;CACnC,MAAM,MAAM,OAAuB,IAAI;CACvC,MAAM,QAAQ,cAAc;CAC5B,MAAM,OAAO,QAAQ,OAAO,SAAS,CAAC,CAAC,KAAK,UAAU,SAAS,KAAA;CAC/D,MAAM,OAAO,MAAM,MAAM;CACzB,MAAM,MAAM,MAAM,oBAAoB,OAAO;CAC7C,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,MAAM,OAAO,WAAW,cAAc,OAAO,oBAAoB,IAAI;CAG3E,MAAM,YAAY,cAEd,cAAc;EACZ,UAAU,OACN;GAAE,OAAO,KAAK,KAAK;GAAO,QAAQ,KAAK,KAAK;EAAO,IACnD;GAAE,OAAO;GAAG,QAAQ;EAAE;EAC1B;EACA,OAAO,OAAO,QAAQ,KAAK,KAAK,QAAQ;EAIxC,WAAY,KAAK,MAAO,MAAM,YAAY;EAC1C;CACF,CAAC,GACH;EAAC,MAAM,KAAK;EAAO,MAAM,KAAK;EAAQ,MAAM;EAAU;EAAU;EAAO;CAAG,CAC5E;CACA,MAAM,MAAM,cAER,gBAAgB,SAAS,IAAI,KAAK,MAAM,WAAW,iBACjD,IAAI,QAAS,sBAAsB,CACrC,GACF;EAAC;EAAO;EAAK;EAAM;EAAW;CAAS,CACzC;CACA,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,OAAO;CACrC,MAAM,IAAI;CACV,MAAM,SAAS,EAAE,YAAY,UAAU,OAAO,UAAU;CACxD,MAAM,SAAS,EAAE,aAAa,UAAU,MAAM,UAAU;CACxD,MAAM,cAAc,UAAU,QAAQ,EAAE,YAAY,EAAE,gBAAgB;CACtE,MAAM,aAAa,UAAU,OAAO,EAAE,aAAa,EAAE,iBAAiB;CACtE,OACE,oBAAC,eAAD;EAAe,IAAI;EACjB,UAAA,oBAAC,OAAD;GAAK,OAAO;IAAE,UAAU;IAAY,OAAO;IAAQ,QAAQ;IAAQ,GAAG;GAAM;GAC1E,UAAA,qBAAC,cAAD;IAAc,OAAO;IAArB,UAAA;KAEE,oBAAC,OAAD,EACE,OAAO;MACL,UAAU;MACV,MAAM,UAAU;MAChB,KAAK,UAAU;MACf,OAAO,EAAE;MACT,QAAQ,EAAE;MACV,WAAW;KACb,EACD,CAAA;KAED,oBAAC,OAAD;MACO;MACL,OAAO;OACL,UAAU;OACV,MAAM;OACN,KAAK;OACL,OAAO,EAAE;OACT,QAAQ,EAAE;OACV,YAAY;OACZ,WAAW,WAAW,UAAU,SAAS,QAAQ,KAAA;OACjD,YAAY;OACZ,kBAAkB;MACpB;MAEC;KACE,CAAA;KACJ;IACW;;EACX,CAAA;CACQ,CAAA;AAEnB"}
1
+ {"version":3,"file":"page-view.js","names":[],"sources":["../src/page-view.tsx"],"sourcesContent":["/**\n * <PageView> — a single page surface with NO Stage.\n *\n * Same layers + rotation + chrome frame as a `<Stage>` page, but no\n * camera/scroll/zoom and, crucially, NO dependency on `@embedpdf/plugin-stage`.\n * It builds its own `PageTransform` from a target content width and shares the\n * exact `PageContext` seam, so every layer (RenderLayer, AnnotationLayer, …)\n * works here identically — and it provides the measured `ViewProjector`, so\n * anchored UI (`<AnnotationMenu>`, `<SelectionMenu>`) works here too, portalled\n * and clipping-immune.\n */\nimport * as React from 'react';\nimport { useId, useMemo, useRef } from 'react';\nimport { NO_FRAME, pageTransform, type PageFrame } from '@embedpdf/core-geometry';\nimport { observeClientGeometry } from '@embedpdf/web';\nimport { ProjectorProvider, type ProjectorBinding, type ViewProjector } from './anchored';\nimport {\n DocumentScope,\n makePageContext,\n PageProvider,\n useActiveDocumentId,\n useKernel,\n} from './runtime';\n\nexport interface PageViewProps {\n page: number;\n /** Which document to show. Defaults to the active document. */\n documentId?: string;\n /** Target width for the page CONTENT; the display box is the rotated footprint. */\n width?: number;\n /** Reserved chrome bands around the page (screen px) — same model as `<Stage>`. */\n pageFrame?: PageFrame;\n /** Page-space content (rotates with the page). */\n children: React.ReactNode;\n /** Box-space chrome (label, border, …) — never rotated. Mirrors `<Stage pageChrome>`. */\n pageChrome?: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/** A single page surface with NO Stage — same layers + rotation + chrome frame,\n * no camera/scroll/zoom. */\nexport function PageView({\n page,\n documentId,\n width = 240,\n pageFrame = NO_FRAME,\n children,\n pageChrome,\n style,\n}: PageViewProps) {\n const kernel = useKernel();\n const active = useActiveDocumentId();\n const ref = useRef<HTMLDivElement>(null);\n const docId = documentId ?? active;\n const meta = docId ? kernel.getState().core.documents[docId] : undefined;\n const base = meta?.pages[page];\n const pon = base?.pageObjectNumber ?? page + 1;\n const rotation = base?.rotation ?? 0;\n const dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n // Standalone (no Stage/camera): build the page's transform from the target\n // content `width` directly. `scale` is view px per point = width / pageWidthPts.\n const transform = useMemo(\n () =>\n pageTransform({\n pageSize: base\n ? { width: base.size.width, height: base.size.height }\n : { width: 1, height: 1 },\n rotation,\n scale: base ? width / base.size.width : 1,\n // Physical 100% on the web: 1pt = 96/72 CSS px, times the page's\n // /UserUnit — so `transform.zoom` is meaningful even without a Stage\n // (a thumbnail-sized PageView reads as zoomed out, as it should).\n baseScale: (96 / 72) * (base?.userUnit ?? 1),\n dpr,\n }),\n [base?.size.width, base?.size.height, base?.userUnit, rotation, width, dpr],\n );\n // This instance's VIEW identity: two PageViews of the same page (a compare\n // strip) must plan rasters independently, like two stage lenses do.\n const viewId = useId();\n const ctx = useMemo(\n () =>\n makePageContext(\n docId ?? '',\n `page-view:${viewId}`,\n pon,\n page,\n pageFrame,\n transform,\n () => ref.current!.getBoundingClientRect(),\n ),\n [docId, pon, page, pageFrame, transform, viewId],\n );\n // The PageView's ViewProjector: no camera, so anchored UI positions by\n // MEASURING the DOM (client space → portal + position:fixed, immune to\n // ancestor overflow clipping). `toScreen` answers null until the page\n // element has committed — <Anchored> forces one post-commit pass to pick\n // it up. The binding's revision covers state-driven changes (a new\n // transform/page); `observeClientGeometry` covers the genuinely\n // browser-driven ones (document scroll, window resize) that no state\n // change announces.\n const projector = useMemo<ViewProjector>(\n () => ({\n space: 'client',\n toScreen: (p, rect) => (p === ctx.pon && ref.current ? ctx.toClientRect(rect) : null),\n toScreenPoint: (p, at) => (p === ctx.pon && ref.current ? ctx.toClientPoint(at) : null),\n viewEnv: (p) =>\n p === ctx.pon\n ? {\n scale: ctx.transform.viewScale,\n rotation: ctx.transform.rotation,\n zoom: ctx.transform.zoom,\n }\n : null,\n }),\n [ctx],\n );\n const projectorBinding = useMemo<ProjectorBinding>(\n () => ({ projector, revision: ctx, subscribe: observeClientGeometry }),\n [projector, ctx],\n );\n if (!docId || !meta || !base) return null;\n const t = transform;\n const outerW = t.viewWidth + pageFrame.left + pageFrame.right;\n const outerH = t.viewHeight + pageFrame.top + pageFrame.bottom;\n const contentLeft = pageFrame.left + (t.viewWidth - t.contentWidth) / 2;\n const contentTop = pageFrame.top + (t.viewHeight - t.contentHeight) / 2;\n return (\n <DocumentScope id={docId}>\n <ProjectorProvider value={projectorBinding}>\n <div style={{ position: 'relative', width: outerW, height: outerH, ...style }}>\n <PageProvider value={ctx}>\n {/* drop shadow ONLY — transparent, axis-aligned, can't leak behind the bitmap */}\n <div\n style={{\n position: 'absolute',\n left: pageFrame.left,\n top: pageFrame.top,\n width: t.viewWidth,\n height: t.viewHeight,\n boxShadow: 'var(--epdf-page-shadow, 0 6px 18px rgba(0,0,0,.18))',\n }}\n />\n {/* white backing + content as ONE box; rotation 0 carries no transform */}\n <div\n ref={ref}\n style={{\n position: 'absolute',\n left: contentLeft,\n top: contentTop,\n width: t.contentWidth,\n height: t.contentHeight,\n background: '#fff',\n transform: rotation ? `rotate(${rotation}deg)` : undefined,\n userSelect: 'none',\n WebkitUserSelect: 'none',\n }}\n >\n {children}\n </div>\n {pageChrome}\n </PageProvider>\n </div>\n </ProjectorProvider>\n </DocumentScope>\n );\n}\n"],"mappings":";;;;;;;;;AAyCA,SAAgB,SAAS,EACvB,MACA,YACA,QAAQ,KACR,YAAY,UACZ,UACA,YACA,SACgB;CAChB,MAAM,SAAS,UAAU;CACzB,MAAM,SAAS,oBAAoB;CACnC,MAAM,MAAM,OAAuB,IAAI;CACvC,MAAM,QAAQ,cAAc;CAC5B,MAAM,OAAO,QAAQ,OAAO,SAAS,CAAC,CAAC,KAAK,UAAU,SAAS,KAAA;CAC/D,MAAM,OAAO,MAAM,MAAM;CACzB,MAAM,MAAM,MAAM,oBAAoB,OAAO;CAC7C,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,MAAM,OAAO,WAAW,cAAc,OAAO,oBAAoB,IAAI;CAG3E,MAAM,YAAY,cAEd,cAAc;EACZ,UAAU,OACN;GAAE,OAAO,KAAK,KAAK;GAAO,QAAQ,KAAK,KAAK;EAAO,IACnD;GAAE,OAAO;GAAG,QAAQ;EAAE;EAC1B;EACA,OAAO,OAAO,QAAQ,KAAK,KAAK,QAAQ;EAIxC,WAAY,KAAK,MAAO,MAAM,YAAY;EAC1C;CACF,CAAC,GACH;EAAC,MAAM,KAAK;EAAO,MAAM,KAAK;EAAQ,MAAM;EAAU;EAAU;EAAO;CAAG,CAC5E;CAGA,MAAM,SAAS,MAAM;CACrB,MAAM,MAAM,cAER,gBACE,SAAS,IACT,aAAa,UACb,KACA,MACA,WACA,iBACM,IAAI,QAAS,sBAAsB,CAC3C,GACF;EAAC;EAAO;EAAK;EAAM;EAAW;EAAW;CAAM,CACjD;CASA,MAAM,YAAY,eACT;EACL,OAAO;EACP,WAAW,GAAG,SAAU,MAAM,IAAI,OAAO,IAAI,UAAU,IAAI,aAAa,IAAI,IAAI;EAChF,gBAAgB,GAAG,OAAQ,MAAM,IAAI,OAAO,IAAI,UAAU,IAAI,cAAc,EAAE,IAAI;EAClF,UAAU,MACR,MAAM,IAAI,MACN;GACE,OAAO,IAAI,UAAU;GACrB,UAAU,IAAI,UAAU;GACxB,MAAM,IAAI,UAAU;EACtB,IACA;CACR,IACA,CAAC,GAAG,CACN;CACA,MAAM,mBAAmB,eAChB;EAAE;EAAW,UAAU;EAAK,WAAW;CAAsB,IACpE,CAAC,WAAW,GAAG,CACjB;CACA,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,OAAO;CACrC,MAAM,IAAI;CACV,MAAM,SAAS,EAAE,YAAY,UAAU,OAAO,UAAU;CACxD,MAAM,SAAS,EAAE,aAAa,UAAU,MAAM,UAAU;CACxD,MAAM,cAAc,UAAU,QAAQ,EAAE,YAAY,EAAE,gBAAgB;CACtE,MAAM,aAAa,UAAU,OAAO,EAAE,aAAa,EAAE,iBAAiB;CACtE,OACE,oBAAC,eAAD;EAAe,IAAI;EACjB,UAAA,oBAAC,mBAAD;GAAmB,OAAO;GAC1B,UAAA,oBAAC,OAAD;IAAK,OAAO;KAAE,UAAU;KAAY,OAAO;KAAQ,QAAQ;KAAQ,GAAG;IAAM;IAC1E,UAAA,qBAAC,cAAD;KAAc,OAAO;KAArB,UAAA;MAEE,oBAAC,OAAD,EACE,OAAO;OACL,UAAU;OACV,MAAM,UAAU;OAChB,KAAK,UAAU;OACf,OAAO,EAAE;OACT,QAAQ,EAAE;OACV,WAAW;MACb,EACD,CAAA;MAED,oBAAC,OAAD;OACO;OACL,OAAO;QACL,UAAU;QACV,MAAM;QACN,KAAK;QACL,OAAO,EAAE;QACT,QAAQ,EAAE;QACV,YAAY;QACZ,WAAW,WAAW,UAAU,SAAS,QAAQ,KAAA;QACjD,YAAY;QACZ,kBAAkB;OACpB;OAEC;MACE,CAAA;MACJ;KACW;;GACX,CAAA;EACc,CAAA;CACN,CAAA;AAEnB"}
package/dist/redaction.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./rolldown-runtime-BBjsoOtd.js";
1
2
  import { useCapability, useSelector } from "./runtime.js";
2
3
  import { RedactionToken } from "@embedpdf/plugin-redaction";
3
4
  export * from "@embedpdf/plugin-redaction";