rc-mentions
Advanced tools
Comparing version 1.8.0 to 1.9.0
@@ -1,4 +0,3 @@ | ||
import * as React from 'react'; | ||
import { MentionsContextProps } from './MentionsContext'; | ||
import { OptionProps } from './Option'; | ||
/// <reference types="react" /> | ||
import type { OptionProps } from './Option'; | ||
interface DropdownMenuProps { | ||
@@ -12,6 +11,3 @@ prefixCls?: string; | ||
*/ | ||
declare class DropdownMenu extends React.Component<DropdownMenuProps, {}> { | ||
renderDropdown: ({ notFoundContent, activeIndex, setActiveIndex, selectOption, onFocus, onBlur, }: MentionsContextProps) => JSX.Element; | ||
render(): JSX.Element; | ||
} | ||
declare function DropdownMenu(props: DropdownMenuProps): JSX.Element; | ||
export default DropdownMenu; |
@@ -1,8 +0,4 @@ | ||
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; | ||
import _createClass from "@babel/runtime/helpers/esm/createClass"; | ||
import _inherits from "@babel/runtime/helpers/esm/inherits"; | ||
import _createSuper from "@babel/runtime/helpers/esm/createSuper"; | ||
import Menu, { MenuItem } from 'rc-menu'; | ||
import * as React from 'react'; | ||
import { MentionsContextConsumer } from './MentionsContext'; | ||
import MentionsContext from './MentionsContext'; | ||
/** | ||
@@ -13,75 +9,47 @@ * We only use Menu to display the candidate. | ||
var DropdownMenu = /*#__PURE__*/function (_React$Component) { | ||
_inherits(DropdownMenu, _React$Component); | ||
function DropdownMenu(props) { | ||
var _React$useContext = React.useContext(MentionsContext), | ||
notFoundContent = _React$useContext.notFoundContent, | ||
activeIndex = _React$useContext.activeIndex, | ||
setActiveIndex = _React$useContext.setActiveIndex, | ||
selectOption = _React$useContext.selectOption, | ||
onFocus = _React$useContext.onFocus, | ||
onBlur = _React$useContext.onBlur; | ||
var _super = _createSuper(DropdownMenu); | ||
var prefixCls = props.prefixCls, | ||
options = props.options; | ||
var activeOption = options[activeIndex] || {}; | ||
return /*#__PURE__*/React.createElement(Menu, { | ||
prefixCls: "".concat(prefixCls, "-menu"), | ||
activeKey: activeOption.key, | ||
onSelect: function onSelect(_ref) { | ||
var key = _ref.key; | ||
var option = options.find(function (_ref2) { | ||
var optionKey = _ref2.key; | ||
return optionKey === key; | ||
}); | ||
selectOption(option); | ||
}, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, options.map(function (option, index) { | ||
var key = option.key, | ||
disabled = option.disabled, | ||
children = option.children, | ||
className = option.className, | ||
style = option.style; | ||
return /*#__PURE__*/React.createElement(MenuItem, { | ||
key: key, | ||
disabled: disabled, | ||
className: className, | ||
style: style, | ||
onMouseEnter: function onMouseEnter() { | ||
setActiveIndex(index); | ||
} | ||
}, children); | ||
}), !options.length && /*#__PURE__*/React.createElement(MenuItem, { | ||
disabled: true | ||
}, notFoundContent)); | ||
} | ||
function DropdownMenu() { | ||
var _this; | ||
_classCallCheck(this, DropdownMenu); | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
_this = _super.call.apply(_super, [this].concat(args)); | ||
_this.renderDropdown = function (_ref) { | ||
var notFoundContent = _ref.notFoundContent, | ||
activeIndex = _ref.activeIndex, | ||
setActiveIndex = _ref.setActiveIndex, | ||
selectOption = _ref.selectOption, | ||
onFocus = _ref.onFocus, | ||
onBlur = _ref.onBlur; | ||
var _this$props = _this.props, | ||
prefixCls = _this$props.prefixCls, | ||
options = _this$props.options; | ||
var activeOption = options[activeIndex] || {}; | ||
return /*#__PURE__*/React.createElement(Menu, { | ||
prefixCls: "".concat(prefixCls, "-menu"), | ||
activeKey: activeOption.key, | ||
onSelect: function onSelect(_ref2) { | ||
var key = _ref2.key; | ||
var option = options.find(function (_ref3) { | ||
var optionKey = _ref3.key; | ||
return optionKey === key; | ||
}); | ||
selectOption(option); | ||
}, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, options.map(function (option, index) { | ||
var key = option.key, | ||
disabled = option.disabled, | ||
children = option.children, | ||
className = option.className, | ||
style = option.style; | ||
return /*#__PURE__*/React.createElement(MenuItem, { | ||
key: key, | ||
disabled: disabled, | ||
className: className, | ||
style: style, | ||
onMouseEnter: function onMouseEnter() { | ||
setActiveIndex(index); | ||
} | ||
}, children); | ||
}), !options.length && /*#__PURE__*/React.createElement(MenuItem, { | ||
disabled: true | ||
}, notFoundContent)); | ||
}; | ||
return _this; | ||
} | ||
_createClass(DropdownMenu, [{ | ||
key: "render", | ||
value: function render() { | ||
return /*#__PURE__*/React.createElement(MentionsContextConsumer, null, this.renderDropdown); | ||
} | ||
}]); | ||
return DropdownMenu; | ||
}(React.Component); | ||
export default DropdownMenu; |
import Mentions from './Mentions'; | ||
import type { MentionsProps } from './Mentions'; | ||
export type { MentionsProps }; | ||
export default Mentions; |
import * as React from 'react'; | ||
import TextArea, { TextAreaProps } from 'rc-textarea'; | ||
import { OptionProps } from './Option'; | ||
import { filterOption as defaultFilterOption, Omit, validateSearch as defaultValidateSearch } from './util'; | ||
import type { TextAreaProps } from 'rc-textarea'; | ||
import Option from './Option'; | ||
import type { OptionProps } from './Option'; | ||
import { filterOption as defaultFilterOption, validateSearch as defaultValidateSearch } from './util'; | ||
declare type BaseTextareaAttrs = Omit<TextAreaProps, 'prefix' | 'onChange' | 'onSelect'>; | ||
@@ -30,63 +31,13 @@ export declare type Placement = 'top' | 'bottom'; | ||
dropdownClassName?: string; | ||
/** @private Testing usage. Do not use in prod. It will not work as your expect. */ | ||
open?: boolean; | ||
children?: React.ReactNode; | ||
} | ||
interface MentionsState { | ||
value: string; | ||
measuring: boolean; | ||
measureText: string | null; | ||
measurePrefix: string; | ||
measureLocation: number; | ||
activeIndex: number; | ||
isFocus: boolean; | ||
export interface MentionsRef { | ||
focus: VoidFunction; | ||
blur: VoidFunction; | ||
} | ||
declare class Mentions extends React.Component<MentionsProps, MentionsState> { | ||
static Option: React.FC<OptionProps>; | ||
textarea?: HTMLTextAreaElement; | ||
measure?: HTMLDivElement; | ||
focusId: number | undefined; | ||
static defaultProps: { | ||
prefixCls: string; | ||
prefix: string; | ||
split: string; | ||
validateSearch: typeof defaultValidateSearch; | ||
filterOption: typeof defaultFilterOption; | ||
notFoundContent: string; | ||
rows: number; | ||
}; | ||
static getDerivedStateFromProps(props: MentionsProps, prevState: MentionsState): Partial<MentionsState>; | ||
constructor(props: MentionsProps); | ||
componentDidUpdate(): void; | ||
triggerChange: (value: string) => void; | ||
onChange: React.ChangeEventHandler<HTMLTextAreaElement>; | ||
onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
/** | ||
* 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 | ||
*/ | ||
onKeyUp: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
onPressEnter: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
onInputFocus: React.FocusEventHandler<HTMLTextAreaElement>; | ||
onInputBlur: React.FocusEventHandler<HTMLTextAreaElement>; | ||
onDropdownFocus: () => void; | ||
onDropdownBlur: () => void; | ||
onFocus: (event?: React.FocusEvent<HTMLTextAreaElement>) => void; | ||
onBlur: (event?: React.FocusEvent<HTMLTextAreaElement>) => void; | ||
selectOption: (option: OptionProps) => void; | ||
setActiveIndex: (activeIndex: number) => void; | ||
setTextAreaRef: (element: TextArea) => void; | ||
setMeasureRef: (element: HTMLDivElement) => void; | ||
getOptions: (measureText?: string) => OptionProps[]; | ||
startMeasure(measureText: string, measurePrefix: string, measureLocation: number): void; | ||
stopMeasure(callback?: () => void): void; | ||
focus(): void; | ||
blur(): void; | ||
render(): JSX.Element; | ||
} | ||
declare const Mentions: React.ForwardRefExoticComponent<MentionsProps & React.RefAttributes<MentionsRef>> & { | ||
Option: typeof Option; | ||
}; | ||
export default Mentions; |
import _extends from "@babel/runtime/helpers/esm/extends"; | ||
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; | ||
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; | ||
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; | ||
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; | ||
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; | ||
import _createClass from "@babel/runtime/helpers/esm/createClass"; | ||
import _inherits from "@babel/runtime/helpers/esm/inherits"; | ||
import _createSuper from "@babel/runtime/helpers/esm/createSuper"; | ||
var _excluded = ["prefixCls", "placement", "direction", "transitionName", "className", "style", "autoFocus", "notFoundContent", "getPopupContainer", "dropdownClassName"]; | ||
var _excluded = ["prefixCls", "className", "style", "prefix", "split", "notFoundContent", "value", "defaultValue", "children", "open", "validateSearch", "filterOption", "onChange", "onKeyDown", "onKeyUp", "onPressEnter", "onSearch", "onSelect", "onFocus", "onBlur", "transitionName", "placement", "direction", "getPopupContainer", "dropdownClassName"]; | ||
import classNames from 'classnames'; | ||
import useMergedState from "rc-util/es/hooks/useMergedState"; | ||
import toArray from "rc-util/es/Children/toArray"; | ||
import KeyCode from "rc-util/es/KeyCode"; | ||
import warning from "rc-util/es/warning"; | ||
import * as React from 'react'; | ||
import { useState, useRef } from 'react'; | ||
import TextArea from 'rc-textarea'; | ||
import KeywordTrigger from './KeywordTrigger'; | ||
import { MentionsContextProvider } from './MentionsContext'; | ||
import MentionsContext from './MentionsContext'; | ||
import Option from './Option'; | ||
import { filterOption as defaultFilterOption, getBeforeSelectionText, getLastMeasureIndex, omit, replaceWithMeasure, setInputSelection, validateSearch as defaultValidateSearch } from './util'; | ||
import { filterOption as defaultFilterOption, getBeforeSelectionText, getLastMeasureIndex, replaceWithMeasure, setInputSelection, validateSearch as defaultValidateSearch } from './util'; | ||
import useEffectState from './hooks/useEffectState'; | ||
var Mentions = /*#__PURE__*/React.forwardRef(function (props, ref) { | ||
var prefixCls = props.prefixCls, | ||
className = props.className, | ||
style = props.style, | ||
prefix = props.prefix, | ||
split = props.split, | ||
notFoundContent = props.notFoundContent, | ||
value = props.value, | ||
defaultValue = props.defaultValue, | ||
children = props.children, | ||
open = props.open, | ||
validateSearch = props.validateSearch, | ||
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, | ||
restProps = _objectWithoutProperties(props, _excluded); | ||
var Mentions = /*#__PURE__*/function (_React$Component) { | ||
_inherits(Mentions, _React$Component); | ||
var mergedPrefix = Array.isArray(prefix) ? prefix : [prefix]; | ||
var _super = _createSuper(Mentions); | ||
var mergedProps = _objectSpread(_objectSpread({}, props), {}, { | ||
prefix: mergedPrefix | ||
}); // =============================== Refs =============================== | ||
function Mentions(_props) { | ||
var _this; | ||
_classCallCheck(this, Mentions); | ||
var textareaRef = useRef(null); | ||
var measureRef = useRef(null); | ||
React.useImperativeHandle(ref, function () { | ||
return { | ||
focus: function focus() { | ||
var _textareaRef$current; | ||
_this = _super.call(this, _props); | ||
_this.textarea = void 0; | ||
_this.measure = void 0; | ||
_this.focusId = undefined; | ||
return (_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 ? void 0 : _textareaRef$current.focus(); | ||
}, | ||
blur: function blur() { | ||
var _textareaRef$current2; | ||
_this.triggerChange = function (value) { | ||
var onChange = _this.props.onChange; | ||
if (!('value' in _this.props)) { | ||
_this.setState({ | ||
value: value | ||
}); | ||
return (_textareaRef$current2 = textareaRef.current) === null || _textareaRef$current2 === void 0 ? void 0 : _textareaRef$current2.blur(); | ||
} | ||
if (onChange) { | ||
onChange(value); | ||
} | ||
}; | ||
}); // ============================== State =============================== | ||
_this.onChange = function (_ref) { | ||
var value = _ref.target.value; | ||
var _useState = useState(false), | ||
_useState2 = _slicedToArray(_useState, 2), | ||
measuring = _useState2[0], | ||
setMeasuring = _useState2[1]; | ||
_this.triggerChange(value); | ||
}; | ||
var _useState3 = useState(''), | ||
_useState4 = _slicedToArray(_useState3, 2), | ||
measureText = _useState4[0], | ||
setMeasureText = _useState4[1]; | ||
_this.onKeyDown = function (event) { | ||
var which = event.which; | ||
var _this$state = _this.state, | ||
activeIndex = _this$state.activeIndex, | ||
measuring = _this$state.measuring; | ||
var clientOnKeyDown = _this.props.onKeyDown; | ||
var _useState5 = useState(''), | ||
_useState6 = _slicedToArray(_useState5, 2), | ||
measurePrefix = _useState6[0], | ||
setMeasurePrefix = _useState6[1]; | ||
if (clientOnKeyDown) { | ||
clientOnKeyDown(event); | ||
} // Skip if not measuring | ||
var _useState7 = useState(0), | ||
_useState8 = _slicedToArray(_useState7, 2), | ||
measureLocation = _useState8[0], | ||
setMeasureLocation = _useState8[1]; | ||
var _useState9 = useState(0), | ||
_useState10 = _slicedToArray(_useState9, 2), | ||
activeIndex = _useState10[0], | ||
setActiveIndex = _useState10[1]; | ||
if (!measuring) { | ||
return; | ||
} | ||
var _useState11 = useState(false), | ||
_useState12 = _slicedToArray(_useState11, 2), | ||
isFocus = _useState12[0], | ||
setIsFocus = _useState12[1]; // ============================== Value =============================== | ||
if (which === KeyCode.UP || which === KeyCode.DOWN) { | ||
// Control arrow function | ||
var optionLen = _this.getOptions().length; | ||
var offset = which === KeyCode.UP ? -1 : 1; | ||
var newActiveIndex = (activeIndex + offset + optionLen) % optionLen; | ||
var _useMergedState = useMergedState('', { | ||
defaultValue: defaultValue, | ||
value: value | ||
}), | ||
_useMergedState2 = _slicedToArray(_useMergedState, 2), | ||
mergedValue = _useMergedState2[0], | ||
setMergedValue = _useMergedState2[1]; // =============================== Open =============================== | ||
_this.setState({ | ||
activeIndex: newActiveIndex | ||
}); | ||
event.preventDefault(); | ||
} else if (which === KeyCode.ESC) { | ||
_this.stopMeasure(); | ||
} else if (which === KeyCode.ENTER) { | ||
// Measure hit | ||
event.preventDefault(); | ||
var _React$useMemo = React.useMemo(function () { | ||
if (open) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warning(false, '`open` of Mentions is only used for debug usage. Do not use in you production.'); | ||
} | ||
var options = _this.getOptions(); | ||
for (var i = 0; i < mergedPrefix.length; i += 1) { | ||
var curPrefix = mergedPrefix[i]; | ||
var index = mergedValue.lastIndexOf(curPrefix); | ||
if (!options.length) { | ||
_this.stopMeasure(); | ||
return; | ||
if (index >= 0) { | ||
return [true, '', curPrefix, index]; | ||
} | ||
} | ||
} | ||
var option = options[activeIndex]; | ||
return [measuring, measureText, measurePrefix, measureLocation]; | ||
}, [open, measuring, mergedPrefix, mergedValue, measureText, measurePrefix, measureLocation]), | ||
_React$useMemo2 = _slicedToArray(_React$useMemo, 4), | ||
mergedMeasuring = _React$useMemo2[0], | ||
mergedMeasureText = _React$useMemo2[1], | ||
mergedMeasurePrefix = _React$useMemo2[2], | ||
mergedMeasureLocation = _React$useMemo2[3]; // ============================== Option ============================== | ||
_this.selectOption(option); | ||
var getOptions = React.useCallback(function (targetMeasureText) { | ||
var list = toArray(children).map(function (_ref) { | ||
var optionProps = _ref.props, | ||
key = _ref.key; | ||
return _objectSpread(_objectSpread({}, optionProps), {}, { | ||
key: key || optionProps.value | ||
}); | ||
}).filter(function (option) { | ||
/** Return all result if `filterOption` is false. */ | ||
if (filterOption === false) { | ||
return true; | ||
} | ||
}; | ||
_this.onKeyUp = function (event) { | ||
var key = event.key, | ||
which = event.which; | ||
var _this$state2 = _this.state, | ||
prevMeasureText = _this$state2.measureText, | ||
measuring = _this$state2.measuring; | ||
var _this$props = _this.props, | ||
_this$props$prefix = _this$props.prefix, | ||
prefix = _this$props$prefix === void 0 ? '' : _this$props$prefix, | ||
clientOnKeyUp = _this$props.onKeyUp, | ||
onSearch = _this$props.onSearch, | ||
validateSearch = _this$props.validateSearch; | ||
var target = event.target; | ||
var selectionStartText = getBeforeSelectionText(target); | ||
return filterOption(targetMeasureText, option); | ||
}); | ||
return list; | ||
}, [children, filterOption]); | ||
var options = React.useMemo(function () { | ||
return getOptions(mergedMeasureText); | ||
}, [getOptions, mergedMeasureText]); // ============================= Measure ============================== | ||
// Mark that we will reset input selection to target position when user select option | ||
var _getLastMeasureIndex = getLastMeasureIndex(selectionStartText, prefix), | ||
measureIndex = _getLastMeasureIndex.location, | ||
measurePrefix = _getLastMeasureIndex.prefix; // If the client implements an onKeyUp handler, call it | ||
var onSelectionEffect = useEffectState(); | ||
var startMeasure = function startMeasure(nextMeasureText, nextMeasurePrefix, nextMeasureLocation) { | ||
setMeasuring(true); | ||
setMeasureText(nextMeasureText); | ||
setMeasurePrefix(nextMeasurePrefix); | ||
setMeasureLocation(nextMeasureLocation); | ||
setActiveIndex(0); | ||
}; | ||
if (clientOnKeyUp) { | ||
clientOnKeyUp(event); | ||
} // Skip if match the white key list | ||
var stopMeasure = function stopMeasure(callback) { | ||
setMeasuring(false); | ||
setMeasureLocation(0); | ||
setMeasureText(''); | ||
onSelectionEffect(callback); | ||
}; // ============================== Change ============================== | ||
if ([KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !== -1) { | ||
return; | ||
} | ||
var triggerChange = function triggerChange(nextValue) { | ||
setMergedValue(nextValue); | ||
onChange === null || onChange === void 0 ? void 0 : onChange(nextValue); | ||
}; | ||
if (measureIndex !== -1) { | ||
var measureText = selectionStartText.slice(measureIndex + measurePrefix.length); | ||
var validateMeasure = validateSearch(measureText, _this.props); | ||
var matchOption = !!_this.getOptions(measureText).length; | ||
var onInternalChange = function onInternalChange(_ref2) { | ||
var nextValue = _ref2.target.value; | ||
triggerChange(nextValue); | ||
}; | ||
if (validateMeasure) { | ||
if (key === measurePrefix || key === 'Shift' || measuring || measureText !== prevMeasureText && matchOption) { | ||
_this.startMeasure(measureText, measurePrefix, measureIndex); | ||
} | ||
} else if (measuring) { | ||
// Stop if measureText is invalidate | ||
_this.stopMeasure(); | ||
} | ||
/** | ||
* We will trigger `onSearch` to developer since they may use for async update. | ||
* If met `space` means user finished searching. | ||
*/ | ||
var selectOption = function selectOption(option) { | ||
var _getTextArea; | ||
var getTextArea = function getTextArea() { | ||
var _textareaRef$current3, _textareaRef$current4; | ||
if (onSearch && validateMeasure) { | ||
onSearch(measureText, measurePrefix); | ||
} | ||
} else if (measuring) { | ||
_this.stopMeasure(); | ||
} | ||
return (_textareaRef$current3 = textareaRef.current) === null || _textareaRef$current3 === void 0 ? void 0 : (_textareaRef$current4 = _textareaRef$current3.resizableTextArea) === null || _textareaRef$current4 === void 0 ? void 0 : _textareaRef$current4.textArea; | ||
}; | ||
_this.onPressEnter = function (event) { | ||
var measuring = _this.state.measuring; | ||
var onPressEnter = _this.props.onPressEnter; | ||
var _option$value = option.value, | ||
mentionValue = _option$value === void 0 ? '' : _option$value; | ||
if (!measuring && onPressEnter) { | ||
onPressEnter(event); | ||
} | ||
}; | ||
var _replaceWithMeasure = 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; | ||
_this.onInputFocus = function (event) { | ||
_this.onFocus(event); | ||
}; | ||
triggerChange(text); | ||
stopMeasure(function () { | ||
// We need restore the selection position | ||
setInputSelection(getTextArea(), selectionLocation); | ||
}); | ||
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option, mergedMeasurePrefix); | ||
}; // ============================= KeyEvent ============================= | ||
// Check if hit the measure keyword | ||
_this.onInputBlur = function (event) { | ||
_this.onBlur(event); | ||
}; | ||
_this.onDropdownFocus = function () { | ||
_this.onFocus(); | ||
}; | ||
var onInternalKeyDown = function onInternalKeyDown(event) { | ||
var which = event.which; | ||
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event); // Skip if not measuring | ||
_this.onDropdownBlur = function () { | ||
_this.onBlur(); | ||
}; | ||
if (!mergedMeasuring) { | ||
return; | ||
} | ||
_this.onFocus = function (event) { | ||
window.clearTimeout(_this.focusId); | ||
var isFocus = _this.state.isFocus; | ||
var onFocus = _this.props.onFocus; | ||
if (which === KeyCode.UP || which === KeyCode.DOWN) { | ||
// Control arrow function | ||
var optionLen = options.length; | ||
var offset = which === KeyCode.UP ? -1 : 1; | ||
var newActiveIndex = (activeIndex + offset + optionLen) % optionLen; | ||
setActiveIndex(newActiveIndex); | ||
event.preventDefault(); | ||
} else if (which === KeyCode.ESC) { | ||
stopMeasure(); | ||
} else if (which === KeyCode.ENTER) { | ||
// Measure hit | ||
event.preventDefault(); | ||
if (!isFocus && event && onFocus) { | ||
onFocus(event); | ||
if (!options.length) { | ||
stopMeasure(); | ||
return; | ||
} | ||
_this.setState({ | ||
isFocus: true | ||
}); | ||
}; | ||
var option = options[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 | ||
*/ | ||
_this.onBlur = function (event) { | ||
_this.focusId = window.setTimeout(function () { | ||
var onBlur = _this.props.onBlur; | ||
_this.setState({ | ||
isFocus: false | ||
}); | ||
var onInternalKeyUp = function onInternalKeyUp(event) { | ||
var key = event.key, | ||
which = event.which; | ||
var target = event.target; | ||
var selectionStartText = getBeforeSelectionText(target); | ||
_this.stopMeasure(); | ||
var _getLastMeasureIndex = getLastMeasureIndex(selectionStartText, mergedPrefix), | ||
measureIndex = _getLastMeasureIndex.location, | ||
nextMeasurePrefix = _getLastMeasureIndex.prefix; // If the client implements an onKeyUp handler, call it | ||
if (onBlur) { | ||
onBlur(event); | ||
} | ||
}, 0); | ||
}; | ||
_this.selectOption = function (option) { | ||
var _this$state3 = _this.state, | ||
value = _this$state3.value, | ||
measureLocation = _this$state3.measureLocation, | ||
measurePrefix = _this$state3.measurePrefix; | ||
var _this$props2 = _this.props, | ||
split = _this$props2.split, | ||
onSelect = _this$props2.onSelect; | ||
var _option$value = option.value, | ||
mentionValue = _option$value === void 0 ? '' : _option$value; | ||
onKeyUp === null || onKeyUp === void 0 ? void 0 : onKeyUp(event); // Skip if match the white key list | ||
var _replaceWithMeasure = replaceWithMeasure(value, { | ||
measureLocation: measureLocation, | ||
targetText: mentionValue, | ||
prefix: measurePrefix, | ||
selectionStart: _this.textarea.selectionStart, | ||
split: split | ||
}), | ||
text = _replaceWithMeasure.text, | ||
selectionLocation = _replaceWithMeasure.selectionLocation; | ||
if ([KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !== -1) { | ||
return; | ||
} | ||
_this.triggerChange(text); | ||
if (measureIndex !== -1) { | ||
var nextMeasureText = selectionStartText.slice(measureIndex + nextMeasurePrefix.length); | ||
var validateMeasure = validateSearch(nextMeasureText, mergedProps); | ||
var matchOption = !!getOptions(nextMeasureText).length; | ||
_this.stopMeasure(function () { | ||
// We need restore the selection position | ||
setInputSelection(_this.textarea, selectionLocation); | ||
}); | ||
if (onSelect) { | ||
onSelect(option, measurePrefix); | ||
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. | ||
*/ | ||
_this.setActiveIndex = function (activeIndex) { | ||
_this.setState({ | ||
activeIndex: activeIndex | ||
}); | ||
}; | ||
_this.setTextAreaRef = function (element) { | ||
var _element$resizableTex; | ||
if (onSearch && validateMeasure) { | ||
onSearch(nextMeasureText, nextMeasurePrefix); | ||
} | ||
} else if (mergedMeasuring) { | ||
stopMeasure(); | ||
} | ||
}; | ||
_this.textarea = element === null || element === void 0 ? void 0 : (_element$resizableTex = element.resizableTextArea) === null || _element$resizableTex === void 0 ? void 0 : _element$resizableTex.textArea; | ||
}; | ||
var onInternalPressEnter = function onInternalPressEnter(event) { | ||
if (!mergedMeasuring && onPressEnter) { | ||
onPressEnter(event); | ||
} | ||
}; // ============================ Focus Blur ============================ | ||
_this.setMeasureRef = function (element) { | ||
_this.measure = element; | ||
}; | ||
_this.getOptions = function (measureText) { | ||
var targetMeasureText = measureText || _this.state.measureText || ''; | ||
var _this$props3 = _this.props, | ||
children = _this$props3.children, | ||
filterOption = _this$props3.filterOption; | ||
var list = toArray(children).map(function (_ref2) { | ||
var props = _ref2.props, | ||
key = _ref2.key; | ||
return _objectSpread(_objectSpread({}, props), {}, { | ||
key: key || props.value | ||
}); | ||
}).filter(function (option) { | ||
/** Return all result if `filterOption` is false. */ | ||
if (filterOption === false) { | ||
return true; | ||
} | ||
var focusRef = useRef(); | ||
return filterOption(targetMeasureText, option); | ||
}); | ||
return list; | ||
}; | ||
var onInternalFocus = function onInternalFocus(event) { | ||
window.clearTimeout(focusRef.current); | ||
_this.state = { | ||
value: _props.defaultValue || _props.value || '', | ||
measuring: false, | ||
measureLocation: 0, | ||
measureText: null, | ||
measurePrefix: '', | ||
activeIndex: 0, | ||
isFocus: false | ||
}; | ||
return _this; | ||
} | ||
if (!isFocus && event && onFocus) { | ||
onFocus(event); | ||
} | ||
_createClass(Mentions, [{ | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
var measuring = this.state.measuring; // Sync measure div top with textarea for rc-trigger usage | ||
setIsFocus(true); | ||
}; | ||
if (measuring) { | ||
this.measure.scrollTop = this.textarea.scrollTop; | ||
} | ||
} | ||
}, { | ||
key: "startMeasure", | ||
value: function startMeasure(measureText, measurePrefix, measureLocation) { | ||
this.setState({ | ||
measuring: true, | ||
measureText: measureText, | ||
measurePrefix: measurePrefix, | ||
measureLocation: measureLocation, | ||
activeIndex: 0 | ||
}); | ||
} | ||
}, { | ||
key: "stopMeasure", | ||
value: function stopMeasure(callback) { | ||
this.setState({ | ||
measuring: false, | ||
measureLocation: 0, | ||
measureText: null | ||
}, callback); | ||
} | ||
}, { | ||
key: "focus", | ||
value: function focus() { | ||
this.textarea.focus(); | ||
} | ||
}, { | ||
key: "blur", | ||
value: function blur() { | ||
this.textarea.blur(); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this$state4 = this.state, | ||
value = _this$state4.value, | ||
measureLocation = _this$state4.measureLocation, | ||
measurePrefix = _this$state4.measurePrefix, | ||
measuring = _this$state4.measuring, | ||
activeIndex = _this$state4.activeIndex; | ||
var onInternalBlur = function onInternalBlur(event) { | ||
focusRef.current = window.setTimeout(function () { | ||
setIsFocus(false); | ||
stopMeasure(); | ||
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event); | ||
}, 0); | ||
}; | ||
var _this$props4 = this.props, | ||
prefixCls = _this$props4.prefixCls, | ||
placement = _this$props4.placement, | ||
direction = _this$props4.direction, | ||
transitionName = _this$props4.transitionName, | ||
className = _this$props4.className, | ||
style = _this$props4.style, | ||
autoFocus = _this$props4.autoFocus, | ||
notFoundContent = _this$props4.notFoundContent, | ||
getPopupContainer = _this$props4.getPopupContainer, | ||
dropdownClassName = _this$props4.dropdownClassName, | ||
restProps = _objectWithoutProperties(_this$props4, _excluded); | ||
var onDropdownFocus = function onDropdownFocus() { | ||
onInternalFocus(); | ||
}; | ||
var inputProps = omit(restProps, 'value', 'defaultValue', 'prefix', 'split', 'children', 'validateSearch', 'filterOption', 'onSelect', 'onSearch'); | ||
var options = measuring ? this.getOptions() : []; | ||
return /*#__PURE__*/React.createElement("div", { | ||
className: classNames(prefixCls, className), | ||
style: style | ||
}, /*#__PURE__*/React.createElement(TextArea, _extends({ | ||
autoFocus: autoFocus, | ||
ref: this.setTextAreaRef, | ||
value: value | ||
}, inputProps, { | ||
onChange: this.onChange, | ||
onKeyDown: this.onKeyDown, | ||
onKeyUp: this.onKeyUp, | ||
onPressEnter: this.onPressEnter, | ||
onFocus: this.onInputFocus, | ||
onBlur: this.onInputBlur | ||
})), measuring && /*#__PURE__*/React.createElement("div", { | ||
ref: this.setMeasureRef, | ||
className: "".concat(prefixCls, "-measure") | ||
}, value.slice(0, measureLocation), /*#__PURE__*/React.createElement(MentionsContextProvider, { | ||
value: { | ||
notFoundContent: notFoundContent, | ||
activeIndex: activeIndex, | ||
setActiveIndex: this.setActiveIndex, | ||
selectOption: this.selectOption, | ||
onFocus: this.onDropdownFocus, | ||
onBlur: this.onDropdownBlur | ||
} | ||
}, /*#__PURE__*/React.createElement(KeywordTrigger, { | ||
prefixCls: prefixCls, | ||
transitionName: transitionName, | ||
placement: placement, | ||
direction: direction, | ||
options: options, | ||
visible: true, | ||
getPopupContainer: getPopupContainer, | ||
dropdownClassName: dropdownClassName | ||
}, /*#__PURE__*/React.createElement("span", null, measurePrefix))), value.slice(measureLocation + measurePrefix.length))); | ||
} | ||
}], [{ | ||
key: "getDerivedStateFromProps", | ||
value: function getDerivedStateFromProps(props, prevState) { | ||
var newState = {}; | ||
var onDropdownBlur = function onDropdownBlur() { | ||
onInternalBlur(); | ||
}; // ============================== Render ============================== | ||
if ('value' in props && props.value !== prevState.value) { | ||
newState.value = props.value || ''; | ||
} | ||
return newState; | ||
return /*#__PURE__*/React.createElement("div", { | ||
className: classNames(prefixCls, className), | ||
style: style | ||
}, /*#__PURE__*/React.createElement(TextArea, _extends({ | ||
ref: textareaRef, | ||
value: mergedValue | ||
}, restProps, { | ||
onChange: onInternalChange, | ||
onKeyDown: onInternalKeyDown, | ||
onKeyUp: onInternalKeyUp, | ||
onPressEnter: onInternalPressEnter, | ||
onFocus: onInternalFocus, | ||
onBlur: onInternalBlur | ||
})), mergedMeasuring && /*#__PURE__*/React.createElement("div", { | ||
ref: measureRef, | ||
className: "".concat(prefixCls, "-measure") | ||
}, mergedValue.slice(0, mergedMeasureLocation), /*#__PURE__*/React.createElement(MentionsContext.Provider, { | ||
value: { | ||
notFoundContent: notFoundContent, | ||
activeIndex: activeIndex, | ||
setActiveIndex: setActiveIndex, | ||
selectOption: selectOption, | ||
onFocus: onDropdownFocus, | ||
onBlur: onDropdownBlur | ||
} | ||
}]); | ||
return Mentions; | ||
}(React.Component); | ||
Mentions.Option = Option; | ||
}, /*#__PURE__*/React.createElement(KeywordTrigger, { | ||
prefixCls: prefixCls, | ||
transitionName: transitionName, | ||
placement: placement, | ||
direction: direction, | ||
options: options, | ||
visible: true, | ||
getPopupContainer: getPopupContainer, | ||
dropdownClassName: dropdownClassName | ||
}, /*#__PURE__*/React.createElement("span", null, mergedMeasurePrefix))), mergedValue.slice(mergedMeasureLocation + mergedMeasurePrefix.length))); | ||
}); | ||
Mentions.defaultProps = { | ||
@@ -423,2 +387,3 @@ prefixCls: 'rc-mentions', | ||
}; | ||
Mentions.Option = Option; | ||
export default Mentions; |
import * as React from 'react'; | ||
import { OptionProps } from './Option'; | ||
import type { OptionProps } from './Option'; | ||
export interface MentionsContextProps { | ||
@@ -11,3 +11,3 @@ notFoundContent: React.ReactNode; | ||
} | ||
export declare const MentionsContextProvider: React.Provider<MentionsContextProps>; | ||
export declare const MentionsContextConsumer: React.Consumer<MentionsContextProps>; | ||
declare const MentionsContext: React.Context<MentionsContextProps>; | ||
export default MentionsContext; |
@@ -5,3 +5,2 @@ /* tslint:disable: no-object-literal-type-assertion */ | ||
var MentionsContext = /*#__PURE__*/React.createContext(null); | ||
export var MentionsContextProvider = MentionsContext.Provider; | ||
export var MentionsContextConsumer = MentionsContext.Consumer; | ||
export default MentionsContext; |
@@ -1,8 +0,3 @@ | ||
import { MentionsProps } from './Mentions'; | ||
import { OptionProps } from './Option'; | ||
export declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||
declare type OmitFunc = <T extends object, K extends [...(keyof T)[]]>(obj: T, ...keys: K) => { | ||
[K2 in Exclude<keyof T, K[number]>]: T[K2]; | ||
}; | ||
export declare const omit: OmitFunc; | ||
import type { MentionsProps } from './Mentions'; | ||
import type { OptionProps } from './Option'; | ||
/** | ||
@@ -19,3 +14,3 @@ * Cut input selection into 2 part and return text before selection start | ||
*/ | ||
export declare function getLastMeasureIndex(text: string, prefix?: string | string[]): MeasureIndex; | ||
export declare function getLastMeasureIndex(text: string, prefix: string[]): MeasureIndex; | ||
interface MeasureConfig { | ||
@@ -22,0 +17,0 @@ measureLocation: number; |
@@ -1,18 +0,4 @@ | ||
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; | ||
export var omit = function omit(obj) { | ||
var clone = _objectSpread({}, obj); | ||
for (var _len = arguments.length, keys = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
keys.forEach(function (key) { | ||
delete clone[key]; | ||
}); | ||
return clone; | ||
}; | ||
/** | ||
* Cut input selection into 2 part and return text before selection start | ||
*/ | ||
export function getBeforeSelectionText(input) { | ||
@@ -26,6 +12,4 @@ var selectionStart = input.selectionStart; | ||
export function getLastMeasureIndex(text) { | ||
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var prefixList = Array.isArray(prefix) ? prefix : [prefix]; | ||
return prefixList.reduce(function (lastMatch, prefixStr) { | ||
export function getLastMeasureIndex(text, prefix) { | ||
return prefix.reduce(function (lastMatch, prefixStr) { | ||
var lastIndex = text.lastIndexOf(prefixStr); | ||
@@ -32,0 +16,0 @@ |
@@ -1,4 +0,3 @@ | ||
import * as React from 'react'; | ||
import { MentionsContextProps } from './MentionsContext'; | ||
import { OptionProps } from './Option'; | ||
/// <reference types="react" /> | ||
import type { OptionProps } from './Option'; | ||
interface DropdownMenuProps { | ||
@@ -12,6 +11,3 @@ prefixCls?: string; | ||
*/ | ||
declare class DropdownMenu extends React.Component<DropdownMenuProps, {}> { | ||
renderDropdown: ({ notFoundContent, activeIndex, setActiveIndex, selectOption, onFocus, onBlur, }: MentionsContextProps) => JSX.Element; | ||
render(): JSX.Element; | ||
} | ||
declare function DropdownMenu(props: DropdownMenuProps): JSX.Element; | ||
export default DropdownMenu; |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
var _typeof = require("@babel/runtime/helpers/typeof"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -12,16 +12,12 @@ value: true | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var _rcMenu = _interopRequireWildcard(require("rc-menu")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); | ||
var React = _interopRequireWildcard(require("react")); | ||
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); | ||
var _MentionsContext = _interopRequireDefault(require("./MentionsContext")); | ||
var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper")); | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
var _rcMenu = _interopRequireWildcard(require("rc-menu")); | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var React = _interopRequireWildcard(require("react")); | ||
var _MentionsContext = require("./MentionsContext"); | ||
/** | ||
@@ -31,75 +27,48 @@ * We only use Menu to display the candidate. | ||
*/ | ||
var DropdownMenu = /*#__PURE__*/function (_React$Component) { | ||
(0, _inherits2.default)(DropdownMenu, _React$Component); | ||
function DropdownMenu(props) { | ||
var _React$useContext = React.useContext(_MentionsContext.default), | ||
notFoundContent = _React$useContext.notFoundContent, | ||
activeIndex = _React$useContext.activeIndex, | ||
setActiveIndex = _React$useContext.setActiveIndex, | ||
selectOption = _React$useContext.selectOption, | ||
onFocus = _React$useContext.onFocus, | ||
onBlur = _React$useContext.onBlur; | ||
var _super = (0, _createSuper2.default)(DropdownMenu); | ||
var prefixCls = props.prefixCls, | ||
options = props.options; | ||
var activeOption = options[activeIndex] || {}; | ||
return /*#__PURE__*/React.createElement(_rcMenu.default, { | ||
prefixCls: "".concat(prefixCls, "-menu"), | ||
activeKey: activeOption.key, | ||
onSelect: function onSelect(_ref) { | ||
var key = _ref.key; | ||
var option = options.find(function (_ref2) { | ||
var optionKey = _ref2.key; | ||
return optionKey === key; | ||
}); | ||
selectOption(option); | ||
}, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, options.map(function (option, index) { | ||
var key = option.key, | ||
disabled = option.disabled, | ||
children = option.children, | ||
className = option.className, | ||
style = option.style; | ||
return /*#__PURE__*/React.createElement(_rcMenu.MenuItem, { | ||
key: key, | ||
disabled: disabled, | ||
className: className, | ||
style: style, | ||
onMouseEnter: function onMouseEnter() { | ||
setActiveIndex(index); | ||
} | ||
}, children); | ||
}), !options.length && /*#__PURE__*/React.createElement(_rcMenu.MenuItem, { | ||
disabled: true | ||
}, notFoundContent)); | ||
} | ||
function DropdownMenu() { | ||
var _this; | ||
(0, _classCallCheck2.default)(this, DropdownMenu); | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
_this = _super.call.apply(_super, [this].concat(args)); | ||
_this.renderDropdown = function (_ref) { | ||
var notFoundContent = _ref.notFoundContent, | ||
activeIndex = _ref.activeIndex, | ||
setActiveIndex = _ref.setActiveIndex, | ||
selectOption = _ref.selectOption, | ||
onFocus = _ref.onFocus, | ||
onBlur = _ref.onBlur; | ||
var _this$props = _this.props, | ||
prefixCls = _this$props.prefixCls, | ||
options = _this$props.options; | ||
var activeOption = options[activeIndex] || {}; | ||
return /*#__PURE__*/React.createElement(_rcMenu.default, { | ||
prefixCls: "".concat(prefixCls, "-menu"), | ||
activeKey: activeOption.key, | ||
onSelect: function onSelect(_ref2) { | ||
var key = _ref2.key; | ||
var option = options.find(function (_ref3) { | ||
var optionKey = _ref3.key; | ||
return optionKey === key; | ||
}); | ||
selectOption(option); | ||
}, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, options.map(function (option, index) { | ||
var key = option.key, | ||
disabled = option.disabled, | ||
children = option.children, | ||
className = option.className, | ||
style = option.style; | ||
return /*#__PURE__*/React.createElement(_rcMenu.MenuItem, { | ||
key: key, | ||
disabled: disabled, | ||
className: className, | ||
style: style, | ||
onMouseEnter: function onMouseEnter() { | ||
setActiveIndex(index); | ||
} | ||
}, children); | ||
}), !options.length && /*#__PURE__*/React.createElement(_rcMenu.MenuItem, { | ||
disabled: true | ||
}, notFoundContent)); | ||
}; | ||
return _this; | ||
} | ||
(0, _createClass2.default)(DropdownMenu, [{ | ||
key: "render", | ||
value: function render() { | ||
return /*#__PURE__*/React.createElement(_MentionsContext.MentionsContextConsumer, null, this.renderDropdown); | ||
} | ||
}]); | ||
return DropdownMenu; | ||
}(React.Component); | ||
var _default = DropdownMenu; | ||
exports.default = _default; |
import Mentions from './Mentions'; | ||
import type { MentionsProps } from './Mentions'; | ||
export type { MentionsProps }; | ||
export default Mentions; |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
var _typeof = require("@babel/runtime/helpers/typeof"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -26,2 +26,6 @@ value: true | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var BUILT_IN_PLACEMENTS = { | ||
@@ -28,0 +32,0 @@ bottomRight: { |
import * as React from 'react'; | ||
import TextArea, { TextAreaProps } from 'rc-textarea'; | ||
import { OptionProps } from './Option'; | ||
import { filterOption as defaultFilterOption, Omit, validateSearch as defaultValidateSearch } from './util'; | ||
import type { TextAreaProps } from 'rc-textarea'; | ||
import Option from './Option'; | ||
import type { OptionProps } from './Option'; | ||
import { filterOption as defaultFilterOption, validateSearch as defaultValidateSearch } from './util'; | ||
declare type BaseTextareaAttrs = Omit<TextAreaProps, 'prefix' | 'onChange' | 'onSelect'>; | ||
@@ -30,63 +31,13 @@ export declare type Placement = 'top' | 'bottom'; | ||
dropdownClassName?: string; | ||
/** @private Testing usage. Do not use in prod. It will not work as your expect. */ | ||
open?: boolean; | ||
children?: React.ReactNode; | ||
} | ||
interface MentionsState { | ||
value: string; | ||
measuring: boolean; | ||
measureText: string | null; | ||
measurePrefix: string; | ||
measureLocation: number; | ||
activeIndex: number; | ||
isFocus: boolean; | ||
export interface MentionsRef { | ||
focus: VoidFunction; | ||
blur: VoidFunction; | ||
} | ||
declare class Mentions extends React.Component<MentionsProps, MentionsState> { | ||
static Option: React.FC<OptionProps>; | ||
textarea?: HTMLTextAreaElement; | ||
measure?: HTMLDivElement; | ||
focusId: number | undefined; | ||
static defaultProps: { | ||
prefixCls: string; | ||
prefix: string; | ||
split: string; | ||
validateSearch: typeof defaultValidateSearch; | ||
filterOption: typeof defaultFilterOption; | ||
notFoundContent: string; | ||
rows: number; | ||
}; | ||
static getDerivedStateFromProps(props: MentionsProps, prevState: MentionsState): Partial<MentionsState>; | ||
constructor(props: MentionsProps); | ||
componentDidUpdate(): void; | ||
triggerChange: (value: string) => void; | ||
onChange: React.ChangeEventHandler<HTMLTextAreaElement>; | ||
onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
/** | ||
* 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 | ||
*/ | ||
onKeyUp: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
onPressEnter: React.KeyboardEventHandler<HTMLTextAreaElement>; | ||
onInputFocus: React.FocusEventHandler<HTMLTextAreaElement>; | ||
onInputBlur: React.FocusEventHandler<HTMLTextAreaElement>; | ||
onDropdownFocus: () => void; | ||
onDropdownBlur: () => void; | ||
onFocus: (event?: React.FocusEvent<HTMLTextAreaElement>) => void; | ||
onBlur: (event?: React.FocusEvent<HTMLTextAreaElement>) => void; | ||
selectOption: (option: OptionProps) => void; | ||
setActiveIndex: (activeIndex: number) => void; | ||
setTextAreaRef: (element: TextArea) => void; | ||
setMeasureRef: (element: HTMLDivElement) => void; | ||
getOptions: (measureText?: string) => OptionProps[]; | ||
startMeasure(measureText: string, measurePrefix: string, measureLocation: number): void; | ||
stopMeasure(callback?: () => void): void; | ||
focus(): void; | ||
blur(): void; | ||
render(): JSX.Element; | ||
} | ||
declare const Mentions: React.ForwardRefExoticComponent<MentionsProps & React.RefAttributes<MentionsRef>> & { | ||
Option: typeof Option; | ||
}; | ||
export default Mentions; |
@@ -5,3 +5,3 @@ "use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _typeof = require("@babel/runtime/helpers/typeof"); | ||
@@ -15,16 +15,12 @@ Object.defineProperty(exports, "__esModule", { | ||
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); | ||
var _classnames = _interopRequireDefault(require("classnames")); | ||
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); | ||
var _useMergedState3 = _interopRequireDefault(require("rc-util/lib/hooks/useMergedState")); | ||
var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper")); | ||
var _classnames = _interopRequireDefault(require("classnames")); | ||
var _toArray = _interopRequireDefault(require("rc-util/lib/Children/toArray")); | ||
@@ -34,2 +30,4 @@ | ||
var _warning = _interopRequireDefault(require("rc-util/lib/warning")); | ||
var React = _interopRequireWildcard(require("react")); | ||
@@ -41,3 +39,3 @@ | ||
var _MentionsContext = require("./MentionsContext"); | ||
var _MentionsContext = _interopRequireDefault(require("./MentionsContext")); | ||
@@ -48,395 +46,366 @@ var _Option = _interopRequireDefault(require("./Option")); | ||
var _excluded = ["prefixCls", "placement", "direction", "transitionName", "className", "style", "autoFocus", "notFoundContent", "getPopupContainer", "dropdownClassName"]; | ||
var _useEffectState = _interopRequireDefault(require("./hooks/useEffectState")); | ||
var Mentions = /*#__PURE__*/function (_React$Component) { | ||
(0, _inherits2.default)(Mentions, _React$Component); | ||
var _excluded = ["prefixCls", "className", "style", "prefix", "split", "notFoundContent", "value", "defaultValue", "children", "open", "validateSearch", "filterOption", "onChange", "onKeyDown", "onKeyUp", "onPressEnter", "onSearch", "onSelect", "onFocus", "onBlur", "transitionName", "placement", "direction", "getPopupContainer", "dropdownClassName"]; | ||
var _super = (0, _createSuper2.default)(Mentions); | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function Mentions(_props) { | ||
var _this; | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
(0, _classCallCheck2.default)(this, Mentions); | ||
_this = _super.call(this, _props); | ||
_this.textarea = void 0; | ||
_this.measure = void 0; | ||
_this.focusId = undefined; | ||
var Mentions = /*#__PURE__*/React.forwardRef(function (props, ref) { | ||
var prefixCls = props.prefixCls, | ||
className = props.className, | ||
style = props.style, | ||
prefix = props.prefix, | ||
split = props.split, | ||
notFoundContent = props.notFoundContent, | ||
value = props.value, | ||
defaultValue = props.defaultValue, | ||
children = props.children, | ||
open = props.open, | ||
validateSearch = props.validateSearch, | ||
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, | ||
restProps = (0, _objectWithoutProperties2.default)(props, _excluded); | ||
var mergedPrefix = Array.isArray(prefix) ? prefix : [prefix]; | ||
var mergedProps = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, { | ||
prefix: mergedPrefix | ||
}); // =============================== Refs =============================== | ||
_this.triggerChange = function (value) { | ||
var onChange = _this.props.onChange; | ||
var textareaRef = (0, React.useRef)(null); | ||
var measureRef = (0, React.useRef)(null); | ||
React.useImperativeHandle(ref, function () { | ||
return { | ||
focus: function focus() { | ||
var _textareaRef$current; | ||
if (!('value' in _this.props)) { | ||
_this.setState({ | ||
value: value | ||
}); | ||
} | ||
return (_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 ? void 0 : _textareaRef$current.focus(); | ||
}, | ||
blur: function blur() { | ||
var _textareaRef$current2; | ||
if (onChange) { | ||
onChange(value); | ||
return (_textareaRef$current2 = textareaRef.current) === null || _textareaRef$current2 === void 0 ? void 0 : _textareaRef$current2.blur(); | ||
} | ||
}; | ||
}); // ============================== State =============================== | ||
_this.onChange = function (_ref) { | ||
var value = _ref.target.value; | ||
var _useState = (0, React.useState)(false), | ||
_useState2 = (0, _slicedToArray2.default)(_useState, 2), | ||
measuring = _useState2[0], | ||
setMeasuring = _useState2[1]; | ||
_this.triggerChange(value); | ||
}; | ||
var _useState3 = (0, React.useState)(''), | ||
_useState4 = (0, _slicedToArray2.default)(_useState3, 2), | ||
measureText = _useState4[0], | ||
setMeasureText = _useState4[1]; | ||
_this.onKeyDown = function (event) { | ||
var which = event.which; | ||
var _this$state = _this.state, | ||
activeIndex = _this$state.activeIndex, | ||
measuring = _this$state.measuring; | ||
var clientOnKeyDown = _this.props.onKeyDown; | ||
var _useState5 = (0, React.useState)(''), | ||
_useState6 = (0, _slicedToArray2.default)(_useState5, 2), | ||
measurePrefix = _useState6[0], | ||
setMeasurePrefix = _useState6[1]; | ||
if (clientOnKeyDown) { | ||
clientOnKeyDown(event); | ||
} // Skip if not measuring | ||
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]; | ||
if (!measuring) { | ||
return; | ||
} | ||
var _useState11 = (0, React.useState)(false), | ||
_useState12 = (0, _slicedToArray2.default)(_useState11, 2), | ||
isFocus = _useState12[0], | ||
setIsFocus = _useState12[1]; // ============================== Value =============================== | ||
if (which === _KeyCode.default.UP || which === _KeyCode.default.DOWN) { | ||
// Control arrow function | ||
var optionLen = _this.getOptions().length; | ||
var offset = which === _KeyCode.default.UP ? -1 : 1; | ||
var newActiveIndex = (activeIndex + offset + optionLen) % optionLen; | ||
var _useMergedState = (0, _useMergedState3.default)('', { | ||
defaultValue: defaultValue, | ||
value: value | ||
}), | ||
_useMergedState2 = (0, _slicedToArray2.default)(_useMergedState, 2), | ||
mergedValue = _useMergedState2[0], | ||
setMergedValue = _useMergedState2[1]; // =============================== Open =============================== | ||
_this.setState({ | ||
activeIndex: newActiveIndex | ||
}); | ||
event.preventDefault(); | ||
} else if (which === _KeyCode.default.ESC) { | ||
_this.stopMeasure(); | ||
} else if (which === _KeyCode.default.ENTER) { | ||
// Measure hit | ||
event.preventDefault(); | ||
var _React$useMemo = React.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.'); | ||
} | ||
var options = _this.getOptions(); | ||
for (var i = 0; i < mergedPrefix.length; i += 1) { | ||
var curPrefix = mergedPrefix[i]; | ||
var index = mergedValue.lastIndexOf(curPrefix); | ||
if (!options.length) { | ||
_this.stopMeasure(); | ||
return; | ||
if (index >= 0) { | ||
return [true, '', curPrefix, index]; | ||
} | ||
} | ||
} | ||
var option = options[activeIndex]; | ||
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 ============================== | ||
_this.selectOption(option); | ||
var getOptions = React.useCallback(function (targetMeasureText) { | ||
var list = (0, _toArray.default)(children).map(function (_ref) { | ||
var optionProps = _ref.props, | ||
key = _ref.key; | ||
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, optionProps), {}, { | ||
key: key || optionProps.value | ||
}); | ||
}).filter(function (option) { | ||
/** Return all result if `filterOption` is false. */ | ||
if (filterOption === false) { | ||
return true; | ||
} | ||
}; | ||
_this.onKeyUp = function (event) { | ||
var key = event.key, | ||
which = event.which; | ||
var _this$state2 = _this.state, | ||
prevMeasureText = _this$state2.measureText, | ||
measuring = _this$state2.measuring; | ||
var _this$props = _this.props, | ||
_this$props$prefix = _this$props.prefix, | ||
prefix = _this$props$prefix === void 0 ? '' : _this$props$prefix, | ||
clientOnKeyUp = _this$props.onKeyUp, | ||
onSearch = _this$props.onSearch, | ||
validateSearch = _this$props.validateSearch; | ||
var target = event.target; | ||
var selectionStartText = (0, _util.getBeforeSelectionText)(target); | ||
return filterOption(targetMeasureText, option); | ||
}); | ||
return list; | ||
}, [children, filterOption]); | ||
var options = React.useMemo(function () { | ||
return getOptions(mergedMeasureText); | ||
}, [getOptions, mergedMeasureText]); // ============================= Measure ============================== | ||
// Mark that we will reset input selection to target position when user select option | ||
var _getLastMeasureIndex = (0, _util.getLastMeasureIndex)(selectionStartText, prefix), | ||
measureIndex = _getLastMeasureIndex.location, | ||
measurePrefix = _getLastMeasureIndex.prefix; // If the client implements an onKeyUp handler, call it | ||
var onSelectionEffect = (0, _useEffectState.default)(); | ||
var startMeasure = function startMeasure(nextMeasureText, nextMeasurePrefix, nextMeasureLocation) { | ||
setMeasuring(true); | ||
setMeasureText(nextMeasureText); | ||
setMeasurePrefix(nextMeasurePrefix); | ||
setMeasureLocation(nextMeasureLocation); | ||
setActiveIndex(0); | ||
}; | ||
if (clientOnKeyUp) { | ||
clientOnKeyUp(event); | ||
} // Skip if match the white key list | ||
var stopMeasure = function stopMeasure(callback) { | ||
setMeasuring(false); | ||
setMeasureLocation(0); | ||
setMeasureText(''); | ||
onSelectionEffect(callback); | ||
}; // ============================== Change ============================== | ||
if ([_KeyCode.default.ESC, _KeyCode.default.UP, _KeyCode.default.DOWN, _KeyCode.default.ENTER].indexOf(which) !== -1) { | ||
return; | ||
} | ||
var triggerChange = function triggerChange(nextValue) { | ||
setMergedValue(nextValue); | ||
onChange === null || onChange === void 0 ? void 0 : onChange(nextValue); | ||
}; | ||
if (measureIndex !== -1) { | ||
var measureText = selectionStartText.slice(measureIndex + measurePrefix.length); | ||
var validateMeasure = validateSearch(measureText, _this.props); | ||
var matchOption = !!_this.getOptions(measureText).length; | ||
var onInternalChange = function onInternalChange(_ref2) { | ||
var nextValue = _ref2.target.value; | ||
triggerChange(nextValue); | ||
}; | ||
if (validateMeasure) { | ||
if (key === measurePrefix || key === 'Shift' || measuring || measureText !== prevMeasureText && matchOption) { | ||
_this.startMeasure(measureText, measurePrefix, measureIndex); | ||
} | ||
} else if (measuring) { | ||
// Stop if measureText is invalidate | ||
_this.stopMeasure(); | ||
} | ||
/** | ||
* We will trigger `onSearch` to developer since they may use for async update. | ||
* If met `space` means user finished searching. | ||
*/ | ||
var selectOption = function selectOption(option) { | ||
var _getTextArea; | ||
var getTextArea = function getTextArea() { | ||
var _textareaRef$current3, _textareaRef$current4; | ||
if (onSearch && validateMeasure) { | ||
onSearch(measureText, measurePrefix); | ||
} | ||
} else if (measuring) { | ||
_this.stopMeasure(); | ||
} | ||
return (_textareaRef$current3 = textareaRef.current) === null || _textareaRef$current3 === void 0 ? void 0 : (_textareaRef$current4 = _textareaRef$current3.resizableTextArea) === null || _textareaRef$current4 === void 0 ? void 0 : _textareaRef$current4.textArea; | ||
}; | ||
_this.onPressEnter = function (event) { | ||
var measuring = _this.state.measuring; | ||
var onPressEnter = _this.props.onPressEnter; | ||
var _option$value = option.value, | ||
mentionValue = _option$value === void 0 ? '' : _option$value; | ||
if (!measuring && onPressEnter) { | ||
onPressEnter(event); | ||
} | ||
}; | ||
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; | ||
_this.onInputFocus = function (event) { | ||
_this.onFocus(event); | ||
}; | ||
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 | ||
_this.onInputBlur = function (event) { | ||
_this.onBlur(event); | ||
}; | ||
_this.onDropdownFocus = function () { | ||
_this.onFocus(); | ||
}; | ||
var onInternalKeyDown = function onInternalKeyDown(event) { | ||
var which = event.which; | ||
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event); // Skip if not measuring | ||
_this.onDropdownBlur = function () { | ||
_this.onBlur(); | ||
}; | ||
if (!mergedMeasuring) { | ||
return; | ||
} | ||
_this.onFocus = function (event) { | ||
window.clearTimeout(_this.focusId); | ||
var isFocus = _this.state.isFocus; | ||
var onFocus = _this.props.onFocus; | ||
if (which === _KeyCode.default.UP || which === _KeyCode.default.DOWN) { | ||
// Control arrow function | ||
var optionLen = options.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 (!isFocus && event && onFocus) { | ||
onFocus(event); | ||
if (!options.length) { | ||
stopMeasure(); | ||
return; | ||
} | ||
_this.setState({ | ||
isFocus: true | ||
}); | ||
}; | ||
var option = options[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 | ||
*/ | ||
_this.onBlur = function (event) { | ||
_this.focusId = window.setTimeout(function () { | ||
var onBlur = _this.props.onBlur; | ||
_this.setState({ | ||
isFocus: false | ||
}); | ||
var onInternalKeyUp = function onInternalKeyUp(event) { | ||
var key = event.key, | ||
which = event.which; | ||
var target = event.target; | ||
var selectionStartText = (0, _util.getBeforeSelectionText)(target); | ||
_this.stopMeasure(); | ||
var _getLastMeasureIndex = (0, _util.getLastMeasureIndex)(selectionStartText, mergedPrefix), | ||
measureIndex = _getLastMeasureIndex.location, | ||
nextMeasurePrefix = _getLastMeasureIndex.prefix; // If the client implements an onKeyUp handler, call it | ||
if (onBlur) { | ||
onBlur(event); | ||
} | ||
}, 0); | ||
}; | ||
_this.selectOption = function (option) { | ||
var _this$state3 = _this.state, | ||
value = _this$state3.value, | ||
measureLocation = _this$state3.measureLocation, | ||
measurePrefix = _this$state3.measurePrefix; | ||
var _this$props2 = _this.props, | ||
split = _this$props2.split, | ||
onSelect = _this$props2.onSelect; | ||
var _option$value = option.value, | ||
mentionValue = _option$value === void 0 ? '' : _option$value; | ||
onKeyUp === null || onKeyUp === void 0 ? void 0 : onKeyUp(event); // Skip if match the white key list | ||
var _replaceWithMeasure = (0, _util.replaceWithMeasure)(value, { | ||
measureLocation: measureLocation, | ||
targetText: mentionValue, | ||
prefix: measurePrefix, | ||
selectionStart: _this.textarea.selectionStart, | ||
split: split | ||
}), | ||
text = _replaceWithMeasure.text, | ||
selectionLocation = _replaceWithMeasure.selectionLocation; | ||
if ([_KeyCode.default.ESC, _KeyCode.default.UP, _KeyCode.default.DOWN, _KeyCode.default.ENTER].indexOf(which) !== -1) { | ||
return; | ||
} | ||
_this.triggerChange(text); | ||
if (measureIndex !== -1) { | ||
var nextMeasureText = selectionStartText.slice(measureIndex + nextMeasurePrefix.length); | ||
var validateMeasure = validateSearch(nextMeasureText, mergedProps); | ||
var matchOption = !!getOptions(nextMeasureText).length; | ||
_this.stopMeasure(function () { | ||
// We need restore the selection position | ||
(0, _util.setInputSelection)(_this.textarea, selectionLocation); | ||
}); | ||
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 (onSelect) { | ||
onSelect(option, measurePrefix); | ||
if (onSearch && validateMeasure) { | ||
onSearch(nextMeasureText, nextMeasurePrefix); | ||
} | ||
}; | ||
} else if (mergedMeasuring) { | ||
stopMeasure(); | ||
} | ||
}; | ||
_this.setActiveIndex = function (activeIndex) { | ||
_this.setState({ | ||
activeIndex: activeIndex | ||
}); | ||
}; | ||
var onInternalPressEnter = function onInternalPressEnter(event) { | ||
if (!mergedMeasuring && onPressEnter) { | ||
onPressEnter(event); | ||
} | ||
}; // ============================ Focus Blur ============================ | ||
_this.setTextAreaRef = function (element) { | ||
var _element$resizableTex; | ||
_this.textarea = element === null || element === void 0 ? void 0 : (_element$resizableTex = element.resizableTextArea) === null || _element$resizableTex === void 0 ? void 0 : _element$resizableTex.textArea; | ||
}; | ||
var focusRef = (0, React.useRef)(); | ||
_this.setMeasureRef = function (element) { | ||
_this.measure = element; | ||
}; | ||
var onInternalFocus = function onInternalFocus(event) { | ||
window.clearTimeout(focusRef.current); | ||
_this.getOptions = function (measureText) { | ||
var targetMeasureText = measureText || _this.state.measureText || ''; | ||
var _this$props3 = _this.props, | ||
children = _this$props3.children, | ||
filterOption = _this$props3.filterOption; | ||
var list = (0, _toArray.default)(children).map(function (_ref2) { | ||
var props = _ref2.props, | ||
key = _ref2.key; | ||
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, { | ||
key: key || props.value | ||
}); | ||
}).filter(function (option) { | ||
/** Return all result if `filterOption` is false. */ | ||
if (filterOption === false) { | ||
return true; | ||
} | ||
if (!isFocus && event && onFocus) { | ||
onFocus(event); | ||
} | ||
return filterOption(targetMeasureText, option); | ||
}); | ||
return list; | ||
}; | ||
setIsFocus(true); | ||
}; | ||
_this.state = { | ||
value: _props.defaultValue || _props.value || '', | ||
measuring: false, | ||
measureLocation: 0, | ||
measureText: null, | ||
measurePrefix: '', | ||
activeIndex: 0, | ||
isFocus: false | ||
}; | ||
return _this; | ||
} | ||
var onInternalBlur = function onInternalBlur(event) { | ||
focusRef.current = window.setTimeout(function () { | ||
setIsFocus(false); | ||
stopMeasure(); | ||
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event); | ||
}, 0); | ||
}; | ||
(0, _createClass2.default)(Mentions, [{ | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
var measuring = this.state.measuring; // Sync measure div top with textarea for rc-trigger usage | ||
var onDropdownFocus = function onDropdownFocus() { | ||
onInternalFocus(); | ||
}; | ||
if (measuring) { | ||
this.measure.scrollTop = this.textarea.scrollTop; | ||
} | ||
} | ||
}, { | ||
key: "startMeasure", | ||
value: function startMeasure(measureText, measurePrefix, measureLocation) { | ||
this.setState({ | ||
measuring: true, | ||
measureText: measureText, | ||
measurePrefix: measurePrefix, | ||
measureLocation: measureLocation, | ||
activeIndex: 0 | ||
}); | ||
} | ||
}, { | ||
key: "stopMeasure", | ||
value: function stopMeasure(callback) { | ||
this.setState({ | ||
measuring: false, | ||
measureLocation: 0, | ||
measureText: null | ||
}, callback); | ||
} | ||
}, { | ||
key: "focus", | ||
value: function focus() { | ||
this.textarea.focus(); | ||
} | ||
}, { | ||
key: "blur", | ||
value: function blur() { | ||
this.textarea.blur(); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this$state4 = this.state, | ||
value = _this$state4.value, | ||
measureLocation = _this$state4.measureLocation, | ||
measurePrefix = _this$state4.measurePrefix, | ||
measuring = _this$state4.measuring, | ||
activeIndex = _this$state4.activeIndex; | ||
var _this$props4 = this.props, | ||
prefixCls = _this$props4.prefixCls, | ||
placement = _this$props4.placement, | ||
direction = _this$props4.direction, | ||
transitionName = _this$props4.transitionName, | ||
className = _this$props4.className, | ||
style = _this$props4.style, | ||
autoFocus = _this$props4.autoFocus, | ||
notFoundContent = _this$props4.notFoundContent, | ||
getPopupContainer = _this$props4.getPopupContainer, | ||
dropdownClassName = _this$props4.dropdownClassName, | ||
restProps = (0, _objectWithoutProperties2.default)(_this$props4, _excluded); | ||
var inputProps = (0, _util.omit)(restProps, 'value', 'defaultValue', 'prefix', 'split', 'children', 'validateSearch', 'filterOption', 'onSelect', 'onSearch'); | ||
var options = measuring ? this.getOptions() : []; | ||
return /*#__PURE__*/React.createElement("div", { | ||
className: (0, _classnames.default)(prefixCls, className), | ||
style: style | ||
}, /*#__PURE__*/React.createElement(_rcTextarea.default, (0, _extends2.default)({ | ||
autoFocus: autoFocus, | ||
ref: this.setTextAreaRef, | ||
value: value | ||
}, inputProps, { | ||
onChange: this.onChange, | ||
onKeyDown: this.onKeyDown, | ||
onKeyUp: this.onKeyUp, | ||
onPressEnter: this.onPressEnter, | ||
onFocus: this.onInputFocus, | ||
onBlur: this.onInputBlur | ||
})), measuring && /*#__PURE__*/React.createElement("div", { | ||
ref: this.setMeasureRef, | ||
className: "".concat(prefixCls, "-measure") | ||
}, value.slice(0, measureLocation), /*#__PURE__*/React.createElement(_MentionsContext.MentionsContextProvider, { | ||
value: { | ||
notFoundContent: notFoundContent, | ||
activeIndex: activeIndex, | ||
setActiveIndex: this.setActiveIndex, | ||
selectOption: this.selectOption, | ||
onFocus: this.onDropdownFocus, | ||
onBlur: this.onDropdownBlur | ||
} | ||
}, /*#__PURE__*/React.createElement(_KeywordTrigger.default, { | ||
prefixCls: prefixCls, | ||
transitionName: transitionName, | ||
placement: placement, | ||
direction: direction, | ||
options: options, | ||
visible: true, | ||
getPopupContainer: getPopupContainer, | ||
dropdownClassName: dropdownClassName | ||
}, /*#__PURE__*/React.createElement("span", null, measurePrefix))), value.slice(measureLocation + measurePrefix.length))); | ||
} | ||
}], [{ | ||
key: "getDerivedStateFromProps", | ||
value: function getDerivedStateFromProps(props, prevState) { | ||
var newState = {}; | ||
var onDropdownBlur = function onDropdownBlur() { | ||
onInternalBlur(); | ||
}; // ============================== Render ============================== | ||
if ('value' in props && props.value !== prevState.value) { | ||
newState.value = props.value || ''; | ||
} | ||
return newState; | ||
return /*#__PURE__*/React.createElement("div", { | ||
className: (0, _classnames.default)(prefixCls, className), | ||
style: style | ||
}, /*#__PURE__*/React.createElement(_rcTextarea.default, (0, _extends2.default)({ | ||
ref: textareaRef, | ||
value: mergedValue | ||
}, restProps, { | ||
onChange: onInternalChange, | ||
onKeyDown: onInternalKeyDown, | ||
onKeyUp: onInternalKeyUp, | ||
onPressEnter: onInternalPressEnter, | ||
onFocus: onInternalFocus, | ||
onBlur: onInternalBlur | ||
})), mergedMeasuring && /*#__PURE__*/React.createElement("div", { | ||
ref: measureRef, | ||
className: "".concat(prefixCls, "-measure") | ||
}, mergedValue.slice(0, mergedMeasureLocation), /*#__PURE__*/React.createElement(_MentionsContext.default.Provider, { | ||
value: { | ||
notFoundContent: notFoundContent, | ||
activeIndex: activeIndex, | ||
setActiveIndex: setActiveIndex, | ||
selectOption: selectOption, | ||
onFocus: onDropdownFocus, | ||
onBlur: onDropdownBlur | ||
} | ||
}]); | ||
return Mentions; | ||
}(React.Component); | ||
Mentions.Option = _Option.default; | ||
}, /*#__PURE__*/React.createElement(_KeywordTrigger.default, { | ||
prefixCls: prefixCls, | ||
transitionName: transitionName, | ||
placement: placement, | ||
direction: direction, | ||
options: options, | ||
visible: true, | ||
getPopupContainer: getPopupContainer, | ||
dropdownClassName: dropdownClassName | ||
}, /*#__PURE__*/React.createElement("span", null, mergedMeasurePrefix))), mergedValue.slice(mergedMeasureLocation + mergedMeasurePrefix.length))); | ||
}); | ||
Mentions.defaultProps = { | ||
@@ -451,3 +420,4 @@ prefixCls: 'rc-mentions', | ||
}; | ||
Mentions.Option = _Option.default; | ||
var _default = Mentions; | ||
exports.default = _default; |
import * as React from 'react'; | ||
import { OptionProps } from './Option'; | ||
import type { OptionProps } from './Option'; | ||
export interface MentionsContextProps { | ||
@@ -11,3 +11,3 @@ notFoundContent: React.ReactNode; | ||
} | ||
export declare const MentionsContextProvider: React.Provider<MentionsContextProps>; | ||
export declare const MentionsContextConsumer: React.Consumer<MentionsContextProps>; | ||
declare const MentionsContext: React.Context<MentionsContextProps>; | ||
export default MentionsContext; |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _typeof = require("@babel/runtime/helpers/typeof"); | ||
@@ -8,12 +8,14 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.MentionsContextProvider = exports.MentionsContextConsumer = void 0; | ||
exports.default = void 0; | ||
var React = _interopRequireWildcard(require("react")); | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
/* tslint:disable: no-object-literal-type-assertion */ | ||
// We will never use default, here only to fix TypeScript warning | ||
var MentionsContext = /*#__PURE__*/React.createContext(null); | ||
var MentionsContextProvider = MentionsContext.Provider; | ||
exports.MentionsContextProvider = MentionsContextProvider; | ||
var MentionsContextConsumer = MentionsContext.Consumer; | ||
exports.MentionsContextConsumer = MentionsContextConsumer; | ||
var _default = MentionsContext; | ||
exports.default = _default; |
@@ -1,8 +0,3 @@ | ||
import { MentionsProps } from './Mentions'; | ||
import { OptionProps } from './Option'; | ||
export declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||
declare type OmitFunc = <T extends object, K extends [...(keyof T)[]]>(obj: T, ...keys: K) => { | ||
[K2 in Exclude<keyof T, K[number]>]: T[K2]; | ||
}; | ||
export declare const omit: OmitFunc; | ||
import type { MentionsProps } from './Mentions'; | ||
import type { OptionProps } from './Option'; | ||
/** | ||
@@ -19,3 +14,3 @@ * Cut input selection into 2 part and return text before selection start | ||
*/ | ||
export declare function getLastMeasureIndex(text: string, prefix?: string | string[]): MeasureIndex; | ||
export declare function getLastMeasureIndex(text: string, prefix: string[]): MeasureIndex; | ||
interface MeasureConfig { | ||
@@ -22,0 +17,0 @@ measureLocation: number; |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -11,3 +9,2 @@ value: true | ||
exports.getLastMeasureIndex = getLastMeasureIndex; | ||
exports.omit = void 0; | ||
exports.replaceWithMeasure = replaceWithMeasure; | ||
@@ -17,23 +14,5 @@ exports.setInputSelection = setInputSelection; | ||
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); | ||
var omit = function omit(obj) { | ||
var clone = (0, _objectSpread2.default)({}, obj); | ||
for (var _len = arguments.length, keys = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
keys.forEach(function (key) { | ||
delete clone[key]; | ||
}); | ||
return clone; | ||
}; | ||
/** | ||
* Cut input selection into 2 part and return text before selection start | ||
*/ | ||
exports.omit = omit; | ||
function getBeforeSelectionText(input) { | ||
@@ -48,6 +27,4 @@ var selectionStart = input.selectionStart; | ||
function getLastMeasureIndex(text) { | ||
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; | ||
var prefixList = Array.isArray(prefix) ? prefix : [prefix]; | ||
return prefixList.reduce(function (lastMatch, prefixStr) { | ||
function getLastMeasureIndex(text, prefix) { | ||
return prefix.reduce(function (lastMatch, prefixStr) { | ||
var lastIndex = text.lastIndexOf(prefixStr); | ||
@@ -54,0 +31,0 @@ |
{ | ||
"name": "rc-mentions", | ||
"version": "1.8.0", | ||
"version": "1.9.0", | ||
"description": "React Mentions", | ||
@@ -42,4 +42,5 @@ "keywords": [ | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "^5.16.4", | ||
"@testing-library/react": "^13.3.0", | ||
"@types/classnames": "^2.2.6", | ||
"@types/enzyme": "^3.1.15", | ||
"@types/react": "^18.0.8", | ||
@@ -49,4 +50,2 @@ "@types/react-dom": "^18.0.3", | ||
"@umijs/fabric": "^2.0.8", | ||
"enzyme": "^3.11.0", | ||
"enzyme-to-json": "^3.1.4", | ||
"eslint": "^7.0.0", | ||
@@ -58,4 +57,4 @@ "father": "^2.13.6", | ||
"prettier": "^2.0.5", | ||
"react": "^16.0.0", | ||
"react-dom": "^16.0.0", | ||
"react": "^18.0.0", | ||
"react-dom": "^18.0.0", | ||
"typescript": "^4.0.3" | ||
@@ -69,4 +68,4 @@ }, | ||
"rc-trigger": "^5.0.4", | ||
"rc-util": "^5.0.1" | ||
"rc-util": "^5.22.5" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
71609
16
36
1568
2
Updatedrc-util@^5.22.5