From e014826b1763b7a47364ae27d86e4bf2d805e063 Mon Sep 17 00:00:00 2001 From: ta264 Date: Mon, 7 Sep 2020 21:05:07 +0100 Subject: [PATCH] New TEXT_AREA input type --- .../src/Components/Form/FormInputGroup.js | 4 + frontend/src/Components/Form/TextArea.css | 19 ++ frontend/src/Components/Form/TextArea.js | 172 ++++++++++++++++++ frontend/src/Helpers/Props/inputTypes.js | 2 + 4 files changed, 197 insertions(+) create mode 100644 frontend/src/Components/Form/TextArea.css create mode 100644 frontend/src/Components/Form/TextArea.js diff --git a/frontend/src/Components/Form/FormInputGroup.js b/frontend/src/Components/Form/FormInputGroup.js index 66d63bdbc..250a0eb88 100644 --- a/frontend/src/Components/Form/FormInputGroup.js +++ b/frontend/src/Components/Form/FormInputGroup.js @@ -20,6 +20,7 @@ import QualityProfileSelectInputConnector from './QualityProfileSelectInputConne import RootFolderSelectInputConnector from './RootFolderSelectInputConnector'; import TagInputConnector from './TagInputConnector'; import TagSelectInputConnector from './TagSelectInputConnector'; +import TextArea from './TextArea'; import TextInput from './TextInput'; import TextTagInputConnector from './TextTagInputConnector'; import styles from './FormInputGroup.css'; @@ -71,6 +72,9 @@ function getComponent(type) { case inputTypes.TAG: return TagInputConnector; + case inputTypes.TEXT_AREA: + return TextArea; + case inputTypes.TEXT_TAG: return TextTagInputConnector; diff --git a/frontend/src/Components/Form/TextArea.css b/frontend/src/Components/Form/TextArea.css new file mode 100644 index 000000000..7a4961c07 --- /dev/null +++ b/frontend/src/Components/Form/TextArea.css @@ -0,0 +1,19 @@ +.input { + composes: input from '~Components/Form/Input.css'; + + flex-grow: 1; + min-height: 200px; + resize: vertical; +} + +.readOnly { + background-color: #eee; +} + +.hasError { + composes: hasError from '~Components/Form/Input.css'; +} + +.hasWarning { + composes: hasWarning from '~Components/Form/Input.css'; +} diff --git a/frontend/src/Components/Form/TextArea.js b/frontend/src/Components/Form/TextArea.js new file mode 100644 index 000000000..5da04dc78 --- /dev/null +++ b/frontend/src/Components/Form/TextArea.js @@ -0,0 +1,172 @@ +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './TextArea.css'; + +class TextArea extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._input = null; + this._selectionStart = null; + this._selectionEnd = null; + this._selectionTimeout = null; + this._isMouseTarget = false; + } + + componentDidMount() { + window.addEventListener('mouseup', this.onDocumentMouseUp); + } + + componentWillUnmount() { + window.removeEventListener('mouseup', this.onDocumentMouseUp); + + if (this._selectionTimeout) { + this._selectionTimeout = clearTimeout(this._selectionTimeout); + } + } + + // + // Control + + setInputRef = (ref) => { + this._input = ref; + } + + selectionChange() { + if (this._selectionTimeout) { + this._selectionTimeout = clearTimeout(this._selectionTimeout); + } + + this._selectionTimeout = setTimeout(() => { + const selectionStart = this._input.selectionStart; + const selectionEnd = this._input.selectionEnd; + + const selectionChanged = ( + this._selectionStart !== selectionStart || + this._selectionEnd !== selectionEnd + ); + + this._selectionStart = selectionStart; + this._selectionEnd = selectionEnd; + + if (this.props.onSelectionChange && selectionChanged) { + this.props.onSelectionChange(selectionStart, selectionEnd); + } + }, 10); + } + + // + // Listeners + + onChange = (event) => { + const { + name, + onChange + } = this.props; + + const payload = { + name, + value: event.target.value + }; + + onChange(payload); + } + + onFocus = (event) => { + if (this.props.onFocus) { + this.props.onFocus(event); + } + + this.selectionChange(); + } + + onKeyUp = () => { + this.selectionChange(); + } + + onMouseDown = () => { + this._isMouseTarget = true; + } + + onMouseUp = () => { + this.selectionChange(); + } + + onDocumentMouseUp = () => { + if (this._isMouseTarget) { + this.selectionChange(); + } + + this._isMouseTarget = false; + } + + // + // Render + + render() { + const { + className, + readOnly, + autoFocus, + placeholder, + name, + value, + hasError, + hasWarning, + onBlur + } = this.props; + + return ( +