@material-ui/core#InputBase TypeScript Examples

The following examples show how to use @material-ui/core#InputBase. 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: SearchBar.tsx    From log4brains with Apache License 2.0 6 votes vote down vote up
export function SearchBar(props: SearchBarProps) {
  const { InputProps, InputLabelProps, open, onClear, ...params } = props;
  const classes = useStyles(props);
  return (
    <InputBase
      placeholder="Search..."
      classes={{
        root: classes.inputRoot,
        input: classes.inputInput
      }}
      startAdornment={
        <InputAdornment position="start">
          <SearchIcon />
        </InputAdornment>
      }
      endAdornment={
        // eslint-disable-next-line react/destructuring-assignment
        <Fade in={open && props.inputProps.value !== ""}>
          <InputAdornment position="end">
            <IconButton
              onClick={(event) => onClear(event)}
              size="small"
              title="Clear"
              className={classes.clearIcon}
            >
              <ClearIcon />
            </IconButton>
          </InputAdornment>
        </Fade>
      }
      ref={InputProps.ref}
      {...params}
    />
  );
}
Example #2
Source File: actionbar-search-field.tsx    From mtcute with GNU Lesser General Public License v3.0 6 votes vote down vote up
export function ActionBarSearchField(
    params: Partial<InputBaseProps> & { inputRef?: React.Ref<any> }
): React.ReactElement {
    const classes = useStyles()

    return (
        <div className={classes.search}>
            <div className={classes.searchIcon}>
                <SearchIcon />
            </div>
            <InputBase
                ref={params.inputRef}
                placeholder="Search…"
                classes={{
                    root: classes.inputRoot,
                    input: classes.inputInput,
                }}
                inputProps={{ 'aria-label': 'search' }}
                {...params}
            />
        </div>
    )
}
Example #3
Source File: HubSortDropdown.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
HubSortDropdown = ({
  selectedSortOption,
  sortOptions,
  handleSortOption,
}: Props) => {
  return (
    <FormControl>
      <SortLabel shrink>Sort</SortLabel>
      <SortSelect
        value={selectedSortOption}
        onChange={handleSortOption}
        input={<InputBase />}
        data-name={`selectedHubSortDropdown-${selectedSortOption.replaceAll(
          " ",
          "_"
        )}`}
      >
        {sortOptions.map((sortOption) => (
          <MenuItem
            data-name={`sortOptionHubSortDropdown-${sortOption.replaceAll(
              " ",
              "_"
            )}`}
            value={sortOption}
          >
            {sortOption}
          </MenuItem>
        ))}
      </SortSelect>
    </FormControl>
  )
}
Example #4
Source File: index.tsx    From GroupChat with MIT License 6 votes vote down vote up
Search: React.FC<Props> = props => {
  const [searchValue, setSearchValue] = useState('');

  const searchHandler = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    setSearchValue(e.target.value);
    const allGroups = props.groups;
    const filteredGroups: Group[] = allGroups.filter(grp =>
      grp.title.toLowerCase().includes(e.target.value.toLowerCase())
    );
    props.update(filteredGroups);
  };

  return (
    <div className={styles.container}>
      <IconButton className={styles.iconButton}>
        <SearchIcon className={styles.search} />
      </IconButton>
      <InputBase
        className={styles.input}
        placeholder="Search..."
        onChange={e => searchHandler(e)}
        value={searchValue}
      />
    </div>
  );
}
Example #5
Source File: SenderFilterInput.tsx    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
export default function SenderFilterInput({ handleChange }: Props) {
  const classes = useStyles();
  return (
    <div className={classes.box}>
      <SelectLabel>Sender</SelectLabel>
      <Box display="flex" alignItems="center">
        <AccountIdenticon />
        <InputBase
          placeholder="select address or start typing"
          onChange={handleChange}
          fullWidth
          className={classes.input}
        />
        <ArrowDropUp color="primary" />
      </Box>
    </div>
  );
}
Example #6
Source File: DatePicker.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
BootstrapInput = withStyles((theme: Theme) =>
  createStyles({
    root: {
      margin: `${theme.spacing(1)} 0px`,
      maxWidth: 300,
      'label + &': {
        marginTop: theme.spacing(3),
      },
    },
    input: {
      borderRadius: 4,
      position: 'relative',
      backgroundColor: theme.palette.background.paper,
      border: '1px solid #ced4da',
      fontSize: 16,
      padding: '10px 26px 10px 12px',
      transition: theme.transitions.create(['border-color', 'box-shadow']),
      fontFamily: 'Helvetica Neue',
      height: 25,
      '&:focus': {
        background: theme.palette.background.paper,
        borderRadius: 4,
      },
    },
  }),
)(InputBase)
Example #7
Source File: ExpandingSearchbar.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
function ExpandingSearchbar({ onSearch, value, onChange }: Props) {
  const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
    if (event.key === "Enter") {
      onSearch && onSearch(value)
    }
  }
  const clearSearch = () => {
    onSearch && onSearch("")
  }

  const SearchBar = styled.div`
    display: flex;
    background-color: ${(props) => props.theme.palette.grey[100]};
    border-radius: 2px;
  `
  return (
    <SearchBar>
      <IconButton type="submit" onClick={() => onSearch && onSearch(value)}>
        <SearchIcon />
      </IconButton>
      <InputBase
        autoFocus={true}
        onChange={(e) => onChange(e.target.value)}
        defaultValue={value}
        placeholder="Search"
        onKeyPress={handleKeyPress}
      />
      {value && (
        <IconButton onClick={clearSearch}>
          <CancelIcon />
        </IconButton>
      )}
    </SearchBar>
  )
}
Example #8
Source File: ReceiverInput.tsx    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
// TODO: To refactor state management for this component #160

function ReceiverInput() {
  const classes = useStyles();
  const { onReceiverChange } = useReceiver();
  const { unformattedReceiverAddress, formatFound, showBalance, transactionToBeExecuted } = useTransactionContext();
  const { api, address } = useApiBalance(unformattedReceiverAddress, formatFound, false);
  const state = useBalance(api, address, true);

  const addressInput = unformattedReceiverAddress || '';
  return (
    <div className={classes.accountMain}>
      <SelectLabel>Receiver</SelectLabel>
      <Box display="flex" alignItems="center">
        <AccountIdenticon address={addressInput} formatFound={formatFound} />
        <InputBase
          id="test-receiver-input"
          className={classes.address}
          fullWidth
          onChange={onReceiverChange}
          autoComplete="off"
          value={addressInput}
          placeholder="Recipient address"
          disabled={transactionToBeExecuted}
        />
        {showBalance && state && <Balance balance={state.formattedBalance} id="test-receiver-balance" />}
      </Box>
    </div>
  );
}
Example #9
Source File: DashboardHeaderPageButton.tsx    From neodash with Apache License 2.0 5 votes vote down vote up
NeoPageButton = ({ title, disabled = false, selected = false, onSelect, onRemove, onTitleUpdate }) => {

    // TODO - debounce page title update
    const [modalOpen, setModalOpen] = React.useState(false);

    const handleClose = () => {
        setModalOpen(false);
    };

    const [titleText, setTitleText] = React.useState(title);
    useEffect(() => {
        // Reset text to the dashboard state when the page gets reorganized.
        if (titleText !== title) {
            setTitleText(title);
        }
    }, [title])

    const content = (
        <>
            <Grid style={{ height: "100%" }}
                onClick={onSelect}
                container spacing={1} alignItems="flex-end">
                <Grid item key={1} style={{ width: "100%" }}>
                    <InputBase
                        value={titleText}
                        onChange={(event) => {
                            if (disabled) {
                                return;
                            }
                            onTitleUpdate(event);
                            setTitleText(event.target.value);
                        }}
                        onFocus={(e) => {
                            if (disabled) {
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        }}
                        readOnly={disabled}
                        inputProps={{ style: { textTransform: 'none', cursor: 'pointer', fontWeight: 'normal' } }}
                        style={{ height: "36px", width: "100%", paddingLeft: "10px", color: selected ? 'black' : '#888', textAlign: "center", textTransform: "uppercase" }}
                        placeholder="Page name..."
                    />
                </Grid>
            </Grid>
            <div style={{position: "absolute", top: 5, right: 0, paddingRight: 3, background: selected ? "white" : "transparent"}}>
                {(selected && !disabled) ? <IconButton size="medium" style={{ padding: "5px", color: "white" }} aria-label="move left" onClick={() => setModalOpen(true)}>
                    <CloseIcon color="disabled" />
                </IconButton> : <IconButton size="medium" style={{ opacity: 0, padding: "5px", color: "white" }} aria-label="move left"
                    onClick={(event) => null}>
                    <CloseIcon color="disabled" />
                </IconButton>}
            </div>
            <NeoDeletePageModal modalOpen={modalOpen} onRemove={onRemove} handleClose={handleClose}></NeoDeletePageModal>
        </>
    );
    return content;
}
Example #10
Source File: HubNavigationBar.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
export default function HubNavigationBar({
  handleChange,
  handleSearch,
  tabNumber,
}: Props) {
  let [searchString, setSearchString] = useState("")

  const NavItems = ["Hub Explore", "Hub List", "My Images", "My Favourites"]

  const SearchBar = styled.div`
    background-color: ${(props) => props.theme.palette.grey[100]};
    border-radius: 2px;
    cursor: pointer;
    min-width: 350px;
    display: flex;
  `

  const HubTabs = styled(Tabs)`
    flex-grow: 1;
  `

  const HubSearchIcon = styled(SearchIcon)`
    margin: 11px;
    margin-left: 20px;
  `

  const handleKeyPress = (event: KeyboardEvent<HTMLDivElement>) => {
    if (event.key === "Enter") handleSearch(searchString)
  }
  return (
    <AppBar elevation={0} position={"static"}>
      <Toolbar>
        <HubTabs
          value={tabNumber}
          onChange={handleChange}
          aria-label="simple tabs example"
          textColor="secondary"
          indicatorColor="secondary"
        >
          {NavItems.map((NavItem, idx) => (
            <Tab label={NavItem} {...a11yProps(idx)} />
          ))}
        </HubTabs>
        <SearchBar>
          <HubSearchIcon onClick={(e) => handleSearch(searchString)} />
          <InputBase
            onKeyPress={handleKeyPress}
            autoFocus={true} //todo this is a hack. It looses focus after setSearchString gets triggered
            value={searchString}
            onChange={(e) => setSearchString(e.target.value)}
            placeholder="Search"
            fullWidth={true}
          />
        </SearchBar>
      </Toolbar>
    </AppBar>
  )
}
Example #11
Source File: DashboardHeaderTitleBar.tsx    From neodash with Apache License 2.0 5 votes vote down vote up
NeoDashboardHeaderTitleBar = ({ dashboardTitle, downloadImageEnabled, onDownloadImage, open, setDashboardTitle, connection, editable, standalone, handleDrawerOpen, onConnectionModalOpen }) => {

    const [dashboardTitleText, setDashboardTitleText] = React.useState(dashboardTitle);
    const debouncedDashboardTitleUpdate = useCallback(
        debounce(setDashboardTitle, 250),
        [],
    );

    useEffect(() => {
        // Reset text to the dashboard state when the page gets reorganized.
        if (dashboardTitle !== dashboardTitleText) {
            setDashboardTitleText(dashboardTitle);
        }
    }, [dashboardTitle])


    const content = <Toolbar key={1} style={{ paddingRight: 24, minHeight: "64px", background: '#0B297D', zIndex: 1201 }}>
        {!standalone ? <IconButton
            edge="start"
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            style={
                (open) ? {
                    display: 'none',
                } : {
                    marginRight: 36,
                    marginLeft: -19,
                }
            }
        >
            <MenuIcon />
        </IconButton> : <></>}
        <InputBase
            id="center-aligned"
            style={{ textAlign: 'center', fontSize: "22px", flexGrow: 1, color: "white" }}
            placeholder="Dashboard Name..."
            fullWidth
            maxRows={4}
            value={dashboardTitleText}
            onChange={(event) => {
                if (editable) {
                    setDashboardTitleText(event.target.value);
                    debouncedDashboardTitleUpdate(event.target.value);
                }
            }}
        />
        {downloadImageEnabled ? <Tooltip title={"Download Dashboard as Image"}>
    <IconButton style={{background: "#ffffff22", padding: "3px", marginRight: "3px"}} onClick={(e) => onDownloadImage()}>
        <ImageIcon style={{ padding: 6, color: "#ffffffdd", width: "36px", height: "36px", fontSize: "1.3rem", zIndex: 5 }} fontSize="small">
        </ImageIcon>
    </IconButton>
</Tooltip> : <></>}

        <Tooltip title={connection.protocol + "://" + connection.url + ":" + connection.port} placement="left" aria-label="host">
            <IconButton style={{ background: "#ffffff22", padding: "3px" }} onClick={(e) => {
                if (!standalone) {
                    onConnectionModalOpen();
                }
            }}>
                <Badge badgeContent={""} >
                    <img style={{ width: "36px", height: "36px" }} src="neo4j-icon.png" />
                </Badge>
            </IconButton>
        </Tooltip>
    </Toolbar>;
    return content;
}
Example #12
Source File: DashboardPlaceholder.tsx    From neodash with Apache License 2.0 5 votes vote down vote up
NeoDashboardPlaceholder = ({connected}) => {
    const content = (
        <div style={{zIndex: -99}}>
            <AppBar position="absolute" style={{
                zIndex: "auto",
                boxShadow: "none",
                transition: "width 125ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
            }
            }>
                <Toolbar style={{ paddingRight: 24, minHeight: "64px", background: '#0B297D', zIndex: 1201 }}>
                    <IconButton
                        edge="start"
                        color="inherit"
                        aria-label="open drawer"
                        style={
                            (open) ? {
                                display: 'none',
                            } : {
                                marginRight: 36,
                                marginLeft: -19,
                            }
                        }
                    >
                        <MenuIcon />
                    </IconButton>
                    <InputBase
                        disabled
                        id="center-aligned"
                        label="placeholder"
                        style={{ textAlign: 'center', fontSize: "22px", flexGrow: 1, color: "white" }}
                        placeholder="Dashboard Name..."
                        fullWidth
                        maxRows={4}
                        value={"NeoDash ⚡"}
                    />

                </Toolbar>
                <Toolbar style={{ zIndex: 10, minHeight: "50px", paddingLeft: "0px", paddingRight: "0px", background: "white" }}>
                    <div style={{
                        width: '100%', zIndex: -112, height: "48px", overflowX: "hidden", overflowY: "auto", background: "rgba(240,240,240)",
                        boxShadow: "2px 1px 10px 0px rgb(0 0 0 / 12%)",
                        borderBottom: "1px solid lightgrey"
                    }}>

                    </div>
                </Toolbar>
            </AppBar>
            <div style={{
                position: "absolute",
                width: "100%",
                height: "100%"
            }}>
                <Typography variant="h2" color="textSecondary" style={{
                    position: "absolute", top: "50%", left: "50%",
                    transform: "translate(-50%, -50%)"
                }}>
                    {!connected ? <CircularProgress color="inherit" /> :<></>}
                </Typography>
            </div>
        </div>
    );
    return content;
}
Example #13
Source File: SearchInput.tsx    From baleen3 with Apache License 2.0 5 votes vote down vote up
Input = styled(InputBase)({
  flexGrow: 1,
})
Example #14
Source File: DashboardSearchControls.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
render() {
    return (
      <div className={this.props.classes.search}>
        <SearchIcon
          className={this.props.classes.searchIcon}
          color='inherit'
        />
        <InputBase
          className={this.props.classes.searchText}
          placeholder={this.props.placeholder || 'Search'}
          fullWidth
          value={this.state.searchText || ''}
          onChange={e => {
            const newSearchText = e.target.value === '' ? undefined : e.target.value;
            this.setState({ searchText: newSearchText });
            this.onSearchChanged(newSearchText);
          }}
        />
        {this.props.filters && (
          <>
            <IconButton
              className={this.props.classes.filterIcon}
              onClick={() => this.setState({ filtersOpen: !this.state.filtersOpen })}
              ref={this.filtersAnchorRef}
            >
              <FilterIcon />
            </IconButton>
            <ClosablePopper
              anchorType='ref'
              anchor={this.filtersAnchorRef}
              closeButtonPosition='disable'
              open={!!this.state.filtersOpen}
              onClose={() => this.setState({ filtersOpen: false })}
              placement='top'
              arrow
              clickAway
              // Allow DatePicker modal to overlap this one
              zIndex={this.props.theme.zIndex.modal}
            >
              {this.props.filters}
            </ClosablePopper>
          </>
        )}
      </div>
    );
  }
Example #15
Source File: CatalogKindHeader.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
/** @public */
export function CatalogKindHeader(props: CatalogKindHeaderProps) {
  const { initialFilter = 'component', allowedKinds } = props;
  const classes = useStyles();
  const catalogApi = useApi(catalogApiRef);
  const { value: allKinds } = useAsync(async () => {
    return await catalogApi
      .getEntityFacets({ facets: ['kind'] })
      .then(response => response.facets.kind?.map(f => f.value).sort() || []);
  });
  const {
    updateFilters,
    queryParameters: { kind: kindParameter },
  } = useEntityList();

  const queryParamKind = useMemo(
    () => [kindParameter].flat()[0]?.toLocaleLowerCase('en-US'),
    [kindParameter],
  );
  const [selectedKind, setSelectedKind] = useState(
    queryParamKind ?? initialFilter,
  );

  useEffect(() => {
    updateFilters({
      kind: selectedKind ? new EntityKindFilter(selectedKind) : undefined,
    });
  }, [selectedKind, updateFilters]);

  // Set selected Kind on query parameter updates; this happens at initial page load and from
  // external updates to the page location.
  useEffect(() => {
    if (queryParamKind) {
      setSelectedKind(queryParamKind);
    }
  }, [queryParamKind]);

  // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not
  // be present in allKinds. It should still be shown in the dropdown, but may not have the nice
  // enforced casing from the catalog-backend. This makes a key/value record for the Select options,
  // including selectedKind if it's unknown - but allows the selectedKind to get clobbered by the
  // more proper catalog kind if it exists.
  const availableKinds = [capitalize(selectedKind)].concat(
    allKinds?.filter(k =>
      allowedKinds
        ? allowedKinds.some(
            a => a.toLocaleLowerCase('en-US') === k.toLocaleLowerCase('en-US'),
          )
        : true,
    ) ?? [],
  );
  const options = availableKinds.sort().reduce((acc, kind) => {
    acc[kind.toLocaleLowerCase('en-US')] = kind;
    return acc;
  }, {} as Record<string, string>);

  return (
    <Select
      input={<InputBase value={selectedKind} />}
      value={selectedKind}
      onChange={e => setSelectedKind(e.target.value as string)}
      classes={classes}
    >
      {Object.keys(options).map(kind => (
        <MenuItem value={kind} key={kind}>
          {`${options[kind]}s`}
        </MenuItem>
      ))}
    </Select>
  );
}
Example #16
Source File: index.tsx    From GroupChat with MIT License 5 votes vote down vote up
MsgInput: React.FC<Props> = props => {
  const [msg, setMsg] = useState('');

  const getDateString = () => {
    const monthNames = [
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'
    ];
    let dateObj = new Date();
    let month = monthNames[dateObj.getMonth()];
    let day = String(dateObj.getDate()).padStart(2, '0');
    let output = month + ' ' + day + ',';

    return `${output} - ${new Date().getHours()}:${new Date().getMinutes()}`;
  };

  const sendHandler = () => {
    props.sendClick(msg, getDateString());
    setMsg('');
  };

  return (
    <div className={styles.container} onClick={props.onClick}>
      <InputBase
        className={styles.input}
        placeholder="Write here..."
        value={msg}
        onChange={e => setMsg(e.target.value)}
        onKeyDown={e => {
          if (e.key === 'Enter') sendHandler();
        }}
      />
      <IconButton className={styles.iconButton} onClick={sendHandler}>
        <SendIcon className={styles.send} />
      </IconButton>
    </div>
  );
}
Example #17
Source File: ClassicCipher.tsx    From DamnVulnerableCryptoApp with MIT License 5 votes vote down vote up
ClassicCipher = (props: IChallengeProps) => {

  const classes = useStyles();
  const [answer, setAnswer] = useState("");
  const [enigma, setEnigma] = useState("");
  const [errorMessage, setErrorMessage] = useState("");
  const layoutContext = useContext(LayoutContext);


  const checkAnswer = (event: React.SyntheticEvent) => {
    event.preventDefault();
    layoutContext.setLoading(true);
    setErrorMessage("");

    ClassicService.checkAnswer(answer).then(res => {
      const flag = res.flag;
      props.setFlag(flag);
      if (!res.success) setErrorMessage("Sorry, not quite there yet...");

      layoutContext.setLoading(false);

    }).catch(() => layoutContext.setLoading(false));
  };

  useEffect(() => {
    layoutContext.setLoading(true);

    ClassicService.init().then(data => {
      setEnigma(data);
      layoutContext.setLoading(false);
    }).catch(() => layoutContext.setLoading(false));
  }, []);

  const onAnswerChange = (e: React.ChangeEvent<HTMLInputElement>) => setAnswer(e.target.value);

  return (
    <Box>
      <Box className={classes.paper} boxShadow={3}>
        <strong>{enigma}</strong>
      </Box>


      <Box className={classes.formContainer}>
        <Typography>Decrypt the message and solve the riddle</Typography>

        <Paper component="form" onSubmit={checkAnswer} >
          <Box className={classes.inputContainer}>
            <InputBase className={classes.input} fullWidth placeholder="[1,4,13,27,35,46,49,62,71]" onChange={onAnswerChange} />
            <IconButton color="primary" type="submit">
              <SendIcon />
            </IconButton>
          </Box>
          {errorMessage ? <Alert severity="error">{errorMessage}</Alert> : <div />}
        </Paper>
      </Box>
    </Box>
  );
}
Example #18
Source File: ExpandableListItemInput.tsx    From bee-dashboard with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
export default function ExpandableListItemKey({
  label,
  value,
  onConfirm,
  onChange,
  confirmLabel,
  confirmLabelDisabled,
  expandedOnly,
  helperText,
  placeholder,
  loading,
  mapperFn,
  locked,
}: Props): ReactElement | null {
  const classes = useStyles()
  const [open, setOpen] = useState(Boolean(expandedOnly))
  const [inputValue, setInputValue] = useState<string>(value || '')
  const toggleOpen = () => setOpen(!open)
  const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
    if (mapperFn) {
      e.target.value = mapperFn(e.target.value)
    }

    setInputValue(e.target.value)

    if (onChange) onChange(e.target.value)
  }

  return (
    <>
      <ListItem className={`${classes.header} ${open ? classes.headerOpen : ''}`}>
        <Grid container direction="column" justifyContent="space-between" alignItems="stretch">
          <Grid container direction="row" justifyContent="space-between" alignItems="center">
            {label && (
              <Typography variant="body1" className={classes.unselectableLabel}>
                {label}
              </Typography>
            )}
            <Typography variant="body2">
              <div>
                {!open && value}
                {!expandedOnly && !locked && (
                  <IconButton size="small" className={classes.copyValue}>
                    {open ? (
                      <Minus onClick={toggleOpen} strokeWidth={1} />
                    ) : (
                      <Edit onClick={toggleOpen} strokeWidth={1} />
                    )}
                  </IconButton>
                )}
              </div>
            </Typography>
          </Grid>
          <Collapse in={open} timeout="auto" unmountOnExit>
            <InputBase
              value={inputValue}
              placeholder={placeholder}
              onChange={handleChange}
              fullWidth
              className={classes.content}
              autoFocus
              hidden={locked}
            />
          </Collapse>
        </Grid>
      </ListItem>
      <Collapse in={open} timeout="auto" unmountOnExit>
        {helperText && <ExpandableListItemNote>{helperText}</ExpandableListItemNote>}
        <ExpandableListItemActions>
          <SwarmButton
            disabled={
              loading ||
              inputValue === value ||
              Boolean(confirmLabelDisabled) || // Disable if external validation is provided
              (inputValue === '' && value === undefined) // Disable if no initial value was not provided and the field is empty. The undefined check is improtant so that it is possible to submit with empty input in other cases
            }
            loading={loading}
            iconType={Search}
            onClick={() => {
              if (onConfirm) onConfirm(inputValue)
            }}
          >
            {confirmLabel || 'Save'}
          </SwarmButton>
          <SwarmButton
            disabled={loading || inputValue === value || inputValue === ''}
            iconType={X}
            onClick={() => setInputValue(value || '')}
            cancel
          >
            Cancel
          </SwarmButton>
        </ExpandableListItemActions>
      </Collapse>
    </>
  )
}
Example #19
Source File: SearchBar.tsx    From glific-frontend with GNU Affero General Public License v3.0 4 votes vote down vote up
SearchBar: React.SFC<SearchBarProps> = (props) => {
  const {
    searchMode,
    searchVal,
    onReset,
    endAdornment,
    handleClick,
    handleSubmit,
    handleChange,
    className,
  } = props;

  const [localSearchValue, setLocalSearchValue] = useState(searchVal);
  const { t } = useTranslation();

  // use local state value so that we can set the defaults correctly
  // local value is needed for list component
  let inputValue: any = '';
  if (searchMode) {
    inputValue = localSearchValue;
  } else if (searchVal) {
    inputValue = searchVal;
  }

  // display reset button only if value is entered
  let resetButton = null;
  if (inputValue) {
    resetButton = (
      <IconButton
        data-testid="resetButton"
        className={styles.ResetSearch}
        onClick={() => {
          setLocalSearchValue('');
          onReset();
        }}
      >
        <CloseIcon className={styles.CloseIcon} />
      </IconButton>
    );
  }

  let endAdornmentInput;
  if (endAdornment) {
    endAdornmentInput = (
      <InputAdornment position="end">
        <IconButton
          aria-label="toggle password visibility"
          onClick={(e: any) => {
            handleClick(e, 'search', 'update');
          }}
        >
          <AdvancedSearch />
        </IconButton>
      </InputAdornment>
    );
  }

  return (
    <form onSubmit={handleSubmit} autoComplete="off" data-testid="searchForm">
      <div className={`${styles.SearchBar} ${className}`}>
        <div className={styles.IconAndText}>
          <img src={searchIcon} className={styles.SearchIcon} alt="Search" />
          <InputBase
            data-testid="searchInput"
            className={styles.SearchField}
            name="searchInput" // This is important for extracting the search value in parent component.
            placeholder={t('Search')}
            onChange={(e: any) => {
              setLocalSearchValue(e.target.value);
              if (handleChange) {
                handleChange(e);
              }
            }}
            value={inputValue}
            endAdornment={endAdornmentInput}
          />
        </div>
        {resetButton}
      </div>
    </form>
  );
}
Example #20
Source File: NotesPanel.tsx    From vscode-crossnote with GNU Affero General Public License v3.0 4 votes vote down vote up
export function NotesPanel(props: Props) {
  const classes = useStyles(props);
  const { t } = useTranslation();
  const [selectedSection, setSelectedSection] = useState<SelectedSection>(null);
  const [selectedNote, setSelectedNote] = useState<Note>(null);
  const [notes, setNotes] = useState<Note[]>([]);
  const [searchValue, setSearchValue] = useState<string>("");
  const [searchValueInputTimeout, setSearchValueInputTimeout] = useState<
    NodeJS.Timeout
  >(null);
  const [finalSearchValue, setFinalSearchValue] = useState<string>("");
  const [sortMenuAnchorEl, setSortMenuAnchorEl] = useState<HTMLElement>(null);
  const [orderBy, setOrderBy] = useState<OrderBy>(OrderBy.ModifiedAt);
  const [orderDirection, setOrderDirection] = useState<OrderDirection>(
    OrderDirection.DESC
  );

  const createNewNote = useCallback(() => {
    if (!selectedSection) {
      return;
    }
    const message: Message = {
      action: MessageAction.CreateNewNote,
      data: selectedSection,
    };
    vscode.postMessage(message);
  }, [selectedSection]);

  const onChangeSearchValue = useCallback(
    (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
      const value = event.target.value;
      setSearchValue(value);
      if (searchValueInputTimeout) {
        clearTimeout(searchValueInputTimeout);
      }
      const timeout = setTimeout(() => {
        setFinalSearchValue(value);
      }, 400);
      setSearchValueInputTimeout(timeout);
    },
    [searchValueInputTimeout]
  );

  useEffect(() => {
    const message: Message = {
      action: MessageAction.InitializedNotesPanelWebview,
      data: {},
    };
    vscode.postMessage(message);
  }, []);

  useEffect(() => {
    const onMessage = (event) => {
      const message: Message = event.data;
      let note: Note;
      switch (message.action) {
        case MessageAction.SelectedSection:
          setSelectedSection(message.data);
          if (
            selectedSection &&
            message.data.notebook.dir !== selectedSection.notebook.dir
          ) {
            setSearchValue("");
          }
          break;
        case MessageAction.SendNotes:
          const notes: Note[] = message.data;
          notes.forEach((note) => {
            note.config.createdAt = new Date(note.config.createdAt || 0);
            note.config.modifiedAt = new Date(note.config.modifiedAt || 0);
          });
          setNotes(message.data || []);
          break;
        case MessageAction.CreatedNewNote:
          note = message.data;
          note.config.createdAt = new Date(note.config.createdAt || 0);
          note.config.modifiedAt = new Date(note.config.modifiedAt || 0);

          setNotes((notes) => [note, ...notes]);
          setSelectedNote(note);
          break;
        case MessageAction.SelectedNote:
          note = message.data;
          note.config.createdAt = new Date(note.config.createdAt || 0);
          note.config.modifiedAt = new Date(note.config.modifiedAt || 0);
          setSelectedNote(note);
          break;
        default:
          break;
      }
    };
    window.addEventListener("message", onMessage);
    return () => {
      window.removeEventListener("message", onMessage);
    };
  }, [selectedSection]);

  return (
    <Box className={clsx(classes.notesPanel)}>
      <Card className={clsx(classes.topPanel)}>
        <Box className={clsx(classes.row)}>
          <div className={clsx(classes.search)}>
            <div className={clsx(classes.searchIcon)}>
              <Magnify />
            </div>
            <InputBase
              placeholder={t("search/placeholder")}
              classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
              }}
              value={searchValue}
              inputProps={{ "aria-label": "search" }}
              onChange={onChangeSearchValue}
              autoComplete={"off"}
              autoCorrect={"off"}
            />
          </div>
          <IconButton onClick={createNewNote}>
            <FileEditOutline></FileEditOutline>
          </IconButton>
        </Box>
        <Box
          className={clsx(classes.row)}
          style={{ justifyContent: "space-between" }}
        >
          {selectedSection?.type === CrossnoteSectionType.Notes ||
          selectedSection?.type === CrossnoteSectionType.Notebook ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="notes">
                ?
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {selectedSection.notebook.name}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Today ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="today-notes">
                ?
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/today")}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Todo ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="todo-notes">
                ☑️
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/todo")}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Tagged ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="tagged-notes">
                ?️
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/tagged")}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Untagged ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="untagged-notes">
                ?
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/untagged")}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Tag ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="tag">
                ?️
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {selectedSection.path}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Encrypted ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="encrypted-notes">
                ?
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/encrypted")}
              </Typography>
            </Box>
          ) : selectedSection?.type === CrossnoteSectionType.Conflicted ? (
            <Box className={clsx(classes.row)}>
              <span role="img" aria-label="conflicted-notes">
                ⚠️
              </span>
              <Typography className={clsx(classes.sectionName)}>
                {t("general/conflicted")}
              </Typography>
            </Box>
          ) : (
            selectedSection?.type === CrossnoteSectionType.Directory && (
              <Box className={clsx(classes.row)}>
                <span role="img" aria-label="folder">
                  {"?"}
                </span>
                <Typography className={clsx(classes.sectionName)}>
                  {selectedSection.path}
                </Typography>
              </Box>
            )
          )}

          <Box>
            <IconButton
              onClick={(event) => setSortMenuAnchorEl(event.currentTarget)}
            >
              <SortVariant></SortVariant>
            </IconButton>
            <Popover
              anchorEl={sortMenuAnchorEl}
              keepMounted
              open={Boolean(sortMenuAnchorEl)}
              onClose={() => setSortMenuAnchorEl(null)}
            >
              <List>
                <ListItem
                  button
                  onClick={() => setOrderBy(OrderBy.ModifiedAt)}
                  className={clsx(
                    orderBy === OrderBy.ModifiedAt && classes.sortSelected
                  )}
                >
                  <ListItemText
                    primary={t("general/date-modified")}
                  ></ListItemText>
                </ListItem>
                <ListItem
                  button
                  onClick={() => setOrderBy(OrderBy.CreatedAt)}
                  className={clsx(
                    orderBy === OrderBy.CreatedAt && classes.sortSelected
                  )}
                >
                  <ListItemText
                    primary={t("general/date-created")}
                  ></ListItemText>
                </ListItem>
                <ListItem
                  button
                  onClick={() => setOrderBy(OrderBy.Title)}
                  className={clsx(
                    orderBy === OrderBy.Title && classes.sortSelected
                  )}
                >
                  <ListItemText primary={t("general/title")}></ListItemText>
                </ListItem>
                <Divider></Divider>
                <ListItem
                  button
                  onClick={() => setOrderDirection(OrderDirection.DESC)}
                  className={clsx(
                    orderDirection === OrderDirection.DESC &&
                      classes.sortSelected
                  )}
                >
                  <ListItemText primary={"Desc"}></ListItemText>
                  <ListItemIcon style={{ marginLeft: "8px" }}>
                    <SortDescending></SortDescending>
                  </ListItemIcon>
                </ListItem>
                <ListItem
                  button
                  onClick={() => setOrderDirection(OrderDirection.ASC)}
                  className={clsx(
                    orderDirection === OrderDirection.ASC &&
                      classes.sortSelected
                  )}
                >
                  <ListItemText primary={"Asc"}></ListItemText>
                  <ListItemIcon style={{ marginLeft: "8px" }}>
                    <SortAscending></SortAscending>
                  </ListItemIcon>
                </ListItem>
              </List>
            </Popover>
          </Box>
        </Box>
      </Card>

      <Notes
        searchValue={finalSearchValue}
        notes={notes}
        orderBy={orderBy}
        orderDirection={orderDirection}
        selectedNote={selectedNote}
        setSelectedNote={setSelectedNote}
      ></Notes>
    </Box>
  );
}
Example #21
Source File: Search.tsx    From gatsby-theme-pristine with Apache License 2.0 4 votes vote down vote up
Search: React.FC = () => {
  const data = useStaticQuery(graphql`
    query SearchIndexQuery {
      localSearchPages {
        index
        store
      }
    }
  `);
  const [query, setQuery] = useState("");
  const [selectedItem, setSelectedItem] = useState();
  const [anchorEl, setAnchorEl] = React.useState(null);

  const handleFocus = (event: any) => {
    setAnchorEl(event.currentTarget);
  };

  const results = useFlexSearch(
    query,
    data.localSearchPages.index,
    JSON.parse(data.localSearchPages.store),
  );
  const open = Boolean(anchorEl);
  const selected = selectedItem || results[0];

  return (
    <div style={{ marginRight: "5px" }}>
      <InputBase
        onKeyDown={(ev: any) => {
          // Enter
          if (ev.keyCode === 13) {
            if (selected) {
              setQuery("");
              if (anchorEl !== null) {
                (anchorEl as any).blur();
                setAnchorEl(null);
              }
              navigate(selected.slug);
            }
          } else if (ev.keyCode === 40) {
            // Down
            const currIndex = _.findIndex(results, (result: any) => result.id === selected.id);
            const newSelected = results[currIndex + 1];
            if (newSelected) {
              setSelectedItem(newSelected);
            }
          } else if (ev.keyCode === 38) {
            // Up
            const currIndex = _.findIndex(results, (result: any) => result.id === selected.id);
            const newSelected = results[currIndex - 1];
            if (newSelected) {
              setSelectedItem(newSelected);
            }
          }
        }}
        onChange={(ev: any) => {
          setQuery(ev.target.value);
        }}
        onFocus={handleFocus}
        placeholder={"? Search"}
        value={query}
        style={{
          fontSize: "16px",
          background: "rgba(0,0,0,0.1)",
          borderRadius: "4px",
          paddingRight: "10px",
          paddingLeft: "10px",
          paddingTop: "4px",
          marginBottom: "4px",
        }}

      />
      {results.length !== 0 &&
        <Popper
          open={open}
          style={{ marginTop: "5px" }}
          anchorEl={anchorEl as any}
          popperOptions={{
            placement: "bottom",
          }}
        >
          <Paper style={{ maxWidth: "450px", marginTop: "12px" }}>
            <List>
              {results.map((result: any) => (
                <ListItem key={result.id} selected={selected.id === result.id}>
                  <GatsbyLink to={result.slug} style={{ textDecoration: "none" }} onClick={() => {
                    setQuery("");
                    setAnchorEl(null);
                  }}>
                    <ListItemText primary={result.slug} secondary={result.title} />
                  </GatsbyLink>
                </ListItem>
              ))}
            </List>
          </Paper>
        </Popper>
      }
    </div>
  );

}
Example #22
Source File: SearchBar.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
SearchBarBase = ({
  onChange,
  onKeyDown,
  onSubmit,
  debounceTime = 200,
  clearButton = true,
  fullWidth = true,
  value: defaultValue,
  inputProps: defaultInputProps = {},
  endAdornment: defaultEndAdornment,
  ...props
}: SearchBarBaseProps) => {
  const configApi = useApi(configApiRef);
  const [value, setValue] = useState<string>(defaultValue as string);
  const hasSearchContext = useSearchContextCheck();

  useEffect(() => {
    setValue(prevValue =>
      prevValue !== defaultValue ? (defaultValue as string) : prevValue,
    );
  }, [defaultValue]);

  useDebounce(() => onChange(value), debounceTime, [value]);

  const handleChange = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => {
      setValue(e.target.value);
    },
    [setValue],
  );

  const handleKeyDown = useCallback(
    (e: KeyboardEvent<HTMLInputElement>) => {
      if (onKeyDown) onKeyDown(e);
      if (onSubmit && e.key === 'Enter') {
        onSubmit();
      }
    },
    [onKeyDown, onSubmit],
  );

  const handleClear = useCallback(() => {
    onChange('');
  }, [onChange]);

  const placeholder = `Search in ${
    configApi.getOptionalString('app.title') || 'Backstage'
  }`;

  const startAdornment = (
    <InputAdornment position="start">
      <IconButton aria-label="Query" disabled>
        <SearchIcon />
      </IconButton>
    </InputAdornment>
  );

  const endAdornment = (
    <InputAdornment position="end">
      <IconButton aria-label="Clear" onClick={handleClear}>
        <ClearButton />
      </IconButton>
    </InputAdornment>
  );

  const searchBar = (
    <TrackSearch>
      <InputBase
        data-testid="search-bar-next"
        value={value}
        placeholder={placeholder}
        startAdornment={startAdornment}
        endAdornment={clearButton ? endAdornment : defaultEndAdornment}
        inputProps={{ 'aria-label': 'Search', ...defaultInputProps }}
        fullWidth={fullWidth}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        {...props}
      />
    </TrackSearch>
  );

  return hasSearchContext ? (
    searchBar
  ) : (
    <SearchContextProvider>{searchBar}</SearchContextProvider>
  );
}
Example #23
Source File: ExperimentsTableAgGrid.tsx    From abacus with GNU General Public License v2.0 4 votes vote down vote up
ExperimentsTable = ({ experiments }: { experiments: ExperimentSummary[] }): JSX.Element => {
  const theme = useTheme()
  const classes = useStyles()

  const gridApiRef = useRef<GridApi | null>(null)
  const gridColumnApiRef = useRef<ColumnApi | null>(null)

  const onGridReady = (event: GridReadyEvent) => {
    gridApiRef.current = event.api
    gridColumnApiRef.current = gridColumnApiRef.current = event.columnApi

    event.api.sizeColumnsToFit()

    searchQuery && setSearchState(searchQuery)
  }

  const onGridResize = () => {
    if (!gridApiRef.current) {
      return
    }

    gridApiRef.current.sizeColumnsToFit()
  }

  const history = useHistory()
  const { pathname, search } = useLocation()
  const searchQuery = Object.fromEntries(new URLSearchParams(search).entries())?.search

  const [searchState, setSearchState] = useState<string>('')
  const onSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setSearchState(event.target.value)
    event.target.value ? history.replace(`${pathname}?search=${event.target.value}`) : history.replace(pathname)
  }

  useEffect(() => {
    // istanbul ignore next; trivial and shouldn't occur
    if (!gridApiRef.current) {
      return
    }

    gridApiRef.current?.setQuickFilter(searchState)
  }, [searchState])

  const onNewDataRender = () => {
    // istanbul ignore next; trivial and shouldn't occur
    if (!gridApiRef.current || !gridColumnApiRef.current) {
      return
    }

    gridColumnApiRef.current.autoSizeAllColumns()
    gridColumnApiRef.current.resetColumnState()
    gridApiRef.current.setFilterModel(null)
    gridColumnApiRef.current.applyColumnState({
      state: [
        {
          colId: 'status',
          sort: 'asc',
          sortIndex: 0,
        },
        {
          colId: 'startDatetime',
          sort: 'desc',
          sortIndex: 1,
        },
      ],
      defaultState: { sort: null },
    })
  }

  const onReset = () => {
    setSearchState('')
    history.push(pathname)
    onNewDataRender()
  }

  return (
    <div className={clsx('ag-theme-alpine', classes.root)}>
      <div className={classes.toolbar}>
        <Typography variant='h2'>Experiments</Typography>
        <div className={classes.controls}>
          <div className={classes.search}>
            <div className={classes.searchIcon}>
              <SearchIcon />
            </div>
            <InputBase
              placeholder='Search…'
              classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
              }}
              inputProps={{ 'aria-label': 'Search' }}
              value={searchState}
              onChange={onSearchChange}
            />
          </div>
          <Button onClick={onReset}> Reset </Button>
        </div>
      </div>
      <div className={clsx('ag-theme-alpine', classes.gridContainer)}>
        <AgGridReact
          columnDefs={[
            {
              headerName: 'Name',
              field: 'name',
              cellStyle: {
                fontFamily: theme.custom.fonts.monospace,
                fontWeight: 600,
              },
              cellRendererFramework: ({ value: name, data }: { value: Status; data: ExperimentSummary }) => (
                <Link component={RouterLink} to={`/experiments/${createIdSlug(data.experimentId, data.name)}`}>
                  {name}
                </Link>
              ),
              sortable: true,
              filter: true,
              resizable: true,
              width: 520,
            },
            {
              headerName: 'Status',
              field: 'status',
              cellRendererFramework: ({ value: status }: { value: Status }) => <ExperimentStatus status={status} />,
              comparator: statusComparator,
              sortable: true,
              filter: true,
              resizable: true,
            },
            {
              headerName: 'Platform',
              field: 'platform',
              cellStyle: {
                fontFamily: theme.custom.fonts.monospace,
              },
              sortable: true,
              filter: true,
              resizable: true,
            },
            {
              headerName: 'Owner',
              field: 'ownerLogin',
              cellStyle: {
                fontFamily: theme.custom.fonts.monospace,
              },
              sortable: true,
              filter: true,
              resizable: true,
            },
            {
              headerName: 'Start',
              field: 'startDatetime',
              cellRendererFramework: ({ value: startDatetime }: { value: Date }) => {
                return <DatetimeText datetime={startDatetime} excludeTime />
              },
              sortable: true,
              filter: 'agDateColumnFilter',
              resizable: true,
            },
            {
              headerName: 'End',
              field: 'endDatetime',
              cellRendererFramework: ({ value: endDatetime }: { value: Date }) => {
                return <DatetimeText datetime={endDatetime} excludeTime />
              },
              sortable: true,
              filter: 'agDateColumnFilter',
              resizable: true,
            },
            {
              field: 'description',
              hide: true,
            },
            {
              headerName: 'Participants',
              valueGetter: (params: { data: { analyses: Analysis[] } }) =>
                params.data.analyses[0]?.participantStats.total || 0,
              cellRendererFramework: ({ value: participants }: { value: number }) => {
                return <MetricValue value={participants} metricParameterType={MetricParameterType.Count} />
              },
              sortable: true,
              filter: 'agNumberColumnFilter',
              resizable: true,
              type: 'rightAligned',
            },
          ]}
          rowData={experiments}
          containerStyle={{ flex: 1, height: 'auto' }}
          onFirstDataRendered={onNewDataRender}
          onGridReady={onGridReady}
          onGridSizeChanged={onGridResize}
        />
      </div>
    </div>
  )
}