snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
297
apps/v4/registry/bases/aria/ui/select.tsx
Normal file
297
apps/v4/registry/bases/aria/ui/select.tsx
Normal file
@@ -0,0 +1,297 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { cn } from "cn"
|
||||
import {
|
||||
Button as ButtonPrimitive,
|
||||
composeRenderProps,
|
||||
Header as HeaderPrimitive,
|
||||
ListBoxItem as ListBoxItemPrimitive,
|
||||
ListBox as ListBoxPrimitive,
|
||||
ListBoxSection as ListBoxSectionPrimitive,
|
||||
Popover as PopoverPrimitive,
|
||||
SearchField,
|
||||
Select as SelectPrimitive,
|
||||
SelectValue as SelectValuePrimitive,
|
||||
Separator as SeparatorPrimitive,
|
||||
type ListBoxProps,
|
||||
type SearchFieldProps,
|
||||
type ListBoxSectionProps as SelectGroupProps,
|
||||
type SelectProps,
|
||||
type SelectValueProps,
|
||||
} from "react-aria-components"
|
||||
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupInput,
|
||||
} from "@/registry/bases/aria/ui/input-group"
|
||||
import { IconPlaceholder } from "@/app/(create)/components/icon-placeholder"
|
||||
|
||||
function Select<T extends object, M extends "single" | "multiple" = "single">({
|
||||
className,
|
||||
...props
|
||||
}: SelectProps<T, M>) {
|
||||
return (
|
||||
<SelectPrimitive
|
||||
data-slot="select"
|
||||
className={cn("w-fit", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectGroup<T extends object>({
|
||||
className,
|
||||
...props
|
||||
}: SelectGroupProps<T>) {
|
||||
return (
|
||||
<ListBoxSectionPrimitive
|
||||
data-slot="select-group"
|
||||
className={cn("cn-select-group", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectValue<T extends object>({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: SelectValueProps<T>) {
|
||||
return (
|
||||
<SelectValuePrimitive
|
||||
data-slot="select-value"
|
||||
className={cn("cn-select-value cn-select-value-aria", className)}
|
||||
{...props}
|
||||
>
|
||||
{typeof children === "function"
|
||||
? children
|
||||
: ({ selectedItems, selectedText, defaultChildren }) =>
|
||||
selectedItems.length > 1 ? selectedText : defaultChildren}
|
||||
</SelectValuePrimitive>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectTrigger({
|
||||
className,
|
||||
size = "default",
|
||||
children,
|
||||
...props
|
||||
}: Omit<React.ComponentProps<typeof ButtonPrimitive>, "children"> & {
|
||||
children?: React.ReactNode
|
||||
size?: "sm" | "default"
|
||||
}) {
|
||||
return (
|
||||
<ButtonPrimitive
|
||||
data-slot="select-trigger"
|
||||
data-size={size}
|
||||
className={cn(
|
||||
"cn-select-trigger flex w-full items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<IconPlaceholder
|
||||
lucide="ChevronDownIcon"
|
||||
tabler="IconSelector"
|
||||
hugeicons="UnfoldMoreIcon"
|
||||
phosphor="CaretDownIcon"
|
||||
remixicon="RiArrowDownSLine"
|
||||
className="cn-select-trigger-icon pointer-events-none"
|
||||
/>
|
||||
</ButtonPrimitive>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectContent({
|
||||
className,
|
||||
children,
|
||||
placement = "bottom",
|
||||
offset = 4,
|
||||
crossOffset = 0,
|
||||
...props
|
||||
}: Omit<
|
||||
React.ComponentProps<typeof PopoverPrimitive>,
|
||||
"className" | "children"
|
||||
> & {
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<SelectPopover
|
||||
className={className}
|
||||
placement={placement}
|
||||
offset={offset}
|
||||
crossOffset={crossOffset}
|
||||
{...props}
|
||||
>
|
||||
<SelectList>{children}</SelectList>
|
||||
</SelectPopover>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectPopover({
|
||||
className,
|
||||
children,
|
||||
placement = "bottom start",
|
||||
offset = 4,
|
||||
crossOffset = 0,
|
||||
...props
|
||||
}: Omit<
|
||||
React.ComponentProps<typeof PopoverPrimitive>,
|
||||
"className" | "children"
|
||||
> & {
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<PopoverPrimitive
|
||||
data-slot="select-content"
|
||||
placement={placement}
|
||||
offset={offset}
|
||||
crossOffset={crossOffset}
|
||||
className={cn(
|
||||
"cn-select-content-aria cn-menu-target cn-menu-translucent cn-menu-translucent-aria relative isolate z-50 w-(--trigger-width) origin-(--trigger-anchor-point) overflow-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</PopoverPrimitive>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectList<T extends object>({
|
||||
className,
|
||||
...props
|
||||
}: ListBoxProps<T>) {
|
||||
return (
|
||||
<ListBoxPrimitive
|
||||
data-slot="select-list"
|
||||
className={cn(
|
||||
"group/select-list max-h-[inherit] overflow-x-hidden overflow-y-auto p-0 outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectInput({ className, ...props }: SearchFieldProps) {
|
||||
return (
|
||||
<SearchField
|
||||
{...props}
|
||||
autoFocus
|
||||
data-slot="select-input-wrapper"
|
||||
className={cn("p-1 pb-0", className)}
|
||||
>
|
||||
<InputGroup>
|
||||
<InputGroupInput
|
||||
data-slot="select-input"
|
||||
className="[&::-webkit-search-cancel-button]:hidden"
|
||||
/>
|
||||
<InputGroupAddon>
|
||||
<IconPlaceholder
|
||||
lucide="SearchIcon"
|
||||
tabler="IconSearch"
|
||||
hugeicons="SearchIcon"
|
||||
phosphor="MagnifyingGlassIcon"
|
||||
remixicon="RiSearchLine"
|
||||
className="cn-command-input-icon"
|
||||
/>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
</SearchField>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectLabel({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof HeaderPrimitive>) {
|
||||
return (
|
||||
<HeaderPrimitive
|
||||
data-slot="select-label"
|
||||
className={cn("cn-select-label", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectItem({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ListBoxItemPrimitive>) {
|
||||
return (
|
||||
<ListBoxItemPrimitive
|
||||
data-slot="select-item"
|
||||
textValue={typeof children === "string" ? children : undefined}
|
||||
className={cn(
|
||||
"cn-select-item cn-select-item-aria relative flex w-full cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{composeRenderProps(children, (children, { isSelected }) => (
|
||||
<>
|
||||
<span className="cn-select-item-text shrink-0 whitespace-nowrap">
|
||||
{children}
|
||||
</span>
|
||||
<span className="cn-select-item-indicator">
|
||||
{isSelected ? (
|
||||
<IconPlaceholder
|
||||
lucide="CheckIcon"
|
||||
tabler="IconCheck"
|
||||
hugeicons="Tick02Icon"
|
||||
phosphor="CheckIcon"
|
||||
remixicon="RiCheckLine"
|
||||
className="cn-select-item-indicator-icon pointer-events-none"
|
||||
/>
|
||||
) : null}
|
||||
</span>
|
||||
</>
|
||||
))}
|
||||
</ListBoxItemPrimitive>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SeparatorPrimitive>) {
|
||||
return (
|
||||
<SeparatorPrimitive
|
||||
data-slot="select-separator"
|
||||
className={cn("cn-select-separator pointer-events-none", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SelectEmpty({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="select-empty"
|
||||
className={cn("cn-select-empty-aria", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectInput,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectList,
|
||||
SelectPopover,
|
||||
SelectSeparator,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
SelectEmpty,
|
||||
}
|
||||
Reference in New Issue
Block a user