UNPKG

@churchapps/apphelper-markdown

Version:
64 lines (63 loc) 3.45 kB
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; } })); }