UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

450 lines (449 loc) 20.2 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _classnames = _interopRequireDefault(require("classnames")); var _FormLabel = _interopRequireDefault(require("../form-label/FormLabel")); var _FormStatus = _interopRequireDefault(require("../form-status/FormStatus")); var _TextCounter = _interopRequireDefault(require("../../fragments/text-counter/TextCounter")); var _componentHelper = require("../../shared/component-helper"); var _filterValidProps = require("../../shared/helpers/filterValidProps"); var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper")); var _SpacingHelper = require("../space/SpacingHelper"); var _SkeletonHelper = require("../skeleton/SkeletonHelper"); var _Context = _interopRequireDefault(require("../../shared/Context")); var _Suffix = _interopRequireDefault(require("../../shared/helpers/Suffix")); var _AlignmentHelper, _span; const _excluded = ["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", "children", "value", "textarea_element"]; 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 ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } 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) { var _this; super(_props); _this = this; _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", function () { let rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 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 } = props, attributes = _objectWithoutProperties(props, _excluded); 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' ? JSON.parse(textarea_attributes) : textarea_attributes : {}; const textareaParams = _objectSpread(_objectSpread(_objectSpread({ 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 = _objectSpread(_objectSpread({ 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