@mui/material#ClickAwayListener TypeScript Examples

The following examples show how to use @mui/material#ClickAwayListener. 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: Popper.tsx    From Cromwell with MIT License 6 votes vote down vote up
/** @internal */
export function Popper(props: BasePopperProps) {
  const onClose = () => {
    props.onClose?.();
  }
  return (
    <MuiPopper open={!!(props.open && props.children)}
      anchorEl={props.anchorEl}
      style={{ zIndex: 10000 }}
      transition
    >
      {({ TransitionProps }) => (
        <Fade {...TransitionProps} timeout={350}>
          {/* ClickAwayListener directly inside Fade crashes the app, we need div wrapper */}
          <div>
            <ClickAwayListener onClickAway={onClose}>
              <div>{props.children}</div>
            </ClickAwayListener>
          </div>
        </Fade>
      )}
    </MuiPopper>
  )
}
Example #2
Source File: ThreePoints.tsx    From your_spotify with GNU General Public License v3.0 6 votes vote down vote up
export default function ThreePoints({ items }: ThreePointsProps) {
  const [open, setOpen] = useState(false);
  const buttonRef = useRef<HTMLButtonElement | null>(null);

  const internClick = useCallback(
    (index: number) => {
      items[index].onClick();
      setOpen(false);
    },
    [items],
  );

  return (
    <ClickAwayListener onClickAway={() => setOpen(false)}>
      <div>
        <IconButton size="small" ref={buttonRef} onClick={() => setOpen((v) => !v)}>
          <MoreHoriz fontSize="small" />
        </IconButton>
        <Popper
          open={open}
          anchorEl={buttonRef.current}
          popperOptions={{ placement: 'auto-start' }}
          transition>
          {({ TransitionProps }) => (
            // eslint-disable-next-line react/jsx-props-no-spreading
            <Fade {...TransitionProps}>
              <div className={s.popper}>
                {items.map((item, index) => (
                  <Tooltip title={(item.disabled && item.disabledTooltip) || ''}>
                    <Button
                      // eslint-disable-next-line react/no-array-index-key
                      key={index}
                      variant="text"
                      disabled={item.disabled}
                      className={clsx({
                        [s.item]: true,
                        [s[item.style ?? 'normal']]: true,
                      })}
                      onClick={() => internClick(index)}>
                      {item.label}
                    </Button>
                  </Tooltip>
                ))}
                {items.length === 0 && (
                  <Button
                    // eslint-disable-next-line react/no-array-index-key
                    variant="text"
                    disabled>
                    No action available
                  </Button>
                )}
              </div>
            </Fade>
          )}
        </Popper>
      </div>
    </ClickAwayListener>
  );
}
Example #3
Source File: HeaderSearch.tsx    From Cromwell with MIT License 5 votes vote down vote up
render() {
        const { isLoading, searchItems, searchOpen } = this.state;

        return (
            <>
                <TextField label="Search..."
                    variant="outlined" size="small"
                    ref={this.searchAnchorRef}
                    // onBlur={handleSearchClose}
                    onChange={(event) => this.handleSearchInput(event.currentTarget.value)} />
                <Popper open={searchOpen} anchorEl={this.searchAnchorRef.current}
                    style={{ zIndex: 9999 }}
                    transition>
                    {({ TransitionProps }) => (
                        <Fade {...TransitionProps} timeout={350}>
                            <div>
                                <ClickAwayListener onClickAway={this.handleSearchClose}>
                                    <div className={styles.searchContent} onClick={this.handleSearchClose}>
                                        {isLoading && (
                                            <LoadBox size={100} />
                                        )}
                                        {!isLoading && searchItems.length === 0 && (
                                            <p className={styles.notFoundText}>No items found</p>
                                        )}
                                        {!isLoading && searchItems.map(post => {
                                            return (
                                                <Grid container className={styles.listItem} key={post.id}>
                                                    <Link href={`/post/${post.slug}`} >
                                                        <Grid item xs={12} className={styles.itemMain}>
                                                            <div
                                                                style={{ backgroundImage: `url(${post?.mainImage})` }}
                                                                className={styles.itemImage}
                                                            ></div>
                                                            <div className={styles.itemMainInfo}>
                                                                <p className={styles.itemTitle}>{post.title ?? ''}</p>
                                                            </div>
                                                        </Grid>
                                                    </Link>
                                                </Grid>
                                            )
                                        })}
                                    </div>
                                </ClickAwayListener>
                            </div>
                        </Fade>
                    )}
                </Popper>
            </>
        );
    }
Example #4
Source File: Autocomplete.tsx    From Cromwell with MIT License 4 votes vote down vote up
render() {
        const { searchOpen, pickedItems, pickedText } = this.state;
        const { multiple } = this.props;

        return (
            <>
                <MuiAutocomplete
                    className={this.props.className}
                    multiple={multiple}
                    options={pickedItems ?? []}
                    getOptionLabel={(option) => option as any}
                    value={multiple ? (pickedItems ?? []) : (pickedText ?? '')}
                    onChange={(event, newValue) => {
                        if (!newValue) {
                            this.handleClear();
                        }
                        if (multiple && newValue) {
                            const pickedItems = [...new Set([...(newValue as any)])];
                            this.props.onSelect?.(pickedItems.map(item => this.pickedData[item]));
                            Object.values(this.multiSelectionListeners).forEach(func => func(pickedItems));
                            this.setState({
                                pickedItems,
                            });
                        }
                    }}
                    PopperComponent={() => <></>}
                    renderInput={(params) => (
                        <TextField
                            {...params}
                            value={this.state.searchText ?? ''}
                            onChange={(event) => this.handleSearchInput(event.currentTarget.value)}
                            onFocus={() => this.handleSearchInput(this.state.searchText)}
                            onBlur={() => !multiple && this.handleSearchClose()}
                            label={this.props.label ?? "Search..."}
                            fullWidth={this.props.fullWidth}
                            ref={this.searchAnchorRef}
                            size="small"
                            variant={this.props.variant ?? 'standard'}
                        />
                    )}
                />
                <Popper open={searchOpen} anchorEl={this.searchAnchorRef.current}
                    style={{ zIndex: 9999 }}
                    transition>
                    {({ TransitionProps }) => (
                        <Fade {...TransitionProps} timeout={350}>
                            <div className={styles.searchContent}>
                                <ClickAwayListener onClickAway={this.handleSearchClose}>
                                    {/* {isLoading && (
                                    <LoadBox size={100} />
                                )}
                                {!isLoading && searchItems.length === 0 && (
                                    <p className={styles.notFoundText}>No items found</p>
                                )}
                                {!isLoading && ( */}
                                    <CList<TItemData, ListItemProps<TItemData>>
                                        useAutoLoading
                                        className={styles.list}
                                        id={this.listId}
                                        loader={this.loadMore}
                                        elements={{ preloader: <div className={styles.listPreloader}>{this.listSkeleton}</div> }}
                                        ListItem={ListItem}
                                        listItemProps={{
                                            handleItemClick: this.handleItemClick,
                                            getOptionLabel: this.props.getOptionLabel,
                                            getOptionValue: this.props.getOptionValue,
                                            pickedItems: this.state?.pickedItems,
                                            multiple,
                                            ItemComponent: this.props.itemComponent,
                                            addMultiSelectListener: this.addMultiSelectListener,
                                            removeMultiSelectListener: this.removeMultiSelectListener,
                                        }}
                                    />
                                    {/* )} */}
                                </ClickAwayListener>
                            </div>
                        </Fade>
                    )}
                </Popper>
            </>
        );
    }
Example #5
Source File: SearchBox.tsx    From multi-downloader-nx with MIT License 4 votes vote down vote up
SearchBox: React.FC = () => {
  const messageHandler = React.useContext(messageChannelContext);
  const [store, dispatch] = useStore();
  const [search, setSearch] = React.useState('');

  const [focus, setFocus] = React.useState(false);

  const [searchResult, setSearchResult] = React.useState<undefined|SearchResponse>();
  const anchor = React.useRef<HTMLDivElement>(null);

  const { enqueueSnackbar } = useSnackbar();

  const selectItem = (id: string) => {
    console.log(id);
    dispatch({
      type: 'downloadOptions',
      payload: {
        ...store.downloadOptions,
        id
      }
    });
  };

  React.useEffect(() => {
    (async () => {
      if (search.trim().length === 0)
        return setSearchResult({ isOk: true, value: [] });
      const s = await messageHandler?.search({search});
      if (s && s.isOk)
        s.value = s.value.slice(0, 10);
      setSearchResult(s);
    })();
  }, [search]);

  const anchorBounding = anchor.current?.getBoundingClientRect();
  return <ClickAwayListener onClickAway={() => setFocus(false)}>
    <Box sx={{ m: 2 }}>
      <TextField ref={anchor} value={search} onClick={() => setFocus(true)} onChange={e => setSearch(e.target.value)} variant='outlined' label='Search' fullWidth  />
      {searchResult !== undefined && searchResult.isOk && searchResult.value.length > 0 && focus &&
      <Paper sx={{ position: 'fixed', maxHeight: '50%', width: `${anchorBounding?.width}px`, 
        left: anchorBounding?.x, top: (anchorBounding?.y ?? 0) + (anchorBounding?.height ?? 0), zIndex: 99, overflowY: 'scroll'}}>
        <List>
          {searchResult && searchResult.isOk ?
            searchResult.value.map((a, ind, arr) => {
              const imageRef = React.createRef<HTMLImageElement>();
              return <Box key={a.id}>
                <ListItem className='listitem-hover' onClick={(e) => {
                  selectItem(a.id);
                  setFocus(false);
                }}>
                  <Box sx={{ display: 'flex' }}>
                    <Box sx={{ width: '20%', height: '100%', pr: 2 }}>
                      <img ref={imageRef} src={a.image} style={{ width: '100%', height: '100%' }}/>
                    </Box>
                    <Box sx={{ display: 'flex', flexDirection: 'column', maxWidth: '70%' }}>
                      <Typography variant='h6' component='h6' color='text.primary' sx={{  }}>
                        {a.name}
                      </Typography>
                      {a.desc && <Typography variant='caption' component='p' color='text.primary' sx={{ pt: 1, pb: 1 }}>
                        {a.desc}
                      </Typography>}
                      {a.lang && <Typography variant='caption' component='p' color='text.primary' sx={{  }}>
                        Languages: {a.lang.join(', ')}
                      </Typography>}
                      <Typography variant='caption' component='p' color='text.primary' sx={{  }}>
                        ID: {a.id}
                      </Typography>
                    </Box>
                  </Box>
                </ListItem>
                <ContextMenu options={[ { text: 'Copy image URL', onClick: () => {
                  messageHandler?.writeToClipboard(a.image);
                  enqueueSnackbar('Copied URL to clipboard', {
                    variant: 'info'
                  });
                }} ]} popupItem={imageRef} />
                {(ind < arr.length - 1) && <Divider />}
              </Box>
            })
          : <></>}
        </List>
      </Paper>}
    </Box>
  </ClickAwayListener>
}