mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-30 07:39:06 +08:00
- Changed utility imports from '@cherrystudio/ui/utils' to '@cherrystudio/ui/lib/utils' across multiple components for better organization. - Introduced a new internal utility module for class name merging, ensuring consistent usage across the UI components. - Updated relevant components to reflect the new import paths, enhancing maintainability and clarity.
117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import { cn } from '@cherrystudio/ui/lib/utils'
|
|
import { composeEventHandlers } from '@radix-ui/primitive'
|
|
import { useCallbackRef } from '@radix-ui/react-use-callback-ref'
|
|
import { useControllableState } from '@radix-ui/react-use-controllable-state'
|
|
import { cva } from 'class-variance-authority'
|
|
import * as React from 'react'
|
|
|
|
/* -------------------------------------------------------------------------------------------------
|
|
* Variants
|
|
* -----------------------------------------------------------------------------------------------*/
|
|
|
|
const textareaVariants = cva(
|
|
cn(
|
|
'flex field-sizing-content min-h-16 w-full border bg-transparent px-4 py-3 text-lg shadow-xs transition-[color,box-shadow] outline-none resize-y',
|
|
'rounded-xs',
|
|
'border-input text-foreground placeholder:text-foreground-secondary',
|
|
'focus-visible:border-primary focus-visible:ring-ring focus-visible:ring-[3px]',
|
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
'md:text-sm'
|
|
),
|
|
{
|
|
variants: {
|
|
hasError: {
|
|
true: 'aria-invalid:border-destructive aria-invalid:ring-destructive/20',
|
|
false: ''
|
|
}
|
|
},
|
|
defaultVariants: {
|
|
hasError: false
|
|
}
|
|
}
|
|
)
|
|
|
|
/* -------------------------------------------------------------------------------------------------
|
|
* TextareaInput
|
|
* -----------------------------------------------------------------------------------------------*/
|
|
|
|
const INPUT_NAME = 'TextareaInput'
|
|
|
|
interface TextareaInputProps extends Omit<React.ComponentPropsWithoutRef<'textarea'>, 'value' | 'defaultValue'> {
|
|
value?: string
|
|
defaultValue?: string
|
|
onValueChange?: (value: string) => void
|
|
hasError?: boolean
|
|
ref?: React.Ref<HTMLTextAreaElement>
|
|
}
|
|
|
|
function TextareaInput({
|
|
value: valueProp,
|
|
defaultValue,
|
|
onValueChange,
|
|
hasError = false,
|
|
className,
|
|
ref,
|
|
...props
|
|
}: TextareaInputProps) {
|
|
const [value = '', setValue] = useControllableState({
|
|
prop: valueProp,
|
|
defaultProp: defaultValue ?? '',
|
|
onChange: onValueChange
|
|
})
|
|
|
|
const handleChange = useCallbackRef((event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
const newValue = event.target.value
|
|
if (props.maxLength && newValue.length > props.maxLength) {
|
|
return
|
|
}
|
|
setValue(newValue)
|
|
})
|
|
|
|
return (
|
|
<textarea
|
|
data-slot="textarea-input"
|
|
{...props}
|
|
ref={ref}
|
|
value={value}
|
|
onChange={composeEventHandlers(props.onChange, handleChange)}
|
|
aria-invalid={hasError}
|
|
className={cn(textareaVariants({ hasError }), className)}
|
|
/>
|
|
)
|
|
}
|
|
|
|
TextareaInput.displayName = INPUT_NAME
|
|
|
|
/* -------------------------------------------------------------------------------------------------
|
|
* TextareaCharCount
|
|
* -----------------------------------------------------------------------------------------------*/
|
|
|
|
const CHAR_COUNT_NAME = 'TextareaCharCount'
|
|
|
|
interface TextareaCharCountProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
value?: string
|
|
maxLength?: number
|
|
}
|
|
|
|
function TextareaCharCount({ value = '', maxLength, className, ...props }: TextareaCharCountProps) {
|
|
return (
|
|
<div
|
|
data-slot="textarea-char-count"
|
|
{...props}
|
|
className={cn('absolute bottom-2 right-2 text-xs text-muted-foreground', className)}>
|
|
{value.length}/{maxLength}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
TextareaCharCount.displayName = CHAR_COUNT_NAME
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
const Input = TextareaInput
|
|
const CharCount = TextareaCharCount
|
|
|
|
export { CharCount, Input }
|
|
export type { TextareaCharCountProps, TextareaInputProps }
|