"use client"; import { Check } from "@phosphor-icons/react/dist/ssr/Check"; import clsx from "clsx"; import type { ComponentProps, ReactNode } from "react"; import type { PopoverProps, Button as BaseButton } from "react-aria-components"; import { Label, Select as BaseSelect, Popover, Header, Collection, SelectValue, } from "react-aria-components"; import styles from "./index.module.scss"; import type { Props as ButtonProps } from "../Button/index.jsx"; import { Button } from "../Button/index.jsx"; import { DropdownCaretDown } from "../DropdownCaretDown/index.jsx"; import { ListBox, ListBoxItem, ListBoxSection, } from "../unstyled/ListBox/index.jsx"; export type Props = Omit< ComponentProps, "defaultSelectedKey" | "selectedKey" | "onSelectionChange" > & Pick< ButtonProps, "variant" | "size" | "rounded" | "hideText" | "isPending" > & Pick & { show?: ((value: T) => ReactNode) | undefined; textValue?: ((value: T) => string) | undefined; icon?: ComponentProps["beforeIcon"]; label: ReactNode; hideLabel?: boolean | undefined; buttonLabel?: ReactNode; defaultButtonLabel?: ReactNode; } & ( | { defaultSelectedKey?: T["id"] | undefined; } | { selectedKey: T["id"]; onSelectionChange: (newValue: T["id"]) => void; } ) & ( | { options: readonly T[]; } | { hideGroupLabel?: boolean | undefined; optionGroups: { name: string; options: readonly T[]; hideLabel?: boolean | undefined; }[]; } ); export const Select = ({ className, show, textValue, variant, size, rounded, hideText, icon, label, hideLabel, placement, isPending, buttonLabel, defaultButtonLabel, ...props }: Props) => ( // @ts-expect-error react-aria coerces everything to Key for some reason... {label} {"options" in props ? ( {(item) => ( {item} )} ) : ( {({ name, options, hideLabel }) => (
{name}
{(item) => ( {item} )}
)}
)}
); type ItemProps = { children: T; show: ((value: T) => ReactNode) | undefined; textValue: ((value: T) => string) | undefined; }; const Item = ({ children, show, textValue, }: ItemProps) => ( {show?.(children) ?? children.id} ); const getTextValue = ({ children, show, textValue, }: ItemProps) => { if (textValue !== undefined) { return textValue(children); } else if (show === undefined) { return children.id.toString(); } else { const result = show(children); return typeof result === "string" ? result : children.id.toString(); } }; type ButtonLabelProps = Pick< Props, "buttonLabel" | "defaultButtonLabel" | "show" >; const ButtonLabel = ({ buttonLabel, defaultButtonLabel, show, }: ButtonLabelProps) => { if (buttonLabel !== undefined && buttonLabel !== "") { return buttonLabel; } else if (defaultButtonLabel !== undefined && defaultButtonLabel !== "") { return ( > {(props) => props.selectedText === null ? ( defaultButtonLabel ) : ( ) } ); } else { return ( > {(props) => } ); } }; type SelectedValueLabelProps = Pick< Props, "show" > & { selectedItem: T | null; selectedText: string | null; }; const SelectedValueLabel = ({ show, selectedItem, selectedText, }: SelectedValueLabelProps) => selectedItem ? (show?.(selectedItem) ?? selectedItem.id) : selectedText;