Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
234ce35
wip
panteliselef Jun 17, 2025
2041111
wip 2
panteliselef Jun 17, 2025
e7a3f26
create the layout and functionality
panteliselef Jun 18, 2025
7af1561
display button for annual to switch to monthly as well
panteliselef Jun 18, 2025
a64ed1d
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jun 30, 2025
99607d7
implement new UI
panteliselef Jul 1, 2025
0af7fb9
add unit tests
panteliselef Jul 1, 2025
a2303b6
address issue with animation
panteliselef Jul 1, 2025
e0f8e1a
add more test cases
panteliselef Jul 1, 2025
1b75fe1
use box shadow instead of border
panteliselef Jul 1, 2025
a8db78f
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 1, 2025
3a0907c
remove unnecessary context
panteliselef Jul 1, 2025
1ddd06b
handle missing avatar url
panteliselef Jul 1, 2025
d84f755
add descriptors
panteliselef Jul 1, 2025
99f4342
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 2, 2025
aaf814c
add more descriptors
panteliselef Jul 2, 2025
55f1ba3
handle localizations
panteliselef Jul 2, 2025
962e8d5
fix issues from conflicts
panteliselef Jul 2, 2025
84528d0
finishing touches on subscription details
panteliselef Jul 2, 2025
dc926ab
add unit tests for PlanDetails
panteliselef Jul 2, 2025
79b3c79
remove old file
panteliselef Jul 2, 2025
958fdd9
replace experimental with internal apis
panteliselef Jul 2, 2025
c5dafc4
Update packages/types/src/clerk.ts
panteliselef Jul 2, 2025
bd9984f
address pr comments
panteliselef Jul 10, 2025
587f2b8
wip
panteliselef Jul 10, 2025
af6a28b
Revert "wip"
panteliselef Jul 13, 2025
1c161cc
address pr feedback
panteliselef Jul 13, 2025
0ed99f1
bump
panteliselef Jul 13, 2025
39100a9
wip subscription items
panteliselef Jul 13, 2025
7db88a9
Revert "wip subscription items"
panteliselef Jul 13, 2025
257a3cc
wip changeset
panteliselef Jul 13, 2025
3753dee
bundlewatch.config.json
panteliselef Jul 13, 2025
477d3f5
Merge branch 'refs/heads/main' into elef/com-835-split-up-plandetails…
panteliselef Jul 14, 2025
28d86b4
fix lint
panteliselef Jul 14, 2025
38fa5f6
fix build issue
panteliselef Jul 14, 2025
6a08920
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
5421403
patch tests
panteliselef Jul 14, 2025
9c5beac
fix changeset
panteliselef Jul 14, 2025
e0a74b6
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
6f01802
Merge branch 'main' into elef/com-835-split-up-plandetails-and-subscr…
panteliselef Jul 14, 2025
86de684
use line items
panteliselef Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/tangy-toes-dress.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
---
'@clerk/localizations': minor
'@clerk/clerk-js': minor
'@clerk/clerk-react': minor
'@clerk/types': minor
---

Extract `SubscriptionDetails`, into its own internal component, out of existing (also internal) `PlanDetails` component.
6 changes: 3 additions & 3 deletions packages/clerk-js/bundlewatch.config.json
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "614kB" },
{ "path": "./dist/clerk.js", "maxSize": "616kB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "72.2KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "110KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "113.72KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "111KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "115KB" },
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
Expand Down
17 changes: 16 additions & 1 deletion packages/clerk-js/src/core/clerk.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ import type {
__internal_ComponentNavigationContext,
__internal_OAuthConsentProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationModalProps,
APIKeysNamespace,
APIKeysProps,
Expand DownExpand Up@@ -602,7 +603,7 @@ export class Clerk implements ClerkInterface {
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('checkout'));
};

public __internal_openPlanDetails = (props?: __internal_PlanDetailsProps): void => {
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
if (disabledBillingFeature(this, this.environment)) {
if (this.#instanceType === 'development') {
Expand All@@ -615,13 +616,27 @@ export class Clerk implements ClerkInterface {
void this.#componentControls
.ensureMounted({ preloadHint: 'PlanDetails' })
.then(controls => controls.openDrawer('planDetails', props || {}));

this.telemetry?.record(eventPrebuiltComponentOpened(`PlanDetails`, props));
};

public __internal_closePlanDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('planDetails'));
};

public __internal_openSubscriptionDetails = (props?: __internal_SubscriptionDetailsProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
.ensureMounted({ preloadHint: 'SubscriptionDetails' })
.then(controls => controls.openDrawer('subscriptionDetails', props || {}));
};

public __internal_closeSubscriptionDetails = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeDrawer('subscriptionDetails'));
};

public __internal_openReverification = (props?: __internal_UserVerificationModalProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this)) {
Expand Down
26 changes: 22 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { createDeferredPromise } from '@clerk/shared/utils';
import type {
__internal_CheckoutProps,
__internal_PlanDetailsProps,
__internal_SubscriptionDetailsProps,
__internal_UserVerificationProps,
Appearance,
Clerk,
Expand DownExpand Up@@ -36,7 +37,7 @@ import {
UserVerificationModal,
WaitlistModal,
} from './lazyModules/components';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer } from './lazyModules/drawers';
import { MountedCheckoutDrawer, MountedPlanDetailDrawer, MountedSubscriptionDetailDrawer } from './lazyModules/drawers';
import {
LazyComponentRenderer,
LazyImpersonationFabProvider,
Expand DownExpand Up@@ -106,16 +107,18 @@ export type ComponentControls = {
notify?: boolean;
},
) => void;
openDrawer: <T extends 'checkout' | 'planDetails'>(
openDrawer: <T extends 'checkout' | 'planDetails' | 'subscriptionDetails'>(
drawer: T,
props: T extends 'checkout'
? __internal_CheckoutProps
: T extends 'planDetails'
? __internal_PlanDetailsProps
: never,
: T extends 'subscriptionDetails'
? __internal_SubscriptionDetailsProps
: never,
) => void;
closeDrawer: (
drawer: 'checkout' | 'planDetails',
drawer: 'checkout' | 'planDetails' | 'subscriptionDetails',
options?: {
notify?: boolean;
},
Expand DownExpand Up@@ -160,6 +163,10 @@ interface ComponentsState {
open: false;
props: null | __internal_PlanDetailsProps;
};
subscriptionDetailsDrawer: {
open: false;
props: null | __internal_SubscriptionDetailsProps;
};
nodes: Map<HTMLDivElement, HtmlNodeOptions>;
impersonationFab: boolean;
}
Expand DownExpand Up@@ -249,6 +256,10 @@ const Components = (props: ComponentsProps) => {
open: false,
props: null,
},
subscriptionDetailsDrawer: {
open: false,
props: null,
},
nodes: new Map(),
impersonationFab: false,
});
Expand All@@ -265,6 +276,7 @@ const Components = (props: ComponentsProps) => {
blankCaptchaModal,
checkoutDrawer,
planDetailsDrawer,
subscriptionDetailsDrawer,
nodes,
} = state;

Expand DownExpand Up@@ -588,6 +600,12 @@ const Components = (props: ComponentsProps) => {
onOpenChange={() => componentsControls.closeDrawer('planDetails')}
/>

<MountedSubscriptionDetailDrawer
appearance={state.appearance}
subscriptionDetailsDrawer={subscriptionDetailsDrawer}
onOpenChange={() => componentsControls.closeDrawer('subscriptionDetails')}
/>

{state.impersonationFab && (
<LazyImpersonationFabProvider globalAppearance={state.appearance}>
<ImpersonationFab />
Expand Down
Loading