@yuntijs/ui
Version:
☁️ Yunti UI - an open-source UI component library for building Cloud Native web apps
180 lines • 7.72 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { LexicalTypeaheadMenuPlugin } from '@lexical/react/LexicalTypeaheadMenuPlugin';
import { ConfigProvider, Tree } from 'antd';
import { COMMAND_PRIORITY_NORMAL } from 'lexical';
import { flatMap } from 'lodash-es';
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { DEFAULT_PUNCTUATION, PRE_TRIGGER_CHARS } from "../../constants";
import { useCheckForMentionMatch } from "../../hooks";
import { CLEAR_HIDE_MENU_TIMEOUT } from "../mention-node";
import { useOptions } from "./hooks";
import { MentionMenu } from "./menu";
import { MentionMenuItem } from "./menu-item";
import { useStyles } from "./style";
import { jsx as _jsx } from "react/jsx-runtime";
export var MentionPickerPlugin = /*#__PURE__*/memo(function (_ref) {
var overlayClassName = _ref.overlayClassName,
triggers = _ref.triggers,
_ref$options = _ref.options,
allOptions = _ref$options === void 0 ? [] : _ref$options,
_ref$allowSpaces = _ref.allowSpaces,
allowSpaces = _ref$allowSpaces === void 0 ? true : _ref$allowSpaces,
_ref$punctuation = _ref.punctuation,
punctuation = _ref$punctuation === void 0 ? DEFAULT_PUNCTUATION : _ref$punctuation,
_ref$preTriggerChars = _ref.preTriggerChars,
preTriggerChars = _ref$preTriggerChars === void 0 ? PRE_TRIGGER_CHARS : _ref$preTriggerChars,
onSelect = _ref.onSelect,
onOpen = _ref.onOpen,
parent = _ref.parent;
var _useStyles = useStyles({}),
cx = _useStyles.cx,
styles = _useStyles.styles;
var _useLexicalComposerCo = useLexicalComposerContext(),
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
editor = _useLexicalComposerCo2[0];
var _useCheckForMentionMa = useCheckForMentionMatch(triggers, {
punctuation: punctuation,
preTriggerChars: preTriggerChars,
allowSpaces: allowSpaces
}),
trigger = _useCheckForMentionMa.trigger,
checkForMentionMatch = _useCheckForMentionMa.checkForMentionMatch;
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2),
queryString = _useState2[0],
setQueryString = _useState2[1];
var _useOptions = useOptions(allOptions, queryString, trigger),
options = _useOptions.options;
var flatOptions = useMemo(function () {
var _flattenTree = function _flattenTree(nodes) {
return flatMap(nodes, function (node) {
return [node].concat(_toConsumableArray(node.children ? _flattenTree(node.children) : []));
});
};
return _flattenTree(options);
}, [options]);
var onSelectOption = useCallback(function (selectedOption, nodeToRemove, closeMenu, matchingString) {
onSelect === null || onSelect === void 0 || onSelect(selectedOption, trigger, queryString);
editor.update(function () {
if (nodeToRemove && selectedOption !== null && selectedOption !== void 0 && selectedOption.key) {
nodeToRemove.remove();
}
if (selectedOption !== null && selectedOption !== void 0 && selectedOption.onSelect) {
selectedOption.onSelect(matchingString);
}
closeMenu();
});
}, [editor, onSelect, queryString, trigger]);
var preSelectedIndex = useRef(0);
var handleDisabledItem = useCallback(function (itemProps) {
var selectedIndex = itemProps.selectedIndex,
setHighlightedIndex = itemProps.setHighlightedIndex;
if (selectedIndex !== null) {
var _flatOptions$selected;
if ((_flatOptions$selected = flatOptions[selectedIndex]) !== null && _flatOptions$selected !== void 0 && _flatOptions$selected.disabled) {
var newIndex = selectedIndex;
// 如果是最后一项,则回到第一项
if (selectedIndex === flatOptions.length - 1) {
newIndex = flatOptions.length === 1 ? null : 0;
// @ts-ignore
setHighlightedIndex(newIndex);
} else if (selectedIndex !== preSelectedIndex.current) {
var _preSelectedIndex$cur;
if (selectedIndex > ((_preSelectedIndex$cur = preSelectedIndex.current) !== null && _preSelectedIndex$cur !== void 0 ? _preSelectedIndex$cur : 0)) {
newIndex++;
} else {
newIndex--;
}
setHighlightedIndex(newIndex);
}
}
preSelectedIndex.current = selectedIndex;
}
}, [flatOptions]);
var renderMenuTree = useCallback(function (itemProps) {
var selectedIndex = itemProps.selectedIndex,
selectOptionAndCleanUp = itemProps.selectOptionAndCleanUp;
handleDisabledItem(itemProps);
return /*#__PURE__*/_jsx(ConfigProvider, {
theme: {
components: {
Tree: {
indentSize: 16,
lineHeight: 32,
titleHeight: 32,
paddingXS: 0,
nodeHoverBg: 'transparent'
}
}
},
children: /*#__PURE__*/_jsx(Tree, {
blockNode: true,
defaultExpandAll: true,
onExpand: function onExpand(_keys, _ref2) {
var nativeEvent = _ref2.nativeEvent;
nativeEvent.stopPropagation();
// 阻止 menu-picker 隐藏
editor.dispatchCommand(CLEAR_HIDE_MENU_TIMEOUT, {});
},
onSelect: function onSelect(_keys, info) {
selectOptionAndCleanUp(info.node);
},
titleRender: function titleRender(option) {
var _flatOptions;
return /*#__PURE__*/_jsx(MentionMenuItem, {
isSelected: ((_flatOptions = flatOptions[selectedIndex]) === null || _flatOptions === void 0 ? void 0 : _flatOptions.value) === option.value,
option: option,
queryString: queryString,
showIcon: !option.isChild
});
},
treeData: options
})
});
}, [handleDisabledItem, options, editor, flatOptions, queryString]);
var renderMenu = useCallback(function (anchorElementRef, itemProps, _matchingString) {
var selectedIndex = itemProps.selectedIndex,
selectOptionAndCleanUp = itemProps.selectOptionAndCleanUp,
setHighlightedIndex = itemProps.setHighlightedIndex;
handleDisabledItem(itemProps);
if (anchorElementRef.current) {
return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/_jsx("div", {
className: cx(styles.menuOverlay, overlayClassName),
role: "menu",
children: options.some(function (o) {
return (o.children || []).length > 0;
}) ? renderMenuTree(itemProps) : /*#__PURE__*/_jsx(MentionMenu, {
onClick: function onClick(index, option) {
if (option.disabled) return;
setHighlightedIndex(index);
selectOptionAndCleanUp(option);
},
onMouseEnter: function onMouseEnter(index, option) {
if (option.disabled) return;
setHighlightedIndex(index);
},
options: options,
queryString: queryString,
selectedIndex: selectedIndex
})
}), anchorElementRef.current);
}
return null;
}, [cx, handleDisabledItem, options, overlayClassName, queryString, renderMenuTree, styles.menuOverlay]);
return /*#__PURE__*/_jsx(LexicalTypeaheadMenuPlugin, {
anchorClassName: styles.anchor
// 优先级要高于 ShiftEnterKeyPlugin
,
commandPriority: COMMAND_PRIORITY_NORMAL,
menuRenderFn: renderMenu,
onOpen: onOpen,
onQueryChange: setQueryString,
onSelectOption: onSelectOption,
options: flatOptions,
parent: parent,
triggerFn: checkForMentionMatch
});
});