Files
comfy-downloader/src/components/Check.tsx
Vixalie ebac9d006b feat(components): 添加 Check 复选框组件
- 实现了一个新的复选框组件 Check
- 支持基本的复选框功能,包括选中、未选中和禁用状态
- 使用图标库来渲染选中和未选中状态
- 添加了隐藏的 input 元素,以便在表单中使用
- 组件具有良好的可定制性和扩展性
2025-08-12 14:00:51 +08:00

63 lines
1.6 KiB
TypeScript

import { Icon } from '@iconify-icon/solid';
import { isNotNil } from 'es-toolkit';
import {
createEffect,
createMemo,
createSignal,
mergeProps,
ParentComponent,
ParentProps,
Show,
} from 'solid-js';
interface CheckBoxProps {
name?: string;
checked?: boolean;
disabled?: boolean;
onChange?: (checked: boolean) => void;
}
const Check: ParentComponent<CheckBoxProps> = (props) => {
const mProps = mergeProps<ParentProps<CheckBoxProps>[]>(
{
disabled: false,
},
props,
);
const originalChecked = createMemo(() => mProps.checked);
const [internalChecked, setInternalChecked] = createSignal<boolean | undefined>(undefined);
createEffect(() => {
if (isNotNil(originalChecked()) && originalChecked() !== internalChecked()) {
setInternalChecked(originalChecked());
}
});
const handleClick = () => {
if (mProps.disabled) {
return;
}
console.debug('[Check]before', internalChecked());
setInternalChecked((prev) => !prev);
console.debug('[Check]after', internalChecked());
mProps.onChange?.(internalChecked());
};
return (
<div class="flex flex-row items-center gap-2 cursor-pointer" onClick={handleClick}>
<Icon
icon={internalChecked() ? 'hugeicons:checkmark-square-03' : 'hugeicons:square'}
class="text-[14px] stroke-1"
classList={{ 'text-primary': internalChecked() }}
/>
<div>{mProps.children}</div>
<Show when={isNotNil(mProps.name)}>
<input type="hidden" name={mProps.name} value={internalChecked()} />
</Show>
</div>
);
};
export default Check;