UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

159 lines (158 loc) 5.7 kB
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