refactor(input): consolidate input components and update exports

Move input component files to lowercase directory and simplify structure
Remove unused button and password input components
Update exports in components index file
This commit is contained in:
icarus 2025-11-02 23:38:49 +08:00
parent cad71c3af7
commit 3911ee2843
6 changed files with 46 additions and 67 deletions

View File

@ -84,7 +84,7 @@ export { Sortable } from './composites/Sortable'
export * from './primitives/button'
export * from './primitives/command'
export * from './primitives/dialog'
export * from './primitives/Input'
export * from './primitives/input'
export * from './primitives/popover'
export * from './primitives/radioGroup'
export * from './primitives/shadcn-io/dropzone'

View File

@ -1 +0,0 @@
export function WithButton() {}

View File

@ -1,14 +0,0 @@
import { WithButton } from './button'
import { Input as InternalInput } from './input'
import { Password } from './password'
type CompoundedComponent = typeof InternalInput & {
Password: typeof Password
Button: typeof WithButton
}
const Input: CompoundedComponent = InternalInput as CompoundedComponent
Input.Password = Password
Input.Button = WithButton
export { Input }

View File

@ -1,50 +0,0 @@
import { cn } from '@cherrystudio/ui/utils'
import React from 'react'
interface BaseInputProps extends React.ComponentPropsWithRef<'input'> {
startContent?: React.ReactNode
endContent?: React.ReactNode
}
interface WithLabel extends BaseInputProps {
label: string
caption?: string
}
interface WithoutLabel extends BaseInputProps {
label?: never
caption?: never
}
type InputProps = WithLabel | WithoutLabel
export function Input({ className, type, required, label, caption, ...props }: InputProps) {
const id = React.useId()
const input = (
<input
type={type}
data-slot="input"
id={id}
className={cn(
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-2xs border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'focus-visible:border-primary focus-visible:ring-primary/50 focus-visible:ring-[3px]',
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
className
)}
required={required}
{...props}
/>
)
if (label !== undefined) {
return (
<div className="flex flex-col w-full">
<label htmlFor={id}>{label}</label>
{input}
{caption && <div className="text-muted-foreground">{caption}</div>}
</div>
)
}
return input
}

View File

@ -1 +0,0 @@
export function Password() {}

View File

@ -0,0 +1,45 @@
import { cn } from '@cherrystudio/ui/utils'
import React, { useMemo } from 'react'
export interface InputProps extends React.ComponentPropsWithRef<'input'> {
startContent?: React.ReactNode
endContent?: React.ReactNode
label?: string
caption?: string
}
export function Input({ className, type, required, label, caption, ...props }: InputProps) {
const id = React.useId()
const input = useMemo(() => {
const input = (
<input
type={type}
data-slot="input"
id={id}
className={cn(
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-2xs border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'focus-visible:border-primary focus-visible:ring-primary/50 focus-visible:ring-[3px]',
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
className
)}
required={required}
{...props}
/>
)
return input
}, [className, id, props, required, type])
if (label !== undefined) {
return (
<div className="flex flex-col w-full">
<label htmlFor={id}>{label}</label>
{input}
{caption && <div className="text-muted-foreground">{caption}</div>}
</div>
)
}
return input
}