@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 |
/** @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 |
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 |
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 |
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 |
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>
}