87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
import { TranslatedString } from "@gnu-taler/taler-util";
|
|
import { Fragment, VNode, h } from "preact";
|
|
import { LabelWithTooltipMaybeRequired, UIFormProps } from "./InputLine.js";
|
|
import { useField } from "./useField.js";
|
|
|
|
export interface Choice<V> {
|
|
label: TranslatedString;
|
|
value: V;
|
|
}
|
|
|
|
export function InputChoiceHorizontal<T extends object, K extends keyof T>(
|
|
props: {
|
|
choices: Choice<T[K]>[];
|
|
} & UIFormProps<T, K>,
|
|
): VNode {
|
|
const {
|
|
choices,
|
|
name,
|
|
label,
|
|
tooltip,
|
|
help,
|
|
placeholder,
|
|
required,
|
|
before,
|
|
after,
|
|
converter,
|
|
} = props;
|
|
const { value, onChange, state, isDirty } = useField<T, K>(name);
|
|
if (state.hidden) {
|
|
return <Fragment />;
|
|
}
|
|
|
|
return (
|
|
<div class="sm:col-span-6">
|
|
<LabelWithTooltipMaybeRequired
|
|
label={label}
|
|
required={required}
|
|
tooltip={tooltip}
|
|
/>
|
|
<fieldset class="mt-2">
|
|
<div class="isolate inline-flex rounded-md shadow-sm">
|
|
{choices.map((choice, idx) => {
|
|
const isFirst = idx === 0;
|
|
const isLast = idx === choices.length - 1;
|
|
let clazz =
|
|
"relative inline-flex items-center px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 focus:z-10";
|
|
if (choice.value === value) {
|
|
clazz +=
|
|
" text-white bg-indigo-600 hover:bg-indigo-500 ring-2 ring-indigo-600 hover:ring-indigo-500";
|
|
} else {
|
|
clazz += " hover:bg-gray-100 border-gray-300";
|
|
}
|
|
if (isFirst) {
|
|
clazz += " rounded-l-md";
|
|
} else {
|
|
clazz += " -ml-px";
|
|
}
|
|
if (isLast) {
|
|
clazz += " rounded-r-md";
|
|
}
|
|
return (
|
|
<button
|
|
type="button"
|
|
class={clazz}
|
|
onClick={(e) => {
|
|
onChange(
|
|
(value === choice.value ? undefined : choice.value) as T[K],
|
|
);
|
|
}}
|
|
>
|
|
{(!converter
|
|
? (choice.value as string)
|
|
: converter?.toStringUI(choice.value)) ?? ""}
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</fieldset>
|
|
{help && (
|
|
<p class="mt-2 text-sm text-gray-500" id="email-description">
|
|
{help}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|