@moyarich/console-addon-search 0.0.0-stage → 0.2.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/dist/index.cjs ADDED
@@ -0,0 +1,523 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const consoleCore = require("@moyarich/console-core");
5
+ const jsxRuntime = require("react/jsx-runtime");
6
+ const search$3 = "Console search";
7
+ const searchOutput$3 = "Search output";
8
+ const searchConsoleOutput$3 = "Search console output";
9
+ const caseSensitive$3 = "Case sensitive";
10
+ const wholeWord$3 = "Whole word";
11
+ const regex$3 = "Regex";
12
+ const noMatches$3 = "No matches";
13
+ const matchCount$3 = "{current} of {total} matches";
14
+ const previousResult$3 = "Previous search result";
15
+ const nextResult$3 = "Next search result";
16
+ const previous$3 = "Previous";
17
+ const next$3 = "Next";
18
+ const en = {
19
+ search: search$3,
20
+ searchOutput: searchOutput$3,
21
+ searchConsoleOutput: searchConsoleOutput$3,
22
+ caseSensitive: caseSensitive$3,
23
+ wholeWord: wholeWord$3,
24
+ regex: regex$3,
25
+ noMatches: noMatches$3,
26
+ matchCount: matchCount$3,
27
+ previousResult: previousResult$3,
28
+ nextResult: nextResult$3,
29
+ previous: previous$3,
30
+ next: next$3
31
+ };
32
+ const search$2 = "Buscar en la consola";
33
+ const searchOutput$2 = "Buscar en la salida";
34
+ const searchConsoleOutput$2 = "Buscar en la salida de la consola";
35
+ const caseSensitive$2 = "Distinguir mayúsculas";
36
+ const wholeWord$2 = "Palabra completa";
37
+ const regex$2 = "Expresión regular";
38
+ const noMatches$2 = "Sin resultados";
39
+ const matchCount$2 = "{current} de {total} resultados";
40
+ const previousResult$2 = "Resultado anterior";
41
+ const nextResult$2 = "Resultado siguiente";
42
+ const previous$2 = "Anterior";
43
+ const next$2 = "Siguiente";
44
+ const es = {
45
+ search: search$2,
46
+ searchOutput: searchOutput$2,
47
+ searchConsoleOutput: searchConsoleOutput$2,
48
+ caseSensitive: caseSensitive$2,
49
+ wholeWord: wholeWord$2,
50
+ regex: regex$2,
51
+ noMatches: noMatches$2,
52
+ matchCount: matchCount$2,
53
+ previousResult: previousResult$2,
54
+ nextResult: nextResult$2,
55
+ previous: previous$2,
56
+ next: next$2
57
+ };
58
+ const search$1 = "Recherche dans la console";
59
+ const searchOutput$1 = "Rechercher dans la sortie";
60
+ const searchConsoleOutput$1 = "Rechercher dans la sortie de la console";
61
+ const caseSensitive$1 = "Respecter la casse";
62
+ const wholeWord$1 = "Mot entier";
63
+ const regex$1 = "Expression régulière";
64
+ const noMatches$1 = "Aucun résultat";
65
+ const matchCount$1 = "{current} sur {total} résultats";
66
+ const previousResult$1 = "Résultat précédent";
67
+ const nextResult$1 = "Résultat suivant";
68
+ const previous$1 = "Précédent";
69
+ const next$1 = "Suivant";
70
+ const fr = {
71
+ search: search$1,
72
+ searchOutput: searchOutput$1,
73
+ searchConsoleOutput: searchConsoleOutput$1,
74
+ caseSensitive: caseSensitive$1,
75
+ wholeWord: wholeWord$1,
76
+ regex: regex$1,
77
+ noMatches: noMatches$1,
78
+ matchCount: matchCount$1,
79
+ previousResult: previousResult$1,
80
+ nextResult: nextResult$1,
81
+ previous: previous$1,
82
+ next: next$1
83
+ };
84
+ const search = "Pesquisar no console";
85
+ const searchOutput = "Pesquisar na saída";
86
+ const searchConsoleOutput = "Pesquisar na saída do console";
87
+ const caseSensitive = "Diferenciar maiúsculas de minúsculas";
88
+ const wholeWord = "Palavra inteira";
89
+ const regex = "Expressão regular";
90
+ const noMatches = "Nenhuma correspondência";
91
+ const matchCount = "{current} de {total} correspondências";
92
+ const previousResult = "Resultado anterior";
93
+ const nextResult = "Próximo resultado";
94
+ const previous = "Anterior";
95
+ const next = "Próximo";
96
+ const pt = {
97
+ search,
98
+ searchOutput,
99
+ searchConsoleOutput,
100
+ caseSensitive,
101
+ wholeWord,
102
+ regex,
103
+ noMatches,
104
+ matchCount,
105
+ previousResult,
106
+ nextResult,
107
+ previous,
108
+ next
109
+ };
110
+ const dictionaries = { en, es, fr, pt };
111
+ function resolveAddonMessages(locale = "en", overrides) {
112
+ const tag = locale.replace(/_/g, "-").toLowerCase();
113
+ return {
114
+ ...en,
115
+ ...dictionaries[tag] ?? dictionaries[tag.split("-")[0]] ?? {},
116
+ ...overrides
117
+ };
118
+ }
119
+ function ConsoleSearchControls({
120
+ controller,
121
+ locale = "en",
122
+ translations
123
+ }) {
124
+ const state = react.useSyncExternalStore(
125
+ controller.subscribe,
126
+ controller.getState,
127
+ controller.getState
128
+ );
129
+ const errorId = react.useId();
130
+ const count = state.matches.length;
131
+ const t = resolveAddonMessages(locale, translations);
132
+ const selectFirstMatch = () => {
133
+ const next2 = controller.getState();
134
+ if (next2.matches.length && next2.activeIndex < 0) controller.next();
135
+ };
136
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "console-search-controls", "aria-label": t.search, children: [
137
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "console-search-controls-row", children: [
138
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "console-search-controls-field", children: [
139
+ /* @__PURE__ */ jsxRuntime.jsxs(
140
+ "svg",
141
+ {
142
+ "aria-hidden": "true",
143
+ width: "16",
144
+ height: "16",
145
+ viewBox: "0 0 24 24",
146
+ fill: "none",
147
+ stroke: "currentColor",
148
+ strokeWidth: "1.75",
149
+ children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10.5", cy: "10.5", r: "6.5" }),
151
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m16 16 4 4" })
152
+ ]
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsxRuntime.jsx(
156
+ "input",
157
+ {
158
+ type: "search",
159
+ placeholder: t.searchOutput,
160
+ "aria-invalid": !!state.error,
161
+ "aria-describedby": state.error ? errorId : void 0,
162
+ onKeyDown: (event) => {
163
+ if (event.key === "Enter") {
164
+ event.preventDefault();
165
+ event.stopPropagation();
166
+ if (event.shiftKey) controller.previous();
167
+ else controller.next();
168
+ }
169
+ },
170
+ value: state.query,
171
+ onChange: (event) => {
172
+ controller.setQuery(event.target.value);
173
+ selectFirstMatch();
174
+ },
175
+ "aria-label": t.searchConsoleOutput
176
+ }
177
+ )
178
+ ] }),
179
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "status", "aria-live": "polite", children: !state.query ? "" : count === 0 ? t.noMatches : t.matchCount.replace("{current}", String(state.activeIndex + 1)).replace("{total}", String(count)) }),
180
+ /* @__PURE__ */ jsxRuntime.jsx(
181
+ "button",
182
+ {
183
+ type: "button",
184
+ onClick: () => controller.previous(),
185
+ disabled: !count,
186
+ "aria-label": t.previousResult,
187
+ title: t.previousResult,
188
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "↑" })
189
+ }
190
+ ),
191
+ /* @__PURE__ */ jsxRuntime.jsx(
192
+ "button",
193
+ {
194
+ type: "button",
195
+ onClick: () => controller.next(),
196
+ disabled: !count,
197
+ "aria-label": t.nextResult,
198
+ title: t.nextResult,
199
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "↓" })
200
+ }
201
+ )
202
+ ] }),
203
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "console-search-controls-options", children: [
204
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
205
+ /* @__PURE__ */ jsxRuntime.jsx(
206
+ "input",
207
+ {
208
+ type: "checkbox",
209
+ checked: !!state.options.caseSensitive,
210
+ onChange: (event) => {
211
+ controller.setOptions({
212
+ ...state.options,
213
+ caseSensitive: event.target.checked
214
+ });
215
+ selectFirstMatch();
216
+ }
217
+ }
218
+ ),
219
+ " ",
220
+ t.caseSensitive
221
+ ] }),
222
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
223
+ /* @__PURE__ */ jsxRuntime.jsx(
224
+ "input",
225
+ {
226
+ type: "checkbox",
227
+ checked: !!state.options.wholeWord,
228
+ onChange: (event) => {
229
+ controller.setOptions({
230
+ ...state.options,
231
+ wholeWord: event.target.checked
232
+ });
233
+ selectFirstMatch();
234
+ }
235
+ }
236
+ ),
237
+ " ",
238
+ t.wholeWord
239
+ ] }),
240
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
241
+ /* @__PURE__ */ jsxRuntime.jsx(
242
+ "input",
243
+ {
244
+ type: "checkbox",
245
+ checked: !!state.options.regex,
246
+ onChange: (event) => {
247
+ controller.setOptions({
248
+ ...state.options,
249
+ regex: event.target.checked
250
+ });
251
+ selectFirstMatch();
252
+ }
253
+ }
254
+ ),
255
+ " ",
256
+ t.regex
257
+ ] })
258
+ ] }),
259
+ state.error && /* @__PURE__ */ jsxRuntime.jsx(
260
+ "span",
261
+ {
262
+ className: "console-search-controls-error",
263
+ id: errorId,
264
+ role: "alert",
265
+ children: state.error
266
+ }
267
+ )
268
+ ] });
269
+ }
270
+ function ConsoleSearchHighlight({
271
+ controller,
272
+ index
273
+ }) {
274
+ const state = react.useSyncExternalStore(
275
+ controller.subscribe,
276
+ controller.getState,
277
+ controller.getState
278
+ );
279
+ const matches = state.matches.map((match, matchIndex) => ({ match, matchIndex })).filter(({ match }) => match.index === index);
280
+ if (!matches.length) return null;
281
+ return /* @__PURE__ */ jsxRuntime.jsx(
282
+ "span",
283
+ {
284
+ className: "console-search-matches",
285
+ "aria-label": `${matches.length} matches in this message`,
286
+ children: matches.map(({ match, matchIndex }) => /* @__PURE__ */ jsxRuntime.jsx(
287
+ "mark",
288
+ {
289
+ className: "console-search-highlight",
290
+ "data-active": state.activeIndex === matchIndex ? "" : void 0,
291
+ "aria-label": state.activeIndex === matchIndex ? "Current search match" : "Search match",
292
+ children: match.text || "Zero-width match"
293
+ },
294
+ `${match.start}-${match.end}-${matchIndex}`
295
+ ))
296
+ }
297
+ );
298
+ }
299
+ const CONSOLE_SEARCH_ADDON_ID = "@moyarich/console-addon-search";
300
+ const consoleSearchService = consoleCore.createConsoleServiceToken(
301
+ `${CONSOLE_SEARCH_ADDON_ID}.controller`
302
+ );
303
+ function findConsoleSearchMatches(entries, query, options = {}) {
304
+ if (!query) return { matches: [] };
305
+ let pattern;
306
+ try {
307
+ pattern = new RegExp(
308
+ options.regex ? query : query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
309
+ options.caseSensitive ? "g" : "gi"
310
+ );
311
+ } catch (error) {
312
+ return {
313
+ matches: [],
314
+ error: error instanceof Error ? error.message : "Invalid pattern"
315
+ };
316
+ }
317
+ const matches = [];
318
+ for (const [index, entry] of entries.entries()) {
319
+ pattern.lastIndex = 0;
320
+ let hit;
321
+ while ((hit = pattern.exec(entry.text)) !== null) {
322
+ const before = entry.text[hit.index - 1] ?? "";
323
+ const after = entry.text[hit.index + hit[0].length] ?? "";
324
+ if (!options.wholeWord || !/\w/.test(before) && !/\w/.test(after)) {
325
+ matches.push({
326
+ id: entry.id ?? String(index),
327
+ index,
328
+ text: hit[0],
329
+ start: hit.index,
330
+ end: hit.index + hit[0].length
331
+ });
332
+ }
333
+ if (hit[0].length === 0) pattern.lastIndex++;
334
+ }
335
+ }
336
+ return { matches };
337
+ }
338
+ function valueSearchText(value) {
339
+ if (typeof value === "string") return value;
340
+ if (value instanceof Error) return value.stack || value.message;
341
+ if (typeof value === "object" && value !== null) {
342
+ try {
343
+ return JSON.stringify(value) ?? String(value);
344
+ } catch {
345
+ return String(value);
346
+ }
347
+ }
348
+ return String(value);
349
+ }
350
+ function visibleTerminalText(value) {
351
+ return value.replace(
352
+ new RegExp(String.raw`\x1b\[[0-?]*[ -/]*[@-~]`, "g"),
353
+ ""
354
+ );
355
+ }
356
+ function createConsoleSearchAddon(options = {}) {
357
+ let data;
358
+ let viewport;
359
+ let state = {
360
+ query: "",
361
+ options: {},
362
+ matches: [],
363
+ activeIndex: -1
364
+ };
365
+ const listeners = /* @__PURE__ */ new Set();
366
+ const emit = () => {
367
+ for (const listener of listeners) listener();
368
+ };
369
+ const controller = {
370
+ getState: () => state,
371
+ subscribe(listener) {
372
+ listeners.add(listener);
373
+ return () => {
374
+ listeners.delete(listener);
375
+ };
376
+ },
377
+ setQuery(query) {
378
+ state = { ...state, query };
379
+ controller.refresh();
380
+ },
381
+ setOptions(options2) {
382
+ state = { ...state, options: options2 };
383
+ controller.refresh();
384
+ },
385
+ refresh() {
386
+ const snapshot = data?.getSnapshot();
387
+ const entries = snapshot?.mode === "console" ? snapshot.visible.map((message, index) => ({
388
+ id: message.id ?? `console-${index}`,
389
+ text: [
390
+ message.method,
391
+ message.source,
392
+ ...message.data.map(valueSearchText)
393
+ ].join(" ")
394
+ })) : snapshot?.mode === "terminal" ? snapshot.visible.map((entry, index) => ({
395
+ id: entry.entry.id ?? `terminal-${index}`,
396
+ text: visibleTerminalText(entry.output.data)
397
+ })) : [];
398
+ const result = findConsoleSearchMatches(
399
+ entries,
400
+ state.query,
401
+ state.options
402
+ );
403
+ const activeMatch = state.matches[state.activeIndex];
404
+ const nextIndex = result.matches.findIndex(
405
+ (match) => match.id === activeMatch?.id && match.index === activeMatch.index && match.text === activeMatch.text && match.start === activeMatch.start
406
+ );
407
+ state = {
408
+ ...state,
409
+ ...result,
410
+ error: result.error,
411
+ activeIndex: nextIndex
412
+ };
413
+ emit();
414
+ },
415
+ next() {
416
+ controller.refresh();
417
+ if (!state.matches.length) return void 0;
418
+ const activeIndex = (state.activeIndex + 1) % state.matches.length;
419
+ state = { ...state, activeIndex };
420
+ emit();
421
+ const match = state.matches[activeIndex];
422
+ viewport?.scrollToMessage(match.id);
423
+ return match;
424
+ },
425
+ previous() {
426
+ controller.refresh();
427
+ if (!state.matches.length) return void 0;
428
+ const activeIndex = (state.activeIndex + state.matches.length - 1) % state.matches.length;
429
+ state = { ...state, activeIndex };
430
+ emit();
431
+ const match = state.matches[activeIndex];
432
+ viewport?.scrollToMessage(match.id);
433
+ return match;
434
+ }
435
+ };
436
+ return {
437
+ id: CONSOLE_SEARCH_ADDON_ID,
438
+ controller,
439
+ activate(host) {
440
+ data = host.services.get(consoleCore.consoleServices.data);
441
+ viewport = host.services.get(consoleCore.consoleServices.viewport);
442
+ host.services.provide(consoleSearchService, controller);
443
+ const textHighlightProvider = {
444
+ subscribe: controller.subscribe,
445
+ getSnapshot: controller.getState,
446
+ getRanges(text, context) {
447
+ if (!state.query) return [];
448
+ const matches = findConsoleSearchMatches(
449
+ [{ id: context.id ?? "local", text }],
450
+ state.query,
451
+ state.options
452
+ ).matches;
453
+ const active = state.matches[state.activeIndex];
454
+ return matches.filter((match) => match.end > match.start).map((match, index) => ({
455
+ start: match.start,
456
+ end: match.end,
457
+ active: active?.id === context.id && active?.text === match.text && state.matches.filter(
458
+ (item) => item.id === active?.id && item.text === active?.text
459
+ ).findIndex((item) => item.start === active?.start) === index
460
+ }));
461
+ }
462
+ };
463
+ host.extensions.register(
464
+ consoleCore.consoleExtensionPoints.textHighlightProvider,
465
+ textHighlightProvider,
466
+ { id: CONSOLE_SEARCH_ADDON_ID + ":inline" }
467
+ );
468
+ const highlight = {
469
+ id: CONSOLE_SEARCH_ADDON_ID + ":highlight",
470
+ placement: "badge",
471
+ render: ({ index }) => react.createElement(ConsoleSearchHighlight, { controller, index })
472
+ };
473
+ host.extensions.register(
474
+ consoleCore.consoleExtensionPoints.messageDecoration,
475
+ highlight,
476
+ { id: highlight.id }
477
+ );
478
+ const panel = {
479
+ id: CONSOLE_SEARCH_ADDON_ID + ":controls",
480
+ placement: "before-output",
481
+ render: () => react.createElement(ConsoleSearchControls, { controller, ...options })
482
+ };
483
+ host.extensions.register(consoleCore.consoleExtensionPoints.panelElement, panel, {
484
+ id: panel.id
485
+ });
486
+ for (const shortcut of [
487
+ {
488
+ id: CONSOLE_SEARCH_ADDON_ID + ":next",
489
+ key: "F3",
490
+ onTrigger: () => {
491
+ controller.next();
492
+ }
493
+ },
494
+ {
495
+ id: CONSOLE_SEARCH_ADDON_ID + ":previous",
496
+ key: "F3",
497
+ shiftKey: true,
498
+ onTrigger: () => {
499
+ controller.previous();
500
+ }
501
+ }
502
+ ])
503
+ host.extensions.register(
504
+ consoleCore.consoleExtensionPoints.keyboardShortcut,
505
+ shortcut,
506
+ { id: shortcut.id }
507
+ );
508
+ const subscription = data?.subscribe(() => controller.refresh());
509
+ return () => {
510
+ subscription?.dispose();
511
+ data = void 0;
512
+ viewport = void 0;
513
+ };
514
+ }
515
+ };
516
+ }
517
+ exports.CONSOLE_SEARCH_ADDON_ID = CONSOLE_SEARCH_ADDON_ID;
518
+ exports.ConsoleSearchControls = ConsoleSearchControls;
519
+ exports.ConsoleSearchHighlight = ConsoleSearchHighlight;
520
+ exports.consoleSearchService = consoleSearchService;
521
+ exports.createConsoleSearchAddon = createConsoleSearchAddon;
522
+ exports.findConsoleSearchMatches = findConsoleSearchMatches;
523
+ exports.resolveConsoleSearchMessages = resolveAddonMessages;
@@ -0,0 +1,50 @@
1
+ import type { AddonTranslations } from "./localization.cjs";
2
+ export { resolveAddonMessages as resolveConsoleSearchMessages } from "./localization.cjs";
3
+ export type { AddonTranslations as ConsoleSearchTranslations } from "./localization.cjs";
4
+ export { ConsoleSearchHighlight } from "./components/ConsoleSearchHighlight/ConsoleSearchHighlight.cjs";
5
+ export { ConsoleSearchControls } from "./components/ConsoleSearchControls/ConsoleSearchControls.cjs";
6
+ import { type ConsoleAddon } from "@moyarich/console-core";
7
+ export declare const CONSOLE_SEARCH_ADDON_ID = "@moyarich/console-addon-search";
8
+ export interface ConsoleSearchOptions {
9
+ caseSensitive?: boolean;
10
+ wholeWord?: boolean;
11
+ regex?: boolean;
12
+ }
13
+ export interface ConsoleSearchMatch {
14
+ id: string;
15
+ index: number;
16
+ text: string;
17
+ /** Offset of this occurrence within the searchable text. */
18
+ start: number;
19
+ end: number;
20
+ }
21
+ export interface ConsoleSearchState {
22
+ query: string;
23
+ options: ConsoleSearchOptions;
24
+ matches: readonly ConsoleSearchMatch[];
25
+ activeIndex: number;
26
+ error?: string;
27
+ }
28
+ export interface ConsoleSearchController {
29
+ getState(): ConsoleSearchState;
30
+ subscribe(listener: () => void): () => void;
31
+ setQuery(query: string): void;
32
+ setOptions(options: ConsoleSearchOptions): void;
33
+ refresh(): void;
34
+ next(): ConsoleSearchMatch | undefined;
35
+ previous(): ConsoleSearchMatch | undefined;
36
+ }
37
+ export declare const consoleSearchService: import("@moyarich/console-core").ConsoleServiceToken<ConsoleSearchController>;
38
+ export declare function findConsoleSearchMatches(entries: readonly {
39
+ id?: string;
40
+ text: string;
41
+ }[], query: string, options?: ConsoleSearchOptions): {
42
+ matches: ConsoleSearchMatch[];
43
+ error?: string;
44
+ };
45
+ export declare function createConsoleSearchAddon(options?: {
46
+ locale?: string;
47
+ translations?: AddonTranslations;
48
+ }): ConsoleAddon & {
49
+ controller: ConsoleSearchController;
50
+ };
@@ -0,0 +1,50 @@
1
+ import type { AddonTranslations } from "./localization.js";
2
+ export { resolveAddonMessages as resolveConsoleSearchMessages } from "./localization.js";
3
+ export type { AddonTranslations as ConsoleSearchTranslations } from "./localization.js";
4
+ export { ConsoleSearchHighlight } from "./components/ConsoleSearchHighlight/ConsoleSearchHighlight.js";
5
+ export { ConsoleSearchControls } from "./components/ConsoleSearchControls/ConsoleSearchControls.js";
6
+ import { type ConsoleAddon } from "@moyarich/console-core";
7
+ export declare const CONSOLE_SEARCH_ADDON_ID = "@moyarich/console-addon-search";
8
+ export interface ConsoleSearchOptions {
9
+ caseSensitive?: boolean;
10
+ wholeWord?: boolean;
11
+ regex?: boolean;
12
+ }
13
+ export interface ConsoleSearchMatch {
14
+ id: string;
15
+ index: number;
16
+ text: string;
17
+ /** Offset of this occurrence within the searchable text. */
18
+ start: number;
19
+ end: number;
20
+ }
21
+ export interface ConsoleSearchState {
22
+ query: string;
23
+ options: ConsoleSearchOptions;
24
+ matches: readonly ConsoleSearchMatch[];
25
+ activeIndex: number;
26
+ error?: string;
27
+ }
28
+ export interface ConsoleSearchController {
29
+ getState(): ConsoleSearchState;
30
+ subscribe(listener: () => void): () => void;
31
+ setQuery(query: string): void;
32
+ setOptions(options: ConsoleSearchOptions): void;
33
+ refresh(): void;
34
+ next(): ConsoleSearchMatch | undefined;
35
+ previous(): ConsoleSearchMatch | undefined;
36
+ }
37
+ export declare const consoleSearchService: import("@moyarich/console-core").ConsoleServiceToken<ConsoleSearchController>;
38
+ export declare function findConsoleSearchMatches(entries: readonly {
39
+ id?: string;
40
+ text: string;
41
+ }[], query: string, options?: ConsoleSearchOptions): {
42
+ matches: ConsoleSearchMatch[];
43
+ error?: string;
44
+ };
45
+ export declare function createConsoleSearchAddon(options?: {
46
+ locale?: string;
47
+ translations?: AddonTranslations;
48
+ }): ConsoleAddon & {
49
+ controller: ConsoleSearchController;
50
+ };