diff options
author | Sebastian <sebasjm@gmail.com> | 2024-05-03 08:43:53 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-05-03 08:44:07 -0300 |
commit | 20353eda268efa962959bead466b59823bfb9b29 (patch) | |
tree | 868d016693f09b40e2c55893d3aed72eca505ecb /packages/web-util/src | |
parent | fa4c7039f4ebeb6ad3cf19237ad7b138519ac142 (diff) |
form hook now takes the shape of the form (do not rely on initial value)
Diffstat (limited to 'packages/web-util/src')
-rw-r--r-- | packages/web-util/src/forms/Caption.tsx | 17 | ||||
-rw-r--r-- | packages/web-util/src/forms/Group.tsx | 38 | ||||
-rw-r--r-- | packages/web-util/src/forms/InputAmount.tsx | 6 | ||||
-rw-r--r-- | packages/web-util/src/forms/InputChoiceHorizontal.tsx | 8 | ||||
-rw-r--r-- | packages/web-util/src/forms/InputLine.tsx | 83 |
5 files changed, 70 insertions, 82 deletions
diff --git a/packages/web-util/src/forms/Caption.tsx b/packages/web-util/src/forms/Caption.tsx index 8facddec3..be4725ffa 100644 --- a/packages/web-util/src/forms/Caption.tsx +++ b/packages/web-util/src/forms/Caption.tsx @@ -1,27 +1,22 @@ import { TranslatedString } from "@gnu-taler/taler-util"; import { VNode, h } from "preact"; -import { - LabelWithTooltipMaybeRequired -} from "./InputLine.js"; +import { LabelWithTooltipMaybeRequired, RenderAddon } from "./InputLine.js"; +import { Addon } from "./FormProvider.js"; interface Props { label: TranslatedString; tooltip?: TranslatedString; help?: TranslatedString; - before?: VNode; - after?: VNode; + before?: Addon; + after?: Addon; } export function Caption({ before, after, label, tooltip, help }: Props): VNode { return ( <div class="sm:col-span-6 flex"> - {before !== undefined && ( - <span class="pointer-events-none flex items-center pr-2">{before}</span> - )} + {before !== undefined && <RenderAddon addon={before} />} <LabelWithTooltipMaybeRequired label={label} tooltip={tooltip} /> - {after !== undefined && ( - <span class="pointer-events-none flex items-center pl-2">{after}</span> - )} + {after !== undefined && <RenderAddon addon={after} />} {help && ( <p class="mt-2 text-sm text-gray-500" id="email-description"> {help} diff --git a/packages/web-util/src/forms/Group.tsx b/packages/web-util/src/forms/Group.tsx index 0645f6d97..d5626be1d 100644 --- a/packages/web-util/src/forms/Group.tsx +++ b/packages/web-util/src/forms/Group.tsx @@ -1,41 +1,39 @@ import { TranslatedString } from "@gnu-taler/taler-util"; import { VNode, h } from "preact"; -import { LabelWithTooltipMaybeRequired } from "./InputLine.js"; +import { LabelWithTooltipMaybeRequired, RenderAddon } from "./InputLine.js"; import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js"; +import { Addon } from "./FormProvider.js"; interface Props { - before?: TranslatedString; - after?: TranslatedString; - tooltipBefore?: TranslatedString; - tooltipAfter?: TranslatedString; + label: TranslatedString; + tooltip?: TranslatedString; + help?: TranslatedString; + before?: Addon; + after?: Addon; fields: UIFormField[]; } export function Group({ before, after, - tooltipAfter, - tooltipBefore, + label, + tooltip, + help, fields, }: Props): VNode { return ( <div class="sm:col-span-6 p-4 rounded-lg border-r-2 border-2 bg-gray-50"> - <div class="pb-4"> - {before && ( - <LabelWithTooltipMaybeRequired - label={before} - tooltip={tooltipBefore} - /> - )} - </div> + {before !== undefined && <RenderAddon addon={before} />} + <LabelWithTooltipMaybeRequired label={label} tooltip={tooltip} /> + {after !== undefined && <RenderAddon addon={after} />} + {help && ( + <p class="mt-2 text-sm text-gray-500" id="email-description"> + {help} + </p> + )} <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-6"> <RenderAllFieldsByUiConfig fields={fields} /> </div> - <div class="pt-4"> - {after && ( - <LabelWithTooltipMaybeRequired label={after} tooltip={tooltipAfter} /> - )} - </div> </div> ); } diff --git a/packages/web-util/src/forms/InputAmount.tsx b/packages/web-util/src/forms/InputAmount.tsx index 31e83350e..e8683468e 100644 --- a/packages/web-util/src/forms/InputAmount.tsx +++ b/packages/web-util/src/forms/InputAmount.tsx @@ -23,15 +23,15 @@ export function InputAmount<T extends object, K extends keyof T>( type: "text", text: currency as TranslatedString, }} - converter={{ - //@ts-ignore + //@ts-ignore + converter={ props.converter ?? { + fromStringUI: (v): AmountJson => { return ( Amounts.parse(`${currency}:${v}`) ?? Amounts.zeroOfCurrency(currency) ); }, - //@ts-ignore toStringUI: (v: AmountJson) => { return v === undefined ? "" : Amounts.stringifyValue(v); }, diff --git a/packages/web-util/src/forms/InputChoiceHorizontal.tsx b/packages/web-util/src/forms/InputChoiceHorizontal.tsx index 82a7c3115..d8361718d 100644 --- a/packages/web-util/src/forms/InputChoiceHorizontal.tsx +++ b/packages/web-util/src/forms/InputChoiceHorizontal.tsx @@ -12,10 +12,10 @@ export interface ChoiceH<V> { export function InputChoiceHorizontal<T extends object, K extends keyof T>( props: { - choices: ChoiceH<T[K]>[]; + choices: ChoiceH<string>[]; } & UIFormProps<T, K>, ): VNode { - const { choices, label, tooltip, help, required } = props; + const { choices, label, tooltip, help, required, converter } = props; //FIXME: remove deprecated const fieldCtx = useField<T, K>(props.name); const { value, onChange, state } = @@ -38,7 +38,7 @@ export function InputChoiceHorizontal<T extends object, K extends keyof T>( 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) { + if (converter?.fromStringUI(choice.value as any) === value) { clazz += " text-white bg-indigo-600 hover:bg-indigo-500 ring-2 ring-indigo-600 hover:ring-indigo-500"; } else { @@ -61,7 +61,7 @@ export function InputChoiceHorizontal<T extends object, K extends keyof T>( class={clazz} onClick={(e) => { onChange( - (value === choice.value ? undefined : choice.value) as any, + (value === choice.value ? undefined : converter?.fromStringUI(choice.value as any)) as any, ); }} > diff --git a/packages/web-util/src/forms/InputLine.tsx b/packages/web-util/src/forms/InputLine.tsx index ee9150492..eb3238ef9 100644 --- a/packages/web-util/src/forms/InputLine.tsx +++ b/packages/web-util/src/forms/InputLine.tsx @@ -1,6 +1,6 @@ import { TranslatedString } from "@gnu-taler/taler-util"; import { ComponentChildren, Fragment, VNode, h } from "preact"; -import { UIFormProps } from "./FormProvider.js"; +import { Addon, UIFormProps } from "./FormProvider.js"; import { noHandlerPropsAndNoContextForField } from "./InputArray.js"; import { useField } from "./useField.js"; @@ -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, @@ -91,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"> @@ -259,13 +254,13 @@ export function InputLine<T extends object, K extends keyof T>( name={String(name)} type={type} onChange={(e) => { - onChange(e.currentTarget.value as any); + onChange(fromString(e.currentTarget.value)); }} placeholder={placeholder ? placeholder : undefined} - value={value as string} - onBlur={() => { - onChange(fromString(value as any)); - }} + value={toString(value) ?? ""} + // onBlur={() => { + // onChange(fromString(value as any)); + // }} // defaultValue={toString(value)} disabled={state.disabled} aria-invalid={showError} |