UNPKG

chayns-components

Version:

A set of beautiful React components for developing chayns® applications.

186 lines (179 loc) 5.36 kB
import _extends from "@babel/runtime/helpers/extends"; /** * @component */ import classnames from 'clsx'; import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useRef, useState } from 'react'; const DEFAULT_STYLE = { width: '100%', paddingBottom: '12px' }; const BORDER_DESIGN_DEFAULT_STYLE = { width: '100%' }; /** * A multiline text input that can automatically grow with its content. */ const TextArea = _ref => { let { style: styleProp, className, placeholder, defaultValue, design = TextArea.DEFAULT_DESIGN, onChange, autogrow, onBlur, onKeyUp, onKeyDown, value, disabled = false, required, stopPropagation = false, reference, ...props } = _ref; const ref = useRef(null); const [offset, setOffset] = useState(0); const grow = useCallback(() => { ref.current.style.height = '0px'; ref.current.style.height = `${ref.current.scrollHeight + offset}px`; }, [offset]); // update in value prop useEffect(() => { if (autogrow) { grow(); } }, [grow, autogrow, value]); // reference or prop change executes initialisation code const setRef = useCallback(node => { ref.current = node; if (node) { if (required) { node.setAttribute('required', ''); } node.setAttribute('row', '1'); if (!(styleProp !== null && styleProp !== void 0 && styleProp.overflow) && !(styleProp !== null && styleProp !== void 0 && styleProp.overflowX) && !(styleProp !== null && styleProp !== void 0 && styleProp.overflowY)) { // eslint-disable-next-line no-param-reassign node.style.overflow = 'hidden'; } if (autogrow) { setOffset(node.offsetHeight - node.clientHeight); grow(); } } if (reference) { reference(node); } }, [reference, required, styleProp === null || styleProp === void 0 ? void 0 : styleProp.overflow, styleProp === null || styleProp === void 0 ? void 0 : styleProp.overflowX, styleProp === null || styleProp === void 0 ? void 0 : styleProp.overflowY, autogrow, grow]); // autogrows on change and pass value to onChange-prop const handleChange = useCallback(() => { if (onChange) { onChange(ref.current.value); } if (autogrow) { grow(); } }, [grow, onChange, autogrow]); // pass only value to onBlur-prop const handleBlur = useCallback(() => { if (onBlur) { onBlur(ref.current.value); // TODO: Get data from event } }, [onBlur]); const style = { ...(design === TextArea.BORDER_DESIGN ? BORDER_DESIGN_DEFAULT_STYLE : DEFAULT_STYLE), ...styleProp }; const classNames = classnames('input', className, disabled && 'input--disabled', design === TextArea.BORDER_DESIGN && 'input--border-design'); return /*#__PURE__*/React.createElement("textarea", _extends({ className: classNames, ref: setRef, placeholder: placeholder, style: style, defaultValue: defaultValue, onChange: handleChange, onBlur: onBlur ? handleBlur : null, onKeyUp: onKeyUp, onKeyDown: onKeyDown, value: value, disabled: disabled, onClick: stopPropagation ? event => event.stopPropagation() : null }, props)); }; TextArea.DEFAULT_DESIGN = 0; TextArea.BORDER_DESIGN = 1; TextArea.propTypes = { /** * A React style object that will be applied to the text area. */ style: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), /** * Wether the component ignores any user interaction and is rendered with a * disabled style. */ disabled: PropTypes.bool, /** * A classname string that will be applied to the `<textarea>`-element. */ className: PropTypes.string, /** * A placeholder, that will be displayed if the text area is empty. */ placeholder: PropTypes.string, /** * Wether the text area is required for a form to complete. Renders the text * area with an error style when its empty. */ required: PropTypes.bool, /** * The design of the input. Use either `TextArea.DEFAULT_DESIGN` or * `TextArea.BORDER_DESIGN`. */ design: PropTypes.number, /** * A callback that is invoked when the value of the `<textarea>` changes. */ onChange: PropTypes.func, /** * A callback that is invoked when the text area loses focus. */ onBlur: PropTypes.func, /** * The default value of the text area. Has no effect when the `value` prop * is used. */ defaultValue: PropTypes.string, /** * The current text value of the area. */ value: PropTypes.string, /** * A callback that will be called when the `keyup`-event is fired from the * `<textarea>`-element. */ onKeyUp: PropTypes.func, /** * A callback that will be called when the `keydown`-event is fired from the * `<textarea>`-element. */ onKeyDown: PropTypes.func, /** * Wether the text area should automatically grow with its content. */ autogrow: PropTypes.bool, /** * A function that will be invoked with a reference to the * `<textarea>`-element or `null`. */ reference: PropTypes.func, /** * Wether click events should be stopped from propagating to parent * elements. */ stopPropagation: PropTypes.bool }; TextArea.displayName = 'TextArea'; export default TextArea; //# sourceMappingURL=TextArea.js.map