Refactor multi autocomplete ux
This commit is contained in:
parent
1f3d3be072
commit
6c44769629
10 changed files with 683 additions and 494 deletions
|
@ -0,0 +1,89 @@
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { countries } from "@saleor/fixtures";
|
||||||
|
import useMultiAutocomplete from "@saleor/hooks/useMultiAutocomplete";
|
||||||
|
import CardDecorator from "@saleor/storybook/CardDecorator";
|
||||||
|
import Decorator from "@saleor/storybook/Decorator";
|
||||||
|
import { ChoiceProvider } from "@saleor/storybook/mock";
|
||||||
|
import MultiAutocompleteSelectField, {
|
||||||
|
MultiAutocompleteSelectFieldProps
|
||||||
|
} from "./MultiAutocompleteSelectField";
|
||||||
|
import MultiAutocompleteSelectFieldContent, {
|
||||||
|
MultiAutocompleteSelectFieldContentProps
|
||||||
|
} from "./MultiAutocompleteSelectFieldContent";
|
||||||
|
|
||||||
|
const suggestions = countries.map(c => ({ label: c.name, value: c.code }));
|
||||||
|
|
||||||
|
const props: MultiAutocompleteSelectFieldProps = {
|
||||||
|
choices: undefined,
|
||||||
|
displayValues: [],
|
||||||
|
label: "Country",
|
||||||
|
loading: false,
|
||||||
|
name: "country",
|
||||||
|
onChange: () => undefined,
|
||||||
|
placeholder: "Select country",
|
||||||
|
value: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const Story: React.FC<
|
||||||
|
Partial<
|
||||||
|
MultiAutocompleteSelectFieldProps & {
|
||||||
|
enableLoadMore: boolean;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
> = storyProps => {
|
||||||
|
const { change, data: countries } = useMultiAutocomplete([suggestions[0]]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChoiceProvider choices={suggestions}>
|
||||||
|
{({ choices, fetchChoices, fetchMore, hasMore, loading }) => (
|
||||||
|
<MultiAutocompleteSelectField
|
||||||
|
{...props}
|
||||||
|
displayValues={countries}
|
||||||
|
choices={choices}
|
||||||
|
fetchChoices={fetchChoices}
|
||||||
|
helperText={`Value: ${countries
|
||||||
|
.map(country => country.value)
|
||||||
|
.join(", ")}`}
|
||||||
|
onChange={event => change(event, choices)}
|
||||||
|
value={countries.map(country => country.value)}
|
||||||
|
loading={loading}
|
||||||
|
hasMore={storyProps.enableLoadMore ? hasMore : false}
|
||||||
|
onFetchMore={storyProps.enableLoadMore ? fetchMore : undefined}
|
||||||
|
{...storyProps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ChoiceProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contentProps: MultiAutocompleteSelectFieldContentProps = {
|
||||||
|
choices: suggestions.slice(0, 10),
|
||||||
|
displayCustomValue: false,
|
||||||
|
displayValues: [suggestions[0]],
|
||||||
|
getItemProps: () => undefined,
|
||||||
|
hasMore: false,
|
||||||
|
highlightedIndex: 0,
|
||||||
|
inputValue: suggestions[0].label,
|
||||||
|
loading: false,
|
||||||
|
onFetchMore: () => undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Generics / Multiple select with autocomplete", module)
|
||||||
|
.addDecorator(CardDecorator)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("default", () => (
|
||||||
|
<MultiAutocompleteSelectFieldContent {...contentProps} />
|
||||||
|
))
|
||||||
|
.add("can load more", () => (
|
||||||
|
<MultiAutocompleteSelectFieldContent {...contentProps} hasMore={true} />
|
||||||
|
))
|
||||||
|
.add("no data", () => (
|
||||||
|
<MultiAutocompleteSelectFieldContent {...contentProps} choices={[]} />
|
||||||
|
))
|
||||||
|
.add("interactive", () => <Story />)
|
||||||
|
.add("interactive with custom option", () => (
|
||||||
|
<Story allowCustomValues={true} />
|
||||||
|
))
|
||||||
|
.add("interactive with load more", () => <Story enableLoadMore={true} />);
|
|
@ -1,7 +1,4 @@
|
||||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
|
||||||
import IconButton from "@material-ui/core/IconButton";
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
import MenuItem from "@material-ui/core/MenuItem";
|
|
||||||
import Paper from "@material-ui/core/Paper";
|
|
||||||
import {
|
import {
|
||||||
createStyles,
|
createStyles,
|
||||||
Theme,
|
Theme,
|
||||||
|
@ -13,26 +10,18 @@ import Typography from "@material-ui/core/Typography";
|
||||||
import CloseIcon from "@material-ui/icons/Close";
|
import CloseIcon from "@material-ui/icons/Close";
|
||||||
import Downshift, { ControllerStateAndHelpers } from "downshift";
|
import Downshift, { ControllerStateAndHelpers } from "downshift";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
import { compareTwoStrings } from "string-similarity";
|
import { compareTwoStrings } from "string-similarity";
|
||||||
|
|
||||||
import { fade } from "@material-ui/core/styles/colorManipulator";
|
import { fade } from "@material-ui/core/styles/colorManipulator";
|
||||||
import Checkbox from "@saleor/components/Checkbox";
|
|
||||||
import Debounce, { DebounceProps } from "@saleor/components/Debounce";
|
import Debounce, { DebounceProps } from "@saleor/components/Debounce";
|
||||||
import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown";
|
import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown";
|
||||||
import Hr from "../Hr";
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
import MultiAutocompleteSelectFieldContent, {
|
||||||
export interface MultiAutocompleteChoiceType {
|
MultiAutocompleteChoiceType
|
||||||
label: string;
|
} from "./MultiAutocompleteSelectFieldContent";
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
checkbox: {
|
|
||||||
height: 24,
|
|
||||||
width: 20
|
|
||||||
},
|
|
||||||
chip: {
|
chip: {
|
||||||
width: "100%"
|
width: "100%"
|
||||||
},
|
},
|
||||||
|
@ -66,49 +55,11 @@ const styles = (theme: Theme) =>
|
||||||
container: {
|
container: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
position: "relative"
|
position: "relative"
|
||||||
},
|
|
||||||
hr: {
|
|
||||||
margin: `${theme.spacing.unit}px 0`
|
|
||||||
},
|
|
||||||
menuItem: {
|
|
||||||
"&:focus": {
|
|
||||||
backgroundColor: [
|
|
||||||
theme.palette.background.default,
|
|
||||||
"!important"
|
|
||||||
] as any,
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
fontWeight: 400
|
|
||||||
},
|
|
||||||
"&:hover": {
|
|
||||||
backgroundColor: [
|
|
||||||
theme.palette.background.default,
|
|
||||||
"!important"
|
|
||||||
] as any,
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
fontWeight: 700
|
|
||||||
},
|
|
||||||
borderRadius: 4,
|
|
||||||
display: "grid",
|
|
||||||
gridColumnGap: theme.spacing.unit + "px",
|
|
||||||
gridTemplateColumns: "30px 1fr",
|
|
||||||
height: "auto",
|
|
||||||
padding: 0,
|
|
||||||
whiteSpace: "normal"
|
|
||||||
},
|
|
||||||
menuItemLabel: {
|
|
||||||
overflowWrap: "break-word"
|
|
||||||
},
|
|
||||||
paper: {
|
|
||||||
left: 0,
|
|
||||||
marginTop: theme.spacing.unit,
|
|
||||||
padding: theme.spacing.unit,
|
|
||||||
position: "absolute",
|
|
||||||
right: 0,
|
|
||||||
zIndex: 2
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface MultiAutocompleteSelectFieldProps {
|
export interface MultiAutocompleteSelectFieldProps
|
||||||
|
extends Partial<FetchMoreProps> {
|
||||||
allowCustomValues?: boolean;
|
allowCustomValues?: boolean;
|
||||||
displayValues: MultiAutocompleteChoiceType[];
|
displayValues: MultiAutocompleteChoiceType[];
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -134,6 +85,7 @@ export const MultiAutocompleteSelectFieldComponent = withStyles(styles, {
|
||||||
choices,
|
choices,
|
||||||
classes,
|
classes,
|
||||||
displayValues,
|
displayValues,
|
||||||
|
hasMore,
|
||||||
helperText,
|
helperText,
|
||||||
label,
|
label,
|
||||||
loading,
|
loading,
|
||||||
|
@ -142,6 +94,7 @@ export const MultiAutocompleteSelectFieldComponent = withStyles(styles, {
|
||||||
value,
|
value,
|
||||||
fetchChoices,
|
fetchChoices,
|
||||||
onChange,
|
onChange,
|
||||||
|
onFetchMore,
|
||||||
...props
|
...props
|
||||||
}: MultiAutocompleteSelectFieldProps & WithStyles<typeof styles>) => {
|
}: MultiAutocompleteSelectFieldProps & WithStyles<typeof styles>) => {
|
||||||
const handleSelect = (
|
const handleSelect = (
|
||||||
|
@ -155,7 +108,6 @@ export const MultiAutocompleteSelectFieldComponent = withStyles(styles, {
|
||||||
target: { name, value: item }
|
target: { name, value: item }
|
||||||
} as any);
|
} as any);
|
||||||
};
|
};
|
||||||
const suggestions = choices.filter(choice => !value.includes(choice.value));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -171,123 +123,53 @@ export const MultiAutocompleteSelectFieldComponent = withStyles(styles, {
|
||||||
toggleMenu,
|
toggleMenu,
|
||||||
highlightedIndex,
|
highlightedIndex,
|
||||||
inputValue
|
inputValue
|
||||||
}) => (
|
}) => {
|
||||||
<div className={classes.container} {...props}>
|
const displayCustomValue =
|
||||||
<TextField
|
inputValue &&
|
||||||
InputProps={{
|
inputValue.length > 0 &&
|
||||||
...getInputProps({
|
allowCustomValues &&
|
||||||
placeholder
|
!choices.find(
|
||||||
}),
|
choice =>
|
||||||
endAdornment: (
|
choice.label.toLowerCase() === inputValue.toLowerCase()
|
||||||
<div>
|
);
|
||||||
{loading ? (
|
|
||||||
<CircularProgress size={20} />
|
return (
|
||||||
) : (
|
<div className={classes.container} {...props}>
|
||||||
|
<TextField
|
||||||
|
InputProps={{
|
||||||
|
...getInputProps({
|
||||||
|
placeholder
|
||||||
|
}),
|
||||||
|
endAdornment: (
|
||||||
|
<div>
|
||||||
<ArrowDropdownIcon onClick={toggleMenu} />
|
<ArrowDropdownIcon onClick={toggleMenu} />
|
||||||
)}
|
</div>
|
||||||
</div>
|
),
|
||||||
),
|
id: undefined,
|
||||||
id: undefined,
|
onClick: toggleMenu
|
||||||
onClick: toggleMenu
|
}}
|
||||||
}}
|
helperText={helperText}
|
||||||
helperText={helperText}
|
label={label}
|
||||||
label={label}
|
fullWidth={true}
|
||||||
fullWidth={true}
|
/>
|
||||||
/>
|
{isOpen && (!!inputValue || !!choices.length) && (
|
||||||
{isOpen && (!!inputValue || !!choices.length) && (
|
<MultiAutocompleteSelectFieldContent
|
||||||
<Paper className={classes.paper} square>
|
choices={choices.filter(
|
||||||
{choices.length > 0 ||
|
choice => !value.includes(choice.value)
|
||||||
displayValues.length > 0 ||
|
)}
|
||||||
allowCustomValues ? (
|
displayCustomValue={displayCustomValue}
|
||||||
<>
|
displayValues={displayValues}
|
||||||
{displayValues.map(value => (
|
getItemProps={getItemProps}
|
||||||
<MenuItem
|
hasMore={hasMore}
|
||||||
className={classes.menuItem}
|
highlightedIndex={highlightedIndex}
|
||||||
key={value.value}
|
loading={loading}
|
||||||
selected={true}
|
inputValue={inputValue}
|
||||||
component="div"
|
onFetchMore={onFetchMore}
|
||||||
{...getItemProps({
|
/>
|
||||||
item: value.value
|
)}
|
||||||
})}
|
</div>
|
||||||
data-tc="multiautocomplete-select-option"
|
);
|
||||||
>
|
}}
|
||||||
<Checkbox
|
|
||||||
className={classes.checkbox}
|
|
||||||
checked={true}
|
|
||||||
disableRipple
|
|
||||||
/>
|
|
||||||
<span className={classes.menuItemLabel}>
|
|
||||||
{value.label}
|
|
||||||
</span>
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
{displayValues.length > 0 && suggestions.length > 0 && (
|
|
||||||
<Hr className={classes.hr} />
|
|
||||||
)}
|
|
||||||
{suggestions.map((suggestion, index) => (
|
|
||||||
<MenuItem
|
|
||||||
className={classes.menuItem}
|
|
||||||
key={suggestion.value}
|
|
||||||
selected={highlightedIndex === index + value.length}
|
|
||||||
component="div"
|
|
||||||
{...getItemProps({
|
|
||||||
item: suggestion.value
|
|
||||||
})}
|
|
||||||
data-tc="multiautocomplete-select-option"
|
|
||||||
>
|
|
||||||
<Checkbox
|
|
||||||
checked={value.includes(suggestion.value)}
|
|
||||||
className={classes.checkbox}
|
|
||||||
disableRipple
|
|
||||||
/>
|
|
||||||
<span className={classes.menuItemLabel}>
|
|
||||||
{suggestion.label}
|
|
||||||
</span>
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
{allowCustomValues &&
|
|
||||||
inputValue &&
|
|
||||||
!choices.find(
|
|
||||||
choice =>
|
|
||||||
choice.label.toLowerCase() ===
|
|
||||||
inputValue.toLowerCase()
|
|
||||||
) && (
|
|
||||||
<MenuItem
|
|
||||||
className={classes.menuItem}
|
|
||||||
key={"customValue"}
|
|
||||||
component="div"
|
|
||||||
{...getItemProps({
|
|
||||||
item: inputValue
|
|
||||||
})}
|
|
||||||
data-tc="multiautocomplete-select-option"
|
|
||||||
>
|
|
||||||
<span className={classes.menuItemLabel}>
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Add new value: {value}"
|
|
||||||
description="add custom option to select input"
|
|
||||||
values={{
|
|
||||||
value: inputValue
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
!loading && (
|
|
||||||
<MenuItem
|
|
||||||
disabled={true}
|
|
||||||
component="div"
|
|
||||||
data-tc="multiautocomplete-select-no-options"
|
|
||||||
>
|
|
||||||
<FormattedMessage defaultMessage="No results found" />
|
|
||||||
</MenuItem>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Paper>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Downshift>
|
</Downshift>
|
||||||
<div className={classes.chipContainer}>
|
<div className={classes.chipContainer}>
|
||||||
{displayValues.map(value => (
|
{displayValues.map(value => (
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
|
import MenuItem from "@material-ui/core/MenuItem";
|
||||||
|
import Paper from "@material-ui/core/Paper";
|
||||||
|
import { Theme } from "@material-ui/core/styles";
|
||||||
|
import AddIcon from "@material-ui/icons/Add";
|
||||||
|
import { makeStyles } from "@material-ui/styles";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { GetItemPropsOptions } from "downshift";
|
||||||
|
import React from "react";
|
||||||
|
import SVG from "react-inlinesvg";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
import chevronDown from "@assets/images/ChevronDown.svg";
|
||||||
|
import Checkbox from "@saleor/components/Checkbox";
|
||||||
|
import useElementScroll, {
|
||||||
|
isScrolledToBottom
|
||||||
|
} from "@saleor/hooks/useElementScroll";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
import Hr from "../Hr";
|
||||||
|
|
||||||
|
const menuItemHeight = 46;
|
||||||
|
const maxMenuItems = 5;
|
||||||
|
const offset = 24;
|
||||||
|
|
||||||
|
export interface MultiAutocompleteChoiceType {
|
||||||
|
label: string;
|
||||||
|
value: any;
|
||||||
|
}
|
||||||
|
export interface MultiAutocompleteSelectFieldContentProps
|
||||||
|
extends Partial<FetchMoreProps> {
|
||||||
|
choices: MultiAutocompleteChoiceType[];
|
||||||
|
displayCustomValue: boolean;
|
||||||
|
displayValues: MultiAutocompleteChoiceType[];
|
||||||
|
getItemProps: (options: GetItemPropsOptions) => void;
|
||||||
|
highlightedIndex: number;
|
||||||
|
inputValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
(theme: Theme) => ({
|
||||||
|
addIcon: {
|
||||||
|
height: 24,
|
||||||
|
margin: 9,
|
||||||
|
width: 20
|
||||||
|
},
|
||||||
|
arrowContainer: {
|
||||||
|
position: "relative"
|
||||||
|
},
|
||||||
|
arrowInnerContainer: {
|
||||||
|
alignItems: "center",
|
||||||
|
background: theme.palette.grey[50],
|
||||||
|
bottom: 0,
|
||||||
|
display: "flex",
|
||||||
|
height: 30,
|
||||||
|
justifyContent: "center",
|
||||||
|
opacity: 1,
|
||||||
|
position: "absolute",
|
||||||
|
transition: theme.transitions.duration.short + "ms",
|
||||||
|
width: "100%"
|
||||||
|
},
|
||||||
|
checkbox: {
|
||||||
|
height: 24,
|
||||||
|
width: 20
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
maxHeight: menuItemHeight * maxMenuItems + theme.spacing.unit * 2,
|
||||||
|
overflow: "scroll",
|
||||||
|
padding: 8
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
opacity: 0
|
||||||
|
},
|
||||||
|
hr: {
|
||||||
|
margin: `${theme.spacing.unit}px 0`
|
||||||
|
},
|
||||||
|
menuItem: {
|
||||||
|
"&:focus": {
|
||||||
|
backgroundColor: [
|
||||||
|
theme.palette.background.default,
|
||||||
|
"!important"
|
||||||
|
] as any,
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
fontWeight: 400
|
||||||
|
},
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: [
|
||||||
|
theme.palette.background.default,
|
||||||
|
"!important"
|
||||||
|
] as any,
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
fontWeight: 700
|
||||||
|
},
|
||||||
|
borderRadius: 4,
|
||||||
|
display: "grid",
|
||||||
|
gridColumnGap: theme.spacing.unit + "px",
|
||||||
|
gridTemplateColumns: "30px 1fr",
|
||||||
|
height: "auto",
|
||||||
|
padding: 0,
|
||||||
|
whiteSpace: "normal"
|
||||||
|
},
|
||||||
|
menuItemLabel: {
|
||||||
|
overflowWrap: "break-word"
|
||||||
|
},
|
||||||
|
progress: {},
|
||||||
|
progressContainer: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center"
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8,
|
||||||
|
left: 0,
|
||||||
|
marginTop: theme.spacing.unit,
|
||||||
|
overflow: "hidden",
|
||||||
|
position: "absolute",
|
||||||
|
right: 0,
|
||||||
|
zIndex: 22
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "MultiAutocompleteSelectFieldContent"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function getChoiceIndex(
|
||||||
|
index: number,
|
||||||
|
displayValues: MultiAutocompleteChoiceType[],
|
||||||
|
displayCustomValue: boolean
|
||||||
|
) {
|
||||||
|
let choiceIndex = index;
|
||||||
|
if (displayCustomValue) {
|
||||||
|
choiceIndex += 2;
|
||||||
|
}
|
||||||
|
if (displayValues.length > 0) {
|
||||||
|
choiceIndex += 1 + displayValues.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return choiceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MultiAutocompleteSelectFieldContent: React.FC<
|
||||||
|
MultiAutocompleteSelectFieldContentProps
|
||||||
|
> = props => {
|
||||||
|
const {
|
||||||
|
choices,
|
||||||
|
displayCustomValue,
|
||||||
|
displayValues,
|
||||||
|
getItemProps,
|
||||||
|
hasMore,
|
||||||
|
highlightedIndex,
|
||||||
|
loading,
|
||||||
|
inputValue,
|
||||||
|
onFetchMore
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const classes = useStyles(props);
|
||||||
|
const anchor = React.useRef<HTMLDivElement>();
|
||||||
|
const scrollPosition = useElementScroll(anchor);
|
||||||
|
const [calledForMore, setCalledForMore] = React.useState(false);
|
||||||
|
|
||||||
|
const scrolledToBottom = isScrolledToBottom(anchor, scrollPosition, offset);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!calledForMore && onFetchMore && scrolledToBottom) {
|
||||||
|
onFetchMore();
|
||||||
|
setCalledForMore(true);
|
||||||
|
}
|
||||||
|
}, [scrolledToBottom]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (calledForMore && !loading) {
|
||||||
|
setCalledForMore(false);
|
||||||
|
}
|
||||||
|
}, [loading]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper className={classes.root}>
|
||||||
|
<div className={classes.content} ref={anchor}>
|
||||||
|
{choices.length > 0 || displayCustomValue ? (
|
||||||
|
<>
|
||||||
|
{displayCustomValue && (
|
||||||
|
<MenuItem
|
||||||
|
className={classes.menuItem}
|
||||||
|
key="customValue"
|
||||||
|
component="div"
|
||||||
|
{...getItemProps({
|
||||||
|
item: inputValue
|
||||||
|
})}
|
||||||
|
data-tc="multiautocomplete-select-option"
|
||||||
|
>
|
||||||
|
<AddIcon className={classes.addIcon} color="primary" />
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Add new value: {value}"
|
||||||
|
description="add custom select input option"
|
||||||
|
values={{
|
||||||
|
value: inputValue
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{(choices.length > 0 || displayValues.length > 0) &&
|
||||||
|
displayCustomValue && <Hr className={classes.hr} />}
|
||||||
|
{displayValues.map(value => (
|
||||||
|
<MenuItem
|
||||||
|
className={classes.menuItem}
|
||||||
|
key={value.value}
|
||||||
|
selected={true}
|
||||||
|
component="div"
|
||||||
|
{...getItemProps({
|
||||||
|
item: value.value
|
||||||
|
})}
|
||||||
|
data-tc="multiautocomplete-select-option"
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
className={classes.checkbox}
|
||||||
|
checked={true}
|
||||||
|
disableRipple
|
||||||
|
/>
|
||||||
|
<span className={classes.menuItemLabel}>{value.label}</span>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
{displayValues.length > 0 && choices.length > 0 && (
|
||||||
|
<Hr className={classes.hr} />
|
||||||
|
)}
|
||||||
|
{choices.map((suggestion, index) => {
|
||||||
|
const choiceIndex = getChoiceIndex(
|
||||||
|
index,
|
||||||
|
displayValues,
|
||||||
|
displayCustomValue
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
className={classes.menuItem}
|
||||||
|
key={suggestion.value}
|
||||||
|
selected={highlightedIndex === choiceIndex}
|
||||||
|
component="div"
|
||||||
|
{...getItemProps({
|
||||||
|
index: choiceIndex,
|
||||||
|
item: suggestion.value
|
||||||
|
})}
|
||||||
|
data-tc="multiautocomplete-select-option"
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={false}
|
||||||
|
className={classes.checkbox}
|
||||||
|
disableRipple
|
||||||
|
/>
|
||||||
|
<span className={classes.menuItemLabel}>
|
||||||
|
{suggestion.label}
|
||||||
|
</span>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{hasMore && (
|
||||||
|
<>
|
||||||
|
<Hr className={classes.hr} />
|
||||||
|
<div className={classes.progressContainer}>
|
||||||
|
<CircularProgress className={classes.progress} size={24} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<MenuItem
|
||||||
|
disabled={true}
|
||||||
|
component="div"
|
||||||
|
data-tc="multiautocomplete-select-no-options"
|
||||||
|
>
|
||||||
|
<FormattedMessage defaultMessage="No results found" />
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={classes.arrowContainer}>
|
||||||
|
<div
|
||||||
|
className={classNames(classes.arrowInnerContainer, {
|
||||||
|
// Needs to be explicitely compared to false because
|
||||||
|
// scrolledToBottom can be either true, false or undefined
|
||||||
|
[classes.hide]: scrolledToBottom !== false
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<SVG src={chevronDown} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiAutocompleteSelectFieldContent.displayName =
|
||||||
|
"MultiAutocompleteSelectFieldContent";
|
||||||
|
export default MultiAutocompleteSelectFieldContent;
|
|
@ -1,2 +1,3 @@
|
||||||
export { default } from "./MultiAutocompleteSelectField";
|
export { default } from "./MultiAutocompleteSelectField";
|
||||||
export * from "./MultiAutocompleteSelectField";
|
export * from "./MultiAutocompleteSelectField";
|
||||||
|
export * from "./MultiAutocompleteSelectFieldContent";
|
||||||
|
|
|
@ -2,11 +2,11 @@ import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
|
import { countries } from "@saleor/fixtures";
|
||||||
import CardDecorator from "@saleor/storybook/CardDecorator";
|
import CardDecorator from "@saleor/storybook/CardDecorator";
|
||||||
import Decorator from "@saleor/storybook/Decorator";
|
import Decorator from "@saleor/storybook/Decorator";
|
||||||
import { ChoiceProvider } from "@saleor/storybook/mock";
|
import { ChoiceProvider } from "@saleor/storybook/mock";
|
||||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||||
import { countries } from "./fixtures";
|
|
||||||
import SingleAutocompleteSelectField, {
|
import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteSelectFieldProps
|
SingleAutocompleteSelectFieldProps
|
||||||
} from "./SingleAutocompleteSelectField";
|
} from "./SingleAutocompleteSelectField";
|
||||||
|
|
|
@ -1,245 +0,0 @@
|
||||||
export const countries = [
|
|
||||||
{ name: "Afghanistan", code: "AF" },
|
|
||||||
{ name: "Åland Islands", code: "AX" },
|
|
||||||
{ name: "Albania", code: "AL" },
|
|
||||||
{ name: "Algeria", code: "DZ" },
|
|
||||||
{ name: "American Samoa", code: "AS" },
|
|
||||||
{ name: "AndorrA", code: "AD" },
|
|
||||||
{ name: "Angola", code: "AO" },
|
|
||||||
{ name: "Anguilla", code: "AI" },
|
|
||||||
{ name: "Antarctica", code: "AQ" },
|
|
||||||
{ name: "Antigua and Barbuda", code: "AG" },
|
|
||||||
{ name: "Argentina", code: "AR" },
|
|
||||||
{ name: "Armenia", code: "AM" },
|
|
||||||
{ name: "Aruba", code: "AW" },
|
|
||||||
{ name: "Australia", code: "AU" },
|
|
||||||
{ name: "Austria", code: "AT" },
|
|
||||||
{ name: "Azerbaijan", code: "AZ" },
|
|
||||||
{ name: "Bahamas", code: "BS" },
|
|
||||||
{ name: "Bahrain", code: "BH" },
|
|
||||||
{ name: "Bangladesh", code: "BD" },
|
|
||||||
{ name: "Barbados", code: "BB" },
|
|
||||||
{ name: "Belarus", code: "BY" },
|
|
||||||
{ name: "Belgium", code: "BE" },
|
|
||||||
{ name: "Belize", code: "BZ" },
|
|
||||||
{ name: "Benin", code: "BJ" },
|
|
||||||
{ name: "Bermuda", code: "BM" },
|
|
||||||
{ name: "Bhutan", code: "BT" },
|
|
||||||
{ name: "Bolivia", code: "BO" },
|
|
||||||
{ name: "Bosnia and Herzegovina", code: "BA" },
|
|
||||||
{ name: "Botswana", code: "BW" },
|
|
||||||
{ name: "Bouvet Island", code: "BV" },
|
|
||||||
{ name: "Brazil", code: "BR" },
|
|
||||||
{ name: "British Indian Ocean Territory", code: "IO" },
|
|
||||||
{ name: "Brunei Darussalam", code: "BN" },
|
|
||||||
{ name: "Bulgaria", code: "BG" },
|
|
||||||
{ name: "Burkina Faso", code: "BF" },
|
|
||||||
{ name: "Burundi", code: "BI" },
|
|
||||||
{ name: "Cambodia", code: "KH" },
|
|
||||||
{ name: "Cameroon", code: "CM" },
|
|
||||||
{ name: "Canada", code: "CA" },
|
|
||||||
{ name: "Cape Verde", code: "CV" },
|
|
||||||
{ name: "Cayman Islands", code: "KY" },
|
|
||||||
{ name: "Central African Republic", code: "CF" },
|
|
||||||
{ name: "Chad", code: "TD" },
|
|
||||||
{ name: "Chile", code: "CL" },
|
|
||||||
{ name: "China", code: "CN" },
|
|
||||||
{ name: "Christmas Island", code: "CX" },
|
|
||||||
{ name: "Cocos (Keeling) Islands", code: "CC" },
|
|
||||||
{ name: "Colombia", code: "CO" },
|
|
||||||
{ name: "Comoros", code: "KM" },
|
|
||||||
{ name: "Congo", code: "CG" },
|
|
||||||
{ name: "Congo, The Democratic Republic of the", code: "CD" },
|
|
||||||
{ name: "Cook Islands", code: "CK" },
|
|
||||||
{ name: "Costa Rica", code: "CR" },
|
|
||||||
{ name: "Cote D'Ivoire", code: "CI" },
|
|
||||||
{ name: "Croatia", code: "HR" },
|
|
||||||
{ name: "Cuba", code: "CU" },
|
|
||||||
{ name: "Cyprus", code: "CY" },
|
|
||||||
{ name: "Czech Republic", code: "CZ" },
|
|
||||||
{ name: "Denmark", code: "DK" },
|
|
||||||
{ name: "Djibouti", code: "DJ" },
|
|
||||||
{ name: "Dominica", code: "DM" },
|
|
||||||
{ name: "Dominican Republic", code: "DO" },
|
|
||||||
{ name: "Ecuador", code: "EC" },
|
|
||||||
{ name: "Egypt", code: "EG" },
|
|
||||||
{ name: "El Salvador", code: "SV" },
|
|
||||||
{ name: "Equatorial Guinea", code: "GQ" },
|
|
||||||
{ name: "Eritrea", code: "ER" },
|
|
||||||
{ name: "Estonia", code: "EE" },
|
|
||||||
{ name: "Ethiopia", code: "ET" },
|
|
||||||
{ name: "Falkland Islands (Malvinas)", code: "FK" },
|
|
||||||
{ name: "Faroe Islands", code: "FO" },
|
|
||||||
{ name: "Fiji", code: "FJ" },
|
|
||||||
{ name: "Finland", code: "FI" },
|
|
||||||
{ name: "France", code: "FR" },
|
|
||||||
{ name: "French Guiana", code: "GF" },
|
|
||||||
{ name: "French Polynesia", code: "PF" },
|
|
||||||
{ name: "French Southern Territories", code: "TF" },
|
|
||||||
{ name: "Gabon", code: "GA" },
|
|
||||||
{ name: "Gambia", code: "GM" },
|
|
||||||
{ name: "Georgia", code: "GE" },
|
|
||||||
{ name: "Germany", code: "DE" },
|
|
||||||
{ name: "Ghana", code: "GH" },
|
|
||||||
{ name: "Gibraltar", code: "GI" },
|
|
||||||
{ name: "Greece", code: "GR" },
|
|
||||||
{ name: "Greenland", code: "GL" },
|
|
||||||
{ name: "Grenada", code: "GD" },
|
|
||||||
{ name: "Guadeloupe", code: "GP" },
|
|
||||||
{ name: "Guam", code: "GU" },
|
|
||||||
{ name: "Guatemala", code: "GT" },
|
|
||||||
{ name: "Guernsey", code: "GG" },
|
|
||||||
{ name: "Guinea", code: "GN" },
|
|
||||||
{ name: "Guinea-Bissau", code: "GW" },
|
|
||||||
{ name: "Guyana", code: "GY" },
|
|
||||||
{ name: "Haiti", code: "HT" },
|
|
||||||
{ name: "Heard Island and Mcdonald Islands", code: "HM" },
|
|
||||||
{ name: "Holy See (Vatican City State)", code: "VA" },
|
|
||||||
{ name: "Honduras", code: "HN" },
|
|
||||||
{ name: "Hong Kong", code: "HK" },
|
|
||||||
{ name: "Hungary", code: "HU" },
|
|
||||||
{ name: "Iceland", code: "IS" },
|
|
||||||
{ name: "India", code: "IN" },
|
|
||||||
{ name: "Indonesia", code: "ID" },
|
|
||||||
{ name: "Iran, Islamic Republic Of", code: "IR" },
|
|
||||||
{ name: "Iraq", code: "IQ" },
|
|
||||||
{ name: "Ireland", code: "IE" },
|
|
||||||
{ name: "Isle of Man", code: "IM" },
|
|
||||||
{ name: "Israel", code: "IL" },
|
|
||||||
{ name: "Italy", code: "IT" },
|
|
||||||
{ name: "Jamaica", code: "JM" },
|
|
||||||
{ name: "Japan", code: "JP" },
|
|
||||||
{ name: "Jersey", code: "JE" },
|
|
||||||
{ name: "Jordan", code: "JO" },
|
|
||||||
{ name: "Kazakhstan", code: "KZ" },
|
|
||||||
{ name: "Kenya", code: "KE" },
|
|
||||||
{ name: "Kiribati", code: "KI" },
|
|
||||||
{ name: "Korea, Democratic People'S Republic of", code: "KP" },
|
|
||||||
{ name: "Korea, Republic of", code: "KR" },
|
|
||||||
{ name: "Kuwait", code: "KW" },
|
|
||||||
{ name: "Kyrgyzstan", code: "KG" },
|
|
||||||
{ name: "Lao People'S Democratic Republic", code: "LA" },
|
|
||||||
{ name: "Latvia", code: "LV" },
|
|
||||||
{ name: "Lebanon", code: "LB" },
|
|
||||||
{ name: "Lesotho", code: "LS" },
|
|
||||||
{ name: "Liberia", code: "LR" },
|
|
||||||
{ name: "Libyan Arab Jamahiriya", code: "LY" },
|
|
||||||
{ name: "Liechtenstein", code: "LI" },
|
|
||||||
{ name: "Lithuania", code: "LT" },
|
|
||||||
{ name: "Luxembourg", code: "LU" },
|
|
||||||
{ name: "Macao", code: "MO" },
|
|
||||||
{ name: "Macedonia, The Former Yugoslav Republic of", code: "MK" },
|
|
||||||
{ name: "Madagascar", code: "MG" },
|
|
||||||
{ name: "Malawi", code: "MW" },
|
|
||||||
{ name: "Malaysia", code: "MY" },
|
|
||||||
{ name: "Maldives", code: "MV" },
|
|
||||||
{ name: "Mali", code: "ML" },
|
|
||||||
{ name: "Malta", code: "MT" },
|
|
||||||
{ name: "Marshall Islands", code: "MH" },
|
|
||||||
{ name: "Martinique", code: "MQ" },
|
|
||||||
{ name: "Mauritania", code: "MR" },
|
|
||||||
{ name: "Mauritius", code: "MU" },
|
|
||||||
{ name: "Mayotte", code: "YT" },
|
|
||||||
{ name: "Mexico", code: "MX" },
|
|
||||||
{ name: "Micronesia, Federated States of", code: "FM" },
|
|
||||||
{ name: "Moldova, Republic of", code: "MD" },
|
|
||||||
{ name: "Monaco", code: "MC" },
|
|
||||||
{ name: "Mongolia", code: "MN" },
|
|
||||||
{ name: "Montserrat", code: "MS" },
|
|
||||||
{ name: "Morocco", code: "MA" },
|
|
||||||
{ name: "Mozambique", code: "MZ" },
|
|
||||||
{ name: "Myanmar", code: "MM" },
|
|
||||||
{ name: "Namibia", code: "NA" },
|
|
||||||
{ name: "Nauru", code: "NR" },
|
|
||||||
{ name: "Nepal", code: "NP" },
|
|
||||||
{ name: "Netherlands", code: "NL" },
|
|
||||||
{ name: "Netherlands Antilles", code: "AN" },
|
|
||||||
{ name: "New Caledonia", code: "NC" },
|
|
||||||
{ name: "New Zealand", code: "NZ" },
|
|
||||||
{ name: "Nicaragua", code: "NI" },
|
|
||||||
{ name: "Niger", code: "NE" },
|
|
||||||
{ name: "Nigeria", code: "NG" },
|
|
||||||
{ name: "Niue", code: "NU" },
|
|
||||||
{ name: "Norfolk Island", code: "NF" },
|
|
||||||
{ name: "Northern Mariana Islands", code: "MP" },
|
|
||||||
{ name: "Norway", code: "NO" },
|
|
||||||
{ name: "Oman", code: "OM" },
|
|
||||||
{ name: "Pakistan", code: "PK" },
|
|
||||||
{ name: "Palau", code: "PW" },
|
|
||||||
{ name: "Palestinian Territory, Occupied", code: "PS" },
|
|
||||||
{ name: "Panama", code: "PA" },
|
|
||||||
{ name: "Papua New Guinea", code: "PG" },
|
|
||||||
{ name: "Paraguay", code: "PY" },
|
|
||||||
{ name: "Peru", code: "PE" },
|
|
||||||
{ name: "Philippines", code: "PH" },
|
|
||||||
{ name: "Pitcairn", code: "PN" },
|
|
||||||
{ name: "Poland", code: "PL" },
|
|
||||||
{ name: "Portugal", code: "PT" },
|
|
||||||
{ name: "Puerto Rico", code: "PR" },
|
|
||||||
{ name: "Qatar", code: "QA" },
|
|
||||||
{ name: "Reunion", code: "RE" },
|
|
||||||
{ name: "Romania", code: "RO" },
|
|
||||||
{ name: "Russian Federation", code: "RU" },
|
|
||||||
{ name: "RWANDA", code: "RW" },
|
|
||||||
{ name: "Saint Helena", code: "SH" },
|
|
||||||
{ name: "Saint Kitts and Nevis", code: "KN" },
|
|
||||||
{ name: "Saint Lucia", code: "LC" },
|
|
||||||
{ name: "Saint Pierre and Miquelon", code: "PM" },
|
|
||||||
{ name: "Saint Vincent and the Grenadines", code: "VC" },
|
|
||||||
{ name: "Samoa", code: "WS" },
|
|
||||||
{ name: "San Marino", code: "SM" },
|
|
||||||
{ name: "Sao Tome and Principe", code: "ST" },
|
|
||||||
{ name: "Saudi Arabia", code: "SA" },
|
|
||||||
{ name: "Senegal", code: "SN" },
|
|
||||||
{ name: "Serbia and Montenegro", code: "CS" },
|
|
||||||
{ name: "Seychelles", code: "SC" },
|
|
||||||
{ name: "Sierra Leone", code: "SL" },
|
|
||||||
{ name: "Singapore", code: "SG" },
|
|
||||||
{ name: "Slovakia", code: "SK" },
|
|
||||||
{ name: "Slovenia", code: "SI" },
|
|
||||||
{ name: "Solomon Islands", code: "SB" },
|
|
||||||
{ name: "Somalia", code: "SO" },
|
|
||||||
{ name: "South Africa", code: "ZA" },
|
|
||||||
{ name: "South Georgia and the South Sandwich Islands", code: "GS" },
|
|
||||||
{ name: "Spain", code: "ES" },
|
|
||||||
{ name: "Sri Lanka", code: "LK" },
|
|
||||||
{ name: "Sudan", code: "SD" },
|
|
||||||
{ name: "Suriname", code: "SR" },
|
|
||||||
{ name: "Svalbard and Jan Mayen", code: "SJ" },
|
|
||||||
{ name: "Swaziland", code: "SZ" },
|
|
||||||
{ name: "Sweden", code: "SE" },
|
|
||||||
{ name: "Switzerland", code: "CH" },
|
|
||||||
{ name: "Syrian Arab Republic", code: "SY" },
|
|
||||||
{ name: "Taiwan, Province of China", code: "TW" },
|
|
||||||
{ name: "Tajikistan", code: "TJ" },
|
|
||||||
{ name: "Tanzania, United Republic of", code: "TZ" },
|
|
||||||
{ name: "Thailand", code: "TH" },
|
|
||||||
{ name: "Timor-Leste", code: "TL" },
|
|
||||||
{ name: "Togo", code: "TG" },
|
|
||||||
{ name: "Tokelau", code: "TK" },
|
|
||||||
{ name: "Tonga", code: "TO" },
|
|
||||||
{ name: "Trinidad and Tobago", code: "TT" },
|
|
||||||
{ name: "Tunisia", code: "TN" },
|
|
||||||
{ name: "Turkey", code: "TR" },
|
|
||||||
{ name: "Turkmenistan", code: "TM" },
|
|
||||||
{ name: "Turks and Caicos Islands", code: "TC" },
|
|
||||||
{ name: "Tuvalu", code: "TV" },
|
|
||||||
{ name: "Uganda", code: "UG" },
|
|
||||||
{ name: "Ukraine", code: "UA" },
|
|
||||||
{ name: "United Arab Emirates", code: "AE" },
|
|
||||||
{ name: "United Kingdom", code: "GB" },
|
|
||||||
{ name: "United States", code: "US" },
|
|
||||||
{ name: "United States Minor Outlying Islands", code: "UM" },
|
|
||||||
{ name: "Uruguay", code: "UY" },
|
|
||||||
{ name: "Uzbekistan", code: "UZ" },
|
|
||||||
{ name: "Vanuatu", code: "VU" },
|
|
||||||
{ name: "Venezuela", code: "VE" },
|
|
||||||
{ name: "Viet Nam", code: "VN" },
|
|
||||||
{ name: "Virgin Islands, British", code: "VG" },
|
|
||||||
{ name: "Virgin Islands, U.S.", code: "VI" },
|
|
||||||
{ name: "Wallis and Futuna", code: "WF" },
|
|
||||||
{ name: "Western Sahara", code: "EH" },
|
|
||||||
{ name: "Yemen", code: "YE" },
|
|
||||||
{ name: "Zambia", code: "ZM" },
|
|
||||||
{ name: "Zimbabwe", code: "ZW" }
|
|
||||||
];
|
|
248
src/fixtures.ts
248
src/fixtures.ts
|
@ -44,11 +44,249 @@ export const listActionsProps: ListActions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const countries = [
|
export const countries = [
|
||||||
{ code: "AF", label: "Afghanistan" },
|
{ name: "Afghanistan", code: "AF" },
|
||||||
{ code: "AX", label: "Åland Islands" },
|
{ name: "Åland Islands", code: "AX" },
|
||||||
{ code: "AL", label: "Albania" },
|
{ name: "Albania", code: "AL" },
|
||||||
{ code: "DZ", label: "Algeria" },
|
{ name: "Algeria", code: "DZ" },
|
||||||
{ code: "AS", label: "American Samoa" }
|
{ name: "American Samoa", code: "AS" },
|
||||||
|
{ name: "AndorrA", code: "AD" },
|
||||||
|
{ name: "Angola", code: "AO" },
|
||||||
|
{ name: "Anguilla", code: "AI" },
|
||||||
|
{ name: "Antarctica", code: "AQ" },
|
||||||
|
{ name: "Antigua and Barbuda", code: "AG" },
|
||||||
|
{ name: "Argentina", code: "AR" },
|
||||||
|
{ name: "Armenia", code: "AM" },
|
||||||
|
{ name: "Aruba", code: "AW" },
|
||||||
|
{ name: "Australia", code: "AU" },
|
||||||
|
{ name: "Austria", code: "AT" },
|
||||||
|
{ name: "Azerbaijan", code: "AZ" },
|
||||||
|
{ name: "Bahamas", code: "BS" },
|
||||||
|
{ name: "Bahrain", code: "BH" },
|
||||||
|
{ name: "Bangladesh", code: "BD" },
|
||||||
|
{ name: "Barbados", code: "BB" },
|
||||||
|
{ name: "Belarus", code: "BY" },
|
||||||
|
{ name: "Belgium", code: "BE" },
|
||||||
|
{ name: "Belize", code: "BZ" },
|
||||||
|
{ name: "Benin", code: "BJ" },
|
||||||
|
{ name: "Bermuda", code: "BM" },
|
||||||
|
{ name: "Bhutan", code: "BT" },
|
||||||
|
{ name: "Bolivia", code: "BO" },
|
||||||
|
{ name: "Bosnia and Herzegovina", code: "BA" },
|
||||||
|
{ name: "Botswana", code: "BW" },
|
||||||
|
{ name: "Bouvet Island", code: "BV" },
|
||||||
|
{ name: "Brazil", code: "BR" },
|
||||||
|
{ name: "British Indian Ocean Territory", code: "IO" },
|
||||||
|
{ name: "Brunei Darussalam", code: "BN" },
|
||||||
|
{ name: "Bulgaria", code: "BG" },
|
||||||
|
{ name: "Burkina Faso", code: "BF" },
|
||||||
|
{ name: "Burundi", code: "BI" },
|
||||||
|
{ name: "Cambodia", code: "KH" },
|
||||||
|
{ name: "Cameroon", code: "CM" },
|
||||||
|
{ name: "Canada", code: "CA" },
|
||||||
|
{ name: "Cape Verde", code: "CV" },
|
||||||
|
{ name: "Cayman Islands", code: "KY" },
|
||||||
|
{ name: "Central African Republic", code: "CF" },
|
||||||
|
{ name: "Chad", code: "TD" },
|
||||||
|
{ name: "Chile", code: "CL" },
|
||||||
|
{ name: "China", code: "CN" },
|
||||||
|
{ name: "Christmas Island", code: "CX" },
|
||||||
|
{ name: "Cocos (Keeling) Islands", code: "CC" },
|
||||||
|
{ name: "Colombia", code: "CO" },
|
||||||
|
{ name: "Comoros", code: "KM" },
|
||||||
|
{ name: "Congo", code: "CG" },
|
||||||
|
{ name: "Congo, The Democratic Republic of the", code: "CD" },
|
||||||
|
{ name: "Cook Islands", code: "CK" },
|
||||||
|
{ name: "Costa Rica", code: "CR" },
|
||||||
|
{ name: "Cote D'Ivoire", code: "CI" },
|
||||||
|
{ name: "Croatia", code: "HR" },
|
||||||
|
{ name: "Cuba", code: "CU" },
|
||||||
|
{ name: "Cyprus", code: "CY" },
|
||||||
|
{ name: "Czech Republic", code: "CZ" },
|
||||||
|
{ name: "Denmark", code: "DK" },
|
||||||
|
{ name: "Djibouti", code: "DJ" },
|
||||||
|
{ name: "Dominica", code: "DM" },
|
||||||
|
{ name: "Dominican Republic", code: "DO" },
|
||||||
|
{ name: "Ecuador", code: "EC" },
|
||||||
|
{ name: "Egypt", code: "EG" },
|
||||||
|
{ name: "El Salvador", code: "SV" },
|
||||||
|
{ name: "Equatorial Guinea", code: "GQ" },
|
||||||
|
{ name: "Eritrea", code: "ER" },
|
||||||
|
{ name: "Estonia", code: "EE" },
|
||||||
|
{ name: "Ethiopia", code: "ET" },
|
||||||
|
{ name: "Falkland Islands (Malvinas)", code: "FK" },
|
||||||
|
{ name: "Faroe Islands", code: "FO" },
|
||||||
|
{ name: "Fiji", code: "FJ" },
|
||||||
|
{ name: "Finland", code: "FI" },
|
||||||
|
{ name: "France", code: "FR" },
|
||||||
|
{ name: "French Guiana", code: "GF" },
|
||||||
|
{ name: "French Polynesia", code: "PF" },
|
||||||
|
{ name: "French Southern Territories", code: "TF" },
|
||||||
|
{ name: "Gabon", code: "GA" },
|
||||||
|
{ name: "Gambia", code: "GM" },
|
||||||
|
{ name: "Georgia", code: "GE" },
|
||||||
|
{ name: "Germany", code: "DE" },
|
||||||
|
{ name: "Ghana", code: "GH" },
|
||||||
|
{ name: "Gibraltar", code: "GI" },
|
||||||
|
{ name: "Greece", code: "GR" },
|
||||||
|
{ name: "Greenland", code: "GL" },
|
||||||
|
{ name: "Grenada", code: "GD" },
|
||||||
|
{ name: "Guadeloupe", code: "GP" },
|
||||||
|
{ name: "Guam", code: "GU" },
|
||||||
|
{ name: "Guatemala", code: "GT" },
|
||||||
|
{ name: "Guernsey", code: "GG" },
|
||||||
|
{ name: "Guinea", code: "GN" },
|
||||||
|
{ name: "Guinea-Bissau", code: "GW" },
|
||||||
|
{ name: "Guyana", code: "GY" },
|
||||||
|
{ name: "Haiti", code: "HT" },
|
||||||
|
{ name: "Heard Island and Mcdonald Islands", code: "HM" },
|
||||||
|
{ name: "Holy See (Vatican City State)", code: "VA" },
|
||||||
|
{ name: "Honduras", code: "HN" },
|
||||||
|
{ name: "Hong Kong", code: "HK" },
|
||||||
|
{ name: "Hungary", code: "HU" },
|
||||||
|
{ name: "Iceland", code: "IS" },
|
||||||
|
{ name: "India", code: "IN" },
|
||||||
|
{ name: "Indonesia", code: "ID" },
|
||||||
|
{ name: "Iran, Islamic Republic Of", code: "IR" },
|
||||||
|
{ name: "Iraq", code: "IQ" },
|
||||||
|
{ name: "Ireland", code: "IE" },
|
||||||
|
{ name: "Isle of Man", code: "IM" },
|
||||||
|
{ name: "Israel", code: "IL" },
|
||||||
|
{ name: "Italy", code: "IT" },
|
||||||
|
{ name: "Jamaica", code: "JM" },
|
||||||
|
{ name: "Japan", code: "JP" },
|
||||||
|
{ name: "Jersey", code: "JE" },
|
||||||
|
{ name: "Jordan", code: "JO" },
|
||||||
|
{ name: "Kazakhstan", code: "KZ" },
|
||||||
|
{ name: "Kenya", code: "KE" },
|
||||||
|
{ name: "Kiribati", code: "KI" },
|
||||||
|
{ name: "Korea, Democratic People'S Republic of", code: "KP" },
|
||||||
|
{ name: "Korea, Republic of", code: "KR" },
|
||||||
|
{ name: "Kuwait", code: "KW" },
|
||||||
|
{ name: "Kyrgyzstan", code: "KG" },
|
||||||
|
{ name: "Lao People'S Democratic Republic", code: "LA" },
|
||||||
|
{ name: "Latvia", code: "LV" },
|
||||||
|
{ name: "Lebanon", code: "LB" },
|
||||||
|
{ name: "Lesotho", code: "LS" },
|
||||||
|
{ name: "Liberia", code: "LR" },
|
||||||
|
{ name: "Libyan Arab Jamahiriya", code: "LY" },
|
||||||
|
{ name: "Liechtenstein", code: "LI" },
|
||||||
|
{ name: "Lithuania", code: "LT" },
|
||||||
|
{ name: "Luxembourg", code: "LU" },
|
||||||
|
{ name: "Macao", code: "MO" },
|
||||||
|
{ name: "Macedonia, The Former Yugoslav Republic of", code: "MK" },
|
||||||
|
{ name: "Madagascar", code: "MG" },
|
||||||
|
{ name: "Malawi", code: "MW" },
|
||||||
|
{ name: "Malaysia", code: "MY" },
|
||||||
|
{ name: "Maldives", code: "MV" },
|
||||||
|
{ name: "Mali", code: "ML" },
|
||||||
|
{ name: "Malta", code: "MT" },
|
||||||
|
{ name: "Marshall Islands", code: "MH" },
|
||||||
|
{ name: "Martinique", code: "MQ" },
|
||||||
|
{ name: "Mauritania", code: "MR" },
|
||||||
|
{ name: "Mauritius", code: "MU" },
|
||||||
|
{ name: "Mayotte", code: "YT" },
|
||||||
|
{ name: "Mexico", code: "MX" },
|
||||||
|
{ name: "Micronesia, Federated States of", code: "FM" },
|
||||||
|
{ name: "Moldova, Republic of", code: "MD" },
|
||||||
|
{ name: "Monaco", code: "MC" },
|
||||||
|
{ name: "Mongolia", code: "MN" },
|
||||||
|
{ name: "Montserrat", code: "MS" },
|
||||||
|
{ name: "Morocco", code: "MA" },
|
||||||
|
{ name: "Mozambique", code: "MZ" },
|
||||||
|
{ name: "Myanmar", code: "MM" },
|
||||||
|
{ name: "Namibia", code: "NA" },
|
||||||
|
{ name: "Nauru", code: "NR" },
|
||||||
|
{ name: "Nepal", code: "NP" },
|
||||||
|
{ name: "Netherlands", code: "NL" },
|
||||||
|
{ name: "Netherlands Antilles", code: "AN" },
|
||||||
|
{ name: "New Caledonia", code: "NC" },
|
||||||
|
{ name: "New Zealand", code: "NZ" },
|
||||||
|
{ name: "Nicaragua", code: "NI" },
|
||||||
|
{ name: "Niger", code: "NE" },
|
||||||
|
{ name: "Nigeria", code: "NG" },
|
||||||
|
{ name: "Niue", code: "NU" },
|
||||||
|
{ name: "Norfolk Island", code: "NF" },
|
||||||
|
{ name: "Northern Mariana Islands", code: "MP" },
|
||||||
|
{ name: "Norway", code: "NO" },
|
||||||
|
{ name: "Oman", code: "OM" },
|
||||||
|
{ name: "Pakistan", code: "PK" },
|
||||||
|
{ name: "Palau", code: "PW" },
|
||||||
|
{ name: "Palestinian Territory, Occupied", code: "PS" },
|
||||||
|
{ name: "Panama", code: "PA" },
|
||||||
|
{ name: "Papua New Guinea", code: "PG" },
|
||||||
|
{ name: "Paraguay", code: "PY" },
|
||||||
|
{ name: "Peru", code: "PE" },
|
||||||
|
{ name: "Philippines", code: "PH" },
|
||||||
|
{ name: "Pitcairn", code: "PN" },
|
||||||
|
{ name: "Poland", code: "PL" },
|
||||||
|
{ name: "Portugal", code: "PT" },
|
||||||
|
{ name: "Puerto Rico", code: "PR" },
|
||||||
|
{ name: "Qatar", code: "QA" },
|
||||||
|
{ name: "Reunion", code: "RE" },
|
||||||
|
{ name: "Romania", code: "RO" },
|
||||||
|
{ name: "Russian Federation", code: "RU" },
|
||||||
|
{ name: "RWANDA", code: "RW" },
|
||||||
|
{ name: "Saint Helena", code: "SH" },
|
||||||
|
{ name: "Saint Kitts and Nevis", code: "KN" },
|
||||||
|
{ name: "Saint Lucia", code: "LC" },
|
||||||
|
{ name: "Saint Pierre and Miquelon", code: "PM" },
|
||||||
|
{ name: "Saint Vincent and the Grenadines", code: "VC" },
|
||||||
|
{ name: "Samoa", code: "WS" },
|
||||||
|
{ name: "San Marino", code: "SM" },
|
||||||
|
{ name: "Sao Tome and Principe", code: "ST" },
|
||||||
|
{ name: "Saudi Arabia", code: "SA" },
|
||||||
|
{ name: "Senegal", code: "SN" },
|
||||||
|
{ name: "Serbia and Montenegro", code: "CS" },
|
||||||
|
{ name: "Seychelles", code: "SC" },
|
||||||
|
{ name: "Sierra Leone", code: "SL" },
|
||||||
|
{ name: "Singapore", code: "SG" },
|
||||||
|
{ name: "Slovakia", code: "SK" },
|
||||||
|
{ name: "Slovenia", code: "SI" },
|
||||||
|
{ name: "Solomon Islands", code: "SB" },
|
||||||
|
{ name: "Somalia", code: "SO" },
|
||||||
|
{ name: "South Africa", code: "ZA" },
|
||||||
|
{ name: "South Georgia and the South Sandwich Islands", code: "GS" },
|
||||||
|
{ name: "Spain", code: "ES" },
|
||||||
|
{ name: "Sri Lanka", code: "LK" },
|
||||||
|
{ name: "Sudan", code: "SD" },
|
||||||
|
{ name: "Suriname", code: "SR" },
|
||||||
|
{ name: "Svalbard and Jan Mayen", code: "SJ" },
|
||||||
|
{ name: "Swaziland", code: "SZ" },
|
||||||
|
{ name: "Sweden", code: "SE" },
|
||||||
|
{ name: "Switzerland", code: "CH" },
|
||||||
|
{ name: "Syrian Arab Republic", code: "SY" },
|
||||||
|
{ name: "Taiwan, Province of China", code: "TW" },
|
||||||
|
{ name: "Tajikistan", code: "TJ" },
|
||||||
|
{ name: "Tanzania, United Republic of", code: "TZ" },
|
||||||
|
{ name: "Thailand", code: "TH" },
|
||||||
|
{ name: "Timor-Leste", code: "TL" },
|
||||||
|
{ name: "Togo", code: "TG" },
|
||||||
|
{ name: "Tokelau", code: "TK" },
|
||||||
|
{ name: "Tonga", code: "TO" },
|
||||||
|
{ name: "Trinidad and Tobago", code: "TT" },
|
||||||
|
{ name: "Tunisia", code: "TN" },
|
||||||
|
{ name: "Turkey", code: "TR" },
|
||||||
|
{ name: "Turkmenistan", code: "TM" },
|
||||||
|
{ name: "Turks and Caicos Islands", code: "TC" },
|
||||||
|
{ name: "Tuvalu", code: "TV" },
|
||||||
|
{ name: "Uganda", code: "UG" },
|
||||||
|
{ name: "Ukraine", code: "UA" },
|
||||||
|
{ name: "United Arab Emirates", code: "AE" },
|
||||||
|
{ name: "United Kingdom", code: "GB" },
|
||||||
|
{ name: "United States", code: "US" },
|
||||||
|
{ name: "United States Minor Outlying Islands", code: "UM" },
|
||||||
|
{ name: "Uruguay", code: "UY" },
|
||||||
|
{ name: "Uzbekistan", code: "UZ" },
|
||||||
|
{ name: "Vanuatu", code: "VU" },
|
||||||
|
{ name: "Venezuela", code: "VE" },
|
||||||
|
{ name: "Viet Nam", code: "VN" },
|
||||||
|
{ name: "Virgin Islands, British", code: "VG" },
|
||||||
|
{ name: "Virgin Islands, U.S.", code: "VI" },
|
||||||
|
{ name: "Wallis and Futuna", code: "WF" },
|
||||||
|
{ name: "Western Sahara", code: "EH" },
|
||||||
|
{ name: "Yemen", code: "YE" },
|
||||||
|
{ name: "Zambia", code: "ZM" },
|
||||||
|
{ name: "Zimbabwe", code: "ZW" }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const tabPageProps: TabPageProps = {
|
export const tabPageProps: TabPageProps = {
|
||||||
|
|
|
@ -29,7 +29,6 @@ function loadStories() {
|
||||||
require("./stories/components/Filter");
|
require("./stories/components/Filter");
|
||||||
require("./stories/components/Money");
|
require("./stories/components/Money");
|
||||||
require("./stories/components/MoneyRange");
|
require("./stories/components/MoneyRange");
|
||||||
require("./stories/components/MultiAutocompleteSelectField");
|
|
||||||
require("./stories/components/MultiSelectField");
|
require("./stories/components/MultiSelectField");
|
||||||
require("./stories/components/NotFoundPage");
|
require("./stories/components/NotFoundPage");
|
||||||
require("./stories/components/PageHeader");
|
require("./stories/components/PageHeader");
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
import { storiesOf } from "@storybook/react";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import MultiAutocompleteSelectField, {
|
|
||||||
MultiAutocompleteSelectFieldProps
|
|
||||||
} from "@saleor/components/MultiAutocompleteSelectField";
|
|
||||||
import useMultiAutocomplete from "@saleor/hooks/useMultiAutocomplete";
|
|
||||||
import CardDecorator from "../../CardDecorator";
|
|
||||||
import Decorator from "../../Decorator";
|
|
||||||
import { ChoiceProvider } from "../../mock";
|
|
||||||
|
|
||||||
const suggestions = [
|
|
||||||
"Afghanistan",
|
|
||||||
"Burundi",
|
|
||||||
"Comoros",
|
|
||||||
"Egypt",
|
|
||||||
"Equatorial Guinea",
|
|
||||||
"Greenland",
|
|
||||||
"Isle of Man",
|
|
||||||
"Israel",
|
|
||||||
"Italy",
|
|
||||||
"United States",
|
|
||||||
"Wallis and Futuna",
|
|
||||||
"Zimbabwe"
|
|
||||||
].map(c => ({ label: c, value: c.toLocaleLowerCase().replace(/\s+/, "_") }));
|
|
||||||
|
|
||||||
const props: MultiAutocompleteSelectFieldProps = {
|
|
||||||
choices: undefined,
|
|
||||||
displayValues: [],
|
|
||||||
label: "Country",
|
|
||||||
loading: false,
|
|
||||||
name: "country",
|
|
||||||
onChange: () => undefined,
|
|
||||||
placeholder: "Select country",
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
const Story: React.FC<
|
|
||||||
Partial<MultiAutocompleteSelectFieldProps>
|
|
||||||
> = storyProps => {
|
|
||||||
const { change, data: countries } = useMultiAutocomplete([suggestions[0]]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChoiceProvider choices={suggestions}>
|
|
||||||
{({ choices, loading, fetchChoices }) => (
|
|
||||||
<MultiAutocompleteSelectField
|
|
||||||
{...props}
|
|
||||||
displayValues={countries}
|
|
||||||
choices={choices}
|
|
||||||
fetchChoices={fetchChoices}
|
|
||||||
helperText={`Value: ${countries
|
|
||||||
.map(country => country.label)
|
|
||||||
.join(", ")}`}
|
|
||||||
onChange={event => change(event, choices)}
|
|
||||||
value={countries.map(country => country.value)}
|
|
||||||
loading={loading}
|
|
||||||
{...storyProps}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ChoiceProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
storiesOf("Generics / MultiAutocompleteSelectField", module)
|
|
||||||
.addDecorator(CardDecorator)
|
|
||||||
.addDecorator(Decorator)
|
|
||||||
.add("with loaded data", () => <Story />)
|
|
||||||
.add("with loading data", () => <Story loading={true} />)
|
|
||||||
.add("with custom option", () => <Story allowCustomValues={true} />);
|
|
|
@ -11,7 +11,10 @@ import Decorator from "../../Decorator";
|
||||||
const props: CustomerAddressDialogProps = {
|
const props: CustomerAddressDialogProps = {
|
||||||
address: customer.addresses[0],
|
address: customer.addresses[0],
|
||||||
confirmButtonState: "default",
|
confirmButtonState: "default",
|
||||||
countries,
|
countries: countries.map(c => ({
|
||||||
|
code: c.code,
|
||||||
|
label: c.name
|
||||||
|
})),
|
||||||
errors: [],
|
errors: [],
|
||||||
onClose: () => undefined,
|
onClose: () => undefined,
|
||||||
onConfirm: () => undefined,
|
onConfirm: () => undefined,
|
||||||
|
|
Loading…
Reference in a new issue