import { TranslatedString } from "@gnu-taler/taler-util";
import { ComponentChildren, Fragment, VNode, h } from "preact";
import { Addon, UIFormProps } from "./FormProvider.js";
import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { useField } from "./useField.js";
//@ts-ignore
const TooltipIcon = (
);
export function LabelWithTooltipMaybeRequired({
label,
required,
tooltip,
}: {
label: TranslatedString;
required?: boolean;
tooltip?: TranslatedString;
}): VNode {
const Label = (
);
const WithTooltip = tooltip ? (
) : (
Label
);
if (required) {
return (
{WithTooltip}
*
);
}
return WithTooltip;
}
export function RenderAddon({ disabled, addon }: { disabled?: boolean, addon: Addon }): VNode {
switch (addon.type) {
case "text": {
return (
{addon.text}
);
}
case "icon": {
return (
{addon.icon}
);
}
case "button": {
return (
);
}
}
}
function InputWrapper({
children,
label,
tooltip,
before,
after,
help,
error,
disabled,
required,
}: {
error?: string;
disabled: boolean;
children: ComponentChildren;
} & UIFormProps): VNode {
return (
{before && }
{children}
{after && }
{error && (
{error}
)}
{help && (
{help}
)}
);
}
function defaultToString(v: unknown) {
return v === undefined ? "" : typeof v !== "object" ? String(v) : "";
}
function defaultFromString(v: string) {
return v;
}
type InputType = "text" | "text-area" | "password" | "email" | "number";
export function InputLine(
props: { type: InputType } & UIFormProps,
): VNode {
const { name, placeholder, before, after, converter, type } = props;
//FIXME: remove deprecated
const fieldCtx = useField(props.name);
const { value, onChange, state, error } =
props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name);
// const [text, setText] = useState("");
const fromString: (s: string) => any =
converter?.fromStringUI ?? defaultFromString;
const toString: (s: any) => string = converter?.toStringUI ?? defaultToString;
// useEffect(() => {
// const newValue = toString(value);
// if (newValue) {
// setText(newValue);
// }
// }, [value]);
if (state.hidden) return ;
let clazz =
"block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200";
if (before) {
switch (before.type) {
case "icon": {
clazz += " pl-10";
break;
}
case "button": {
clazz += " rounded-none rounded-r-md ";
break;
}
case "text": {
clazz += " min-w-0 flex-1 rounded-r-md rounded-none ";
break;
}
}
}
if (after) {
switch (after.type) {
case "icon": {
clazz += " pr-10";
break;
}
case "button": {
clazz += " rounded-none rounded-l-md";
break;
}
case "text": {
clazz += " min-w-0 flex-1 rounded-l-md rounded-none ";
break;
}
}
}
const showError = value !== undefined && error;
if (showError) {
clazz +=
" text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500";
} else {
clazz +=
" text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-indigo-600";
}
if (type === "text-area") {
return (
{...props}
help={props.help ?? state.help}
disabled={state.disabled ?? false}
error={showError ? error : undefined}
>
);
}
return (
{...props}
help={props.help ?? state.help}
disabled={state.disabled ?? false}
error={showError ? error : undefined}
>
{
onChange(fromString(e.currentTarget.value));
}}
placeholder={placeholder ? placeholder : undefined}
value={toString(value) ?? ""}
// onBlur={() => {
// onChange(fromString(value as any));
// }}
// defaultValue={toString(value)}
disabled={state.disabled}
aria-invalid={showError}
// aria-describedby="email-error"
class={clazz}
/>
);
}