@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
159 lines (158 loc) • 5.7 kB
JavaScript
import React, { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { useTheme } from 'styled-components';
import { useElementSize } from '../../hooks/element';
import { AreaContext } from '../area-provider/AreaContextProvider';
import Icon from '../icon/Icon';
import { StyledInput, StyledInputContent, StyledInputContentWrapper, StyledInputField, StyledInputIconWrapper, StyledInputLabel, StyledInputRightElement, StyledMotionInputClearIcon, StyledMotionInputLabelWrapper } from './Input.styles';
export let InputSize = /*#__PURE__*/function (InputSize) {
InputSize["Small"] = "small";
InputSize["Medium"] = "medium";
return InputSize;
}({});
const Input = /*#__PURE__*/forwardRef((_ref, ref) => {
let {
leftElement,
inputMode,
isDisabled,
onBlur,
onChange,
onFocus,
onKeyDown,
onPaste,
placeholder,
rightElement,
shouldShowOnlyBottomBorder,
shouldRemainPlaceholder = false,
shouldShowClearIcon = false,
shouldShowCenteredContent = false,
size = InputSize.Medium,
type = 'text',
value,
shouldUseAutoFocus = false,
isInvalid = false,
shouldPreventPlaceholderAnimation = false,
id
} = _ref;
const [hasValue, setHasValue] = useState(typeof value === 'string' && value !== '');
const [placeholderWidth, setPlaceholderWidth] = useState(0);
const areaProvider = useContext(AreaContext);
const theme = useTheme();
const inputRef = useRef(null);
const placeholderRef = useRef(null);
const placeholderSize = useElementSize(placeholderRef);
useEffect(() => {
if (placeholderSize && shouldShowOnlyBottomBorder) {
setPlaceholderWidth(placeholderSize.width + 5);
}
}, [placeholderSize, shouldShowOnlyBottomBorder]);
const shouldChangeColor = useMemo(() => areaProvider.shouldChangeColor ?? false, [areaProvider.shouldChangeColor]);
const handleClearIconClick = useCallback(() => {
if (inputRef.current) {
inputRef.current.value = '';
setHasValue(false);
if (typeof onChange === 'function') {
onChange({
target: inputRef.current
});
}
}
}, [onChange]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const shouldShowBorder = rightElement?.props?.style?.backgroundColor === undefined;
const handleInputFieldChange = useCallback(event => {
setHasValue(event.target.value !== '');
if (typeof onChange === 'function') {
onChange(event);
}
}, [onChange]);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
blur: () => inputRef.current?.blur()
}), []);
useEffect(() => {
if (typeof value === 'string') {
setHasValue(value !== '');
}
}, [value]);
const labelPosition = useMemo(() => {
if (hasValue && !shouldRemainPlaceholder && !shouldPreventPlaceholderAnimation) {
return shouldShowOnlyBottomBorder ? {
right: 3,
top: -1.5
} : {
bottom: size === InputSize.Small ? -4 : -10,
right: -6
};
}
return {
left: -1
};
}, [hasValue, shouldPreventPlaceholderAnimation, shouldRemainPlaceholder, shouldShowOnlyBottomBorder, size]);
return /*#__PURE__*/React.createElement(StyledInput, {
className: "beta-chayns-input",
$isDisabled: isDisabled
}, /*#__PURE__*/React.createElement(StyledInputContentWrapper, {
$shouldChangeColor: shouldChangeColor,
$isInvalid: isInvalid,
$shouldRoundRightCorners: shouldShowBorder,
$shouldShowOnlyBottomBorder: shouldShowOnlyBottomBorder,
$size: size
}, leftElement && /*#__PURE__*/React.createElement(StyledInputIconWrapper, null, leftElement), /*#__PURE__*/React.createElement(StyledInputContent, {
$shouldShowOnlyBottomBorder: shouldShowOnlyBottomBorder
}, /*#__PURE__*/React.createElement(StyledInputField, {
$placeholderWidth: placeholderWidth,
id: id,
disabled: isDisabled,
onBlur: onBlur,
onChange: handleInputFieldChange,
onFocus: onFocus,
onKeyDown: onKeyDown,
onClick: event => {
event.preventDefault();
event.stopPropagation();
},
onPaste: onPaste,
ref: inputRef,
type: type,
value: value,
autoFocus: shouldUseAutoFocus,
inputMode: inputMode,
$isInvalid: isInvalid,
$shouldShowCenteredContent: shouldShowCenteredContent
}), /*#__PURE__*/React.createElement(StyledMotionInputLabelWrapper, {
animate: shouldPreventPlaceholderAnimation ? {
opacity: hasValue ? 0 : 1
} : {
fontSize: hasValue && !shouldShowOnlyBottomBorder && !shouldRemainPlaceholder ? '9px' : `${Number(theme.fontSize)}px`
},
initial: false,
layout: true,
ref: placeholderRef,
style: {
...labelPosition
},
transition: {
type: 'tween',
duration: shouldPreventPlaceholderAnimation ? 0 : 0.1
}
}, /*#__PURE__*/React.createElement(StyledInputLabel, {
$isInvalid: isInvalid
}, placeholder))), shouldShowClearIcon && /*#__PURE__*/React.createElement(StyledMotionInputClearIcon, {
$shouldShowOnlyBottomBorder: shouldShowOnlyBottomBorder,
$size: size,
animate: {
opacity: hasValue ? 1 : 0
},
initial: false,
onClick: handleClearIconClick,
transition: {
type: 'tween'
}
}, /*#__PURE__*/React.createElement(Icon, {
icons: ['fa fa-times'],
color: isInvalid ? theme.wrong : undefined
})), rightElement && shouldShowBorder && rightElement), rightElement && !shouldShowBorder && /*#__PURE__*/React.createElement(StyledInputRightElement, null, rightElement));
});
Input.displayName = 'Input';
export default Input;
//# sourceMappingURL=Input.js.map