@chakra-ui/react#InputRightElement TypeScript Examples

The following examples show how to use @chakra-ui/react#InputRightElement. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SearchInput.tsx    From ksana.in with Apache License 2.0 6 votes vote down vote up
export function SearchInput({ searchText, onChangeSearch }: ISearchInputProps) {
  return (
    <Box width={{ base: '100%' }}>
      <Stack spacing={4}>
        <InputGroup>
          <Input
            size="lg"
            borderWidth="2px"
            borderColor="orange.400"
            name="searchText"
            placeholder="Cari tautan kamu"
            variant="filled"
            value={searchText}
            onChange={onChangeSearch}
          />
          <InputRightElement
            fontSize="2em"
            color="orange.400"
            mr="2"
            mt="1"
            children={<FiSearch />}
          />
        </InputGroup>
      </Stack>
    </Box>
  )
}
Example #2
Source File: InputRightElement.tsx    From openchakra with MIT License 6 votes vote down vote up
InputRightElementPreview: React.FC<{ component: IComponent }> = ({
  component,
}) => {
  const { drop, isOver } = useDropComponent(component.id)
  const { props, ref } = useInteractive(component, true)

  if (isOver) {
    props.bg = 'teal.50'
  }

  return (
    <InputRightElement top="10px" right="10px" {...props} ref={drop(ref)}>
      {component.children.map((key: string) => (
        <ComponentPreview key={key} componentName={key} />
      ))}
    </InputRightElement>
  )
}
Example #3
Source File: Profile.tsx    From dope-monorepo with GNU General Public License v3.0 5 votes vote down vote up
Profile = () => {
  const [section, setSection] = useQueryParam('section', SECTIONS[0]);
  const [searchValue, setSearchValue] = useQueryParam('q', '');
  const debouncedSearchValue = useDebounce<string>(searchValue, 250);

  const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value;
    setSearchValue(value);
  };

  return (
    <>
      <Stack
        margin="0"
        spacing="8px"
        width="100%"
        padding="16px"
        background="white"
        borderBottom="2px solid black"
        direction={['column', 'column', 'row']}
      >
        <InputGroup>
          <Input
            className="search"
            placeholder="Search…"
            size="sm"
            border="2px solid black"
            borderRadius="4px"
            onChange={handleSearchChange}
            value={searchValue}
            _focus={{ boxShadow: '0' }}
          />
          {searchValue !== '' && (
            <InputRightElement height="100%">
              <Image
                width="16px"
                src="/images/icon/circle-clear-input.svg"
                alt="Search"
                onClick={() => setSearchValue('')}
                cursor="pointer"
              />
            </InputRightElement>
          )}
        </InputGroup>
      </Stack>
      <Accordion
        allowToggle
        defaultIndex={SECTIONS.findIndex(val => val === section)}
        onChange={idx => {
          if (idx == -1) return;
          const sectionIdx = Array.isArray(idx) ? idx[0] : idx;
          setSection(SECTIONS[sectionIdx]);
        }}
      >
        <Section>
          <Hustlers searchValue={debouncedSearchValue} />
        </Section>
        <Section>
          <Gear searchValue={debouncedSearchValue} />
        </Section>
        <Section>
          <Dopes searchValue={debouncedSearchValue} />
        </Section>
      </Accordion>
    </>
  );
}
Example #4
Source File: index.tsx    From dope-monorepo with GNU General Public License v3.0 4 votes vote down vote up
MarketFilterBar = ({
  setViewCompactCards,
  setOrderBy,
  orderBy,
  setFilterBy,
  filterBy,
  compactSwitchOn,
  setSearchValue,
}: MarketFilterBarProps) => {
  const [sortBy, setSortBy] = useQueryParam('sort_by', sortKeys[1].value);
  const [status, setStatus] = useQueryParam('status', statusKeys[2]);
  const [searchValueParam, setSearchValueParam] = useQueryParam('q', '');

  const debouncedSearchValue = useDebounce<string>(searchValueParam, 250);

  useEffect(() => {
    setSearchValue(debouncedSearchValue);
  }, [debouncedSearchValue, setSearchValue]);

  useEffect(() => {
    setFilterBy(status as FILTERS);
    setOrderBy(sortBy as SearchOrderField);
  }, [sortBy, setOrderBy, status, setFilterBy]);

  const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value;
    setSearchValueParam(value);
    setSearchValue(value);
  };

  const handleStatusChange = (event: ChangeEvent<HTMLSelectElement>) => {
    const value = event.target.value;
    setStatus(value);
    setFilterBy(status as FILTERS);
  };

  const handleSortChange = (event: ChangeEvent<HTMLSelectElement>) => {
    const value = event.target.value;
    setSortBy(value);
    setFilterBy(value as FILTERS);
  };

  const iconPath = '/images/icon';
  const icon = compactSwitchOn ? 'expand' : 'collapse';

  return (
    <Stack
      margin="0"
      spacing="8px"
      width="100%"
      padding="16px"
      background="white"
      borderBottom="2px solid black"
      direction={['column', 'column', 'row']}
    >
      <a
        href="https://dope-wars.notion.site/dope-wars/Dope-Wiki-e237166bd7e6457babc964d1724befb2#d97ecd4b61ef4189964cd67f230c91c5"
        target="wiki"
      >
        <Button fontSize="xs">DOPE NFT FAQ</Button>
      </a>
      <Container>
        <InputGroup>
          <Input
            className="search"
            placeholder="Search…"
            size="sm"
            onChange={handleSearchChange}
            value={searchValueParam}
            _focus={{ boxShadow: '0' }}
          />
          {searchValueParam !== '' && (
            <InputRightElement height="100%">
              <Image
                width="16px"
                src="/images/icon/circle-clear-input.svg"
                alt="Search"
                onClick={() => setSearchValueParam('')}
                cursor="pointer"
              />
            </InputRightElement>
          )}
        </InputGroup>
        <div>
          <Select
            className="status"
            size="sm"
            onChange={handleStatusChange}
            value={filterBy}
            fontSize="xs"
          >
            <option disabled>Status…</option>
            {statusKeys.map((value, index) => (
              <option key={`${value}-${index}`}>{value}</option>
            ))}
          </Select>
        </div>
        <div>
          <Select size="sm" fontSize="xs" onChange={handleSortChange} value={orderBy}>
            <option disabled>Sort By…</option>
            {sortKeys.map(({ label, value }, index) => (
              <option key={`${value}-${index}`} value={value}>
                {label}
              </option>
            ))}
          </Select>
        </div>
        <Button
          className="toggleButton"
          onClick={() => setViewCompactCards(prevState => !prevState)}
        >
          <Image alt="toggle" src={`${iconPath}/${icon}.svg`} />
        </Button>
      </Container>
    </Stack>
  );
}
Example #5
Source File: ChatType.tsx    From dope-monorepo with GNU General Public License v3.0 4 votes vote down vote up
export default function ChatType(props: Props) {
  const [ unreadMessages, setUnreadMessages ] = React.useState(0);
  const [ inputText, setInputText ] = React.useState('');
  const [ messages, setMessages ] = React.useState(props.messagesStore);
  const [ canSendMessage, setCanSendMessage ] = React.useState((props.chatMessageBoxes?.length ?? 0) < 3);

  const messagesListRef = React.useRef<HTMLUListElement>(null);

  let state = React.useRef({
    i: -1,
  });

  useEffect(() => {
    props.manager.events.on('chat_message', (message: DataTypes[NetworkEvents.SERVER_PLAYER_CHAT_MESSAGE]) => {
      setMessages(m => [...m, message]);
      const lastMessageEl = messagesListRef.current?.lastElementChild as HTMLLIElement;
      if (lastMessageEl && 
        lastMessageEl?.parentElement?.parentElement && !isVisible(lastMessageEl, lastMessageEl?.parentElement?.parentElement)) 
        setUnreadMessages(u => u + 1);
    });

    // constantly check chatMessageBoxes size and if it's less than 3, set canSendMessage to true
    const interval = setInterval(() => setCanSendMessage((props.chatMessageBoxes?.length ?? 0) < 3));
    return () => clearInterval(interval);
  }, []);

  const handleInputKey = (e: KeyboardEvent) => {
    if (e.key === 'Enter' && canSendMessage) handleSubmit(inputText);
    else if (e.key === 'Escape')
      // send "nothing", chat will get closed & message will not get sent
      handleSubmit('');
    else if (e.key === 'ArrowUp') {
      state.current.i = ++state.current.i % props.precedentMessages.length;
      const precedentMessage = props.precedentMessages[state.current.i];
      if (precedentMessage) setInputText(precedentMessage);
    } else if (e.key === 'ArrowDown') {
      // rolling window, wrap around
      state.current.i = --state.current.i % props.precedentMessages.length;
      if (state.current.i < 0) state.current.i = props.precedentMessages.length - 1;

      const precedentMessage = props.precedentMessages[state.current.i];
      if (precedentMessage) setInputText(precedentMessage);
    }
  };

  const handleSubmit = (content: string) => {
    if (content.length > 150)
      return;

    props.manager.events.emit('chat_submit', content);
  };

  return (
    <ChakraProvider theme={theme}>
      <Container 
      style={{
        position: 'absolute',
        backgroundColor: 'rgba(0,0,0,0.7)',
        borderRadius: '0.5rem',
        boxShadow: '0 0.5rem 1rem rgba(0, 0, 0, 0.7)',
        height: '30%',
        width: '30%',
        left: "1%",
        bottom: "1%",
      }}>
        <Stack style={{
          paddingTop: '1rem',
          height: '95%',
        }}>
          <div style={{
            display: 'flex',
            overflow: 'auto',
            flexDirection: 'column-reverse',
            marginBottom: '-3%',
          }}>
            <List ref={messagesListRef} spacing={-2} style={{
            }}>
              <Text style={{
                color: 'blueviolet',
              }}>
                Welcome to the Dopeverse!
              </Text>
              {messages.map((message, i) => <ListItem key={i}>
                  <HStack style={{
                    opacity: '0.8'
                  }}>
                    <Text style={{
                      color: 'white',
                    }}>
                      {message.author}: {message.message}
                    </Text>
                    <Spacer />
                    <Text style={{
                      color: 'grey',
                      fontSize: '0.6rem',
                    }}>
                      {new Date(message.timestamp).toLocaleString()}
                    </Text>
                  </HStack>
              </ListItem>)}
            </List>
          </div>
          <Spacer />
          <Center>
            <Button 
                  style={{
                    marginRight: '1%',
                    marginTop: '-10%'
                  }}
                  variant="primary"
                  backgroundColor="red.600"
                  hidden={inputText.length <= 150} 
                  onClick={() => setInputText(inputText.substring(0, 150))}
                >
                ❌ Message too long
            </Button>
            <Button 
              style={{
                marginTop: '-10%',
              }}
              variant="primary" 
              hidden={unreadMessages === 0} 
              onClick={(e) => {
                setUnreadMessages(0);
                e.currentTarget.hidden = true;
                if (messagesListRef.current)
                  (messagesListRef.current as HTMLOListElement).lastElementChild?.scrollIntoView({
                    behavior: 'smooth',
                  });
              }}
            >
              ⬇️ New message ({unreadMessages})
            </Button>
          </Center>
          <Center>
            <InputGroup width="90%" size="md">
              <Input
                autoFocus={true}
                focusBorderColor="white"
                onBlur={({ target }) => target.focus()}
                pr="4.5rem"
                placeholder="Message"
                _placeholder={{ color: '#b8b8b8' }}
                textColor="#f5f5f5"
                value={inputText}
                onChange={({ target }) => setInputText(target.value)}
                onKeyDown={handleInputKey}
                style={{
                  backgroundColor: 'rgba(0, 0, 0, 0.3)',
                }}
              />
              <InputRightElement width="4.5rem" style={{ paddingRight: '2%' }}>
                <Button h="1.75rem" size="sm" disabled={!canSendMessage} onClick={() => handleSubmit(inputText)}>
                  Send
                </Button>
              </InputRightElement>
            </InputGroup>
          </Center>
        </Stack>
      </Container>
    </ChakraProvider>
  );
}
Example #6
Source File: CustomPropsPanel.tsx    From openchakra with MIT License 4 votes vote down vote up
CustomPropsPanel = () => {
  const dispatch = useDispatch()
  const inputRef = useRef<HTMLInputElement>(null)

  const activePropsRef = useInspectorState()
  const { props, id } = useSelector(getSelectedComponent)
  const { setValue } = useForm()

  const [quickProps, setQuickProps] = useState('')
  const [hasError, setError] = useState(false)

  const onDelete = (propsName: string) => {
    dispatch.components.deleteProps({
      id,
      name: propsName,
    })
  }

  const activeProps = activePropsRef || []
  const customProps = Object.keys(props).filter(
    propsName => !activeProps.includes(propsName),
  )

  return (
    <>
      <form
        onSubmit={(event: FormEvent) => {
          event.preventDefault()

          const [name, value] = quickProps.split(SEPARATOR)

          if (name && value) {
            setValue(name, value)
            setQuickProps('')
            setError(false)
          } else {
            setError(true)
          }
        }}
      >
        <InputGroup mb={3} size="sm">
          <InputRightElement
            children={<Box as={IoIosFlash} color="gray.300" />}
          />
          <Input
            ref={inputRef}
            isInvalid={hasError}
            value={quickProps}
            placeholder={`props${SEPARATOR}value`}
            onChange={(event: ChangeEvent<HTMLInputElement>) =>
              setQuickProps(event.target.value)
            }
          />
        </InputGroup>
      </form>

      {customProps.map((propsName, i) => (
        <Flex
          key={propsName}
          alignItems="center"
          px={2}
          bg={i % 2 === 0 ? 'white' : 'gray.50'}
          fontSize="xs"
          justifyContent="space-between"
        >
          <SimpleGrid width="100%" columns={2} spacing={1}>
            <Box fontWeight="bold">{propsName}</Box>
            <Box>{props[propsName]}</Box>
          </SimpleGrid>

          <ButtonGroup display="flex" size="xs" isAttached>
            <IconButton
              onClick={() => {
                setQuickProps(`${propsName}=`)
                if (inputRef.current) {
                  inputRef.current.focus()
                }
              }}
              variant="ghost"
              size="xs"
              aria-label="edit"
              icon={<EditIcon path="" />}
            />
            <IconButton
              onClick={() => onDelete(propsName)}
              variant="ghost"
              size="xs"
              aria-label="delete"
              icon={<SmallCloseIcon path="" />}
            />
          </ButtonGroup>
        </Flex>
      ))}
    </>
  )
}
Example #7
Source File: Sidebar.tsx    From openchakra with MIT License 4 votes vote down vote up
Menu = () => {
  const [searchTerm, setSearchTerm] = useState('')

  return (
    <DarkMode>
      <Box
        maxH="calc(100vh - 3rem)"
        overflowY="auto"
        overflowX="visible"
        boxShadow="xl"
        flex="0 0 14rem"
        p={5}
        m={0}
        as="menu"
        backgroundColor="#2e3748"
        width="15rem"
      >
        <InputGroup size="sm" mb={4}>
          <Input
            value={searchTerm}
            color="gray.300"
            placeholder="Search component…"
            onChange={(event: ChangeEvent<HTMLInputElement>) =>
              setSearchTerm(event.target.value)
            }
            borderColor="rgba(255, 255, 255, 0.04)"
            bg="rgba(255, 255, 255, 0.06)"
            _hover={{
              borderColor: 'rgba(255, 255, 255, 0.08)',
            }}
            zIndex={0}
          />
          <InputRightElement zIndex={1}>
            {searchTerm ? (
              <IconButton
                color="gray.300"
                aria-label="clear"
                icon={<CloseIcon path="" />}
                size="xs"
                onClick={() => setSearchTerm('')}
              />
            ) : (
              <SearchIcon path="" color="gray.300" />
            )}
          </InputRightElement>
        </InputGroup>

        {(Object.keys(menuItems) as ComponentType[])
          .filter(c => c.toLowerCase().includes(searchTerm.toLowerCase()))
          .map(name => {
            const { children, soon } = menuItems[name] as MenuItem

            if (children) {
              const elements = Object.keys(children).map(childName => (
                <DragItem
                  isChild
                  key={childName}
                  label={childName}
                  type={childName as any}
                  id={childName as any}
                  rootParentType={menuItems[name]?.rootParentType || name}
                >
                  {childName}
                </DragItem>
              ))

              return [
                <DragItem
                  isMeta
                  soon={soon}
                  key={`${name}Meta`}
                  label={name}
                  type={`${name}Meta` as any}
                  id={`${name}Meta` as any}
                  rootParentType={menuItems[name]?.rootParentType || name}
                >
                  {name}
                </DragItem>,
                ...elements,
              ]
            }

            return (
              <DragItem
                soon={soon}
                key={name}
                label={name}
                type={name as any}
                id={name as any}
                rootParentType={menuItems[name]?.rootParentType || name}
              >
                {name}
              </DragItem>
            )
          })}
      </Box>
    </DarkMode>
  )
}
Example #8
Source File: EditUrlInput.tsx    From coindrop with GNU General Public License v3.0 4 votes vote down vote up
EditUrlInput: FunctionComponent<Props> = ({ register, value }) => {
    const { query: { piggybankName }} = useRouter();
    const currentPiggybankId = Array.isArray(piggybankName) ? piggybankName[0] : piggybankName;
    const [isValidating, setIsValidating] = useState(false);
    const [isValid, setIsValid] = useState(false);
    const [error, setError] = useState<'Invalid input' | 'Id taken' | 'Network error'>();
    const debouncedValue = useDebounce(value, 1500);
    const { setIsPiggybankIdAvailable } = useContext(AdditionalValidation);
    const isUrlUnchanged = value === currentPiggybankId;
    const isInvalid = !debouncedValue.match(piggybankPathRegex);
    const validateIsAvailable = async () => {
        if (isUrlUnchanged) {
            setIsValid(true);
            setIsPiggybankIdAvailable(true);
            setError(null);
            setIsValidating(false);
            return;
        }
        if (isInvalid) {
            setIsValid(false);
            setIsPiggybankIdAvailable(false);
            setError('Invalid input');
            setIsValidating(false);
            return;
        }
        try {
            const isAvailable = await isCoindropUrlAvailable(debouncedValue);
            setIsValid(isAvailable && !isInvalid);
            setIsPiggybankIdAvailable(isAvailable && !isInvalid);
            if (!isAvailable) {
                setError('Id taken');
            }
        } catch (err) {
            setIsValid(false);
            setIsPiggybankIdAvailable(false);
            setError('Network error');
        } finally {
            setIsValidating(false);
        }
    };
    useEffect(() => {
        validateIsAvailable();
    }, [debouncedValue]);
    useEffect(() => {
        setIsValidating(true);
        setError(null);
    }, [value]);
    useEffect(() => {
        setIsValidating(false);
    }, []);
    return (
        <>
        <InputGroup>
            <InputLeftAddon>
                coindrop.to/
            </InputLeftAddon>
            <Input
                id="input-piggybankId"
                maxLength={32}
                roundedLeft="0"
                isInvalid={!isValid && !isValidating && value === debouncedValue && !isUrlUnchanged}
                ref={register}
                name="piggybankId"
            />
            <InputRightElement>
                <StatusIcon
                    value={value}
                    debouncedValue={debouncedValue}
                    currentPiggybankId={currentPiggybankId}
                    isValid={isValid}
                    isValidating={isValidating}
                />
            </InputRightElement>
        </InputGroup>
        {error === 'Invalid input' && (
            <CoindropRequirements />
        )}
        {error === 'Id taken' && (
            <CreateCoindropError
                error="URL is taken, try another!"
            />
        )}
        {error === 'Network error' && (
            <CreateCoindropError
                error="Error checking availability, please try again"
            />
        )}
        </>
    );
}