145a6fce8f
Select reescrito de @base-ui/react primitives a <select> nativo con wrapper para mantener la misma API visual (ChevronDown, estilos tema). SimpleSelect actualizado para usar <select>/<optgroup> directamente sin intermediarios. Checkbox corregido: import CheckboxIndicator separado reemplazado por CheckboxPrimitive.Indicator para consistencia. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
"use client"
|
|
|
|
import * as React from "react"
|
|
import { cn } from "../core/cn"
|
|
import { ChevronDown } from "lucide-react"
|
|
|
|
// ── Native select wrapper ─────────────────────────────────────────────────
|
|
|
|
interface SelectProps extends React.ComponentPropsWithoutRef<"select"> {
|
|
placeholder?: string
|
|
}
|
|
|
|
const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
({ className, children, placeholder, ...props }, ref) => {
|
|
return (
|
|
<div className="relative">
|
|
<select
|
|
ref={ref}
|
|
data-slot="select"
|
|
className={cn(
|
|
"flex h-8 w-full appearance-none items-center rounded-lg border border-input bg-transparent px-2.5 pr-8 py-1 text-sm transition-colors outline-none",
|
|
"focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
"aria-invalid:border-destructive aria-invalid:ring-destructive/20",
|
|
className,
|
|
)}
|
|
{...props}
|
|
>
|
|
{placeholder && (
|
|
<option value="" disabled>
|
|
{placeholder}
|
|
</option>
|
|
)}
|
|
{children}
|
|
</select>
|
|
<ChevronDown className="pointer-events-none absolute right-2 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
</div>
|
|
)
|
|
},
|
|
)
|
|
Select.displayName = "Select"
|
|
|
|
// ── Sub-components (thin wrappers for API compatibility) ──────────────────
|
|
|
|
function SelectItem({
|
|
className,
|
|
...props
|
|
}: React.ComponentPropsWithoutRef<"option">) {
|
|
return <option className={className} {...props} />
|
|
}
|
|
|
|
function SelectGroup({
|
|
className,
|
|
...props
|
|
}: React.ComponentPropsWithoutRef<"optgroup">) {
|
|
return <optgroup className={className} {...props} />
|
|
}
|
|
|
|
function SelectGroupLabel(_props: { children?: React.ReactNode }) {
|
|
// optgroup uses `label` attr, this is a no-op for compatibility
|
|
return null
|
|
}
|
|
|
|
// Stubs for barrel export compatibility — these are no-ops with native select
|
|
function SelectContent({ children }: { children?: React.ReactNode; className?: string }) {
|
|
return <>{children}</>
|
|
}
|
|
function SelectTrigger({ children }: { children?: React.ReactNode; className?: string }) {
|
|
return <>{children}</>
|
|
}
|
|
function SelectValue(_props: { placeholder?: string }) {
|
|
return null
|
|
}
|
|
function SelectPortal({ children }: { children?: React.ReactNode }) {
|
|
return <>{children}</>
|
|
}
|
|
function SelectSeparator({ className, ...props }: React.ComponentProps<"div">) {
|
|
return <div className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
|
|
}
|
|
|
|
export {
|
|
Select,
|
|
SelectContent,
|
|
SelectGroup,
|
|
SelectGroupLabel,
|
|
SelectItem,
|
|
SelectPortal,
|
|
SelectSeparator,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
}
|