amis-rpc-design/node_modules/rc-mentions/lib/Mentions.js
2023-10-07 19:42:30 +08:00

401 lines
17 KiB
JavaScript

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _classnames = _interopRequireDefault(require("classnames"));
var _rcInput = require("rc-input");
var _rcTextarea = _interopRequireDefault(require("rc-textarea"));
var _toArray = _interopRequireDefault(require("rc-util/lib/Children/toArray"));
var _useMergedState3 = _interopRequireDefault(require("rc-util/lib/hooks/useMergedState"));
var _KeyCode = _interopRequireDefault(require("rc-util/lib/KeyCode"));
var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
var _react = _interopRequireWildcard(require("react"));
var _useEffectState = _interopRequireDefault(require("./hooks/useEffectState"));
var _KeywordTrigger = _interopRequireDefault(require("./KeywordTrigger"));
var _MentionsContext = _interopRequireDefault(require("./MentionsContext"));
var _Option = _interopRequireDefault(require("./Option"));
var _util = require("./util");
var _excluded = ["prefixCls", "className", "style", "prefix", "split", "notFoundContent", "value", "defaultValue", "children", "options", "open", "validateSearch", "filterOption", "onChange", "onKeyDown", "onKeyUp", "onPressEnter", "onSearch", "onSelect", "onFocus", "onBlur", "transitionName", "placement", "direction", "getPopupContainer", "dropdownClassName", "rows"],
_excluded2 = ["suffix", "prefixCls", "classes", "value"];
var InternalMentions = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
var _props$prefixCls = props.prefixCls,
prefixCls = _props$prefixCls === void 0 ? 'rc-mentions' : _props$prefixCls,
className = props.className,
style = props.style,
_props$prefix = props.prefix,
prefix = _props$prefix === void 0 ? '@' : _props$prefix,
_props$split = props.split,
split = _props$split === void 0 ? ' ' : _props$split,
_props$notFoundConten = props.notFoundContent,
notFoundContent = _props$notFoundConten === void 0 ? 'Not Found' : _props$notFoundConten,
value = props.value,
defaultValue = props.defaultValue,
children = props.children,
options = props.options,
open = props.open,
_props$validateSearch = props.validateSearch,
validateSearch = _props$validateSearch === void 0 ? _util.validateSearch : _props$validateSearch,
_props$filterOption = props.filterOption,
filterOption = _props$filterOption === void 0 ? _util.filterOption : _props$filterOption,
onChange = props.onChange,
onKeyDown = props.onKeyDown,
onKeyUp = props.onKeyUp,
onPressEnter = props.onPressEnter,
onSearch = props.onSearch,
onSelect = props.onSelect,
onFocus = props.onFocus,
onBlur = props.onBlur,
transitionName = props.transitionName,
placement = props.placement,
direction = props.direction,
getPopupContainer = props.getPopupContainer,
dropdownClassName = props.dropdownClassName,
_props$rows = props.rows,
rows = _props$rows === void 0 ? 1 : _props$rows,
restProps = (0, _objectWithoutProperties2.default)(props, _excluded);
var mergedPrefix = (0, _react.useMemo)(function () {
return Array.isArray(prefix) ? prefix : [prefix];
}, [prefix]);
// =============================== Refs ===============================
var textareaRef = (0, _react.useRef)(null);
var measureRef = (0, _react.useRef)(null);
var getTextArea = function getTextArea() {
var _textareaRef$current, _textareaRef$current$;
return (_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 ? void 0 : (_textareaRef$current$ = _textareaRef$current.resizableTextArea) === null || _textareaRef$current$ === void 0 ? void 0 : _textareaRef$current$.textArea;
};
_react.default.useImperativeHandle(ref, function () {
var _textareaRef$current4, _textareaRef$current5;
return {
focus: function focus() {
var _textareaRef$current2;
return (_textareaRef$current2 = textareaRef.current) === null || _textareaRef$current2 === void 0 ? void 0 : _textareaRef$current2.focus();
},
blur: function blur() {
var _textareaRef$current3;
return (_textareaRef$current3 = textareaRef.current) === null || _textareaRef$current3 === void 0 ? void 0 : _textareaRef$current3.blur();
},
textarea: (_textareaRef$current4 = textareaRef.current) === null || _textareaRef$current4 === void 0 ? void 0 : (_textareaRef$current5 = _textareaRef$current4.resizableTextArea) === null || _textareaRef$current5 === void 0 ? void 0 : _textareaRef$current5.textArea
};
});
// ============================== State ===============================
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
measuring = _useState2[0],
setMeasuring = _useState2[1];
var _useState3 = (0, _react.useState)(''),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
measureText = _useState4[0],
setMeasureText = _useState4[1];
var _useState5 = (0, _react.useState)(''),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
measurePrefix = _useState6[0],
setMeasurePrefix = _useState6[1];
var _useState7 = (0, _react.useState)(0),
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
measureLocation = _useState8[0],
setMeasureLocation = _useState8[1];
var _useState9 = (0, _react.useState)(0),
_useState10 = (0, _slicedToArray2.default)(_useState9, 2),
activeIndex = _useState10[0],
setActiveIndex = _useState10[1];
var _useState11 = (0, _react.useState)(false),
_useState12 = (0, _slicedToArray2.default)(_useState11, 2),
isFocus = _useState12[0],
setIsFocus = _useState12[1];
// ============================== Value ===============================
var _useMergedState = (0, _useMergedState3.default)('', {
defaultValue: defaultValue,
value: value
}),
_useMergedState2 = (0, _slicedToArray2.default)(_useMergedState, 2),
mergedValue = _useMergedState2[0],
setMergedValue = _useMergedState2[1];
// =============================== Open ===============================
(0, _react.useEffect)(function () {
// Sync measure div top with textarea for rc-trigger usage
if (measuring && measureRef.current) {
measureRef.current.scrollTop = getTextArea().scrollTop;
}
}, [measuring]);
var _React$useMemo = _react.default.useMemo(function () {
if (open) {
if (process.env.NODE_ENV !== 'production') {
(0, _warning.default)(false, '`open` of Mentions is only used for debug usage. Do not use in you production.');
}
for (var i = 0; i < mergedPrefix.length; i += 1) {
var curPrefix = mergedPrefix[i];
var index = mergedValue.lastIndexOf(curPrefix);
if (index >= 0) {
return [true, '', curPrefix, index];
}
}
}
return [measuring, measureText, measurePrefix, measureLocation];
}, [open, measuring, mergedPrefix, mergedValue, measureText, measurePrefix, measureLocation]),
_React$useMemo2 = (0, _slicedToArray2.default)(_React$useMemo, 4),
mergedMeasuring = _React$useMemo2[0],
mergedMeasureText = _React$useMemo2[1],
mergedMeasurePrefix = _React$useMemo2[2],
mergedMeasureLocation = _React$useMemo2[3];
// ============================== Option ==============================
var getOptions = _react.default.useCallback(function (targetMeasureText) {
var list;
if (options && options.length > 0) {
list = options.map(function (item) {
var _item$key;
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, item), {}, {
key: (_item$key = item === null || item === void 0 ? void 0 : item.key) !== null && _item$key !== void 0 ? _item$key : item.value
});
});
} else {
list = (0, _toArray.default)(children).map(function (_ref) {
var optionProps = _ref.props,
key = _ref.key;
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, optionProps), {}, {
label: optionProps.children,
key: key || optionProps.value
});
});
}
return list.filter(function (option) {
/** Return all result if `filterOption` is false. */
if (filterOption === false) {
return true;
}
return filterOption(targetMeasureText, option);
});
}, [children, options, filterOption]);
var mergedOptions = _react.default.useMemo(function () {
return getOptions(mergedMeasureText);
}, [getOptions, mergedMeasureText]);
// ============================= Measure ==============================
// Mark that we will reset input selection to target position when user select option
var onSelectionEffect = (0, _useEffectState.default)();
var startMeasure = function startMeasure(nextMeasureText, nextMeasurePrefix, nextMeasureLocation) {
setMeasuring(true);
setMeasureText(nextMeasureText);
setMeasurePrefix(nextMeasurePrefix);
setMeasureLocation(nextMeasureLocation);
setActiveIndex(0);
};
var stopMeasure = function stopMeasure(callback) {
setMeasuring(false);
setMeasureLocation(0);
setMeasureText('');
onSelectionEffect(callback);
};
// ============================== Change ==============================
var triggerChange = function triggerChange(nextValue) {
setMergedValue(nextValue);
onChange === null || onChange === void 0 ? void 0 : onChange(nextValue);
};
var onInternalChange = function onInternalChange(_ref2) {
var nextValue = _ref2.target.value;
triggerChange(nextValue);
};
var selectOption = function selectOption(option) {
var _getTextArea;
var _option$value = option.value,
mentionValue = _option$value === void 0 ? '' : _option$value;
var _replaceWithMeasure = (0, _util.replaceWithMeasure)(mergedValue, {
measureLocation: mergedMeasureLocation,
targetText: mentionValue,
prefix: mergedMeasurePrefix,
selectionStart: (_getTextArea = getTextArea()) === null || _getTextArea === void 0 ? void 0 : _getTextArea.selectionStart,
split: split
}),
text = _replaceWithMeasure.text,
selectionLocation = _replaceWithMeasure.selectionLocation;
triggerChange(text);
stopMeasure(function () {
// We need restore the selection position
(0, _util.setInputSelection)(getTextArea(), selectionLocation);
});
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option, mergedMeasurePrefix);
};
// ============================= KeyEvent =============================
// Check if hit the measure keyword
var onInternalKeyDown = function onInternalKeyDown(event) {
var which = event.which;
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
// Skip if not measuring
if (!mergedMeasuring) {
return;
}
if (which === _KeyCode.default.UP || which === _KeyCode.default.DOWN) {
// Control arrow function
var optionLen = mergedOptions.length;
var offset = which === _KeyCode.default.UP ? -1 : 1;
var newActiveIndex = (activeIndex + offset + optionLen) % optionLen;
setActiveIndex(newActiveIndex);
event.preventDefault();
} else if (which === _KeyCode.default.ESC) {
stopMeasure();
} else if (which === _KeyCode.default.ENTER) {
// Measure hit
event.preventDefault();
if (!mergedOptions.length) {
stopMeasure();
return;
}
var _option = mergedOptions[activeIndex];
selectOption(_option);
}
};
/**
* When to start measure:
* 1. When user press `prefix`
* 2. When measureText !== prevMeasureText
* - If measure hit
* - If measuring
*
* When to stop measure:
* 1. Selection is out of range
* 2. Contains `space`
* 3. ESC or select one
*/
var onInternalKeyUp = function onInternalKeyUp(event) {
var key = event.key,
which = event.which;
var target = event.target;
var selectionStartText = (0, _util.getBeforeSelectionText)(target);
var _getLastMeasureIndex = (0, _util.getLastMeasureIndex)(selectionStartText, mergedPrefix),
measureIndex = _getLastMeasureIndex.location,
nextMeasurePrefix = _getLastMeasureIndex.prefix;
// If the client implements an onKeyUp handler, call it
onKeyUp === null || onKeyUp === void 0 ? void 0 : onKeyUp(event);
// Skip if match the white key list
if ([_KeyCode.default.ESC, _KeyCode.default.UP, _KeyCode.default.DOWN, _KeyCode.default.ENTER].indexOf(which) !== -1) {
return;
}
if (measureIndex !== -1) {
var nextMeasureText = selectionStartText.slice(measureIndex + nextMeasurePrefix.length);
var validateMeasure = validateSearch(nextMeasureText, split);
var matchOption = !!getOptions(nextMeasureText).length;
if (validateMeasure) {
if (key === nextMeasurePrefix || key === 'Shift' || mergedMeasuring || nextMeasureText !== mergedMeasureText && matchOption) {
startMeasure(nextMeasureText, nextMeasurePrefix, measureIndex);
}
} else if (mergedMeasuring) {
// Stop if measureText is invalidate
stopMeasure();
}
/**
* We will trigger `onSearch` to developer since they may use for async update.
* If met `space` means user finished searching.
*/
if (onSearch && validateMeasure) {
onSearch(nextMeasureText, nextMeasurePrefix);
}
} else if (mergedMeasuring) {
stopMeasure();
}
};
var onInternalPressEnter = function onInternalPressEnter(event) {
if (!mergedMeasuring && onPressEnter) {
onPressEnter(event);
}
};
// ============================ Focus Blur ============================
var focusRef = (0, _react.useRef)();
var onInternalFocus = function onInternalFocus(event) {
window.clearTimeout(focusRef.current);
if (!isFocus && event && onFocus) {
onFocus(event);
}
setIsFocus(true);
};
var onInternalBlur = function onInternalBlur(event) {
focusRef.current = window.setTimeout(function () {
setIsFocus(false);
stopMeasure();
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
}, 0);
};
var onDropdownFocus = function onDropdownFocus() {
onInternalFocus();
};
var onDropdownBlur = function onDropdownBlur() {
onInternalBlur();
};
// ============================== Render ==============================
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _classnames.default)(prefixCls, className),
style: style
}, /*#__PURE__*/_react.default.createElement(_rcTextarea.default, (0, _extends2.default)({
ref: textareaRef,
value: mergedValue
}, restProps, {
rows: rows,
onChange: onInternalChange,
onKeyDown: onInternalKeyDown,
onKeyUp: onInternalKeyUp,
onPressEnter: onInternalPressEnter,
onFocus: onInternalFocus,
onBlur: onInternalBlur
})), mergedMeasuring && /*#__PURE__*/_react.default.createElement("div", {
ref: measureRef,
className: "".concat(prefixCls, "-measure")
}, mergedValue.slice(0, mergedMeasureLocation), /*#__PURE__*/_react.default.createElement(_MentionsContext.default.Provider, {
value: {
notFoundContent: notFoundContent,
activeIndex: activeIndex,
setActiveIndex: setActiveIndex,
selectOption: selectOption,
onFocus: onDropdownFocus,
onBlur: onDropdownBlur
}
}, /*#__PURE__*/_react.default.createElement(_KeywordTrigger.default, {
prefixCls: prefixCls,
transitionName: transitionName,
placement: placement,
direction: direction,
options: mergedOptions,
visible: true,
getPopupContainer: getPopupContainer,
dropdownClassName: dropdownClassName
}, /*#__PURE__*/_react.default.createElement("span", null, mergedMeasurePrefix))), mergedValue.slice(mergedMeasureLocation + mergedMeasurePrefix.length)));
});
var Mentions = /*#__PURE__*/(0, _react.forwardRef)(function (_ref3, ref) {
var suffix = _ref3.suffix,
prefixCls = _ref3.prefixCls,
classes = _ref3.classes,
value = _ref3.value,
rest = (0, _objectWithoutProperties2.default)(_ref3, _excluded2);
return /*#__PURE__*/_react.default.createElement(_rcInput.BaseInput, {
inputElement: /*#__PURE__*/_react.default.createElement(InternalMentions, (0, _extends2.default)({
prefixCls: prefixCls,
ref: ref
}, rest)),
suffix: suffix,
prefixCls: prefixCls,
classes: classes,
value: value
});
});
Mentions.Option = _Option.default;
var _default = Mentions;
exports.default = _default;