Skip to content

Commit

Permalink
feat(clerk-js,clerk-react,types): Terse params for OrganizationSwitch…
Browse files Browse the repository at this point in the history
…er and UserButton
  • Loading branch information
octoper committed Oct 31, 2023
1 parent 9b3015b commit 8d4259c
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 96 deletions.
15 changes: 13 additions & 2 deletions packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ export const useUserButtonContext = () => {
const afterSwitchSessionUrl = ctx.afterSwitchSessionUrl || displayConfig.afterSwitchSessionUrl;
const navigateAfterSwitchSession = () => navigate(afterSwitchSessionUrl);

const userProfileMode = !!userProfileUrl && ctx.userProfileMode === undefined ? 'navigation' : ctx.userProfileMode;

return {
...ctx,
componentName,
Expand All @@ -252,6 +254,7 @@ export const useUserButtonContext = () => {
afterMultiSessionSingleSignOutUrl,
afterSignOutUrl,
afterSwitchSessionUrl,
userProfileMode,
};
};

Expand Down Expand Up @@ -316,11 +319,19 @@ export const useOrganizationSwitcherContext = () => {

const navigateAfterSelectPersonal = (user: UserResource) => navigateAfterSelectOrganizationOrPersonal({ user });

const organizationProfileMode =
!!ctx.organizationProfileUrl && ctx.organizationProfileMode === undefined
? 'navigation'
: ctx.organizationProfileMode;

const createOrganizationMode =
!!ctx.createOrganizationUrl && ctx.createOrganizationMode === undefined ? 'navigation' : ctx.createOrganizationMode;

return {
...ctx,
hidePersonal: ctx.hidePersonal || false,
organizationProfileMode: ctx.organizationProfileMode || 'modal',
createOrganizationMode: ctx.createOrganizationMode || 'modal',
organizationProfileMode: organizationProfileMode || 'modal',
createOrganizationMode: createOrganizationMode || 'modal',
afterCreateOrganizationUrl,
afterLeaveOrganizationUrl,
navigateOrganizationProfile,
Expand Down
5 changes: 3 additions & 2 deletions packages/react/src/components/uiComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
SignUpProps,
UserButtonProps,
UserProfileProps,
Without,
} from '@clerk/types';
import type { PropsWithChildren } from 'react';
import React, { createElement } from 'react';
Expand Down Expand Up @@ -39,7 +40,7 @@ type UserButtonExportType = typeof _UserButton & {
UserProfileLink: typeof UserProfileLink;
};

type UserButtonPropsWithoutCustomPages = Omit<UserButtonProps, 'userProfileProps'> & {
type UserButtonPropsWithoutCustomPages = Without<UserButtonProps, 'userProfileProps'> & {
userProfileProps?: Pick<UserProfileProps, 'additionalOAuthScopes' | 'appearance'>;
};

Expand All @@ -53,7 +54,7 @@ type OrganizationSwitcherExportType = typeof _OrganizationSwitcher & {
OrganizationProfileLink: typeof OrganizationProfileLink;
};

type OrganizationSwitcherPropsWithoutCustomPages = Omit<OrganizationSwitcherProps, 'organizationProfileProps'> & {
type OrganizationSwitcherPropsWithoutCustomPages = Without<OrganizationSwitcherProps, 'organizationProfileProps'> & {
organizationProfileProps?: Pick<OrganizationProfileProps, 'appearance'>;
};

Expand Down
168 changes: 76 additions & 92 deletions packages/types/src/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,18 @@ export type CreateOrganizationProps = RoutingOptions & {
appearance?: CreateOrganizationTheme;
};

export type UserButtonProps = {
type UserProfileMode = 'modal' | 'navigation';
type UserButtonProfileMode =
| {
userProfileUrl?: never;
userProfileMode?: Extract<UserProfileMode, 'modal'>;
}
| {
userProfileUrl: string;
userProfileMode?: Extract<UserProfileMode, 'navigation'>;
};

export type UserButtonProps = UserButtonProfileMode & {
/**
* Controls if the username is displayed next to the trigger button
*/
Expand All @@ -766,11 +777,6 @@ export type UserButtonProps = {
* This option applies to multi-session applications.
*/
afterMultiSessionSingleSignOutUrl?: string;
/**
* Full URL or path leading to the
* account management interface.
*/
userProfileUrl?: string;
/**
* Full URL or path to navigate on "Add another account" action.
* Multi-session mode only.
Expand All @@ -781,13 +787,6 @@ export type UserButtonProps = {
* Multi-session mode only.
*/
afterSwitchSessionUrl?: string;
/**
* Controls whether clicking the "Manage your account" button will cause
* the UserProfile component to open as a modal, or if the browser will navigate
* to the `userProfileUrl` where UserProfile is mounted as a page.
* @default 'modal'
*/
userProfileMode?: 'modal' | 'navigation';
/**
* Customisation options to fully match the Clerk components to your own brand.
* These options serve as overrides and will be merged with the global `appearance`
Expand All @@ -813,89 +812,74 @@ type PrimitiveKeys<T> = {

type LooseExtractedParams<T extends string> = `:${T}` | (string & NonNullable<unknown>);

export type OrganizationSwitcherProps = {
/**
type OrganizationProfileMode =
| { organizationProfileUrl: string; organizationProfileMode?: 'navigation' }
| { organizationProfileUrl?: never; organizationProfileMode?: 'modal' };

type CreateOrganizationMode =
| { createOrganizationUrl: string; createOrganizationMode?: 'navigation' }
| { createOrganizationUrl?: never; createOrganizationMode?: 'modal' };

export type OrganizationSwitcherProps = CreateOrganizationMode &
OrganizationProfileMode & {
/**
Controls the default state of the OrganizationSwitcher
*/
defaultOpen?: boolean;
/**
* By default, users can switch between organization and their personal account.
* This option controls whether OrganizationSwitcher will include the user's personal account
* in the organization list. Setting this to `false` will hide the personal account entry,
* and users will only be able to switch between organizations.
* @default true
*/
hidePersonal?: boolean;
/**
* Full URL or path to navigate after a successful organization switch.
* @default undefined
* @deprecated use `afterSelectOrganizationUrl` or `afterSelectPersonalUrl`
*/
afterSwitchOrganizationUrl?: string;
/**
* Full URL or path to navigate after creating a new organization.
* @default undefined
*/
afterCreateOrganizationUrl?:
| ((organization: OrganizationResource) => string)
| LooseExtractedParams<PrimitiveKeys<OrganizationResource>>;
/**
* Full URL or path to navigate after a successful organization selection.
* Accepts a function that returns URL or path
* @default undefined`
*/
afterSelectOrganizationUrl?:
| ((organization: OrganizationResource) => string)
| LooseExtractedParams<PrimitiveKeys<OrganizationResource>>;
defaultOpen?: boolean;
/**
* By default, users can switch between organization and their personal account.
* This option controls whether OrganizationSwitcher will include the user's personal account
* in the organization list. Setting this to `false` will hide the personal account entry,
* and users will only be able to switch between organizations.
* @default true
*/
hidePersonal?: boolean;
/**
* Full URL or path to navigate after a successful organization switch.
* @default undefined
* @deprecated use `afterSelectOrganizationUrl` or `afterSelectPersonalUrl`
*/
afterSwitchOrganizationUrl?: string;
/**
* Full URL or path to navigate after creating a new organization.
* @default undefined
*/
afterCreateOrganizationUrl?:
| ((organization: OrganizationResource) => string)
| LooseExtractedParams<PrimitiveKeys<OrganizationResource>>;
/**
* Full URL or path to navigate after a successful organization selection.
* Accepts a function that returns URL or path
* @default undefined`
*/
afterSelectOrganizationUrl?:
| ((organization: OrganizationResource) => string)
| LooseExtractedParams<PrimitiveKeys<OrganizationResource>>;

/**
* Full URL or path to navigate after a successful selection of personal workspace.
* Accepts a function that returns URL or path
* @default undefined`
*/
afterSelectPersonalUrl?: ((user: UserResource) => string) | LooseExtractedParams<PrimitiveKeys<UserResource>>;
/**
* Full URL or path to navigate to after the user leaves the currently active organization.
* @default undefined
*/
afterLeaveOrganizationUrl?: string;
/**
* Controls whether clicking the "Manage organization" button will cause
* the OrganizationProfile component to open as a modal, or if the browser will navigate
* to the `organizationProfileUrl` where OrganizationProfile is mounted as a page.
* @default modal
*/
organizationProfileMode?: 'modal' | 'navigation';
/**
* Controls whether clicking the "Create organization" button will cause
* the CreateOrganization component to open as a modal, or if the browser will navigate
* to the `createOrganizationUrl` where CreateOrganization is mounted as a page.
* @default modal
*/
createOrganizationMode?: 'modal' | 'navigation';
/**
* Full URL or path where the <OrganizationProfile /> component is mounted.
* @default undefined
*/
organizationProfileUrl?: string;
/**
* Full URL or path where the <CreateOrganization /> component is mounted.
* @default undefined
*/
createOrganizationUrl?: string;
/**
* Customisation options to fully match the Clerk components to your own brand.
* These options serve as overrides and will be merged with the global `appearance`
* prop of ClerkProvided (if one is provided)
*/
appearance?: OrganizationSwitcherTheme;
/**
* Full URL or path to navigate after a successful selection of personal workspace.
* Accepts a function that returns URL or path
* @default undefined`
*/
afterSelectPersonalUrl?: ((user: UserResource) => string) | LooseExtractedParams<PrimitiveKeys<UserResource>>;
/**
* Full URL or path to navigate to after the user leaves the currently active organization.
* @default undefined
*/
afterLeaveOrganizationUrl?: string;
/**
* Customisation options to fully match the Clerk components to your own brand.
* These options serve as overrides and will be merged with the global `appearance`
* prop of ClerkProvided (if one is provided)
*/
appearance?: OrganizationSwitcherTheme;

/*
* Specify options for the underlying <OrganizationProfile /> component.
* e.g. <UserButton userProfileProps={{appearance: {...}}} />
*/
organizationProfileProps?: Pick<OrganizationProfileProps, 'appearance' | 'customPages'>;
};
/*
* Specify options for the underlying <OrganizationProfile /> component.
* e.g. <UserButton userProfileProps={{appearance: {...}}} />
*/
organizationProfileProps?: Pick<OrganizationProfileProps, 'appearance' | 'customPages'>;
};

export type OrganizationListProps = {
/**
Expand Down

0 comments on commit 8d4259c

Please sign in to comment.