gitscope
← marzneshin / v0.1.0 / app/dashboard/src/components/textarea/index.tsx
https://dev.kronoz.win/r/marzneshin.git
app/dashboard/src/components/textarea/index.tsx · TypeScript
Blame Raw
  1import {
  2  chakra,
  3  FormControl,
  4  FormErrorMessage,
  5  FormLabel,
  6  InputGroup,
  7  InputLeftAddon,
  8  InputRightAddon,
  9  InputRightElement,
 10  Textarea as ChakraTextarea,
 11  TextareaProps as ChakraTextareaProps,
 12} from '@chakra-ui/react';
 13import { XMarkIcon } from '@heroicons/react/24/outline';
 14import classNames from 'classnames';
 15import React, { PropsWithChildren, ReactNode } from 'react';
 16
 17const ClearIcon = chakra(XMarkIcon, {
 18  baseStyle: {
 19    w: 4,
 20    h: 4,
 21  },
 22});
 23
 24export type TextareaProps = PropsWithChildren<
 25  {
 26    value?: string;
 27    className?: string;
 28    endAdornment?: ReactNode;
 29    startAdornment?: ReactNode;
 30    type?: string;
 31    placeholder?: string;
 32    onChange?: (e: any) => void;
 33    onBlur?: (e: any) => void;
 34    onClick?: (e: any) => void;
 35    name?: string;
 36    error?: string;
 37    disabled?: boolean;
 38    step?: number;
 39    label?: string;
 40    clearable?: boolean;
 41  } & ChakraTextareaProps
 42>;
 43
 44export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
 45  (
 46    {
 47      disabled,
 48      step,
 49      label,
 50      className,
 51      startAdornment,
 52      endAdornment,
 53      placeholder,
 54      onChange,
 55      onBlur,
 56      name,
 57      value,
 58      onClick,
 59      error,
 60      clearable = false,
 61      ...props
 62    },
 63    ref
 64  ) => {
 65    const clear = () => {
 66      if (onChange)
 67        onChange({
 68          target: {
 69            value: '',
 70            name,
 71          },
 72        });
 73    };
 74    const { size = 'md' } = props;
 75
 76    return (
 77      <FormControl isInvalid={!!error}>
 78        {label && <FormLabel>{label}</FormLabel>}
 79        <InputGroup
 80          size={size}
 81          w="full"
 82          rounded="md"
 83          _focusWithin={{
 84            outline: '2px solid',
 85            outlineColor: 'primary.200',
 86          }}
 87          bg={disabled ? 'gray.100' : 'transparent'}
 88          _dark={{ bg: disabled ? 'gray.600' : 'transparent' }}
 89        >
 90          {startAdornment && <InputLeftAddon>{startAdornment}</InputLeftAddon>}
 91          {/* @ts-ignore */}
 92          <ChakraTextarea
 93            name={name}
 94            ref={ref}
 95            step={step}
 96            className={classNames(className)}
 97            placeholder={placeholder}
 98            onChange={onChange}
 99            onBlur={onBlur}
100            value={value}
101            onClick={onClick}
102            disabled={disabled}
103            flexGrow={1}
104            _focusVisible={{
105              outline: 'none',
106              borderTopColor: 'transparent',
107              borderRightColor: 'transparent',
108              borderBottomColor: 'transparent',
109            }}
110            _disabled={{
111              cursor: 'not-allowed',
112            }}
113            {...props}
114            roundedLeft={startAdornment ? '0' : 'md'}
115            roundedRight={endAdornment ? '0' : 'md'}
116          />
117          {endAdornment && (
118            <InputRightAddon
119              borderLeftRadius={0}
120              borderRightRadius="6px"
121              bg="transparent"
122            >
123              {endAdornment}
124            </InputRightAddon>
125          )}
126          {clearable && value && value.length && (
127            <InputRightElement
128              borderLeftRadius={0}
129              borderRightRadius="6px"
130              bg="transparent"
131              onClick={clear}
132              cursor="pointer"
133            >
134              <ClearIcon />
135            </InputRightElement>
136          )}
137        </InputGroup>
138        {!!error && <FormErrorMessage>{error}</FormErrorMessage>}
139      </FormControl>
140    );
141  }
142);