generated from layer5io/layer5-repo-template
-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #122 from sudhanshutech/toolbar-customSearch
[components]: Toolbar custom components
- Loading branch information
Showing
12 changed files
with
448 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { Popper } from './popper'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { Popper as MuiPopper, type PopperProps } from '@mui/material'; | ||
|
||
export const Popper = (props: PopperProps) => { | ||
return <MuiPopper {...props} />; | ||
}; |
119 changes: 119 additions & 0 deletions
119
packages/components/src/custom/Toolbar/custom-column.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { | ||
Checkbox, | ||
ClickAwayListener, | ||
FormControlLabel, | ||
IconButton, | ||
Paper, | ||
Popper, | ||
Tooltip | ||
} from '@layer5/sistent-components'; | ||
|
||
import React, { useState } from 'react'; | ||
import ColumnIcon from '../../../../svg/src/icons/Column/columnIcon'; | ||
|
||
interface CustomColumnVisibilityControlProps { | ||
columns: Column[]; | ||
customToolsProps: { | ||
columnVisibility: Record<string, boolean>; | ||
setColumnVisibility: React.Dispatch<React.SetStateAction<Record<string, boolean>>>; | ||
}; | ||
style?: React.CSSProperties; | ||
} | ||
|
||
interface Column { | ||
name: string; | ||
label: string; | ||
} | ||
|
||
const CustomColumnVisibilityControl: React.FC<CustomColumnVisibilityControlProps> = ({ | ||
columns, | ||
customToolsProps, | ||
style | ||
}) => { | ||
const [open, setOpen] = useState(false); | ||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); | ||
|
||
const handleOpen = (event: React.MouseEvent<HTMLElement>) => { | ||
setAnchorEl(event.currentTarget); | ||
setOpen(true); | ||
}; | ||
|
||
const handleClose = () => { | ||
setAnchorEl(null); | ||
setOpen(false); | ||
}; | ||
|
||
const handleColumnVisibilityChange = (columnName: string, isVisible: boolean) => { | ||
customToolsProps.setColumnVisibility((prevState) => ({ | ||
...prevState, | ||
[columnName]: isVisible | ||
})); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<Tooltip title="View Columns" arrow> | ||
<IconButton | ||
onClick={handleOpen} | ||
sx={{ | ||
'&:hover': { | ||
'& svg': { | ||
fill: '#00d3a9' | ||
}, | ||
borderRadius: '4px' | ||
}, | ||
...style | ||
}} | ||
disableRipple | ||
> | ||
<ColumnIcon fill="#3c494f" /> | ||
</IconButton> | ||
</Tooltip> | ||
|
||
<Popper | ||
open={Boolean(anchorEl)} | ||
anchorEl={anchorEl} | ||
placement="bottom-end" | ||
modifiers={{ | ||
flip: { | ||
enabled: false | ||
}, | ||
preventOverflow: { | ||
enabled: true, | ||
boundariesElement: 'scrollParent' | ||
} | ||
}} | ||
transition | ||
> | ||
<ClickAwayListener onClickAway={handleClose}> | ||
<Paper | ||
sx={{ | ||
padding: '1rem', | ||
boxShadow: open ? '0px 4px 8px rgba(0, 0, 0, 0.2)' : 'none', | ||
background: '#f4f5f7' | ||
}} | ||
> | ||
<div style={{ display: 'flex', flexDirection: 'column' }}> | ||
{columns.map((col) => ( | ||
<FormControlLabel | ||
key={col.name} | ||
control={ | ||
<Checkbox | ||
checked={customToolsProps.columnVisibility[col.name]} | ||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => | ||
handleColumnVisibilityChange(col.name, e.target.checked) | ||
} | ||
/> | ||
} | ||
label={col.label} | ||
/> | ||
))} | ||
</div> | ||
</Paper> | ||
</ClickAwayListener> | ||
</Popper> | ||
</div> | ||
); | ||
}; | ||
|
||
export default CustomColumnVisibilityControl; |
155 changes: 155 additions & 0 deletions
155
packages/components/src/custom/Toolbar/custom-filter.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import { | ||
Button, | ||
ClickAwayListener, | ||
IconButton, | ||
MenuItem, | ||
Paper, | ||
Popper, | ||
Select, | ||
Tooltip | ||
} from '@layer5/sistent-components'; | ||
import InputLabel from '@mui/material/InputLabel'; | ||
import React, { useState } from 'react'; | ||
import FilterIcon from '../../../../svg/src/icons/Filter/FilterIcon'; | ||
|
||
interface FilterColumn { | ||
name: string; | ||
options: { label: string; value: string }[]; | ||
} | ||
|
||
interface UniversalFilterProps { | ||
filters: Record<string, FilterColumn>; | ||
selectedFilters: Record<string, string>; | ||
setSelectedFilters: React.Dispatch<React.SetStateAction<Record<string, string>>>; | ||
handleApplyFilter: () => void; | ||
showAllOption?: boolean; | ||
} | ||
|
||
const UniversalFilter: React.FC<UniversalFilterProps> = ({ | ||
filters, | ||
selectedFilters, | ||
setSelectedFilters, | ||
handleApplyFilter, | ||
showAllOption = true | ||
}) => { | ||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); | ||
const [open, setOpen] = useState(false); | ||
|
||
const handleFilterChange = (event: React.ChangeEvent<{ value: string }>, columnName: string) => { | ||
const value = event.target.value; | ||
|
||
setSelectedFilters((prevFilters) => ({ | ||
...prevFilters, | ||
[columnName]: value | ||
})); | ||
}; | ||
|
||
const handleApplyOnClick = () => { | ||
handleClose(); | ||
handleApplyFilter(); | ||
}; | ||
|
||
const handleClick = (event: React.MouseEvent<HTMLElement>) => { | ||
setAnchorEl(event.currentTarget); | ||
setOpen((previousOpen) => !previousOpen); | ||
}; | ||
|
||
const canBeOpen = open && Boolean(anchorEl); | ||
const id = canBeOpen ? 'transition-popper' : undefined; | ||
|
||
const handleClose = () => { | ||
setAnchorEl(null); | ||
setOpen(false); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<Tooltip title="Filter" arrow> | ||
<IconButton | ||
onClick={handleClick} | ||
sx={{ | ||
'&:hover': { | ||
'& svg': { | ||
fill: '#00d3a9' | ||
} | ||
} | ||
}} | ||
disableRipple | ||
> | ||
<FilterIcon fill="#3c494f" /> | ||
</IconButton> | ||
</Tooltip> | ||
<Popper | ||
id={id} | ||
open={open} | ||
anchorEl={anchorEl} | ||
placement="bottom-end" | ||
modifiers={{ | ||
flip: { | ||
enabled: false | ||
}, | ||
preventOverflow: { | ||
enabled: true, | ||
boundariesElement: 'scrollParent' | ||
} | ||
}} | ||
transition | ||
> | ||
<ClickAwayListener | ||
onClickAway={handleClose} | ||
mouseEvent="onMouseDown" | ||
touchEvent="onTouchStart" | ||
> | ||
<Paper | ||
sx={{ | ||
padding: '1rem', | ||
paddingTop: '1.8rem', | ||
boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)', | ||
backgroundColor: '#f4f5f7' | ||
}} | ||
> | ||
{Object.keys(filters).map((filterColumn) => { | ||
const options = filters[filterColumn].options; | ||
return ( | ||
<div key={filterColumn} role="presentation"> | ||
<InputLabel id={filters[filterColumn].name}> | ||
{filters[filterColumn].name} | ||
</InputLabel> | ||
<Select | ||
defaultValue="All" | ||
key={filterColumn} | ||
value={selectedFilters[filterColumn]} | ||
onChange={(e: React.ChangeEvent<{ value: string }>) => | ||
handleFilterChange(e, filterColumn) | ||
} | ||
style={{ | ||
width: '15rem', | ||
marginBottom: '1rem' | ||
}} | ||
inputProps={{ 'aria-label': 'Without label' }} | ||
displayEmpty | ||
> | ||
{showAllOption && <MenuItem value="All">All</MenuItem>} | ||
{options.map((option) => ( | ||
<MenuItem key={option.value} value={option.value}> | ||
{option.label} | ||
</MenuItem> | ||
))} | ||
</Select> | ||
</div> | ||
); | ||
})} | ||
|
||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}> | ||
<Button variant="contained" onClick={handleApplyOnClick}> | ||
Apply | ||
</Button> | ||
</div> | ||
</Paper> | ||
</ClickAwayListener> | ||
</Popper> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UniversalFilter; |
106 changes: 106 additions & 0 deletions
106
packages/components/src/custom/Toolbar/custom-search.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { IconButton, TextField, Tooltip } from '@layer5/sistent-components'; | ||
import React, { useRef, useState } from 'react'; | ||
import CloseIcon from '../../../../svg/src/icons/Close/closeIcon'; | ||
import SearchIcon from '../../../../svg/src/icons/Search/searchIcon'; | ||
|
||
interface SearchBarProps { | ||
onSearch: (searchText: string) => void; | ||
style?: React.CSSProperties; | ||
placeholder?: string; | ||
onClear?: () => void; | ||
expanded: boolean; | ||
setExpanded: (expanded: boolean) => void; | ||
} | ||
|
||
const SearchBar: React.FC<SearchBarProps> = ({ placeholder, onClear, expanded, setExpanded }) => { | ||
const [searchText, setSearchText] = useState(''); | ||
const searchRef = useRef<HTMLInputElement | null>(null); | ||
|
||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>): void => { | ||
setSearchText(event.target.value); | ||
}; | ||
|
||
const handleClearIconClick = (): void => { | ||
setSearchText(''); | ||
setExpanded(false); | ||
if (onClear) { | ||
onClear(); | ||
} | ||
}; | ||
|
||
const handleSearchIconClick = (): void => { | ||
if (expanded) { | ||
setSearchText(''); | ||
setExpanded(false); | ||
} else { | ||
setExpanded(true); | ||
setTimeout(() => { | ||
if (searchRef.current) { | ||
searchRef.current.focus(); | ||
} | ||
}, 300); | ||
} | ||
}; | ||
|
||
//Todo: Need a width utility function | ||
// const width = window.innerWidth; | ||
// let searchWidth = "200px"; | ||
// if (width <= 360) { | ||
// searchWidth = "100px"; | ||
// } | ||
|
||
return ( | ||
<div> | ||
<TextField | ||
variant="standard" | ||
value={searchText} | ||
onChange={handleSearchChange} | ||
inputRef={searchRef} | ||
placeholder={placeholder} | ||
style={{ | ||
width: '150px', | ||
opacity: expanded ? 1 : 0, | ||
transition: 'width 0.3s ease, opacity 0.3s ease' | ||
}} | ||
/> | ||
|
||
{expanded ? ( | ||
<Tooltip title="Close"> | ||
<IconButton | ||
onClick={handleClearIconClick} | ||
sx={{ | ||
'&:hover': { | ||
'& svg': { | ||
fill: '#00D3A9' | ||
}, | ||
borderRadius: '4px' | ||
} | ||
}} | ||
disableRipple | ||
> | ||
<CloseIcon fill="#00D3A9" /> | ||
</IconButton> | ||
</Tooltip> | ||
) : ( | ||
<Tooltip title="Search" arrow> | ||
<IconButton | ||
onClick={handleSearchIconClick} | ||
sx={{ | ||
'&:hover': { | ||
'& svg': { | ||
fill: '#00D3A9' | ||
}, | ||
borderRadius: '4px' | ||
} | ||
}} | ||
disableRipple | ||
> | ||
<SearchIcon fill="#00D3A9" /> | ||
</IconButton> | ||
</Tooltip> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchBar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './custom-column'; | ||
export * from './custom-filter'; | ||
export * from './custom-search'; |
Oops, something went wrong.