-
Notifications
You must be signed in to change notification settings - Fork 282
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(clerk-js): Render
@clerk/ui
(#4114)
Co-authored-by: Alex Carpenter <[email protected]> Co-authored-by: Dylan Staley <[email protected]> Co-authored-by: Nikos Douvlis <[email protected]> Co-authored-by: panteliselef <[email protected]> Co-authored-by: Jacek Radko <[email protected]>
- Loading branch information
1 parent
45f3ae5
commit 3b50b67
Showing
45 changed files
with
606 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@clerk/elements": patch | ||
--- | ||
|
||
Remove @clerk/clerk-react as a dev depedency. Move @clerk/shared to depedencies (previously devDepedencies). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
"@clerk/clerk-js": minor | ||
"@clerk/elements": minor | ||
"@clerk/nextjs": minor | ||
"@clerk/shared": minor | ||
"@clerk/types": minor | ||
--- | ||
|
||
Add experimental support for new UI components |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@clerk/types": patch | ||
--- | ||
|
||
Fix `SignInProps`/`SignUpProps` `__experimental` type to allow for arbitrary properties |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
declare module '@clerk/ui/styles.css' { | ||
const content: string; | ||
export default content; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { createDeferredPromise } from '@clerk/shared'; | ||
import type { ClerkHostRouter } from '@clerk/shared/router'; | ||
import type { ClerkOptions, LoadedClerk } from '@clerk/types'; | ||
|
||
import type { init } from './renderer'; | ||
import type { ClerkNewComponents, ComponentDefinition } from './types'; | ||
|
||
function assertRouter(router: ClerkHostRouter | undefined): asserts router is ClerkHostRouter { | ||
if (!router) { | ||
throw new Error(`Clerk: Attempted to use functionality that requires the "router" option to be provided to Clerk.`); | ||
} | ||
} | ||
|
||
export class UI { | ||
router?: ClerkHostRouter; | ||
clerk: LoadedClerk; | ||
options: ClerkOptions; | ||
componentRegistry = new Map<string, ComponentDefinition>(); | ||
|
||
#rendererPromise?: ReturnType<typeof createDeferredPromise>; | ||
#renderer?: ReturnType<typeof init>; | ||
|
||
constructor({ | ||
router, | ||
clerk, | ||
options, | ||
}: { | ||
router: ClerkHostRouter | undefined; | ||
clerk: LoadedClerk; | ||
options: ClerkOptions; | ||
}) { | ||
this.router = router; | ||
this.clerk = clerk; | ||
this.options = options; | ||
|
||
// register components | ||
this.register('SignIn', { | ||
type: 'component', | ||
load: () => | ||
import(/* webpackChunkName: "rebuild--sign-in" */ '@clerk/ui/sign-in').then(({ SignIn }) => ({ | ||
default: SignIn, | ||
})), | ||
}); | ||
this.register('SignUp', { | ||
type: 'component', | ||
load: () => | ||
import(/* webpackChunkName: "rebuild--sign-up" */ '@clerk/ui/sign-up').then(({ SignUp }) => ({ | ||
default: SignUp, | ||
})), | ||
}); | ||
} | ||
|
||
// Mount a component from the registry | ||
mount<C extends keyof ClerkNewComponents>(componentName: C, node: HTMLElement, props: ClerkNewComponents[C]): void { | ||
const component = this.componentRegistry.get(componentName); | ||
if (!component) { | ||
throw new Error(`clerk/ui: Unable to find component definition for ${componentName}`); | ||
} | ||
|
||
// immediately start loading the component | ||
component.load(); | ||
|
||
this.renderer() | ||
.then(() => { | ||
this.#renderer?.mount(this.#renderer.createElementFromComponentDefinition(component), props, node); | ||
}) | ||
.catch(err => { | ||
console.error(`clerk/ui: Error mounting component ${componentName}:`, err); | ||
}); | ||
} | ||
|
||
unmount(node: HTMLElement) { | ||
this.#renderer?.unmount(node); | ||
} | ||
|
||
// Registers a component for rendering later | ||
register(componentName: string, componentDefinition: ComponentDefinition) { | ||
this.componentRegistry.set(componentName, componentDefinition); | ||
} | ||
|
||
renderer() { | ||
if (this.#rendererPromise) { | ||
return this.#rendererPromise.promise; | ||
} | ||
|
||
this.#rendererPromise = createDeferredPromise(); | ||
|
||
import('./renderer').then(({ init, wrapperInit }) => { | ||
assertRouter(this.router); | ||
this.#renderer = init({ | ||
wrapper: wrapperInit({ clerk: this.clerk, options: this.options, router: this.router }), | ||
}); | ||
this.#rendererPromise?.resolve(); | ||
}); | ||
|
||
return this.#rendererPromise.promise; | ||
} | ||
} |
Oops, something went wrong.