UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

606 lines (605 loc) 25.3 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.inputPropTypes = exports.default = exports.SubmitButton = 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 _componentHelper = require("../../shared/component-helper.js"); var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper.js")); var _SpacingHelper = require("../space/SpacingHelper.js"); var _SkeletonHelper = require("../skeleton/SkeletonHelper.js"); var _filterValidProps = require("../../shared/helpers/filterValidProps.js"); var _Button = _interopRequireWildcard(require("../button/Button.js")); var _FormLabel = _interopRequireDefault(require("../form-label/FormLabel.js")); var _FormStatus = _interopRequireDefault(require("../form-status/FormStatus.js")); var _IconPrimary = _interopRequireDefault(require("../icon-primary/IconPrimary.js")); var _Context = _interopRequireDefault(require("../../shared/Context.js")); var _Suffix = _interopRequireDefault(require("../../shared/helpers/Suffix.js")); var _AlignmentHelper; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } 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); } const inputPropTypes = exports.inputPropTypes = { type: _propTypes.default.string, size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['default', 'small', 'medium', 'large']), _propTypes.default.number]), value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), 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]), globalStatus: _propTypes.default.shape({ id: _propTypes.default.string, message: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]) }), status_state: _propTypes.default.string, status_props: _propTypes.default.object, status_no_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), input_state: _propTypes.default.string, autocomplete: _propTypes.default.string, submit_button_title: _propTypes.default.string, clear_button_title: _propTypes.default.string, placeholder: _propTypes.default.node, clear: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), keep_placeholder: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), suffix: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), align: _propTypes.default.oneOf(['left', 'center', 'right']), selectall: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), 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]), input_class: _propTypes.default.string, input_attributes: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), input_element: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]), icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.func]), icon_size: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), icon_position: _propTypes.default.oneOf(['left', 'right']), inner_ref: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]), readOnly: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), inner_element: _propTypes.default.node, submit_element: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]), submit_button_variant: _Button.buttonVariantPropType.variant, submit_button_icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.func]), submit_button_status: _propTypes.default.string, ..._SpacingHelper.spacingPropTypes, className: _propTypes.default.string, children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]), on_change: _propTypes.default.func, on_key_down: _propTypes.default.func, on_submit: _propTypes.default.func, on_focus: _propTypes.default.func, on_blur: _propTypes.default.func, on_submit_focus: _propTypes.default.func, on_submit_blur: _propTypes.default.func, on_state_update: _propTypes.default.func, on_clear: _propTypes.default.func }; class Input extends _react.default.PureComponent { static getDerivedStateFromProps(props, state) { const value = Input.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.input_state) { state.inputState = props.input_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 === '' || Input.hasValue(value)) { return value; } return props.value; } constructor(props, context) { super(props); _defineProperty(this, "state", { inputState: 'virgin', value: null, _value: null }); _defineProperty(this, "updateInputValue", () => { if (this._ref.current && !this.props.input_element) { const value = this.state.value; const hasValue = Input.hasValue(value); this._ref.current.value = hasValue ? value : ''; } }); _defineProperty(this, "onFocusHandler", event => { const { value } = event.target; this.setState({ inputState: 'focus' }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_focus', { value, event }); if ((0, _componentHelper.isTrue)(this.props.selectall) && this._ref.current) { clearTimeout(this._selectallTimeout); this._selectallTimeout = setTimeout(() => { try { this._ref.current.select(); } catch (e) { (0, _componentHelper.warn)(e); } }, 1); } }); _defineProperty(this, "onBlurHandler", event => { const { value } = event.target; const result = (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_blur', { value, event }); if (result !== false) { this.setState({ inputState: Input.hasValue(value) && value !== this.state._value ? 'dirty' : 'initial' }); } }); _defineProperty(this, "onChangeHandler", event => { const { value } = event.target; const result = (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_change', { value, event }); if (result === false) { this.updateInputValue(); return; } if (typeof result === 'string') { this.setState({ value: result }); } else { this.setState({ value }); } }); _defineProperty(this, "onKeyDownHandler", event => { const value = event.target.value; (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_key_down', { value, event }); if (event.key === 'Enter') { (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_submit', { value, event }); } }); _defineProperty(this, "clearValue", event => { const previousValue = this.state.value; const value = ''; this.setState({ value }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_change', { value, event }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_clear', { value, previousValue, event }); this._ref.current.focus({ preventScroll: true }); }); this._ref = props.inner_ref || _react.default.createRef(); this._id = props.id || context.FormRow && typeof context.FormRow.useId === 'function' && context.FormRow.useId() || context.formElement && typeof context.formElement.useId === 'function' && context.formElement.useId() || (0, _componentHelper.makeUniqueId)(); if ((0, _componentHelper.isTrue)(props.clear) && props.icon_position === 'right') { (0, _componentHelper.warn)('You cannot have a clear button and icon_position="right"'); } } componentWillUnmount() { clearTimeout(this._selectallTimeout); } componentDidMount() { this.updateInputValue(); } componentDidUpdate() { this.updateInputValue(); } render() { var _this$context, _this$context2, _this$context3; const props = (0, _componentHelper.extendPropsWithContextInClassComponent)(this.props, Input.defaultProps, { skeleton: (_this$context = this.context) === null || _this$context === void 0 ? void 0 : _this$context.skeleton }, this.context.getTranslation(this.props).Input, (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.Input); const { type, size, label, label_direction, label_sr_only, status, globalStatus, status_state, status_props, status_no_animation, disabled, skeleton, placeholder, clear, keep_placeholder, suffix, align, input_class, submit_button_title, clear_button_title, submit_button_variant, submit_button_icon, submit_button_status, submit_element, inner_element, autocomplete, readOnly, stretch, input_attributes, icon, icon_position, icon_size, className, id: _id, children, value: _value, selectall, on_submit, input_element: _input_element, ...attributes } = props; let { value, focusState, inputState } = this.state; if ((0, _componentHelper.isTrue)(disabled) || (0, _componentHelper.isTrue)(skeleton)) { inputState = 'disabled'; } const sizeIsNumber = parseFloat(size) > 0; const id = this._id; const showStatus = (0, _componentHelper.getStatusState)(status); const hasSubmitButton = submit_element || submit_element !== false && type === 'search'; const hasValue = Input.hasValue(value); const iconSize = size === 'large' && (icon_size === 'default' || !icon_size) ? 'medium' : icon_size; const mainParams = { className: (0, _classnames.default)("dnb-input dnb-input__border--tokens dnb-form-component", (0, _SpacingHelper.createSpacingClasses)(props), className, icon && `dnb-input--icon-position-${icon_position} dnb-input--has-icon` + (iconSize ? ` dnb-input--icon-size-${iconSize}` : ""), type && `dnb-input--${type}`, size && !sizeIsNumber && `dnb-input--${size}`, hasSubmitButton && 'dnb-input--has-submit-element', inner_element && 'dnb-input--has-inner-element', (0, _componentHelper.isTrue)(clear) && 'dnb-input--has-clear-button', align && `dnb-input__align--${align}`, status && `dnb-input__status--${status_state}`, disabled && 'dnb-input--disabled', label_direction && `dnb-input--${label_direction}`, (0, _componentHelper.isTrue)(stretch) && `dnb-input--stretch`, (0, _componentHelper.isTrue)(keep_placeholder) && 'dnb-input--keep-placeholder'), 'data-input-state': inputState, 'data-has-content': hasValue ? 'true' : 'false' }; const innerParams = { className: 'dnb-input__inner' }; let { input_element: InputElement } = props; const inputAttributes = input_attributes ? typeof input_attributes === 'string' ? (0, _parse.default)(input_attributes) : input_attributes : {}; const inputParams = { className: (0, _classnames.default)('dnb-input__input', input_class), autoComplete: autocomplete, type, id, disabled: (0, _componentHelper.isTrue)(disabled), name: id, 'aria-placeholder': placeholder ? (0, _componentHelper.convertJsxToString)(placeholder) : undefined, ...attributes, ...inputAttributes, onChange: this.onChangeHandler, onKeyDown: this.onKeyDownHandler, onFocus: this.onFocusHandler, onBlur: this.onBlurHandler }; if (sizeIsNumber) { inputParams.size = size; } if (showStatus || suffix || hasSubmitButton) { inputParams['aria-describedby'] = (0, _componentHelper.combineDescribedBy)(inputParams, hasSubmitButton && !submit_element ? id + '-submit-button' : null, showStatus ? id + '-status' : null, suffix ? id + '-suffix' : null); } if (readOnly) { inputParams['aria-readonly'] = inputParams.readOnly = true; } const shellParams = { className: (0, _classnames.default)("dnb-input__shell dnb-input__border", (0, _SkeletonHelper.createSkeletonClass)('shape', skeleton, this.context)) }; (0, _SkeletonHelper.skeletonDOMAttributes)(inputParams, skeleton, this.context); (0, _componentHelper.validateDOMAttributes)(this.props, inputParams); (0, _componentHelper.validateDOMAttributes)(null, shellParams); if (InputElement && typeof InputElement === 'function') { InputElement = InputElement({ ...inputParams, value }, this._ref); } else if (!InputElement && _input_element) { InputElement = _input_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: status, state: status_state, text_id: id + '-status', no_animation: status_no_animation, skeleton: skeleton }, status_props)), _react.default.createElement("span", { className: "dnb-input__row" }, _react.default.createElement("span", shellParams, InputElement || _react.default.createElement("input", _extends({ ref: this._ref }, inputParams)), inner_element && _react.default.createElement("span", { className: "dnb-input__inner__element dnb-p" }, inner_element), icon && _react.default.createElement(InputIcon, { className: "dnb-input__icon", icon: icon, size: iconSize }), !hasValue && placeholder && focusState !== 'focus' && _react.default.createElement("span", { id: id + '-placeholder', className: 'dnb-input__placeholder' + (align ? ` dnb-input__align--${align}` : ""), role: "presentation", "aria-hidden": true }, placeholder), (0, _componentHelper.isTrue)(clear) && icon_position !== 'right' && _react.default.createElement("span", { className: "dnb-input--clear dnb-input__submit-element" }, _react.default.createElement(InputSubmitButton, { "aria-hidden": !hasValue, attributes: { className: 'dnb-input__clear-button' }, id: id + '-clear-button', type: "button", variant: "tertiary", "aria-controls": id, "aria-label": clear_button_title, tooltip: hasValue && clear_button_title, icon: "close", icon_size: size === 'small' ? 'small' : undefined, skeleton: skeleton, disabled: (0, _componentHelper.isTrue)(disabled) || !hasValue, onClick: this.clearValue }))), hasSubmitButton && _react.default.createElement("span", { className: "dnb-input__submit-element" }, submit_element ? submit_element : _react.default.createElement(InputSubmitButton, _extends({}, attributes, { id: id + '-submit-button', value: hasValue ? value : '', icon: submit_button_icon, status: (0, _componentHelper.convertStatusToStateOnly)(submit_button_status || status, status_state), status_state: status_state, icon_size: size === 'medium' || size === 'large' ? 'medium' : 'default', title: submit_button_title, variant: submit_button_variant, disabled: (0, _componentHelper.isTrue)(disabled), skeleton: (0, _componentHelper.isTrue)(skeleton), size: size, on_submit: on_submit }, status_props))), suffix && _react.default.createElement(_Suffix.default, { className: "dnb-input__suffix", id: id + '-suffix', context: props }, suffix)))); } } exports.default = Input; _defineProperty(Input, "contextType", _Context.default); _defineProperty(Input, "defaultProps", { type: 'text', size: null, value: 'initval', id: null, label: null, label_direction: null, label_sr_only: null, status: null, globalStatus: null, status_state: 'error', status_props: null, status_no_animation: null, input_state: null, autocomplete: 'off', placeholder: null, clear: null, keep_placeholder: null, suffix: null, align: null, selectall: null, stretch: null, disabled: null, skeleton: null, input_class: null, input_attributes: null, input_element: null, inner_ref: null, icon: null, icon_size: null, icon_position: 'left', readOnly: false, inner_element: null, submit_element: null, submit_button_title: null, clear_button_title: null, submit_button_variant: 'secondary', submit_button_icon: 'loupe', submit_button_status: null, className: null, children: null, on_change: null, on_key_down: null, on_submit: null, on_focus: null, on_blur: null, on_submit_focus: null, on_submit_blur: null, on_state_update: null, on_clear: null }); process.env.NODE_ENV !== "production" ? Input.propTypes = { ...inputPropTypes } : void 0; class InputSubmitButton extends _react.default.PureComponent { constructor(...args) { super(...args); _defineProperty(this, "state", { focusState: 'virgin' }); _defineProperty(this, "onSubmitFocusHandler", event => { const value = this.props.value; this.setState({ focusState: 'focus' }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_submit_focus', { value, event }); }); _defineProperty(this, "onSubmitBlurHandler", event => { const value = this.props.value; this.setState({ focusState: 'dirty' }); (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_submit_blur', { value, event }); }); _defineProperty(this, "onSubmitHandler", event => { const value = this.props.value; (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_submit', { value, event }); }); } render() { const { id, title, disabled, skeleton, variant, icon, icon_size, status, status_state, status_props, className, ...rest } = this.props; const params = { id, type: 'submit', 'aria-label': title, disabled, ...rest }; (0, _SkeletonHelper.skeletonDOMAttributes)(params, skeleton, this.context); (0, _componentHelper.validateDOMAttributes)(this.props, params); return _react.default.createElement("span", { className: "dnb-input__submit-button", "data-input-state": this.state.focusState }, _react.default.createElement(_Button.default, _extends({ className: (0, _classnames.default)("dnb-input__submit-button__button dnb-button--input-button", className), variant: variant, icon: icon, icon_size: icon_size, status: status, status_state: status_state, onClick: this.onSubmitHandler, onFocus: this.onSubmitFocusHandler, onBlur: this.onSubmitBlurHandler }, params, status_props))); } } _defineProperty(InputSubmitButton, "defaultProps", { id: null, value: null, title: null, disabled: false, skeleton: false, variant: 'secondary', icon: 'loupe', icon_size: null, status: null, status_state: 'error', status_props: null, className: null, on_submit: null, on_submit_focus: null, on_submit_blur: null }); process.env.NODE_ENV !== "production" ? InputSubmitButton.propTypes = { id: _propTypes.default.string, value: _propTypes.default.string, title: _propTypes.default.string, variant: _Button.buttonVariantPropType.variant, disabled: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), skeleton: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.func]), icon_size: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), status: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool, _propTypes.default.func, _propTypes.default.node]), status_state: _propTypes.default.string, status_props: _propTypes.default.object, className: _propTypes.default.string, on_submit: _propTypes.default.func, on_submit_focus: _propTypes.default.func, on_submit_blur: _propTypes.default.func } : void 0; const SubmitButton = exports.SubmitButton = _react.default.forwardRef((props, ref) => _react.default.createElement(InputSubmitButton, _extends({ innerRef: ref }, props))); const InputIcon = _react.default.memo(props => _react.default.createElement(_IconPrimary.default, props), ({ icon: prev }, { icon: next }) => { if (typeof prev === 'string' && typeof next === 'string') { return prev === next; } const isProgressIndicator = icon => { var _icon$type, _icon$type2; return _react.default.isValidElement(icon) && (((_icon$type = icon.type) === null || _icon$type === void 0 ? void 0 : _icon$type.displayName) === 'ProgressIndicator' || ((_icon$type2 = icon.type) === null || _icon$type2 === void 0 ? void 0 : _icon$type2.name) === 'ProgressIndicator'); }; if (isProgressIndicator(prev) && isProgressIndicator(next)) { return typeof prev === typeof next; } return false; }); InputIcon.propTypes = { icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.func]).isRequired }; Input._formElement = true; Input._supportsSpacingProps = true; //# sourceMappingURL=Input.js.map