pdf-search-highlight 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -9
- package/dist/{PDFSearchViewer-rNp5NirR.d.cts → PDFSearchViewer-DzKHoKTp.d.cts} +52 -27
- package/dist/{PDFSearchViewer-rNp5NirR.d.ts → PDFSearchViewer-DzKHoKTp.d.ts} +52 -27
- package/dist/{chunk-Y5LFTIMY.cjs → chunk-GDUHZCFR.cjs} +158 -12
- package/dist/chunk-GDUHZCFR.cjs.map +1 -0
- package/dist/{chunk-AA4UECNB.js → chunk-XFH7JUDJ.js} +151 -5
- package/dist/chunk-XFH7JUDJ.js.map +1 -0
- package/dist/core/index.cjs +4 -2
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +21 -4
- package/dist/core/index.d.ts +21 -4
- package/dist/core/index.js +3 -1
- package/dist/pdf-search-highlight.css +27 -1
- package/dist/react/index.cjs +36 -24
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +16 -4
- package/dist/react/index.d.ts +16 -4
- package/dist/react/index.js +18 -6
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-AA4UECNB.js.map +0 -1
- package/dist/chunk-Y5LFTIMY.cjs.map +0 -1
package/dist/react/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunkGDUHZCFRcjs = require('../chunk-GDUHZCFR.cjs');
|
|
9
9
|
|
|
10
10
|
// src/react/usePDFRenderer.ts
|
|
11
11
|
var _react = require('react');
|
|
@@ -27,7 +27,7 @@ function usePDFRenderer(pdfjsLib, options = {}) {
|
|
|
27
27
|
const getRenderer = _react.useCallback.call(void 0, () => {
|
|
28
28
|
if (!containerRef.current) throw new Error("Container ref not attached");
|
|
29
29
|
if (!rendererRef.current) {
|
|
30
|
-
const r = new (0,
|
|
30
|
+
const r = new (0, _chunkGDUHZCFRcjs.PDFRenderer)(containerRef.current, optionsRef.current);
|
|
31
31
|
r.setPdfjsLib(pdfjsLib);
|
|
32
32
|
rendererRef.current = r;
|
|
33
33
|
}
|
|
@@ -64,13 +64,13 @@ function usePDFRenderer(pdfjsLib, options = {}) {
|
|
|
64
64
|
const zoomIn = _react.useCallback.call(void 0, async () => {
|
|
65
65
|
const renderer = getRenderer();
|
|
66
66
|
const current = renderer.getScale() === "auto" ? renderer.getEffectiveScale() : renderer.getScale();
|
|
67
|
-
const newScale = Math.min(current +
|
|
67
|
+
const newScale = Math.min(current + _chunkGDUHZCFRcjs.ZOOM_STEP, _chunkGDUHZCFRcjs.MAX_SCALE);
|
|
68
68
|
return setScale(newScale);
|
|
69
69
|
}, [getRenderer, setScale]);
|
|
70
70
|
const zoomOut = _react.useCallback.call(void 0, async () => {
|
|
71
71
|
const renderer = getRenderer();
|
|
72
72
|
const current = renderer.getScale() === "auto" ? renderer.getEffectiveScale() : renderer.getScale();
|
|
73
|
-
const newScale = Math.max(current -
|
|
73
|
+
const newScale = Math.max(current - _chunkGDUHZCFRcjs.ZOOM_STEP, _chunkGDUHZCFRcjs.MIN_SCALE);
|
|
74
74
|
return setScale(newScale);
|
|
75
75
|
}, [getRenderer, setScale]);
|
|
76
76
|
const download = _react.useCallback.call(void 0,
|
|
@@ -108,7 +108,7 @@ function useSearchController(pages, options = {}) {
|
|
|
108
108
|
const [current, setCurrent] = _react.useState.call(void 0, -1);
|
|
109
109
|
const [total, setTotal] = _react.useState.call(void 0, 0);
|
|
110
110
|
if (!controllerRef.current) {
|
|
111
|
-
controllerRef.current = new (0,
|
|
111
|
+
controllerRef.current = new (0, _chunkGDUHZCFRcjs.SearchController)(options);
|
|
112
112
|
}
|
|
113
113
|
_react.useEffect.call(void 0, () => {
|
|
114
114
|
const ctrl = controllerRef.current;
|
|
@@ -126,6 +126,12 @@ function useSearchController(pages, options = {}) {
|
|
|
126
126
|
const search = _react.useCallback.call(void 0, (query, opts) => {
|
|
127
127
|
return controllerRef.current.search(query, opts);
|
|
128
128
|
}, []);
|
|
129
|
+
const searchMultiple = _react.useCallback.call(void 0,
|
|
130
|
+
(contexts, opts) => {
|
|
131
|
+
return controllerRef.current.searchMultiple(contexts, opts);
|
|
132
|
+
},
|
|
133
|
+
[]
|
|
134
|
+
);
|
|
129
135
|
const next = _react.useCallback.call(void 0, () => {
|
|
130
136
|
controllerRef.current.next();
|
|
131
137
|
}, []);
|
|
@@ -138,7 +144,7 @@ function useSearchController(pages, options = {}) {
|
|
|
138
144
|
const clear = _react.useCallback.call(void 0, () => {
|
|
139
145
|
controllerRef.current.clear();
|
|
140
146
|
}, []);
|
|
141
|
-
return { search, next, prev, goTo, clear, current, total };
|
|
147
|
+
return { search, searchMultiple, next, prev, goTo, clear, current, total };
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
// src/react/PDFSearchViewer.tsx
|
|
@@ -154,10 +160,12 @@ var PDFSearchViewer2 = _react.forwardRef.call(void 0, function PDFSearchViewer3(
|
|
|
154
160
|
pdfjsLib,
|
|
155
161
|
source,
|
|
156
162
|
searchQuery,
|
|
163
|
+
searchContexts,
|
|
157
164
|
searchOptions,
|
|
158
165
|
viewerOptions,
|
|
159
166
|
onLoad,
|
|
160
167
|
onSearch,
|
|
168
|
+
onSearchMultiple,
|
|
161
169
|
onMatchChange,
|
|
162
170
|
onZoom,
|
|
163
171
|
onError,
|
|
@@ -166,20 +174,21 @@ var PDFSearchViewer2 = _react.forwardRef.call(void 0, function PDFSearchViewer3(
|
|
|
166
174
|
} = props;
|
|
167
175
|
const containerRef = _react.useRef.call(void 0, null);
|
|
168
176
|
const coreRef = _react.useRef.call(void 0, null);
|
|
169
|
-
const callbackRefs = _react.useRef.call(void 0, { onLoad, onSearch, onMatchChange, onZoom, onError });
|
|
170
|
-
callbackRefs.current = { onLoad, onSearch, onMatchChange, onZoom, onError };
|
|
177
|
+
const callbackRefs = _react.useRef.call(void 0, { onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError });
|
|
178
|
+
callbackRefs.current = { onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError };
|
|
171
179
|
_react.useEffect.call(void 0, () => {
|
|
172
180
|
if (!containerRef.current || !pdfjsLib) return;
|
|
173
|
-
const core = new (0,
|
|
181
|
+
const core = new (0, _chunkGDUHZCFRcjs.PDFSearchViewer)(
|
|
174
182
|
containerRef.current,
|
|
175
183
|
pdfjsLib,
|
|
176
184
|
_nullishCoalesce(viewerOptions, () => ( {}))
|
|
177
185
|
);
|
|
178
186
|
core.on("load", (data) => _optionalChain([callbackRefs, 'access', _7 => _7.current, 'access', _8 => _8.onLoad, 'optionalCall', _9 => _9(data)]));
|
|
179
187
|
core.on("search", (data) => _optionalChain([callbackRefs, 'access', _10 => _10.current, 'access', _11 => _11.onSearch, 'optionalCall', _12 => _12(data)]));
|
|
180
|
-
core.on("
|
|
181
|
-
core.on("
|
|
182
|
-
core.on("
|
|
188
|
+
core.on("searchmultiple", (data) => _optionalChain([callbackRefs, 'access', _13 => _13.current, 'access', _14 => _14.onSearchMultiple, 'optionalCall', _15 => _15(data)]));
|
|
189
|
+
core.on("matchchange", (data) => _optionalChain([callbackRefs, 'access', _16 => _16.current, 'access', _17 => _17.onMatchChange, 'optionalCall', _18 => _18(data)]));
|
|
190
|
+
core.on("zoom", (data) => _optionalChain([callbackRefs, 'access', _19 => _19.current, 'access', _20 => _20.onZoom, 'optionalCall', _21 => _21(data)]));
|
|
191
|
+
core.on("error", (data) => _optionalChain([callbackRefs, 'access', _22 => _22.current, 'access', _23 => _23.onError, 'optionalCall', _24 => _24(data)]));
|
|
183
192
|
coreRef.current = core;
|
|
184
193
|
return () => {
|
|
185
194
|
core.destroy();
|
|
@@ -193,30 +202,33 @@ var PDFSearchViewer2 = _react.forwardRef.call(void 0, function PDFSearchViewer3(
|
|
|
193
202
|
}, [source]);
|
|
194
203
|
_react.useEffect.call(void 0, () => {
|
|
195
204
|
if (!coreRef.current) return;
|
|
196
|
-
if (
|
|
205
|
+
if (searchContexts && searchContexts.length > 0) {
|
|
206
|
+
coreRef.current.searchMultiple(searchContexts, searchOptions);
|
|
207
|
+
} else if (searchQuery && searchQuery.trim().length > 0) {
|
|
197
208
|
coreRef.current.search(searchQuery, searchOptions);
|
|
198
209
|
} else {
|
|
199
210
|
coreRef.current.clearSearch();
|
|
200
211
|
}
|
|
201
|
-
}, [searchQuery, searchOptions]);
|
|
212
|
+
}, [searchQuery, searchContexts, searchOptions]);
|
|
202
213
|
_react.useImperativeHandle.call(void 0, ref, () => ({
|
|
203
|
-
nextMatch: () => _nullishCoalesce(_optionalChain([coreRef, 'access',
|
|
204
|
-
prevMatch: () => _nullishCoalesce(_optionalChain([coreRef, 'access',
|
|
205
|
-
clearSearch: () => _optionalChain([coreRef, 'access',
|
|
206
|
-
|
|
207
|
-
|
|
214
|
+
nextMatch: () => _nullishCoalesce(_optionalChain([coreRef, 'access', _25 => _25.current, 'optionalAccess', _26 => _26.nextMatch, 'call', _27 => _27()]), () => ( -1)),
|
|
215
|
+
prevMatch: () => _nullishCoalesce(_optionalChain([coreRef, 'access', _28 => _28.current, 'optionalAccess', _29 => _29.prevMatch, 'call', _30 => _30()]), () => ( -1)),
|
|
216
|
+
clearSearch: () => _optionalChain([coreRef, 'access', _31 => _31.current, 'optionalAccess', _32 => _32.clearSearch, 'call', _33 => _33()]),
|
|
217
|
+
searchMultiple: (contexts, opts) => _nullishCoalesce(_optionalChain([coreRef, 'access', _34 => _34.current, 'optionalAccess', _35 => _35.searchMultiple, 'call', _36 => _36(contexts, opts)]), () => ( 0)),
|
|
218
|
+
getMatchCount: () => _nullishCoalesce(_optionalChain([coreRef, 'access', _37 => _37.current, 'optionalAccess', _38 => _38.getMatchCount, 'call', _39 => _39()]), () => ( 0)),
|
|
219
|
+
getCurrentMatchIndex: () => _nullishCoalesce(_optionalChain([coreRef, 'access', _40 => _40.current, 'optionalAccess', _41 => _41.getCurrentMatchIndex, 'call', _42 => _42()]), () => ( -1)),
|
|
208
220
|
zoomIn: async () => {
|
|
209
|
-
await _optionalChain([coreRef, 'access',
|
|
221
|
+
await _optionalChain([coreRef, 'access', _43 => _43.current, 'optionalAccess', _44 => _44.zoomIn, 'call', _45 => _45()]);
|
|
210
222
|
},
|
|
211
223
|
zoomOut: async () => {
|
|
212
|
-
await _optionalChain([coreRef, 'access',
|
|
224
|
+
await _optionalChain([coreRef, 'access', _46 => _46.current, 'optionalAccess', _47 => _47.zoomOut, 'call', _48 => _48()]);
|
|
213
225
|
},
|
|
214
226
|
setScale: async (s) => {
|
|
215
|
-
await _optionalChain([coreRef, 'access',
|
|
227
|
+
await _optionalChain([coreRef, 'access', _49 => _49.current, 'optionalAccess', _50 => _50.setScale, 'call', _51 => _51(s)]);
|
|
216
228
|
},
|
|
217
|
-
getScale: () => _nullishCoalesce(_optionalChain([coreRef, 'access',
|
|
229
|
+
getScale: () => _nullishCoalesce(_optionalChain([coreRef, 'access', _52 => _52.current, 'optionalAccess', _53 => _53.getScale, 'call', _54 => _54()]), () => ( "auto")),
|
|
218
230
|
download: async (filename) => {
|
|
219
|
-
await _optionalChain([coreRef, 'access',
|
|
231
|
+
await _optionalChain([coreRef, 'access', _55 => _55.current, 'optionalAccess', _56 => _56.download, 'call', _57 => _57(filename)]);
|
|
220
232
|
},
|
|
221
233
|
getCore: () => coreRef.current
|
|
222
234
|
}));
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/hoangnguyen/Desktop/pdf-search-highlight/dist/react/index.cjs","../../src/react/usePDFRenderer.ts","../../src/react/useSearchController.ts","../../src/react/PDFSearchViewer.tsx"],"names":["useRef","useState","useEffect","useCallback","PDFSearchViewer"],"mappings":"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","file":"/Users/hoangnguyen/Desktop/pdf-search-highlight/dist/react/index.cjs","sourcesContent":[null,"import { useRef, useEffect, useCallback, useState } from 'react';\nimport { PDFRenderer } from '../core/PDFRenderer';\nimport { ZOOM_STEP, MIN_SCALE, MAX_SCALE } from '../core/constants';\nimport type { PDFSearchViewerOptions, PageData, PDFSource } from '../core';\n\nexport interface UsePDFRendererReturn {\n /** Ref to attach to the container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Rendered page data (available after loading) */\n pages: PageData[];\n /** Number of pages */\n pageCount: number;\n /** Whether PDF is currently loading */\n loading: boolean;\n /** Current scale value */\n scale: number | 'auto';\n /** Load a PDF source */\n loadPDF: (source: PDFSource) => Promise<PageData[]>;\n /** Set scale and re-render */\n setScale: (scale: number | 'auto') => Promise<PageData[]>;\n /** Zoom in by one step */\n zoomIn: () => Promise<PageData[]>;\n /** Zoom out by one step */\n zoomOut: () => Promise<PageData[]>;\n /** Download the loaded PDF */\n download: (filename?: string) => Promise<void>;\n /** Clean up renderer */\n cleanup: () => void;\n}\n\n/**\n * Hook for rendering PDF into a container div.\n * Returns pages data that can be passed to useSearchController.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF, zoomIn, zoomOut, download } = usePDFRenderer(pdfjsLib);\n *\n * return <div ref={containerRef} style={{ height: '80vh', overflow: 'auto' }} />;\n * ```\n */\nexport function usePDFRenderer(\n pdfjsLib: any,\n options: PDFSearchViewerOptions = {}\n): UsePDFRendererReturn {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rendererRef = useRef<PDFRenderer | null>(null);\n const [pages, setPages] = useState<PageData[]>([]);\n const [pageCount, setPageCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [scale, setScaleState] = useState<number | 'auto'>(options.scale ?? 'auto');\n\n // Init renderer when container is available\n useEffect(() => {\n return () => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n };\n }, []);\n\n // Store options in a ref so getRenderer/loadPDF don't depend on object identity\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const getRenderer = useCallback(() => {\n if (!containerRef.current) throw new Error('Container ref not attached');\n if (!rendererRef.current) {\n const r = new PDFRenderer(containerRef.current, optionsRef.current);\n r.setPdfjsLib(pdfjsLib);\n rendererRef.current = r;\n }\n return rendererRef.current;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n const loadPDF = useCallback(\n async (source: PDFSource): Promise<PageData[]> => {\n const renderer = getRenderer();\n setLoading(true);\n try {\n const count = await renderer.loadDocument(source);\n const p = await renderer.renderAllPages();\n setPages(p);\n setPageCount(count);\n setScaleState(renderer.getScale());\n return p;\n } finally {\n setLoading(false);\n }\n },\n [getRenderer]\n );\n\n const setScale = useCallback(\n async (newScale: number | 'auto'): Promise<PageData[]> => {\n const renderer = getRenderer();\n renderer.setScale(newScale);\n const p = await renderer.renderAllPages();\n setPages(p);\n setScaleState(newScale);\n return p;\n },\n [getRenderer]\n );\n\n const zoomIn = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.min(current + ZOOM_STEP, MAX_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const zoomOut = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.max(current - ZOOM_STEP, MIN_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const download = useCallback(\n async (filename?: string) => {\n const renderer = getRenderer();\n await renderer.download(filename);\n },\n [getRenderer]\n );\n\n const cleanup = useCallback(() => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n setPages([]);\n setPageCount(0);\n }, []);\n\n return {\n containerRef, pages, pageCount, loading, scale,\n loadPDF, setScale, zoomIn, zoomOut, download, cleanup,\n };\n}\n","import { useRef, useEffect, useCallback, useState } from 'react';\nimport { SearchController } from '../core/SearchController';\nimport type { SearchOptions, ClassNames, PageData } from '../core';\n\nexport interface UseSearchControllerReturn {\n /** Run a search query */\n search: (query: string, options?: SearchOptions) => number;\n /** Go to next match */\n next: () => void;\n /** Go to previous match */\n prev: () => void;\n /** Go to specific match index */\n goTo: (index: number) => void;\n /** Clear all highlights */\n clear: () => void;\n /** Current active match index (0-based), -1 if none */\n current: number;\n /** Total number of matches */\n total: number;\n}\n\nexport interface UseSearchControllerOptions {\n classNames?: Pick<ClassNames, 'highlight' | 'activeHighlight'>;\n}\n\n/**\n * Hook for search + highlight logic (headless).\n * Pass pages from usePDFRenderer to connect them.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);\n * const { search, next, prev, current, total } = useSearchController(pages);\n *\n * return (\n * <>\n * <input onChange={e => search(e.target.value)} />\n * <span>{current + 1}/{total}</span>\n * <button onClick={prev}>Prev</button>\n * <button onClick={next}>Next</button>\n * <div ref={containerRef} />\n * </>\n * );\n * ```\n */\nexport function useSearchController(\n pages: PageData[],\n options: UseSearchControllerOptions = {}\n): UseSearchControllerReturn {\n const controllerRef = useRef<SearchController | null>(null);\n const [current, setCurrent] = useState(-1);\n const [total, setTotal] = useState(0);\n\n // Create controller once\n if (!controllerRef.current) {\n controllerRef.current = new SearchController(options);\n }\n\n // Sync onChange callback\n useEffect(() => {\n const ctrl = controllerRef.current!;\n ctrl.onChange = ({ current: c, total: t }) => {\n setCurrent(c);\n setTotal(t);\n };\n return () => {\n ctrl.onChange = null;\n };\n }, []);\n\n // Update pages when they change\n useEffect(() => {\n controllerRef.current!.setPages(pages);\n }, [pages]);\n\n const search = useCallback((query: string, opts?: SearchOptions) => {\n return controllerRef.current!.search(query, opts);\n }, []);\n\n const next = useCallback(() => {\n controllerRef.current!.next();\n }, []);\n\n const prev = useCallback(() => {\n controllerRef.current!.prev();\n }, []);\n\n const goTo = useCallback((index: number) => {\n controllerRef.current!.goTo(index);\n }, []);\n\n const clear = useCallback(() => {\n controllerRef.current!.clear();\n }, []);\n\n return { search, next, prev, goTo, clear, current, total };\n}\n","import {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef,\n type Ref,\n type CSSProperties,\n} from 'react';\nimport {\n PDFSearchViewer as CorePDFSearchViewer,\n type PDFSearchViewerOptions,\n type SearchOptions,\n type PDFSource,\n} from '../core';\n\nexport interface PDFSearchViewerProps {\n /** pdfjs-dist library instance. Must be passed by consumer. */\n pdfjsLib: any;\n\n /** PDF source: URL string, File, ArrayBuffer, or Uint8Array. */\n source?: PDFSource | null;\n\n /** Search query string. Empty/undefined clears the search. */\n searchQuery?: string;\n\n /** Search options. */\n searchOptions?: SearchOptions;\n\n /** Viewer options (applied once on mount). */\n viewerOptions?: PDFSearchViewerOptions;\n\n /** Called when PDF finishes loading. */\n onLoad?: (data: { pageCount: number }) => void;\n\n /** Called when search completes. */\n onSearch?: (data: { query: string; total: number }) => void;\n\n /** Called when active match changes. */\n onMatchChange?: (data: { current: number; total: number }) => void;\n\n /** Called when zoom/scale changes. */\n onZoom?: (data: { scale: number }) => void;\n\n /** Called on error. */\n onError?: (data: { error: Error; context: string }) => void;\n\n /** Additional className for the container div. */\n className?: string;\n\n /** Inline style for the container div. */\n style?: CSSProperties;\n}\n\nexport interface PDFSearchViewerHandle {\n /** Navigate to next match. Returns new index. */\n nextMatch: () => number;\n /** Navigate to previous match. Returns new index. */\n prevMatch: () => number;\n /** Clear all search highlights. */\n clearSearch: () => void;\n /** Get total match count. */\n getMatchCount: () => number;\n /** Get current match index. */\n getCurrentMatchIndex: () => number;\n /** Zoom in by one step. */\n zoomIn: () => Promise<void>;\n /** Zoom out by one step. */\n zoomOut: () => Promise<void>;\n /** Set scale and re-render. */\n setScale: (scale: number | 'auto') => Promise<void>;\n /** Get current scale. */\n getScale: () => number | 'auto';\n /** Download the loaded PDF. */\n download: (filename?: string) => Promise<void>;\n /** Get underlying core instance. */\n getCore: () => CorePDFSearchViewer | null;\n}\n\nexport const PDFSearchViewer = forwardRef(function PDFSearchViewer(\n props: PDFSearchViewerProps,\n ref: Ref<PDFSearchViewerHandle>\n) {\n const {\n pdfjsLib,\n source,\n searchQuery,\n searchOptions,\n viewerOptions,\n onLoad,\n onSearch,\n onMatchChange,\n onZoom,\n onError,\n className,\n style,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const coreRef = useRef<CorePDFSearchViewer | null>(null);\n\n // Store latest callbacks in refs to avoid re-subscribing\n const callbackRefs = useRef({ onLoad, onSearch, onMatchChange, onZoom, onError });\n callbackRefs.current = { onLoad, onSearch, onMatchChange, onZoom, onError };\n\n // Initialize core on mount\n useEffect(() => {\n if (!containerRef.current || !pdfjsLib) return;\n\n const core = new CorePDFSearchViewer(\n containerRef.current,\n pdfjsLib,\n viewerOptions ?? {}\n );\n\n core.on('load', (data) => callbackRefs.current.onLoad?.(data));\n core.on('search', (data) => callbackRefs.current.onSearch?.(data));\n core.on('matchchange', (data) => callbackRefs.current.onMatchChange?.(data));\n core.on('zoom', (data) => callbackRefs.current.onZoom?.(data));\n core.on('error', (data) => callbackRefs.current.onError?.(data));\n\n coreRef.current = core;\n\n return () => {\n core.destroy();\n coreRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n // Load PDF when source changes\n useEffect(() => {\n if (!coreRef.current || !source) return;\n coreRef.current.loadPDF(source).catch(() => {\n // Error already emitted via 'error' event\n });\n }, [source]);\n\n // Run search when query or options change\n useEffect(() => {\n if (!coreRef.current) return;\n\n if (searchQuery && searchQuery.trim().length > 0) {\n coreRef.current.search(searchQuery, searchOptions);\n } else {\n coreRef.current.clearSearch();\n }\n }, [searchQuery, searchOptions]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n nextMatch: () => coreRef.current?.nextMatch() ?? -1,\n prevMatch: () => coreRef.current?.prevMatch() ?? -1,\n clearSearch: () => coreRef.current?.clearSearch(),\n getMatchCount: () => coreRef.current?.getMatchCount() ?? 0,\n getCurrentMatchIndex: () => coreRef.current?.getCurrentMatchIndex() ?? -1,\n zoomIn: async () => { await coreRef.current?.zoomIn(); },\n zoomOut: async () => { await coreRef.current?.zoomOut(); },\n setScale: async (s: number | 'auto') => { await coreRef.current?.setScale(s); },\n getScale: () => coreRef.current?.getScale() ?? 'auto',\n download: async (filename?: string) => { await coreRef.current?.download(filename); },\n getCore: () => coreRef.current,\n }));\n\n return <div ref={containerRef} className={className} style={style} />;\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/hoangnguyen/Desktop/labs/pdf-search-highlight/dist/react/index.cjs","../../src/react/usePDFRenderer.ts","../../src/react/useSearchController.ts","../../src/react/PDFSearchViewer.tsx"],"names":["useRef","useState","useEffect","useCallback","PDFSearchViewer"],"mappings":"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","file":"/Users/hoangnguyen/Desktop/labs/pdf-search-highlight/dist/react/index.cjs","sourcesContent":[null,"import { useRef, useEffect, useCallback, useState } from 'react';\nimport { PDFRenderer } from '../core/PDFRenderer';\nimport { ZOOM_STEP, MIN_SCALE, MAX_SCALE } from '../core/constants';\nimport type { PDFSearchViewerOptions, PageData, PDFSource } from '../core';\n\nexport interface UsePDFRendererReturn {\n /** Ref to attach to the container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Rendered page data (available after loading) */\n pages: PageData[];\n /** Number of pages */\n pageCount: number;\n /** Whether PDF is currently loading */\n loading: boolean;\n /** Current scale value */\n scale: number | 'auto';\n /** Load a PDF source */\n loadPDF: (source: PDFSource) => Promise<PageData[]>;\n /** Set scale and re-render */\n setScale: (scale: number | 'auto') => Promise<PageData[]>;\n /** Zoom in by one step */\n zoomIn: () => Promise<PageData[]>;\n /** Zoom out by one step */\n zoomOut: () => Promise<PageData[]>;\n /** Download the loaded PDF */\n download: (filename?: string) => Promise<void>;\n /** Clean up renderer */\n cleanup: () => void;\n}\n\n/**\n * Hook for rendering PDF into a container div.\n * Returns pages data that can be passed to useSearchController.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF, zoomIn, zoomOut, download } = usePDFRenderer(pdfjsLib);\n *\n * return <div ref={containerRef} style={{ height: '80vh', overflow: 'auto' }} />;\n * ```\n */\nexport function usePDFRenderer(\n pdfjsLib: any,\n options: PDFSearchViewerOptions = {}\n): UsePDFRendererReturn {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rendererRef = useRef<PDFRenderer | null>(null);\n const [pages, setPages] = useState<PageData[]>([]);\n const [pageCount, setPageCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [scale, setScaleState] = useState<number | 'auto'>(options.scale ?? 'auto');\n\n // Init renderer when container is available\n useEffect(() => {\n return () => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n };\n }, []);\n\n // Store options in a ref so getRenderer/loadPDF don't depend on object identity\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const getRenderer = useCallback(() => {\n if (!containerRef.current) throw new Error('Container ref not attached');\n if (!rendererRef.current) {\n const r = new PDFRenderer(containerRef.current, optionsRef.current);\n r.setPdfjsLib(pdfjsLib);\n rendererRef.current = r;\n }\n return rendererRef.current;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n const loadPDF = useCallback(\n async (source: PDFSource): Promise<PageData[]> => {\n const renderer = getRenderer();\n setLoading(true);\n try {\n const count = await renderer.loadDocument(source);\n const p = await renderer.renderAllPages();\n setPages(p);\n setPageCount(count);\n setScaleState(renderer.getScale());\n return p;\n } finally {\n setLoading(false);\n }\n },\n [getRenderer]\n );\n\n const setScale = useCallback(\n async (newScale: number | 'auto'): Promise<PageData[]> => {\n const renderer = getRenderer();\n renderer.setScale(newScale);\n const p = await renderer.renderAllPages();\n setPages(p);\n setScaleState(newScale);\n return p;\n },\n [getRenderer]\n );\n\n const zoomIn = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.min(current + ZOOM_STEP, MAX_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const zoomOut = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.max(current - ZOOM_STEP, MIN_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const download = useCallback(\n async (filename?: string) => {\n const renderer = getRenderer();\n await renderer.download(filename);\n },\n [getRenderer]\n );\n\n const cleanup = useCallback(() => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n setPages([]);\n setPageCount(0);\n }, []);\n\n return {\n containerRef, pages, pageCount, loading, scale,\n loadPDF, setScale, zoomIn, zoomOut, download, cleanup,\n };\n}\n","import { useRef, useEffect, useCallback, useState } from 'react';\nimport { SearchController } from '../core/SearchController';\nimport type { SearchOptions, ClassNames, PageData, SearchContext } from '../core';\n\nexport interface UseSearchControllerReturn {\n /** Run a search query */\n search: (query: string, options?: SearchOptions) => number;\n /** Search multiple contexts with different highlight colors */\n searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;\n /** Go to next match */\n next: () => void;\n /** Go to previous match */\n prev: () => void;\n /** Go to specific match index */\n goTo: (index: number) => void;\n /** Clear all highlights */\n clear: () => void;\n /** Current active match index (0-based), -1 if none */\n current: number;\n /** Total number of matches */\n total: number;\n}\n\nexport interface UseSearchControllerOptions {\n classNames?: Pick<ClassNames, 'highlight' | 'activeHighlight'>;\n}\n\n/**\n * Hook for search + highlight logic (headless).\n * Pass pages from usePDFRenderer to connect them.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);\n * const { search, searchMultiple, next, prev, current, total } = useSearchController(pages);\n *\n * return (\n * <>\n * <input onChange={e => search(e.target.value)} />\n * <span>{current + 1}/{total}</span>\n * <button onClick={prev}>Prev</button>\n * <button onClick={next}>Next</button>\n * <div ref={containerRef} />\n * </>\n * );\n * ```\n */\nexport function useSearchController(\n pages: PageData[],\n options: UseSearchControllerOptions = {}\n): UseSearchControllerReturn {\n const controllerRef = useRef<SearchController | null>(null);\n const [current, setCurrent] = useState(-1);\n const [total, setTotal] = useState(0);\n\n // Create controller once\n if (!controllerRef.current) {\n controllerRef.current = new SearchController(options);\n }\n\n // Sync onChange callback\n useEffect(() => {\n const ctrl = controllerRef.current!;\n ctrl.onChange = ({ current: c, total: t }) => {\n setCurrent(c);\n setTotal(t);\n };\n return () => {\n ctrl.onChange = null;\n };\n }, []);\n\n // Update pages when they change\n useEffect(() => {\n controllerRef.current!.setPages(pages);\n }, [pages]);\n\n const search = useCallback((query: string, opts?: SearchOptions) => {\n return controllerRef.current!.search(query, opts);\n }, []);\n\n const searchMultiple = useCallback(\n (contexts: SearchContext[], opts?: SearchOptions) => {\n return controllerRef.current!.searchMultiple(contexts, opts);\n },\n []\n );\n\n const next = useCallback(() => {\n controllerRef.current!.next();\n }, []);\n\n const prev = useCallback(() => {\n controllerRef.current!.prev();\n }, []);\n\n const goTo = useCallback((index: number) => {\n controllerRef.current!.goTo(index);\n }, []);\n\n const clear = useCallback(() => {\n controllerRef.current!.clear();\n }, []);\n\n return { search, searchMultiple, next, prev, goTo, clear, current, total };\n}\n","import {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef,\n type Ref,\n type CSSProperties,\n} from 'react';\nimport {\n PDFSearchViewer as CorePDFSearchViewer,\n type PDFSearchViewerOptions,\n type SearchOptions,\n type SearchContext,\n type PDFSource,\n} from '../core';\n\nexport interface PDFSearchViewerProps {\n /** pdfjs-dist library instance. Must be passed by consumer. */\n pdfjsLib: any;\n\n /** PDF source: URL string, File, ArrayBuffer, or Uint8Array. */\n source?: PDFSource | null;\n\n /** Search query string. Empty/undefined clears the search. */\n searchQuery?: string;\n\n /** Multiple search contexts (alternative to searchQuery). Each context highlighted with different color. */\n searchContexts?: SearchContext[];\n\n /** Search options. */\n searchOptions?: SearchOptions;\n\n /** Viewer options (applied once on mount). */\n viewerOptions?: PDFSearchViewerOptions;\n\n /** Called when PDF finishes loading. */\n onLoad?: (data: { pageCount: number }) => void;\n\n /** Called when search completes. */\n onSearch?: (data: { query: string; total: number }) => void;\n\n /** Called when multi-context search completes. */\n onSearchMultiple?: (data: { contexts: SearchContext[]; total: number; totalsPerContext: number[] }) => void;\n\n /** Called when active match changes. */\n onMatchChange?: (data: { current: number; total: number }) => void;\n\n /** Called when zoom/scale changes. */\n onZoom?: (data: { scale: number }) => void;\n\n /** Called on error. */\n onError?: (data: { error: Error; context: string }) => void;\n\n /** Additional className for the container div. */\n className?: string;\n\n /** Inline style for the container div. */\n style?: CSSProperties;\n}\n\nexport interface PDFSearchViewerHandle {\n /** Navigate to next match. Returns new index. */\n nextMatch: () => number;\n /** Navigate to previous match. Returns new index. */\n prevMatch: () => number;\n /** Clear all search highlights. */\n clearSearch: () => void;\n /** Search multiple contexts. Returns total match count. */\n searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;\n /** Get total match count. */\n getMatchCount: () => number;\n /** Get current match index. */\n getCurrentMatchIndex: () => number;\n /** Zoom in by one step. */\n zoomIn: () => Promise<void>;\n /** Zoom out by one step. */\n zoomOut: () => Promise<void>;\n /** Set scale and re-render. */\n setScale: (scale: number | 'auto') => Promise<void>;\n /** Get current scale. */\n getScale: () => number | 'auto';\n /** Download the loaded PDF. */\n download: (filename?: string) => Promise<void>;\n /** Get underlying core instance. */\n getCore: () => CorePDFSearchViewer | null;\n}\n\nexport const PDFSearchViewer = forwardRef(function PDFSearchViewer(\n props: PDFSearchViewerProps,\n ref: Ref<PDFSearchViewerHandle>\n) {\n const {\n pdfjsLib,\n source,\n searchQuery,\n searchContexts,\n searchOptions,\n viewerOptions,\n onLoad,\n onSearch,\n onSearchMultiple,\n onMatchChange,\n onZoom,\n onError,\n className,\n style,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const coreRef = useRef<CorePDFSearchViewer | null>(null);\n\n // Store latest callbacks in refs to avoid re-subscribing\n const callbackRefs = useRef({ onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError });\n callbackRefs.current = { onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError };\n\n // Initialize core on mount\n useEffect(() => {\n if (!containerRef.current || !pdfjsLib) return;\n\n const core = new CorePDFSearchViewer(\n containerRef.current,\n pdfjsLib,\n viewerOptions ?? {}\n );\n\n core.on('load', (data) => callbackRefs.current.onLoad?.(data));\n core.on('search', (data) => callbackRefs.current.onSearch?.(data));\n core.on('searchmultiple', (data) => callbackRefs.current.onSearchMultiple?.(data));\n core.on('matchchange', (data) => callbackRefs.current.onMatchChange?.(data));\n core.on('zoom', (data) => callbackRefs.current.onZoom?.(data));\n core.on('error', (data) => callbackRefs.current.onError?.(data));\n\n coreRef.current = core;\n\n return () => {\n core.destroy();\n coreRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n // Load PDF when source changes\n useEffect(() => {\n if (!coreRef.current || !source) return;\n coreRef.current.loadPDF(source).catch(() => {\n // Error already emitted via 'error' event\n });\n }, [source]);\n\n // Run search when query, contexts, or options change\n useEffect(() => {\n if (!coreRef.current) return;\n\n if (searchContexts && searchContexts.length > 0) {\n coreRef.current.searchMultiple(searchContexts, searchOptions);\n } else if (searchQuery && searchQuery.trim().length > 0) {\n coreRef.current.search(searchQuery, searchOptions);\n } else {\n coreRef.current.clearSearch();\n }\n }, [searchQuery, searchContexts, searchOptions]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n nextMatch: () => coreRef.current?.nextMatch() ?? -1,\n prevMatch: () => coreRef.current?.prevMatch() ?? -1,\n clearSearch: () => coreRef.current?.clearSearch(),\n searchMultiple: (contexts: SearchContext[], opts?: SearchOptions) =>\n coreRef.current?.searchMultiple(contexts, opts) ?? 0,\n getMatchCount: () => coreRef.current?.getMatchCount() ?? 0,\n getCurrentMatchIndex: () => coreRef.current?.getCurrentMatchIndex() ?? -1,\n zoomIn: async () => { await coreRef.current?.zoomIn(); },\n zoomOut: async () => { await coreRef.current?.zoomOut(); },\n setScale: async (s: number | 'auto') => { await coreRef.current?.setScale(s); },\n getScale: () => coreRef.current?.getScale() ?? 'auto',\n download: async (filename?: string) => { await coreRef.current?.download(filename); },\n getCore: () => coreRef.current,\n }));\n\n return <div ref={containerRef} className={className} style={style} />;\n});\n"]}
|
package/dist/react/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PageData,
|
|
2
|
-
export {
|
|
1
|
+
import { P as PageData, g as PDFSource, b as PDFSearchViewerOptions, C as ClassNames, S as SearchOptions, a as SearchContext, e as PDFSearchViewer$1 } from '../PDFSearchViewer-DzKHoKTp.cjs';
|
|
2
|
+
export { d as SearchMatch } from '../PDFSearchViewer-DzKHoKTp.cjs';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { CSSProperties } from 'react';
|
|
5
5
|
|
|
@@ -42,6 +42,8 @@ declare function usePDFRenderer(pdfjsLib: any, options?: PDFSearchViewerOptions)
|
|
|
42
42
|
interface UseSearchControllerReturn {
|
|
43
43
|
/** Run a search query */
|
|
44
44
|
search: (query: string, options?: SearchOptions) => number;
|
|
45
|
+
/** Search multiple contexts with different highlight colors */
|
|
46
|
+
searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;
|
|
45
47
|
/** Go to next match */
|
|
46
48
|
next: () => void;
|
|
47
49
|
/** Go to previous match */
|
|
@@ -64,7 +66,7 @@ interface UseSearchControllerOptions {
|
|
|
64
66
|
*
|
|
65
67
|
* ```tsx
|
|
66
68
|
* const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);
|
|
67
|
-
* const { search, next, prev, current, total } = useSearchController(pages);
|
|
69
|
+
* const { search, searchMultiple, next, prev, current, total } = useSearchController(pages);
|
|
68
70
|
*
|
|
69
71
|
* return (
|
|
70
72
|
* <>
|
|
@@ -86,6 +88,8 @@ interface PDFSearchViewerProps {
|
|
|
86
88
|
source?: PDFSource | null;
|
|
87
89
|
/** Search query string. Empty/undefined clears the search. */
|
|
88
90
|
searchQuery?: string;
|
|
91
|
+
/** Multiple search contexts (alternative to searchQuery). Each context highlighted with different color. */
|
|
92
|
+
searchContexts?: SearchContext[];
|
|
89
93
|
/** Search options. */
|
|
90
94
|
searchOptions?: SearchOptions;
|
|
91
95
|
/** Viewer options (applied once on mount). */
|
|
@@ -99,6 +103,12 @@ interface PDFSearchViewerProps {
|
|
|
99
103
|
query: string;
|
|
100
104
|
total: number;
|
|
101
105
|
}) => void;
|
|
106
|
+
/** Called when multi-context search completes. */
|
|
107
|
+
onSearchMultiple?: (data: {
|
|
108
|
+
contexts: SearchContext[];
|
|
109
|
+
total: number;
|
|
110
|
+
totalsPerContext: number[];
|
|
111
|
+
}) => void;
|
|
102
112
|
/** Called when active match changes. */
|
|
103
113
|
onMatchChange?: (data: {
|
|
104
114
|
current: number;
|
|
@@ -125,6 +135,8 @@ interface PDFSearchViewerHandle {
|
|
|
125
135
|
prevMatch: () => number;
|
|
126
136
|
/** Clear all search highlights. */
|
|
127
137
|
clearSearch: () => void;
|
|
138
|
+
/** Search multiple contexts. Returns total match count. */
|
|
139
|
+
searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;
|
|
128
140
|
/** Get total match count. */
|
|
129
141
|
getMatchCount: () => number;
|
|
130
142
|
/** Get current match index. */
|
|
@@ -144,4 +156,4 @@ interface PDFSearchViewerHandle {
|
|
|
144
156
|
}
|
|
145
157
|
declare const PDFSearchViewer: react.ForwardRefExoticComponent<PDFSearchViewerProps & react.RefAttributes<PDFSearchViewerHandle>>;
|
|
146
158
|
|
|
147
|
-
export { ClassNames, PDFSearchViewer, type PDFSearchViewerHandle, PDFSearchViewerOptions, type PDFSearchViewerProps, PDFSource, PageData, SearchOptions, type UsePDFRendererReturn, type UseSearchControllerOptions, type UseSearchControllerReturn, usePDFRenderer, useSearchController };
|
|
159
|
+
export { ClassNames, PDFSearchViewer, type PDFSearchViewerHandle, PDFSearchViewerOptions, type PDFSearchViewerProps, PDFSource, PageData, SearchContext, SearchOptions, type UsePDFRendererReturn, type UseSearchControllerOptions, type UseSearchControllerReturn, usePDFRenderer, useSearchController };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PageData,
|
|
2
|
-
export {
|
|
1
|
+
import { P as PageData, g as PDFSource, b as PDFSearchViewerOptions, C as ClassNames, S as SearchOptions, a as SearchContext, e as PDFSearchViewer$1 } from '../PDFSearchViewer-DzKHoKTp.js';
|
|
2
|
+
export { d as SearchMatch } from '../PDFSearchViewer-DzKHoKTp.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { CSSProperties } from 'react';
|
|
5
5
|
|
|
@@ -42,6 +42,8 @@ declare function usePDFRenderer(pdfjsLib: any, options?: PDFSearchViewerOptions)
|
|
|
42
42
|
interface UseSearchControllerReturn {
|
|
43
43
|
/** Run a search query */
|
|
44
44
|
search: (query: string, options?: SearchOptions) => number;
|
|
45
|
+
/** Search multiple contexts with different highlight colors */
|
|
46
|
+
searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;
|
|
45
47
|
/** Go to next match */
|
|
46
48
|
next: () => void;
|
|
47
49
|
/** Go to previous match */
|
|
@@ -64,7 +66,7 @@ interface UseSearchControllerOptions {
|
|
|
64
66
|
*
|
|
65
67
|
* ```tsx
|
|
66
68
|
* const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);
|
|
67
|
-
* const { search, next, prev, current, total } = useSearchController(pages);
|
|
69
|
+
* const { search, searchMultiple, next, prev, current, total } = useSearchController(pages);
|
|
68
70
|
*
|
|
69
71
|
* return (
|
|
70
72
|
* <>
|
|
@@ -86,6 +88,8 @@ interface PDFSearchViewerProps {
|
|
|
86
88
|
source?: PDFSource | null;
|
|
87
89
|
/** Search query string. Empty/undefined clears the search. */
|
|
88
90
|
searchQuery?: string;
|
|
91
|
+
/** Multiple search contexts (alternative to searchQuery). Each context highlighted with different color. */
|
|
92
|
+
searchContexts?: SearchContext[];
|
|
89
93
|
/** Search options. */
|
|
90
94
|
searchOptions?: SearchOptions;
|
|
91
95
|
/** Viewer options (applied once on mount). */
|
|
@@ -99,6 +103,12 @@ interface PDFSearchViewerProps {
|
|
|
99
103
|
query: string;
|
|
100
104
|
total: number;
|
|
101
105
|
}) => void;
|
|
106
|
+
/** Called when multi-context search completes. */
|
|
107
|
+
onSearchMultiple?: (data: {
|
|
108
|
+
contexts: SearchContext[];
|
|
109
|
+
total: number;
|
|
110
|
+
totalsPerContext: number[];
|
|
111
|
+
}) => void;
|
|
102
112
|
/** Called when active match changes. */
|
|
103
113
|
onMatchChange?: (data: {
|
|
104
114
|
current: number;
|
|
@@ -125,6 +135,8 @@ interface PDFSearchViewerHandle {
|
|
|
125
135
|
prevMatch: () => number;
|
|
126
136
|
/** Clear all search highlights. */
|
|
127
137
|
clearSearch: () => void;
|
|
138
|
+
/** Search multiple contexts. Returns total match count. */
|
|
139
|
+
searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;
|
|
128
140
|
/** Get total match count. */
|
|
129
141
|
getMatchCount: () => number;
|
|
130
142
|
/** Get current match index. */
|
|
@@ -144,4 +156,4 @@ interface PDFSearchViewerHandle {
|
|
|
144
156
|
}
|
|
145
157
|
declare const PDFSearchViewer: react.ForwardRefExoticComponent<PDFSearchViewerProps & react.RefAttributes<PDFSearchViewerHandle>>;
|
|
146
158
|
|
|
147
|
-
export { ClassNames, PDFSearchViewer, type PDFSearchViewerHandle, PDFSearchViewerOptions, type PDFSearchViewerProps, PDFSource, PageData, SearchOptions, type UsePDFRendererReturn, type UseSearchControllerOptions, type UseSearchControllerReturn, usePDFRenderer, useSearchController };
|
|
159
|
+
export { ClassNames, PDFSearchViewer, type PDFSearchViewerHandle, PDFSearchViewerOptions, type PDFSearchViewerProps, PDFSource, PageData, SearchContext, SearchOptions, type UsePDFRendererReturn, type UseSearchControllerOptions, type UseSearchControllerReturn, usePDFRenderer, useSearchController };
|
package/dist/react/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
PDFSearchViewer,
|
|
6
6
|
SearchController,
|
|
7
7
|
ZOOM_STEP
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-XFH7JUDJ.js";
|
|
9
9
|
|
|
10
10
|
// src/react/usePDFRenderer.ts
|
|
11
11
|
import { useRef, useEffect, useCallback, useState } from "react";
|
|
@@ -126,6 +126,12 @@ function useSearchController(pages, options = {}) {
|
|
|
126
126
|
const search = useCallback2((query, opts) => {
|
|
127
127
|
return controllerRef.current.search(query, opts);
|
|
128
128
|
}, []);
|
|
129
|
+
const searchMultiple = useCallback2(
|
|
130
|
+
(contexts, opts) => {
|
|
131
|
+
return controllerRef.current.searchMultiple(contexts, opts);
|
|
132
|
+
},
|
|
133
|
+
[]
|
|
134
|
+
);
|
|
129
135
|
const next = useCallback2(() => {
|
|
130
136
|
controllerRef.current.next();
|
|
131
137
|
}, []);
|
|
@@ -138,7 +144,7 @@ function useSearchController(pages, options = {}) {
|
|
|
138
144
|
const clear = useCallback2(() => {
|
|
139
145
|
controllerRef.current.clear();
|
|
140
146
|
}, []);
|
|
141
|
-
return { search, next, prev, goTo, clear, current, total };
|
|
147
|
+
return { search, searchMultiple, next, prev, goTo, clear, current, total };
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
// src/react/PDFSearchViewer.tsx
|
|
@@ -154,10 +160,12 @@ var PDFSearchViewer2 = forwardRef(function PDFSearchViewer3(props, ref) {
|
|
|
154
160
|
pdfjsLib,
|
|
155
161
|
source,
|
|
156
162
|
searchQuery,
|
|
163
|
+
searchContexts,
|
|
157
164
|
searchOptions,
|
|
158
165
|
viewerOptions,
|
|
159
166
|
onLoad,
|
|
160
167
|
onSearch,
|
|
168
|
+
onSearchMultiple,
|
|
161
169
|
onMatchChange,
|
|
162
170
|
onZoom,
|
|
163
171
|
onError,
|
|
@@ -166,8 +174,8 @@ var PDFSearchViewer2 = forwardRef(function PDFSearchViewer3(props, ref) {
|
|
|
166
174
|
} = props;
|
|
167
175
|
const containerRef = useRef3(null);
|
|
168
176
|
const coreRef = useRef3(null);
|
|
169
|
-
const callbackRefs = useRef3({ onLoad, onSearch, onMatchChange, onZoom, onError });
|
|
170
|
-
callbackRefs.current = { onLoad, onSearch, onMatchChange, onZoom, onError };
|
|
177
|
+
const callbackRefs = useRef3({ onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError });
|
|
178
|
+
callbackRefs.current = { onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError };
|
|
171
179
|
useEffect3(() => {
|
|
172
180
|
if (!containerRef.current || !pdfjsLib) return;
|
|
173
181
|
const core = new PDFSearchViewer(
|
|
@@ -177,6 +185,7 @@ var PDFSearchViewer2 = forwardRef(function PDFSearchViewer3(props, ref) {
|
|
|
177
185
|
);
|
|
178
186
|
core.on("load", (data) => callbackRefs.current.onLoad?.(data));
|
|
179
187
|
core.on("search", (data) => callbackRefs.current.onSearch?.(data));
|
|
188
|
+
core.on("searchmultiple", (data) => callbackRefs.current.onSearchMultiple?.(data));
|
|
180
189
|
core.on("matchchange", (data) => callbackRefs.current.onMatchChange?.(data));
|
|
181
190
|
core.on("zoom", (data) => callbackRefs.current.onZoom?.(data));
|
|
182
191
|
core.on("error", (data) => callbackRefs.current.onError?.(data));
|
|
@@ -193,16 +202,19 @@ var PDFSearchViewer2 = forwardRef(function PDFSearchViewer3(props, ref) {
|
|
|
193
202
|
}, [source]);
|
|
194
203
|
useEffect3(() => {
|
|
195
204
|
if (!coreRef.current) return;
|
|
196
|
-
if (
|
|
205
|
+
if (searchContexts && searchContexts.length > 0) {
|
|
206
|
+
coreRef.current.searchMultiple(searchContexts, searchOptions);
|
|
207
|
+
} else if (searchQuery && searchQuery.trim().length > 0) {
|
|
197
208
|
coreRef.current.search(searchQuery, searchOptions);
|
|
198
209
|
} else {
|
|
199
210
|
coreRef.current.clearSearch();
|
|
200
211
|
}
|
|
201
|
-
}, [searchQuery, searchOptions]);
|
|
212
|
+
}, [searchQuery, searchContexts, searchOptions]);
|
|
202
213
|
useImperativeHandle(ref, () => ({
|
|
203
214
|
nextMatch: () => coreRef.current?.nextMatch() ?? -1,
|
|
204
215
|
prevMatch: () => coreRef.current?.prevMatch() ?? -1,
|
|
205
216
|
clearSearch: () => coreRef.current?.clearSearch(),
|
|
217
|
+
searchMultiple: (contexts, opts) => coreRef.current?.searchMultiple(contexts, opts) ?? 0,
|
|
206
218
|
getMatchCount: () => coreRef.current?.getMatchCount() ?? 0,
|
|
207
219
|
getCurrentMatchIndex: () => coreRef.current?.getCurrentMatchIndex() ?? -1,
|
|
208
220
|
zoomIn: async () => {
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/usePDFRenderer.ts","../../src/react/useSearchController.ts","../../src/react/PDFSearchViewer.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback, useState } from 'react';\nimport { PDFRenderer } from '../core/PDFRenderer';\nimport { ZOOM_STEP, MIN_SCALE, MAX_SCALE } from '../core/constants';\nimport type { PDFSearchViewerOptions, PageData, PDFSource } from '../core';\n\nexport interface UsePDFRendererReturn {\n /** Ref to attach to the container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Rendered page data (available after loading) */\n pages: PageData[];\n /** Number of pages */\n pageCount: number;\n /** Whether PDF is currently loading */\n loading: boolean;\n /** Current scale value */\n scale: number | 'auto';\n /** Load a PDF source */\n loadPDF: (source: PDFSource) => Promise<PageData[]>;\n /** Set scale and re-render */\n setScale: (scale: number | 'auto') => Promise<PageData[]>;\n /** Zoom in by one step */\n zoomIn: () => Promise<PageData[]>;\n /** Zoom out by one step */\n zoomOut: () => Promise<PageData[]>;\n /** Download the loaded PDF */\n download: (filename?: string) => Promise<void>;\n /** Clean up renderer */\n cleanup: () => void;\n}\n\n/**\n * Hook for rendering PDF into a container div.\n * Returns pages data that can be passed to useSearchController.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF, zoomIn, zoomOut, download } = usePDFRenderer(pdfjsLib);\n *\n * return <div ref={containerRef} style={{ height: '80vh', overflow: 'auto' }} />;\n * ```\n */\nexport function usePDFRenderer(\n pdfjsLib: any,\n options: PDFSearchViewerOptions = {}\n): UsePDFRendererReturn {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rendererRef = useRef<PDFRenderer | null>(null);\n const [pages, setPages] = useState<PageData[]>([]);\n const [pageCount, setPageCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [scale, setScaleState] = useState<number | 'auto'>(options.scale ?? 'auto');\n\n // Init renderer when container is available\n useEffect(() => {\n return () => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n };\n }, []);\n\n // Store options in a ref so getRenderer/loadPDF don't depend on object identity\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const getRenderer = useCallback(() => {\n if (!containerRef.current) throw new Error('Container ref not attached');\n if (!rendererRef.current) {\n const r = new PDFRenderer(containerRef.current, optionsRef.current);\n r.setPdfjsLib(pdfjsLib);\n rendererRef.current = r;\n }\n return rendererRef.current;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n const loadPDF = useCallback(\n async (source: PDFSource): Promise<PageData[]> => {\n const renderer = getRenderer();\n setLoading(true);\n try {\n const count = await renderer.loadDocument(source);\n const p = await renderer.renderAllPages();\n setPages(p);\n setPageCount(count);\n setScaleState(renderer.getScale());\n return p;\n } finally {\n setLoading(false);\n }\n },\n [getRenderer]\n );\n\n const setScale = useCallback(\n async (newScale: number | 'auto'): Promise<PageData[]> => {\n const renderer = getRenderer();\n renderer.setScale(newScale);\n const p = await renderer.renderAllPages();\n setPages(p);\n setScaleState(newScale);\n return p;\n },\n [getRenderer]\n );\n\n const zoomIn = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.min(current + ZOOM_STEP, MAX_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const zoomOut = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.max(current - ZOOM_STEP, MIN_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const download = useCallback(\n async (filename?: string) => {\n const renderer = getRenderer();\n await renderer.download(filename);\n },\n [getRenderer]\n );\n\n const cleanup = useCallback(() => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n setPages([]);\n setPageCount(0);\n }, []);\n\n return {\n containerRef, pages, pageCount, loading, scale,\n loadPDF, setScale, zoomIn, zoomOut, download, cleanup,\n };\n}\n","import { useRef, useEffect, useCallback, useState } from 'react';\nimport { SearchController } from '../core/SearchController';\nimport type { SearchOptions, ClassNames, PageData } from '../core';\n\nexport interface UseSearchControllerReturn {\n /** Run a search query */\n search: (query: string, options?: SearchOptions) => number;\n /** Go to next match */\n next: () => void;\n /** Go to previous match */\n prev: () => void;\n /** Go to specific match index */\n goTo: (index: number) => void;\n /** Clear all highlights */\n clear: () => void;\n /** Current active match index (0-based), -1 if none */\n current: number;\n /** Total number of matches */\n total: number;\n}\n\nexport interface UseSearchControllerOptions {\n classNames?: Pick<ClassNames, 'highlight' | 'activeHighlight'>;\n}\n\n/**\n * Hook for search + highlight logic (headless).\n * Pass pages from usePDFRenderer to connect them.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);\n * const { search, next, prev, current, total } = useSearchController(pages);\n *\n * return (\n * <>\n * <input onChange={e => search(e.target.value)} />\n * <span>{current + 1}/{total}</span>\n * <button onClick={prev}>Prev</button>\n * <button onClick={next}>Next</button>\n * <div ref={containerRef} />\n * </>\n * );\n * ```\n */\nexport function useSearchController(\n pages: PageData[],\n options: UseSearchControllerOptions = {}\n): UseSearchControllerReturn {\n const controllerRef = useRef<SearchController | null>(null);\n const [current, setCurrent] = useState(-1);\n const [total, setTotal] = useState(0);\n\n // Create controller once\n if (!controllerRef.current) {\n controllerRef.current = new SearchController(options);\n }\n\n // Sync onChange callback\n useEffect(() => {\n const ctrl = controllerRef.current!;\n ctrl.onChange = ({ current: c, total: t }) => {\n setCurrent(c);\n setTotal(t);\n };\n return () => {\n ctrl.onChange = null;\n };\n }, []);\n\n // Update pages when they change\n useEffect(() => {\n controllerRef.current!.setPages(pages);\n }, [pages]);\n\n const search = useCallback((query: string, opts?: SearchOptions) => {\n return controllerRef.current!.search(query, opts);\n }, []);\n\n const next = useCallback(() => {\n controllerRef.current!.next();\n }, []);\n\n const prev = useCallback(() => {\n controllerRef.current!.prev();\n }, []);\n\n const goTo = useCallback((index: number) => {\n controllerRef.current!.goTo(index);\n }, []);\n\n const clear = useCallback(() => {\n controllerRef.current!.clear();\n }, []);\n\n return { search, next, prev, goTo, clear, current, total };\n}\n","import {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef,\n type Ref,\n type CSSProperties,\n} from 'react';\nimport {\n PDFSearchViewer as CorePDFSearchViewer,\n type PDFSearchViewerOptions,\n type SearchOptions,\n type PDFSource,\n} from '../core';\n\nexport interface PDFSearchViewerProps {\n /** pdfjs-dist library instance. Must be passed by consumer. */\n pdfjsLib: any;\n\n /** PDF source: URL string, File, ArrayBuffer, or Uint8Array. */\n source?: PDFSource | null;\n\n /** Search query string. Empty/undefined clears the search. */\n searchQuery?: string;\n\n /** Search options. */\n searchOptions?: SearchOptions;\n\n /** Viewer options (applied once on mount). */\n viewerOptions?: PDFSearchViewerOptions;\n\n /** Called when PDF finishes loading. */\n onLoad?: (data: { pageCount: number }) => void;\n\n /** Called when search completes. */\n onSearch?: (data: { query: string; total: number }) => void;\n\n /** Called when active match changes. */\n onMatchChange?: (data: { current: number; total: number }) => void;\n\n /** Called when zoom/scale changes. */\n onZoom?: (data: { scale: number }) => void;\n\n /** Called on error. */\n onError?: (data: { error: Error; context: string }) => void;\n\n /** Additional className for the container div. */\n className?: string;\n\n /** Inline style for the container div. */\n style?: CSSProperties;\n}\n\nexport interface PDFSearchViewerHandle {\n /** Navigate to next match. Returns new index. */\n nextMatch: () => number;\n /** Navigate to previous match. Returns new index. */\n prevMatch: () => number;\n /** Clear all search highlights. */\n clearSearch: () => void;\n /** Get total match count. */\n getMatchCount: () => number;\n /** Get current match index. */\n getCurrentMatchIndex: () => number;\n /** Zoom in by one step. */\n zoomIn: () => Promise<void>;\n /** Zoom out by one step. */\n zoomOut: () => Promise<void>;\n /** Set scale and re-render. */\n setScale: (scale: number | 'auto') => Promise<void>;\n /** Get current scale. */\n getScale: () => number | 'auto';\n /** Download the loaded PDF. */\n download: (filename?: string) => Promise<void>;\n /** Get underlying core instance. */\n getCore: () => CorePDFSearchViewer | null;\n}\n\nexport const PDFSearchViewer = forwardRef(function PDFSearchViewer(\n props: PDFSearchViewerProps,\n ref: Ref<PDFSearchViewerHandle>\n) {\n const {\n pdfjsLib,\n source,\n searchQuery,\n searchOptions,\n viewerOptions,\n onLoad,\n onSearch,\n onMatchChange,\n onZoom,\n onError,\n className,\n style,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const coreRef = useRef<CorePDFSearchViewer | null>(null);\n\n // Store latest callbacks in refs to avoid re-subscribing\n const callbackRefs = useRef({ onLoad, onSearch, onMatchChange, onZoom, onError });\n callbackRefs.current = { onLoad, onSearch, onMatchChange, onZoom, onError };\n\n // Initialize core on mount\n useEffect(() => {\n if (!containerRef.current || !pdfjsLib) return;\n\n const core = new CorePDFSearchViewer(\n containerRef.current,\n pdfjsLib,\n viewerOptions ?? {}\n );\n\n core.on('load', (data) => callbackRefs.current.onLoad?.(data));\n core.on('search', (data) => callbackRefs.current.onSearch?.(data));\n core.on('matchchange', (data) => callbackRefs.current.onMatchChange?.(data));\n core.on('zoom', (data) => callbackRefs.current.onZoom?.(data));\n core.on('error', (data) => callbackRefs.current.onError?.(data));\n\n coreRef.current = core;\n\n return () => {\n core.destroy();\n coreRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n // Load PDF when source changes\n useEffect(() => {\n if (!coreRef.current || !source) return;\n coreRef.current.loadPDF(source).catch(() => {\n // Error already emitted via 'error' event\n });\n }, [source]);\n\n // Run search when query or options change\n useEffect(() => {\n if (!coreRef.current) return;\n\n if (searchQuery && searchQuery.trim().length > 0) {\n coreRef.current.search(searchQuery, searchOptions);\n } else {\n coreRef.current.clearSearch();\n }\n }, [searchQuery, searchOptions]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n nextMatch: () => coreRef.current?.nextMatch() ?? -1,\n prevMatch: () => coreRef.current?.prevMatch() ?? -1,\n clearSearch: () => coreRef.current?.clearSearch(),\n getMatchCount: () => coreRef.current?.getMatchCount() ?? 0,\n getCurrentMatchIndex: () => coreRef.current?.getCurrentMatchIndex() ?? -1,\n zoomIn: async () => { await coreRef.current?.zoomIn(); },\n zoomOut: async () => { await coreRef.current?.zoomOut(); },\n setScale: async (s: number | 'auto') => { await coreRef.current?.setScale(s); },\n getScale: () => coreRef.current?.getScale() ?? 'auto',\n download: async (filename?: string) => { await coreRef.current?.download(filename); },\n getCore: () => coreRef.current,\n }));\n\n return <div ref={containerRef} className={className} style={style} />;\n});\n"],"mappings":"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","names":["useRef","useEffect","useCallback","useState","useRef","useState","useEffect","useCallback","useRef","useEffect","PDFSearchViewer","useRef","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/usePDFRenderer.ts","../../src/react/useSearchController.ts","../../src/react/PDFSearchViewer.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback, useState } from 'react';\nimport { PDFRenderer } from '../core/PDFRenderer';\nimport { ZOOM_STEP, MIN_SCALE, MAX_SCALE } from '../core/constants';\nimport type { PDFSearchViewerOptions, PageData, PDFSource } from '../core';\n\nexport interface UsePDFRendererReturn {\n /** Ref to attach to the container div */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Rendered page data (available after loading) */\n pages: PageData[];\n /** Number of pages */\n pageCount: number;\n /** Whether PDF is currently loading */\n loading: boolean;\n /** Current scale value */\n scale: number | 'auto';\n /** Load a PDF source */\n loadPDF: (source: PDFSource) => Promise<PageData[]>;\n /** Set scale and re-render */\n setScale: (scale: number | 'auto') => Promise<PageData[]>;\n /** Zoom in by one step */\n zoomIn: () => Promise<PageData[]>;\n /** Zoom out by one step */\n zoomOut: () => Promise<PageData[]>;\n /** Download the loaded PDF */\n download: (filename?: string) => Promise<void>;\n /** Clean up renderer */\n cleanup: () => void;\n}\n\n/**\n * Hook for rendering PDF into a container div.\n * Returns pages data that can be passed to useSearchController.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF, zoomIn, zoomOut, download } = usePDFRenderer(pdfjsLib);\n *\n * return <div ref={containerRef} style={{ height: '80vh', overflow: 'auto' }} />;\n * ```\n */\nexport function usePDFRenderer(\n pdfjsLib: any,\n options: PDFSearchViewerOptions = {}\n): UsePDFRendererReturn {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rendererRef = useRef<PDFRenderer | null>(null);\n const [pages, setPages] = useState<PageData[]>([]);\n const [pageCount, setPageCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [scale, setScaleState] = useState<number | 'auto'>(options.scale ?? 'auto');\n\n // Init renderer when container is available\n useEffect(() => {\n return () => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n };\n }, []);\n\n // Store options in a ref so getRenderer/loadPDF don't depend on object identity\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const getRenderer = useCallback(() => {\n if (!containerRef.current) throw new Error('Container ref not attached');\n if (!rendererRef.current) {\n const r = new PDFRenderer(containerRef.current, optionsRef.current);\n r.setPdfjsLib(pdfjsLib);\n rendererRef.current = r;\n }\n return rendererRef.current;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n const loadPDF = useCallback(\n async (source: PDFSource): Promise<PageData[]> => {\n const renderer = getRenderer();\n setLoading(true);\n try {\n const count = await renderer.loadDocument(source);\n const p = await renderer.renderAllPages();\n setPages(p);\n setPageCount(count);\n setScaleState(renderer.getScale());\n return p;\n } finally {\n setLoading(false);\n }\n },\n [getRenderer]\n );\n\n const setScale = useCallback(\n async (newScale: number | 'auto'): Promise<PageData[]> => {\n const renderer = getRenderer();\n renderer.setScale(newScale);\n const p = await renderer.renderAllPages();\n setPages(p);\n setScaleState(newScale);\n return p;\n },\n [getRenderer]\n );\n\n const zoomIn = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.min(current + ZOOM_STEP, MAX_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const zoomOut = useCallback(async (): Promise<PageData[]> => {\n const renderer = getRenderer();\n const current = renderer.getScale() === 'auto'\n ? renderer.getEffectiveScale()\n : (renderer.getScale() as number);\n const newScale = Math.max(current - ZOOM_STEP, MIN_SCALE);\n return setScale(newScale);\n }, [getRenderer, setScale]);\n\n const download = useCallback(\n async (filename?: string) => {\n const renderer = getRenderer();\n await renderer.download(filename);\n },\n [getRenderer]\n );\n\n const cleanup = useCallback(() => {\n rendererRef.current?.cleanup();\n rendererRef.current = null;\n setPages([]);\n setPageCount(0);\n }, []);\n\n return {\n containerRef, pages, pageCount, loading, scale,\n loadPDF, setScale, zoomIn, zoomOut, download, cleanup,\n };\n}\n","import { useRef, useEffect, useCallback, useState } from 'react';\nimport { SearchController } from '../core/SearchController';\nimport type { SearchOptions, ClassNames, PageData, SearchContext } from '../core';\n\nexport interface UseSearchControllerReturn {\n /** Run a search query */\n search: (query: string, options?: SearchOptions) => number;\n /** Search multiple contexts with different highlight colors */\n searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;\n /** Go to next match */\n next: () => void;\n /** Go to previous match */\n prev: () => void;\n /** Go to specific match index */\n goTo: (index: number) => void;\n /** Clear all highlights */\n clear: () => void;\n /** Current active match index (0-based), -1 if none */\n current: number;\n /** Total number of matches */\n total: number;\n}\n\nexport interface UseSearchControllerOptions {\n classNames?: Pick<ClassNames, 'highlight' | 'activeHighlight'>;\n}\n\n/**\n * Hook for search + highlight logic (headless).\n * Pass pages from usePDFRenderer to connect them.\n *\n * ```tsx\n * const { containerRef, pages, loadPDF } = usePDFRenderer(pdfjsLib);\n * const { search, searchMultiple, next, prev, current, total } = useSearchController(pages);\n *\n * return (\n * <>\n * <input onChange={e => search(e.target.value)} />\n * <span>{current + 1}/{total}</span>\n * <button onClick={prev}>Prev</button>\n * <button onClick={next}>Next</button>\n * <div ref={containerRef} />\n * </>\n * );\n * ```\n */\nexport function useSearchController(\n pages: PageData[],\n options: UseSearchControllerOptions = {}\n): UseSearchControllerReturn {\n const controllerRef = useRef<SearchController | null>(null);\n const [current, setCurrent] = useState(-1);\n const [total, setTotal] = useState(0);\n\n // Create controller once\n if (!controllerRef.current) {\n controllerRef.current = new SearchController(options);\n }\n\n // Sync onChange callback\n useEffect(() => {\n const ctrl = controllerRef.current!;\n ctrl.onChange = ({ current: c, total: t }) => {\n setCurrent(c);\n setTotal(t);\n };\n return () => {\n ctrl.onChange = null;\n };\n }, []);\n\n // Update pages when they change\n useEffect(() => {\n controllerRef.current!.setPages(pages);\n }, [pages]);\n\n const search = useCallback((query: string, opts?: SearchOptions) => {\n return controllerRef.current!.search(query, opts);\n }, []);\n\n const searchMultiple = useCallback(\n (contexts: SearchContext[], opts?: SearchOptions) => {\n return controllerRef.current!.searchMultiple(contexts, opts);\n },\n []\n );\n\n const next = useCallback(() => {\n controllerRef.current!.next();\n }, []);\n\n const prev = useCallback(() => {\n controllerRef.current!.prev();\n }, []);\n\n const goTo = useCallback((index: number) => {\n controllerRef.current!.goTo(index);\n }, []);\n\n const clear = useCallback(() => {\n controllerRef.current!.clear();\n }, []);\n\n return { search, searchMultiple, next, prev, goTo, clear, current, total };\n}\n","import {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef,\n type Ref,\n type CSSProperties,\n} from 'react';\nimport {\n PDFSearchViewer as CorePDFSearchViewer,\n type PDFSearchViewerOptions,\n type SearchOptions,\n type SearchContext,\n type PDFSource,\n} from '../core';\n\nexport interface PDFSearchViewerProps {\n /** pdfjs-dist library instance. Must be passed by consumer. */\n pdfjsLib: any;\n\n /** PDF source: URL string, File, ArrayBuffer, or Uint8Array. */\n source?: PDFSource | null;\n\n /** Search query string. Empty/undefined clears the search. */\n searchQuery?: string;\n\n /** Multiple search contexts (alternative to searchQuery). Each context highlighted with different color. */\n searchContexts?: SearchContext[];\n\n /** Search options. */\n searchOptions?: SearchOptions;\n\n /** Viewer options (applied once on mount). */\n viewerOptions?: PDFSearchViewerOptions;\n\n /** Called when PDF finishes loading. */\n onLoad?: (data: { pageCount: number }) => void;\n\n /** Called when search completes. */\n onSearch?: (data: { query: string; total: number }) => void;\n\n /** Called when multi-context search completes. */\n onSearchMultiple?: (data: { contexts: SearchContext[]; total: number; totalsPerContext: number[] }) => void;\n\n /** Called when active match changes. */\n onMatchChange?: (data: { current: number; total: number }) => void;\n\n /** Called when zoom/scale changes. */\n onZoom?: (data: { scale: number }) => void;\n\n /** Called on error. */\n onError?: (data: { error: Error; context: string }) => void;\n\n /** Additional className for the container div. */\n className?: string;\n\n /** Inline style for the container div. */\n style?: CSSProperties;\n}\n\nexport interface PDFSearchViewerHandle {\n /** Navigate to next match. Returns new index. */\n nextMatch: () => number;\n /** Navigate to previous match. Returns new index. */\n prevMatch: () => number;\n /** Clear all search highlights. */\n clearSearch: () => void;\n /** Search multiple contexts. Returns total match count. */\n searchMultiple: (contexts: SearchContext[], options?: SearchOptions) => number;\n /** Get total match count. */\n getMatchCount: () => number;\n /** Get current match index. */\n getCurrentMatchIndex: () => number;\n /** Zoom in by one step. */\n zoomIn: () => Promise<void>;\n /** Zoom out by one step. */\n zoomOut: () => Promise<void>;\n /** Set scale and re-render. */\n setScale: (scale: number | 'auto') => Promise<void>;\n /** Get current scale. */\n getScale: () => number | 'auto';\n /** Download the loaded PDF. */\n download: (filename?: string) => Promise<void>;\n /** Get underlying core instance. */\n getCore: () => CorePDFSearchViewer | null;\n}\n\nexport const PDFSearchViewer = forwardRef(function PDFSearchViewer(\n props: PDFSearchViewerProps,\n ref: Ref<PDFSearchViewerHandle>\n) {\n const {\n pdfjsLib,\n source,\n searchQuery,\n searchContexts,\n searchOptions,\n viewerOptions,\n onLoad,\n onSearch,\n onSearchMultiple,\n onMatchChange,\n onZoom,\n onError,\n className,\n style,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const coreRef = useRef<CorePDFSearchViewer | null>(null);\n\n // Store latest callbacks in refs to avoid re-subscribing\n const callbackRefs = useRef({ onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError });\n callbackRefs.current = { onLoad, onSearch, onSearchMultiple, onMatchChange, onZoom, onError };\n\n // Initialize core on mount\n useEffect(() => {\n if (!containerRef.current || !pdfjsLib) return;\n\n const core = new CorePDFSearchViewer(\n containerRef.current,\n pdfjsLib,\n viewerOptions ?? {}\n );\n\n core.on('load', (data) => callbackRefs.current.onLoad?.(data));\n core.on('search', (data) => callbackRefs.current.onSearch?.(data));\n core.on('searchmultiple', (data) => callbackRefs.current.onSearchMultiple?.(data));\n core.on('matchchange', (data) => callbackRefs.current.onMatchChange?.(data));\n core.on('zoom', (data) => callbackRefs.current.onZoom?.(data));\n core.on('error', (data) => callbackRefs.current.onError?.(data));\n\n coreRef.current = core;\n\n return () => {\n core.destroy();\n coreRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pdfjsLib]);\n\n // Load PDF when source changes\n useEffect(() => {\n if (!coreRef.current || !source) return;\n coreRef.current.loadPDF(source).catch(() => {\n // Error already emitted via 'error' event\n });\n }, [source]);\n\n // Run search when query, contexts, or options change\n useEffect(() => {\n if (!coreRef.current) return;\n\n if (searchContexts && searchContexts.length > 0) {\n coreRef.current.searchMultiple(searchContexts, searchOptions);\n } else if (searchQuery && searchQuery.trim().length > 0) {\n coreRef.current.search(searchQuery, searchOptions);\n } else {\n coreRef.current.clearSearch();\n }\n }, [searchQuery, searchContexts, searchOptions]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n nextMatch: () => coreRef.current?.nextMatch() ?? -1,\n prevMatch: () => coreRef.current?.prevMatch() ?? -1,\n clearSearch: () => coreRef.current?.clearSearch(),\n searchMultiple: (contexts: SearchContext[], opts?: SearchOptions) =>\n coreRef.current?.searchMultiple(contexts, opts) ?? 0,\n getMatchCount: () => coreRef.current?.getMatchCount() ?? 0,\n getCurrentMatchIndex: () => coreRef.current?.getCurrentMatchIndex() ?? -1,\n zoomIn: async () => { await coreRef.current?.zoomIn(); },\n zoomOut: async () => { await coreRef.current?.zoomOut(); },\n setScale: async (s: number | 'auto') => { await coreRef.current?.setScale(s); },\n getScale: () => coreRef.current?.getScale() ?? 'auto',\n download: async (filename?: string) => { await coreRef.current?.download(filename); },\n getCore: () => coreRef.current,\n }));\n\n return <div ref={containerRef} className={className} style={style} />;\n});\n"],"mappings":";;;;;;;;;;AAAA,SAAS,QAAQ,WAAW,aAAa,gBAAgB;AAwClD,SAAS,eACd,UACA,UAAkC,CAAC,GACb;AACtB,QAAM,eAAe,OAA8B,IAAI;AACvD,QAAM,cAAc,OAA2B,IAAI;AACnD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAqB,CAAC,CAAC;AACjD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,CAAC;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,aAAa,IAAI,SAA0B,QAAQ,SAAS,MAAM;AAGhF,YAAU,MAAM;AACd,WAAO,MAAM;AACX,kBAAY,SAAS,QAAQ;AAC7B,kBAAY,UAAU;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI,CAAC,aAAa,QAAS,OAAM,IAAI,MAAM,4BAA4B;AACvE,QAAI,CAAC,YAAY,SAAS;AACxB,YAAM,IAAI,IAAI,YAAY,aAAa,SAAS,WAAW,OAAO;AAClE,QAAE,YAAY,QAAQ;AACtB,kBAAY,UAAU;AAAA,IACxB;AACA,WAAO,YAAY;AAAA,EAErB,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,UAAU;AAAA,IACd,OAAO,WAA2C;AAChD,YAAM,WAAW,YAAY;AAC7B,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,QAAQ,MAAM,SAAS,aAAa,MAAM;AAChD,cAAM,IAAI,MAAM,SAAS,eAAe;AACxC,iBAAS,CAAC;AACV,qBAAa,KAAK;AAClB,sBAAc,SAAS,SAAS,CAAC;AACjC,eAAO;AAAA,MACT,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,WAAW;AAAA,IACf,OAAO,aAAmD;AACxD,YAAM,WAAW,YAAY;AAC7B,eAAS,SAAS,QAAQ;AAC1B,YAAM,IAAI,MAAM,SAAS,eAAe;AACxC,eAAS,CAAC;AACV,oBAAc,QAAQ;AACtB,aAAO;AAAA,IACT;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,SAAS,YAAY,YAAiC;AAC1D,UAAM,WAAW,YAAY;AAC7B,UAAM,UAAU,SAAS,SAAS,MAAM,SACpC,SAAS,kBAAkB,IAC1B,SAAS,SAAS;AACvB,UAAM,WAAW,KAAK,IAAI,UAAU,WAAW,SAAS;AACxD,WAAO,SAAS,QAAQ;AAAA,EAC1B,GAAG,CAAC,aAAa,QAAQ,CAAC;AAE1B,QAAM,UAAU,YAAY,YAAiC;AAC3D,UAAM,WAAW,YAAY;AAC7B,UAAM,UAAU,SAAS,SAAS,MAAM,SACpC,SAAS,kBAAkB,IAC1B,SAAS,SAAS;AACvB,UAAM,WAAW,KAAK,IAAI,UAAU,WAAW,SAAS;AACxD,WAAO,SAAS,QAAQ;AAAA,EAC1B,GAAG,CAAC,aAAa,QAAQ,CAAC;AAE1B,QAAM,WAAW;AAAA,IACf,OAAO,aAAsB;AAC3B,YAAM,WAAW,YAAY;AAC7B,YAAM,SAAS,SAAS,QAAQ;AAAA,IAClC;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,UAAU,YAAY,MAAM;AAChC,gBAAY,SAAS,QAAQ;AAC7B,gBAAY,UAAU;AACtB,aAAS,CAAC,CAAC;AACX,iBAAa,CAAC;AAAA,EAChB,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IAAc;AAAA,IAAO;AAAA,IAAW;AAAA,IAAS;AAAA,IACzC;AAAA,IAAS;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAU;AAAA,EAChD;AACF;;;AC7IA,SAAS,UAAAA,SAAQ,aAAAC,YAAW,eAAAC,cAAa,YAAAC,iBAAgB;AA8ClD,SAAS,oBACd,OACA,UAAsC,CAAC,GACZ;AAC3B,QAAM,gBAAgBC,QAAgC,IAAI;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,EAAE;AACzC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,CAAC;AAGpC,MAAI,CAAC,cAAc,SAAS;AAC1B,kBAAc,UAAU,IAAI,iBAAiB,OAAO;AAAA,EACtD;AAGA,EAAAC,WAAU,MAAM;AACd,UAAM,OAAO,cAAc;AAC3B,SAAK,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,EAAE,MAAM;AAC5C,iBAAW,CAAC;AACZ,eAAS,CAAC;AAAA,IACZ;AACA,WAAO,MAAM;AACX,WAAK,WAAW;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,EAAAA,WAAU,MAAM;AACd,kBAAc,QAAS,SAAS,KAAK;AAAA,EACvC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,SAASC,aAAY,CAAC,OAAe,SAAyB;AAClE,WAAO,cAAc,QAAS,OAAO,OAAO,IAAI;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiBA;AAAA,IACrB,CAAC,UAA2B,SAAyB;AACnD,aAAO,cAAc,QAAS,eAAe,UAAU,IAAI;AAAA,IAC7D;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,OAAOA,aAAY,MAAM;AAC7B,kBAAc,QAAS,KAAK;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,OAAOA,aAAY,MAAM;AAC7B,kBAAc,QAAS,KAAK;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,OAAOA,aAAY,CAAC,UAAkB;AAC1C,kBAAc,QAAS,KAAK,KAAK;AAAA,EACnC,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQA,aAAY,MAAM;AAC9B,kBAAc,QAAS,MAAM;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,QAAQ,gBAAgB,MAAM,MAAM,MAAM,OAAO,SAAS,MAAM;AAC3E;;;ACxGA;AAAA,EACE,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AA4KE;AA5FF,IAAMC,mBAAkB,WAAW,SAASA,iBACjD,OACA,KACA;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,eAAeC,QAAuB,IAAI;AAChD,QAAM,UAAUA,QAAmC,IAAI;AAGvD,QAAM,eAAeA,QAAO,EAAE,QAAQ,UAAU,kBAAkB,eAAe,QAAQ,QAAQ,CAAC;AAClG,eAAa,UAAU,EAAE,QAAQ,UAAU,kBAAkB,eAAe,QAAQ,QAAQ;AAG5F,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,aAAa,WAAW,CAAC,SAAU;AAExC,UAAM,OAAO,IAAI;AAAA,MACf,aAAa;AAAA,MACb;AAAA,MACA,iBAAiB,CAAC;AAAA,IACpB;AAEA,SAAK,GAAG,QAAQ,CAAC,SAAS,aAAa,QAAQ,SAAS,IAAI,CAAC;AAC7D,SAAK,GAAG,UAAU,CAAC,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACjE,SAAK,GAAG,kBAAkB,CAAC,SAAS,aAAa,QAAQ,mBAAmB,IAAI,CAAC;AACjF,SAAK,GAAG,eAAe,CAAC,SAAS,aAAa,QAAQ,gBAAgB,IAAI,CAAC;AAC3E,SAAK,GAAG,QAAQ,CAAC,SAAS,aAAa,QAAQ,SAAS,IAAI,CAAC;AAC7D,SAAK,GAAG,SAAS,CAAC,SAAS,aAAa,QAAQ,UAAU,IAAI,CAAC;AAE/D,YAAQ,UAAU;AAElB,WAAO,MAAM;AACX,WAAK,QAAQ;AACb,cAAQ,UAAU;AAAA,IACpB;AAAA,EAEF,GAAG,CAAC,QAAQ,CAAC;AAGb,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,WAAW,CAAC,OAAQ;AACjC,YAAQ,QAAQ,QAAQ,MAAM,EAAE,MAAM,MAAM;AAAA,IAE5C,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAGX,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,QAAS;AAEtB,QAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,cAAQ,QAAQ,eAAe,gBAAgB,aAAa;AAAA,IAC9D,WAAW,eAAe,YAAY,KAAK,EAAE,SAAS,GAAG;AACvD,cAAQ,QAAQ,OAAO,aAAa,aAAa;AAAA,IACnD,OAAO;AACL,cAAQ,QAAQ,YAAY;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,aAAa,gBAAgB,aAAa,CAAC;AAG/C,sBAAoB,KAAK,OAAO;AAAA,IAC9B,WAAW,MAAM,QAAQ,SAAS,UAAU,KAAK;AAAA,IACjD,WAAW,MAAM,QAAQ,SAAS,UAAU,KAAK;AAAA,IACjD,aAAa,MAAM,QAAQ,SAAS,YAAY;AAAA,IAChD,gBAAgB,CAAC,UAA2B,SAC1C,QAAQ,SAAS,eAAe,UAAU,IAAI,KAAK;AAAA,IACrD,eAAe,MAAM,QAAQ,SAAS,cAAc,KAAK;AAAA,IACzD,sBAAsB,MAAM,QAAQ,SAAS,qBAAqB,KAAK;AAAA,IACvE,QAAQ,YAAY;AAAE,YAAM,QAAQ,SAAS,OAAO;AAAA,IAAG;AAAA,IACvD,SAAS,YAAY;AAAE,YAAM,QAAQ,SAAS,QAAQ;AAAA,IAAG;AAAA,IACzD,UAAU,OAAO,MAAuB;AAAE,YAAM,QAAQ,SAAS,SAAS,CAAC;AAAA,IAAG;AAAA,IAC9E,UAAU,MAAM,QAAQ,SAAS,SAAS,KAAK;AAAA,IAC/C,UAAU,OAAO,aAAsB;AAAE,YAAM,QAAQ,SAAS,SAAS,QAAQ;AAAA,IAAG;AAAA,IACpF,SAAS,MAAM,QAAQ;AAAA,EACzB,EAAE;AAEF,SAAO,oBAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACrE,CAAC;","names":["useRef","useEffect","useCallback","useState","useRef","useState","useEffect","useCallback","useRef","useEffect","PDFSearchViewer","useRef","useEffect"]}
|