"use client"; import { mergeProps } from "@base-ui/react/merge-props";import { Select as SelectPrimitive } from "@base-ui/react/select";import { useRender } from "@base-ui/react/use-render";import { cva, type VariantProps } from "class-variance-authority";import { ChevronDownIcon, ChevronsUpDownIcon, ChevronUpIcon } from "lucide-react";import type * as React from "react"; import { cn } from "~/lib/utils"; const Select = SelectPrimitive.Root; const selectTriggerVariants = cva( "relative inline-flex cursor-pointer select-none items-center justify-between gap-2 border rounded-lg text-left text-base outline-none transition-[color,box-shadow,background-color] data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4", { defaultVariants: { size: "default", variant: "default", }, variants: { variant: { default: "w-full min-w-36 border-input bg-background not-dark:bg-clip-padding text-foreground shadow-xs/5 ring-ring/24 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='text-'])]:text-icon-muted [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none", ghost: "border-transparent text-secondary-label focus-visible:ring-2 focus-visible:ring-ring data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground", }, size: { compact: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-xs before:rounded-[calc(var(--radius-md)-1px)] [&_svg:not([class*='size-'])]:size-3.5", default: "min-h-9 px-[calc(--spacing(3)-1px)] sm:min-h-8", lg: "min-h-10 px-[calc(--spacing(3)-1px)] sm:min-h-9", sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7", xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5", }, }, },); const selectTriggerIconClassName = "-me-1 size-4.5 opacity-80 sm:size-4"; interface SelectButtonProps extends useRender.ComponentProps<"button"> { size?: VariantProps<typeof selectTriggerVariants>["size"]; variant?: VariantProps<typeof selectTriggerVariants>["variant"];} function SelectButton({ className, size, variant, render, children, ...props }: SelectButtonProps) { const typeValue: React.ButtonHTMLAttributes<HTMLButtonElement>["type"] = render ? undefined : "button"; const defaultProps = { children: ( <> <span className="flex-1 truncate in-data-placeholder:text-placeholder">{children}</span> {variant === "ghost" ? ( <ChevronDownIcon className="-me-1 size-3 opacity-50" /> ) : ( <ChevronsUpDownIcon className={selectTriggerIconClassName} /> )} </> ), className: cn(selectTriggerVariants({ size, variant }), "min-w-none", className), "data-slot": "select-button", type: typeValue, }; return useRender({ defaultTagName: "button", props: mergeProps<"button">(defaultProps, props), render, });} function SelectTrigger({ className, size = "default", variant = "default", children, icon, ...props}: SelectPrimitive.Trigger.Props & VariantProps<typeof selectTriggerVariants> & { icon?: React.ReactNode }) { return ( <SelectPrimitive.Trigger className={cn(selectTriggerVariants({ size, variant }), className)} data-slot="select-trigger" {...props} > {children} <SelectPrimitive.Icon data-slot="select-icon"> {icon ?? <ChevronDownIcon className="-me-1 size-3 opacity-50" />} </SelectPrimitive.Icon> </SelectPrimitive.Trigger> );} function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) { return ( <SelectPrimitive.Value className={cn("flex-1 truncate data-placeholder:text-placeholder", className)} data-slot="select-value" {...props} /> );} function SelectPopup({ className, popupClassName, children, side = "bottom", sideOffset = 4, align = "start", alignOffset = 0, alignItemWithTrigger = true, matchTriggerWidth = true, anchor, ...props}: SelectPrimitive.Popup.Props & { popupClassName?: string; side?: SelectPrimitive.Positioner.Props["side"]; sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"]; align?: SelectPrimitive.Positioner.Props["align"]; alignOffset?: SelectPrimitive.Positioner.Props["alignOffset"]; alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"]; matchTriggerWidth?: boolean; anchor?: SelectPrimitive.Positioner.Props["anchor"];}) { return ( <SelectPrimitive.Portal> <SelectPrimitive.Positioner align={align} alignItemWithTrigger={alignItemWithTrigger} alignOffset={alignOffset} anchor={anchor} className="z-[130] select-none" data-slot="select-positioner" side={side} sideOffset={sideOffset} > <SelectPrimitive.Popup className="origin-(--transform-origin) rounded-lg text-foreground outline-none" data-slot="select-popup" {...props} > <SelectPrimitive.ScrollUpArrow className="top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover" data-slot="select-scroll-up-arrow" > <ChevronUpIcon className="relative size-4.5 sm:size-4" /> </SelectPrimitive.ScrollUpArrow> <div className={cn( "dropdown-glass relative h-full rounded-lg shadow-[0_16px_40px_-18px_rgb(0_0_0/55%)] dark:shadow-[0_18px_44px_-18px_rgb(0_0_0/80%)]", matchTriggerWidth && "min-w-(--anchor-width)", popupClassName, )} > <SelectPrimitive.List className={cn("max-h-(--available-height) overflow-y-auto p-1", className)} data-slot="select-list" > {children} </SelectPrimitive.List> </div> <SelectPrimitive.ScrollDownArrow className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover" data-slot="select-scroll-down-arrow" > <ChevronDownIcon className="relative size-4.5 sm:size-4" /> </SelectPrimitive.ScrollDownArrow> </SelectPrimitive.Popup> </SelectPrimitive.Positioner> </SelectPrimitive.Portal> );} function SelectItem({ className, children, hideIndicator: _hideIndicator = false, ...props}: SelectPrimitive.Item.Props & { hideIndicator?: boolean;}) { return ( <SelectPrimitive.Item className={cn( "flex min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-pointer items-center rounded-sm px-2 py-1 text-base outline-none data-selected:bg-foreground/[0.08] data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", className, )} data-slot="select-item" {...props} > <SelectPrimitive.ItemText className="min-w-0 flex-1 [&_svg:not([class*='text-'])]:text-muted-foreground" data-slot="select-item-text" > {children} </SelectPrimitive.ItemText> </SelectPrimitive.Item> );} function SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) { return ( <SelectPrimitive.Separator className={cn("mx-2 my-1 h-px bg-border", className)} data-slot="select-separator" {...props} /> );} function SelectGroup(props: SelectPrimitive.Group.Props) { return <SelectPrimitive.Group data-slot="select-group" {...props} />;} function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) { return ( <SelectPrimitive.GroupLabel className="px-2 py-1.5 font-medium text-muted-foreground text-xs" data-slot="select-group-label" {...props} /> );} export { Select, SelectTrigger, SelectButton, selectTriggerVariants, SelectValue, SelectPopup, SelectPopup as SelectContent, SelectItem, SelectSeparator, SelectGroup, SelectGroupLabel,};
"use client";
import { mergeProps } from "@base-ui/react/merge-props";
import { Select as SelectPrimitive } from "@base-ui/react/select";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { ChevronDownIcon, ChevronsUpDownIcon, ChevronUpIcon } from "lucide-react";
import type * as React from "react";
import { cn } from "~/lib/utils";
const Select = SelectPrimitive.Root;
const selectTriggerVariants = cva(
"relative inline-flex cursor-pointer select-none items-center justify-between gap-2 border rounded-lg text-left text-base outline-none transition-[color,box-shadow,background-color] data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4",
{
defaultVariants: {
size: "default",
variant: "default",
},
variants: {
variant: {
default:
"w-full min-w-36 border-input bg-background not-dark:bg-clip-padding text-foreground shadow-xs/5 ring-ring/24 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='text-'])]:text-icon-muted [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
ghost:
"border-transparent text-secondary-label focus-visible:ring-2 focus-visible:ring-ring data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground",
},
size: {
compact:
"h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-xs before:rounded-[calc(var(--radius-md)-1px)] [&_svg:not([class*='size-'])]:size-3.5",
default: "min-h-9 px-[calc(--spacing(3)-1px)] sm:min-h-8",
lg: "min-h-10 px-[calc(--spacing(3)-1px)] sm:min-h-9",
sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5",
},
},
},
);
const selectTriggerIconClassName = "-me-1 size-4.5 opacity-80 sm:size-4";
interface SelectButtonProps extends useRender.ComponentProps<"button"> {
size?: VariantProps<typeof selectTriggerVariants>["size"];
variant?: VariantProps<typeof selectTriggerVariants>["variant"];
}
function SelectButton({ className, size, variant, render, children, ...props }: SelectButtonProps) {
const typeValue: React.ButtonHTMLAttributes<HTMLButtonElement>["type"] = render
? undefined
: "button";
const defaultProps = {
children: (
<>
<span className="flex-1 truncate in-data-placeholder:text-placeholder">{children}</span>
{variant === "ghost" ? (
<ChevronDownIcon className="-me-1 size-3 opacity-50" />
) : (
<ChevronsUpDownIcon className={selectTriggerIconClassName} />
)}
</>
),
className: cn(selectTriggerVariants({ size, variant }), "min-w-none", className),
"data-slot": "select-button",
type: typeValue,
};
return useRender({
defaultTagName: "button",
props: mergeProps<"button">(defaultProps, props),
render,
});
}
function SelectTrigger({
className,
size = "default",
variant = "default",
children,
icon,
...props
}: SelectPrimitive.Trigger.Props &
VariantProps<typeof selectTriggerVariants> & { icon?: React.ReactNode }) {
return (
<SelectPrimitive.Trigger
className={cn(selectTriggerVariants({ size, variant }), className)}
data-slot="select-trigger"
{...props}
>
{children}
<SelectPrimitive.Icon data-slot="select-icon">
{icon ?? <ChevronDownIcon className="-me-1 size-3 opacity-50" />}
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
);
}
function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
return (
<SelectPrimitive.Value
className={cn("flex-1 truncate data-placeholder:text-placeholder", className)}
data-slot="select-value"
{...props}
/>
);
}
function SelectPopup({
className,
popupClassName,
children,
side = "bottom",
sideOffset = 4,
align = "start",
alignOffset = 0,
alignItemWithTrigger = true,
matchTriggerWidth = true,
anchor,
...props
}: SelectPrimitive.Popup.Props & {
popupClassName?: string;
side?: SelectPrimitive.Positioner.Props["side"];
sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
align?: SelectPrimitive.Positioner.Props["align"];
alignOffset?: SelectPrimitive.Positioner.Props["alignOffset"];
alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
matchTriggerWidth?: boolean;
anchor?: SelectPrimitive.Positioner.Props["anchor"];
}) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Positioner
align={align}
alignItemWithTrigger={alignItemWithTrigger}
alignOffset={alignOffset}
anchor={anchor}
className="z-[130] select-none"
data-slot="select-positioner"
side={side}
sideOffset={sideOffset}
>
<SelectPrimitive.Popup
className="origin-(--transform-origin) rounded-lg text-foreground outline-none"
data-slot="select-popup"
{...props}
>
<SelectPrimitive.ScrollUpArrow
className="top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover"
data-slot="select-scroll-up-arrow"
>
<ChevronUpIcon className="relative size-4.5 sm:size-4" />
</SelectPrimitive.ScrollUpArrow>
<div
className={cn(
"dropdown-glass relative h-full rounded-lg shadow-[0_16px_40px_-18px_rgb(0_0_0/55%)] dark:shadow-[0_18px_44px_-18px_rgb(0_0_0/80%)]",
matchTriggerWidth && "min-w-(--anchor-width)",
popupClassName,
)}
>
<SelectPrimitive.List
className={cn("max-h-(--available-height) overflow-y-auto p-1", className)}
data-slot="select-list"
>
{children}
</SelectPrimitive.List>
</div>
<SelectPrimitive.ScrollDownArrow
className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover"
data-slot="select-scroll-down-arrow"
>
<ChevronDownIcon className="relative size-4.5 sm:size-4" />
</SelectPrimitive.ScrollDownArrow>
</SelectPrimitive.Popup>
</SelectPrimitive.Positioner>
</SelectPrimitive.Portal>
);
}
function SelectItem({
className,
children,
hideIndicator: _hideIndicator = false,
...props
}: SelectPrimitive.Item.Props & {
hideIndicator?: boolean;
}) {
return (
<SelectPrimitive.Item
className={cn(
"flex min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-pointer items-center rounded-sm px-2 py-1 text-base outline-none data-selected:bg-foreground/[0.08] data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className,
)}
data-slot="select-item"
{...props}
>
<SelectPrimitive.ItemText
className="min-w-0 flex-1 [&_svg:not([class*='text-'])]:text-muted-foreground"
data-slot="select-item-text"
>
{children}
</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
);
}
function SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) {
return (
<SelectPrimitive.Separator
className={cn("mx-2 my-1 h-px bg-border", className)}
data-slot="select-separator"
{...props}
/>
);
}
function SelectGroup(props: SelectPrimitive.Group.Props) {
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
}
function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
return (
<SelectPrimitive.GroupLabel
className="px-2 py-1.5 font-medium text-muted-foreground text-xs"
data-slot="select-group-label"
{...props}
/>
);
}
export {
Select,
SelectTrigger,
SelectButton,
selectTriggerVariants,
SelectValue,
SelectPopup,
SelectPopup as SelectContent,
SelectItem,
SelectSeparator,
SelectGroup,
SelectGroupLabel,
};