2020-02-07 16:12:01 +00:00
|
|
|
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
|
|
|
|
import MenuItem from "@material-ui/core/MenuItem";
|
2020-05-14 09:30:32 +00:00
|
|
|
import Paper from "@material-ui/core/Paper";
|
2020-02-07 16:12:01 +00:00
|
|
|
import Popper from "@material-ui/core/Popper";
|
|
|
|
import { fade } from "@material-ui/core/styles/colorManipulator";
|
2020-05-14 09:30:32 +00:00
|
|
|
import { FormChange } from "@saleor/hooks/useForm";
|
|
|
|
import ArrowDropdown from "@saleor/icons/ArrowDropdown";
|
2021-03-30 07:40:18 +00:00
|
|
|
import { makeStyles } from "@saleor/theme";
|
2020-02-07 16:12:01 +00:00
|
|
|
import classNames from "classnames";
|
|
|
|
import { codes } from "keycode";
|
2020-05-14 09:30:32 +00:00
|
|
|
import React from "react";
|
2020-02-07 16:12:01 +00:00
|
|
|
|
|
|
|
import Link from "../Link";
|
2020-05-14 09:30:32 +00:00
|
|
|
import { SingleAutocompleteChoiceType } from "../SingleAutocompleteSelectField";
|
2020-02-07 16:12:01 +00:00
|
|
|
|
|
|
|
const useStyles = makeStyles(
|
|
|
|
theme => ({
|
|
|
|
arrow: {
|
|
|
|
position: "relative",
|
|
|
|
top: 6,
|
|
|
|
transition: theme.transitions.duration.short + "ms"
|
|
|
|
},
|
|
|
|
highlighted: {
|
|
|
|
background: theme.palette.background.default
|
|
|
|
},
|
|
|
|
menuItem: {
|
|
|
|
"&:not(:last-of-type)": {
|
|
|
|
marginBottom: theme.spacing()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
paper: {
|
|
|
|
padding: theme.spacing()
|
|
|
|
},
|
|
|
|
popper: {
|
|
|
|
boxShadow: `0px 5px 10px 0 ${fade(theme.palette.common.black, 0.05)}`,
|
|
|
|
marginTop: theme.spacing(1),
|
|
|
|
zIndex: 2
|
|
|
|
},
|
|
|
|
root: {
|
|
|
|
"&:focus": {
|
|
|
|
textDecoration: "underline"
|
|
|
|
},
|
|
|
|
outline: 0,
|
|
|
|
position: "relative"
|
|
|
|
},
|
|
|
|
rotate: {
|
|
|
|
transform: "rotate(180deg)"
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
name: "LinkChoice"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
export interface LinkChoiceProps {
|
2020-02-07 16:44:42 +00:00
|
|
|
className?: string;
|
2020-02-07 16:12:01 +00:00
|
|
|
choices: SingleAutocompleteChoiceType[];
|
2020-02-07 16:44:42 +00:00
|
|
|
name?: string;
|
2020-02-07 16:12:01 +00:00
|
|
|
value: string;
|
|
|
|
onChange: FormChange;
|
|
|
|
}
|
|
|
|
|
|
|
|
const LinkChoice: React.FC<LinkChoiceProps> = ({
|
2020-02-07 16:44:42 +00:00
|
|
|
className,
|
2020-02-07 16:12:01 +00:00
|
|
|
choices,
|
|
|
|
name,
|
|
|
|
value,
|
|
|
|
onChange
|
|
|
|
}) => {
|
|
|
|
const classes = useStyles({});
|
|
|
|
const [open, setOpen] = React.useState(false);
|
|
|
|
const anchor = React.useRef<HTMLInputElement>(null);
|
|
|
|
const current = choices.find(c => c.value === value);
|
|
|
|
const [highlightedIndex, setHighlightedIndex] = React.useState(0);
|
|
|
|
|
|
|
|
const handleChange = (value: string) => {
|
|
|
|
setOpen(false);
|
|
|
|
onChange({
|
|
|
|
target: {
|
|
|
|
name,
|
|
|
|
value
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleKeyPress = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
|
|
switch (event.keyCode) {
|
|
|
|
case codes.down:
|
|
|
|
setHighlightedIndex(
|
|
|
|
highlightedIndex => (highlightedIndex + 1) % choices.length
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case codes.up:
|
|
|
|
setHighlightedIndex(highlightedIndex =>
|
|
|
|
highlightedIndex === 0
|
|
|
|
? choices.length - 1
|
|
|
|
: (highlightedIndex - 1) % choices.length
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case codes.enter:
|
|
|
|
if (open) {
|
|
|
|
handleChange(choices[highlightedIndex].value);
|
|
|
|
} else {
|
|
|
|
setOpen(true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<span
|
2020-02-07 16:44:42 +00:00
|
|
|
className={classNames(classes.root, className)}
|
2020-02-07 16:12:01 +00:00
|
|
|
ref={anchor}
|
|
|
|
onKeyDown={handleKeyPress}
|
|
|
|
tabIndex={0}
|
|
|
|
>
|
2020-04-29 14:14:20 +00:00
|
|
|
<Link onClick={() => setOpen(open => !open)}>
|
|
|
|
{current.label}
|
|
|
|
<ArrowDropdown
|
|
|
|
className={classNames(classes.arrow, {
|
|
|
|
[classes.rotate]: open
|
|
|
|
})}
|
|
|
|
color="primary"
|
|
|
|
/>
|
|
|
|
</Link>
|
2020-02-07 16:12:01 +00:00
|
|
|
|
|
|
|
<Popper
|
|
|
|
className={classes.popper}
|
|
|
|
open={open}
|
|
|
|
anchorEl={anchor.current}
|
|
|
|
transition
|
|
|
|
disablePortal
|
|
|
|
placement="bottom-start"
|
|
|
|
>
|
|
|
|
<ClickAwayListener
|
|
|
|
onClickAway={() => setOpen(false)}
|
|
|
|
mouseEvent="onClick"
|
|
|
|
>
|
|
|
|
<Paper className={classes.paper}>
|
|
|
|
{choices.map((choice, choiceIndex) => (
|
|
|
|
<MenuItem
|
|
|
|
className={classNames(classes.menuItem, {
|
|
|
|
[classes.highlighted]: highlightedIndex === choiceIndex
|
|
|
|
})}
|
|
|
|
selected={choice.value === value}
|
|
|
|
key={choice.value}
|
|
|
|
onClick={() => handleChange(choice.value)}
|
2020-07-02 10:59:09 +00:00
|
|
|
data-test="select-option"
|
2020-02-07 16:12:01 +00:00
|
|
|
>
|
|
|
|
{choice.label}
|
|
|
|
</MenuItem>
|
|
|
|
))}
|
|
|
|
</Paper>
|
|
|
|
</ClickAwayListener>
|
|
|
|
</Popper>
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
LinkChoice.displayName = "LinkChoice";
|
|
|
|
export default LinkChoice;
|