@embedpdf/plugin-search 1.4.1 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +324 -199
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/actions.d.ts +58 -22
  6. package/dist/lib/index.d.ts +2 -2
  7. package/dist/lib/reducer.d.ts +2 -1
  8. package/dist/lib/search-plugin.d.ts +8 -8
  9. package/dist/lib/types.d.ts +76 -63
  10. package/dist/preact/adapter.d.ts +1 -1
  11. package/dist/preact/index.cjs +1 -1
  12. package/dist/preact/index.cjs.map +1 -1
  13. package/dist/preact/index.js +49 -18
  14. package/dist/preact/index.js.map +1 -1
  15. package/dist/react/adapter.d.ts +1 -1
  16. package/dist/react/index.cjs +1 -1
  17. package/dist/react/index.cjs.map +1 -1
  18. package/dist/react/index.js +49 -18
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/shared/components/search-layer.d.ts +3 -2
  21. package/dist/shared/hooks/use-search.d.ts +4 -4
  22. package/dist/shared-preact/components/search-layer.d.ts +3 -2
  23. package/dist/shared-preact/hooks/use-search.d.ts +4 -4
  24. package/dist/shared-react/components/search-layer.d.ts +3 -2
  25. package/dist/shared-react/hooks/use-search.d.ts +4 -4
  26. package/dist/svelte/components/SearchLayer.svelte.d.ts +4 -3
  27. package/dist/svelte/hooks/use-search.svelte.d.ts +11 -5
  28. package/dist/svelte/index.cjs +1 -1
  29. package/dist/svelte/index.cjs.map +1 -1
  30. package/dist/svelte/index.js +69 -35
  31. package/dist/svelte/index.js.map +1 -1
  32. package/dist/vue/components/search-layer.vue.d.ts +4 -2
  33. package/dist/vue/hooks/use-search.d.ts +9 -64
  34. package/dist/vue/index.cjs +1 -1
  35. package/dist/vue/index.cjs.map +1 -1
  36. package/dist/vue/index.js +77 -32
  37. package/dist/vue/index.js.map +1 -1
  38. package/package.json +5 -7
package/dist/index.js CHANGED
@@ -1,39 +1,149 @@
1
1
  import { BasePlugin, createBehaviorEmitter } from "@embedpdf/core";
2
- import { PdfTaskHelper } from "@embedpdf/models";
3
- const START_SEARCH_SESSION = "START_SEARCH_SESSION";
4
- const STOP_SEARCH_SESSION = "STOP_SEARCH_SESSION";
5
- const SET_SEARCH_FLAGS = "SET_SEARCH_FLAGS";
6
- const SET_SHOW_ALL_RESULTS = "SET_SHOW_ALL_RESULTS";
7
- const START_SEARCH = "START_SEARCH";
8
- const SET_SEARCH_RESULTS = "SET_SEARCH_RESULTS";
9
- const APPEND_SEARCH_RESULTS = "APPEND_SEARCH_RESULTS";
10
- const SET_ACTIVE_RESULT_INDEX = "SET_ACTIVE_RESULT_INDEX";
11
- function startSearchSession() {
12
- return { type: START_SEARCH_SESSION };
2
+ import { PdfErrorCode, PdfTaskHelper } from "@embedpdf/models";
3
+ const INIT_SEARCH_STATE = "SEARCH/INIT_STATE";
4
+ const CLEANUP_SEARCH_STATE = "SEARCH/CLEANUP_STATE";
5
+ const START_SEARCH_SESSION = "SEARCH/START_SEARCH_SESSION";
6
+ const STOP_SEARCH_SESSION = "SEARCH/STOP_SEARCH_SESSION";
7
+ const SET_SEARCH_FLAGS = "SEARCH/SET_SEARCH_FLAGS";
8
+ const SET_SHOW_ALL_RESULTS = "SEARCH/SET_SHOW_ALL_RESULTS";
9
+ const START_SEARCH = "SEARCH/START_SEARCH";
10
+ const SET_SEARCH_RESULTS = "SEARCH/SET_SEARCH_RESULTS";
11
+ const APPEND_SEARCH_RESULTS = "SEARCH/APPEND_SEARCH_RESULTS";
12
+ const SET_ACTIVE_RESULT_INDEX = "SEARCH/SET_ACTIVE_RESULT_INDEX";
13
+ function initSearchState(documentId, state) {
14
+ return { type: INIT_SEARCH_STATE, payload: { documentId, state } };
13
15
  }
14
- function stopSearchSession() {
15
- return { type: STOP_SEARCH_SESSION };
16
+ function cleanupSearchState(documentId) {
17
+ return { type: CLEANUP_SEARCH_STATE, payload: documentId };
16
18
  }
17
- function setSearchFlags(flags) {
18
- return { type: SET_SEARCH_FLAGS, payload: flags };
19
+ function startSearchSession(documentId) {
20
+ return { type: START_SEARCH_SESSION, payload: { documentId } };
19
21
  }
20
- function setShowAllResults(showAll) {
21
- return { type: SET_SHOW_ALL_RESULTS, payload: showAll };
22
+ function stopSearchSession(documentId) {
23
+ return { type: STOP_SEARCH_SESSION, payload: { documentId } };
22
24
  }
23
- function startSearch(query) {
24
- return { type: START_SEARCH, payload: query };
25
+ function setSearchFlags(documentId, flags) {
26
+ return { type: SET_SEARCH_FLAGS, payload: { documentId, flags } };
25
27
  }
26
- function setSearchResults(results, total, activeResultIndex) {
27
- return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };
28
+ function setShowAllResults(documentId, showAll) {
29
+ return { type: SET_SHOW_ALL_RESULTS, payload: { documentId, showAll } };
28
30
  }
29
- function appendSearchResults(results) {
30
- return { type: APPEND_SEARCH_RESULTS, payload: { results } };
31
+ function startSearch(documentId, query) {
32
+ return { type: START_SEARCH, payload: { documentId, query } };
31
33
  }
32
- function setActiveResultIndex(index) {
33
- return { type: SET_ACTIVE_RESULT_INDEX, payload: index };
34
+ function setSearchResults(documentId, results, total, activeResultIndex) {
35
+ return { type: SET_SEARCH_RESULTS, payload: { documentId, results, total, activeResultIndex } };
34
36
  }
37
+ function appendSearchResults(documentId, results) {
38
+ return { type: APPEND_SEARCH_RESULTS, payload: { documentId, results } };
39
+ }
40
+ function setActiveResultIndex(documentId, index) {
41
+ return { type: SET_ACTIVE_RESULT_INDEX, payload: { documentId, index } };
42
+ }
43
+ const initialSearchDocumentState = {
44
+ flags: [],
45
+ results: [],
46
+ total: 0,
47
+ activeResultIndex: -1,
48
+ showAllResults: true,
49
+ query: "",
50
+ loading: false,
51
+ active: false
52
+ };
53
+ const initialState = {
54
+ documents: {}
55
+ };
56
+ const updateDocState = (state, documentId, newDocState) => {
57
+ const oldDocState = state.documents[documentId] || initialSearchDocumentState;
58
+ return {
59
+ ...state,
60
+ documents: {
61
+ ...state.documents,
62
+ [documentId]: {
63
+ ...oldDocState,
64
+ ...newDocState
65
+ }
66
+ }
67
+ };
68
+ };
69
+ const searchReducer = (state = initialState, action) => {
70
+ switch (action.type) {
71
+ case INIT_SEARCH_STATE:
72
+ return {
73
+ ...state,
74
+ documents: {
75
+ ...state.documents,
76
+ [action.payload.documentId]: action.payload.state
77
+ }
78
+ };
79
+ case CLEANUP_SEARCH_STATE: {
80
+ const documentId = action.payload;
81
+ const { [documentId]: removed, ...remaining } = state.documents;
82
+ return {
83
+ ...state,
84
+ documents: remaining
85
+ };
86
+ }
87
+ case START_SEARCH_SESSION:
88
+ return updateDocState(state, action.payload.documentId, { active: true });
89
+ case STOP_SEARCH_SESSION:
90
+ return updateDocState(state, action.payload.documentId, {
91
+ results: [],
92
+ total: 0,
93
+ activeResultIndex: -1,
94
+ query: "",
95
+ loading: false,
96
+ active: false
97
+ });
98
+ case SET_SEARCH_FLAGS:
99
+ return updateDocState(state, action.payload.documentId, { flags: action.payload.flags });
100
+ case SET_SHOW_ALL_RESULTS:
101
+ return updateDocState(state, action.payload.documentId, {
102
+ showAllResults: action.payload.showAll
103
+ });
104
+ case START_SEARCH:
105
+ return updateDocState(state, action.payload.documentId, {
106
+ loading: true,
107
+ query: action.payload.query,
108
+ // clear old results on new search start
109
+ results: [],
110
+ total: 0,
111
+ activeResultIndex: -1
112
+ });
113
+ case APPEND_SEARCH_RESULTS: {
114
+ const { documentId, results } = action.payload;
115
+ const docState = state.documents[documentId];
116
+ if (!docState) return state;
117
+ const newResults = [...docState.results, ...results];
118
+ const firstHitIndex = docState.activeResultIndex === -1 && newResults.length > 0 ? 0 : docState.activeResultIndex;
119
+ return updateDocState(state, documentId, {
120
+ results: newResults,
121
+ total: newResults.length,
122
+ // total-so-far
123
+ activeResultIndex: firstHitIndex,
124
+ // keep loading true until final SET_SEARCH_RESULTS
125
+ loading: true
126
+ });
127
+ }
128
+ case SET_SEARCH_RESULTS: {
129
+ const { documentId, results, total, activeResultIndex } = action.payload;
130
+ return updateDocState(state, documentId, {
131
+ results,
132
+ total,
133
+ activeResultIndex,
134
+ loading: false
135
+ });
136
+ }
137
+ case SET_ACTIVE_RESULT_INDEX:
138
+ return updateDocState(state, action.payload.documentId, {
139
+ activeResultIndex: action.payload.index
140
+ });
141
+ default:
142
+ return state;
143
+ }
144
+ };
35
145
  const _SearchPlugin = class _SearchPlugin extends BasePlugin {
36
- constructor(id, registry) {
146
+ constructor(id, registry, config) {
37
147
  super(id, registry);
38
148
  this.searchStop$ = createBehaviorEmitter();
39
149
  this.searchStart$ = createBehaviorEmitter();
@@ -41,172 +151,250 @@ const _SearchPlugin = class _SearchPlugin extends BasePlugin {
41
151
  this.searchActiveResultChange$ = createBehaviorEmitter();
42
152
  this.searchResultState$ = createBehaviorEmitter();
43
153
  this.searchState$ = createBehaviorEmitter();
44
- this.loader = this.registry.getPlugin("loader").provides();
45
- this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this));
46
- this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this));
154
+ this.currentTask = /* @__PURE__ */ new Map();
155
+ this.pluginConfig = config;
47
156
  }
48
- handleDocumentLoaded(doc) {
49
- this.currentDocument = doc;
50
- if (this.state.active) {
51
- this.startSearchSession();
52
- }
157
+ onDocumentLoadingStarted(documentId) {
158
+ const initialState2 = {
159
+ ...initialSearchDocumentState,
160
+ flags: this.pluginConfig.flags || [],
161
+ showAllResults: this.pluginConfig.showAllResults ?? true
162
+ };
163
+ this.dispatch(initSearchState(documentId, initialState2));
53
164
  }
54
- handleLoaderEvent(event) {
55
- if (event.type === "error" || event.type === "start" && this.currentDocument) {
56
- if (this.state.active) {
57
- this.stopSearchSession();
58
- }
59
- this.currentDocument = void 0;
60
- }
165
+ onDocumentClosed(documentId) {
166
+ this.stopSearchSession(documentId);
167
+ this.dispatch(cleanupSearchState(documentId));
168
+ this.currentTask.delete(documentId);
61
169
  }
62
- async initialize(config) {
63
- this.dispatch(setSearchFlags(config.flags || []));
64
- this.dispatch(
65
- setShowAllResults(config.showAllResults !== void 0 ? config.showAllResults : true)
66
- );
170
+ async initialize() {
67
171
  }
68
- onStoreUpdated(_prevState, newState) {
69
- this.searchResultState$.emit({
70
- results: newState.results,
71
- activeResultIndex: newState.activeResultIndex,
72
- showAllResults: newState.showAllResults,
73
- active: newState.active
74
- });
75
- this.searchState$.emit(newState);
172
+ onStoreUpdated(prevState, newState) {
173
+ for (const documentId in newState.documents) {
174
+ const prevDocState = prevState.documents[documentId];
175
+ const newDocState = newState.documents[documentId];
176
+ if (prevDocState !== newDocState) {
177
+ this.searchState$.emit({ documentId, state: newDocState });
178
+ if (!prevDocState || prevDocState.results !== newDocState.results || prevDocState.activeResultIndex !== newDocState.activeResultIndex || prevDocState.showAllResults !== newDocState.showAllResults || prevDocState.active !== newDocState.active) {
179
+ this.searchResultState$.emit({
180
+ documentId,
181
+ state: {
182
+ results: newDocState.results,
183
+ activeResultIndex: newDocState.activeResultIndex,
184
+ showAllResults: newDocState.showAllResults,
185
+ active: newDocState.active
186
+ }
187
+ });
188
+ }
189
+ }
190
+ }
76
191
  }
77
192
  buildCapability() {
193
+ const getDocId = (documentId) => documentId ?? this.getActiveDocumentId();
194
+ const getDocState = (docId) => {
195
+ const id = getDocId(docId);
196
+ const state = this.state.documents[id];
197
+ if (!state) throw new Error(`Search state not found for document ${id}`);
198
+ return state;
199
+ };
78
200
  return {
79
- startSearch: this.startSearchSession.bind(this),
80
- stopSearch: this.stopSearchSession.bind(this),
81
- searchAllPages: this.searchAllPages.bind(this),
82
- nextResult: this.nextResult.bind(this),
83
- previousResult: this.previousResult.bind(this),
84
- goToResult: this.goToResult.bind(this),
85
- setShowAllResults: (showAll) => this.dispatch(setShowAllResults(showAll)),
86
- getShowAllResults: () => this.state.showAllResults,
201
+ startSearch: (docId) => this.startSearchSession(getDocId(docId)),
202
+ stopSearch: (docId) => this.stopSearchSession(getDocId(docId)),
203
+ searchAllPages: (keyword, docId) => this.searchAllPages(keyword, getDocId(docId)),
204
+ nextResult: (docId) => this.nextResult(getDocId(docId)),
205
+ previousResult: (docId) => this.previousResult(getDocId(docId)),
206
+ goToResult: (index, docId) => this.goToResult(index, getDocId(docId)),
207
+ setShowAllResults: (showAll, docId) => this.dispatch(setShowAllResults(getDocId(docId), showAll)),
208
+ getShowAllResults: (docId) => getDocState(docId).showAllResults,
209
+ getFlags: (docId) => getDocState(docId).flags,
210
+ setFlags: (flags, docId) => this.setFlags(flags, getDocId(docId)),
211
+ getState: (docId) => getDocState(docId),
212
+ forDocument: this.createSearchScope.bind(this),
87
213
  onSearchResult: this.searchResult$.on,
88
214
  onSearchStart: this.searchStart$.on,
89
215
  onSearchStop: this.searchStop$.on,
90
216
  onActiveResultChange: this.searchActiveResultChange$.on,
91
217
  onSearchResultStateChange: this.searchResultState$.on,
92
- onStateChange: this.searchState$.on,
93
- getFlags: () => this.state.flags,
94
- setFlags: (flags) => this.setFlags(flags),
95
- getState: () => this.state
218
+ onStateChange: this.searchState$.on
96
219
  };
97
220
  }
98
- setFlags(flags) {
99
- this.dispatch(setSearchFlags(flags));
100
- if (this.state.active) {
101
- this.searchAllPages(this.state.query, true);
221
+ createSearchScope(documentId) {
222
+ const getDocState = () => {
223
+ const state = this.state.documents[documentId];
224
+ if (!state) throw new Error(`Search state not found for document ${documentId}`);
225
+ return state;
226
+ };
227
+ return {
228
+ startSearch: () => this.startSearchSession(documentId),
229
+ stopSearch: () => this.stopSearchSession(documentId),
230
+ searchAllPages: (keyword) => this.searchAllPages(keyword, documentId),
231
+ nextResult: () => this.nextResult(documentId),
232
+ previousResult: () => this.previousResult(documentId),
233
+ goToResult: (index) => this.goToResult(index, documentId),
234
+ setShowAllResults: (showAll) => this.dispatch(setShowAllResults(documentId, showAll)),
235
+ getShowAllResults: () => getDocState().showAllResults,
236
+ getFlags: () => getDocState().flags,
237
+ setFlags: (flags) => this.setFlags(flags, documentId),
238
+ getState: getDocState,
239
+ onSearchResult: (listener) => this.searchResult$.on((event) => {
240
+ if (event.documentId === documentId) listener(event.results);
241
+ }),
242
+ onSearchStart: (listener) => this.searchStart$.on((event) => {
243
+ if (event.documentId === documentId) listener();
244
+ }),
245
+ onSearchStop: (listener) => this.searchStop$.on((event) => {
246
+ if (event.documentId === documentId) listener();
247
+ }),
248
+ onActiveResultChange: (listener) => this.searchActiveResultChange$.on((event) => {
249
+ if (event.documentId === documentId) listener(event.index);
250
+ }),
251
+ onSearchResultStateChange: (listener) => this.searchResultState$.on((event) => {
252
+ if (event.documentId === documentId) listener(event.state);
253
+ }),
254
+ onStateChange: (listener) => this.searchState$.on((event) => {
255
+ if (event.documentId === documentId) listener(event.state);
256
+ })
257
+ };
258
+ }
259
+ setFlags(flags, documentId) {
260
+ this.dispatch(setSearchFlags(documentId, flags));
261
+ const docState = this.state.documents[documentId];
262
+ if (docState == null ? void 0 : docState.active) {
263
+ this.searchAllPages(docState.query, documentId, true);
102
264
  }
103
265
  }
104
- notifySearchStart() {
105
- this.searchStart$.emit();
266
+ notifySearchStart(documentId) {
267
+ this.searchStart$.emit({ documentId });
106
268
  }
107
- notifySearchStop() {
108
- this.searchStop$.emit();
269
+ notifySearchStop(documentId) {
270
+ this.searchStop$.emit({ documentId });
109
271
  }
110
- notifyActiveResultChange(index) {
111
- this.searchActiveResultChange$.emit(index);
272
+ notifyActiveResultChange(documentId, index) {
273
+ this.searchActiveResultChange$.emit({ documentId, index });
112
274
  }
113
- startSearchSession() {
114
- if (!this.currentDocument) return;
115
- this.dispatch(startSearchSession());
116
- this.notifySearchStart();
275
+ startSearchSession(documentId) {
276
+ const coreDoc = this.getCoreDocument(documentId);
277
+ if (!coreDoc) return;
278
+ this.dispatch(startSearchSession(documentId));
279
+ this.notifySearchStart(documentId);
117
280
  }
118
- stopSearchSession() {
119
- var _a, _b;
120
- if (!this.currentDocument || !this.state.active) return;
121
- try {
122
- (_b = (_a = this.currentTask) == null ? void 0 : _a.abort) == null ? void 0 : _b.call(_a, { type: "abort", code: "cancelled", message: "search stopped" });
123
- } catch {
281
+ stopSearchSession(documentId) {
282
+ var _a;
283
+ const docState = this.state.documents[documentId];
284
+ if (!(docState == null ? void 0 : docState.active)) return;
285
+ const task = this.currentTask.get(documentId);
286
+ if (task) {
287
+ try {
288
+ (_a = task.abort) == null ? void 0 : _a.call(task, { code: PdfErrorCode.Cancelled, message: "search stopped" });
289
+ } catch {
290
+ }
291
+ this.currentTask.delete(documentId);
124
292
  }
125
- this.currentTask = void 0;
126
- this.dispatch(stopSearchSession());
127
- this.notifySearchStop();
293
+ this.dispatch(stopSearchSession(documentId));
294
+ this.notifySearchStop(documentId);
128
295
  }
129
- searchAllPages(keyword, force = false) {
130
- var _a, _b;
296
+ searchAllPages(keyword, documentId, force = false) {
297
+ var _a;
298
+ const docState = this.state.documents[documentId];
299
+ if (!docState) {
300
+ return PdfTaskHelper.reject({
301
+ code: PdfErrorCode.NotFound,
302
+ message: "Search state not initialized"
303
+ });
304
+ }
305
+ const coreDoc = this.getCoreDocument(documentId);
306
+ if (!(coreDoc == null ? void 0 : coreDoc.document)) {
307
+ return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: "Document not loaded" });
308
+ }
131
309
  const trimmedKeyword = keyword.trim();
132
- if (this.state.query === trimmedKeyword && !force) {
310
+ if (docState.query === trimmedKeyword && !force) {
133
311
  return PdfTaskHelper.resolve({
134
- results: this.state.results,
135
- total: this.state.total
312
+ results: docState.results,
313
+ total: docState.total
136
314
  });
137
315
  }
138
- if (this.currentTask) {
316
+ const oldTask = this.currentTask.get(documentId);
317
+ if (oldTask) {
139
318
  try {
140
- (_b = (_a = this.currentTask).abort) == null ? void 0 : _b.call(_a, { type: "abort", code: "superseded", message: "new search" });
319
+ (_a = oldTask.abort) == null ? void 0 : _a.call(oldTask, { code: PdfErrorCode.Cancelled, message: "new search" });
141
320
  } catch {
142
321
  }
143
- this.currentTask = void 0;
322
+ this.currentTask.delete(documentId);
144
323
  }
145
- this.dispatch(startSearch(trimmedKeyword));
146
- if (!trimmedKeyword || !this.currentDocument) {
147
- this.dispatch(setSearchResults([], 0, -1));
324
+ this.dispatch(startSearch(documentId, trimmedKeyword));
325
+ if (!trimmedKeyword) {
326
+ this.dispatch(setSearchResults(documentId, [], 0, -1));
148
327
  return PdfTaskHelper.resolve({
149
328
  results: [],
150
329
  total: 0
151
330
  });
152
331
  }
153
- if (!this.state.active) {
154
- this.startSearchSession();
332
+ if (!docState.active) {
333
+ this.startSearchSession(documentId);
155
334
  }
156
- const task = this.currentTask = this.engine.searchAllPages(
157
- this.currentDocument,
158
- trimmedKeyword,
159
- { flags: this.state.flags }
160
- );
335
+ const task = this.engine.searchAllPages(coreDoc.document, trimmedKeyword, {
336
+ flags: docState.flags
337
+ });
338
+ this.currentTask.set(documentId, task);
161
339
  task.onProgress((p) => {
162
340
  var _a2;
163
341
  if ((_a2 = p == null ? void 0 : p.results) == null ? void 0 : _a2.length) {
164
- this.dispatch(appendSearchResults(p.results));
165
- if (this.state.activeResultIndex === -1) {
166
- this.dispatch(setActiveResultIndex(0));
167
- this.notifyActiveResultChange(0);
342
+ if (this.currentTask.get(documentId) === task) {
343
+ this.dispatch(appendSearchResults(documentId, p.results));
344
+ if (this.state.documents[documentId].activeResultIndex === -1) {
345
+ this.dispatch(setActiveResultIndex(documentId, 0));
346
+ this.notifyActiveResultChange(documentId, 0);
347
+ }
168
348
  }
169
349
  }
170
350
  });
171
351
  task.wait(
172
352
  (results) => {
173
- this.currentTask = void 0;
353
+ this.currentTask.delete(documentId);
174
354
  const activeResultIndex = results.total > 0 ? 0 : -1;
175
- this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));
176
- this.searchResult$.emit(results);
355
+ this.dispatch(
356
+ setSearchResults(documentId, results.results, results.total, activeResultIndex)
357
+ );
358
+ this.searchResult$.emit({ documentId, results });
177
359
  if (results.total > 0) {
178
- this.notifyActiveResultChange(0);
360
+ this.notifyActiveResultChange(documentId, 0);
179
361
  }
180
362
  },
181
363
  (error) => {
182
- this.currentTask = void 0;
183
- console.error("Error during search:", error);
184
- this.dispatch(setSearchResults([], 0, -1));
364
+ var _a2;
365
+ if (((_a2 = error == null ? void 0 : error.reason) == null ? void 0 : _a2.code) !== PdfErrorCode.Cancelled) {
366
+ console.error("Error during search:", error);
367
+ this.dispatch(setSearchResults(documentId, [], 0, -1));
368
+ }
369
+ this.currentTask.delete(documentId);
185
370
  }
186
371
  );
187
372
  return task;
188
373
  }
189
- nextResult() {
190
- if (this.state.results.length === 0) return -1;
191
- const nextIndex = this.state.activeResultIndex >= this.state.results.length - 1 ? 0 : this.state.activeResultIndex + 1;
192
- return this.goToResult(nextIndex);
374
+ nextResult(documentId) {
375
+ const docState = this.state.documents[documentId];
376
+ if (!docState || docState.results.length === 0) return -1;
377
+ const nextIndex = docState.activeResultIndex >= docState.results.length - 1 ? 0 : docState.activeResultIndex + 1;
378
+ return this.goToResult(nextIndex, documentId);
193
379
  }
194
- previousResult() {
195
- if (this.state.results.length === 0) return -1;
196
- const prevIndex = this.state.activeResultIndex <= 0 ? this.state.results.length - 1 : this.state.activeResultIndex - 1;
197
- return this.goToResult(prevIndex);
380
+ previousResult(documentId) {
381
+ const docState = this.state.documents[documentId];
382
+ if (!docState || docState.results.length === 0) return -1;
383
+ const prevIndex = docState.activeResultIndex <= 0 ? docState.results.length - 1 : docState.activeResultIndex - 1;
384
+ return this.goToResult(prevIndex, documentId);
198
385
  }
199
- goToResult(index) {
200
- if (this.state.results.length === 0 || index < 0 || index >= this.state.results.length) {
386
+ goToResult(index, documentId) {
387
+ const docState = this.state.documents[documentId];
388
+ if (!docState || docState.results.length === 0 || index < 0 || index >= docState.results.length) {
201
389
  return -1;
202
390
  }
203
- this.dispatch(setActiveResultIndex(index));
204
- this.notifyActiveResultChange(index);
391
+ this.dispatch(setActiveResultIndex(documentId, index));
392
+ this.notifyActiveResultChange(documentId, index);
205
393
  return index;
206
394
  }
207
395
  async destroy() {
208
- if (this.state.active && this.currentDocument) {
209
- this.stopSearchSession();
396
+ for (const documentId of Object.keys(this.state.documents)) {
397
+ this.stopSearchSession(documentId);
210
398
  }
211
399
  this.searchResult$.clear();
212
400
  this.searchStart$.clear();
@@ -214,6 +402,7 @@ const _SearchPlugin = class _SearchPlugin extends BasePlugin {
214
402
  this.searchActiveResultChange$.clear();
215
403
  this.searchResultState$.clear();
216
404
  this.searchState$.clear();
405
+ super.destroy();
217
406
  }
218
407
  };
219
408
  _SearchPlugin.id = "search";
@@ -224,81 +413,16 @@ const manifest = {
224
413
  name: "Search Plugin",
225
414
  version: "1.0.0",
226
415
  provides: ["search"],
227
- requires: ["loader"],
416
+ requires: [],
228
417
  optional: [],
229
418
  defaultConfig: {
230
419
  enabled: true,
231
420
  flags: []
232
421
  }
233
422
  };
234
- const initialState = {
235
- flags: [],
236
- results: [],
237
- total: 0,
238
- activeResultIndex: -1,
239
- showAllResults: true,
240
- query: "",
241
- loading: false,
242
- active: false
243
- };
244
- const searchReducer = (state = initialState, action) => {
245
- switch (action.type) {
246
- case START_SEARCH_SESSION:
247
- return { ...state, active: true };
248
- case STOP_SEARCH_SESSION:
249
- return {
250
- ...state,
251
- results: [],
252
- total: 0,
253
- activeResultIndex: -1,
254
- query: "",
255
- loading: false,
256
- active: false
257
- };
258
- case SET_SEARCH_FLAGS:
259
- return { ...state, flags: action.payload };
260
- case SET_SHOW_ALL_RESULTS:
261
- return { ...state, showAllResults: action.payload };
262
- case START_SEARCH:
263
- return {
264
- ...state,
265
- loading: true,
266
- query: action.payload,
267
- // clear old results on new search start
268
- results: [],
269
- total: 0,
270
- activeResultIndex: -1
271
- };
272
- case APPEND_SEARCH_RESULTS: {
273
- const newResults = [...state.results, ...action.payload.results];
274
- const firstHitIndex = state.activeResultIndex === -1 && newResults.length > 0 ? 0 : state.activeResultIndex;
275
- return {
276
- ...state,
277
- results: newResults,
278
- total: newResults.length,
279
- // total-so-far
280
- activeResultIndex: firstHitIndex,
281
- // keep loading true until final SET_SEARCH_RESULTS
282
- loading: true
283
- };
284
- }
285
- case SET_SEARCH_RESULTS:
286
- return {
287
- ...state,
288
- results: action.payload.results,
289
- total: action.payload.total,
290
- activeResultIndex: action.payload.activeResultIndex,
291
- loading: false
292
- };
293
- case SET_ACTIVE_RESULT_INDEX:
294
- return { ...state, activeResultIndex: action.payload };
295
- default:
296
- return state;
297
- }
298
- };
299
423
  const SearchPluginPackage = {
300
424
  manifest,
301
- create: (registry) => new SearchPlugin(SEARCH_PLUGIN_ID, registry),
425
+ create: (registry, config) => new SearchPlugin(SEARCH_PLUGIN_ID, registry, config),
302
426
  reducer: searchReducer,
303
427
  initialState
304
428
  };
@@ -306,6 +430,7 @@ export {
306
430
  SEARCH_PLUGIN_ID,
307
431
  SearchPlugin,
308
432
  SearchPluginPackage,
433
+ initialSearchDocumentState,
309
434
  initialState,
310
435
  manifest
311
436
  };