@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
606 lines (605 loc) • 25.3 kB
JavaScript
"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