From f39efa1b24cac3d87df72378ebd83c8c793a5f24 Mon Sep 17 00:00:00 2001 From: Kermit Date: Thu, 11 Jun 2020 19:33:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20replace=20textarea=20with=20rc-?= =?UTF-8?q?textarea=20to=20support=20autoSize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ examples/textarea.js | 8 +++++++ package.json | 1 + src/Mentions.tsx | 52 +++++++++++++------------------------------- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index c28f6e9..1dbc332 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,9 @@ React.render(, container); | onFocus | Trigger when mentions get focus | React.FocusEventHandler | - | | onBlur | Trigger when mentions lose focus | React.FocusEventHandler | - | | getPopupContainer | DOM Container for suggestions | () => HTMLElement | - | +| autoSize | Textarea height autosize feature, can be set to `true\|false` or an object `{ minRows: 2, maxRows: 6 }` | boolean \| object | - | +| onPressEnter | The callback function that is triggered when Enter key is pressed | function(e) | - | +| onResize | The callback function that is triggered when textarea resize | function({ width, height }) | - | ### Methods diff --git a/examples/textarea.js b/examples/textarea.js index 3a1ea29..b7d6d70 100644 --- a/examples/textarea.js +++ b/examples/textarea.js @@ -21,6 +21,14 @@ export default () => ( +
+ + + + + +
+
diff --git a/package.json b/package.json index 6836867..7147a09 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", "rc-menu": "^8.0.1", + "rc-textarea": "^0.2.0", "rc-trigger": "^4.3.0", "rc-util": "^5.0.1" } diff --git a/src/Mentions.tsx b/src/Mentions.tsx index 0263c2d..cf7b78e 100644 --- a/src/Mentions.tsx +++ b/src/Mentions.tsx @@ -2,6 +2,7 @@ import classNames from 'classnames'; import toArray from 'rc-util/lib/Children/toArray'; import KeyCode from 'rc-util/lib/KeyCode'; import * as React from 'react'; +import TextArea, { TextAreaProps } from 'rc-textarea'; import KeywordTrigger from './KeywordTrigger'; import { MentionsContextProvider } from './MentionsContext'; import Option, { OptionProps } from './Option'; @@ -16,10 +17,7 @@ import { validateSearch as defaultValidateSearch, } from './util'; -type BaseTextareaAttrs = Omit< - React.TextareaHTMLAttributes, - 'prefix' | 'onChange' | 'onSelect' ->; +type BaseTextareaAttrs = Omit; export type Placement = 'top' | 'bottom'; export type Direction = 'ltr' | 'rtl'; @@ -74,10 +72,7 @@ class Mentions extends React.Component { rows: 1, }; - public static getDerivedStateFromProps( - props: MentionsProps, - prevState: MentionsState, - ) { + public static getDerivedStateFromProps(props: MentionsProps, prevState: MentionsState) { const newState: Partial = {}; if ('value' in props && props.value !== prevState.value) { @@ -120,9 +115,7 @@ class Mentions extends React.Component { } }; - public onChange: React.ChangeEventHandler = ({ - target: { value }, - }) => { + public onChange: React.ChangeEventHandler = ({ target: { value } }) => { this.triggerChange(value); }; @@ -173,23 +166,18 @@ class Mentions extends React.Component { const { prefix = '', onSearch, validateSearch } = this.props; const target = event.target as HTMLTextAreaElement; const selectionStartText = getBeforeSelectionText(target); - const { - location: measureIndex, - prefix: measurePrefix, - } = getLastMeasureIndex(selectionStartText, prefix); + const { location: measureIndex, prefix: measurePrefix } = getLastMeasureIndex( + selectionStartText, + prefix, + ); // Skip if match the white key list - if ( - [KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !== - -1 - ) { + if ([KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !== -1) { return; } if (measureIndex !== -1) { - const measureText = selectionStartText.slice( - measureIndex + measurePrefix.length, - ); + const measureText = selectionStartText.slice(measureIndex + measurePrefix.length); const validateMeasure: boolean = validateSearch(measureText, this.props); const matchOption = !!this.getOptions(measureText).length; @@ -284,8 +272,8 @@ class Mentions extends React.Component { }); }; - public setTextAreaRef = (element: HTMLTextAreaElement) => { - this.textarea = element; + public setTextAreaRef = (element: TextArea) => { + this.textarea = element.resizableTextArea.textArea; }; public setMeasureRef = (element: HTMLDivElement) => { @@ -307,11 +295,7 @@ class Mentions extends React.Component { return list; }; - public startMeasure( - measureText: string, - measurePrefix: string, - measureLocation: number, - ) { + public startMeasure(measureText: string, measurePrefix: string, measureLocation: number) { this.setState({ measuring: true, measureText, @@ -341,13 +325,7 @@ class Mentions extends React.Component { } public render() { - const { - value, - measureLocation, - measurePrefix, - measuring, - activeIndex, - } = this.state; + const { value, measureLocation, measurePrefix, measuring, activeIndex } = this.state; const { prefixCls, placement, @@ -378,7 +356,7 @@ class Mentions extends React.Component { return (
-