80 lines
2.2 KiB
TypeScript
80 lines
2.2 KiB
TypeScript
import {
|
|
ComponentProps,
|
|
DetailedHTMLProps,
|
|
InputHTMLAttributes,
|
|
LabelHTMLAttributes,
|
|
} from "react";
|
|
import Row from "../layout/Row";
|
|
import twuiSlugify from "../utils/slugify";
|
|
import twuiSlugToNormalText from "../utils/slug-to-normal-text";
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
type Value = {
|
|
value: string;
|
|
title?: string;
|
|
default?: boolean;
|
|
};
|
|
|
|
export type TWUI_FORM_RADIO_PROPS = {
|
|
values: Value[];
|
|
name: string;
|
|
inputProps?: DetailedHTMLProps<
|
|
InputHTMLAttributes<HTMLInputElement>,
|
|
HTMLInputElement
|
|
>;
|
|
labelProps?: DetailedHTMLProps<
|
|
LabelHTMLAttributes<HTMLLabelElement>,
|
|
HTMLLabelElement
|
|
>;
|
|
wrapperProps?: ComponentProps<typeof Row>;
|
|
changeHandler?: (value: string) => void;
|
|
};
|
|
|
|
/**
|
|
* # Form Radios Component
|
|
* @className twui-textarea
|
|
*/
|
|
export default function Radios({
|
|
values,
|
|
name,
|
|
inputProps,
|
|
labelProps,
|
|
wrapperProps,
|
|
changeHandler,
|
|
}: TWUI_FORM_RADIO_PROPS) {
|
|
const finalName = twuiSlugify(name);
|
|
const finalTitle = twuiSlugToNormalText(finalName);
|
|
|
|
return (
|
|
<Row
|
|
title={finalTitle}
|
|
{...wrapperProps}
|
|
className={twMerge("gap-4", wrapperProps?.className)}
|
|
>
|
|
{values.map((v, i) => {
|
|
const valueName = twuiSlugify(`${finalName}-${v.value}`);
|
|
const valueTitle = v.title || twuiSlugToNormalText(v.value);
|
|
|
|
return (
|
|
<Row key={i} className="gap-1.5">
|
|
<input
|
|
id={valueName}
|
|
type="radio"
|
|
defaultChecked={v.default}
|
|
name={finalName}
|
|
onChange={(e) => {
|
|
const targetValue = v.value;
|
|
changeHandler?.(targetValue);
|
|
}}
|
|
{...inputProps}
|
|
/>
|
|
<label htmlFor={valueName} {...labelProps}>
|
|
{valueTitle}
|
|
</label>
|
|
</Row>
|
|
);
|
|
})}
|
|
</Row>
|
|
);
|
|
}
|