-
Notifications
You must be signed in to change notification settings - Fork 4
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 #8 from Rhymlore/parameter-chips
Created Parameter Chips for Parameters Page
- Loading branch information
Showing
5 changed files
with
225 additions
and
140 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,71 @@ | ||
import React, { useState } from "react"; | ||
import { ParameterDetail } from "../utils/types"; | ||
import { Box, Paper, Typography, IconButton } from "@mui/material"; | ||
import { Link } from "@mui/icons-material"; | ||
import { useTheme } from "@mui/material/styles"; | ||
|
||
export const ParameterBox: React.FC<{ parameter: ParameterDetail }> = ({ parameter }) => { | ||
|
||
const [hover, setHover] = useState(false); | ||
const parts = parameter.name.split('.'); | ||
const groupName = parts.length > 1 ? parts.slice(0, -1).join('.') : null; | ||
const parameterName = parts.length > 1 ? parts[parts.length - 1] : parameter.name; | ||
const parameterId = parameter.name.replace(".", "-") | ||
const theme = useTheme(); | ||
|
||
return ( | ||
<Box | ||
id={parameterId} | ||
sx={{ marginTop: ".8em" }} | ||
onMouseEnter={() => setHover(true)} | ||
onMouseLeave={() => setHover(false)} | ||
onClick={async () => { | ||
// Copy link to clipboard | ||
const url = new URL(window.location.href); | ||
url.hash = parameterId; | ||
await navigator.clipboard.writeText(url.toString()); | ||
}} | ||
> | ||
<Paper elevation={hover ? 3 : 1} sx={{ padding: "0.7em" }}> | ||
<Box mb={1}> | ||
<Box display={"flex"} justifyContent={"space-between"}> | ||
<Typography variant="h5" > | ||
{parameterName} | ||
</Typography> | ||
{hover && ( | ||
<IconButton size={"small"}> | ||
<Link fontSize={"small"}/> | ||
</IconButton> | ||
)} | ||
</Box> | ||
{/* If groupName exists, display it on a separate line */} | ||
{groupName && ( | ||
<Typography variant="subtitle2" component="div"> | ||
{groupName} | ||
</Typography> | ||
)} | ||
</Box> | ||
<Typography variant="body1" mb={1}> | ||
{parameter.description} | ||
</Typography> | ||
<Box p={1} sx={{ | ||
borderRadius: "0.5em", | ||
marginTop: "0.5em", | ||
backgroundColor: theme.palette.mode === "light" ? "#e7e7e7" : "#666666" | ||
}}> | ||
{parameter.components && ( | ||
<Typography variant="body2"> | ||
Components: [{parameter.components.join(", ")}] | ||
</Typography> | ||
)} | ||
<Typography variant="body2"> | ||
Type: {parameter.type} | ||
</Typography> | ||
<Typography variant="body2"> | ||
Default: {parameter.default === "" ? '""' : parameter.default.toString()} | ||
</Typography> | ||
</Box> | ||
</Paper> | ||
</Box> | ||
); | ||
}; |
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,38 @@ | ||
import { Chip, Stack, Divider, Typography, Box } from "@mui/material"; | ||
import { parameterGroups } from "../utils/types"; | ||
import ClearIcon from '@mui/icons-material/Clear'; | ||
|
||
interface ParameterChipsProps { | ||
handleClick: (group: string) => void; | ||
} | ||
|
||
export const ParameterChips: React.FC<ParameterChipsProps> = ({handleClick}) => { | ||
return ( | ||
<Box sx={{ marginBottom: 2, display:"flex", alignContent:"center", flexDirection:"column" }}> | ||
<Typography variant="overline" sx={{ marginBottom: 1 }} align="center">Filter by component</Typography> | ||
<Stack | ||
direction="row" | ||
spacing={2} | ||
flexWrap="wrap" | ||
useFlexGap | ||
divider={<Divider orientation="vertical" flexItem />} | ||
sx={{ marginBottom: 2 }} | ||
justifyContent={"center"} | ||
> | ||
{parameterGroups.map((component, index) => ( | ||
<Chip | ||
key={index} | ||
label={component} | ||
onClick={() => handleClick(component)} | ||
/> | ||
))} | ||
<Chip | ||
variant="outlined" | ||
label="Clear Filter" | ||
onClick={() => handleClick("")} | ||
icon={<ClearIcon />} | ||
/> | ||
</Stack> | ||
</Box> | ||
); | ||
}; |
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 |
---|---|---|
@@ -1,142 +1,108 @@ | ||
import { Box, Paper, Typography, Autocomplete, TextField, Divider, IconButton} from '@mui/material'; | ||
import {Link} from "@mui/icons-material"; | ||
import { Box, Typography, Autocomplete, TextField, Divider, IconButton} from '@mui/material'; | ||
import React, {useState, useMemo} from "react"; | ||
import { ParametersArray, ParameterDetail } from "../utils/types"; | ||
import { ParameterBox } from "./ParameterBox"; | ||
import { ParameterChips } from './ParameterChips'; | ||
import { Link } from "@mui/icons-material"; | ||
import { DarkLightContainer } from '@/utils/darkLightContainer'; | ||
|
||
interface ParameterDetail { | ||
components: string[]; | ||
default: boolean | string; | ||
description: string; | ||
name: string; | ||
type: string; | ||
} | ||
|
||
interface Parameter { | ||
[key: string]: ParameterDetail; | ||
} | ||
|
||
type ParametersArray = Parameter[]; | ||
|
||
const ParameterBox: React.FC<{ parameter: ParameterDetail }> = ({ parameter }) => { | ||
|
||
const Parameters: React.FC<{ parameters: ParametersArray }> = ({ parameters }) => { | ||
const [searchValue, setSearchValue] = useState(''); | ||
const [selectedComponent, setSelectedComponent] = useState<string | null>(null); | ||
const [hover, setHover] = useState(false); | ||
|
||
const parts = parameter.name.split('.'); | ||
const groupName = parts.length > 1 ? parts.slice(0, -1).join('.') : null; | ||
const parameterName = parts.length > 1 ? parts[parts.length - 1] : parameter.name; | ||
const parameterId = parameter.name.replace(".", "-") | ||
const filteredParameters = useMemo(() => { | ||
const searchLower = searchValue.toLowerCase(); | ||
return parameters.filter((parameter) => { | ||
const parameterName = Object.keys(parameter)[0].toLowerCase(); | ||
const detail = Object.values(parameter)[0]; | ||
|
||
// Ensure detail.components is defined and is an array before calling includes. | ||
const isComponentMatch = selectedComponent ? (Array.isArray(detail.components) && detail.components.includes(selectedComponent)) : true; | ||
return parameterName.includes(searchLower) && isComponentMatch; | ||
}); | ||
}, [searchValue, parameters, selectedComponent]); | ||
|
||
const groupedParameters = useMemo(() => { | ||
const groups: { [key: string]: ParameterDetail[] } = {}; | ||
filteredParameters.forEach((param) => { | ||
const detail = Object.values(param)[0]; | ||
const parent = detail.name.split('.').slice(0, -1).join('.'); | ||
const group = parent || ''; | ||
|
||
if (!groups[group]) { | ||
groups[group] = []; | ||
} | ||
groups[group].push(detail); | ||
}); | ||
return groups; | ||
}, [filteredParameters]); | ||
return ( | ||
<Box | ||
id={parameterId} | ||
sx={{ marginTop: ".8em" }} | ||
<DarkLightContainer> | ||
<Box> | ||
<Autocomplete | ||
disablePortal | ||
options={parameters.map((param) => Object.keys(param)[0])} | ||
onInputChange={(_, value) => setSearchValue(value)} | ||
sx={{ marginBottom: 2 }} | ||
fullWidth={true} | ||
freeSolo | ||
renderInput={(params) => ( | ||
<TextField | ||
{...params} | ||
label="Search..." | ||
value={searchValue} | ||
onChange={(event) => setSearchValue(event.target.value)} | ||
/> | ||
)} | ||
/> | ||
<ParameterChips handleClick={(component) => { | ||
setSelectedComponent(component); | ||
setSearchValue(''); | ||
}} /> | ||
{Object.entries(groupedParameters).map(([group, groupParams]) => ( | ||
<Box | ||
key={group} | ||
onMouseEnter={() => setHover(true)} | ||
onMouseLeave={() => setHover(false)} | ||
onClick={async () => { | ||
// Copy link to clipboard | ||
const url = new URL(window.location.href); | ||
url.hash = parameterId; | ||
await navigator.clipboard.writeText(url); | ||
url.hash = group | ||
await navigator.clipboard.writeText(url.toString()); | ||
}} | ||
> | ||
<Paper elevation={hover ? 3 : 1} sx={{ padding: "0.7em" }}> | ||
<Box mb={1}> | ||
<Box display={"flex"} justifyContent={"space-between"}> | ||
<Typography variant="h5" > | ||
{parameterName} | ||
</Typography> | ||
{hover && ( | ||
<IconButton size={"small"}> | ||
<Link fontSize={"small"}/> | ||
</IconButton> | ||
)} | ||
</Box> | ||
{/* If groupName exists, display it on a separate line */} | ||
{groupName && ( | ||
<Typography variant="subtitle2" component="div"> | ||
{groupName} | ||
</Typography> | ||
> | ||
<Typography | ||
sx={{ | ||
marginTop: ".5em" | ||
|
||
}} | ||
variant="h4" | ||
gutterBottom | ||
id={group} | ||
> | ||
{group} | ||
{hover && group && group !== "" && ( | ||
<IconButton size={"small"}> | ||
<Link fontSize={"small"}/> | ||
</IconButton> | ||
)} | ||
</Box> | ||
<Typography variant="body1" mb={1}> | ||
{parameter.description} | ||
</Typography> | ||
<Box p={1} bgcolor={"#e7e7e7"}> | ||
{parameter.components && ( | ||
<Typography variant="body2"> | ||
Components: [{parameter.components.join(", ")}] | ||
</Typography> | ||
)} | ||
<Typography variant="body2"> | ||
Type: {parameter.type} | ||
</Typography> | ||
<Typography variant="body2"> | ||
Default: {parameter.default === "" ? '""' : parameter.default.toString()} | ||
</Typography> | ||
</Box> | ||
</Paper> | ||
</Box> | ||
); | ||
}; | ||
|
||
const Parameters: React.FC<{ parameters: ParametersArray }> = ({ parameters }) => { | ||
const [searchValue, setSearchValue] = useState(''); | ||
|
||
const filteredParameters = useMemo(() => { | ||
const searchLower = searchValue.toLowerCase(); | ||
return parameters.filter((parameter) => { | ||
const parameterName = Object.keys(parameter)[0].toLowerCase(); | ||
return parameterName.includes(searchLower); | ||
}); | ||
}, [searchValue, parameters]); | ||
|
||
const groupedParameters = useMemo(() => { | ||
const groups: { [key: string]: ParameterDetail[] } = {}; | ||
filteredParameters.forEach((param) => { | ||
const detail = Object.values(param)[0]; | ||
const parent = detail.name.split('.').slice(0, -1).join('.'); | ||
const group = parent || ''; | ||
|
||
if (!groups[group]) { | ||
groups[group] = []; | ||
} | ||
groups[group].push(detail); | ||
}); | ||
return groups; | ||
}, [filteredParameters]); | ||
|
||
return ( | ||
<Box> | ||
<Autocomplete | ||
disablePortal | ||
options={parameters.map((param) => Object.keys(param)[0])} | ||
onInputChange={(_, value) => setSearchValue(value)} | ||
sx={{marginBottom: 2}} | ||
fullWidth={true} | ||
renderInput={(params) => ( | ||
<TextField | ||
{...params} | ||
label="Search..." | ||
value={searchValue} | ||
onChange={(event) => setSearchValue(event.target.value)} | ||
/> | ||
)} | ||
/> | ||
{Object.entries(groupedParameters).map(([group, groupParams]) => ( | ||
<React.Fragment key={group}> | ||
<Typography sx={{ marginTop: ".5em" }} variant="h4" gutterBottom>{group}</Typography> | ||
|
||
{group && group !== "" && ( | ||
<Divider sx={{ height: "0.5em", backgroundColor: "#0885ff", width: "100%", borderRadius: "0.5em" }} /> | ||
<Divider sx={{ height: "0.5em", backgroundColor: "#0885ff", width: "100%", borderRadius: "0.5em" }} /> | ||
)} | ||
{groupParams.map((param, index) => ( | ||
<ParameterBox key={index} parameter={param} /> | ||
<ParameterBox key={index} parameter={param} /> | ||
))} | ||
</React.Fragment> | ||
</Box> | ||
))} | ||
{filteredParameters.length === 0 && searchValue ? ( | ||
<Typography variant="h5">No results found</Typography> | ||
{filteredParameters.length === 0 && (searchValue || selectedComponent) ? ( | ||
<Typography variant="h5">No results found</Typography> | ||
) : null} | ||
</Box> | ||
); | ||
}; | ||
|
||
export default Parameters; | ||
</Box> | ||
</DarkLightContainer> | ||
); | ||
}; | ||
|
||
export default Parameters; |
Oops, something went wrong.