You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
2.5 KiB
TypeScript

import * as React from "react";
import * as $ from "@radix-ui/react-select";
import { match, P } from "ts-pattern";
import { FaCheck, FaChevronDown, FaChevronUp } from "react-icons/fa";
import * as T from "./Select.types";
import * as styles from "./Select.styles";
import { cx } from "../../utils";
import { Box } from "../Box";
import { Label, HelpText } from "../Common";
const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
(
{
label,
hideLabel = false,
helpText,
fullWidth,
hasError,
children,
className,
...props
},
ref
) => {
const classes = cx(
[styles.selectStyles({ fullWidth, hasError })],
className
);
return (
<Box className={cx(["relative"])}>
<Label
htmlFor={"select"}
className={cx([""], {
"sr-only": hideLabel,
})}
>
{label}
</Label>
<Box className={cx(["mt-1"])}>
<$.Root>
<$.Trigger id="select" {...props} className={classes} ref={ref}>
<$.Value placeholder={props.placeholder} />
<$.Icon className={cx(["ml-2"])} asChild>
<FaChevronDown />
</$.Icon>
</$.Trigger>
<$.Portal>
<$.Content className={cx([styles.content])} position="popper">
<$.ScrollUpButton className={cx([styles.scroll])}>
<FaChevronUp />
</$.ScrollUpButton>
<$.Viewport className={cx([styles.viewport])}>
{children}
</$.Viewport>
<$.ScrollDownButton className={cx([styles.scroll])}>
<FaChevronDown />
</$.ScrollDownButton>
<$.Arrow />
</$.Content>
</$.Portal>
</$.Root>
</Box>
{match(helpText)
.with(P.not(P.nullish), (helpText) => (
<HelpText hasError={hasError}>{helpText}</HelpText>
))
.otherwise(() => null)}
</Box>
);
}
);
const SelectItem = React.forwardRef<T.SelectItemElement, T.SelectItemProps>(
({ children, className, ...props }, forwardedRef) => {
const classes = cx([styles.itemStyles()], className);
return (
<$.Item {...props} className={classes} ref={forwardedRef}>
<$.ItemText>{children}</$.ItemText>
<$.ItemIndicator className={cx([styles.indicator])}>
<FaCheck />
</$.ItemIndicator>{" "}
</$.Item>
);
}
);
export { Select, SelectItem };