UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

444 lines (443 loc) 18.4 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _parse = _interopRequireDefault(require("core-js-pure/stable/json/parse.js")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _classnames = _interopRequireDefault(require("classnames")); var _FormLabel = _interopRequireDefault(require("../form-label/FormLabel.js")); var _FormStatus = _interopRequireDefault(require("../form-status/FormStatus.js")); var _TextCounter = _interopRequireDefault(require("../../fragments/text-counter/TextCounter.js")); var _componentHelper = require("../../shared/component-helper.js"); var _filterValidProps = require("../../shared/helpers/filterValidProps.js"); var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper.js")); var _SpacingHelper = require("../space/SpacingHelper.js"); var _SkeletonHelper = require("../skeleton/SkeletonHelper.js"); var _Context = _interopRequireDefault(require("../../shared/Context.js")); var _Suffix = _interopRequireDefault(require("../../shared/helpers/Suffix.js")); var _AlignmentHelper, _span; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class Textarea extends _react.default.PureComponent { static getDerivedStateFromProps(props, state) { const value = Textarea.getValue(props); if (value !== 'initval' && value !== state.value && value !== state._value) { if (value !== state.value && typeof props.on_state_update === 'function') { (0, _componentHelper.dispatchCustomElementEvent)({ props }, 'on_state_update', { value }); } state.value = value; } if (props.textarea_state) { state.textareaState = props.textarea_state; } state._value = props.value; return state; } static hasValue(value) { return (typeof value === 'string' || typeof value === 'number') && String(value).length > 0 || false; } static getValue(props) { const value = (0, _componentHelper.processChildren)(props); if (value === '' || Textarea.hasValue(value)) { return value; } return props.value; } constructor(_props) { super(_props); _defineProperty(this, "state", { textareaState: 'virgin', value: null, _value: null }); _defineProperty(this, "onFocusHandler", event => { const { value } = this._ref.current; this.setState({ value, textareaState: 'focus' }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_focus', { value, event }); }); _defineProperty(this, "onBlurHandler", event => { const { value } = event.target; this.setState({ value, textareaState: Textarea.hasValue(value) ? 'dirty' : 'initial' }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_blur', { value, event }); }); _defineProperty(this, "onChangeHandler", event => { const { value } = event.target; const props = this.getProps(); const autoresize = (0, _componentHelper.isTrue)(props.autoresize); if (autoresize) { this.prepareAutosize(); } const rows = this.getRows(value); const ret = (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_change', { value, rows, event }); if (ret !== false) { this.setState({ value }); if (autoresize) { this.setAutosize(rows); } } }); _defineProperty(this, "onKeyDownHandler", event => { const rows = this.getRows(); const { value } = event.target; (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_key_down', { value, rows, event }); }); _defineProperty(this, "prepareAutosize", () => { const elem = this._ref.current; if (!elem) { return; } try { elem.style.height = 'auto'; } catch (e) { (0, _componentHelper.warn)(e); } }); _defineProperty(this, "setAutosize", (rows = null) => { const elem = this._ref.current; if (!elem) { return; } try { if (typeof this._heightOffset === 'undefined') { this._heightOffset = elem.offsetHeight - elem.clientHeight; } elem.style.height = 'auto'; const lineHeight = this.getLineHeight(); let newHeight = elem.scrollHeight + this._heightOffset; if (!rows) { rows = this.getRows(); } if (rows === 1) { if (newHeight > lineHeight) { newHeight = lineHeight; } } const props = this.getProps(); const maxRows = parseFloat(props.autoresize_max_rows); if (maxRows > 0) { const maxHeight = maxRows * lineHeight; if (rows > maxRows || newHeight > maxHeight) { newHeight = maxHeight; } } elem.style.height = newHeight + 'px'; } catch (e) { (0, _componentHelper.warn)(e); } }); this._ref = _react.default.createRef(); this._id = _props.id || (0, _componentHelper.makeUniqueId)(); if (_props.textarea_state) { this.state.textareaState = _props.textarea_state; } try { if (typeof navigator !== 'undefined') { this.resizeModifier = /Firefox|Edg/.test(navigator.userAgent) || /Chrome/.test(navigator.userAgent) && /Win/.test(navigator.platform) ? 'large' : false; if (!this.resizeModifier) { this.resizeModifier = /Safari|Chrome/.test(navigator.userAgent) && /Mac/.test(navigator.platform) ? 'medium' : false; } } } catch (error) { console.error(error); } } componentDidMount() { const props = this.getProps(); if (props.inner_ref) { typeof props.inner_ref === 'function' ? props.inner_ref(this._ref.current) : props.inner_ref.current = this._ref.current; } if ((0, _componentHelper.isTrue)(props.autoresize) && typeof window !== 'undefined') { this.setAutosize(); try { this.resizeObserver = new ResizeObserver(entries => { window.requestAnimationFrame(() => { if (!Array.isArray(entries) || !entries.length) { return; } this.setAutosize(); }); }); this.resizeObserver.observe(document.body); } catch (e) { window.addEventListener('resize', this.setAutosize); } } } componentWillUnmount() { if (this.resizeObserver) { this.resizeObserver.disconnect(); this.resizeObserver = null; } if (typeof window !== 'undefined') { window.removeEventListener('resize', this.setAutosize); } } getRows() { return Math.floor(this._ref.current.scrollHeight / this.getLineHeight()) || 1; } getLineHeight() { return parseFloat(getComputedStyle(this._ref.current).lineHeight) || 0; } getProps() { var _this$context, _this$context2, _this$context3; return (0, _componentHelper.extendPropsWithContextInClassComponent)(this.props, Textarea.defaultProps, { skeleton: (_this$context = this.context) === null || _this$context === void 0 ? void 0 : _this$context.skeleton }, this.context.getTranslation(this.props).Textarea, (0, _filterValidProps.pickFormElementProps)((_this$context2 = this.context) === null || _this$context2 === void 0 ? void 0 : _this$context2.FormRow), (0, _filterValidProps.pickFormElementProps)((_this$context3 = this.context) === null || _this$context3 === void 0 ? void 0 : _this$context3.formElement), this.context.Textarea); } render() { const props = this.getProps(); const { label, label_direction, label_sr_only, status, status_state, status_props, status_no_animation, globalStatus, suffix, disabled, skeleton, stretch, placeholder, keepPlaceholder, align, size, textarea_class, readOnly, textarea_attributes, className, autoresize, characterCounter, autoresize_max_rows, id: _id, children, value: _value, textarea_element: _textarea_element, ...attributes } = props; const { value, textareaState } = this.state; const id = this._id; const showStatus = (0, _componentHelper.getStatusState)(status); const hasValue = Textarea.hasValue(value); let { textarea_element: TextareaElement } = props; const textareaAttributes = textarea_attributes ? typeof textarea_attributes === 'string' ? (0, _parse.default)(textarea_attributes) : textarea_attributes : {}; const textareaParams = { className: (0, _classnames.default)("dnb-textarea__textarea dnb-input__border", textarea_class), role: 'textbox', value: hasValue ? value : '', id, name: id, disabled: (0, _componentHelper.isTrue)(disabled) || (0, _componentHelper.isTrue)(skeleton), 'aria-placeholder': placeholder ? (0, _componentHelper.convertJsxToString)(placeholder) : undefined, ...attributes, ...textareaAttributes, onChange: this.onChangeHandler, onFocus: this.onFocusHandler, onBlur: this.onBlurHandler, onKeyDown: this.onKeyDownHandler }; if (showStatus || suffix) { textareaParams['aria-describedby'] = (0, _componentHelper.combineDescribedBy)(textareaParams, showStatus ? id + '-status' : null, suffix ? id + '-suffix' : null); } if (readOnly) { textareaParams['aria-readonly'] = textareaParams.readOnly = true; } const mainParams = { className: (0, _classnames.default)(`dnb-textarea dnb-textarea--${textareaState} dnb-form-component`, (0, _SkeletonHelper.createSkeletonClass)(null, skeleton), (0, _SpacingHelper.createSpacingClasses)(props), className, autoresize ? 'dnb-textarea__autoresize' : this.resizeModifier && `dnb-textarea__resize--${this.resizeModifier}`, disabled && 'dnb-textarea--disabled', hasValue && 'dnb-textarea--has-content', align && `dnb-textarea__align--${align}`, size && `dnb-textarea__size--${size}`, status && `dnb-textarea__status--${status_state}`, label_direction && `dnb-textarea--${label_direction}`, (0, _componentHelper.isTrue)(stretch) && `dnb-textarea--stretch`, (0, _componentHelper.isTrue)(keepPlaceholder) && `dnb-textarea--keep-placeholder`) }; const innerParams = { className: (0, _classnames.default)('dnb-textarea__inner', (0, _SkeletonHelper.createSkeletonClass)('shape', skeleton, this.context)) }; const shellParams = { className: 'dnb-textarea__shell' }; if ((0, _componentHelper.isTrue)(disabled) || (0, _componentHelper.isTrue)(skeleton)) { shellParams['aria-disabled'] = true; } const placeholderStyle = parseFloat(props.rows) > 0 ? { '--textarea-rows': parseFloat(props.rows) } : null; (0, _SkeletonHelper.skeletonDOMAttributes)(innerParams, skeleton, this.context); (0, _componentHelper.validateDOMAttributes)(this.props, textareaParams); (0, _componentHelper.validateDOMAttributes)(null, innerParams); (0, _componentHelper.validateDOMAttributes)(null, shellParams); if (TextareaElement && typeof TextareaElement === 'function') { TextareaElement = TextareaElement(textareaParams, this._ref); } else if (!TextareaElement && _textarea_element) { TextareaElement = _textarea_element; } return _react.default.createElement("span", mainParams, label && _react.default.createElement(_FormLabel.default, { id: id + '-label', forId: id, text: label, labelDirection: label_direction, srOnly: label_sr_only, disabled: disabled, skeleton: skeleton }), _react.default.createElement("span", innerParams, _AlignmentHelper || (_AlignmentHelper = _react.default.createElement(_AlignmentHelper2.default, null)), _react.default.createElement(_FormStatus.default, _extends({ show: showStatus, id: id + '-form-status', globalStatus: globalStatus, label: label, text_id: id + '-status', text: status, state: status_state, no_animation: status_no_animation, skeleton: skeleton }, status_props)), _react.default.createElement("span", { className: "dnb-textarea__row" }, _react.default.createElement("span", shellParams, TextareaElement || _react.default.createElement("textarea", _extends({ ref: this._ref }, textareaParams)), !hasValue && placeholder && (textareaState !== 'focus' || keepPlaceholder) && _react.default.createElement("span", { className: 'dnb-textarea__placeholder' + (align ? ` dnb-textarea__align--${align}` : ""), style: placeholderStyle, "aria-hidden": true }, placeholder), _span || (_span = _react.default.createElement("span", { className: "dnb-textarea__state" }))), suffix && _react.default.createElement(_Suffix.default, { className: "dnb-textarea__suffix", id: id + '-suffix', context: props }, suffix)), characterCounter && _react.default.createElement(_TextCounter.default, _extends({ top: "x-small", text: value, max: characterCounter, lang: props.lang, locale: props.locale }, characterCounter)))); } } exports.default = Textarea; _defineProperty(Textarea, "contextType", _Context.default); _defineProperty(Textarea, "defaultProps", { value: 'initval', id: null, label: null, label_direction: null, label_sr_only: null, status: null, textarea_state: null, status_state: 'error', status_props: null, status_no_animation: null, globalStatus: null, suffix: null, placeholder: null, keepPlaceholder: null, align: null, size: null, stretch: null, disabled: null, skeleton: null, autoresize: null, autoresize_max_rows: null, characterCounter: null, textarea_class: null, textarea_attributes: null, readOnly: false, rows: null, cols: null, inner_ref: null, className: null, textarea_element: null, children: null, on_change: null, on_focus: null, on_blur: null, on_key_down: null, on_state_update: null }); process.env.NODE_ENV !== "production" ? Textarea.propTypes = { value: _propTypes.default.string, id: _propTypes.default.string, label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), label_direction: _propTypes.default.oneOf(['horizontal', 'vertical']), label_sr_only: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), status: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool, _propTypes.default.func, _propTypes.default.node]), textarea_state: _propTypes.default.string, status_state: _propTypes.default.string, status_props: _propTypes.default.object, status_no_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), globalStatus: _propTypes.default.shape({ id: _propTypes.default.string, message: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]) }), suffix: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), placeholder: _propTypes.default.node, keepPlaceholder: _propTypes.default.bool, align: _propTypes.default.oneOf(['left', 'right']), size: _propTypes.default.oneOf(['small', 'medium', 'large']), stretch: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), disabled: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), skeleton: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), characterCounter: _propTypes.default.oneOfType([_propTypes.default.shape({ max: _propTypes.default.number, variant: _propTypes.default.oneOf(['down', 'up']) }), _propTypes.default.number]), autoresize: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), autoresize_max_rows: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), textarea_class: _propTypes.default.string, textarea_attributes: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), readOnly: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), rows: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), cols: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), inner_ref: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]), ..._SpacingHelper.spacingPropTypes, className: _propTypes.default.string, textarea_element: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]), children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]), on_change: _propTypes.default.func, on_focus: _propTypes.default.func, on_blur: _propTypes.default.func, on_key_down: _propTypes.default.func, on_state_update: _propTypes.default.func } : void 0; Textarea._formElement = true; Textarea._supportsSpacingProps = true; //# sourceMappingURL=Textarea.js.map