taler-typescript-core

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

commit 58edf272f56a3474a9ff6e7f0ba2aadb38ccffcb
parent a28d38bb5d742f153f1655b909d5d58bff686913
Author: Florian Dold <dold@taler.net>
Date:   Thu, 10 Sep 2026 15:20:56 +0200

web UIs: use Preact 10.29.8 throughout the workspace

Pin every Preact dependency to the same stable release so applications
and shared components use one runtime. Update component return types,
element attributes, state setter types, and DOM setup for compatibility.

Diffstat:
Mpackages/anastasis-webui/package.json | 3++-
Mpackages/anastasis-webui/src/context/anastasis.ts | 2+-
Mpackages/anastasis-webui/src/context/translation.ts | 2+-
Mpackages/anastasis-webui/src/hooks/useLocalStorage.ts | 4++--
Mpackages/anastasis-webui/src/index.test.ts | 2+-
Mpackages/anastasis-webui/src/pages/home/AddingProviderScreen/AddingProviderScreen.test.ts | 20+++++++++++++++++++-
Mpackages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx | 2+-
Mpackages/challenger-webui/package.json | 2+-
Mpackages/challenger-webui/src/context/settings.ts | 2+-
Mpackages/libeufin-bank-webui/package.json | 2+-
Mpackages/libeufin-bank-webui/src/components/Cashouts/views.tsx | 4++--
Mpackages/libeufin-bank-webui/src/components/DemoBanner.tsx | 2+-
Mpackages/libeufin-bank-webui/src/context/challenge.ts | 2+-
Mpackages/libeufin-bank-webui/src/context/settings.ts | 2+-
Mpackages/libeufin-bank-webui/src/pages/ConversionRateClassDetails.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/NewConversionRateClass.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/OperationState/views.tsx | 6+++---
Mpackages/libeufin-bank-webui/src/pages/PaymentOptions.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/PaytoWireTransferForm.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/WalletWithdrawForm.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/account/ShowAccountDetails.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/account/UpdateAccountPassword.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/admin/AccountList.tsx | 8++++----
Mpackages/libeufin-bank-webui/src/pages/admin/AdminHome.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/admin/ConversionClassList.tsx | 2+-
Mpackages/libeufin-bank-webui/src/pages/admin/CreateNewAccount.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/admin/DownloadStats.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/admin/RemoveAccount.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/regional/ConversionConfig.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/regional/CreateCashout.tsx | 4++--
Mpackages/libeufin-bank-webui/src/pages/regional/ShowCashoutDetails.tsx | 2+-
Mpackages/taler-auditor-webui/package.json | 2+-
Mpackages/taler-exchange-aml-webui/package.json | 2+-
Mpackages/taler-exchange-aml-webui/src/context/officer-info.tsx | 2+-
Mpackages/taler-exchange-aml-webui/src/context/ui-forms.ts | 2+-
Mpackages/taler-exchange-aml-webui/src/context/ui-settings.ts | 2+-
Mpackages/taler-exchange-aml-webui/src/hooks/decision-request.ts | 2+-
Mpackages/taler-exchange-aml-webui/src/hooks/officer.ts | 4++--
Mpackages/taler-exchange-kyc-webui/package.json | 2+-
Mpackages/taler-exchange-kyc-webui/src/context/notifier.ts | 2+-
Mpackages/taler-exchange-kyc-webui/src/context/settings.ts | 2+-
Mpackages/taler-exchange-kyc-webui/src/context/ui-forms.ts | 2+-
Mpackages/taler-harness/src/integrationtests/test-libeufin-bank-webui.ts | 4++--
Mpackages/wallet-webui/package.json | 2+-
Mpackages/web-util/package.json | 2+-
Mpackages/web-util/src/components/Button.tsx | 13+++++--------
Mpackages/web-util/src/components/Header.tsx | 12++++++------
Mpackages/web-util/src/components/utils.ts | 16++++++++--------
Mpackages/web-util/src/context/bank-api.ts | 4++--
Mpackages/web-util/src/context/challenger-api.ts | 2+-
Mpackages/web-util/src/context/exchange-api.ts | 4++--
Mpackages/web-util/src/context/navigation.ts | 2+-
Mpackages/web-util/src/context/notification.ts | 2+-
Mpackages/web-util/src/context/translation.ts | 2+-
Mpackages/web-util/src/context/wallet-integration.ts | 4++--
Mpackages/web-util/src/forms/fields/InputChoiceHorizontal.tsx | 1-
Mpackages/web-util/src/forms/fields/InputDownloadLink.tsx | 2--
Mpackages/web-util/src/forms/fields/InputDuration.tsx | 2+-
Mpackages/web-util/src/forms/fields/InputLine.tsx | 2+-
Mpackages/web-util/src/tests/hook.ts | 18+++++++-----------
Mpnpm-lock.yaml | 73+++++++++++++++++++++++++++----------------------------------------------
61 files changed, 144 insertions(+), 154 deletions(-)

diff --git a/packages/anastasis-webui/package.json b/packages/anastasis-webui/package.json @@ -24,7 +24,7 @@ "date-fns": "2.29.2", "jed": "1.1.1", "jssha": "^3.3.0", - "preact": "10.11.3", + "preact": "10.29.8", "preact-router": "^3.2.1", "qrcode-generator": "^1.4.4" }, @@ -37,6 +37,7 @@ "bulma-checkbox": "^1.1.1", "bulma-radio": "^1.1.1", "chai": "^6.2.2", + "happy-dom": "^20.11.2", "sass": "1.56.1", "typescript": "^7.0.2" }, diff --git a/packages/anastasis-webui/src/context/anastasis.ts b/packages/anastasis-webui/src/context/anastasis.ts @@ -32,7 +32,7 @@ interface Props { children: any; } -export const AnastasisProvider = ({ value, children }: Props): VNode => { +export const AnastasisProvider = ({ value, children }: Props): VNode<any> => { return h(Context.Provider, { value, children }); }; diff --git a/packages/anastasis-webui/src/context/translation.ts b/packages/anastasis-webui/src/context/translation.ts @@ -62,7 +62,7 @@ export const TranslationProvider = ({ initial, children, forceLang, -}: Props): VNode => { +}: Props): VNode<any> => { const [lang, changeLanguage, isSaved] = useLang(initial); useEffect(() => { if (forceLang) { diff --git a/packages/anastasis-webui/src/hooks/useLocalStorage.ts b/packages/anastasis-webui/src/hooks/useLocalStorage.ts @@ -19,13 +19,13 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { StateUpdater, useState } from "preact/hooks"; +import { Dispatch, StateUpdater, useState } from "preact/hooks"; //TODO: merge with the above function export function useNotNullLocalStorage( key: string, initialValue: string, -): [string, StateUpdater<string>, boolean] { +): [string, Dispatch<StateUpdater<string>>, boolean] { const [storedValue, setStoredValue] = useState<string>((): string => { return typeof window !== "undefined" ? window.localStorage.getItem(key) || initialValue diff --git a/packages/anastasis-webui/src/index.test.ts b/packages/anastasis-webui/src/index.test.ts @@ -56,7 +56,7 @@ function DefaultTestingContext({ ...rest }: { children: ComponentChildren; -}): VNode { +}): VNode<any> { //some UI example can specify the state of the reducer const currentReducerState = rest as ReducerState; const value: AnastasisReducerApi = { diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/AddingProviderScreen.test.ts b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/AddingProviderScreen.test.ts @@ -25,7 +25,25 @@ import useComponentState from "./state.js"; import * as tests from "@gnu-taler/web-util/testing"; describe("AddingProviderScreen states", () => { - it("should not load more if has reach the end", async () => { + it("should not load more if has reach the end", async (t) => { + // Keep the Node-only DOM implementation out of the browser test bundle. + const happyDomPackage = "happy-dom"; + const { Window } = await import(happyDomPackage); + const window = new Window(); + const previousDocument = Object.getOwnPropertyDescriptor( + globalThis, + "document", + ); + Object.defineProperty(globalThis, "document", { + configurable: true, + value: window.document, + }); + t.after(async () => { + if (previousDocument) + Object.defineProperty(globalThis, "document", previousDocument); + else Reflect.deleteProperty(globalThis, "document"); + await window.happyDOM.abort(); + }); const hookBehavior = await tests.hookBehaveLikeThis( () => { return useComponentState({ diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx @@ -112,7 +112,7 @@ function RecoveredSecret({ {secretName} </p> )} - <div class="block buttons" disabled={copied}> + <div class="block buttons"> {plainText ? ( <button class="button" diff --git a/packages/challenger-webui/package.json b/packages/challenger-webui/package.json @@ -38,7 +38,7 @@ "dependencies": { "@gnu-taler/taler-util": "workspace:*", "@gnu-taler/web-util": "workspace:*", - "preact": "10.11.3", + "preact": "10.29.8", "swr": "2.0.3" } } diff --git a/packages/challenger-webui/src/context/settings.ts b/packages/challenger-webui/src/context/settings.ts @@ -33,7 +33,7 @@ export const SettingsProvider = ({ }: { value: ChallengerUiSettings; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value, children, diff --git a/packages/libeufin-bank-webui/package.json b/packages/libeufin-bank-webui/package.json @@ -22,7 +22,7 @@ "@gnu-taler/taler-util": "workspace:*", "@gnu-taler/web-util": "workspace:*", "date-fns": "2.29.3", - "preact": "10.11.3", + "preact": "10.29.8", "swr": "2.0.3" }, "devDependencies": { diff --git a/packages/libeufin-bank-webui/src/components/Cashouts/views.tsx b/packages/libeufin-bank-webui/src/components/Cashouts/views.tsx @@ -165,7 +165,7 @@ export function ReadyView({ </div> </div> <a - name="cashout details" + data-name="cashout details" class="shrink-0 text-sm font-semibold text-brand hover:underline" href={routeCashoutDetails.url({ cid: String(item.id), @@ -281,7 +281,7 @@ export function ReadyView({ </td> <td class="whitespace-nowrap py-3 pl-3 pr-4 text-right text-sm"> <a - name="cashout details" + data-name="cashout details" class="font-semibold text-brand hover:underline" href={routeCashoutDetails.url({ cid: String(item.id), diff --git a/packages/libeufin-bank-webui/src/components/DemoBanner.tsx b/packages/libeufin-bank-webui/src/components/DemoBanner.tsx @@ -76,7 +76,7 @@ export function DemoBanner({ <a class="inline-flex flex-none items-center" href="https://taler.net/" - name="GNU Taler" + data-name="GNU Taler" > <img class="h-auto w-[clamp(5.25rem,9vw,6.25rem)] max-[544px]:w-[4.75rem]" diff --git a/packages/libeufin-bank-webui/src/context/challenge.ts b/packages/libeufin-bank-webui/src/context/challenge.ts @@ -62,7 +62,7 @@ export const BankChallengeHandlerProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { const [state, setState] = useState<MfaState>(); const regenerationInFlight = useRef<number>(); const challengeGeneration = useRef(0); diff --git a/packages/libeufin-bank-webui/src/context/settings.ts b/packages/libeufin-bank-webui/src/context/settings.ts @@ -36,7 +36,7 @@ export const SettingsProvider = ({ }: { value: UiSettings; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value, children, diff --git a/packages/libeufin-bank-webui/src/pages/ConversionRateClassDetails.tsx b/packages/libeufin-bank-webui/src/pages/ConversionRateClassDetails.tsx @@ -574,7 +574,7 @@ function Form({ <OperationError class="mb-4" /> <div class="flex items-center justify-between gap-x-6"> <a - name="cancel" + data-name="cancel" href={routeCancel.url({})} class="text-sm font-semibold leading-6 text-onBackground" > diff --git a/packages/libeufin-bank-webui/src/pages/NewConversionRateClass.tsx b/packages/libeufin-bank-webui/src/pages/NewConversionRateClass.tsx @@ -103,7 +103,7 @@ export function NewConversionRateClass({ <div class="flex items-center justify-between gap-x-6"> <a href={routeCancel.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground hover:underline" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/OperationState/views.tsx b/packages/libeufin-bank-webui/src/pages/OperationState/views.tsx @@ -1046,7 +1046,7 @@ export function ConfirmedView({ routeClose, cashAcceptor }: State.Confirmed) { <div class="border-t border-onBackground/10 bg-background px-6 py-4 sm:flex sm:justify-end sm:px-8"> <a href={routeClose.url({})} - name="back to account" + data-name="back to account" class="inline-flex w-full justify-center rounded-md bg-primary px-4 py-2 text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary sm:w-auto" > <i18n.Translate>Back to account</i18n.Translate> @@ -1219,7 +1219,7 @@ export function ReadyView({ <div class="mt-6"> <a href={talerWithdrawUri} - name="withdraw" + data-name="withdraw" class="inline-flex items-center justify-center rounded-md border border-primary px-4 py-2 text-sm font-semibold text-primaryDark hover:bg-primary/10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Open Taler Wallet manually</i18n.Translate> @@ -1230,7 +1230,7 @@ export function ReadyView({ <i18n.Translate>Don't have a Taler Wallet?</i18n.Translate>{" "} <a class="font-semibold text-primaryDark hover:text-onPrimaryContainer" - name="wallet page" + data-name="wallet page" href="https://taler.net/en/wallet.html" target="_blank" rel="noreferrer noopener" diff --git a/packages/libeufin-bank-webui/src/pages/PaymentOptions.tsx b/packages/libeufin-bank-webui/src/pages/PaymentOptions.tsx @@ -114,7 +114,7 @@ function ActionCard({ return ( <a href={href} - name={name} + data-name={name} aria-label={title} class="group flex min-h-28 gap-4 rounded-lg border border-outlineVariant bg-white p-5 shadow-sm transition hover:border-primary/50 hover:shadow focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > diff --git a/packages/libeufin-bank-webui/src/pages/PaytoWireTransferForm.tsx b/packages/libeufin-bank-webui/src/pages/PaytoWireTransferForm.tsx @@ -583,7 +583,7 @@ export function PaytoWireTransferForm({ Need to move money out of this bank? </i18n.Translate>{" "} <a - name="do cashout" + data-name="do cashout" href={routeCashout.url({})} class="font-semibold text-brand hover:underline" > @@ -599,7 +599,7 @@ export function PaytoWireTransferForm({ <div class="flex items-center justify-between gap-x-6"> {routeCancel ? ( <a - name="cancel" + data-name="cancel" href={routeCancel.url({})} class="text-sm font-semibold leading-6 text-onBackground hover:underline" > diff --git a/packages/libeufin-bank-webui/src/pages/WalletWithdrawForm.tsx b/packages/libeufin-bank-webui/src/pages/WalletWithdrawForm.tsx @@ -409,7 +409,7 @@ export function WithdrawalAmountForm({ <i18n.Translate>Need a Taler Wallet?</i18n.Translate>{" "} <a target="_blank" - name="wallet page" + data-name="wallet page" rel="noreferrer noopener" class="font-semibold text-primaryDark hover:underline" href="https://taler.net/en/wallet.html" diff --git a/packages/libeufin-bank-webui/src/pages/account/ShowAccountDetails.tsx b/packages/libeufin-bank-webui/src/pages/account/ShowAccountDetails.tsx @@ -280,7 +280,7 @@ export function ShowAccountDetails({ <div class="flex items-center justify-between gap-x-6"> <a href={routeClose.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/account/UpdateAccountPassword.tsx b/packages/libeufin-bank-webui/src/pages/account/UpdateAccountPassword.tsx @@ -292,7 +292,7 @@ export function UpdateAccountPassword({ <div class="flex items-center justify-between gap-x-6"> <a href={routeClose.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/admin/AccountList.tsx b/packages/libeufin-bank-webui/src/pages/admin/AccountList.tsx @@ -103,7 +103,7 @@ export function AccountList({ ) : undefined} <a href={routeCreate.url({})} - name="create account" + data-name="create account" class="block rounded-md bg-primary px-3 py-2 text-center text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Create account</i18n.Translate> @@ -194,7 +194,7 @@ export function AccountList({ > <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-onBackground sm:pl-0"> <a - name={`show account ${item.username}`} + data-name={`show account ${item.username}`} href={routeShowAccount.url({ account: item.username, })} @@ -237,7 +237,7 @@ export function AccountList({ ) : ( <Fragment> <a - name={`update password ${item.username}`} + data-name={`update password ${item.username}`} href={routeUpdatePasswordAccount.url({ account: item.username, })} @@ -251,7 +251,7 @@ export function AccountList({ {noBalance ? ( <a - name={`remove account ${item.username}`} + data-name={`remove account ${item.username}`} href={routeRemoveAccount.url({ account: item.username, })} diff --git a/packages/libeufin-bank-webui/src/pages/admin/AdminHome.tsx b/packages/libeufin-bank-webui/src/pages/admin/AdminHome.tsx @@ -567,7 +567,7 @@ function Metrics({ <div class="flex justify-end mt-4"> <a href={routeDownloadStats.url({})} - name="download stats" + data-name="download stats" class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-primary px-3 py-2 text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Download stats as CSV</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/admin/ConversionClassList.tsx b/packages/libeufin-bank-webui/src/pages/admin/ConversionClassList.tsx @@ -137,7 +137,7 @@ export function ConversionClassList({ </a> <a href={routeCreate.url({})} - name="create account" + data-name="create account" class="block rounded-md bg-primary px-3 py-2 text-center text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Create conversion rate class</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/admin/CreateNewAccount.tsx b/packages/libeufin-bank-webui/src/pages/admin/CreateNewAccount.tsx @@ -112,7 +112,7 @@ export function CreateNewAccount({ <div class="mt-5 sm:mt-6"> <a href={routeCancel.url({})} - name="close" + data-name="close" class="inline-flex w-full justify-center rounded-md bg-primary px-3 py-2 text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Close</i18n.Translate> @@ -155,7 +155,7 @@ export function CreateNewAccount({ <div class="flex items-center justify-between gap-x-6"> <a href={routeCancel.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground hover:underline" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/admin/DownloadStats.tsx b/packages/libeufin-bank-webui/src/pages/admin/DownloadStats.tsx @@ -385,7 +385,7 @@ export function DownloadStats({ routeCancel }: Props): VNode { <OperationError class="mb-4" /> <div class="flex items-center justify-between gap-x-6"> <a - name="cancel" + data-name="cancel" href={routeCancel.url({})} class="text-sm font-semibold leading-6 text-onBackground" > @@ -434,7 +434,7 @@ export function DownloadStats({ routeCancel }: Props): VNode { "data:text/plain;charset=utf-8," + encodeURIComponent(downloaded.csv) } - name="save file" + data-name="save file" download={"bank-stats.csv"} > <Attention diff --git a/packages/libeufin-bank-webui/src/pages/admin/RemoveAccount.tsx b/packages/libeufin-bank-webui/src/pages/admin/RemoveAccount.tsx @@ -170,7 +170,7 @@ export function RemoveAccount({ <div class="mt-5 sm:mt-6"> <a href={routeCancel.url({})} - name="close" + data-name="close" class="inline-flex w-full justify-center rounded-md bg-primary px-3 py-2 text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Close</i18n.Translate> @@ -258,7 +258,7 @@ export function RemoveAccount({ <div class="flex items-center justify-between gap-x-6"> <a href={routeCancel.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/regional/ConversionConfig.tsx b/packages/libeufin-bank-webui/src/pages/regional/ConversionConfig.tsx @@ -302,7 +302,7 @@ function useComponentState({ return ( <section class="mt-2"> <a - name="cancel" + data-name="cancel" href={routeCancel.url({})} class="inline-flex items-center text-sm font-semibold text-brand hover:underline" > @@ -619,7 +619,7 @@ function useComponentState({ <OperationError class="mb-4" /> <div class="flex items-center justify-between gap-x-6"> <a - name="cancel" + data-name="cancel" href={routeCancel.url({})} class="text-sm font-semibold leading-6 text-onBackground" > diff --git a/packages/libeufin-bank-webui/src/pages/regional/CreateCashout.tsx b/packages/libeufin-bank-webui/src/pages/regional/CreateCashout.tsx @@ -109,7 +109,7 @@ export function CreateCashout({ <div class="mt-5 sm:mt-6"> <a href={routeClose.url({})} - name="close" + data-name="close" class="inline-flex w-full justify-center rounded-md bg-primary px-3 py-2 text-sm font-semibold text-onPrimary shadow-sm hover:bg-primaryHover hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > <i18n.Translate>Close</i18n.Translate> @@ -792,7 +792,7 @@ function CreateCashoutInternal({ <div class="flex items-center justify-between gap-x-6"> <a href={routeClose.url({})} - name="cancel" + data-name="cancel" class="text-sm font-semibold leading-6 text-onBackground" > <i18n.Translate>Cancel</i18n.Translate> diff --git a/packages/libeufin-bank-webui/src/pages/regional/ShowCashoutDetails.tsx b/packages/libeufin-bank-webui/src/pages/regional/ShowCashoutDetails.tsx @@ -129,7 +129,7 @@ export function ShowCashoutDetails({ id, routeClose }: Props): VNode { <section class="mt-2"> <a href={routeClose.url({})} - name="close" + data-name="close" class="inline-flex items-center text-sm font-semibold text-brand hover:underline" > <span class="mr-1" aria-hidden="true"> diff --git a/packages/taler-auditor-webui/package.json b/packages/taler-auditor-webui/package.json @@ -22,7 +22,7 @@ "dependencies": { "@gnu-taler/taler-util": "workspace:*", "@gnu-taler/web-util": "workspace:*", - "preact": "10.11.3", + "preact": "10.29.8", "swr": "2.2.2", "wouter-preact": "^3.0.0" }, diff --git a/packages/taler-exchange-aml-webui/package.json b/packages/taler-exchange-aml-webui/package.json @@ -27,7 +27,7 @@ "@heroicons/react": "^2.0.17", "date-fns": "2.29.3", "jed": "1.1.1", - "preact": "10.11.3", + "preact": "10.29.8", "swr": "2.2.2", "wouter-preact": "^3.7.1" }, diff --git a/packages/taler-exchange-aml-webui/src/context/officer-info.tsx b/packages/taler-exchange-aml-webui/src/context/officer-info.tsx @@ -19,7 +19,7 @@ export function OfficerInfoProvider({ }: { children: ComponentChildren; value: AmlOfficerInfo; -}): VNode { +}): VNode<any> { return h(OfficerInfoContext.Provider, { value, children }); } diff --git a/packages/taler-exchange-aml-webui/src/context/ui-forms.ts b/packages/taler-exchange-aml-webui/src/context/ui-forms.ts @@ -46,7 +46,7 @@ export const UiFormsProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { const { i18n } = useTranslationContext(); return h(Context.Provider, { diff --git a/packages/taler-exchange-aml-webui/src/context/ui-settings.ts b/packages/taler-exchange-aml-webui/src/context/ui-settings.ts @@ -49,7 +49,7 @@ export const UiSettingsProvider = ({ }: { value: UiSettings; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value, children, diff --git a/packages/taler-exchange-aml-webui/src/hooks/decision-request.ts b/packages/taler-exchange-aml-webui/src/hooks/decision-request.ts @@ -155,7 +155,7 @@ export function DecisionRequestProvider({ }: { initial?: Partial<DecisionRequest>; children: ComponentChildren; -}): VNode { +}): VNode<any> { const defaultRef = useRef<DecisionRequest>({ ...DECISION_REQUEST_EMPTY, ...initial, diff --git a/packages/taler-exchange-aml-webui/src/hooks/officer.ts b/packages/taler-exchange-aml-webui/src/hooks/officer.ts @@ -212,7 +212,7 @@ export function OfficerProvider({ children, }: { children: ComponentChildren; -}): VNode { +}): VNode<any> { const { lib: { exchange: api }, } = useExchangeApiContext(); @@ -388,6 +388,6 @@ export function OfficerProviderTesting({ }: { children: ComponentChildren; value: OfficerState; -}): VNode { +}): VNode<any> { return h(OfficerContext.Provider, { value, children }); } diff --git a/packages/taler-exchange-kyc-webui/package.json b/packages/taler-exchange-kyc-webui/package.json @@ -40,7 +40,7 @@ "@gnu-taler/taler-util": "workspace:*", "@gnu-taler/web-util": "workspace:*", "date-fns": "2.29.3", - "preact": "10.11.3", + "preact": "10.29.8", "swr": "2.0.3" } } diff --git a/packages/taler-exchange-kyc-webui/src/context/notifier.ts b/packages/taler-exchange-kyc-webui/src/context/notifier.ts @@ -50,7 +50,7 @@ export const NotifierProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value: new Notifier(), children, diff --git a/packages/taler-exchange-kyc-webui/src/context/settings.ts b/packages/taler-exchange-kyc-webui/src/context/settings.ts @@ -33,7 +33,7 @@ export const SettingsProvider = ({ }: { value: KycUiSettings; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value, children, diff --git a/packages/taler-exchange-kyc-webui/src/context/ui-forms.ts b/packages/taler-exchange-kyc-webui/src/context/ui-forms.ts @@ -41,7 +41,7 @@ export const UiFormsProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { const { i18n } = useTranslationContext(); return h(Context.Provider, { value: { forms: preloadedForms(i18n) }, diff --git a/packages/taler-harness/src/integrationtests/test-libeufin-bank-webui.ts b/packages/taler-harness/src/integrationtests/test-libeufin-bank-webui.ts @@ -1113,7 +1113,7 @@ export async function runLibeufinBankWebuiMoneyFlowsTest(t: GlobalTestState) { .getByText("Welcome, Bank WebUI Money Flows", { exact: true }) .waitFor({ state: "visible" }); - await page.locator('a[name="cash out"]').click(); + await page.locator('a[data-name="cash out"]').click(); await page.waitForURL(/#\/new-cashout$/); await browser.saveScreenshot("cashout-form"); await page @@ -1387,7 +1387,7 @@ export async function runLibeufinBankWebuiMoneyFlowsTest(t: GlobalTestState) { ); t.assertDeepEqual(aborted.status, "aborted"); t.assertDeepEqual( - await page.locator('a[name="charge wallet"]').getAttribute("href"), + await page.locator('a[data-name="charge wallet"]').getAttribute("href"), "#/account/charge-wallet", ); diff --git a/packages/wallet-webui/package.json b/packages/wallet-webui/package.json @@ -42,7 +42,7 @@ "@preact/signals": "^2.3.1", "@sqlite.org/sqlite-wasm": "3.53.0-build1", "jsqr": "^1.4.0", - "preact": "^10.27.2", + "preact": "10.29.8", "qrcode-generator": "1.4.4", "swr": "2.2.2", "wouter-preact": "^3.7.1" diff --git a/packages/web-util/package.json b/packages/web-util/package.json @@ -57,7 +57,7 @@ "happy-dom": "^20.11.2", "postcss": "^8.4.23", "postcss-load-config": "^4.0.1", - "preact": "10.11.3", + "preact": "10.29.8", "preact-render-to-string": "^5.2.6", "prettier": "^3.8.3", "sass": "1.56.1", diff --git a/packages/web-util/src/components/Button.tsx b/packages/web-util/src/components/Button.tsx @@ -8,17 +8,14 @@ */ import { h, JSX, VNode } from "preact"; -import { - CSSProperties, - HTMLAttributes, - useEffect, - useRef, - useState, -} from "preact/compat"; +import { CSSProperties, useEffect, useRef, useState } from "preact/compat"; import { useTranslationContext } from "../context/translation.js"; import { doAutoFocus } from "./utils.js"; -export type ButtonProps = Omit<HTMLAttributes<HTMLButtonElement>, "type"> & { +export type ButtonProps = Omit< + JSX.ButtonHTMLAttributes<HTMLButtonElement>, + "type" +> & { submit?: boolean; focus?: boolean; type?: "button" | "submit" | "reset"; diff --git a/packages/web-util/src/components/Header.tsx b/packages/web-util/src/components/Header.tsx @@ -56,7 +56,7 @@ export function Header({ <div class="flex flex-row h-16 items-center "> <div class="flex px-2 justify-start"> <div class="flex-shrink-0 rounded-lg"> - <a href={iconLinkURL ?? "#"} name="logo"> + <a href={iconLinkURL ?? "#"} data-name="logo"> <img class="h-8 w-auto m-1" src={logoSrc ?? logo} @@ -77,7 +77,7 @@ export function Header({ <a key={idx} href={url} - name={`site header ${name}`} + data-name={`site header ${name}`} class="hidden sm:block text-white hover:bg-indigo-500 hover:bg-opacity-75 rounded-md py-2 px-3 text-sm font-medium" > {name} @@ -90,7 +90,7 @@ export function Header({ {!notificationURL ? undefined : ( <a href={notificationURL} - name="notifications" + data-name="notifications" class="relative inline-flex items-center justify-center rounded-md bg-primary p-1 mr-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600" aria-controls="mobile-menu" aria-expanded="false" @@ -134,7 +134,7 @@ export function Header({ {!profileURL ? undefined : ( <a href={profileURL} - name="profile" + data-name="profile" class="relative inline-flex items-center justify-center rounded-md bg-primary p-1 mr-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600" aria-controls="mobile-menu" aria-expanded="false" @@ -200,7 +200,7 @@ export function Header({ <div id="settings-panel" class="relative z-10" - name="sidebar overlay" + data-name="sidebar overlay" aria-labelledby="slide-over-title" role="dialog" aria-modal="true" @@ -309,7 +309,7 @@ export function Header({ <li key={url}> <a href={url} - name={`site ${name}`} + data-name={`site ${name}`} target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold" diff --git a/packages/web-util/src/components/utils.ts b/packages/web-util/src/components/utils.ts @@ -1,7 +1,7 @@ import { createElement, VNode } from "preact"; import { MutableRef, useEffect, useRef } from "preact/hooks"; -export type StateFunc<S> = (p: S) => VNode; +export type StateFunc<S> = (p: S) => VNode<any>; export type StateViewMap<StateType extends { status: string }> = { [S in StateType as S["status"]]: StateFunc<S>; @@ -12,9 +12,9 @@ export type RecursiveState<S extends object> = S | (() => RecursiveState<S>); export function compose<SType extends { status: string }, PType>( hook: (p: PType) => RecursiveState<SType>, viewMap: StateViewMap<SType>, -): (p: PType) => VNode { - function withHook(stateHook: () => RecursiveState<SType>): () => VNode { - function ComposedComponent(): VNode { +): (p: PType) => VNode<any> { + function withHook(stateHook: () => RecursiveState<SType>): () => VNode<any> { + function ComposedComponent(): VNode<any> { const state = stateHook(); if (typeof state === "function") { @@ -37,10 +37,10 @@ export function compose<SType extends { status: string }, PType>( } export function recursive<PType>( - hook: (p: PType) => RecursiveState<VNode>, -): (p: PType) => VNode { - function withHook(stateHook: () => RecursiveState<VNode>): () => VNode { - function ComposedComponent(): VNode { + hook: (p: PType) => RecursiveState<VNode<any>>, +): (p: PType) => VNode<any> { + function withHook(stateHook: () => RecursiveState<VNode<any>>): () => VNode<any> { + function ComposedComponent(): VNode<any> { const state = stateHook(); if (typeof state === "function") { diff --git a/packages/web-util/src/context/bank-api.ts b/packages/web-util/src/context/bank-api.ts @@ -87,7 +87,7 @@ export const BankApiProvider = ({ children: ComponentChildren; evictors?: Evictors; frameOnError: FunctionComponent<{ children: ComponentChildren }>; -}): VNode => { +}): VNode<any> => { const [checked, setChecked] = useState<ConfigResult<TalerCorebankApi.TalerCorebankConfigResponse>>(); const checkedFor = useRef<string>(); @@ -255,7 +255,7 @@ export const BankApiProviderTesting = ({ }: { value: BankContextType; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(BankContext.Provider, { value, children, diff --git a/packages/web-util/src/context/challenger-api.ts b/packages/web-util/src/context/challenger-api.ts @@ -100,7 +100,7 @@ export const ChallengerApiProvider = ({ evictors?: Evictors; frameOnError: FunctionComponent<{ children: ComponentChildren }>; renderStatus?: (status: ChallengerApiProviderStatus) => ComponentChildren; -}): VNode => { +}): VNode<any> => { const [checked, setChecked] = useState<ConfigResult<ChallengerApi.ChallengerTermsOfServiceResponse>>(); const [retryRequest, setRetryRequest] = useState(0); diff --git a/packages/web-util/src/context/exchange-api.ts b/packages/web-util/src/context/exchange-api.ts @@ -112,7 +112,7 @@ export const ExchangeApiProvider = ({ frameOnError: FunctionComponent<{ children: ComponentChildren }>; preventCompression?: boolean; compatibilityLoading?: ComponentChildren; -}): VNode => { +}): VNode<any> => { const [checked, setChecked] = useState<ConfigResult<KeysAndConfigType>>(); const checkedFor = useRef<string>(); const endpointKey = `${baseUrl.href}:${!!preventCompression}`; @@ -301,7 +301,7 @@ export const ExchangeApiProviderTesting = ({ }: { value: ExchangeContextType; children: ComponentChildren; -}): VNode => { +}): VNode<any> => { return h(ExchangeContext.Provider, { value, children, diff --git a/packages/web-util/src/context/navigation.ts b/packages/web-util/src/context/navigation.ts @@ -106,7 +106,7 @@ export const BrowserHashNavigationProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { const [{ path, params }, setState] = useState({ path: initialPath, params: initialParams, diff --git a/packages/web-util/src/context/notification.ts b/packages/web-util/src/context/notification.ts @@ -42,7 +42,7 @@ interface Props { } // Outmost UI wrapper. -export const NotificationProvider = ({ children }: Props): VNode => { +export const NotificationProvider = ({ children }: Props): VNode<any> => { const { notification, ...nf } = useNotificationHandler(); return h(Context.Provider, { value: { diff --git a/packages/web-util/src/context/translation.ts b/packages/web-util/src/context/translation.ts @@ -93,7 +93,7 @@ export const TranslationProvider = ({ children, forceLang__testing: forceLang, source, -}: Props): VNode => { +}: Props): VNode<any> => { const mergedSource = useMemo( () => composeTranslationCatalogues(webUtilStrings, source), [source], diff --git a/packages/web-util/src/context/wallet-integration.ts b/packages/web-util/src/context/wallet-integration.ts @@ -59,7 +59,7 @@ export const TalerWalletIntegrationBrowserProvider = ({ children, }: { children: ComponentChildren; -}): VNode => { +}): VNode<any> => { const value: Type = { publishTalerAction: createHeadMetaTag, }; @@ -75,7 +75,7 @@ export const TalerWalletIntegrationTestingProvider = ({ }: { children: ComponentChildren; value: Type; -}): VNode => { +}): VNode<any> => { return h(Context.Provider, { value, children, diff --git a/packages/web-util/src/forms/fields/InputChoiceHorizontal.tsx b/packages/web-util/src/forms/fields/InputChoiceHorizontal.tsx @@ -55,7 +55,6 @@ export function InputChoiceHorizontal<ChoiceVal>( type="button" key={idx} disabled={props.disabled} - label={choice.label} class={clazz} onClick={(e) => { onChange( diff --git a/packages/web-util/src/forms/fields/InputDownloadLink.tsx b/packages/web-util/src/forms/fields/InputDownloadLink.tsx @@ -67,8 +67,6 @@ export function InputDownloadLink(props: Props & UIFormProps<boolean>): VNode { onChange(undefined); } }} - media={media} - download > {label} </button> diff --git a/packages/web-util/src/forms/fields/InputDuration.tsx b/packages/web-util/src/forms/fields/InputDuration.tsx @@ -128,7 +128,7 @@ export function InputDuration(props: UIFormProps<Duration>): VNode { } } } - const showError = value !== undefined && error; + const showError = value !== undefined && !!error; if (showError) { clazz += " text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500"; diff --git a/packages/web-util/src/forms/fields/InputLine.tsx b/packages/web-util/src/forms/fields/InputLine.tsx @@ -252,7 +252,7 @@ export function InputLine<Value = string>( } } } - const showError = value !== undefined && error; + const showError = value !== undefined && !!error; if (showError) { clazz += " text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500"; diff --git a/packages/web-util/src/tests/hook.ts b/packages/web-util/src/tests/hook.ts @@ -49,7 +49,7 @@ export function createExample<T extends object, Props extends object>( contextProps?: T | (() => T), ): ExampleItemSetup<Props> { const evaluatedProps = typeof props === "function" ? props() : props; - const Render = (args: any): VNode => create(Component, args); + const Render = (args: any): VNode<any> => create(Component, args); const evaluatedContextProps = typeof contextProps === "function" ? contextProps() : contextProps; return { @@ -90,11 +90,7 @@ export function renderUI(example: ExampleItemSetup<any>, Context?: any): void { * No need to render. * Should mount, update and run effects. * - * Browser: mount update and unmount - * Node: mount on a mock virtual dom - * - * Mounting hook doesn't use DOM api so is - * safe to use normal mounting api in node + * Requires a DOM document, including in Node test environments. * * @param Component * @param props @@ -102,7 +98,7 @@ export function renderUI(example: ExampleItemSetup<any>, Context?: any): void { */ function renderHook( Component: FunctionComponent, - Context?: ({ children }: { children: any }) => VNode | null, + Context?: ({ children }: { children: any }) => VNode<any> | null, ): void { const vdom = !Context ? create(Component, {}) @@ -110,7 +106,7 @@ function renderHook( //use normal mounting API since we expect //useEffect to be called ( and similar APIs ) - renderIntoDom(vdom, {} as Element); + renderIntoDom(vdom, document.createElement("div")); } type RecursiveState<S> = S | (() => RecursiveState<S>); @@ -132,14 +128,14 @@ interface Mounted<T> { */ function mountHook<T extends object>( hookToBeTested: () => RecursiveState<T>, - Context?: ({ children }: { children: any }) => VNode | null, + Context?: ({ children }: { children: any }) => VNode<any> | null, ): Mounted<T> { let lastResult: Exclude<T, VoidFunction> | Error | null = null; const listener: Array<() => void> = []; // component that's going to hold the hook - function Component(): VNode { + function Component(): VNode<any> { try { let componentOrResult = hookToBeTested(); @@ -252,7 +248,7 @@ export async function hookBehaveLikeThis<T extends object, PropsType>( hookFunction: (p: PropsType) => RecursiveState<T>, props: PropsType, checks: Array<(state: Exclude<T, VoidFunction>) => void>, - Context?: ({ children }: { children: any }) => VNode | null, + Context?: ({ children }: { children: any }) => VNode<any> | null, ): Promise<HookTestResult> { const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } = mountHook<T>(() => hookFunction(props), Context); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml @@ -80,11 +80,11 @@ importers: specifier: ^3.3.0 version: 3.3.0 preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) preact-router: specifier: ^3.2.1 - version: 3.2.1(preact@10.11.3) + version: 3.2.1(preact@10.29.8) qrcode-generator: specifier: ^1.4.4 version: 1.4.4 @@ -113,6 +113,9 @@ importers: chai: specifier: ^6.2.2 version: 6.2.2 + happy-dom: + specifier: ^20.11.2 + version: 20.11.6 sass: specifier: 1.56.1 version: 1.56.1 @@ -129,8 +132,8 @@ importers: specifier: workspace:* version: link:../web-util preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) swr: specifier: 2.0.3 version: 2.0.3(react@18.3.1) @@ -200,8 +203,8 @@ importers: specifier: 2.29.3 version: 2.29.3 preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) swr: specifier: 2.0.3 version: 2.0.3(react@18.3.1) @@ -311,14 +314,14 @@ importers: specifier: workspace:* version: link:../web-util preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) swr: specifier: 2.2.2 version: 2.2.2(react@18.3.1) wouter-preact: specifier: ^3.0.0 - version: 3.10.0(preact@10.11.3) + version: 3.10.0(preact@10.29.8) devDependencies: '@gnu-taler/pogen': specifier: workspace:* @@ -357,14 +360,14 @@ importers: specifier: 1.1.1 version: 1.1.1 preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) swr: specifier: 2.2.2 version: 2.2.2(react@18.3.1) wouter-preact: specifier: ^3.7.1 - version: 3.10.0(preact@10.11.3) + version: 3.10.0(preact@10.29.8) devDependencies: '@gnu-taler/pogen': specifier: workspace:* @@ -412,8 +415,8 @@ importers: specifier: 2.29.3 version: 2.29.3 preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) swr: specifier: 2.0.3 version: 2.0.3(react@18.3.1) @@ -444,7 +447,7 @@ importers: version: 0.28.0 preact-render-to-string: specifier: ^5.2.6 - version: 5.2.6(preact@10.11.3) + version: 5.2.6(preact@10.29.8) tailwindcss: specifier: 3.4.17 version: 3.4.17(ts-node@10.9.1(@types/node@20.19.41)(typescript@7.0.2)) @@ -701,7 +704,7 @@ importers: specifier: ^1.4.0 version: 1.4.0 preact: - specifier: ^10.27.2 + specifier: 10.29.8 version: 10.29.8(preact-render-to-string@5.2.6) qrcode-generator: specifier: 1.4.4 @@ -779,7 +782,7 @@ importers: version: 0.5.9(tailwindcss@3.4.17(ts-node@10.9.1(@types/node@20.19.41)(typescript@7.0.2))) '@testing-library/preact': specifier: ^3.2.4 - version: 3.2.4(preact@10.11.3) + version: 3.2.4(preact@10.29.8) '@types/node': specifier: ^20.19.41 version: 20.19.41 @@ -814,11 +817,11 @@ importers: specifier: ^4.0.1 version: 4.0.2(postcss@8.4.49)(ts-node@10.9.1(@types/node@20.19.41)(typescript@7.0.2)) preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@5.2.6) preact-render-to-string: specifier: ^5.2.6 - version: 5.2.6(preact@10.11.3) + version: 5.2.6(preact@10.29.8) prettier: specifier: ^3.8.3 version: 3.8.3 @@ -3431,9 +3434,6 @@ packages: peerDependencies: preact: '>=10' - preact@10.11.3: - resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} - preact@10.29.8: resolution: {integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==} peerDependencies: @@ -4439,7 +4439,7 @@ snapshots: '@happy-dom/global-registrator@20.11.1': dependencies: '@types/node': 20.19.41 - happy-dom: 20.11.1 + happy-dom: 20.11.6 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4587,11 +4587,6 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/preact@3.2.4(preact@10.11.3)': - dependencies: - '@testing-library/dom': 8.20.1 - preact: 10.11.3 - '@testing-library/preact@3.2.4(preact@10.29.8)': dependencies: '@testing-library/dom': 8.20.1 @@ -6834,22 +6829,14 @@ snapshots: powershell-utils@0.1.0: {} - preact-render-to-string@5.2.6(preact@10.11.3): - dependencies: - preact: 10.11.3 - pretty-format: 3.8.0 - preact-render-to-string@5.2.6(preact@10.29.8): dependencies: preact: 10.29.8(preact-render-to-string@5.2.6) pretty-format: 3.8.0 - optional: true - preact-router@3.2.1(preact@10.11.3): + preact-router@3.2.1(preact@10.29.8): dependencies: - preact: 10.11.3 - - preact@10.11.3: {} + preact: 10.29.8(preact-render-to-string@5.2.6) preact@10.29.8(preact-render-to-string@5.2.6): optionalDependencies: @@ -7698,12 +7685,6 @@ snapshots: word-wrap@1.2.5: {} - wouter-preact@3.10.0(preact@10.11.3): - dependencies: - mitt: 3.0.1 - preact: 10.11.3 - regexparam: 3.0.0 - wouter-preact@3.10.0(preact@10.29.8): dependencies: mitt: 3.0.1