148 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import React, { useState, useEffect } from 'react';
 | 
						|
import styled, { css } from 'styled-components/macro';
 | 
						|
 | 
						|
const InputWrapper = styled.div<{ width: string }>`
 | 
						|
  position: relative;
 | 
						|
  width: ${props => props.width};
 | 
						|
  display: flex;
 | 
						|
  align-items: flex-start;
 | 
						|
  flex-direction: column;
 | 
						|
  position: relative;
 | 
						|
  justify-content: center;
 | 
						|
 | 
						|
  margin-bottom: 2.2rem;
 | 
						|
  margin-top: 24px;
 | 
						|
`;
 | 
						|
 | 
						|
const InputLabel = styled.span<{ width: string }>`
 | 
						|
  width: ${props => props.width};
 | 
						|
  padding: 0.7rem !important;
 | 
						|
  color: #c2c6dc;
 | 
						|
  left: 0;
 | 
						|
  top: 0;
 | 
						|
  transition: all 0.2s ease;
 | 
						|
  position: absolute;
 | 
						|
  border-radius: 5px;
 | 
						|
  overflow: hidden;
 | 
						|
  font-size: 0.85rem;
 | 
						|
  cursor: text;
 | 
						|
  font-size: 12px;
 | 
						|
      user-select: none;
 | 
						|
    pointer-events: none;
 | 
						|
}
 | 
						|
`;
 | 
						|
 | 
						|
const InputInput = styled.input<{
 | 
						|
  hasValue: boolean;
 | 
						|
  hasIcon: boolean;
 | 
						|
  width: string;
 | 
						|
  focusBg: string;
 | 
						|
  borderColor: string;
 | 
						|
}>`
 | 
						|
  width: ${props => props.width};
 | 
						|
  font-size: 14px;
 | 
						|
  border: 1px solid rgba(0, 0, 0, 0.2);
 | 
						|
  border-color: ${props => props.borderColor};
 | 
						|
  background: #262c49;
 | 
						|
  box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.15);
 | 
						|
  ${props => (props.hasIcon ? 'padding: 0.7rem 1rem 0.7rem 3rem;' : 'padding: 0.7rem;')}
 | 
						|
  line-height: 16px;
 | 
						|
  color: #c2c6dc;
 | 
						|
  position: relative;
 | 
						|
  border-radius: 5px;
 | 
						|
  transition: all 0.3s ease;
 | 
						|
  &:focus {
 | 
						|
    box-shadow: 0 3px 10px 0 rgba(0, 0, 0, 0.15);
 | 
						|
    border: 1px solid rgba(115, 103, 240);
 | 
						|
    background: ${props => props.focusBg};
 | 
						|
  }
 | 
						|
  &:focus ~ ${InputLabel} {
 | 
						|
    color: rgba(115, 103, 240);
 | 
						|
    transform: translate(-3px, -90%);
 | 
						|
  }
 | 
						|
  ${props =>
 | 
						|
    props.hasValue &&
 | 
						|
    css`
 | 
						|
      & ~ ${InputLabel} {
 | 
						|
        color: rgba(115, 103, 240);
 | 
						|
        transform: translate(-3px, -90%);
 | 
						|
      }
 | 
						|
    `}
 | 
						|
`;
 | 
						|
 | 
						|
const Icon = styled.div`
 | 
						|
  display: flex;
 | 
						|
  left: 16px;
 | 
						|
  position: absolute;
 | 
						|
`;
 | 
						|
 | 
						|
type InputProps = {
 | 
						|
  variant?: 'normal' | 'alternate';
 | 
						|
  label?: string;
 | 
						|
  width?: string;
 | 
						|
  placeholder?: string;
 | 
						|
  icon?: JSX.Element;
 | 
						|
  id?: string;
 | 
						|
  name?: string;
 | 
						|
  className?: string;
 | 
						|
  value?: string;
 | 
						|
  onClick?: (e: React.MouseEvent<HTMLInputElement>) => void;
 | 
						|
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
 | 
						|
};
 | 
						|
 | 
						|
const Input = React.forwardRef(
 | 
						|
  (
 | 
						|
    {
 | 
						|
      width = 'auto',
 | 
						|
      variant = 'normal',
 | 
						|
      label,
 | 
						|
      placeholder,
 | 
						|
      icon,
 | 
						|
      name,
 | 
						|
      onChange,
 | 
						|
      className,
 | 
						|
      onClick,
 | 
						|
      value: initialValue,
 | 
						|
      id,
 | 
						|
    }: InputProps,
 | 
						|
    $ref: any,
 | 
						|
  ) => {
 | 
						|
    const [value, setValue] = useState(initialValue ?? '');
 | 
						|
    useEffect(() => {
 | 
						|
      if (initialValue) {
 | 
						|
        setValue(initialValue);
 | 
						|
      }
 | 
						|
    }, [initialValue]);
 | 
						|
    const borderColor = variant === 'normal' ? 'rgba(0, 0, 0, 0.2)' : '#414561';
 | 
						|
    const focusBg = variant === 'normal' ? 'rgba(38, 44, 73, )' : 'rgba(16, 22, 58, 1)';
 | 
						|
    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
 | 
						|
      setValue(e.currentTarget.value);
 | 
						|
      if (onChange) {
 | 
						|
        onChange(e);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    return (
 | 
						|
      <InputWrapper className={className} width={width}>
 | 
						|
        <InputInput
 | 
						|
          hasValue={value !== ''}
 | 
						|
          ref={$ref}
 | 
						|
          id={id}
 | 
						|
          name={name}
 | 
						|
          onClick={onClick}
 | 
						|
          onChange={handleChange}
 | 
						|
          value={value}
 | 
						|
          hasIcon={typeof icon !== 'undefined'}
 | 
						|
          width={width}
 | 
						|
          placeholder={placeholder}
 | 
						|
          focusBg={focusBg}
 | 
						|
          borderColor={borderColor}
 | 
						|
        />
 | 
						|
        {label && <InputLabel width={width}>{label}</InputLabel>}
 | 
						|
        <Icon>{icon && icon}</Icon>
 | 
						|
      </InputWrapper>
 | 
						|
    );
 | 
						|
  },
 | 
						|
);
 | 
						|
 | 
						|
export default Input;
 |