Skip to content

Commit

Permalink
feat(clerk-js): Add sandbox support for persistent component props (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
dstaley authored Nov 20, 2024
1 parent a97a830 commit bf713bc
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .changeset/rude-lions-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
109 changes: 100 additions & 9 deletions packages/clerk-js/sandbox/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,99 @@

/** @typedef {import('@clerk/clerk-js').Clerk} Clerk */

/**
* @typedef {object} ComponentPropsControl
* @property {(props: unknown) => void} setProps
* @property {() => (any | null)} getProps
*/

const AVAILABLE_COMPONENTS = /** @type {const} */ ([
'signIn',
'signUp',
'userButton',
'userProfile',
'createOrganization',
'organizationList',
'organizationProfile',
'organizationSwitcher',
'waitlist',
]);

const COMPONENT_PROPS_NAMESPACE = 'clerk-js-sandbox';

const urlParams = new URL(window.location.href).searchParams;
for (const [component, encodedProps] of urlParams.entries()) {
if (AVAILABLE_COMPONENTS.includes(/** @type {typeof AVAILABLE_COMPONENTS[number]} */ (component))) {
localStorage.setItem(`${COMPONENT_PROPS_NAMESPACE}-${component}`, encodedProps);
}
}

/**
* @param {typeof AVAILABLE_COMPONENTS[number]} component
* @param {unknown} props
*/
function setComponentProps(component, props) {
const encodedProps = JSON.stringify(props);

const url = new URL(window.location.href);
url.searchParams.set(component, encodedProps);

window.location.href = url.toString();
}

/**
* @param {typeof AVAILABLE_COMPONENTS[number]} component
* @returns {unknown | null}
*/
function getComponentProps(component) {
const url = new URL(window.location.href);
const encodedProps = url.searchParams.get(component);
if (encodedProps) {
return JSON.parse(encodedProps);
}

const localEncodedProps = localStorage.getItem(`${COMPONENT_PROPS_NAMESPACE}-${component}`);
if (localEncodedProps) {
return JSON.parse(localEncodedProps);
}

return null;
}

/**
* @param {typeof AVAILABLE_COMPONENTS[number]} component
* @returns {ComponentPropsControl}
*/
function buildComponentControls(component) {
return {
setProps(props) {
setComponentProps(component, props);
},
getProps() {
return getComponentProps(component);
},
};
}

/**
* @type {Record<typeof AVAILABLE_COMPONENTS[number], ComponentPropsControl>}
*/
const componentControls = {
signIn: buildComponentControls('signIn'),
signUp: buildComponentControls('signUp'),
userButton: buildComponentControls('userButton'),
userProfile: buildComponentControls('userProfile'),
createOrganization: buildComponentControls('createOrganization'),
organizationList: buildComponentControls('organizationList'),
organizationProfile: buildComponentControls('organizationProfile'),
organizationSwitcher: buildComponentControls('organizationSwitcher'),
waitlist: buildComponentControls('waitlist'),
};

/**
* @typedef {object} CustomWindowObject
* @property {Clerk} [Clerk]
* @property {Record<typeof AVAILABLE_COMPONENTS[number], ComponentPropsControl>} [components]
*/

/**
Expand All @@ -13,6 +103,7 @@

/** @type {CustomWindow} */
const windowWithClerk = window;
windowWithClerk.components = componentControls;

const Clerk = /** @type {Clerk} **/ (windowWithClerk.Clerk);
if (!Clerk) {
Expand All @@ -36,31 +127,31 @@ const routes = {
mountIndex(app);
},
'/sign-in': () => {
Clerk.mountSignIn(app, {});
Clerk.mountSignIn(app, componentControls.signIn.getProps() ?? {});
},
'/sign-up': () => {
Clerk.mountSignUp(app, {});
Clerk.mountSignUp(app, componentControls.signUp.getProps() ?? {});
},
'/user-button': () => {
Clerk.mountUserButton(app, {});
Clerk.mountUserButton(app, componentControls.userButton.getProps() ?? {});
},
'/user-profile': () => {
Clerk.mountUserProfile(app, {});
Clerk.mountUserProfile(app, componentControls.userProfile.getProps() ?? {});
},
'/create-organization': () => {
Clerk.mountCreateOrganization(app, {});
Clerk.mountCreateOrganization(app, componentControls.createOrganization.getProps() ?? {});
},
'/organization-list': () => {
Clerk.mountOrganizationList(app, {});
Clerk.mountOrganizationList(app, componentControls.organizationList.getProps() ?? {});
},
'/organization-profile': () => {
Clerk.mountOrganizationProfile(app, {});
Clerk.mountOrganizationProfile(app, componentControls.organizationProfile.getProps() ?? {});
},
'/organization-switcher': () => {
Clerk.mountOrganizationSwitcher(app, {});
Clerk.mountOrganizationSwitcher(app, componentControls.organizationSwitcher.getProps() ?? {});
},
'/waitlist': () => {
Clerk.mountWaitlist(app, {});
Clerk.mountWaitlist(app, componentControls.waitlist.getProps() ?? {});
},
};

Expand Down

0 comments on commit bf713bc

Please sign in to comment.