chore: Refactoring some editor controls (#5023)
* Refactor EmojiMenu * Refactor CommandMenu to functional component * Remove more direct props, refactor to useEditor * Remove hardcoded IDs * Refactor SelectionToolbar to functional component * fix: Positioning of suggestion menu on long paragraphs
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import FuzzySearch from "fuzzy-search";
|
||||
import gemojies from "gemoji";
|
||||
import React from "react";
|
||||
import CommandMenu, { Props } from "./CommandMenu";
|
||||
import { useEditor } from "./EditorContext";
|
||||
import EmojiMenuItem from "./EmojiMenuItem";
|
||||
import SuggestionsMenu, {
|
||||
Props as SuggestionsMenuProps,
|
||||
} from "./SuggestionsMenu";
|
||||
|
||||
type Emoji = {
|
||||
name: string;
|
||||
@@ -21,19 +24,16 @@ const searcher = new FuzzySearch<{
|
||||
sort: true,
|
||||
});
|
||||
|
||||
class EmojiMenu extends React.PureComponent<
|
||||
Omit<
|
||||
Props<Emoji>,
|
||||
| "renderMenuItem"
|
||||
| "items"
|
||||
| "onLinkToolbarOpen"
|
||||
| "embeds"
|
||||
| "onClearSearch"
|
||||
>
|
||||
> {
|
||||
get items(): Emoji[] {
|
||||
const { search = "" } = this.props;
|
||||
type Props = Omit<
|
||||
SuggestionsMenuProps<Emoji>,
|
||||
"renderMenuItem" | "items" | "onLinkToolbarOpen" | "embeds" | "onClearSearch"
|
||||
>;
|
||||
|
||||
const EmojiMenu = (props: Props) => {
|
||||
const { search = "" } = props;
|
||||
const { view } = useEditor();
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const n = search.toLowerCase();
|
||||
const result = searcher.search(n).map((item) => {
|
||||
const description = item.description;
|
||||
@@ -48,42 +48,37 @@ class EmojiMenu extends React.PureComponent<
|
||||
});
|
||||
|
||||
return result.slice(0, 10);
|
||||
}
|
||||
}, [search]);
|
||||
|
||||
clearSearch = () => {
|
||||
const { state, dispatch } = this.props.view;
|
||||
const clearSearch = React.useCallback(() => {
|
||||
const { state, dispatch } = view;
|
||||
|
||||
// clear search input
|
||||
dispatch(
|
||||
state.tr.insertText(
|
||||
"",
|
||||
state.selection.$from.pos - (this.props.search ?? "").length - 1,
|
||||
state.selection.$from.pos - (props.search ?? "").length - 1,
|
||||
state.selection.to
|
||||
)
|
||||
);
|
||||
};
|
||||
}, [view, props.search]);
|
||||
|
||||
render() {
|
||||
const containerId = "emoji-menu-container";
|
||||
return (
|
||||
<CommandMenu
|
||||
{...this.props}
|
||||
id={containerId}
|
||||
filterable={false}
|
||||
onClearSearch={this.clearSearch}
|
||||
renderMenuItem={(item, _index, options) => (
|
||||
<EmojiMenuItem
|
||||
onClick={options.onClick}
|
||||
selected={options.selected}
|
||||
title={item.description}
|
||||
emoji={item.emoji}
|
||||
containerId={containerId}
|
||||
/>
|
||||
)}
|
||||
items={this.items}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<SuggestionsMenu
|
||||
{...props}
|
||||
filterable={false}
|
||||
onClearSearch={clearSearch}
|
||||
renderMenuItem={(item, _index, options) => (
|
||||
<EmojiMenuItem
|
||||
onClick={options.onClick}
|
||||
selected={options.selected}
|
||||
title={item.description}
|
||||
emoji={item.emoji}
|
||||
/>
|
||||
)}
|
||||
items={items}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmojiMenu;
|
||||
|
||||
Reference in New Issue
Block a user