Skip to content

Commit

Permalink
chore: settings component override API (#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas-jonas committed Oct 24, 2024
1 parent 3ce8ee1 commit d971743
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 75 deletions.
43 changes: 23 additions & 20 deletions packages/elements-react/src/components/form/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ export type OryFlowComponents = {
* This is only used, if login is configured to use identifier_first authentication.
*/
AuthMethodListItem: ComponentType<OryCardAuthMethodListItemProps>

/**
* The SettingsSection component is rendered around each section of the settings.
*/
SettingsSection: ComponentType<OryFormSectionProps>
/**
* The SettingsSectionContent component is rendered around the content of each section of the settings.
*/
SettingsSectionContent: ComponentType<OryFormSectionContentProps>
/**
* The SettingsSectionFooter component is rendered around the footer of each section of the settings.
*/
SettingsSectionFooter: ComponentType<OryFormSectionContentProps>
}
Form: {
/**
Expand All @@ -170,6 +183,16 @@ export type OryFlowComponents = {
* The FormGroup is rendered around each group of nodes in the UI nodes.
*/
Group: ComponentType<OryFormGroupProps>

OidcSettings: ComponentType<OrySettingsOidcProps>

WebauthnSettings: ComponentType<OrySettingsWebauthnProps>

PasskeySettings: ComponentType<OrySettingsPasskeyProps>

TotpSettings: ComponentType<OrySettingsTotpProps>

RecoveryCodesSettings: ComponentType<OrySettingsRecoveryCodesProps>
}
Message: {
/**
Expand All @@ -185,26 +208,6 @@ export type OryFlowComponents = {
Page: {
Header: ComponentType<OryPageHeaderProps>
}
Settings: {
/**
* The SettingsSection component is rendered around each section of the settings.
*/
Section: ComponentType<OryFormSectionProps>
/**
* The SettingsSectionContent component is rendered around the content of each section of the settings.
*/
SectionContent: ComponentType<OryFormSectionContentProps>
/**
* The SettingsSectionFooter component is rendered around the footer of each section of the settings.
*/
SectionFooter: ComponentType<OryFormSectionContentProps>

Oidc: ComponentType<OrySettingsOidcProps>
Webauthn: ComponentType<OrySettingsWebauthnProps>
Passkey: ComponentType<OrySettingsPasskeyProps>
Totp: ComponentType<OrySettingsTotpProps>
RecoveryCodes: ComponentType<OrySettingsRecoveryCodesProps>
}
}

type DeepPartialTwoLevels<T> = {
Expand Down
4 changes: 2 additions & 2 deletions packages/elements-react/src/components/form/section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ export type OryFormSectionProps = PropsWithChildren<{
}>

export function OryFormSection({ children, nodes }: OryFormSectionProps) {
const { Settings } = useComponents()
const { Card } = useComponents()

return (
<OryForm nodes={nodes}>
<Settings.Section>{children}</Settings.Section>
<Card.SettingsSection>{children}</Card.SettingsSection>
</OryForm>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,26 @@ export interface HeadlessSettingsOidcProps {
}

export function OrySettingsOidc({ nodes }: HeadlessSettingsOidcProps) {
const { Settings } = useComponents()
const { Card, Form } = useComponents()
const intl = useIntl()

const linkButtons = getLinkButtons(nodes)
const unlinkButtons = getUnlinkButtons(nodes)

return (
<>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({ id: "settings.oidc.title" })}
description={intl.formatMessage({ id: "settings.oidc.description" })}
>
<Settings.Oidc
<Form.OidcSettings
linkButtons={linkButtons}
unlinkButtons={unlinkButtons}
/>
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
<span>{intl.formatMessage({ id: "settings.oidc.info" })}</span>
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -62,7 +62,7 @@ export function OrySettingsPasskey({ nodes }: HeadlessSettingsPasskeyProps) {

return (
<>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({ id: "settings.passkey.title" })}
description={intl.formatMessage({
id: "settings.passkey.description",
Expand All @@ -74,18 +74,18 @@ export function OrySettingsPasskey({ nodes }: HeadlessSettingsPasskeyProps) {
{settingsNodes.map((node, i) => (
<Node key={`passkey-settings-nodes-${i}`} node={node} />
))}
<Settings.Passkey
<Form.PasskeySettings
triggerButton={{
...triggerButton,
attributes: triggerAttributes as UiNodeAttributes,
onClick: onTriggerClick,
}}
removeButtons={removeNodes}
/>
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
<span>{intl.formatMessage({ id: "settings.passkey.info" })}</span>
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -50,19 +50,19 @@ export function OrySettingsRecoveryCodes({

return (
<>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({ id: "settings.lookup_secret.title" })}
description={intl.formatMessage({
id: "settings.lookup_secret.description",
})}
>
<Settings.RecoveryCodes
<Form.RecoveryCodesSettings
codes={secrets}
revealButton={revealNode}
regnerateButton={regenerateNode}
/>
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
{nodes
.filter(
(node) =>
Expand All @@ -75,7 +75,7 @@ export function OrySettingsRecoveryCodes({
.map((node, k) => (
<Node key={k} node={node} />
))}
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -68,7 +68,7 @@ function SettingsSectionContent({ group, nodes }: SettingsSectionProps) {

return (
<OryFormSection nodes={nodes}>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({
id: `settings.${group}.title`,
})}
Expand All @@ -87,8 +87,8 @@ function SettingsSectionContent({ group, nodes }: SettingsSectionProps) {
.map((node, k) => (
<Node key={k} node={node} />
))}
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
{nodes
.filter(
(node) =>
Expand All @@ -97,7 +97,7 @@ function SettingsSectionContent({ group, nodes }: SettingsSectionProps) {
.map((node, k) => (
<Node key={k} node={node} />
))}
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</OryFormSection>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -54,17 +54,17 @@ export function OrySettingsTotp({ nodes }: HeadlessSettingsTotpProps) {
totpUnlink: totpUnlink,
} as OrySettingsTotpProps

const content = <Settings.Totp {...props} />
const content = <Form.TotpSettings {...props} />

return (
<>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({ id: "settings.totp.title" })}
description={intl.formatMessage({ id: "settings.totp.description" })}
>
{content}
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
<span>
{totpUnlink
? intl.formatMessage({ id: "settings.totp.info.linked" })
Expand All @@ -76,7 +76,7 @@ export function OrySettingsTotp({ nodes }: HeadlessSettingsTotpProps) {
attributes={totpLinkButton.attributes as UiNodeInputAttributes}
/>
)}
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -75,7 +75,7 @@ export function OrySettingsWebauthn({ nodes }: HeadlessSettingsWebauthnProps) {

return (
<>
<Settings.SectionContent
<Card.SettingsSectionContent
title={intl.formatMessage({ id: "settings.webauthn.title" })}
description={intl.formatMessage({
id: "settings.webauthn.description",
Expand All @@ -86,7 +86,7 @@ export function OrySettingsWebauthn({ nodes }: HeadlessSettingsWebauthnProps) {
))}
{scriptNode && <Node node={scriptNode} />}
{registerNode && <Node node={registerNode} />}
<Settings.Webauthn
<Form.WebauthnSettings
nameInput={inputNode}
triggerButton={{
...triggerButton,
Expand All @@ -95,10 +95,10 @@ export function OrySettingsWebauthn({ nodes }: HeadlessSettingsWebauthnProps) {
}}
removeButtons={removeButtons}
/>
</Settings.SectionContent>
<Settings.SectionFooter>
</Card.SettingsSectionContent>
<Card.SettingsSectionFooter>
<span>{intl.formatMessage({ id: "settings.webauthn.info" })}</span>
</Settings.SectionFooter>
</Card.SettingsSectionFooter>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export const OryDefaultComponents: OryFlowComponents = {
Logo: DefaultCardLogo,
Divider: DefaultHorizontalDivider,
AuthMethodListItem: DefaultAuthMethodListItem,

SettingsSection: DefaultFormSection,
SettingsSectionContent: DefaultFormSectionContent,
SettingsSectionFooter: DefaultFormSectionFooter,
},
Node: {
Button: DefaultButton,
Expand All @@ -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,
Expand All @@ -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,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 6 additions & 6 deletions packages/elements-react/src/util/ui/__test__/ui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
})
2 changes: 1 addition & 1 deletion packages/elements-react/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/*"]
Expand Down

0 comments on commit d971743

Please sign in to comment.