@churchapps/apphelper-markdown
Version:
ChurchApps markdown/lexical editor components
64 lines (63 loc) • 3.45 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { LexicalTypeaheadMenuPlugin, useBasicTypeaheadTriggerMatch, } from '@lexical/react/LexicalTypeaheadMenuPlugin';
import { $getSelection, $isRangeSelection, } from 'lexical';
import { $createEmojiNode } from './EmojiNode';
import materialIcons from '../../IconNamesList';
import { useCallback, useMemo, useState } from 'react';
import * as ReactDOM from 'react-dom';
function EmojiMenuItem({ index, isSelected, onClick, onMouseEnter, option, }) {
let className = 'item';
if (isSelected) {
className += ' selected';
}
return (_jsx("li", { tabIndex: -1, className: className, role: "option", "aria-selected": isSelected, id: 'typeahead-item-' + index, onMouseEnter: onMouseEnter, onClick: onClick, children: _jsxs("span", { className: "text", children: [_jsx("span", { className: "material-symbols-outlined", children: option }), " ", option] }) }, option));
}
const MAX_EMOJI_SUGGESTION_COUNT = 10;
export default function EmojiPickerPlugin() {
const [editor] = useLexicalComposerContext();
const [queryString, setQueryString] = useState(null);
const checkForTriggerMatch = useBasicTypeaheadTriggerMatch(':', {
minLength: 0,
});
const options = useMemo(() => {
let result = materialIcons.filter((option) => (queryString != null) ? new RegExp(queryString, 'gi').exec(option) : materialIcons);
return result.slice(0, MAX_EMOJI_SUGGESTION_COUNT);
}, [queryString]);
const onSelectOption = useCallback((selectedOption, nodeToRemove, closeMenu) => {
editor.update(() => {
const selection = $getSelection();
if (!$isRangeSelection(selection) || selectedOption == null) {
return;
}
if (nodeToRemove) {
nodeToRemove.remove();
}
selection.insertNodes([$createEmojiNode(selectedOption)]);
closeMenu();
});
}, [editor]);
if (typeof document === "undefined") {
return null;
}
return (_jsx(LexicalTypeaheadMenuPlugin, { onQueryChange: setQueryString, onSelectOption: onSelectOption, triggerFn: checkForTriggerMatch, options: options, menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
if (anchorElementRef.current == null || options.length === 0) {
return null;
}
return anchorElementRef.current && options.length
? ReactDOM.createPortal(_jsx("div", { className: "typeahead-popover emoji-menu", children: _jsx("ul", { children: options.map((option, index) => (_jsx("div", { children: _jsx(EmojiMenuItem, { index: index, isSelected: selectedIndex === index, onClick: () => {
setHighlightedIndex(index);
selectOptionAndCleanUp(option);
}, onMouseEnter: () => {
setHighlightedIndex(index);
}, option: option }) }, option))) }) }), anchorElementRef.current)
: null;
} }));
}