diff options
Diffstat (limited to 'packages/web-util/src/forms/InputLine.tsx')
-rw-r--r-- | packages/web-util/src/forms/InputLine.tsx | 120 |
1 files changed, 62 insertions, 58 deletions
diff --git a/packages/web-util/src/forms/InputLine.tsx b/packages/web-util/src/forms/InputLine.tsx index b8879f9ec..eb3238ef9 100644 --- a/packages/web-util/src/forms/InputLine.tsx +++ b/packages/web-util/src/forms/InputLine.tsx @@ -1,7 +1,7 @@ import { TranslatedString } from "@gnu-taler/taler-util"; import { ComponentChildren, Fragment, VNode, h } from "preact"; -import { useEffect, useState } from "preact/hooks"; -import { UIFormProps } from "./FormProvider.js"; +import { Addon, UIFormProps } from "./FormProvider.js"; +import { noHandlerPropsAndNoContextForField } from "./InputArray.js"; import { useField } from "./useField.js"; //@ts-ignore @@ -68,6 +68,37 @@ export function LabelWithTooltipMaybeRequired({ return WithTooltip; } +export function RenderAddon({ disabled, addon }: { disabled?: boolean, addon: Addon }): VNode { + switch (addon.type) { + case "text": { + return ( + <span class="inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm"> + {addon.text} + </span> + ); + } + case "icon": { + return ( + <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"> + {addon.icon} + </div> + ); + } + case "button": { + return ( + <button + type="button" + disabled={disabled} + onClick={addon.onClick} + class="relative -ml-px inline-flex items-center gap-x-1.5 rounded-l-md px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50" + > + {addon.children} + </button> + ); + } + } +} + function InputWrapper<T extends object, K extends keyof T>({ children, label, @@ -78,7 +109,11 @@ function InputWrapper<T extends object, K extends keyof T>({ error, disabled, required, -}: { error?: string; disabled: boolean, children: ComponentChildren } & UIFormProps<T, K>): VNode { +}: { + error?: string; + disabled: boolean; + children: ComponentChildren; +} & UIFormProps<T, K>): VNode { return ( <div class="sm:col-span-6"> <LabelWithTooltipMaybeRequired @@ -87,47 +122,11 @@ function InputWrapper<T extends object, K extends keyof T>({ tooltip={tooltip} /> <div class="relative mt-2 flex rounded-md shadow-sm"> - {before && - (before.type === "text" ? ( - <span class="inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm"> - {before.text} - </span> - ) : before.type === "icon" ? ( - <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"> - {before.icon} - </div> - ) : before.type === "button" ? ( - <button - type="button" - disabled={disabled} - onClick={before.onClick} - class="relative -ml-px inline-flex items-center gap-x-1.5 rounded-l-md px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50" - > - {before.children} - </button> - ) : undefined)} + {before && <RenderAddon disabled={disabled} addon={before} />} {children} - {after && - (after.type === "text" ? ( - <span class="inline-flex items-center rounded-r-md border border-l-0 border-gray-300 px-3 text-gray-500 sm:text-sm"> - {after.text} - </span> - ) : after.type === "icon" ? ( - <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3"> - {after.icon} - </div> - ) : after.type === "button" ? ( - <button - type="button" - disabled={disabled} - onClick={after.onClick} - class="relative -ml-px inline-flex items-center gap-x-1.5 rounded-r-md px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50" - > - {after.children} - </button> - ) : undefined)} + {after && <RenderAddon disabled={disabled} addon={after} />} </div> {error && ( <p class="mt-2 text-sm text-red-600" id="email-error"> @@ -156,19 +155,22 @@ export function InputLine<T extends object, K extends keyof T>( props: { type: InputType } & UIFormProps<T, K>, ): VNode { const { name, placeholder, before, after, converter, type } = props; - const { value, onChange, state, isDirty } = useField<T, K>(name); + //FIXME: remove deprecated + const fieldCtx = useField<T, K>(props.name); + const { value, onChange, state, error } = + props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name); - const [text, setText] = useState("") + // 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]) + // useEffect(() => { + // const newValue = toString(value); + // if (newValue) { + // setText(newValue); + // } + // }, [value]); if (state.hidden) return <div />; @@ -206,7 +208,7 @@ export function InputLine<T extends object, K extends keyof T>( } } } - const showError = isDirty && state.error; + const showError = value !== undefined && error; if (showError) { clazz += " text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500"; @@ -221,7 +223,7 @@ export function InputLine<T extends object, K extends keyof T>( {...props} help={props.help ?? state.help} disabled={state.disabled ?? false} - error={showError ? state.error : undefined} + error={showError ? error : undefined} > <textarea rows={4} @@ -242,21 +244,23 @@ export function InputLine<T extends object, K extends keyof T>( } return ( - <InputWrapper<T, K> {...props} + <InputWrapper<T, K> + {...props} help={props.help ?? state.help} - disabled={state.disabled ?? false} error={showError ? state.error : undefined} + disabled={state.disabled ?? false} + error={showError ? error : undefined} > <input name={String(name)} type={type} onChange={(e) => { - setText(e.currentTarget.value) + onChange(fromString(e.currentTarget.value)); }} placeholder={placeholder ? placeholder : undefined} - value={text} - onBlur={() => { - onChange(fromString(text)); - }} + value={toString(value) ?? ""} + // onBlur={() => { + // onChange(fromString(value as any)); + // }} // defaultValue={toString(value)} disabled={state.disabled} aria-invalid={showError} |