tiptap: use event-emitter for search result

This commit is contained in:
fantasticit 2022-06-03 19:06:33 +08:00
parent a632181f80
commit 1c4cb792de
2 changed files with 10 additions and 9 deletions

View File

@ -3,6 +3,7 @@ import { Node as ProsemirrorNode } from 'prosemirror-model';
import { EditorState, Plugin, PluginKey } from 'prosemirror-state'; import { EditorState, Plugin, PluginKey } from 'prosemirror-state';
import { Decoration, DecorationSet } from 'prosemirror-view'; import { Decoration, DecorationSet } from 'prosemirror-view';
import scrollIntoView from 'scroll-into-view-if-needed'; import scrollIntoView from 'scroll-into-view-if-needed';
import { Editor } from 'tiptap/core';
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands<ReturnType> { interface Commands<ReturnType> {
@ -203,6 +204,8 @@ const gotoSearchResult = ({ view, tr, searchResults, searchResultCurrentClass, g
return false; return false;
}; };
export const ON_SEARCH_RESULTS = 'ON_SEARCH_RESULTS';
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
export const SearchNReplace = Extension.create<SearchOptions>({ export const SearchNReplace = Extension.create<SearchOptions>({
name: 'search', name: 'search',
@ -225,11 +228,13 @@ export const SearchNReplace = Extension.create<SearchOptions>({
return { return {
setSearchTerm: setSearchTerm:
(searchTerm: string) => (searchTerm: string) =>
({ state, dispatch }) => { ({ state, dispatch, editor }) => {
this.options.searchTerm = searchTerm; this.options.searchTerm = searchTerm;
this.options.results = []; this.options.results = [];
this.options.currentIndex = 0; this.options.currentIndex = 0;
(editor as Editor).eventEmitter.emit(ON_SEARCH_RESULTS);
updateView(state, dispatch); updateView(state, dispatch);
return false; return false;
@ -332,11 +337,7 @@ export const SearchNReplace = Extension.create<SearchOptions>({
searchResultClass searchResultClass
); );
extensionThis.options.results = results; extensionThis.options.results = results;
(extensionThis.editor as Editor).eventEmitter.emit(ON_SEARCH_RESULTS);
if (results.length && searchTerm) {
extensionThis.options.onChange && extensionThis.options.onChange();
}
if (ctx.getMeta('directDecoration')) { if (ctx.getMeta('directDecoration')) {
const { fromPos, toPos, attrs } = ctx.getMeta('directDecoration'); const { fromPos, toPos, attrs } = ctx.getMeta('directDecoration');
decorationsToReturn.push(Decoration.inline(fromPos, toPos, attrs)); decorationsToReturn.push(Decoration.inline(fromPos, toPos, attrs));

View File

@ -5,7 +5,7 @@ import { IsOnMobile } from 'hooks/use-on-mobile';
import { useToggle } from 'hooks/use-toggle'; import { useToggle } from 'hooks/use-toggle';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { Editor } from 'tiptap/core'; import { Editor } from 'tiptap/core';
import { SearchNReplace } from 'tiptap/core/extensions/search'; import { ON_SEARCH_RESULTS, SearchNReplace } from 'tiptap/core/extensions/search';
const { Text } = Typography; const { Text } = Typography;
@ -55,11 +55,11 @@ export const Search: React.FC<{ editor: Editor }> = ({ editor }) => {
setResults(results); setResults(results);
}; };
searchExtension.options.onChange = listener; editor.eventEmitter.on(ON_SEARCH_RESULTS, listener);
return () => { return () => {
if (!searchExtension) return; if (!searchExtension) return;
delete searchExtension.options.onChange; editor.eventEmitter.off(ON_SEARCH_RESULTS, listener);
}; };
}, [editor]); }, [editor]);