diff --git a/package-lock.json b/package-lock.json index 125c658c..9529c785 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26204,7 +26204,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, "license": "MIT" }, "node_modules/lodash.flattendeep": { @@ -33272,6 +33271,21 @@ } } }, + "node_modules/usehooks-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.1.tgz", + "integrity": "sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==", + "license": "MIT", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -35107,6 +35121,7 @@ "react-hook-form": "7.53.0", "react-intl": "6.7.0", "tailwind-merge": "2.5.2", + "usehooks-ts": "3.1.1", "zustand": "5.0.0" }, "devDependencies": { diff --git a/packages/elements-react/package.json b/packages/elements-react/package.json index 7243f344..59d28d18 100644 --- a/packages/elements-react/package.json +++ b/packages/elements-react/package.json @@ -49,6 +49,7 @@ "react-hook-form": "7.53.0", "react-intl": "6.7.0", "tailwind-merge": "2.5.2", + "usehooks-ts": "3.1.1", "zustand": "5.0.0" }, "peerDependencies": { diff --git a/packages/elements-react/src/theme/default/components/form/social.tsx b/packages/elements-react/src/theme/default/components/form/social.tsx index 4c255051..6d46c67b 100644 --- a/packages/elements-react/src/theme/default/components/form/social.tsx +++ b/packages/elements-react/src/theme/default/components/form/social.tsx @@ -7,11 +7,12 @@ import { uiTextToFormattedMessage, useOryFlow, } from "@ory/elements-react" +import { ElementType, useEffect } from "react" +import { useFormContext } from "react-hook-form" +import { useIntl } from "react-intl" +import { useDebounceValue } from "usehooks-ts" import defaultLogos from "../../provider-logos" import { cn } from "../../utils/cn" -import { useIntl } from "react-intl" -import { ElementType, useEffect, useState } from "react" -import { useFormContext } from "react-hook-form" import { Spinner } from "./spinner" export function extractProvider( @@ -50,7 +51,9 @@ export function DefaultButtonSocial({ const { flow: { ui }, } = useOryFlow() - const [clicked, setClicked] = useState(false) + // Safari cancels form submission events, if we do a state update in the same tick + // so we delay the state update by 100ms + const [clicked, setClicked] = useDebounceValue(false, 100) const intl = useIntl() const { formState: { isSubmitting }, @@ -72,15 +75,15 @@ export function DefaultButtonSocial({ const provider = extractProvider(node.meta.label?.context) ?? "" const localOnClick = () => { - setClicked(true) onClick?.() + setClicked(true) } useEffect(() => { if (!isSubmitting) { setClicked(false) } - }, [isSubmitting]) + }, [isSubmitting, setClicked]) return ( ) diff --git a/packages/elements-react/src/theme/default/components/settings/settings-oidc.tsx b/packages/elements-react/src/theme/default/components/settings/settings-oidc.tsx index d4a74833..f10b2b50 100644 --- a/packages/elements-react/src/theme/default/components/settings/settings-oidc.tsx +++ b/packages/elements-react/src/theme/default/components/settings/settings-oidc.tsx @@ -3,8 +3,9 @@ import { UiNode, UiNodeInputAttributes } from "@ory/client-fetch" import { OrySettingsOidcProps } from "@ory/elements-react" -import { useEffect, useState } from "react" +import { useEffect } from "react" import { useFormContext } from "react-hook-form" +import { useDebounceValue } from "usehooks-ts" import Trash from "../../assets/icons/trash.svg" import logos from "../../provider-logos" import { DefaultHorizontalDivider } from "../form/horizontal-divider" @@ -53,33 +54,31 @@ type UnlinkRowProps = { } function UnlinkRow({ button }: UnlinkRowProps) { - const [clicked, setClicked] = useState(false) + // Safari cancels form submission events, if we do a state update in the same tick + // so we delay the state update by 100ms + const [clicked, setClicked] = useDebounceValue(false, 100) const { formState: { isSubmitting }, } = useFormContext() const attrs = button.attributes as UiNodeInputAttributes const provider = extractProvider(button.meta.label?.context) ?? "" - const Logo = attrs.value in logos ? logos[attrs.value] : logos.generic + const Logo = logos[(attrs.value as string).split("-")[0]] const localOnClick = () => { button.onClick() - // Safari cancels form submission events, if we do a state update in the same tick - // so we delay the state update by 100ms - setTimeout(() => { - setClicked(true) - }, 100) + setClicked(true) } useEffect(() => { if (!isSubmitting) { setClicked(false) } - }, [isSubmitting]) + }, [isSubmitting, setClicked]) return (
{provider}