forked from admin/hair-keeper
68 lines
1.6 KiB
TypeScript
68 lines
1.6 KiB
TypeScript
'use client'
|
|
|
|
import React from 'react'
|
|
import { Checkbox } from '@/components/ui/checkbox'
|
|
import { Label } from '@/components/ui/label'
|
|
|
|
export interface CheckboxOption {
|
|
id: number | string
|
|
name: string
|
|
[key: string]: any // 允许额外的属性
|
|
}
|
|
|
|
export interface CheckboxGroupProps {
|
|
options: CheckboxOption[]
|
|
value?: (number | string)[]
|
|
onChange?: (value: (number | string)[]) => void
|
|
className?: string
|
|
itemClassName?: string
|
|
labelClassName?: string
|
|
idPrefix?: string
|
|
disabled?: boolean
|
|
}
|
|
|
|
export function CheckboxGroup({
|
|
options,
|
|
value = [],
|
|
onChange,
|
|
className = "space-y-2",
|
|
itemClassName = "flex items-center space-x-2",
|
|
labelClassName = "text-sm",
|
|
idPrefix = "checkbox",
|
|
disabled = false,
|
|
}: CheckboxGroupProps) {
|
|
const handleToggle = (optionId: number | string, checked: boolean) => {
|
|
const newValue = checked
|
|
? [...value, optionId]
|
|
: value.filter((id) => id !== optionId)
|
|
onChange?.(newValue)
|
|
}
|
|
|
|
if (!options || options.length === 0) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className={className}>
|
|
{options.map((option) => (
|
|
<div key={option.id} className={itemClassName}>
|
|
<Checkbox
|
|
id={`${idPrefix}-${option.id}`}
|
|
checked={value.includes(option.id)}
|
|
onCheckedChange={(checked) =>
|
|
handleToggle(option.id, checked as boolean)
|
|
}
|
|
disabled={disabled}
|
|
/>
|
|
<Label
|
|
htmlFor={`${idPrefix}-${option.id}`}
|
|
className={labelClassName}
|
|
>
|
|
{option.name}
|
|
</Label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|