@embedpdf/react 3.0.0-next.14 → 3.0.0-next.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/dist/AnnotationList-CkijRHet-HEFNUIZe.d.cts +877 -0
  2. package/dist/AnnotationList-CkijRHet-HEFNUIZe.d.ts +877 -0
  3. package/dist/actions.cjs +25 -5
  4. package/dist/actions.cjs.map +1 -1
  5. package/dist/actions.d.cts +18 -5
  6. package/dist/actions.d.ts +18 -5
  7. package/dist/actions.js +22 -6
  8. package/dist/actions.js.map +1 -1
  9. package/dist/anchored-DeX95xSd.d.ts +85 -0
  10. package/dist/anchored-DzN3JywS.d.cts +85 -0
  11. package/dist/anchored.cjs +71 -28
  12. package/dist/anchored.cjs.map +1 -1
  13. package/dist/anchored.d.cts +2 -45
  14. package/dist/anchored.d.ts +2 -45
  15. package/dist/anchored.js +56 -19
  16. package/dist/anchored.js.map +1 -1
  17. package/dist/annotation-B48UT2ln.d.ts +302 -0
  18. package/dist/annotation-C1ttM8Wj.js +708 -0
  19. package/dist/annotation-C1ttM8Wj.js.map +1 -0
  20. package/dist/annotation-C9dVwo9b.d.cts +302 -0
  21. package/dist/annotation-Dex5EBda.cjs +830 -0
  22. package/dist/annotation-Dex5EBda.cjs.map +1 -0
  23. package/dist/annotation.cjs +20 -784
  24. package/dist/annotation.d.cts +2 -2
  25. package/dist/annotation.d.ts +2 -2
  26. package/dist/annotation.js +2 -769
  27. package/dist/commands.cjs +68 -28
  28. package/dist/commands.cjs.map +1 -1
  29. package/dist/commands.d.cts +37 -10
  30. package/dist/commands.d.ts +37 -10
  31. package/dist/commands.js +68 -31
  32. package/dist/commands.js.map +1 -1
  33. package/dist/form-55izw0jS.js +511 -0
  34. package/dist/form-55izw0jS.js.map +1 -0
  35. package/dist/form-BNqQfGGH.cjs +548 -0
  36. package/dist/form-BNqQfGGH.cjs.map +1 -0
  37. package/dist/form.cjs +5 -5
  38. package/dist/form.d.cts +41 -2
  39. package/dist/form.d.ts +41 -2
  40. package/dist/form.js +2 -3
  41. package/dist/history.cjs +38 -0
  42. package/dist/history.cjs.map +1 -0
  43. package/dist/history.d.cts +27 -0
  44. package/dist/history.d.ts +27 -0
  45. package/dist/history.js +27 -0
  46. package/dist/history.js.map +1 -0
  47. package/dist/i18n.cjs +26 -30
  48. package/dist/i18n.cjs.map +1 -1
  49. package/dist/i18n.d.cts +24 -21
  50. package/dist/i18n.d.ts +24 -21
  51. package/dist/i18n.js +24 -31
  52. package/dist/i18n.js.map +1 -1
  53. package/dist/index.cjs +200 -57
  54. package/dist/index.d.cts +31 -32
  55. package/dist/index.d.ts +31 -32
  56. package/dist/index.js +32 -30
  57. package/dist/inert-CmBEbKCn.cjs +19 -0
  58. package/dist/inert-CmBEbKCn.cjs.map +1 -0
  59. package/dist/inert-D8fkennb.js +14 -0
  60. package/dist/inert-D8fkennb.js.map +1 -0
  61. package/dist/interaction.cjs +48 -102
  62. package/dist/interaction.cjs.map +1 -1
  63. package/dist/interaction.d.cts +23 -32
  64. package/dist/interaction.d.ts +23 -32
  65. package/dist/interaction.js +33 -102
  66. package/dist/interaction.js.map +1 -1
  67. package/dist/link.cjs +65 -104
  68. package/dist/link.cjs.map +1 -1
  69. package/dist/link.d.cts +21 -16
  70. package/dist/link.d.ts +22 -17
  71. package/dist/link.js +67 -107
  72. package/dist/link.js.map +1 -1
  73. package/dist/measurement.cjs +36 -11
  74. package/dist/measurement.cjs.map +1 -1
  75. package/dist/measurement.d.cts +33 -7
  76. package/dist/measurement.d.ts +33 -7
  77. package/dist/measurement.js +35 -14
  78. package/dist/measurement.js.map +1 -1
  79. package/dist/metadata.cjs +20 -7
  80. package/dist/metadata.cjs.map +1 -1
  81. package/dist/metadata.d.cts +22 -7
  82. package/dist/metadata.d.ts +22 -7
  83. package/dist/metadata.js +20 -10
  84. package/dist/metadata.js.map +1 -1
  85. package/dist/page-edit.cjs +7 -3
  86. package/dist/page-edit.cjs.map +1 -1
  87. package/dist/page-edit.d.cts +6 -2
  88. package/dist/page-edit.d.ts +6 -2
  89. package/dist/page-edit.js +7 -4
  90. package/dist/page-edit.js.map +1 -1
  91. package/dist/page-layers-Bkaaz8Zf.js +26 -0
  92. package/dist/page-layers-Bkaaz8Zf.js.map +1 -0
  93. package/dist/page-layers-BloZDoOV.cjs +37 -0
  94. package/dist/page-layers-BloZDoOV.cjs.map +1 -0
  95. package/dist/page-view.cjs +89 -82
  96. package/dist/page-view.cjs.map +1 -1
  97. package/dist/page-view.d.cts +14 -7
  98. package/dist/page-view.d.ts +18 -11
  99. package/dist/page-view.js +86 -81
  100. package/dist/page-view.js.map +1 -1
  101. package/dist/redaction.cjs +30 -15
  102. package/dist/redaction.cjs.map +1 -1
  103. package/dist/redaction.d.cts +27 -9
  104. package/dist/redaction.d.ts +27 -9
  105. package/dist/redaction.js +29 -18
  106. package/dist/redaction.js.map +1 -1
  107. package/dist/render.cjs +71 -46
  108. package/dist/render.cjs.map +1 -1
  109. package/dist/render.d.cts +17 -5
  110. package/dist/render.d.ts +17 -5
  111. package/dist/render.js +70 -49
  112. package/dist/render.js.map +1 -1
  113. package/dist/runtime-B6xcPsEb.js +398 -0
  114. package/dist/runtime-B6xcPsEb.js.map +1 -0
  115. package/dist/runtime-DBEBlpQV.d.cts +237 -0
  116. package/dist/runtime-V3MVMb91.d.ts +237 -0
  117. package/dist/runtime-fzpGv78v.cjs +555 -0
  118. package/dist/runtime-fzpGv78v.cjs.map +1 -0
  119. package/dist/runtime.cjs +45 -324
  120. package/dist/runtime.d.cts +2 -2
  121. package/dist/runtime.d.ts +2 -2
  122. package/dist/runtime.js +2 -306
  123. package/dist/search.cjs +81 -50
  124. package/dist/search.cjs.map +1 -1
  125. package/dist/search.d.cts +37 -24
  126. package/dist/search.d.ts +37 -24
  127. package/dist/search.js +81 -53
  128. package/dist/search.js.map +1 -1
  129. package/dist/selection.cjs +105 -108
  130. package/dist/selection.cjs.map +1 -1
  131. package/dist/selection.d.cts +54 -26
  132. package/dist/selection.d.ts +56 -28
  133. package/dist/selection.js +103 -110
  134. package/dist/selection.js.map +1 -1
  135. package/dist/shell.cjs +36 -21
  136. package/dist/shell.cjs.map +1 -1
  137. package/dist/shell.d.cts +32 -17
  138. package/dist/shell.d.ts +32 -17
  139. package/dist/shell.js +36 -24
  140. package/dist/shell.js.map +1 -1
  141. package/dist/signature.cjs +29 -48
  142. package/dist/signature.cjs.map +1 -1
  143. package/dist/signature.d.cts +26 -26
  144. package/dist/signature.d.ts +26 -26
  145. package/dist/signature.js +30 -48
  146. package/dist/signature.js.map +1 -1
  147. package/dist/stage-BIG6aeVd.cjs +369 -0
  148. package/dist/stage-BIG6aeVd.cjs.map +1 -0
  149. package/dist/stage-ByFPD-Fv.d.cts +117 -0
  150. package/dist/stage-DaboaheR.d.ts +117 -0
  151. package/dist/stage-DoVekb83.js +302 -0
  152. package/dist/stage-DoVekb83.js.map +1 -0
  153. package/dist/stage-scope-CQgCuf1w.cjs +46 -0
  154. package/dist/stage-scope-CQgCuf1w.cjs.map +1 -0
  155. package/dist/stage-scope-D7ZeNduT.js +23 -0
  156. package/dist/stage-scope-D7ZeNduT.js.map +1 -0
  157. package/dist/stage.cjs +12 -235
  158. package/dist/stage.d.cts +2 -116
  159. package/dist/stage.d.ts +2 -116
  160. package/dist/stage.js +3 -228
  161. package/dist/stamp.cjs +41 -35
  162. package/dist/stamp.cjs.map +1 -1
  163. package/dist/stamp.d.cts +25 -18
  164. package/dist/stamp.d.ts +25 -18
  165. package/dist/stamp.js +40 -37
  166. package/dist/stamp.js.map +1 -1
  167. package/dist/state-0K1I5cM4.d.cts +29 -0
  168. package/dist/state-0K1I5cM4.d.ts +29 -0
  169. package/dist/state-CbgxhwLA.js +62 -0
  170. package/dist/state-CbgxhwLA.js.map +1 -0
  171. package/dist/state-CsfZy_Eq.cjs +73 -0
  172. package/dist/state-CsfZy_Eq.cjs.map +1 -0
  173. package/dist/svg-shapes-Dm1yTR1b.js +40 -0
  174. package/dist/svg-shapes-Dm1yTR1b.js.map +1 -0
  175. package/dist/svg-shapes-zo0GNkc9.cjs +53 -0
  176. package/dist/svg-shapes-zo0GNkc9.cjs.map +1 -0
  177. package/dist/toolbar.cjs +297 -295
  178. package/dist/toolbar.cjs.map +1 -1
  179. package/dist/toolbar.d.cts +58 -68
  180. package/dist/toolbar.d.ts +67 -77
  181. package/dist/toolbar.js +271 -293
  182. package/dist/toolbar.js.map +1 -1
  183. package/dist/view-manager.cjs +34 -0
  184. package/dist/view-manager.cjs.map +1 -0
  185. package/dist/view-manager.d.cts +21 -0
  186. package/dist/view-manager.d.ts +21 -0
  187. package/dist/view-manager.js +23 -0
  188. package/dist/view-manager.js.map +1 -0
  189. package/package.json +37 -39
  190. package/dist/annotation-BCED_p9H.d.cts +0 -160
  191. package/dist/annotation-anchors-CetwM1g7.js +0 -15
  192. package/dist/annotation-anchors-CetwM1g7.js.map +0 -1
  193. package/dist/annotation-anchors-DuYRBJLl.cjs +0 -26
  194. package/dist/annotation-anchors-DuYRBJLl.cjs.map +0 -1
  195. package/dist/annotation-hooks-BB5ZhPpf.cjs +0 -16
  196. package/dist/annotation-hooks-BB5ZhPpf.cjs.map +0 -1
  197. package/dist/annotation-hooks-Df8EmzDO.js +0 -11
  198. package/dist/annotation-hooks-Df8EmzDO.js.map +0 -1
  199. package/dist/annotation-k38KDlIZ.d.ts +0 -160
  200. package/dist/annotation-menu.cjs +0 -64
  201. package/dist/annotation-menu.cjs.map +0 -1
  202. package/dist/annotation-menu.d.cts +0 -33
  203. package/dist/annotation-menu.d.ts +0 -33
  204. package/dist/annotation-menu.js +0 -48
  205. package/dist/annotation-menu.js.map +0 -1
  206. package/dist/annotation.cjs.map +0 -1
  207. package/dist/annotation.js.map +0 -1
  208. package/dist/form-BVumS7up.cjs +0 -926
  209. package/dist/form-BVumS7up.cjs.map +0 -1
  210. package/dist/form-Bdjk0Z3T.d.cts +0 -537
  211. package/dist/form-CK3mp99m.js +0 -895
  212. package/dist/form-CK3mp99m.js.map +0 -1
  213. package/dist/form-CYRYgthn.d.ts +0 -537
  214. package/dist/rolldown-runtime-BBjsoOtd.js +0 -27
  215. package/dist/runtime-DE76hlnl.d.ts +0 -216
  216. package/dist/runtime-umHA_xHt.d.cts +0 -216
  217. package/dist/runtime.cjs.map +0 -1
  218. package/dist/runtime.js.map +0 -1
  219. package/dist/scrollbar.cjs +0 -241
  220. package/dist/scrollbar.cjs.map +0 -1
  221. package/dist/scrollbar.d.cts +0 -42
  222. package/dist/scrollbar.d.ts +0 -42
  223. package/dist/scrollbar.js +0 -213
  224. package/dist/scrollbar.js.map +0 -1
  225. package/dist/stage.cjs.map +0 -1
  226. package/dist/stage.js.map +0 -1
  227. package/dist/views.cjs +0 -35
  228. package/dist/views.cjs.map +0 -1
  229. package/dist/views.d.cts +0 -21
  230. package/dist/views.d.ts +0 -21
  231. package/dist/views.js +0 -27
  232. package/dist/views.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -1,307 +1,3 @@
1
- import "./rolldown-runtime-BBjsoOtd.js";
2
- import { Fragment, jsx } from "react/jsx-runtime";
3
- import { createKernel, docInfoListEquals } from "@embedpdf/core";
4
- import { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from "react";
1
+ import { C as useOptionalSelector, D as useViewerSettings, E as useSelector, S as useOptionalCapability, T as usePageList, _ as useDocuments, a as PageProvider, b as useKernel, c as mountWebFont, d as useActiveDocumentId, f as useCapability, g as useDocumentScope, h as useDocumentId, i as KernelProvider, k as epdfTheme, l as saveFile, m as useDocument, n as DocumentScope, o as Viewer, p as useCapabilityEvent, r as EmbedPDF, s as makePageContext, t as DocumentGate, u as shallowArray, v as useDocumentsEvent, w as usePage, x as useKernelValue, y as useDocumentsState } from "./runtime-B6xcPsEb.js";
5
2
  export * from "@embedpdf/core";
6
- //#region src/runtime.tsx
7
- const KernelCtx = createContext(null);
8
- /** The document a subtree is bound to. null => use the active document. */
9
- const DocumentScopeCtx = createContext(null);
10
- function useKernel() {
11
- const k = useContext(KernelCtx);
12
- if (!k) throw new Error("useKernel must be used within <Viewer>/<EmbedPDF>");
13
- return k;
14
- }
15
- const shallowArray = (a, b) => a === b || a.length === b.length && a.every((x, i) => x === b[i]);
16
- /** Read a value derived from the kernel, cached by equality (no tearing loop). */
17
- function useKernelValue(select, isEqual = Object.is) {
18
- const kernel = useKernel();
19
- const last = useRef(null);
20
- const get = () => {
21
- const next = select(kernel);
22
- if (last.current && isEqual(last.current.v, next)) return last.current.v;
23
- last.current = { v: next };
24
- return next;
25
- };
26
- return useSyncExternalStore(kernel.subscribe, get, get);
27
- }
28
- function useActiveDocumentId() {
29
- return useKernelValue((k) => k.documents.activeId());
30
- }
31
- /** The document id for this subtree: the nearest <DocumentScope>, else the active doc. */
32
- function useDocumentId() {
33
- const scoped = useContext(DocumentScopeCtx);
34
- const active = useActiveDocumentId();
35
- return scoped ?? active;
36
- }
37
- /** Bind a subtree to a specific document (panes, comparison). */
38
- function DocumentScope({ id, children }) {
39
- return /* @__PURE__ */ jsx(DocumentScopeCtx.Provider, {
40
- value: id,
41
- children
42
- });
43
- }
44
- /**
45
- * Render children only while this subtree has a READY document — the
46
- * structural way to say "this UI is defined over a document". An empty
47
- * workspace is a legitimate, designable state (the Viewer no longer blocks on
48
- * documents so chrome can render at t≈0): workspace-scoped UI (toolbars,
49
- * commands, i18n) lives OUTSIDE the gate; document-scoped UI (Stage, panels,
50
- * page chrome) lives inside it, or reads through `useOptionalSelector`.
51
- * A `loading`/`locked`/`error` tab renders `fallback` — so the gate's
52
- * fallback doubles as the per-tab boot state; richer chrome (a password
53
- * prompt, an error pane) branches on `useDocumentStatus()` beside the gate.
54
- * Sibling of <DocumentScope>, which picks WHICH document; this one handles
55
- * WHETHER.
56
- */
57
- function DocumentGate({ fallback = null, children }) {
58
- const docId = useDocumentId();
59
- return /* @__PURE__ */ jsx(Fragment, { children: useKernelValue((k) => docId ? k.documents.get(docId)?.status === "ready" : false) ? children : fallback });
60
- }
61
- /** Lifecycle status of this subtree's document (loading/locked/ready/error),
62
- * or null with no document. The password prompt and error panes key off it. */
63
- function useDocumentStatus() {
64
- const docId = useDocumentId();
65
- return useKernelValue((k) => docId ? k.documents.get(docId)?.status ?? null : null);
66
- }
67
- /**
68
- * Resolve a capability by token, binding document-scoped ones to this
69
- * subtree's document. Resolution is a REACTIVE read (`tryCapability` through
70
- * the kernel's one change stream), not a memoized call — under the
71
- * request-time lifecycle a document can become resolvable while its id stays
72
- * the same, so any id-keyed cache goes stale; subscribing makes staleness
73
- * structurally impossible. Fail-fast: while unresolvable, this re-runs the
74
- * strict resolver so the kernel's truthful reason (`no capability` / `no
75
- * document` / `document is loading|locked`) is what throws.
76
- */
77
- function useCapability(token) {
78
- const kernel = useKernel();
79
- const scoped = useContext(DocumentScopeCtx);
80
- return useKernelValue((k) => k.tryCapability(token, scoped ?? void 0)) ?? kernel.capability(token, scoped ?? void 0);
81
- }
82
- /** Like `useCapability`, but null while the token can't resolve (no plugin,
83
- * no document, or a document that isn't ready yet). */
84
- function useOptionalCapability(token) {
85
- const scoped = useContext(DocumentScopeCtx);
86
- return useKernelValue((k) => k.tryCapability(token, scoped ?? void 0));
87
- }
88
- /** Subscribe to a selector over a (document-resolved) capability. */
89
- function useSelector(token, select, isEqual = Object.is) {
90
- const kernel = useKernel();
91
- const cap = useCapability(token);
92
- const last = useRef(null);
93
- const get = () => {
94
- const next = select(cap);
95
- if (last.current && isEqual(last.current.v, next)) return last.current.v;
96
- last.current = { v: next };
97
- return next;
98
- };
99
- return useSyncExternalStore(kernel.subscribe, get, get);
100
- }
101
- /**
102
- * Null-safe `useSelector`: `fallback` whenever the token can't resolve — no
103
- * provider, or a document-scoped token with no document. For chrome that stays
104
- * mounted across the empty-workspace state (a zoom readout, a mode band).
105
- * `useSelector` stays strict (fail-fast) for code that KNOWS a document exists
106
- * — e.g. anything inside a <DocumentGate>.
107
- *
108
- * The `select` guard also swallows reads through a capability whose document
109
- * closed between the store notification and this render — that teardown race
110
- * resolves to `fallback` for one frame, then re-renders against the new state.
111
- */
112
- function useOptionalSelector(token, select, fallback, isEqual = Object.is) {
113
- const kernel = useKernel();
114
- const cap = useOptionalCapability(token);
115
- const last = useRef(null);
116
- const get = () => {
117
- let next;
118
- if (cap === null) next = fallback;
119
- else try {
120
- next = select(cap);
121
- } catch {
122
- next = fallback;
123
- }
124
- if (last.current && isEqual(last.current.v, next)) return last.current.v;
125
- last.current = { v: next };
126
- return next;
127
- };
128
- return useSyncExternalStore(kernel.subscribe, get, get);
129
- }
130
- /**
131
- * Subscribe to a capability's {@link EventHook} for the mounted lifetime —
132
- * `useCapabilityEvent(ActionsToken, (c) => c.onAction, handler)`. Events
133
- * carry occurrences, never state (a late subscriber that needs the current
134
- * value uses `useSelector`). The handler rides a ref, so a fresh closure per
135
- * render never resubscribes. Null-safe: no plugin/document → no subscription.
136
- */
137
- function useCapabilityEvent(token, select, handler) {
138
- const cap = useOptionalCapability(token);
139
- const handlerRef = useRef(handler);
140
- handlerRef.current = handler;
141
- const selectRef = useRef(select);
142
- selectRef.current = select;
143
- useEffect(() => {
144
- if (!cap) return;
145
- return selectRef.current(cap)((event) => handlerRef.current(event));
146
- }, [cap]);
147
- }
148
- /** The document registry (open/close/active/list), reactive. */
149
- function useDocuments() {
150
- const kernel = useKernel();
151
- return {
152
- docs: useKernelValue((k) => k.documents.list(), docInfoListEquals),
153
- activeId: useActiveDocumentId(),
154
- open: kernel.documents.open,
155
- unlock: kernel.documents.unlock,
156
- close: kernel.documents.close,
157
- setActive: kernel.documents.setActive,
158
- move: kernel.documents.move,
159
- swap: kernel.documents.swap,
160
- download: kernel.documents.download,
161
- downloadLayer: kernel.documents.downloadLayer
162
- };
163
- }
164
- /**
165
- * Owns the kernel as an EFFECT-scoped resource: each effect setup creates and
166
- * starts exactly one kernel; each cleanup destroys exactly that one. That is
167
- * the contract StrictMode exercises (two kernels in dev, the first fully
168
- * destroyed) — the kernel itself is never restarted after destroy.
169
- *
170
- * The kernel is published to context the moment it exists — before `start()`
171
- * resolves — so the `fallback` can use workspace capabilities (i18n copy on a
172
- * loading screen) exactly as before. The one exception is the very first
173
- * render, which happens before the effect: it renders nothing. Children mount
174
- * once `start()` resolves — which never touches the engine, so the shell is
175
- * alive while WASM compiles or the transport connects. `initialDocuments`
176
- * open in the BACKGROUND and stream into the registry (`useDocuments()` is
177
- * reactive); per-document loading UI is the Stage's job, not a root gate.
178
- *
179
- * ENGINE OWNERSHIP. When `engine` is a thunk, the Viewer OWNS it: each effect
180
- * setup constructs one engine (construction is synchronous and inert — boot
181
- * happens lazily inside the engine) and each cleanup destroys exactly that one
182
- * — after the kernel, so handles close first. When `engine` is an instance it
183
- * is BORROWED and never destroyed here; the Viewer only calls `warmup?.()` so
184
- * the WASM/transport boot overlaps plugin initialization. StrictMode's
185
- * double-mount therefore constructs two independent thunk engines and tears
186
- * the first fully down, matching the kernel's own effect-scoped lifecycle.
187
- * That means dev-only double resource use (two worker spawns, two font
188
- * fetches, briefly overlapping) — deliberate, because it is exactly the
189
- * leak-detection contract StrictMode exists to exercise; production mounts
190
- * once and boots once.
191
- */
192
- function Viewer({ engine, plugins, initialDocuments, fallback, renderError, children }) {
193
- const initial = useRef({
194
- engine,
195
- plugins,
196
- initialDocuments
197
- });
198
- const warned = useRef(false);
199
- if (process.env.NODE_ENV !== "production" && !warned.current) {
200
- if (initial.current.engine !== engine || initial.current.plugins !== plugins) {
201
- warned.current = true;
202
- console.warn("[embedpdf] <Viewer> engine/plugins are init-only. A changed identity is ignored — pass stable references (module scope, useState, or useMemo). An inline `plugins={[...]}` array recreates its identity every render.");
203
- }
204
- }
205
- const [boot, setBoot] = useState({
206
- phase: "booting",
207
- kernel: null
208
- });
209
- useEffect(() => {
210
- const captured = initial.current;
211
- const ownsEngine = typeof captured.engine === "function";
212
- const engine = ownsEngine ? captured.engine() : captured.engine;
213
- engine.warmup?.();
214
- let kernel;
215
- try {
216
- kernel = createKernel({
217
- engine,
218
- plugins: captured.plugins
219
- });
220
- } catch (error) {
221
- setBoot({
222
- phase: "error",
223
- error
224
- });
225
- if (ownsEngine) engine.destroy();
226
- return;
227
- }
228
- let alive = true;
229
- setBoot({
230
- phase: "booting",
231
- kernel
232
- });
233
- kernel.start().then(() => {
234
- if (!alive) return;
235
- setBoot({
236
- phase: "ready",
237
- kernel
238
- });
239
- kernel.documents.openAll(captured.initialDocuments ?? []);
240
- }, (error) => {
241
- if (alive) setBoot({
242
- phase: "error",
243
- error
244
- });
245
- });
246
- return () => {
247
- alive = false;
248
- kernel.destroy().then(() => {
249
- if (ownsEngine) engine.destroy();
250
- });
251
- };
252
- }, []);
253
- if (boot.phase === "error") return /* @__PURE__ */ jsx(Fragment, { children: renderError ? renderError(boot.error) : null });
254
- if (!boot.kernel) return null;
255
- return /* @__PURE__ */ jsx(KernelCtx.Provider, {
256
- value: boot.kernel,
257
- children: boot.phase === "ready" ? children : fallback ?? null
258
- });
259
- }
260
- const EmbedPDF = Viewer;
261
- const PageCtx = createContext(null);
262
- const PageProvider = PageCtx.Provider;
263
- function usePage() {
264
- const c = useContext(PageCtx);
265
- if (!c) throw new Error("usePage must be used inside <PageView> or a <Stage> page");
266
- return c;
267
- }
268
- function makePageContext(documentId, view, pon, pageIndex, frame, transform, getRect, getViewDemand) {
269
- return {
270
- documentId,
271
- view,
272
- pon,
273
- pageIndex,
274
- frame,
275
- transform,
276
- ...getViewDemand ? { getViewDemand } : {},
277
- toContentPoint: (cx, cy) => {
278
- const r = getRect();
279
- return transform.viewToContent({
280
- x: cx - r.left,
281
- y: cy - r.top
282
- });
283
- },
284
- toClientPoint: (p) => {
285
- const r = getRect();
286
- const v = transform.contentToView(p);
287
- return {
288
- x: r.left + v.x,
289
- y: r.top + v.y
290
- };
291
- },
292
- toClientRect: (rect) => {
293
- const r = getRect();
294
- const v = transform.contentToViewRect(rect);
295
- return {
296
- x: r.left + v.x,
297
- y: r.top + v.y,
298
- width: v.width,
299
- height: v.height
300
- };
301
- }
302
- };
303
- }
304
- //#endregion
305
- export { DocumentGate, DocumentScope, EmbedPDF, PageProvider, Viewer, makePageContext, shallowArray, useActiveDocumentId, useCapability, useCapabilityEvent, useDocumentId, useDocumentStatus, useDocuments, useKernel, useKernelValue, useOptionalCapability, useOptionalSelector, usePage, useSelector };
306
-
307
- //# sourceMappingURL=runtime.js.map
3
+ export { DocumentGate, DocumentScope, EmbedPDF, KernelProvider, PageProvider, Viewer, epdfTheme, makePageContext, mountWebFont, saveFile, shallowArray, useActiveDocumentId, useCapability, useCapabilityEvent, useDocument, useDocumentId, useDocumentScope, useDocuments, useDocumentsEvent, useDocumentsState, useKernel, useKernelValue, useOptionalCapability, useOptionalSelector, usePage, usePageList, useSelector, useViewerSettings };
package/dist/search.cjs CHANGED
@@ -1,79 +1,110 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-DDXJien1.cjs");
3
- const require_runtime = require("./runtime.cjs");
3
+ const require_runtime = require("./runtime-fzpGv78v.cjs");
4
+ const require_state = require("./state-CsfZy_Eq.cjs");
4
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
+ let _embedpdf_web = require("@embedpdf/web");
5
7
  let react = require("react");
6
8
  react = require_rolldown_runtime.__toESM(react, 1);
7
9
  let _embedpdf_plugin_search = require("@embedpdf/plugin-search");
8
10
  //#region src/search.tsx
9
- function SearchLayer({ color = "#ffd500", activeColor = "#ff9632", blendMode = "multiply" }) {
11
+ function SearchLayer({ onHitClick }) {
10
12
  const page = require_runtime.usePage();
11
- const hits = require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.hitsForPage(page.pon), require_runtime.shallowArray);
12
- const active = require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.activeHit());
13
+ const hits = useSearchHits(page.ref);
14
+ const active = useSearchState((state) => state.activeHit);
15
+ const highlight = useSearchSettings((settings) => settings.highlight);
16
+ const [clicks] = (0, react.useState)(_embedpdf_web.createClickDetector);
13
17
  if (hits.length === 0) return null;
18
+ const color = (0, _embedpdf_web.paint)("search-highlight", highlight.color);
19
+ const activeColor = (0, _embedpdf_web.paint)("search-highlight-active", highlight.activeColor);
20
+ const blendMode = (0, _embedpdf_web.paint)("search-blend-mode", highlight.blendMode);
21
+ const clickable = onHitClick ? {
22
+ pointerEvents: "auto",
23
+ cursor: "pointer"
24
+ } : null;
25
+ const pointerHandlers = (hit) => onHitClick && {
26
+ onPointerDown: (event) => clicks.press(event),
27
+ onClick: (event) => {
28
+ if (clicks.isClick(event)) onHitClick(hit);
29
+ }
30
+ };
14
31
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
15
32
  style: {
16
33
  position: "absolute",
17
34
  inset: 0,
18
35
  pointerEvents: "none"
19
36
  },
20
- children: hits.map((hit) => hit.segments.map(({ quad: q }, i) => {
21
- const fill = hit === active ? activeColor : color;
22
- if (q.upperStart.y === q.upperEnd.y && q.lowerStart.y === q.lowerEnd.y && q.upperStart.x === q.lowerStart.x) {
23
- const tl = page.transform.toPixels(q.upperStart);
24
- const br = page.transform.toPixels(q.lowerEnd);
25
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
26
- position: "absolute",
27
- left: tl.x,
28
- top: tl.y,
29
- width: br.x - tl.x,
30
- height: br.y - tl.y,
31
- background: fill,
32
- mixBlendMode: blendMode,
33
- borderRadius: 2
34
- } }, `${hit.charStart}:${i}`);
37
+ children: (0, _embedpdf_web.searchHighlightsOf)(hits, {
38
+ active,
39
+ page: page.transform,
40
+ color,
41
+ activeColor
42
+ }).map((piece) => piece.box ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
43
+ ...pointerHandlers(piece.hit),
44
+ style: {
45
+ position: "absolute",
46
+ left: piece.box.left,
47
+ top: piece.box.top,
48
+ width: piece.box.width,
49
+ height: piece.box.height,
50
+ backgroundColor: piece.fill,
51
+ mixBlendMode: blendMode,
52
+ borderRadius: 2,
53
+ ...clickable
35
54
  }
36
- const ring = [
37
- q.upperStart,
38
- q.upperEnd,
39
- q.lowerEnd,
40
- q.lowerStart
41
- ].map((p) => page.transform.toPixels(p));
42
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
55
+ }, piece.key) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
56
+ style: {
57
+ position: "absolute",
58
+ inset: 0,
59
+ width: "100%",
60
+ height: "100%",
61
+ overflow: "visible",
62
+ mixBlendMode: blendMode
63
+ },
64
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
65
+ points: piece.points ?? void 0,
66
+ ...pointerHandlers(piece.hit),
43
67
  style: {
44
- position: "absolute",
45
- inset: 0,
46
- width: "100%",
47
- height: "100%",
48
- overflow: "visible",
49
- mixBlendMode: blendMode
50
- },
51
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
52
- points: ring.map((p) => `${p.x},${p.y}`).join(" "),
53
- fill
54
- })
55
- }, `${hit.charStart}:${i}`);
56
- }))
68
+ fill: piece.fill,
69
+ ...clickable
70
+ }
71
+ })
72
+ }, piece.key))
57
73
  });
58
74
  }
59
- /** The search capability (search/clear/next/prev/…) for app chrome. */
75
+ /** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */
60
76
  function useSearch() {
61
77
  return require_runtime.useCapability(_embedpdf_plugin_search.SearchToken);
62
78
  }
63
- /** Reactive search read-model for chrome: the query, status, counts, progress. */
64
- function useSearchState() {
65
- return {
66
- query: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.query()),
67
- status: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.status()),
68
- hitCount: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.hitCount()),
69
- activeIndex: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.activeIndex()),
70
- progress: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.progress(), (a, b) => a.scanned === b.scanned && a.total === b.total),
71
- error: require_runtime.useSelector(_embedpdf_plugin_search.SearchToken, (c) => c.errorMessage())
72
- };
79
+ /** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */
80
+ function useSearchEvent(select, handler) {
81
+ require_runtime.useCapabilityEvent(_embedpdf_plugin_search.SearchToken, select, handler);
82
+ }
83
+ /**
84
+ * The search's state: the query, status, count, active match, progress and
85
+ * error (the page's State table, declared once in `searchState`). Takes a
86
+ * selector, and re-renders only when what it returns changes.
87
+ */
88
+ const useSearchState = require_state.stateHook(_embedpdf_plugin_search.searchState);
89
+ /** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */
90
+ const useSearchSettings = require_state.settingsHook(_embedpdf_plugin_search.SearchToken);
91
+ const NO_HITS = Object.freeze([]);
92
+ /**
93
+ * Every match found so far, or one page's (its ref or index), for a results
94
+ * list or a count per thumbnail. The arrays are reference-stable, so a
95
+ * component re-renders only when matches land on what it shows. Empty without
96
+ * a document, and for a page that has just left the document.
97
+ */
98
+ function useSearchHits(page) {
99
+ const scoped = require_runtime.useDocumentScope();
100
+ return require_runtime.useKernelValue((kernel) => kernel.tryCapability(_embedpdf_plugin_search.SearchToken, scoped ?? void 0)?.listHits(page === void 0 ? void 0 : { page }) ?? NO_HITS);
73
101
  }
74
102
  //#endregion
75
103
  exports.SearchLayer = SearchLayer;
76
104
  exports.useSearch = useSearch;
105
+ exports.useSearchEvent = useSearchEvent;
106
+ exports.useSearchHits = useSearchHits;
107
+ exports.useSearchSettings = useSearchSettings;
77
108
  exports.useSearchState = useSearchState;
78
109
  Object.keys(_embedpdf_plugin_search).forEach(function(k) {
79
110
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
@@ -1 +1 @@
1
- {"version":3,"file":"search.cjs","names":["usePage","useSelector","SearchToken","shallowArray","useCapability"],"sources":["../src/search.tsx"],"sourcesContent":["/**\n * The React surface for @embedpdf/plugin-search.\n *\n * <SearchLayer> is a dumb renderer, the SelectionLayer's twin: it reads\n * the page's content-space hit rects from the capability and paints them\n * through PageContext.toPixels. The active hit gets its own colour.\n * No pointer handling, no engine calls — search is driven from app chrome\n * via useSearch().\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-search';\nimport * as React from 'react';\nimport { SearchToken } from '@embedpdf/plugin-search';\nimport type { SearchHit } from '@embedpdf/plugin-search';\nimport { shallowArray, useCapability, usePage, useSelector } from './runtime';\n\nexport interface SearchLayerProps {\n /** Highlight colour for hits — SOLID (default: highlighter yellow). */\n color?: string;\n /** Highlight colour for the ACTIVE hit — SOLID (default: orange). */\n activeColor?: string;\n /**\n * How the highlight composites with the page. `'multiply'` (default) is\n * the real-highlighter look: text stays crisp black through the colour,\n * only the paper tints. Pass `'normal'` (with translucent colours) for\n * dark/scanned documents where multiply-on-dark would vanish.\n */\n blendMode?: React.CSSProperties['mixBlendMode'];\n}\n\nexport function SearchLayer({\n color = '#ffd500',\n activeColor = '#ff9632',\n blendMode = 'multiply',\n}: SearchLayerProps) {\n const page = usePage();\n const hits = useSelector(SearchToken, (c) => c.hitsForPage(page.pon), shallowArray);\n const active = useSelector(SearchToken, (c) => c.activeHit());\n\n if (hits.length === 0) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {hits.map((hit: SearchHit) =>\n hit.segments.map(({ quad: q }, i) => {\n const fill = hit === active ? activeColor : color;\n // Upright hits keep the classic rounded div (pixel-identical to the\n // pre-orientation layer); rotated hits draw their true oriented cell.\n const upright =\n q.upperStart.y === q.upperEnd.y &&\n q.lowerStart.y === q.lowerEnd.y &&\n q.upperStart.x === q.lowerStart.x;\n if (upright) {\n const tl = page.transform.toPixels(q.upperStart);\n const br = page.transform.toPixels(q.lowerEnd);\n return (\n <div\n key={`${hit.charStart}:${i}`}\n style={{\n position: 'absolute',\n left: tl.x,\n top: tl.y,\n width: br.x - tl.x,\n height: br.y - tl.y,\n background: fill,\n mixBlendMode: blendMode,\n borderRadius: 2,\n }}\n />\n );\n }\n const ring = [q.upperStart, q.upperEnd, q.lowerEnd, q.lowerStart].map((p) =>\n page.transform.toPixels(p),\n );\n return (\n <svg\n key={`${hit.charStart}:${i}`}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n overflow: 'visible',\n mixBlendMode: blendMode,\n }}\n >\n <polygon points={ring.map((p) => `${p.x},${p.y}`).join(' ')} fill={fill} />\n </svg>\n );\n }),\n )}\n </div>\n );\n}\n\n/** The search capability (search/clear/next/prev/…) for app chrome. */\nexport function useSearch() {\n return useCapability(SearchToken);\n}\n\n/** Reactive search read-model for chrome: the query, status, counts, progress. */\nexport function useSearchState() {\n const query = useSelector(SearchToken, (c) => c.query());\n const status = useSelector(SearchToken, (c) => c.status());\n const hitCount = useSelector(SearchToken, (c) => c.hitCount());\n const activeIndex = useSelector(SearchToken, (c) => c.activeIndex());\n const progress = useSelector(\n SearchToken,\n (c) => c.progress(),\n (a, b) => a.scanned === b.scanned && a.total === b.total,\n );\n const error = useSelector(SearchToken, (c) => c.errorMessage());\n return { query, status, hitCount, activeIndex, progress, error };\n}\n"],"mappings":";;;;;;;;AA+BA,SAAgB,YAAY,EAC1B,QAAQ,WACR,cAAc,WACd,YAAY,cACO;CACnB,MAAM,OAAOA,gBAAAA,QAAQ;CACrB,MAAM,OAAOC,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,YAAY,KAAK,GAAG,GAAGC,gBAAAA,YAAY;CAClF,MAAM,SAASF,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,UAAU,CAAC;CAE5D,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EACjE,UAAA,KAAK,KAAK,QACT,IAAI,SAAS,KAAK,EAAE,MAAM,KAAK,MAAM;GACnC,MAAM,OAAO,QAAQ,SAAS,cAAc;GAO5C,IAHE,EAAE,WAAW,MAAM,EAAE,SAAS,KAC9B,EAAE,WAAW,MAAM,EAAE,SAAS,KAC9B,EAAE,WAAW,MAAM,EAAE,WAAW,GACrB;IACX,MAAM,KAAK,KAAK,UAAU,SAAS,EAAE,UAAU;IAC/C,MAAM,KAAK,KAAK,UAAU,SAAS,EAAE,QAAQ;IAC7C,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAEE,OAAO;KACL,UAAU;KACV,MAAM,GAAG;KACT,KAAK,GAAG;KACR,OAAO,GAAG,IAAI,GAAG;KACjB,QAAQ,GAAG,IAAI,GAAG;KAClB,YAAY;KACZ,cAAc;KACd,cAAc;IAChB,EACD,GAXM,GAAG,IAAI,UAAU,GAAG,GAW1B;GAEL;GACA,MAAM,OAAO;IAAC,EAAE;IAAY,EAAE;IAAU,EAAE;IAAU,EAAE;GAAU,CAAC,CAAC,KAAK,MACrE,KAAK,UAAU,SAAS,CAAC,CAC3B;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAEE,OAAO;KACL,UAAU;KACV,OAAO;KACP,OAAO;KACP,QAAQ;KACR,UAAU;KACV,cAAc;IAChB;IAEA,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD;KAAS,QAAQ,KAAK,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG;KAAS;IAAO,CAAA;GACvE,GAXE,GAAG,IAAI,UAAU,GAAG,GAWtB;EAET,CAAC,CACH;CACG,CAAA;AAET;;AAGA,SAAgB,YAAY;CAC1B,OAAOE,gBAAAA,cAAcF,wBAAAA,WAAW;AAClC;;AAGA,SAAgB,iBAAiB;CAW/B,OAAO;EAAE,OAVKD,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,MAAM,CAUzC;EAAG,QATDD,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,OAAO,CASnC;EAAG,UARPD,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,SAAS,CAQ7B;EAAG,aAPdD,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,YAAY,CAOtB;EAAG,UAN9BD,gBAAAA,YACfC,wBAAAA,cACC,MAAM,EAAE,SAAS,IACjB,GAAG,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,KAGC;EAAG,OAD3CD,gBAAAA,YAAYC,wBAAAA,cAAc,MAAM,EAAE,aAAa,CACA;CAAE;AACjE"}
1
+ {"version":3,"file":"search.cjs","names":["usePage","createClickDetector","useCapability","SearchToken","stateHook","searchState","settingsHook","useDocumentScope","useKernelValue"],"sources":["../src/search.tsx"],"sourcesContent":["/**\n * The React surface for @embedpdf/plugin-search.\n *\n * <SearchLayer> is the SelectionLayer's twin: it reads the page's page-space\n * hit rects from the capability and paints them through PageContext.toPixels,\n * in the colors of the plugin's `highlight` setting, which the `--epdf-search-*`\n * CSS variables override. No engine calls: search is driven from app chrome\n * via useSearch().\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-search';\nimport * as React from 'react';\nimport { useState } from 'react';\nimport { SearchToken, searchState } from '@embedpdf/plugin-search';\nimport type { SearchCapability, SearchHit } from '@embedpdf/plugin-search';\nimport type { EventHook, PageRef } from '@embedpdf/core';\nimport { createClickDetector, paint, searchHighlightsOf } from '@embedpdf/web';\nimport {\n useCapability,\n useCapabilityEvent,\n useDocumentScope,\n useKernelValue,\n usePage,\n} from './runtime';\nimport { settingsHook, stateHook } from './state';\n\nexport interface SearchLayerProps {\n /**\n * Make matches clickable: called with the match someone clicks, for example\n * to make it the active one with `search.goToHit(hit)`. The press still\n * reaches the page, so a drag that starts on a match selects text, and only\n * a click calls this. Without it, matches are only paint and the pointer\n * goes straight through.\n */\n onHitClick?: (hit: SearchHit) => void;\n}\n\nexport function SearchLayer({ onHitClick }: SearchLayerProps) {\n const page = usePage();\n // Per-page hit arrays are reference-stable in the plugin, so this re-renders\n // only when matches land on this page.\n const hits = useSearchHits(page.ref);\n const active = useSearchState((state) => state.activeHit);\n const highlight = useSearchSettings((settings) => settings.highlight);\n // Tells a click on a match from a drag that starts there (and selects text).\n const [clicks] = useState(createClickDetector);\n\n if (hits.length === 0) return null;\n\n // Each color is its CSS variable first, then the setting: CSS wins.\n const color = paint('search-highlight', highlight.color);\n const activeColor = paint('search-highlight-active', highlight.activeColor);\n const blendMode = paint(\n 'search-blend-mode',\n highlight.blendMode,\n ) as React.CSSProperties['mixBlendMode'];\n\n // Only a clickable match takes the pointer; a plain highlight stays inert.\n // Nothing here stops the press, so it reaches the page as well.\n const clickable = onHitClick ? { pointerEvents: 'auto' as const, cursor: 'pointer' } : null;\n const pointerHandlers = (hit: SearchHit) =>\n onHitClick && {\n onPointerDown: (event: React.PointerEvent) => clicks.press(event),\n onClick: (event: React.MouseEvent) => {\n if (clicks.isClick(event)) onHitClick(hit);\n },\n };\n\n // Upright lines are a rounded box; turned lines draw their true quad.\n const pieces = searchHighlightsOf(hits, {\n active,\n page: page.transform,\n color,\n activeColor,\n });\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {pieces.map((piece) =>\n piece.box ? (\n <div\n key={piece.key}\n {...pointerHandlers(piece.hit)}\n style={{\n position: 'absolute',\n left: piece.box.left,\n top: piece.box.top,\n width: piece.box.width,\n height: piece.box.height,\n backgroundColor: piece.fill,\n mixBlendMode: blendMode,\n borderRadius: 2,\n ...clickable,\n }}\n />\n ) : (\n <svg\n key={piece.key}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n overflow: 'visible',\n mixBlendMode: blendMode,\n }}\n >\n {/* The fill goes in `style`: an SVG attribute doesn't read var(). */}\n <polygon\n points={piece.points ?? undefined}\n {...pointerHandlers(piece.hit)}\n style={{ fill: piece.fill, ...clickable }}\n />\n </svg>\n ),\n )}\n </div>\n );\n}\n\n/** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */\nexport function useSearch(): SearchCapability {\n return useCapability(SearchToken);\n}\n\n/** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */\nexport function useSearchEvent<T>(\n select: (search: SearchCapability) => EventHook<T>,\n handler: (event: T) => void,\n): void {\n useCapabilityEvent(SearchToken, select, handler);\n}\n\n/**\n * The search's state: the query, status, count, active match, progress and\n * error (the page's State table, declared once in `searchState`). Takes a\n * selector, and re-renders only when what it returns changes.\n */\nexport const useSearchState = stateHook(searchState);\n\n/** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */\nexport const useSearchSettings = settingsHook(SearchToken);\n\nconst NO_HITS: readonly SearchHit[] = Object.freeze([]);\n\n/**\n * Every match found so far, or one page's (its ref or index), for a results\n * list or a count per thumbnail. The arrays are reference-stable, so a\n * component re-renders only when matches land on what it shows. Empty without\n * a document, and for a page that has just left the document.\n */\nexport function useSearchHits(page?: PageRef | number): readonly SearchHit[] {\n const scoped = useDocumentScope();\n // Resolved on every read, like the state hook: a document that closes reads as no hits.\n return useKernelValue(\n (kernel) =>\n kernel\n .tryCapability(SearchToken, scoped ?? undefined)\n ?.listHits(page === undefined ? undefined : { page }) ?? NO_HITS,\n );\n}\n"],"mappings":";;;;;;;;;;AAsCA,SAAgB,YAAY,EAAE,cAAgC;CAC5D,MAAM,OAAOA,gBAAAA,QAAQ;CAGrB,MAAM,OAAO,cAAc,KAAK,GAAG;CACnC,MAAM,SAAS,gBAAgB,UAAU,MAAM,SAAS;CACxD,MAAM,YAAY,mBAAmB,aAAa,SAAS,SAAS;CAEpE,MAAM,CAAC,WAAA,GAAA,MAAA,SAAA,CAAmBC,cAAAA,mBAAmB;CAE7C,IAAI,KAAK,WAAW,GAAG,OAAO;CAG9B,MAAM,SAAA,GAAA,cAAA,MAAA,CAAc,oBAAoB,UAAU,KAAK;CACvD,MAAM,eAAA,GAAA,cAAA,MAAA,CAAoB,2BAA2B,UAAU,WAAW;CAC1E,MAAM,aAAA,GAAA,cAAA,MAAA,CACJ,qBACA,UAAU,SACZ;CAIA,MAAM,YAAY,aAAa;EAAE,eAAe;EAAiB,QAAQ;CAAU,IAAI;CACvF,MAAM,mBAAmB,QACvB,cAAc;EACZ,gBAAgB,UAA8B,OAAO,MAAM,KAAK;EAChE,UAAU,UAA4B;GACpC,IAAI,OAAO,QAAQ,KAAK,GAAG,WAAW,GAAG;EAC3C;CACF;CAUF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EARpC,WAAA,GAAA,cAAA,mBAAA,CAAA,MAAM;GACtC;GACA,MAAM,KAAK;GACX;GACA;EACF,CAIU,CAAC,CAAC,KAAK,UACX,MAAM,MACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAEE,GAAI,gBAAgB,MAAM,GAAG;GAC7B,OAAO;IACL,UAAU;IACV,MAAM,MAAM,IAAI;IAChB,KAAK,MAAM,IAAI;IACf,OAAO,MAAM,IAAI;IACjB,QAAQ,MAAM,IAAI;IAClB,iBAAiB,MAAM;IACvB,cAAc;IACd,cAAc;IACd,GAAG;GACL;EACD,GAbM,MAAM,GAaZ,IAED,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAEE,OAAO;IACL,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;IACR,UAAU;IACV,cAAc;GAChB;GAGA,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD;IACE,QAAQ,MAAM,UAAU,KAAA;IACxB,GAAI,gBAAgB,MAAM,GAAG;IAC7B,OAAO;KAAE,MAAM,MAAM;KAAM,GAAG;IAAU;GACzC,CAAA;EACE,GAhBE,MAAM,GAgBR,CAET;CACG,CAAA;AAET;;AAGA,SAAgB,YAA8B;CAC5C,OAAOC,gBAAAA,cAAcC,wBAAAA,WAAW;AAClC;;AAGA,SAAgB,eACd,QACA,SACM;CACN,gBAAA,mBAAmBA,wBAAAA,aAAa,QAAQ,OAAO;AACjD;;;;;;AAOA,MAAa,iBAAiBC,cAAAA,UAAUC,wBAAAA,WAAW;;AAGnD,MAAa,oBAAoBC,cAAAA,aAAaH,wBAAAA,WAAW;AAEzD,MAAM,UAAgC,OAAO,OAAO,CAAC,CAAC;;;;;;;AAQtD,SAAgB,cAAc,MAA+C;CAC3E,MAAM,SAASI,gBAAAA,iBAAiB;CAEhC,OAAOC,gBAAAA,gBACJ,WACC,OACG,cAAcL,wBAAAA,aAAa,UAAU,KAAA,CAAS,CAAC,EAC9C,SAAS,SAAS,KAAA,IAAY,KAAA,IAAY,EAAE,KAAK,CAAC,KAAK,OAC/D;AACF"}
package/dist/search.d.cts CHANGED
@@ -1,34 +1,47 @@
1
- import * as React from "react";
1
+ import { n as StateHook, t as SettingsHook } from "./state-0K1I5cM4.cjs";
2
+ import { o as SearchQuery } from "./AnnotationList-CkijRHet-HEFNUIZe.cjs";
3
+ import { EventHook, PageRef } from "@embedpdf/core";
4
+ import { SearchCapability, SearchHit } from "@embedpdf/plugin-search";
2
5
  export * from "@embedpdf/plugin-search";
3
6
  //#region src/search.d.ts
4
7
  interface SearchLayerProps {
5
- /** Highlight colour for hits — SOLID (default: highlighter yellow). */
6
- color?: string;
7
- /** Highlight colour for the ACTIVE hit — SOLID (default: orange). */
8
- activeColor?: string;
9
8
  /**
10
- * How the highlight composites with the page. `'multiply'` (default) is
11
- * the real-highlighter look: text stays crisp black through the colour,
12
- * only the paper tints. Pass `'normal'` (with translucent colours) for
13
- * dark/scanned documents where multiply-on-dark would vanish.
9
+ * Make matches clickable: called with the match someone clicks, for example
10
+ * to make it the active one with `search.goToHit(hit)`. The press still
11
+ * reaches the page, so a drag that starts on a match selects text, and only
12
+ * a click calls this. Without it, matches are only paint and the pointer
13
+ * goes straight through.
14
14
  */
15
- blendMode?: React.CSSProperties['mixBlendMode'];
15
+ onHitClick?: (hit: SearchHit) => void;
16
16
  }
17
- declare function SearchLayer({ color, activeColor, blendMode }: SearchLayerProps): import("react/jsx-runtime").JSX.Element | null;
18
- /** The search capability (search/clear/next/prev/…) for app chrome. */
19
- declare function useSearch(): import("@embedpdf/plugin-search").SearchCapability;
20
- /** Reactive search read-model for chrome: the query, status, counts, progress. */
21
- declare function useSearchState(): {
22
- query: import("@embedpdf/plugin-search").SearchQuery | null;
17
+ declare function SearchLayer({ onHitClick }: SearchLayerProps): import("react/jsx-runtime").JSX.Element | null;
18
+ /** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */
19
+ declare function useSearch(): SearchCapability;
20
+ /** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */
21
+ declare function useSearchEvent<T>(select: (search: SearchCapability) => EventHook<T>, handler: (event: T) => void): void;
22
+ /**
23
+ * The search's state: the query, status, count, active match, progress and
24
+ * error (the page's State table, declared once in `searchState`). Takes a
25
+ * selector, and re-renders only when what it returns changes.
26
+ */
27
+ declare const useSearchState: StateHook<{
28
+ query: SearchQuery | null;
23
29
  status: import("@embedpdf/plugin-search").SearchStatus;
24
30
  hitCount: number;
25
- activeIndex: number;
26
- progress: {
27
- scanned: number;
28
- total: number;
29
- };
30
- error: string | null;
31
- };
31
+ activeHitIndex: number;
32
+ activeHit: SearchHit | null;
33
+ progress: import("@embedpdf/plugin-search").SearchProgress;
34
+ error: import("@embedpdf/core").PluginErrorInfo | null;
35
+ }>;
36
+ /** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */
37
+ declare const useSearchSettings: SettingsHook<import("@embedpdf/plugin-search").SearchSettings>;
38
+ /**
39
+ * Every match found so far, or one page's (its ref or index), for a results
40
+ * list or a count per thumbnail. The arrays are reference-stable, so a
41
+ * component re-renders only when matches land on what it shows. Empty without
42
+ * a document, and for a page that has just left the document.
43
+ */
44
+ declare function useSearchHits(page?: PageRef | number): readonly SearchHit[];
32
45
  //#endregion
33
- export { SearchLayer, SearchLayerProps, useSearch, useSearchState };
46
+ export { SearchLayer, SearchLayerProps, useSearch, useSearchEvent, useSearchHits, useSearchSettings, useSearchState };
34
47
  //# sourceMappingURL=search.d.cts.map