Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
163 lines
4.6 KiB
TypeScript
163 lines
4.6 KiB
TypeScript
import * as React from 'react';
|
|
import Grid from '@mui/material/Grid';
|
|
import List from '@mui/material/List';
|
|
import Card from '@mui/material/Card';
|
|
import CardHeader from '@mui/material/CardHeader';
|
|
import ListItemButton from '@mui/material/ListItemButton';
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
|
import Checkbox from '@mui/material/Checkbox';
|
|
import Button from '@mui/material/Button';
|
|
import Divider from '@mui/material/Divider';
|
|
|
|
function not(a: readonly number[], b: readonly number[]) {
|
|
return a.filter((value) => !b.includes(value));
|
|
}
|
|
|
|
function intersection(a: readonly number[], b: readonly number[]) {
|
|
return a.filter((value) => b.includes(value));
|
|
}
|
|
|
|
function union(a: readonly number[], b: readonly number[]) {
|
|
return [...a, ...not(b, a)];
|
|
}
|
|
|
|
export default function SelectAllTransferList() {
|
|
const [checked, setChecked] = React.useState<readonly number[]>([]);
|
|
const [left, setLeft] = React.useState<readonly number[]>([0, 1, 2, 3]);
|
|
const [right, setRight] = React.useState<readonly number[]>([4, 5, 6, 7]);
|
|
|
|
const leftChecked = intersection(checked, left);
|
|
const rightChecked = intersection(checked, right);
|
|
|
|
const handleToggle = (value: number) => () => {
|
|
const currentIndex = checked.indexOf(value);
|
|
const newChecked = [...checked];
|
|
|
|
if (currentIndex === -1) {
|
|
newChecked.push(value);
|
|
} else {
|
|
newChecked.splice(currentIndex, 1);
|
|
}
|
|
|
|
setChecked(newChecked);
|
|
};
|
|
|
|
const numberOfChecked = (items: readonly number[]) =>
|
|
intersection(checked, items).length;
|
|
|
|
const handleToggleAll = (items: readonly number[]) => () => {
|
|
if (numberOfChecked(items) === items.length) {
|
|
setChecked(not(checked, items));
|
|
} else {
|
|
setChecked(union(checked, items));
|
|
}
|
|
};
|
|
|
|
const handleCheckedRight = () => {
|
|
setRight(right.concat(leftChecked));
|
|
setLeft(not(left, leftChecked));
|
|
setChecked(not(checked, leftChecked));
|
|
};
|
|
|
|
const handleCheckedLeft = () => {
|
|
setLeft(left.concat(rightChecked));
|
|
setRight(not(right, rightChecked));
|
|
setChecked(not(checked, rightChecked));
|
|
};
|
|
|
|
const customList = (title: React.ReactNode, items: readonly number[]) => (
|
|
<Card>
|
|
<CardHeader
|
|
sx={{ px: 2, py: 1 }}
|
|
avatar={
|
|
<Checkbox
|
|
onClick={handleToggleAll(items)}
|
|
checked={numberOfChecked(items) === items.length && items.length !== 0}
|
|
indeterminate={
|
|
numberOfChecked(items) !== items.length && numberOfChecked(items) !== 0
|
|
}
|
|
disabled={items.length === 0}
|
|
inputProps={{
|
|
'aria-label': 'all items selected',
|
|
}}
|
|
/>
|
|
}
|
|
title={title}
|
|
subheader={`${numberOfChecked(items)}/${items.length} selected`}
|
|
/>
|
|
<Divider />
|
|
<List
|
|
sx={{
|
|
width: 200,
|
|
height: 230,
|
|
bgcolor: 'background.paper',
|
|
overflow: 'auto',
|
|
}}
|
|
dense
|
|
component="div"
|
|
role="list"
|
|
>
|
|
{items.map((value: number) => {
|
|
const labelId = `transfer-list-all-item-${value}-label`;
|
|
|
|
return (
|
|
<ListItemButton
|
|
key={value}
|
|
role="listitem"
|
|
onClick={handleToggle(value)}
|
|
>
|
|
<ListItemIcon>
|
|
<Checkbox
|
|
checked={checked.includes(value)}
|
|
tabIndex={-1}
|
|
disableRipple
|
|
inputProps={{
|
|
'aria-labelledby': labelId,
|
|
}}
|
|
/>
|
|
</ListItemIcon>
|
|
<ListItemText id={labelId} primary={`List item ${value + 1}`} />
|
|
</ListItemButton>
|
|
);
|
|
})}
|
|
</List>
|
|
</Card>
|
|
);
|
|
|
|
return (
|
|
<Grid
|
|
container
|
|
spacing={2}
|
|
sx={{ justifyContent: 'center', alignItems: 'center' }}
|
|
>
|
|
<Grid>{customList('Choices', left)}</Grid>
|
|
<Grid>
|
|
<Grid container direction="column" sx={{ alignItems: 'center' }}>
|
|
<Button
|
|
sx={{ my: 0.5 }}
|
|
variant="outlined"
|
|
size="small"
|
|
onClick={handleCheckedRight}
|
|
disabled={leftChecked.length === 0}
|
|
aria-label="move selected right"
|
|
>
|
|
>
|
|
</Button>
|
|
<Button
|
|
sx={{ my: 0.5 }}
|
|
variant="outlined"
|
|
size="small"
|
|
onClick={handleCheckedLeft}
|
|
disabled={rightChecked.length === 0}
|
|
aria-label="move selected left"
|
|
>
|
|
<
|
|
</Button>
|
|
</Grid>
|
|
</Grid>
|
|
<Grid>{customList('Chosen', right)}</Grid>
|
|
</Grid>
|
|
);
|
|
}
|