Skip to content

Commit

Permalink
feat(clerk-js,clerk-react,types,nextjs): Expose OrganizationList to p… (
Browse files Browse the repository at this point in the history
#1692)

* feat(clerk-js,clerk-react,types,nextjs): Expose OrganizationList to packages

* chore(types): Update component names in jsdoc

* feat(clerk-js): Add OrganizationList to bundlewatch

* chore(types): Update organization list in jsdoc
  • Loading branch information
panteliselef authored Sep 8, 2023
1 parent a8eb435 commit e99df0a
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 4 deletions.
13 changes: 13 additions & 0 deletions .changeset/dirty-panthers-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@clerk/chrome-extension': minor
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/nextjs': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Introduce the new brand new component <OrganizationList />

- Lists all the memberships, invitations or suggestions an active user may have
- Powered by our `useOrganizationList` react hook
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ exports[`public exports should not include a breaking change 1`] = `
"CreateOrganization",
"MagicLinkErrorCode",
"MultisessionAppSupport",
"OrganizationList",
"OrganizationProfile",
"OrganizationSwitcher",
"RedirectToCreateOrganization",
Expand Down
1 change: 1 addition & 0 deletions packages/clerk-js/bundlewatch.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
{ "path": "./dist/impersonationfab*.js", "maxSize": "5KB" },
{ "path": "./dist/organizationprofile*.js", "maxSize": "10KB" },
{ "path": "./dist/organizationswitcher*.js", "maxSize": "5KB" },
{ "path": "./dist/organizationlist*.js", "maxSize": "5.5KB" },
{ "path": "./dist/signin*.js", "maxSize": "10KB" },
{ "path": "./dist/signup*.js", "maxSize": "10KB" },
{ "path": "./dist/userbutton*.js", "maxSize": "5KB" },
Expand Down
18 changes: 18 additions & 0 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
InstanceType,
ListenerCallback,
OrganizationInvitationResource,
OrganizationListProps,
OrganizationMembershipResource,
OrganizationProfileProps,
OrganizationResource,
Expand Down Expand Up @@ -506,6 +507,23 @@ export default class Clerk implements ClerkInterface {
void this.#componentControls?.ensureMounted().then(controls => controls.unmountComponent({ node }));
};

public mountOrganizationList = (node: HTMLDivElement, props?: OrganizationListProps) => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls?.ensureMounted({ preloadHint: 'OrganizationList' }).then(controls =>
controls.mountComponent({
name: 'OrganizationList',
appearanceKey: 'organizationList',
node,
props,
}),
);
};

public unmountOrganizationList = (node: HTMLDivElement): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls?.ensureMounted().then(controls => controls.unmountComponent({ node }));
};

public mountUserButton = (node: HTMLDivElement, props?: UserButtonProps) => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls?.ensureMounted({ preloadHint: 'UserButton' }).then(controls =>
Expand Down
6 changes: 6 additions & 0 deletions packages/clerk-js/src/ui/lazyModules/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const componentImportPaths = {
import(/* webpackChunkName: "organizationprofile" */ './../components/OrganizationProfile'),
OrganizationSwitcher: () =>
import(/* webpackChunkName: "organizationswitcher" */ './../components/OrganizationSwitcher'),
OrganizationList: () => import(/* webpackChunkName: "organizationlist" */ './../components/OrganizationList'),
ImpersonationFab: () => import(/* webpackChunkName: "impersonationfab" */ './../components/ImpersonationFab'),
} as const;

Expand Down Expand Up @@ -50,6 +51,10 @@ export const OrganizationSwitcher = lazy(() =>
componentImportPaths.OrganizationSwitcher().then(module => ({ default: module.OrganizationSwitcher })),
);

export const OrganizationList = lazy(() =>
componentImportPaths.OrganizationList().then(module => ({ default: module.OrganizationList })),
);

export const ImpersonationFab = lazy(() =>
componentImportPaths.ImpersonationFab().then(module => ({ default: module.ImpersonationFab })),
);
Expand All @@ -64,6 +69,7 @@ export const ClerkComponents = {
UserButton,
UserProfile,
OrganizationSwitcher,
OrganizationList,
OrganizationProfile,
CreateOrganization,
SignInModal,
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/src/client-boundary/uiComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export {
SignInButton,
SignUpButton,
SignOutButton,
OrganizationList,
} from '@clerk/clerk-react';

export const SignIn = (props: SignInProps) => {
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export {
CreateOrganization,
SignInButton,
SignOutButton,
OrganizationList,
} from './client-boundary/uiComponents';

/**
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export {
OrganizationSwitcher,
OrganizationProfile,
CreateOrganization,
OrganizationList,
} from './uiComponents';

export {
Expand Down
12 changes: 12 additions & 0 deletions packages/react/src/components/uiComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
CreateOrganizationProps,
OrganizationListProps,
OrganizationProfileProps,
OrganizationSwitcherProps,
SignInProps,
Expand Down Expand Up @@ -142,3 +143,14 @@ export const OrganizationSwitcher = withClerk(({ clerk, ...props }: WithClerkPro
/>
);
}, 'OrganizationSwitcher');

export const OrganizationList = withClerk(({ clerk, ...props }: WithClerkProp<OrganizationListProps>) => {
return (
<Portal
mount={clerk.mountOrganizationList}
unmount={clerk.unmountOrganizationList}
updateProps={(clerk as any).__unstable__updateProps}
props={props}
/>
);
}, 'OrganizationList');
22 changes: 22 additions & 0 deletions packages/react/src/isomorphicClerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
HandleMagicLinkVerificationParams,
HandleOAuthCallbackParams,
ListenerCallback,
OrganizationListProps,
OrganizationMembershipResource,
OrganizationResource,
RedirectOptions,
Expand Down Expand Up @@ -71,6 +72,7 @@ export default class IsomorphicClerk {
private premountOrganizationProfileNodes = new Map<HTMLDivElement, OrganizationProfileProps>();
private premountCreateOrganizationNodes = new Map<HTMLDivElement, CreateOrganizationProps>();
private premountOrganizationSwitcherNodes = new Map<HTMLDivElement, OrganizationSwitcherProps>();
private premountOrganizationListNodes = new Map<HTMLDivElement, OrganizationListProps>();
private premountMethodCalls = new Map<MethodName<BrowserClerk>, MethodCallback>();
private loadedListeners: Array<() => void> = [];

Expand Down Expand Up @@ -266,6 +268,10 @@ export default class IsomorphicClerk {
clerkjs.mountUserButton(node, props);
});

this.premountOrganizationListNodes.forEach((props: OrganizationListProps, node: HTMLDivElement) => {
clerkjs.mountOrganizationList(node, props);
});

this.#loaded = true;
this.emitLoaded();
return this.clerkjs;
Expand Down Expand Up @@ -528,6 +534,22 @@ export default class IsomorphicClerk {
}
};

mountOrganizationList = (node: HTMLDivElement, props: OrganizationListProps): void => {
if (this.clerkjs && this.#loaded) {
this.clerkjs.mountOrganizationList(node, props);
} else {
this.premountOrganizationListNodes.set(node, props);
}
};

unmountOrganizationList = (node: HTMLDivElement): void => {
if (this.clerkjs && this.#loaded) {
this.clerkjs.unmountOrganizationList(node);
} else {
this.premountOrganizationListNodes.delete(node);
}
};

mountUserButton = (node: HTMLDivElement, userButtonProps: UserButtonProps): void => {
if (this.clerkjs && this.#loaded) {
this.clerkjs.mountUserButton(node, userButtonProps);
Expand Down
21 changes: 17 additions & 4 deletions packages/types/src/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,14 @@ export interface Clerk {

/**
* Mount an organization profile component at the target element.
* @param targetNode Target to mount the UserProfile component.
* @param targetNode Target to mount the OrganizationProfile component.
* @param props Configuration parameters.
*/
mountOrganizationProfile: (targetNode: HTMLDivElement, props?: OrganizationProfileProps) => void;

/**
* Unmount the organization profile component from the target node.
* @param targetNode Target node to unmount the UserProfile component from.
* @param targetNode Target node to unmount the OrganizationProfile component from.
*/
unmountOrganizationProfile: (targetNode: HTMLDivElement) => void;

Expand All @@ -244,17 +244,30 @@ export interface Clerk {

/**
* Mount an organization switcher component at the target element.
* @param targetNode Target to mount the UserProfile component.
* @param targetNode Target to mount the OrganizationSwitcher component.
* @param props Configuration parameters.
*/
mountOrganizationSwitcher: (targetNode: HTMLDivElement, props?: OrganizationSwitcherProps) => void;

/**
* Unmount the organization profile component from the target node.*
* @param targetNode Target node to unmount the UserProfile component from.
* @param targetNode Target node to unmount the OrganizationSwitcher component from.
*/
unmountOrganizationSwitcher: (targetNode: HTMLDivElement) => void;

/**
* Mount an organization list component at the target element.
* @param targetNode Target to mount the OrganizationList component.
* @param props Configuration parameters.
*/
mountOrganizationList: (targetNode: HTMLDivElement, props?: OrganizationListProps) => void;

/**
* Unmount the organization list component from the target node.*
* @param targetNode Target node to unmount the OrganizationList component from.
*/
unmountOrganizationList: (targetNode: HTMLDivElement) => void;

/**
* Register a listener that triggers a callback each time important Clerk resources are changed.
* Allows to hook up at different steps in the sign up, sign in processes.
Expand Down

0 comments on commit e99df0a

Please sign in to comment.