From ba94448edd951b70f7590a868df69055938b7abd Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 11 Sep 2023 09:02:06 +0900 Subject: [PATCH 1/5] remove react-autosize-textarea and wrap autosize directly --- package.json | 3 +- .../js/beatmap-discussions/new-discussion.tsx | 4 +- .../js/beatmap-discussions/new-reply.tsx | 4 +- resources/js/beatmap-discussions/post.tsx | 4 +- resources/js/chat/input-box.tsx | 4 +- resources/js/components/comment-editor.tsx | 6 +- resources/js/components/textarea-autosize.tsx | 69 +++++++++++++++++++ resources/js/oauth/client-details.tsx | 2 +- resources/js/oauth/new-client.tsx | 2 +- yarn.lock | 36 +++------- 10 files changed, 94 insertions(+), 40 deletions(-) create mode 100644 resources/js/components/textarea-autosize.tsx diff --git a/package.json b/package.json index 3478d451ca9..2f24fe301a0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@types/timeago": "^1.6.0", "@types/unist": "^2.0.6", "autoprefixer": "^9.8.6", + "autosize": "^6.0.1", "blueimp-file-upload": "^9.11.2", "bootstrap": "^3.3.6", "chokidar": "^3.5.2", @@ -73,7 +74,6 @@ "postcss-loader": "^3.0.0", "qtip2": "https://github.com/notbakaneko/qTip2.git#cd5f038667d2b23a44f4274c46de01834d704ce6", "react": "^17.0.2", - "react-autosize-textarea": "7.0.0", "react-dom": "^17.0.2", "react-dom-factories": "^1.0.0", "react-markdown": "^8.0.5", @@ -101,6 +101,7 @@ "yargs": "^12.0.5" }, "devDependencies": { + "@types/autosize": "^4.0.1", "@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/parser": "^5.29.0", "deasync": "^0.1.26", diff --git a/resources/js/beatmap-discussions/new-discussion.tsx b/resources/js/beatmap-discussions/new-discussion.tsx index a3ff4f146d3..fabfeea26ee 100644 --- a/resources/js/beatmap-discussions/new-discussion.tsx +++ b/resources/js/beatmap-discussions/new-discussion.tsx @@ -4,6 +4,7 @@ import { DiscussionType, discussionTypeIcons, discussionTypes } from 'beatmap-discussions/discussion-type'; import BigButton from 'components/big-button'; import StringWithComponent from 'components/string-with-component'; +import TextareaAutosize from 'components/textarea-autosize'; import TimeWithTooltip from 'components/time-with-tooltip'; import UserAvatar from 'components/user-avatar'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; @@ -16,7 +17,6 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx' import { observer } from 'mobx-react'; import core from 'osu-core-singleton'; import * as React from 'react'; -import TextareaAutosize from 'react-autosize-textarea'; import { onError } from 'utils/ajax'; import { canModeratePosts, formatTimestamp, makeUrl, NearbyDiscussion, nearbyDiscussions, parseTimestamp, validMessageLength } from 'utils/beatmapset-discussion-helper'; import { downloadLimited, nominationsCount } from 'utils/beatmapset-helper'; @@ -391,9 +391,9 @@ export class NewDiscussion extends React.Component { return ( <> {
{ ) : ( <> { return (
. Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +import TextareaAutosize from 'components/textarea-autosize'; import { CommentableMetaJson } from 'interfaces/comment-json'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import Comment from 'models/comment'; import core from 'osu-core-singleton'; import * as React from 'react'; -import TextareaAutosize from 'react-autosize-textarea'; import { classWithModifiers, Modifiers } from 'utils/css'; import { InputEventType, makeTextAreaHandler, TextAreaCallback } from 'utils/input-handler'; import { trans } from 'utils/lang'; @@ -115,9 +115,9 @@ export default class CommentEditor extends React.Component { } { }; @action - private readonly onChange = (e: React.KeyboardEvent) => { + private readonly onChange = (e: React.ChangeEvent) => { this.message = e.currentTarget.value; }; diff --git a/resources/js/components/textarea-autosize.tsx b/resources/js/components/textarea-autosize.tsx new file mode 100644 index 00000000000..3ba5f6bb7af --- /dev/null +++ b/resources/js/components/textarea-autosize.tsx @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +import autosize from 'autosize'; +import React from 'react'; + +interface Props extends React.TextareaHTMLAttributes { + async: boolean; + innerRef?: React.RefObject; + maxRows?: number; +} + +export default class TextareaAutosize extends React.Component { + static readonly defaultProps = { + async: false, + rows: 1, + }; + + private lineHeight?: number; + private ref = this.props.innerRef ?? React.createRef(); + + private get maxHeight() { + return this.props.maxRows != null && this.lineHeight + ? Math.ceil(this.lineHeight * this.props.maxRows) + : null; + } + + componentDidMount() { + if (this.ref.current == null) return; + + if (this.props.maxRows != null) { + this.lineHeight = parseFloat(window.getComputedStyle(this.ref.current).getPropertyValue('line-height')); + } + + if (this.props.maxRows != null || this.props.async) { + window.setTimeout(() => { + if (this.ref.current != null) { + autosize(this.ref.current); + } + }, 0); + } else { + autosize(this.ref.current); + } + } + + componentDidUpdate() { + if (this.ref.current == null) return; + autosize.update(this.ref.current); + } + + componentWillUnmount() { + if (this.ref.current == null) return; + autosize.destroy(this.ref.current); + } + + render() { + const { async, innerRef, maxRows, style, ...otherProps } = this.props; + + const maxHeight = this.maxHeight; + + return ( +