chayns-components
Version:
A set of beautiful React components for developing chayns® applications.
509 lines (504 loc) • 17 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _clsx = _interopRequireDefault(require("clsx"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _Button = _interopRequireDefault(require("../../react-chayns-button/component/Button"));
var _Icon = _interopRequireDefault(require("../../react-chayns-icon/component/Icon"));
var _is = require("../../utils/is");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* @component
*/
let currentId = 0;
const PREFIX = 'CC_INPUT_';
/**
* A text input that can be validated and decorated with different designs.
*/
class Input extends _react.PureComponent {
constructor(props) {
super(props);
this.state = {
valid: (!props.regExp || !props.value || props.value.match(props.regExp)) && !(props.value === '' && props.required),
initial: true,
right: false,
value: props.value || props.defaultValue || ''
};
this.id = `${PREFIX}${currentId++}`;
this.setRef = this.setRef.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onKeyPress = this.onKeyPress.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onChange = this.onChange.bind(this);
this.onPaste = this.onPaste.bind(this);
this.callValidated = this.callValidated.bind(this);
this.onIconClick = this.onIconClick.bind(this);
}
componentDidUpdate(_ref) {
let {
regExp: oldRegExp,
value: oldValue
} = _ref;
const {
regExp,
onChange,
value
} = this.props;
if (String(oldRegExp) !== String(regExp) && this.ref) {
this.callValidated(this.ref.value, onChange);
}
if (value !== oldValue) {
this.callValidated(value);
}
}
onKeyUp(e) {
const {
onKeyUp,
onEnter
} = this.props;
if (onKeyUp) {
onKeyUp(e);
}
if (e.keyCode === 13) {
this.callValidated(e.target.value, onEnter, e);
}
}
onKeyPress(e) {
const {
type
} = this.props;
if (type === 'number' && e.code && e.code.startsWith('Key')) {
e.preventDefault();
}
}
onBlur(e) {
const {
onBlur
} = this.props;
this.callValidated(e.target.value, onBlur, e);
}
onChange(e) {
const {
onChange
} = this.props;
this.setState({
value: e.target.value
});
this.callValidated(e.target.value, onChange, e);
}
onPaste(e) {
const {
type
} = this.props;
if (type === 'number') {
const data = e.clipboardData.getData('text/plain');
if (!/^[0-9.,]*$/.test(data)) {
e.preventDefault();
}
}
}
onIconClick(e) {
const {
right,
initial
} = this.state;
const {
onIconClick,
clearIcon,
value,
defaultValue
} = this.props;
if (clearIcon && (right || !(0, _is.isNullOrWhiteSpace)(value) || initial && !(0, _is.isNullOrWhiteSpace)(defaultValue))) {
this.onChange({
target: {
value: ''
}
});
e.stopPropagation();
this.ref.value = '';
} else if (onIconClick) {
onIconClick(e);
e.stopPropagation();
}
}
setRef(ref) {
const {
inputRef
} = this.props;
if (inputRef) {
inputRef(ref);
}
this.ref = ref;
}
callValidated(value, callback, event) {
const {
regExp,
required
} = this.props;
const valid = !(required && !value) && !(regExp && !value.match(regExp));
if (callback) {
callback(value, valid, event);
}
this.setState({
valid,
initial: false,
right: !(0, _is.isNullOrWhiteSpace)(value)
});
}
render() {
const {
className,
defaultValue,
value,
style,
placeholder,
type,
dynamic,
icon: iconProp,
iconLeft,
wrapperRef,
invalid,
onIconClick,
onKeyDown,
id,
onFocus,
stopPropagation,
customProps,
disabled,
design,
clearIcon,
required,
invalidMessage,
emptyValue,
autoComplete,
left,
right: rightProp
} = this.props;
const {
valid,
right,
initial,
value: stateValue
} = this.state;
const icon = clearIcon && (right || !(0, _is.isNullOrWhiteSpace)(value) || initial && !(0, _is.isNullOrWhiteSpace)(defaultValue)) ? 'fa fa-times' : iconProp;
if (design === Input.BORDER_DESIGN) {
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _clsx.default)('input--border-design', className, (right || !(0, _is.isNullOrWhiteSpace)(value) || initial && !(0, _is.isNullOrWhiteSpace)(defaultValue)) && 'input--label-right', (!valid || invalid) && 'input--border-design--invalid', dynamic === Input.BOTTOM_DYNAMIC ? 'input--bottom-dynamic' : dynamic && 'input--dynamic', disabled && 'input--disabled', required && 'input--border-design--required', icon && 'input--border_has-icon', rightProp && 'input--border_has-right', left && 'input--border_has-left'),
onClick: () => {
this.ref.focus();
},
style: style
}, iconLeft && /*#__PURE__*/_react.default.createElement(_Icon.default, {
icon: iconLeft,
className: "input__icon-left"
}), left, /*#__PURE__*/_react.default.createElement("div", {
className: "input__input-wrapper"
}, /*#__PURE__*/_react.default.createElement("input", (0, _extends2.default)({
ref: this.setRef,
value: value,
defaultValue: defaultValue,
onKeyUp: this.onKeyUp,
onKeyDown: onKeyDown,
onBlur: this.onBlur,
onChange: this.onChange,
onKeyPress: this.onKeyPress,
onPaste: this.onPaste,
onFocus: onFocus,
type: type || 'text',
id: id || this.id,
required: true,
onClick: stopPropagation ? event => event.stopPropagation() : null,
disabled: disabled,
autoComplete: autoComplete
}, customProps)), placeholder && !emptyValue && /*#__PURE__*/_react.default.createElement("label", {
htmlFor: id || this.id
}, /*#__PURE__*/_react.default.createElement("div", {
className: "space"
}, (0, _is.isString)(value) ? value : stateValue), /*#__PURE__*/_react.default.createElement("div", {
className: "ellipsis"
}, (invalid || !valid) && invalidMessage && (value || stateValue || defaultValue) ? invalidMessage : placeholder)), emptyValue && !(value || (value === null || value === undefined) && stateValue || defaultValue) && /*#__PURE__*/_react.default.createElement("div", {
style: {
position: 'absolute',
top: 0,
left: 0,
color: 'var(--chayns-color--text)'
}
}, emptyValue)), rightProp, icon && /*#__PURE__*/_react.default.createElement(_Button.default, {
onClick: this.onIconClick
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
icon: icon,
style: (onIconClick || clearIcon) && !disabled ? {
pointerEvents: 'all'
} : null,
className: "input__icon-right"
})));
}
if (dynamic || icon) {
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _clsx.default)('input-group', className, (right || !(0, _is.isNullOrWhiteSpace)(value) || initial && !(0, _is.isNullOrWhiteSpace)(defaultValue)) && "labelRight", disabled && 'input-group--disabled'),
ref: wrapperRef
}, /*#__PURE__*/_react.default.createElement("input", (0, _extends2.default)({
style: {
width: '100%',
paddingRight: icon ? '30px' : null,
...style
},
ref: this.setRef,
className: (0, _clsx.default)('input', className, (!valid || invalid) && 'input--invalid'),
value: value,
defaultValue: defaultValue,
onKeyUp: this.onKeyUp,
onKeyDown: onKeyDown,
onBlur: this.onBlur,
onChange: this.onChange,
onFocus: onFocus,
type: type || 'text',
id: id || this.id,
required: true,
onClick: stopPropagation ? event => event.stopPropagation() : null,
disabled: disabled,
autoComplete: autoComplete
}, customProps)), placeholder && /*#__PURE__*/_react.default.createElement("label", {
style: {
paddingRight: icon ? '30px' : null
},
htmlFor: id || this.id,
className: (0, _clsx.default)((!valid || invalid) && 'input--invalid', icon && "labelIcon")
}, /*#__PURE__*/_react.default.createElement("div", {
className: "space"
}, (0, _is.isString)(value) ? value : stateValue), /*#__PURE__*/_react.default.createElement("div", {
className: "ellipsis"
}, placeholder)), icon ? /*#__PURE__*/_react.default.createElement(_Icon.default, {
icon: icon,
className: "input-group__icon",
style: icon ? {
opacity: '.3',
pointerEvents: 'all'
} : {
opacity: '0'
},
onClick: this.onIconClick
}) : null);
}
return /*#__PURE__*/_react.default.createElement("input", (0, _extends2.default)({
className: (0, _clsx.default)('input', className, (!valid || invalid) && 'input--invalid', disabled && 'input--disabled'),
style: {
...{
width: '100%'
},
...style
},
placeholder: placeholder,
onKeyUp: this.onKeyUp,
onKeyDown: onKeyDown,
onBlur: this.onBlur,
onChange: this.onChange,
onFocus: onFocus,
value: value,
defaultValue: defaultValue,
type: type,
ref: this.setRef,
id: id || this.id,
onClick: stopPropagation ? event => event.stopPropagation() : null,
required: true,
disabled: disabled,
autoComplete: autoComplete
}, customProps));
}
}
exports.default = Input;
Input.DEFAULT_DESIGN = 0;
Input.BORDER_DESIGN = 1;
Input.MOVING_DYNAMIC = true;
Input.NO_DYNAMIC = false;
Input.BOTTOM_DYNAMIC = 2;
Input.propTypes = {
/**
* A classname string that will be applied to the `<input>`-element
*/
className: _propTypes.default.string,
/**
* A callback for the `keyup`-event on the input.
*/
onKeyUp: _propTypes.default.func,
/**
* A callback for the `keyup`-event on the input.
*/
onKeyDown: _propTypes.default.func,
/**
* A callback for when the users presses the Enter-key while the input
* is focused.
*/
onEnter: _propTypes.default.func,
/**
* Called when the inputs content was changed. If the `regExp`-prop is set,
* this callback receives a second argument indicating wether the input is
* valid or not.
*/
onChange: _propTypes.default.func,
/**
* A callback for the `blur`-event on the input.
*/
onBlur: _propTypes.default.func,
/**
* A callback for the `focus`-event on the input.
*/
onFocus: _propTypes.default.func,
/**
* A regular expression that will check if the input is valid. If the input
* is not valid, this component will show it to the user.
*/
regExp: _propTypes.default.instanceOf(RegExp),
/**
* A React style object that is applied to the `<input>`-element.
*/
style: _propTypes.default.objectOf(_propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])),
/**
* An animated placeholder that is shown when the input is empty.
*/
placeholder: _propTypes.default.string,
/**
* The current value of the input field.
*/
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
/**
* The initial value of the input field. Has no effect when using the
* `value`-prop.
*/
defaultValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
/**
* Wether the input should be marked as invalid.
*/
invalid: _propTypes.default.bool,
/**
* The input type that is set on the `<input>`-element (e.g. `text`,
* `password`, etc.)
*/
type: _propTypes.default.string,
/**
* A funtion that receives the reference to the `<input>`-element.
*/
inputRef: _propTypes.default.func,
/**
* An icon that will be shown on the right side of the input. Only applies
* when `dynamic` is `true` or the border-design is active.
*/
icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]),
/**
* The `onClick`-callback for the `icon`.
*/
onIconClick: _propTypes.default.func,
/**
* A function that will receive the reference to the wrapper element. This
* only has an effect if `dynamic` is `true`.
*/
wrapperRef: _propTypes.default.func,
/**
* When active the placeholder will not disappear on input but rather slide
* to the right of the input field to act more like a label. The option can
* also be `Input.BOTTOM_DYNAMIC` when the border-design is active.
*/
dynamic: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.number]),
/**
* Any additional props that will be forwarded to the `<input>`-element.
*/
customProps: _propTypes.default.object,
// eslint-disable-line react/forbid-prop-types
/**
* A HTML id that will be applied to the `<input>`-element.
*/
id: _propTypes.default.string,
/**
* Wether to stop propagation of click events to parent elements.
*/
stopPropagation: _propTypes.default.bool,
/**
* Wether to mark an empty input as invalid.
*/
required: _propTypes.default.bool,
/**
* Disables any user interaction with the input and renders it with a
* disabled style.
*/
disabled: _propTypes.default.bool,
/**
* Wether to show a clear icon on the right side of the input when it is not
* empty.
*/
clearIcon: _propTypes.default.bool,
/**
* The design of the input. Use either `Input.DEFAULT_DESIGN` or
* `Input.BORDER_DESIGN`.
*/
design: _propTypes.default.number,
/**
* An icon that will be shown on the left side of the input when the
* border-design is active.
*/
iconLeft: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]),
/**
* A string or `ReactNode` that will be rendered on the left side of the
* input when the border-design is active.
*/
left: _propTypes.default.node,
/**
* A string or `ReactNode` that will be rendered on the right side of the
* input when the border-design is active.
*/
right: _propTypes.default.node,
/**
* An error message that will be shown instead of the placeholder when the
* border-design is active and the `dynamic`-prop is set to
* `Input.BOTTOM_DYNAMIC`.
*/
invalidMessage: _propTypes.default.string,
/**
* Default value if nothing is typed into the input. Only for border design
* and not compatible with placeholder.
*/
emptyValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
/**
* Sets the autocomplete attribute
*/
autoComplete: _propTypes.default.string
};
Input.defaultProps = {
className: '',
onKeyUp: null,
onKeyDown: null,
onEnter: null,
onChange: null,
onBlur: null,
onFocus: null,
regExp: null,
style: {},
placeholder: '',
value: undefined,
defaultValue: undefined,
invalid: false,
type: 'text',
inputRef: null,
icon: null,
onIconClick: null,
wrapperRef: null,
dynamic: false,
customProps: null,
id: null,
stopPropagation: false,
required: false,
disabled: false,
clearIcon: false,
design: Input.DEFAULT_DESIGN,
iconLeft: null,
left: null,
right: null,
invalidMessage: null,
emptyValue: null,
autoComplete: 'off'
};
Input.displayName = 'Input';
//# sourceMappingURL=Input.js.map