react#KeyboardEvent TypeScript Examples

The following examples show how to use react#KeyboardEvent. 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: index.ts    From anchor-web-app with Apache License 2.0 6 votes vote down vote up
/**
 * @param availableCharacters 'abc', 'a-z', 'a-z0-9'
 */
export function useRestrictedInput(
  availableCharacters: ((character: string) => boolean) | string,
): RestrictedInputReturn {
  const test: (character: string) => boolean = useMemo(() => {
    if (typeof availableCharacters === 'string') {
      const pattern: RegExp = new RegExp(`[${availableCharacters}]`);
      return (character: string) => pattern.test(character);
    } else if (typeof availableCharacters === 'function') {
      return availableCharacters;
    }
    throw new Error('availableCharacters must be string or function');
  }, [availableCharacters]);

  const onKeyPress: (event: KeyboardEvent<HTMLInputElement>) => void =
    useCallback(
      (event: KeyboardEvent<HTMLInputElement>) => {
        if (!test(event.key)) {
          // prevent key press
          event.preventDefault();
          event.stopPropagation();
        }
      },
      [test],
    );

  return {
    onKeyPress,
  };
}
Example #2
Source File: plugin.ts    From brilliant with MIT License 6 votes vote down vote up
onTab = (
    e: KeyboardEvent,
    { getEditorState, setEditorState }: PluginFunctions
  ): void => {
    const editorState = getEditorState();
    const selection = editorState.getSelection();
    const content = editorState.getCurrentContent();
    const type = content.getBlockForKey(selection.getStartKey()).getType();
    if (type === 'unordered-list-item' || type === 'ordered-list-item') {
      setEditorState(RichUtils.onTab(e as any, editorState, 4));
      e.preventDefault();
      return;
    }
    const newContentState = Modifier.insertText(
      content,
      selection,
      '  ',
      editorState.getCurrentInlineStyle()
    );
    setEditorState(
      EditorState.push(editorState, newContentState, 'insert-fragment')
    );
    e.preventDefault();
  };
Example #3
Source File: index.tsx    From reskript with MIT License 6 votes vote down vote up
export default function Create({onSubmit}: Props) {
    const [value, setValue] = useState('');
    const updateValue = useCallback(
        (e: ChangeEvent<HTMLInputElement>) => setValue(e.target.value),
        []
    );
    const submit = useCallback(
        (e: KeyboardEvent<HTMLInputElement>) => {
            const description = value.trim();

            if (description && e.key === 'Enter') {
                e.preventDefault();
                onSubmit({description});
                setValue('');
            }
        },
        [onSubmit, value]
    );

    return (
        <div id="create">
            <Input
                className={c.input}
                placeholder="What needs to be done?"
                value={value}
                onChange={updateValue}
                onKeyDown={submit}
            />
        </div>
    );
}
Example #4
Source File: CalculatorInputs.tsx    From po8klasie with GNU General Public License v3.0 6 votes vote down vote up
GradeInput: FC<CalculatorInputProps> = ({ inputId, ...props }) => {
  const { watch, setValue: setValueOriginal, setError } = useFormContext();
  const value = watch(inputId);
  const setValue = (updatedValue: number | null) => setValueOriginal(inputId, updatedValue);

  const handleKeyDown = (e: KeyboardEvent) => {
    if (['Backspace', 'Delete'].includes(e.key)) {
      e.preventDefault();
      setValue(null);
    }
  };

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const len = e.target.value.length;
    const updatedValue = len > 0 ? e.target.value[len - 1] : '';

    const parsedValue = parseInt(updatedValue, 10);
    if (isGradeValid(parsedValue)) setValue(parsedValue);
    else {
      setValue(null);
      setError(inputId, { message: 'Invalid value' });
    }
  };

  const inputProps: Partial<HTMLProps<HTMLInputElement>> = {
    ...props,
    placeholder: '5',
    'aria-label': 'Ocena',
    inputMode: 'numeric',
    value: value ?? '',
    onKeyDown: handleKeyDown,
    onChange: handleChange,
    autoComplete: 'off',
  };

  return <input {...inputProps} data-testid="input" />;
}
Example #5
Source File: ChildrenControl.tsx    From openchakra with MIT License 6 votes vote down vote up
ChildrenControl: React.FC = () => {
  const dispatch = useDispatch()
  const textInput = useRef<HTMLInputElement>(null)
  const focusInput = useSelector(getInputTextFocused)
  const { setValueFromEvent } = useForm()
  const children = usePropsSelector('children')
  const onKeyUp = (event: KeyboardEvent) => {
    if (event.keyCode === 13 && textInput.current) {
      textInput.current.blur()
    }
  }
  useEffect(() => {
    if (focusInput && textInput.current) {
      textInput.current.focus()
    } else if (focusInput === false && textInput.current) {
      textInput.current.blur()
    }
  }, [focusInput])

  return (
    <FormControl htmlFor="children" label="Text">
      <Input
        id="children"
        name="children"
        size="sm"
        value={children}
        type="text"
        onChange={setValueFromEvent}
        ref={textInput}
        onKeyUp={onKeyUp}
        onBlur={() => {
          dispatch.app.toggleInputText(false)
        }}
      />
    </FormControl>
  )
}
Example #6
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 6 votes vote down vote up
setTagFilters(filter: string, event: KeyboardEvent | MouseEvent | TouchEvent) {
    const tags = Object.keys(this.taxonomy.tagCounts).sort((a, b) => {
      if (a === 'untagged') return -1;
      else if (b === 'untagged') return 1;
      else return a.localeCompare(b);
    });

    // Put 'untagged' in the correct second position for shift click ordering
    tags.splice(tags.indexOf('untagged'), 1);
    tags.splice(1, 0, 'untagged');

    this.computeFilters(tags, this.tagFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #7
Source File: useDatePicker.ts    From use-platform with MIT License 6 votes vote down vote up
export function useDatePicker(
  props: UseDatePickerProps,
  state: UseDatePickerStateResult<Date | DateRangeValue | null>,
): UseDatePickerResult {
  const { disabled, readOnly } = props

  const onKeyDown = (event: KeyboardEvent) => {
    if (disabled || readOnly) {
      return
    }

    if (event.key === ' ') {
      event.preventDefault()
      event.stopPropagation()
      state.setOpen(true)
    }
  }

  const onPress = () => {
    state.setOpen(!state.isOpen)
  }

  return {
    groupProps: {
      role: 'group',
      onKeyDown,
    },
    triggerProps: {
      tabIndex: -1,
      onPress,
    },
  }
}
Example #8
Source File: TorrentListRow.tsx    From flood with GNU General Public License v3.0 6 votes vote down vote up
onKeyPress = (hash: string, e: KeyboardEvent) => {
  if (e.key === ' ' || e.key === 'Enter' || e.key === 'ContextMenu') {
    e.preventDefault();
    if (TorrentStore.selectedTorrents.includes(hash)) {
      if (e.key === 'Enter') {
        displayTorrentDetails(hash);
      } else if (e.key === 'ContextMenu') {
        displayContextMenu(hash, e);
      }
    } else {
      selectTorrent(hash, e);
    }
  }
}
Example #9
Source File: MessageFormatEditor.tsx    From project-loved-web with MIT License 5 votes vote down vote up
function onKeyDown(event: KeyboardEvent): void {
  if (event.key === 'Enter') {
    event.preventDefault();
  }
}
Example #10
Source File: plugin.ts    From brilliant with MIT License 5 votes vote down vote up
keyBindingFn = (e: React.KeyboardEvent<{}>): string | null =>
    handleMyKeyBindingFn(e, getDefaultKeyBinding);
Example #11
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
private computeFilters<T extends TorrentStatus | string>(
    keys: readonly T[],
    currentFilters: Array<T>,
    newFilter: T,
    event: KeyboardEvent | MouseEvent | TouchEvent,
  ) {
    if (newFilter === ('' as T)) {
      currentFilters.splice(0);
    } else if (event.shiftKey) {
      if (currentFilters.length) {
        const lastKey = currentFilters[currentFilters.length - 1];
        const lastKeyIndex = keys.indexOf(lastKey);
        let currentKeyIndex = keys.indexOf(newFilter);

        if (!~currentKeyIndex || !~lastKeyIndex) {
          return;
        }

        // from the previously selected index to the currently selected index,
        // add all filters to the selected array.
        // if the newly selected index is larger than the previous, start from
        // the newly selected index and work backwards. otherwise go forwards.
        const increment = currentKeyIndex > lastKeyIndex ? -1 : 1;

        for (; currentKeyIndex !== lastKeyIndex; currentKeyIndex += increment) {
          const foundKey = keys[currentKeyIndex] as T;
          // if the filter isn't already selected, add the filter to the array.
          if (!currentFilters.includes(foundKey)) {
            currentFilters.push(foundKey);
          }
        }
      } else {
        currentFilters.splice(0, currentFilters.length, newFilter);
      }
    } else if (event.metaKey || event.ctrlKey) {
      if (currentFilters.includes(newFilter)) {
        currentFilters.splice(currentFilters.indexOf(newFilter), 1);
      } else {
        currentFilters.push(newFilter);
      }
    } else {
      currentFilters.splice(0, currentFilters.length, newFilter);
    }
  }
Example #12
Source File: index.tsx    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
function RestoreBase(props: UIElementProps) {
  const { className } = props;

  const [input, state] = useRestoreTxForm();
  const [restoreTx, txResult] = useRestoreTx();

  const submit = useCallback(() => {
    if (restoreTx) {
      restoreTx({ txHash: state.txHash });
    }
  }, [state, restoreTx]);

  if (
    txResult?.status === StreamStatus.IN_PROGRESS ||
    txResult?.status === StreamStatus.DONE
  ) {
    return <TxRendering className={className} txResult={txResult} />;
  }

  return (
    <CenteredLayout className={className} maxWidth={800}>
      <Section>
        <h1>Restore</h1>
        <p className="text">
          Below you may attempt to restore a stuck transaction. In order to
          proceed with restoration, transaction hash is required.
        </p>

        <TextInput
          className="tx-hash"
          fullWidth
          placeholder="TRANSACTION HASH"
          value={state.txHash}
          onChange={({ target }: ChangeEvent<HTMLInputElement>) =>
            input({ txHash: target.value })
          }
          onKeyPress={({ key }: KeyboardEvent<HTMLInputElement>) => {
            if (key === 'Enter') {
              submit();
            }
          }}
        />

        <ActionButton className="submit" onClick={submit}>
          Restore
        </ActionButton>
      </Section>
    </CenteredLayout>
  );
}
Example #13
Source File: UserBox.tsx    From tobira with Apache License 2.0 5 votes vote down vote up
MenuItem: React.FC<MenuItemProps> = ({
    icon,
    children,
    linkTo,
    onClick = () => {},
    className,
    htmlLink = false,
    borderBottom = false,
    borderTop = false,
}) => {
    const inner = <>
        {icon ?? <svg />}
        <div>{children}</div>
    </>;
    const css = {
        display: "flex",
        gap: 16,
        alignItems: "center",
        height: 40,
        paddingLeft: "12px",
        paddingRight: "16px",
        cursor: "pointer",
        whiteSpace: "nowrap",
        color: "black",
        ...borderBottom && {
            borderBottom: "1px solid var(--grey80)",
        },
        ...borderTop && {
            borderTop: "1px solid var(--grey80)",
        },
        "& > svg": {
            fontSize: 22,
            width: 24,
            strokeWidth: 1.5,
            "& > path": {
                strokeWidth: "inherit",
            },
        },
        "&:hover": {
            backgroundColor: "var(--grey97)",
        },
        ...FOCUS_STYLE_INSET,
    } as const;


    // One should be able to use the menu with keyboard only. So if the item is
    // focussed, pressing enter should have the same effect as clicking it.
    // Thats already true automatically for links.
    const onKeyDown = (e: KeyboardEvent<HTMLLIElement>) => {
        if (document.activeElement === e.currentTarget && e.key === "Enter") {
            onClick();
        }
    };

    return linkTo
        ? <li {... { className }}>
            <Link to={linkTo} css={css} {...{ htmlLink, onClick, className }}>{inner}</Link>
        </li>
        : <li tabIndex={0} css={css} {...{ onClick, className, onKeyDown }}>
            {inner}
        </li>;
}
Example #14
Source File: FileLocation.tsx    From firebase-tools-ui with Apache License 2.0 5 votes vote down vote up
FileLocation: React.FC<
  React.PropsWithChildren<FileLocationProps>
> = ({ fullPath }) => {
  const { tokens, createToken, deleteToken } = useTokens(fullPath);
  const { getLocation } = useStorageFiles();
  const { writeText } = useClipboard();

  return (
    <Accordion title="File location">
      <dl className={styles.metadata}>
        <Typography use="body2" tag="dt" theme="secondary">
          File location
        </Typography>
        <Typography use="body2" tag="dd" className={styles.location}>
          {getLocation(fullPath)}
        </Typography>
        {tokens.map((token) => (
          <div key={token}>
            <Typography use="body2" tag="dt" theme="secondary">
              Access token
              <SimpleMenu
                handle={<IconButton icon="more_vert" label="Open menu" />}
                renderToPortal
              >
                <MenuItem
                  onKeyDown={(e: KeyboardEvent<HTMLElement>) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                      deleteToken(token);
                    }
                  }}
                  onClick={() => deleteToken(token)}
                >
                  Revoke
                </MenuItem>
              </SimpleMenu>
            </Typography>
            <Typography use="body2" tag="dd">
              <Tooltip content="Click to copy the token to clipboard">
                <input
                  aria-label="Token, press Enter to copy"
                  className={styles.token}
                  readOnly
                  value={token}
                  onClick={() => writeText(token)}
                  onKeyDown={(e: KeyboardEvent<HTMLElement>) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                      writeText(token);
                    }
                  }}
                />
              </Tooltip>
            </Typography>
          </div>
        ))}
      </dl>
      <Button unelevated onClick={createToken}>
        Create new access token
      </Button>
    </Accordion>
  );
}
Example #15
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
setTrackerFilters(filter: string, event: KeyboardEvent | MouseEvent | TouchEvent) {
    const trackers = Object.keys(this.taxonomy.trackerCounts).sort((a, b) => a.localeCompare(b));

    this.computeFilters(trackers, this.trackerFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #16
Source File: TagsInput.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onKeyboardAdd = (event: KeyboardEvent) => {
    event.preventDefault();
    if (event.key === 'Enter' && this.state.newTag !== '') {
      this.setNewTags();
    }
  };
Example #17
Source File: CurrencySearch.tsx    From goose-frontend-amm with GNU General Public License v3.0 5 votes vote down vote up
export function CurrencySearch({
  selectedCurrency,
  onCurrencySelect,
  otherSelectedCurrency,
  showCommonBases,
  onDismiss,
  isOpen,
  onChangeList,
}: CurrencySearchProps) {
  const { t } = useTranslation()
  const { chainId } = useActiveWeb3React()
  const theme = useContext(ThemeContext)

  const fixedList = useRef<FixedSizeList>()
  const [searchQuery, setSearchQuery] = useState<string>('')
  const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
  const allTokens = useAllTokens()

  // if they input an address, use it
  const isAddressSearch = isAddress(searchQuery)
  const searchToken = useToken(searchQuery)

  const showETH: boolean = useMemo(() => {
    const s = searchQuery.toLowerCase().trim()
    return s === '' || s === 'e' || s === 'et' || s === 'eth'
  }, [searchQuery])

  const tokenComparator = useTokenComparator(invertSearchOrder)

  const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>((state) => state.user.audioPlay)

  const filteredTokens: Token[] = useMemo(() => {
    if (isAddressSearch) return searchToken ? [searchToken] : []
    return filterTokens(Object.values(allTokens), searchQuery)
  }, [isAddressSearch, searchToken, allTokens, searchQuery])

  const filteredSortedTokens: Token[] = useMemo(() => {
    if (searchToken) return [searchToken]
    const sorted = filteredTokens.sort(tokenComparator)
    const symbolMatch = searchQuery
      .toLowerCase()
      .split(/\s+/)
      .filter((s) => s.length > 0)
    if (symbolMatch.length > 1) return sorted

    return [
      ...(searchToken ? [searchToken] : []),
      // sort any exact symbol matches first
      ...sorted.filter((token) => token.symbol?.toLowerCase() === symbolMatch[0]),
      ...sorted.filter((token) => token.symbol?.toLowerCase() !== symbolMatch[0]),
    ]
  }, [filteredTokens, searchQuery, searchToken, tokenComparator])

  const handleCurrencySelect = useCallback(
    (currency: Currency) => {
      onCurrencySelect(currency)
      onDismiss()
      if (audioPlay) {
        const audio = document.getElementById('bgMusic') as HTMLAudioElement
        if (audio) {
          audio.play()
        }
      }
    },
    [onDismiss, onCurrencySelect, audioPlay]
  )

  // clear the input on open
  useEffect(() => {
    if (isOpen) setSearchQuery('')
  }, [isOpen])

  // manage focus on modal show
  const inputRef = useRef<HTMLInputElement>()
  const handleInput = useCallback((event) => {
    const input = event.target.value
    const checksummedInput = isAddress(input)
    setSearchQuery(checksummedInput || input)
    fixedList.current?.scrollTo(0)
  }, [])

  const handleEnter = useCallback(
    (e: KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        const s = searchQuery.toLowerCase().trim()
        if (s === 'eth') {
          handleCurrencySelect(ETHER)
        } else if (filteredSortedTokens.length > 0) {
          if (
            filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
            filteredSortedTokens.length === 1
          ) {
            handleCurrencySelect(filteredSortedTokens[0])
          }
        }
      }
    },
    [filteredSortedTokens, handleCurrencySelect, searchQuery]
  )

  const selectedListInfo = useSelectedListInfo()

  return (
    <Column style={{ width: '100%', flex: '1 1' }}>
      <PaddedColumn gap="14px">
        <RowBetween>
          <Text>
            <TranslatedText translationId={82}>Select a token</TranslatedText>
            <QuestionHelper
              text={TranslateString(
                130,
                'Find a token by searching for its name or symbol or by pasting its address below.'
              )}
            />
          </Text>
          <CloseIcon onClick={onDismiss} />
        </RowBetween>
        <SearchInput
          type="text"
          id="token-search-input"
          placeholder={t('tokenSearchPlaceholder')}
          value={searchQuery}
          ref={inputRef as RefObject<HTMLInputElement>}
          onChange={handleInput}
          onKeyDown={handleEnter}
        />
        {showCommonBases && (
          <CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
        )}
        <RowBetween>
          <Text fontSize="14px">
            <TranslatedText translationId={126}>Token name</TranslatedText>
          </Text>
          <SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder((iso) => !iso)} />
        </RowBetween>
      </PaddedColumn>

      <Separator />

      <div style={{ flex: '1' }}>
        <AutoSizer disableWidth>
          {({ height }) => (
            <CurrencyList
              height={height}
              showETH={showETH}
              currencies={filteredSortedTokens}
              onCurrencySelect={handleCurrencySelect}
              otherCurrency={otherSelectedCurrency}
              selectedCurrency={selectedCurrency}
              fixedListRef={fixedList}
            />
          )}
        </AutoSizer>
      </div>

      {null && (
        <>
          <Separator />
          <Card>
            <RowBetween>
              {selectedListInfo.current ? (
                <Row>
                  {selectedListInfo.current.logoURI ? (
                    <ListLogo
                      style={{ marginRight: 12 }}
                      logoURI={selectedListInfo.current.logoURI}
                      alt={`${selectedListInfo.current.name} list logo`}
                    />
                  ) : null}
                  <Main id="currency-search-selected-list-name">{selectedListInfo.current.name}</Main>
                </Row>
              ) : null}
              <LinkStyledButton
                style={{ fontWeight: 500, color: theme.colors.textSubtle, fontSize: 16 }}
                onClick={onChangeList}
                id="currency-search-change-list-button"
              >
                {selectedListInfo.current ? 'Change' : 'Select a list'}
              </LinkStyledButton>
            </RowBetween>
          </Card>
        </>
      )}
    </Column>
  )
}
Example #18
Source File: InputChip.tsx    From frontegg-react with MIT License 5 votes vote down vote up
InputChip: FC<InputChipProps> = ({ onChange, validate, value = [], ...props }) => {
  const inputRef = useRef<HTMLInputElement>(null);
  const onSave = useCallback(async () => {
    const inputValue = inputRef.current?.value ?? '';
    if (!inputValue) return;
    if (validate && !(await validate([...value, inputValue]))) {
      return;
    }
    if (inputRef.current) {
      inputRef.current.value = '';
    }
    const ev2 = new Event('input', { bubbles: true });
    inputRef.current?.dispatchEvent(ev2);

    onChange && onChange([...value, inputValue]);
    return;
  }, [inputRef, value, validate]);

  const onKeyPress = useCallback(
    async (e: KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        await onSave();
      }
      return;
    },
    [onSave]
  );

  const onDelete = useCallback(
    (idx: number) => {
      onChange && onChange([...value.slice(0, idx), ...value.slice(idx + 1)]);
    },
    [onChange, value]
  );

  const onBlur = useCallback(
    async (e: ChangeEvent<HTMLInputElement>) => {
      if (!e.currentTarget.value.trim()) {
        e.currentTarget.value = '';
        return;
      }
      await onSave();
      return;
    },
    [onSave]
  );

  return React.createElement(ElementsFactory.getElement('InputChip'), {
    ...props,
    onBlur,
    onKeyPress,
    onDelete,
    chips: value,
    ref: inputRef,
  });
}
Example #19
Source File: index.tsx    From dockerstats with Apache License 2.0 5 votes vote down vote up
onKeyPress = (e: KeyboardEvent) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      this.go()
    }
  }
Example #20
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
setStatusFilters(filter: TorrentStatus | '', event: KeyboardEvent | MouseEvent | TouchEvent) {
    this.computeFilters(torrentStatusMap, this.statusFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #21
Source File: NativeList.tsx    From GTAV-NativeDB with MIT License 5 votes vote down vote up
export default function NativeList() {
  const [filter, setFilter] = useState('')
  const namespaces = useNativeSearch(filter)
  const inputRef = useRef<HTMLInputElement>(null)
  const history = useHistory()
  const query = useQuery()

  useEffect(() => {
    const search = query.get('search')
    setFilter(search ?? '')
  }, [query, setFilter])

  const handleSearchKeyDown = useCallback((e: KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      inputRef.current?.blur()
      e.preventDefault()
    }
  }, [inputRef])

  const handleSearchBlur = useCallback(() => {
    if (filter) {
      history.replace(`${history.location.pathname}?search=${encodeURIComponent(filter)}`)
    }
    else {
      history.replace(history.location.pathname)
    }
  }, [history, filter])

  const handleFilterChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    setFilter(e.target.value)
  }, [setFilter])

  useSetAppBarSettings('NativeList', {
    search: {
      onChange: handleFilterChange,
      onKeyDown: handleSearchKeyDown,
      onBlur: handleSearchBlur,
      ref: inputRef,
      value: filter
    }
  })

  useHotkeys('ctrl+k', () => {
    inputRef.current?.focus()
  }, {
    filter: (event: globalThis.KeyboardEvent) => {
      event.preventDefault()
      return true
    },
  }, [inputRef])

  return (
    <Fragment>
      <NativeListComponent
        sx={{ height: '100%' }}
        namespaces={namespaces}
      />
    </Fragment>
  )
}
Example #22
Source File: index.tsx    From hive with MIT License 5 votes vote down vote up
button = (e: KeyboardEvent<HTMLInputElement>) => {
        const { authService } = this.props;
        if (e.key === constants.keys.enter) {
            authService.loginWan();
        }
    };
Example #23
Source File: TextArea.tsx    From Notepad with MIT License 5 votes vote down vote up
function TextArea() {
  const [linesNum, setLineNum] = useState(1);
  const [columnIndex, setColumnIndex] = useState(0);
  const [textAreaContent, setTextAreaContent] = useState(() => {
    return getFromLocalStorage("notepad_textarea_content") || "";
  });

  function handleTextAreaChange(
    event:
      | ChangeEvent<HTMLTextAreaElement>
      | KeyboardEvent<HTMLTextAreaElement>
      | MouseEvent<HTMLTextAreaElement>
  ) {
    setLineNum(getLineNumber(event.target as HTMLTextAreaElement));
    setColumnIndex(getColumnIndex(event.target as HTMLTextAreaElement));
    setTextAreaContent((event.target as HTMLTextAreaElement).value);
    setToLocalStorage(
      "notepad_textarea_content",
      event.target as HTMLTextAreaElement
    );
  }

  useEffect(() => {
    let textAreaElem: HTMLTextAreaElement = document.getElementById(
      "text-area"
    ) as HTMLTextAreaElement;
    enableTabIndentation(textAreaElem);

    new UserPreference().setFontSettings();
  }, []);

  return (
    <>
      <textarea
        name="text-area"
        id="text-area"
        autoFocus
        spellCheck="false"
        value={textAreaContent}
        onKeyUp={handleTextAreaChange}
        onKeyDown={handleTextAreaChange}
        onKeyPress={handleTextAreaChange}
        onChange={handleTextAreaChange}
        onFocus={handleTextAreaChange}
        onMouseUp={handleTextAreaChange}
        data-testid="text-area"
      />
      <div className="details-tab">
        <div className="line-number">
          <p data-testid="line-index">
            Ln {linesNum}, Col {columnIndex}
          </p>
        </div>
        <div className="extra-details"></div>
      </div>
    </>
  );
}
Example #24
Source File: Input.tsx    From avalon.ist with MIT License 5 votes vote down vote up
tabComplete = (event: KeyboardEvent<HTMLInputElement>) => {
    // Only tab complete if we have stuff to complete on and we are at the end of the input.
    if (
      event.key === 'Tab' &&
      event.currentTarget &&
      this.props.autoComplete.length > 0 &&
      event.currentTarget.selectionStart === this.state.content.length
    ) {
      event.preventDefault();
      // Get the word being completed.
      const t = event.currentTarget;
      let start = t.value.lastIndexOf(' ');
      // If no space, then start at the beginning, and if there is a space, skip it...
      start = start === -1 ? 0 : start + 1;
      // If we are already tabbing, get the word we were tabbing on since the
      // content will have been auto-completed already. Otherwise, fetch it.
      let word = this.state.tabbing ? this.state.autoCompleteWord : '';
      if (word.length === 0) {
        word = t.value.substring(start).toLowerCase();
      }
      const matches = this.props.autoComplete.filter((player) =>
        player.toLowerCase().startsWith(word)
      );
      // No matches...bail.
      if (matches.length === 0) {
        this.setState({ tabbing: true });
        return;
      }
      // Find the index of the last item, if there is no past item, it will return -1.
      // However, we increment that to 0 below, so it will return the first result.
      const autoCompleteIndex = matches.indexOf(this.state.lastAutoCompleteWord);
      const newIndex = (autoCompleteIndex + 1) % matches.length;
      // Perform the completion and save the tab completion state.
      const content = t.value.substring(0, start) + matches[newIndex];
      this.setState({
        content: content,
        autoCompleteWord: word,
        lastAutoCompleteWord: matches[newIndex],
        tabbing: true,
      });
    } else if (this.state.tabbing) {
      // Once we stop tabbing, wipe the state so we don't taint future tabs.
      this.setState({
        autoCompleteWord: '',
        lastAutoCompleteWord: '',
        tabbing: false,
      });
    }
  };
Example #25
Source File: CurrencySearch.tsx    From pancakeswap-testnet with GNU General Public License v3.0 4 votes vote down vote up
export function CurrencySearch({
  selectedCurrency,
  onCurrencySelect,
  otherSelectedCurrency,
  showCommonBases,
  onDismiss,
  isOpen,
  onChangeList,
}: CurrencySearchProps) {
  const { t } = useTranslation()
  const { chainId } = useActiveWeb3React()
  const theme = useContext(ThemeContext)

  const fixedList = useRef<FixedSizeList>()
  const [searchQuery, setSearchQuery] = useState<string>('')
  const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
  const allTokens = useAllTokens()

  // if they input an address, use it
  const isAddressSearch = isAddress(searchQuery)
  const searchToken = useToken(searchQuery)

  const showETH: boolean = useMemo(() => {
    const s = searchQuery.toLowerCase().trim()
    return s === '' || s === 'b' || s === 'bn' || s === 'bnb'
  }, [searchQuery])

  const tokenComparator = useTokenComparator(invertSearchOrder)

  const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>((state) => state.user.audioPlay)

  const filteredTokens: Token[] = useMemo(() => {
    if (isAddressSearch) return searchToken ? [searchToken] : []
    return filterTokens(Object.values(allTokens), searchQuery)
  }, [isAddressSearch, searchToken, allTokens, searchQuery])

  const filteredSortedTokens: Token[] = useMemo(() => {
    if (searchToken) return [searchToken]
    const sorted = filteredTokens.sort(tokenComparator)
    const symbolMatch = searchQuery
      .toLowerCase()
      .split(/\s+/)
      .filter((s) => s.length > 0)
    if (symbolMatch.length > 1) return sorted

    return [
      ...(searchToken ? [searchToken] : []),
      // sort any exact symbol matches first
      ...sorted.filter((token) => token.symbol?.toLowerCase() === symbolMatch[0]),
      ...sorted.filter((token) => token.symbol?.toLowerCase() !== symbolMatch[0]),
    ]
  }, [filteredTokens, searchQuery, searchToken, tokenComparator])

  const handleCurrencySelect = useCallback(
    (currency: Currency) => {
      onCurrencySelect(currency)
      onDismiss()
      if (audioPlay) {
        const audio = document.getElementById('bgMusic') as HTMLAudioElement
        if (audio) {
          audio.play()
        }
      }
    },
    [onDismiss, onCurrencySelect, audioPlay]
  )

  // clear the input on open
  useEffect(() => {
    if (isOpen) setSearchQuery('')
  }, [isOpen])

  // manage focus on modal show
  const inputRef = useRef<HTMLInputElement>()
  const handleInput = useCallback((event) => {
    const input = event.target.value
    const checksummedInput = isAddress(input)
    setSearchQuery(checksummedInput || input)
    fixedList.current?.scrollTo(0)
  }, [])

  const handleEnter = useCallback(
    (e: KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        const s = searchQuery.toLowerCase().trim()
        if (s === 'bnb') {
          handleCurrencySelect(ETHER)
        } else if (filteredSortedTokens.length > 0) {
          if (
            filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
            filteredSortedTokens.length === 1
          ) {
            handleCurrencySelect(filteredSortedTokens[0])
          }
        }
      }
    },
    [filteredSortedTokens, handleCurrencySelect, searchQuery]
  )

  const selectedListInfo = useSelectedListInfo()
  const TranslateString = useI18n()
  return (
    <Column style={{ width: '100%', flex: '1 1' }}>
      <PaddedColumn gap="14px">
        <RowBetween>
          <Text>
            {TranslateString(82, 'Select a token')}
            <QuestionHelper
              text={TranslateString(
                128,
                'Find a token by searching for its name or symbol or by pasting its address below.'
              )}
            />
          </Text>
          <CloseIcon onClick={onDismiss} />
        </RowBetween>
        <SearchInput
          type="text"
          id="token-search-input"
          placeholder={t('tokenSearchPlaceholder')}
          value={searchQuery}
          ref={inputRef as RefObject<HTMLInputElement>}
          onChange={handleInput}
          onKeyDown={handleEnter}
        />
        {showCommonBases && (
          <CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
        )}
        <RowBetween>
          <Text fontSize="14px">{TranslateString(126, 'Token name')}</Text>
          <SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder((iso) => !iso)} />
        </RowBetween>
      </PaddedColumn>

      <Separator />

      <div style={{ flex: '1' }}>
        <AutoSizer disableWidth>
          {({ height }) => (
            <CurrencyList
              height={height}
              showETH={showETH}
              currencies={filteredSortedTokens}
              onCurrencySelect={handleCurrencySelect}
              otherCurrency={otherSelectedCurrency}
              selectedCurrency={selectedCurrency}
              fixedListRef={fixedList}
            />
          )}
        </AutoSizer>
      </div>

      {null && (
        <>
          <Separator />
          <Card>
            <RowBetween>
              {selectedListInfo.current ? (
                <Row>
                  {selectedListInfo.current.logoURI ? (
                    <ListLogo
                      style={{ marginRight: 12 }}
                      logoURI={selectedListInfo.current.logoURI}
                      alt={`${selectedListInfo.current.name} list logo`}
                    />
                  ) : null}
                  <Text id="currency-search-selected-list-name">{selectedListInfo.current.name}</Text>
                </Row>
              ) : null}
              <LinkStyledButton
                style={{ fontWeight: 500, color: theme.colors.textSubtle, fontSize: 16 }}
                onClick={onChangeList}
                id="currency-search-change-list-button"
              >
                {selectedListInfo.current ? TranslateString(180, 'Change') : TranslateString(1152, 'Select a list')}
              </LinkStyledButton>
            </RowBetween>
          </Card>
        </>
      )}
    </Column>
  )
}
Example #26
Source File: index.tsx    From react-terminal-ui with MIT License 4 votes vote down vote up
Terminal = ({name, prompt, colorMode, lineData, onInput, startingInputValue = ""}: Props) => {
  const [currentLineInput, setCurrentLineInput] = useState('');

  const lastLineRef = useRef<null | HTMLElement>(null)

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

  const handleEnter = (event: KeyboardEvent<HTMLInputElement>) => {
    if (onInput != null && event.key === 'Enter') {
      onInput(currentLineInput);
      setCurrentLineInput('');
    }
  }

  useEffect(() => {
    setCurrentLineInput(startingInputValue.trim());
  }, [startingInputValue]);

  // An effect that handles scrolling into view the last line of terminal input or output
  const performScrolldown = useRef(false);
  useEffect(() => {
    if (performScrolldown.current) { // skip scrolldown when the component first loads
      setTimeout(() => lastLineRef?.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }), 500);
    }
    performScrolldown.current = true;
  }, [lineData.length]);

  // We use a hidden input to capture terminal input; make sure the hidden input is focused when clicking anywhere on the terminal
  useEffect(() => {
    if (onInput == null) {
      return;
    }
    // keep reference to listeners so we can perform cleanup
    const elListeners: { terminalEl: Element; listener: EventListenerOrEventListenerObject }[] = [];
    for (const terminalEl of document.getElementsByClassName('react-terminal-wrapper')) {
      const listener = () => (terminalEl?.querySelector('.terminal-hidden-input') as HTMLElement)?.focus();
      terminalEl?.addEventListener('click', listener);
      elListeners.push({ terminalEl, listener });
    }
    return function cleanup () {
      elListeners.forEach(elListener => {
        elListener.terminalEl.removeEventListener('click', elListener.listener);
      });
    }
  }, [onInput]);

  const renderedLineData = lineData.map((ld, i) => {
    const classes = ['react-terminal-line'];
    if (ld.type === LineType.Input) {
      classes.push('react-terminal-input');
    }
    // `lastLineRef` is used to ensure the terminal scrolls into view to the last line; make sure to add the ref to the last
    // redendered line if input prompt is not shown, i.e. `onInput` is not declared; see 'render prompt' below
    if (lineData.length === i + 1 && onInput == null) {
      return (
        <span className={ classes.join(' ') } key={ i } ref={ lastLineRef }>{ ld.value }</span>
      );
    } else {
      return (
        <span className={ classes.join(' ') } key={ i }>{ ld.value }</span>
      );
    }
  });

  // render prompt
  if (onInput != null) {
    renderedLineData.push(
      <span className="react-terminal-line react-terminal-input react-terminal-active-input" data-terminal-prompt={ prompt || '$' } key={ lineData.length } ref={ lastLineRef }>{ currentLineInput }</span>,
    );
  }

  const classes = ['react-terminal-wrapper'];
  if (colorMode === ColorMode.Light) {
    classes.push('react-terminal-light');
  }
  return (
    <div className={ classes.join(' ') } data-terminal-name={ name }>
      <div className="react-terminal">
        { renderedLineData }
      </div>
      <input className="terminal-hidden-input" placeholder="Terminal Hidden Input" value={ currentLineInput } autoFocus={ onInput != null } onChange={ updateCurrentLineInput } onKeyDown={ handleEnter } />
    </div>
  );
}
Example #27
Source File: TorrentList.tsx    From flood with GNU General Public License v3.0 4 votes vote down vote up
TorrentList: FC = observer(() => {
  const listHeaderRef = useRef<HTMLDivElement>(null);
  const listViewportRef = useRef<FixedSizeList>(null);
  const listViewportOuterRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const dispose = reaction(
      () => TorrentFilterStore.filterTrigger,
      () => {
        if (listViewportRef.current != null) {
          listViewportRef.current.scrollTo(0);
        }
      },
    );

    return dispose;
  }, []);

  useEvent('keydown', (e: KeyboardEvent) => {
    const {ctrlKey, key, metaKey, repeat, target} = e;

    const tagName = (target as HTMLElement)?.tagName.toUpperCase();
    if (tagName === 'INPUT' || tagName === 'TEXTAREA') {
      return;
    }

    if (repeat) {
      return;
    }

    if ((metaKey || ctrlKey) && key === 'a') {
      e.preventDefault();
      TorrentStore.selectAllTorrents();
    }
  });

  const torrents = TorrentStore.filteredTorrents;
  const {torrentListViewSize = 'condensed'} = SettingStore.floodSettings;

  const isCondensed = torrentListViewSize === 'condensed';
  const isListEmpty = torrents == null || torrents.length === 0;

  let content: ReactNode = null;
  let torrentListHeading: ReactNode = null;
  if (!ClientStatusStore.isConnected) {
    content = (
      <div className="torrents__alert__wrapper">
        <div className="torrents__alert">
          <Trans id="torrents.list.cannot.connect" />
        </div>
      </div>
    );
  } else if (isListEmpty || torrents == null) {
    content = (
      <div className="torrents__alert__wrapper">
        <div className="torrents__alert">
          <Trans id="torrents.list.no.torrents" />
        </div>
        {TorrentFilterStore.isFilterActive ? (
          <div className="torrents__alert__action">
            <Button
              onClick={() => {
                TorrentFilterStore.clearAllFilters();
              }}
              priority="tertiary"
            >
              <Trans id="torrents.list.clear.filters" />
            </Button>
          </div>
        ) : null}
      </div>
    );
  } else {
    if (isCondensed) {
      torrentListHeading = (
        <TableHeading
          onCellFocus={() => {
            if (listViewportOuterRef.current != null && listHeaderRef.current != null) {
              listViewportOuterRef.current.scrollLeft = listHeaderRef.current.scrollLeft;
            }
          }}
          onCellClick={(property: TorrentListColumn) => {
            const currentSort = SettingStore.floodSettings.sortTorrents;

            let nextDirection = SortDirections[property] ?? 'asc';

            if (currentSort.property === property) {
              nextDirection = currentSort.direction === 'asc' ? 'desc' : 'asc';
            }

            const sortBy = {
              property,
              direction: nextDirection,
            };

            SettingActions.saveSetting('sortTorrents', sortBy);
          }}
          onWidthsChange={(column: TorrentListColumn, width: number) => {
            const {torrentListColumnWidths = defaultFloodSettings.torrentListColumnWidths} = SettingStore.floodSettings;

            SettingActions.saveSetting('torrentListColumnWidths', {
              ...torrentListColumnWidths,
              [column]: width,
            });
          }}
          ref={listHeaderRef}
        />
      );
    }

    // itemSize must sync with styles &--is-condensed and &--is-expanded
    content = (
      <ListViewport
        className="torrent__list__viewport"
        itemCount={torrents.length}
        itemKey={(index) => TorrentStore.filteredTorrents[index].hash}
        itemRenderer={TorrentListRowRenderer}
        itemSize={isCondensed ? 30 : 70}
        ref={listViewportRef}
        outerRef={(ref) => {
          const viewportDiv = ref;
          if (viewportDiv != null && viewportDiv.onscroll == null) {
            viewportDiv.onscroll = () => {
              if (listHeaderRef.current != null) {
                listHeaderRef.current.scrollLeft = viewportDiv.scrollLeft;
              }
            };
          }
          listViewportOuterRef.current = viewportDiv;
        }}
      />
    );
  }

  return (
    <TorrentListDropzone>
      <div className="torrent__list__wrapper" role="table">
        <ContextMenuMountPoint id="torrent-list-item" />
        {torrentListHeading}
        {content}
      </div>
      <div className="dropzone__overlay">
        <div className="dropzone__copy">
          <div className="dropzone__icon">
            <Files />
          </div>
          <Trans id="torrents.list.drop" />
        </div>
      </div>
    </TorrentListDropzone>
  );
})
Example #28
Source File: AuthForm.tsx    From ksana.in with Apache License 2.0 4 votes vote down vote up
export function AuthForm({ state }: IAuthFormProps) {
  const router = useRouter()
  const { showAlert, hideAlert } = useAlertContext()

  const bgBox = useColorModeValue('white', 'gray.700')
  const [internalState, setInternalState] = useState<any>(state)
  const [isLogin, setIsLogin] = useState<any>(state === 'login')

  const [loading, setLoading] = useState<boolean>(false)
  const [errorForm, setErrorForm] = useState<string>('')
  const [email, setEmail] = useState<string>('')
  const [password, setPassword] = useState<string>('')

  const toggleState = () => {
    if (internalState === 'login') {
      setInternalState('register')
      setIsLogin(false)
    } else {
      setInternalState('login')
      setIsLogin(true)
    }
  }

  const handleChangeEmail = (e: ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value
    setEmail(value)
  }

  const handleChangePassword = (e: ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value
    setPassword(value)
  }

  const checkIsEmpty = () => {
    if (email === '' || password === '') {
      setErrorForm('Email dan password tidak boleh dikosongkan.')
      return true
    }

    setErrorForm('')
    return false
  }

  const handleSubmit = async () => {
    setLoading(true)

    const isEmpty = checkIsEmpty()

    if (!isEmpty) {
      if (isLogin) {
        await handleLogin()
      } else {
        await handleRegister()
      }
    }

    setLoading(false)
  }

  const handleLoginGoogle = async () => {
    setLoading(true)
    await loginWithGoogle()
    setLoading(false)
  }

  const handleLoginGithub = async () => {
    setLoading(true)
    await loginWithGithub()
    setLoading(false)
  }

  const handleLoginTwitter = async () => {
    setLoading(true)
    await loginWithTwitter()
    setLoading(false)
  }

  const processResponse = async ({ session, error, stateType = 'login' }: IProcessResponse) => {
    if (error) {
      setErrorForm(error.message)
      return false
    }

    if (session && !error) {
      if (stateType === 'login') {
        // only set for the login flow
        await setSessionToServer(EVENT_SIGN_IN, session)
      }

      showAlert({
        title: `${stateType === 'login' ? 'Login' : 'Register'} success`,
        message: `${
          stateType === 'login'
            ? 'Selamat datang kembali!'
            : 'Terima kasih telah mendaftar. Silahkan melakukan verifikasi dengan mengklik tautan yang kami kirimkan melalui email.'
        }`,
        onClose: () => {
          hideAlert()

          if (stateType === 'login') {
            setTimeout(() => {
              // trigger hard redirect to dashboard page
              // TODO: mutate SWR to reload the user data
              window.location.assign(dashboard)
            }, 500)
          } else {
            router.push('/')
          }
        }
      })
    }
  }

  const handleLogin = async () => {
    const { session, error } = await login({
      email: email,
      password: password
    })

    processResponse({ session, error, stateType: 'login' })
  }

  const handleRegister = async () => {
    const { session, error } = await register({
      email: email,
      password: password
    })

    processResponse({ session, error, stateType: 'register' })

    if (!error) {
      showAlert({
        title: 'Registrasi Berhasil!',
        message:
          'Terima kasih telah mendaftar. Silahkan melakukan verifikasi dengan mengklik tautan yang kami kirimkan melalui email.'
      })
    } else {
      showAlert({
        title: 'Registrasi Gagal!',
        message: 'Silahkan ulangi proses registrasi!'
      })
    }
  }

  const handleKeyPress = (e: KeyboardEvent) => {
    if (e.code === '13') {
      handleSubmit()
    }
  }

  return (
    <Stack spacing={8} mx={'auto'} mt="20" maxW={'lg'} py={12} px={6}>
      <Stack align={'center'}>
        <Heading
          fontWeight={700}
          fontSize={{ base: '3xl', sm: '4xl', md: '5xl' }}
          lineHeight={'110%'}
          color="orange.400"
        >
          {isLogin ? 'Masuk ke akunmu' : 'Daftarkan akun baru'}
        </Heading>
      </Stack>
      <Box rounded={'lg'} bg={bgBox} boxShadow={'lg'} p={8}>
        <VStack
          direction="row"
          align={'center'}
          justify={'center'}
          borderBottom="1px"
          borderColor="gray.200"
          py="4"
        >
          {isEnableGoogleLogin && (
            <Button
              isLoading={loading}
              loadingText="Memproses"
              variant={'outline'}
              w="full"
              onClick={handleLoginGoogle}
              leftIcon={<FcGoogle />}
            >
              {isLogin ? 'Masuk dengan Google' : 'Daftar dengan Google'}
            </Button>
          )}

          {isEnableTwitterLogin && (
            <Button
              isLoading={loading}
              loadingText="Memproses"
              variant={'outline'}
              w="full"
              onClick={handleLoginTwitter}
              leftIcon={<SiTwitter fill="#1DA1F2" />}
            >
              {isLogin ? 'Masuk dengan Twitter' : 'Daftar dengan Twitter'}
            </Button>
          )}

          {isEnableGithubLogin && (
            <Button
              isLoading={loading}
              loadingText="Memproses"
              variant={'outline'}
              w="full"
              onClick={handleLoginGithub}
              leftIcon={<SiGithub />}
            >
              {isLogin ? 'Masuk dengan Github' : 'Daftar dengan Github'}
            </Button>
          )}
        </VStack>

        <Stack spacing={4} mt="4">
          <FormControl id="email" isRequired>
            <FormLabel>Email</FormLabel>
            <Input
              isInvalid={Boolean(errorForm)}
              type="email"
              name="email"
              value={email}
              onChange={handleChangeEmail}
              onKeyPress={handleKeyPress}
              autoComplete="username"
            />
          </FormControl>

          <FormControl id="password" isRequired>
            <FormLabel>Password</FormLabel>
            <Input
              isInvalid={Boolean(errorForm)}
              type="password"
              name="password"
              value={password}
              onChange={handleChangePassword}
              onKeyPress={handleKeyPress}
              autoComplete={isLogin ? 'current-password' : 'new-password'}
            />
          </FormControl>

          {errorForm && (
            <Text color="red.300" fontSize="xs">
              Galat: {errorForm}
            </Text>
          )}

          <Stack spacing={10}>
            {isLogin ? (
              <Stack
                direction={{ base: 'column', sm: 'row' }}
                align={'start'}
                justify={'space-between'}
              >
                <Button variant="link" as={Link} color={'orange.400'} href={forgetPasword}>
                  Lupa password?
                </Button>
              </Stack>
            ) : null}

            <Button
              isLoading={loading}
              loadingText="Memproses"
              w="full"
              bg="orange.400"
              _hover={{
                bg: 'orange.500'
              }}
              color="white"
              onClick={handleSubmit}
            >
              {isLogin ? 'Masuk' : 'Daftar Sekarang'}
            </Button>
          </Stack>

          {isLogin ? (
            <Stack direction="row" align={'center'} justify={'center'}>
              <Text>Belum punya akun? </Text>
              <Button variant="link" as={Link} color={'orange.400'} onClick={toggleState}>
                Daftar sekarang
              </Button>
            </Stack>
          ) : (
            <Stack direction="row" align={'center'} justify={'center'}>
              <Text>Sudah punya akun? </Text>
              <Button variant="link" as={Link} color={'orange.400'} onClick={toggleState}>
                Masuk
              </Button>
            </Stack>
          )}
        </Stack>
      </Box>
    </Stack>
  )
}
Example #29
Source File: ClueList.tsx    From crosshare with GNU Affero General Public License v3.0 4 votes vote down vote up
ClueListItem = memo(function ClueListItem({
  isActive,
  isCross,
  ...props
}: ClueListItemProps) {
  const ref = useRef<HTMLLIElement>(null);
  if (ref.current && props.listRef.current) {
    if (
      (isActive && !props.wasEntryClick) ||
      (props.scrollToCross && isCross)
    ) {
      props.listRef.current.scrollTop =
        ref.current.offsetTop - props.listRef.current.offsetTop;
    }
  }
  function click(e: MouseEvent | KeyboardEvent) {
    e.preventDefault();
    if (isActive) {
      props.dispatch({ type: 'CHANGEDIRECTION' });
      return;
    }
    const ca: ClickedEntryAction = {
      type: 'CLICKEDENTRY',
      entryIndex: props.entry.index,
    };
    props.dispatch(ca);
  }
  return (
    <li
      css={{
        display: isActive || props.showEntry ? 'list-item' : 'none',
        [SMALL_AND_UP]: {
          display: 'list-item',
        },
        backgroundColor: isActive
          ? 'var(--lighter)'
          : props.isRefed
            ? 'var(--secondary)'
            : 'var(--bg)',
        listStyleType: 'none',
        cursor: 'pointer',
        '&:hover': {
          backgroundColor: isActive
            ? 'var(--lighter)'
            : props.isRefed
              ? 'var(--secondary-hover)'
              : 'var(--bg-hover)',
        },
        width: '100%',
      }}
      ref={ref}
      key={props.entry.index}
    >
      <div
        css={{
          outline: 'none',
          width: '100%',
          paddingLeft: '0.4em',
        }}
        role="button"
        tabIndex={0}
        onClick={click}
        onKeyPress={click}
      >
        <div
          css={{
            width: '100%',
            display: 'flex',
            flexDirection: 'row',
            flexWrap: 'nowrap',
            alignItems: 'center',
            borderLeft: isCross
              ? '0.6em solid var(--lighter)'
              : '0.6em solid transparent',
            padding: '0.5em 0.5em 0.5em 0',
          }}
        >
          <div
            css={{
              display: props.showEntry ? 'block' : 'none',
              [SMALL_AND_UP]: {
                display: 'block',
              },
              flexShrink: 0,
              width: '2.5em',
              height: '100%',
              fontWeight: 'bold',
              textAlign: 'right',
              paddingRight: '0.5em',
            }}
          >
            {props.entry.labelNumber}
            <span
              css={{
                [SMALL_AND_UP]: { display: 'none' },
              }}
            >
              {props.entry.direction === Direction.Across ? 'A' : 'D'}
            </span>
          </div>
          <div
            css={{
              flex: '1 1 auto',
              height: '100%',
              color: props.conceal
                ? 'transparent'
                : props.entry.completedWord && props.dimCompleted
                  ? 'var(--completed-clue)'
                  : 'var(--text)',
              textShadow: props.conceal ? '0 0 1em var(--conceal-text)' : '',
            }}
          >
            {props.allEntries && props.refPositions ? (
              <div>
                <ClueText
                  refPositions={props.refPositions}
                  entryIndex={props.entry.index}
                  allEntries={props.allEntries}
                  grid={props.grid}
                  downsOnly={props.downsOnly}
                />
              </div>
            ) : (
              <div>{getClueText(props.entry)}</div>
            )}
            {props.showEntry ? (
              <div>
                {props.entry.cells.map((a) => {
                  const isActiveCell =
                    props.active &&
                    a.row === props.active.row &&
                    a.col === props.active.col;
                  return (
                    <span
                      key={a.col + '-' + a.row}
                      css={{
                        display: 'inline-block',
                        textAlign: 'center',
                        fontWeight: 'bold',
                        minWidth: '1em',
                        border: isActiveCell
                          ? props.isEnteringRebus
                            ? '1px solid var(--primary)'
                            : '1px solid var(--black)'
                          : '1px solid transparent',
                      }}
                    >
                      {props.isEnteringRebus && isActiveCell
                        ? props.rebusValue || '|'
                        : valAt(props.grid, a).trim() || '-'}
                    </span>
                  );
                })}
              </div>
            ) : (
              ''
            )}
          </div>
        </div>
      </div>
    </li>
  );
})