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
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 };
|