taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 1707ffd5f777b28c4b52dcbabb2b1cfdfc79bb1f
parent 759b941d2431c23ca53792c8af791fe0b0717141
Author: Sebastian <sebasjm@taler-systems.com>
Date:   Fri, 27 Feb 2026 11:37:53 -0300

fix #11159

Diffstat:
Mpackages/merchant-backoffice-ui/src/components/form/Input.tsx | 74++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mpackages/merchant-backoffice-ui/src/components/form/InputPassword.tsx | 4+++-
Mpackages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx | 37+++++++++++++++++++++++--------------
Mpackages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx | 5+++++
Mpackages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx | 5+++--
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx | 3+++
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx | 2++
Mpackages/merchant-backoffice-ui/src/paths/instance/password/DetailPage.tsx | 6++++--
Mpackages/merchant-backoffice-ui/src/paths/login/index.tsx | 2++
Mpackages/merchant-backoffice-ui/src/paths/newAccount/index.tsx | 10++++++++--
Mpackages/merchant-backoffice-ui/src/paths/resetAccount/index.tsx | 5+++--
11 files changed, 104 insertions(+), 49 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/components/form/Input.tsx b/packages/merchant-backoffice-ui/src/components/form/Input.tsx @@ -22,16 +22,33 @@ import { ComponentChildren, h, VNode } from "preact"; import { InputProps, useField } from "./useField.js"; import { Tooltip } from "../Tooltip.js"; -export type SupportedTextInputType = - | "text" - | "numeric" - | "decimal" - | "tel" - | "email" - | "url" - | "search" - | "multiline" - | "password"; +export type SupportedTextInputType = + | "text" + | "numeric" + | "decimal" + | "tel" + | "email" + | "url" + | "search" + | "multiline" + | "password"; + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete +export type SupportedAutocomplete = + | "username" + | "current-password" + | "new-password" + | "one-time-code" + | "organization" + | "street-address" + | "country" + | "postal-code" + | "language" + | "url" + | "photo" + | "email" + | "tel"; + interface Props<T> extends InputProps<T> { inputType?: SupportedTextInputType; expand?: boolean; @@ -42,6 +59,7 @@ interface Props<T> extends InputProps<T> { children?: ComponentChildren; focus?: boolean; dontRemember?: boolean; + autoComplete?: SupportedAutocomplete; } export function doAutoFocus<T extends HTMLElement>( @@ -103,7 +121,7 @@ export function InternalTextInputSwitch({ {...(rest as any)} ref={focus ? doAutoFocus : undefined} class={hasError ? "input is-danger" : "input"} - type={inputType} + type={inputType ?? "text"} /> ); } @@ -121,6 +139,7 @@ export function Input<T>({ dontRemember, inputType, inputExtra, + autoComplete, side, fromStr = defaultFromString, toStr = defaultToString, @@ -152,21 +171,24 @@ export function Input<T>({ : "control has-icons-right" } > - <InternalTextInputSwitch - hasError={error} - {...inputExtra} - inputType={inputType} - placeholder={placeholder} - autocomplete={dontRemember ? "off" : undefined} - readonly={readonly} - disabled={readonly} - name={String(name)} - focus={focus} - value={toStr(value)} - onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void => - onChange(fromStr(e.currentTarget.value)) - } - /> + <fieldset> + <InternalTextInputSwitch + hasError={error} + {...inputExtra} + inputType={inputType} + placeholder={placeholder} + autocomplete={dontRemember ? "off" : undefined} + readonly={readonly} + disabled={readonly} + autoComplete={autoComplete} + name={String(name)} + focus={focus} + value={toStr(value)} + onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void => + onChange(fromStr(e.currentTarget.value)) + } + /> + </fieldset> {help} {children} </p> diff --git a/packages/merchant-backoffice-ui/src/components/form/InputPassword.tsx b/packages/merchant-backoffice-ui/src/components/form/InputPassword.tsx @@ -28,6 +28,7 @@ export interface Props<T> extends InputProps<T> { addonAfter?: ComponentChildren; children?: ComponentChildren; side?: ComponentChildren; + autoComplete?: "current-password" | "new-password"; } export function InputPassword<T>({ @@ -38,7 +39,7 @@ export function InputPassword<T>({ help, tooltip, expand, - addonAfter, + autoComplete, children, side, }: Props<keyof T>): VNode { @@ -50,6 +51,7 @@ export function InputPassword<T>({ side={side} label={label} placeholder={placeholder} + autoComplete={autoComplete} help={help} tooltip={tooltip} addonAfterAction={() => { diff --git a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx @@ -21,7 +21,11 @@ import { ComponentChildren, h, VNode } from "preact"; import { InputProps, useField } from "./useField.js"; import { Tooltip } from "../Tooltip.js"; -import { InternalTextInputSwitch, SupportedTextInputType } from "./Input.js"; +import { + InternalTextInputSwitch, + SupportedAutocomplete, + SupportedTextInputType, +} from "./Input.js"; export interface Props<T> extends InputProps<T> { expand?: boolean; @@ -35,6 +39,7 @@ export interface Props<T> extends InputProps<T> { inputExtra?: any; children?: ComponentChildren; side?: ComponentChildren; + autoComplete?: SupportedAutocomplete; } const defaultToString = (f?: any): string => f || ""; @@ -48,6 +53,7 @@ export function InputWithAddon<T>({ expand, label, addonBeforeLarge, + autoComplete, placeholder, help, tooltip, @@ -97,19 +103,22 @@ export function InputWithAddon<T>({ required ? " has-icons-right" : "" }`} > - <InternalTextInputSwitch - {...(inputExtra || {})} - class={error ? "input is-danger" : "input"} - inputType={inputType} - placeholder={placeholder} - readonly={readonly} - disabled={readonly} - name={String(name)} - value={toStr(value)} - onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void => - onChange(fromStr(e.currentTarget.value)) - } - /> + <fieldset> + <InternalTextInputSwitch + {...(inputExtra || {})} + class={error ? "input is-danger" : "input"} + inputType={inputType} + placeholder={placeholder} + readonly={readonly} + autoComplete={autoComplete} + disabled={readonly} + name={String(name)} + value={toStr(value)} + onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void => + onChange(fromStr(e.currentTarget.value)) + } + /> + </fieldset> {children} </p> {addonAfter && ( diff --git a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx @@ -62,6 +62,7 @@ export function DefaultInstanceFormFields({ readonly={readonlyId} label={i18n.str`Username`} tooltip={i18n.str`Name of the instance in URLs. The 'admin' instance is special in that it is used to administer other instances.`} + autoComplete="username" /> )} @@ -69,24 +70,28 @@ export function DefaultInstanceFormFields({ name="name" label={i18n.str`Business name`} tooltip={i18n.str`Legal name of the business represented by this instance.`} + autoComplete="organization" /> <Input<Entity> name="email" label={i18n.str`Email`} tooltip={i18n.str`Contact email`} + autoComplete="email" /> <Input<Entity> name="phone_number" label={i18n.str`Phone number`} tooltip={i18n.str`Contact phone`} + autoComplete="tel" /> <FragmentPersonaFlag point={UIElement.option_advanceInstanceSettings}> <Input<Entity> name="website" label={i18n.str`Website URL`} tooltip={i18n.str`URL.`} + autoComplete="url" /> <InputImage<Entity> diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx @@ -270,12 +270,13 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode { name="password" label={i18n.str`New password`} tooltip={i18n.str`Next password to be used`} + autoComplete="new-password" /> - <Input<Entity> + <InputPassword<Entity> name="repeat" label={i18n.str`Repeat password`} tooltip={i18n.str`Confirm the same password`} - inputType="password" + autoComplete="new-password" /> <div class="buttons is-right mt-5"> {onBack && ( diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx @@ -281,6 +281,7 @@ export function CreatePage({ onCreated, onBack }: Props): VNode { help="https://bank.demo.taler.net/accounts/${USERNAME}/taler-revenue/" expand tooltip={i18n.str`From where the merchant can download information about incoming wire transfers to this account`} + inputType="url" /> <InputSelector name="credit_facade_credentials.type" @@ -299,12 +300,14 @@ export function CreatePage({ onCreated, onBack }: Props): VNode { name="credit_facade_credentials.username" label={i18n.str`Username`} tooltip={i18n.str`Username to access the account information.`} + autoComplete="username" /> <InputPassword name="credit_facade_credentials.password" expand label={i18n.str`Password`} tooltip={i18n.str`Password to access the account information.`} + autoComplete="current-password" /> </Fragment> ) : undefined} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx @@ -387,12 +387,14 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode { name="credit_facade_credentials.username" label={i18n.str`Username`} tooltip={i18n.str`Username to access the account information.`} + autoComplete="username" /> <InputPassword name="credit_facade_credentials.password" expand label={i18n.str`Password`} tooltip={i18n.str`Password to access the account information.`} + autoComplete="current-password" /> </Fragment> ) : undefined} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/password/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/password/DetailPage.tsx @@ -108,6 +108,7 @@ export function DetailPage({ label={i18n.str`Current password`} tooltip={i18n.str`In order to verify that you have access.`} expand + autoComplete="current-password" /> )} <InputPassword<State> @@ -115,12 +116,13 @@ export function DetailPage({ expand label={i18n.str`New password`} tooltip={i18n.str`Next password to be used`} + autoComplete="new-password" /> - <Input<State> + <InputPassword<State> name="repeat" label={i18n.str`Repeat password`} tooltip={i18n.str`Confirm the same password`} - inputType="password" + autoComplete="new-password" /> </Fragment> <div class="buttons is-right mt-5"> diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx b/packages/merchant-backoffice-ui/src/paths/login/index.tsx @@ -160,6 +160,7 @@ export function LoginPage({ showCreateAccount, focus }: Props): VNode { ref={focus ? doAutoFocus : undefined} // placeholder={i18n.str`instance name`} name="username" + autoComplete="username" value={username} onInput={(e): void => setUsername(e?.currentTarget.value) @@ -186,6 +187,7 @@ export function LoginPage({ showCreateAccount, focus }: Props): VNode { type={hidePassword ? "password" : "text"} // placeholder={i18n.str`current password`} name="token" + autoComplete="current-password" value={password} onInput={(e): void => setPassword(e?.currentTarget.value) diff --git a/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx @@ -267,30 +267,35 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode { name="id" label={i18n.str`Username`} tooltip={i18n.str`Name of the instance in URLs. The 'admin' instance is special in that it is used to administer other instances.`} + autoComplete="username" /> <Input<Account> name="name" label={i18n.str`Business name`} tooltip={i18n.str`Legal name of the business represented by this instance.`} + autoComplete="organization" /> <InputPassword<Account> expand label={i18n.str`New password`} tooltip={i18n.str`Next password to be used`} name="password" + autoComplete="new-password" /> - <Input<Account> + <InputPassword<Account> label={i18n.str`Repeat password`} tooltip={i18n.str`Confirm the same password`} - inputType="password" name="repeat" + expand + autoComplete="new-password" /> {serverRequiresEmail ? ( <Input<Account> label={i18n.str`Email`} tooltip={i18n.str`Contact email`} name="email" + autoComplete="email" /> ) : undefined} {serverRequiresSms ? ( @@ -298,6 +303,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode { label={i18n.str`Phone`} tooltip={i18n.str`Contact phone number`} name="phone" + autoComplete="tel" /> ) : undefined} <InputToggle diff --git a/packages/merchant-backoffice-ui/src/paths/resetAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/resetAccount/index.tsx @@ -165,11 +165,12 @@ export function ResetAccount({ label={i18n.str`New password`} name="password" expand + autoComplete="new-password" /> - <Input<Form> + <InputPassword<Form> label={i18n.str`Repeat password`} - inputType="password" name="repeat" + autoComplete="new-password" /> </section> <footer