From d971743b464e03a50aefb10f181276e14b456e60 Mon Sep 17 00:00:00 2001 From: Jonas Hungershausen Date: Thu, 24 Oct 2024 17:24:12 +0200 Subject: [PATCH] chore: settings component override API (#250) --- .../src/components/form/form.tsx | 43 ++++++++++--------- .../src/components/form/section.tsx | 4 +- .../src/components/settings/oidc-settings.tsx | 12 +++--- .../components/settings/passkey-settings.tsx | 12 +++--- .../settings/recovery-codes-settings.tsx | 12 +++--- .../src/components/settings/settings-card.tsx | 10 ++--- .../src/components/settings/totp-settings.tsx | 12 +++--- .../components/settings/webauthn-settings.tsx | 12 +++--- .../default/components/default-components.tsx | 19 ++++---- .../theme/default/components/form/social.tsx | 1 - .../src/util/ui/__test__/ui.spec.ts | 12 +++--- packages/elements-react/tsconfig.json | 2 +- 12 files changed, 76 insertions(+), 75 deletions(-) diff --git a/packages/elements-react/src/components/form/form.tsx b/packages/elements-react/src/components/form/form.tsx index 99bf8a73e..89b38ed75 100644 --- a/packages/elements-react/src/components/form/form.tsx +++ b/packages/elements-react/src/components/form/form.tsx @@ -147,6 +147,19 @@ export type OryFlowComponents = { * This is only used, if login is configured to use identifier_first authentication. */ AuthMethodListItem: ComponentType + + /** + * The SettingsSection component is rendered around each section of the settings. + */ + SettingsSection: ComponentType + /** + * The SettingsSectionContent component is rendered around the content of each section of the settings. + */ + SettingsSectionContent: ComponentType + /** + * The SettingsSectionFooter component is rendered around the footer of each section of the settings. + */ + SettingsSectionFooter: ComponentType } Form: { /** @@ -170,6 +183,16 @@ export type OryFlowComponents = { * The FormGroup is rendered around each group of nodes in the UI nodes. */ Group: ComponentType + + OidcSettings: ComponentType + + WebauthnSettings: ComponentType + + PasskeySettings: ComponentType + + TotpSettings: ComponentType + + RecoveryCodesSettings: ComponentType } Message: { /** @@ -185,26 +208,6 @@ export type OryFlowComponents = { Page: { Header: ComponentType } - Settings: { - /** - * The SettingsSection component is rendered around each section of the settings. - */ - Section: ComponentType - /** - * The SettingsSectionContent component is rendered around the content of each section of the settings. - */ - SectionContent: ComponentType - /** - * The SettingsSectionFooter component is rendered around the footer of each section of the settings. - */ - SectionFooter: ComponentType - - Oidc: ComponentType - Webauthn: ComponentType - Passkey: ComponentType - Totp: ComponentType - RecoveryCodes: ComponentType - } } type DeepPartialTwoLevels = { diff --git a/packages/elements-react/src/components/form/section.tsx b/packages/elements-react/src/components/form/section.tsx index 2ecec3e68..684ee203f 100644 --- a/packages/elements-react/src/components/form/section.tsx +++ b/packages/elements-react/src/components/form/section.tsx @@ -11,11 +11,11 @@ export type OryFormSectionProps = PropsWithChildren<{ }> export function OryFormSection({ children, nodes }: OryFormSectionProps) { - const { Settings } = useComponents() + const { Card } = useComponents() return ( - {children} + {children} ) } diff --git a/packages/elements-react/src/components/settings/oidc-settings.tsx b/packages/elements-react/src/components/settings/oidc-settings.tsx index 38bf3718a..95a1fc483 100644 --- a/packages/elements-react/src/components/settings/oidc-settings.tsx +++ b/packages/elements-react/src/components/settings/oidc-settings.tsx @@ -20,7 +20,7 @@ export interface HeadlessSettingsOidcProps { } export function OrySettingsOidc({ nodes }: HeadlessSettingsOidcProps) { - const { Settings } = useComponents() + const { Card, Form } = useComponents() const intl = useIntl() const linkButtons = getLinkButtons(nodes) @@ -28,18 +28,18 @@ export function OrySettingsOidc({ nodes }: HeadlessSettingsOidcProps) { return ( <> - - - - + + {intl.formatMessage({ id: "settings.oidc.info" })} - + ) } diff --git a/packages/elements-react/src/components/settings/passkey-settings.tsx b/packages/elements-react/src/components/settings/passkey-settings.tsx index 288254735..33edd39cf 100644 --- a/packages/elements-react/src/components/settings/passkey-settings.tsx +++ b/packages/elements-react/src/components/settings/passkey-settings.tsx @@ -37,7 +37,7 @@ interface HeadlessSettingsPasskeyProps { } export function OrySettingsPasskey({ nodes }: HeadlessSettingsPasskeyProps) { - const { Settings } = useComponents() + const { Card, Form } = useComponents() const intl = useIntl() const { flow } = useOryFlow() const { groups } = useNodesGroups(flow.ui.nodes) @@ -62,7 +62,7 @@ export function OrySettingsPasskey({ nodes }: HeadlessSettingsPasskeyProps) { return ( <> - ( ))} - - - + + {intl.formatMessage({ id: "settings.passkey.info" })} - + ) } diff --git a/packages/elements-react/src/components/settings/recovery-codes-settings.tsx b/packages/elements-react/src/components/settings/recovery-codes-settings.tsx index a2b6a8bcd..1f16b560e 100644 --- a/packages/elements-react/src/components/settings/recovery-codes-settings.tsx +++ b/packages/elements-react/src/components/settings/recovery-codes-settings.tsx @@ -33,7 +33,7 @@ interface HeadlessSettingsRecoveryCodesProps { export function OrySettingsRecoveryCodes({ nodes, }: HeadlessSettingsRecoveryCodesProps) { - const { Settings } = useComponents() + const { Card, Form } = useComponents() const intl = useIntl() const codesNode = getRecoveryCodes(nodes) @@ -50,19 +50,19 @@ export function OrySettingsRecoveryCodes({ return ( <> - - - - + + {nodes .filter( (node) => @@ -75,7 +75,7 @@ export function OrySettingsRecoveryCodes({ .map((node, k) => ( ))} - + ) } diff --git a/packages/elements-react/src/components/settings/settings-card.tsx b/packages/elements-react/src/components/settings/settings-card.tsx index 5696f183c..bcb18bf48 100644 --- a/packages/elements-react/src/components/settings/settings-card.tsx +++ b/packages/elements-react/src/components/settings/settings-card.tsx @@ -19,7 +19,7 @@ interface SettingsSectionProps { } function SettingsSectionContent({ group, nodes }: SettingsSectionProps) { - const { Settings } = useComponents() + const { Card } = useComponents() const intl = useIntl() const { flow } = useOryFlow() const uniqueGroups = useNodesGroups(flow.ui.nodes) @@ -68,7 +68,7 @@ function SettingsSectionContent({ group, nodes }: SettingsSectionProps) { return ( - ( ))} - - + + {nodes .filter( (node) => @@ -97,7 +97,7 @@ function SettingsSectionContent({ group, nodes }: SettingsSectionProps) { .map((node, k) => ( ))} - + ) } diff --git a/packages/elements-react/src/components/settings/totp-settings.tsx b/packages/elements-react/src/components/settings/totp-settings.tsx index 882910e6f..f051cb0f2 100644 --- a/packages/elements-react/src/components/settings/totp-settings.tsx +++ b/packages/elements-react/src/components/settings/totp-settings.tsx @@ -38,7 +38,7 @@ interface HeadlessSettingsTotpProps { } export function OrySettingsTotp({ nodes }: HeadlessSettingsTotpProps) { - const { Settings, Node } = useComponents() + const { Card, Form, Node } = useComponents() const intl = useIntl() const totpUnlink = getTotpUnlinkInput(nodes) @@ -54,17 +54,17 @@ export function OrySettingsTotp({ nodes }: HeadlessSettingsTotpProps) { totpUnlink: totpUnlink, } as OrySettingsTotpProps - const content = + const content = return ( <> - {content} - - + + {totpUnlink ? intl.formatMessage({ id: "settings.totp.info.linked" }) @@ -76,7 +76,7 @@ export function OrySettingsTotp({ nodes }: HeadlessSettingsTotpProps) { attributes={totpLinkButton.attributes as UiNodeInputAttributes} /> )} - + ) } diff --git a/packages/elements-react/src/components/settings/webauthn-settings.tsx b/packages/elements-react/src/components/settings/webauthn-settings.tsx index 034f11c6c..d79cc3f19 100644 --- a/packages/elements-react/src/components/settings/webauthn-settings.tsx +++ b/packages/elements-react/src/components/settings/webauthn-settings.tsx @@ -48,7 +48,7 @@ interface HeadlessSettingsWebauthnProps { } export function OrySettingsWebauthn({ nodes }: HeadlessSettingsWebauthnProps) { - const { Settings } = useComponents() + const { Card, Form } = useComponents() const intl = useIntl() const { flow } = useOryFlow() const { groups } = useNodesGroups(flow.ui.nodes) @@ -75,7 +75,7 @@ export function OrySettingsWebauthn({ nodes }: HeadlessSettingsWebauthnProps) { return ( <> - } {registerNode && } - - - + + {intl.formatMessage({ id: "settings.webauthn.info" })} - + ) } diff --git a/packages/elements-react/src/theme/default/components/default-components.tsx b/packages/elements-react/src/theme/default/components/default-components.tsx index a966ba5e9..6e1d72657 100644 --- a/packages/elements-react/src/theme/default/components/default-components.tsx +++ b/packages/elements-react/src/theme/default/components/default-components.tsx @@ -51,6 +51,10 @@ export const OryDefaultComponents: OryFlowComponents = { Logo: DefaultCardLogo, Divider: DefaultHorizontalDivider, AuthMethodListItem: DefaultAuthMethodListItem, + + SettingsSection: DefaultFormSection, + SettingsSectionContent: DefaultFormSectionContent, + SettingsSectionFooter: DefaultFormSectionFooter, }, Node: { Button: DefaultButton, @@ -68,6 +72,11 @@ export const OryDefaultComponents: OryFlowComponents = { Root: DefaultFormContainer, Group: DefaultGroupContainer, OidcRoot: DefaultSocialButtonContainer, + RecoveryCodesSettings: DefaultSettingsRecoveryCodes, + TotpSettings: DefaultSettingsTotp, + OidcSettings: DefaultSettingsOidc, + WebauthnSettings: DefaultSettingsWebauthn, + PasskeySettings: DefaultSettingsPasskey, }, Message: { Root: DefaultMessageContainer, @@ -76,14 +85,4 @@ export const OryDefaultComponents: OryFlowComponents = { Page: { Header: DefaultPageHeader, }, - Settings: { - Section: DefaultFormSection, - SectionContent: DefaultFormSectionContent, - SectionFooter: DefaultFormSectionFooter, - RecoveryCodes: DefaultSettingsRecoveryCodes, - Totp: DefaultSettingsTotp, - Oidc: DefaultSettingsOidc, - Webauthn: DefaultSettingsWebauthn, - Passkey: DefaultSettingsPasskey, - }, } 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 832c7ebdb..0bc00e139 100644 --- a/packages/elements-react/src/theme/default/components/form/social.tsx +++ b/packages/elements-react/src/theme/default/components/form/social.tsx @@ -7,7 +7,6 @@ import { uiTextToFormattedMessage, useOryFlow, } from "@ory/elements-react" -import { useOryFlow } from "@ory/elements-react" import logos from "../../provider-logos" import { cn } from "../../utils/cn" import { useIntl } from "react-intl" diff --git a/packages/elements-react/src/util/ui/__test__/ui.spec.ts b/packages/elements-react/src/util/ui/__test__/ui.spec.ts index b75cb07b8..2e4b4e4e1 100644 --- a/packages/elements-react/src/util/ui/__test__/ui.spec.ts +++ b/packages/elements-react/src/util/ui/__test__/ui.spec.ts @@ -14,11 +14,11 @@ describe("utils/ui", () => { useNodesGroups(allMethodsInitialForm.ui.nodes as UiNode[]), ) - expect(result.current.oidc).toHaveLength(2) - expect(result.current.default).toHaveLength(2) - expect(result.current.webauthn).toHaveLength(2) - expect(result.current.passkey).toHaveLength(3) - expect(result.current.password).toHaveLength(2) - expect(result.current.code).toHaveLength(1) + expect(result.current.groups.oidc).toHaveLength(2) + expect(result.current.groups.default).toHaveLength(2) + expect(result.current.groups.webauthn).toHaveLength(2) + expect(result.current.groups.passkey).toHaveLength(3) + expect(result.current.groups.password).toHaveLength(2) + expect(result.current.groups.code).toHaveLength(1) }) }) diff --git a/packages/elements-react/tsconfig.json b/packages/elements-react/tsconfig.json index 106512be5..44c733162 100644 --- a/packages/elements-react/tsconfig.json +++ b/packages/elements-react/tsconfig.json @@ -17,7 +17,7 @@ "declarationDir": "dist/types", "jsx": "react-jsx", "lib": ["ES6", "DOM", "WebWorker"], - "rootDir": "src", + "rootDir": ".", "paths": { "@ory/elements-react": ["./src/index.ts"], "@tests/*": ["./src/tests/*"]