diff options
author | 2024-08-24 02:52:07 +0100 | |
---|---|---|
committer | 2024-08-24 02:52:07 +0100 | |
commit | 4f8835a48ab627e2d1d18a1eb2f537210f730e11 (patch) | |
tree | 19afdf07b4674de1dc761a06782e43ac432cbf6d /src | |
parent | update keycloakify (diff) |
Add some pydis styling
Diffstat (limited to 'src')
36 files changed, 1206 insertions, 0 deletions
diff --git a/src/login/KcContext.ts b/src/login/KcContext.ts index a130466..abe9ebb 100644 --- a/src/login/KcContext.ts +++ b/src/login/KcContext.ts @@ -5,6 +5,7 @@ import type { KcEnvName, ThemeName } from "../kc.gen"; export type KcContextExtension = { themeName: ThemeName; properties: Record<KcEnvName, string> & {}; + realm: Record<KcEnvName, string> & {}; }; export type KcContextExtensionPerPage = {}; diff --git a/src/login/KcPageStory.tsx b/src/login/KcPageStory.tsx index 2a69b6a..5d0eb3b 100644 --- a/src/login/KcPageStory.tsx +++ b/src/login/KcPageStory.tsx @@ -9,6 +9,9 @@ const kcContextExtension: KcContextExtension = { themeName: themeNames[0], properties: { ...kcEnvDefaults + }, + realm: { + displayNameHtml: '<div class="kc-logo-text"><span>Python Discord</span></div>', } }; const kcContextExtensionPerPage: KcContextExtensionPerPage = {}; diff --git a/src/login/pages/Code.stories.tsx b/src/login/pages/Code.stories.tsx new file mode 100644 index 0000000..0fcdf87 --- /dev/null +++ b/src/login/pages/Code.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "code.ftl" }); + +const meta = { + title: "login/code.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/DeleteAccountConfirm.stories.tsx b/src/login/pages/DeleteAccountConfirm.stories.tsx new file mode 100644 index 0000000..501fa0c --- /dev/null +++ b/src/login/pages/DeleteAccountConfirm.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "delete-account-confirm.ftl" }); + +const meta = { + title: "login/delete-account-confirm.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/DeleteCredential.stories.tsx b/src/login/pages/DeleteCredential.stories.tsx new file mode 100644 index 0000000..7b211a5 --- /dev/null +++ b/src/login/pages/DeleteCredential.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "delete-credential.ftl" }); + +const meta = { + title: "login/delete-credential.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/Error.stories.tsx b/src/login/pages/Error.stories.tsx new file mode 100644 index 0000000..7b12410 --- /dev/null +++ b/src/login/pages/Error.stories.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "error.ftl" }); + +const meta = { + title: "login/error.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithAnotherMessage: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { summary: "With another error message" } + }} + /> + ) +}; diff --git a/src/login/pages/FrontchannelLogout.stories.tsx b/src/login/pages/FrontchannelLogout.stories.tsx new file mode 100644 index 0000000..9dacf0b --- /dev/null +++ b/src/login/pages/FrontchannelLogout.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "frontchannel-logout.ftl" }); + +const meta = { + title: "login/frontchannel-logout.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/IdpReviewUserProfile.stories.tsx b/src/login/pages/IdpReviewUserProfile.stories.tsx new file mode 100644 index 0000000..6778e77 --- /dev/null +++ b/src/login/pages/IdpReviewUserProfile.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "idp-review-user-profile.ftl" }); + +const meta = { + title: "login/idp-review-user-profile.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/Info.stories.tsx b/src/login/pages/Info.stories.tsx new file mode 100644 index 0000000..195061f --- /dev/null +++ b/src/login/pages/Info.stories.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "info.ftl" }); + +const meta = { + title: "login/info.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { + summary: "Server info message" + } + }} + /> + ) +}; + +export const WithLinkBack: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { + summary: "Server message" + }, + actionUri: undefined + }} + /> + ) +}; + +export const WithRequiredActions: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { + summary: "Required actions: " + }, + requiredActions: ["CONFIGURE_TOTP", "UPDATE_PROFILE", "VERIFY_EMAIL", "CUSTOM_ACTION"], + "x-keycloakify": { + messages: { + "requiredAction.CUSTOM_ACTION": "Custom action" + } + } + }} + /> + ) +}; diff --git a/src/login/pages/Login.stories.tsx b/src/login/pages/Login.stories.tsx new file mode 100644 index 0000000..075d1f9 --- /dev/null +++ b/src/login/pages/Login.stories.tsx @@ -0,0 +1,233 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login.ftl" }); + +const meta = { + title: "login/login.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithInvalidCredential: Story = { + render: () => ( + <KcPageStory + kcContext={{ + login: { + username: "johndoe" + }, + messagesPerField: { + // NOTE: The other functions of messagesPerField are derived from get() and + // existsError() so they are the only ones that need to mock. + existsError: (fieldName: string, ...otherFieldNames: string[]) => { + const fieldNames = [fieldName, ...otherFieldNames]; + return fieldNames.includes("username") || fieldNames.includes("password"); + }, + get: (fieldName: string) => { + if (fieldName === "username" || fieldName === "password") { + return "Invalid username or password."; + } + return ""; + } + } + }} + /> + ) +}; + +export const WithoutRegistration: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { registrationAllowed: false } + }} + /> + ) +}; + +export const WithoutRememberMe: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { rememberMe: false } + }} + /> + ) +}; + +export const WithoutPasswordReset: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { resetPasswordAllowed: false } + }} + /> + ) +}; + +export const WithEmailAsUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { loginWithEmailAllowed: false } + }} + /> + ) +}; + +export const WithPresetUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + login: { username: "[email protected]" } + }} + /> + ) +}; + +export const WithImmutablePresetUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + auth: { + attemptedUsername: "[email protected]", + showUsername: true + }, + usernameHidden: true, + message: { + type: "info", + summary: "Please re-authenticate to continue" + } + }} + /> + ) +}; + +export const WithSocialProviders: Story = { + render: () => ( + <KcPageStory + kcContext={{ + social: { + displayInfo: true, + providers: [ + { + loginUrl: "google", + alias: "google", + providerId: "google", + displayName: "Google", + iconClasses: "fa fa-google" + }, + { + loginUrl: "microsoft", + alias: "microsoft", + providerId: "microsoft", + displayName: "Microsoft", + iconClasses: "fa fa-windows" + }, + { + loginUrl: "facebook", + alias: "facebook", + providerId: "facebook", + displayName: "Facebook", + iconClasses: "fa fa-facebook" + }, + { + loginUrl: "instagram", + alias: "instagram", + providerId: "instagram", + displayName: "Instagram", + iconClasses: "fa fa-instagram" + }, + { + loginUrl: "twitter", + alias: "twitter", + providerId: "twitter", + displayName: "Twitter", + iconClasses: "fa fa-twitter" + }, + { + loginUrl: "linkedin", + alias: "linkedin", + providerId: "linkedin", + displayName: "LinkedIn", + iconClasses: "fa fa-linkedin" + }, + { + loginUrl: "stackoverflow", + alias: "stackoverflow", + providerId: "stackoverflow", + displayName: "Stackoverflow", + iconClasses: "fa fa-stack-overflow" + }, + { + loginUrl: "github", + alias: "github", + providerId: "github", + displayName: "Github", + iconClasses: "fa fa-github" + }, + { + loginUrl: "gitlab", + alias: "gitlab", + providerId: "gitlab", + displayName: "Gitlab", + iconClasses: "fa fa-gitlab" + }, + { + loginUrl: "bitbucket", + alias: "bitbucket", + providerId: "bitbucket", + displayName: "Bitbucket", + iconClasses: "fa fa-bitbucket" + }, + { + loginUrl: "paypal", + alias: "paypal", + providerId: "paypal", + displayName: "PayPal", + iconClasses: "fa fa-paypal" + }, + { + loginUrl: "openshift", + alias: "openshift", + providerId: "openshift", + displayName: "OpenShift", + iconClasses: "fa fa-cloud" + } + ] + } + }} + /> + ) +}; + +export const WithoutPasswordField: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { password: false } + }} + /> + ) +}; + +export const WithErrorMessage: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { + summary: "The time allotted for the connection has elapsed.<br/>The login process will restart from the beginning.", + type: "error" + } + }} + /> + ) +}; diff --git a/src/login/pages/LoginConfigTotp.stories.tsx b/src/login/pages/LoginConfigTotp.stories.tsx new file mode 100644 index 0000000..5d38df9 --- /dev/null +++ b/src/login/pages/LoginConfigTotp.stories.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-config-totp.ftl" }); + +const meta = { + title: "login/login-config-totp.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithManualSetUp: Story = { + render: () => ( + <KcPageStory + kcContext={{ + mode: "manual" + }} + /> + ) +}; + +export const WithError: Story = { + render: () => ( + <KcPageStory + kcContext={{ + messagesPerField: { + get: (fieldName: string) => (fieldName === "totp" ? "Invalid TOTP" : undefined), + exists: (fieldName: string) => fieldName === "totp", + existsError: (fieldName: string) => fieldName === "totp", + printIfExists: <T,>(fieldName: string, x: T) => (fieldName === "totp" ? x : undefined) + } + }} + /> + ) +}; diff --git a/src/login/pages/LoginIdpLinkConfirm.stories.tsx b/src/login/pages/LoginIdpLinkConfirm.stories.tsx new file mode 100644 index 0000000..6642bf2 --- /dev/null +++ b/src/login/pages/LoginIdpLinkConfirm.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-idp-link-confirm.ftl" }); + +const meta = { + title: "login/login-idp-link-confirm.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginIdpLinkEmail.stories.tsx b/src/login/pages/LoginIdpLinkEmail.stories.tsx new file mode 100644 index 0000000..a58ae2d --- /dev/null +++ b/src/login/pages/LoginIdpLinkEmail.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-idp-link-email.ftl" }); + +const meta = { + title: "login/login-idp-link-email.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginOauth2DeviceVerifyUserCode.stories.tsx b/src/login/pages/LoginOauth2DeviceVerifyUserCode.stories.tsx new file mode 100644 index 0000000..c042174 --- /dev/null +++ b/src/login/pages/LoginOauth2DeviceVerifyUserCode.stories.tsx @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-oauth2-device-verify-user-code.ftl" }); + +const meta = { + title: "login/login-oauth2-device-verify-user-code.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginOauthGrant.stories.tsx b/src/login/pages/LoginOauthGrant.stories.tsx new file mode 100644 index 0000000..5356990 --- /dev/null +++ b/src/login/pages/LoginOauthGrant.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-oauth-grant.ftl" }); + +const meta = { + title: "login/login-oauth-grant.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginOtp.stories.tsx b/src/login/pages/LoginOtp.stories.tsx new file mode 100644 index 0000000..84b1061 --- /dev/null +++ b/src/login/pages/LoginOtp.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-otp.ftl" }); + +const meta = { + title: "login/login-otp.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginPageExpired.stories.tsx b/src/login/pages/LoginPageExpired.stories.tsx new file mode 100644 index 0000000..22e4307 --- /dev/null +++ b/src/login/pages/LoginPageExpired.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-page-expired.ftl" }); + +const meta = { + title: "login/login-page-expired.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginPassword.stories.tsx b/src/login/pages/LoginPassword.stories.tsx new file mode 100644 index 0000000..247ec78 --- /dev/null +++ b/src/login/pages/LoginPassword.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-password.ftl" }); + +const meta = { + title: "login/login-password.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginRecoveryAuthnCodeConfig.stories.tsx b/src/login/pages/LoginRecoveryAuthnCodeConfig.stories.tsx new file mode 100644 index 0000000..26c181f --- /dev/null +++ b/src/login/pages/LoginRecoveryAuthnCodeConfig.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-recovery-authn-code-config.ftl" }); + +const meta = { + title: "login/login-recovery-authn-code-config.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginRecoveryAuthnCodeInput.stories.tsx b/src/login/pages/LoginRecoveryAuthnCodeInput.stories.tsx new file mode 100644 index 0000000..d4cddcc --- /dev/null +++ b/src/login/pages/LoginRecoveryAuthnCodeInput.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-recovery-authn-code-input.ftl" }); + +const meta = { + title: "login/login-recovery-authn-code-input.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginResetOtp.stories.tsx b/src/login/pages/LoginResetOtp.stories.tsx new file mode 100644 index 0000000..59db763 --- /dev/null +++ b/src/login/pages/LoginResetOtp.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-reset-otp.ftl" }); + +const meta = { + title: "login/login-reset-otp.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginResetPassword.stories.tsx b/src/login/pages/LoginResetPassword.stories.tsx new file mode 100644 index 0000000..12412f3 --- /dev/null +++ b/src/login/pages/LoginResetPassword.stories.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-reset-password.ftl" }); + +const meta = { + title: "login/login-reset-password.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithEmailAsUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { + loginWithEmailAllowed: true, + registrationEmailAsUsername: true + } + }} + /> + ) +}; diff --git a/src/login/pages/LoginUpdatePassword.stories.tsx b/src/login/pages/LoginUpdatePassword.stories.tsx new file mode 100644 index 0000000..904e398 --- /dev/null +++ b/src/login/pages/LoginUpdatePassword.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-update-password.ftl" }); + +const meta = { + title: "login/login-update-password.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginUpdateProfile.stories.tsx b/src/login/pages/LoginUpdateProfile.stories.tsx new file mode 100644 index 0000000..bb5a6e0 --- /dev/null +++ b/src/login/pages/LoginUpdateProfile.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-update-profile.ftl" }); + +const meta = { + title: "login/login-update-profile.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LoginUsername.stories.tsx b/src/login/pages/LoginUsername.stories.tsx new file mode 100644 index 0000000..a391ffb --- /dev/null +++ b/src/login/pages/LoginUsername.stories.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-username.ftl" }); + +const meta = { + title: "login/login-username.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithEmailAsUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { + loginWithEmailAllowed: true, + registrationEmailAsUsername: true + } + }} + /> + ) +}; diff --git a/src/login/pages/LoginVerifyEmail.stories.tsx b/src/login/pages/LoginVerifyEmail.stories.tsx new file mode 100644 index 0000000..6da554d --- /dev/null +++ b/src/login/pages/LoginVerifyEmail.stories.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-verify-email.ftl" }); + +const meta = { + title: "login/login-verify-email.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => ( + <KcPageStory + kcContext={{ + message: { + summary: "You need to verify your email to activate your account.", + type: "warning" + }, + user: { + email: "[email protected]" + } + }} + /> + ) +}; diff --git a/src/login/pages/LoginX509Info.stories.tsx b/src/login/pages/LoginX509Info.stories.tsx new file mode 100644 index 0000000..f3c6be7 --- /dev/null +++ b/src/login/pages/LoginX509Info.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "login-x509-info.ftl" }); + +const meta = { + title: "login/login-x509-info.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/LogoutConfirm.stories.tsx b/src/login/pages/LogoutConfirm.stories.tsx new file mode 100644 index 0000000..20ae5c9 --- /dev/null +++ b/src/login/pages/LogoutConfirm.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "logout-confirm.ftl" }); + +const meta = { + title: "login/logout-confirm.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/Register.stories.tsx b/src/login/pages/Register.stories.tsx new file mode 100644 index 0000000..0a8c395 --- /dev/null +++ b/src/login/pages/Register.stories.tsx @@ -0,0 +1,187 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; +import type { Attribute } from "../../../dist/login"; + +const { KcPageStory } = createKcPageStory({ pageId: "register.ftl" }); + +const meta = { + title: "login/register.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithEmailAlreadyExists: Story = { + render: () => ( + <KcPageStory + kcContext={{ + profile: { + attributesByName: { + username: { + value: "johndoe" + }, + email: { + value: "[email protected]" + }, + firstName: { + value: "John" + }, + lastName: { + value: "Doe" + } + } + }, + messagesPerField: { + // NOTE: The other functions of messagesPerField are derived from get() and + // existsError() so they are the only ones that need to mock. + existsError: (fieldName: string, ...otherFieldNames: string[]) => [fieldName, ...otherFieldNames].includes("email"), + get: (fieldName: string) => (fieldName === "email" ? "Email already exists." : undefined) + } + }} + /> + ) +}; + +export const WithRestrictedToMITStudents: Story = { + render: () => ( + <KcPageStory + kcContext={{ + profile: { + attributesByName: { + email: { + validators: { + pattern: { + pattern: "^[^@]+@([^.]+\\.)*((mit\\.edu)|(berkeley\\.edu))$", + "error-message": "${profile.attributes.email.pattern.error}" + } + }, + annotations: { + inputHelperTextBefore: "${profile.attributes.email.inputHelperTextBefore}" + } + } + } + }, + "x-keycloakify": { + messages: { + "profile.attributes.email.inputHelperTextBefore": "Please use your MIT or Berkeley email.", + "profile.attributes.email.pattern.error": + "This is not an MIT (<strong>@mit.edu</strong>) nor a Berkeley (<strong>@berkeley.edu</strong>) email." + } + } + }} + /> + ) +}; + +export const WithFavoritePet: Story = { + render: () => ( + <KcPageStory + kcContext={{ + profile: { + attributesByName: { + favoritePet: { + name: "favorite-pet", + displayName: "${profile.attributes.favoritePet}", + validators: { + options: { + options: ["cat", "dog", "fish"] + } + }, + annotations: { + inputOptionLabelsI18nPrefix: "profile.attributes.favoritePet.options" + }, + required: false, + readOnly: false + } satisfies Attribute + } + }, + "x-keycloakify": { + messages: { + "profile.attributes.favoritePet": "Favorite Pet", + "profile.attributes.favoritePet.options.cat": "Fluffy Cat", + "profile.attributes.favoritePet.options.dog": "Loyal Dog", + "profile.attributes.favoritePet.options.fish": "Peaceful Fish" + } + } + }} + /> + ) +}; + +export const WithEmailAsUsername: Story = { + render: () => ( + <KcPageStory + kcContext={{ + realm: { + registrationEmailAsUsername: true + }, + profile: { + attributesByName: { + username: undefined + } + } + }} + /> + ) +}; + +export const WithRecaptcha: Story = { + render: () => ( + <KcPageStory + kcContext={{ + scripts: ["https://www.google.com/recaptcha/api.js?hl=en"], + recaptchaRequired: true, + recaptchaSiteKey: "6LfQHvApAAAAAE73SYTd5vS0lB1Xr7zdiQ-6iBVa" + }} + /> + ) +}; + +export const WithRecaptchaFrench: Story = { + render: () => ( + <KcPageStory + kcContext={{ + locale: { + currentLanguageTag: "fr" + }, + scripts: ["https://www.google.com/recaptcha/api.js?hl=fr"], + recaptchaRequired: true, + recaptchaSiteKey: "6LfQHvApAAAAAE73SYTd5vS0lB1Xr7zdiQ-6iBVa" + }} + /> + ) +}; + +export const WithPasswordMinLength8: Story = { + render: () => ( + <KcPageStory + kcContext={{ + passwordPolicies: { + length: 8 + } + }} + /> + ) +}; + +export const WithTermsAcceptance: Story = { + render: () => ( + <KcPageStory + kcContext={{ + termsAcceptanceRequired: true, + "x-keycloakify": { + messages: { + termsText: "<a href='https://example.com/terms'>Service Terms of Use</a>" + } + } + }} + /> + ) +}; diff --git a/src/login/pages/SamlPostForm.stories.tsx b/src/login/pages/SamlPostForm.stories.tsx new file mode 100644 index 0000000..32faad1 --- /dev/null +++ b/src/login/pages/SamlPostForm.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "saml-post-form.ftl" }); + +const meta = { + title: "login/saml-post-form.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/SelectAuthenticator.stories.tsx b/src/login/pages/SelectAuthenticator.stories.tsx new file mode 100644 index 0000000..f5ddcf1 --- /dev/null +++ b/src/login/pages/SelectAuthenticator.stories.tsx @@ -0,0 +1,84 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "select-authenticator.ftl" }); + +const meta = { + title: "login/select-authenticator.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; + +export const WithDifferentAuthenticationMethods: Story = { + render: () => ( + <KcPageStory + kcContext={{ + auth: { + authenticationSelections: [ + { + authExecId: "25697c4e-0c80-4f2c-8eb7-2c16347e8e8d", + displayName: "auth-username-password-form-display-name", + helpText: "auth-username-password-form-help-text", + iconCssClass: "kcAuthenticatorPasswordClass" + }, + { + authExecId: "4cb60872-ce0d-4c8f-a806-e651ed77994b", + displayName: "webauthn-passwordless-display-name", + helpText: "webauthn-passwordless-help-text", + iconCssClass: "kcAuthenticatorWebAuthnPasswordlessClass" + } + ] + } + }} + /> + ) +}; + +export const WithRealmTranslations: Story = { + render: () => ( + <KcPageStory + kcContext={{ + auth: { + authenticationSelections: [ + { + authExecId: "f0c22855-eda7-4092-8565-0c22f77d2ffb", + displayName: "home-idp-discovery-display-name", + helpText: "home-idp-discovery-help-text", + iconCssClass: "kcAuthenticatorDefaultClass" + }, + { + authExecId: "20456f5a-8b2b-45f3-98e0-551dcb27e3e1", + displayName: "identity-provider-redirctor-display-name", + helpText: "identity-provider-redirctor-help-text", + iconCssClass: "kcAuthenticatorDefaultClass" + }, + { + authExecId: "eb435db9-474e-473a-8da7-c184fa510b96", + displayName: "auth-username-password-form-display-name", + helpText: "auth-username-password-help-text", + iconCssClass: "kcAuthenticatorDefaultClass" + } + ] + }, + "x-keycloakify": { + messages: { + "home-idp-discovery-display-name": "Home identity provider", + "home-idp-discovery-help-text": + "Sign in via your home identity provider which will be automatically determined based on your provided email address.", + "identity-provider-redirctor-display-name": "Identity Provider Redirector", + "identity-provider-redirctor-help-text": "Sign in via your identity provider.", + "auth-username-password-help-text": "Sign in via your username and password." + } + } + }} + /> + ) +}; diff --git a/src/login/pages/Terms.stories.tsx b/src/login/pages/Terms.stories.tsx new file mode 100644 index 0000000..f5837b0 --- /dev/null +++ b/src/login/pages/Terms.stories.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "terms.ftl" }); + +const meta = { + title: "login/terms.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => ( + <KcPageStory + kcContext={{ + "x-keycloakify": { + messages: { + termsText: "<p>My terms in <strong>English</strong></p>" + } + } + }} + /> + ) +}; + +export const French: Story = { + render: () => ( + <KcPageStory + kcContext={{ + locale: { + currentLanguageTag: "fr" + }, + "x-keycloakify": { + // cSpell: disable + messages: { + termsText: "<p>Mes terme en <strong>Français</strong></p>" + } + // cSpell: enable + } + }} + /> + ) +}; diff --git a/src/login/pages/UpdateEmail.stories.tsx b/src/login/pages/UpdateEmail.stories.tsx new file mode 100644 index 0000000..bcb5655 --- /dev/null +++ b/src/login/pages/UpdateEmail.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "update-email.ftl" }); + +const meta = { + title: "login/update-email.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/WebauthnAuthenticate.stories.tsx b/src/login/pages/WebauthnAuthenticate.stories.tsx new file mode 100644 index 0000000..fc68e97 --- /dev/null +++ b/src/login/pages/WebauthnAuthenticate.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "webauthn-authenticate.ftl" }); + +const meta = { + title: "login/webauthn-authenticate.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/WebauthnError.stories.tsx b/src/login/pages/WebauthnError.stories.tsx new file mode 100644 index 0000000..db76221 --- /dev/null +++ b/src/login/pages/WebauthnError.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "webauthn-error.ftl" }); + +const meta = { + title: "login/webauthn-error.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; diff --git a/src/login/pages/WebauthnRegister.stories.tsx b/src/login/pages/WebauthnRegister.stories.tsx new file mode 100644 index 0000000..ff8b70b --- /dev/null +++ b/src/login/pages/WebauthnRegister.stories.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { createKcPageStory } from "../KcPageStory"; + +const { KcPageStory } = createKcPageStory({ pageId: "webauthn-register.ftl" }); + +const meta = { + title: "login/webauthn-register.ftl", + component: KcPageStory +} satisfies Meta<typeof KcPageStory>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Default: Story = { + render: () => <KcPageStory /> +}; |