31 lines
1.2 KiB
TypeScript
31 lines
1.2 KiB
TypeScript
import { effect, h } from '@ui-arch/frame';
|
|
import type { RadioGroupProps } from './types.js';
|
|
|
|
/*** 单选组:value 信号双向绑定,options 同组互斥,name 固定保证原生互斥行为 ***/
|
|
export function radioGroup(props: RadioGroupProps): HTMLElement {
|
|
const groupName = `ua-radio-${Math.random().toString(36).slice(2, 8)}`; // 组内唯一 name
|
|
const radios: HTMLInputElement[] = [];
|
|
for (const opt of props.options) {
|
|
const input = h('input', {
|
|
type: 'radio',
|
|
name: groupName,
|
|
class: 'ua-radio',
|
|
disabled: props.disabled, // 布尔或信号禁用,h() 直接透传
|
|
}) as HTMLInputElement;
|
|
input.value = opt.value;
|
|
radios.push(input);
|
|
input.addEventListener('change', () => {
|
|
if (props.value) props.value(input.value); // 用户选择写回信号
|
|
props.onChange?.(input.value);
|
|
});
|
|
}
|
|
if (props.value) {
|
|
const value = props.value;
|
|
effect(() => {
|
|
for (const input of radios) input.checked = input.value === value(); // 外部变化同步勾选态
|
|
});
|
|
}
|
|
const rows = props.options.map((opt, i) => h('label', { class: 'ua-check-row' }, radios[i], opt.label));
|
|
return h('div', { class: 'ua-radio-group' }, ...rows);
|
|
}
|