diff --git a/.changeset/cold-parks-push.md b/.changeset/cold-parks-push.md
new file mode 100644
index 00000000000..469a530e50f
--- /dev/null
+++ b/.changeset/cold-parks-push.md
@@ -0,0 +1,5 @@
+---
+'@clerk/vue': minor
+---
+
+Expose billing buttons as experimental
diff --git a/integration/templates/vue-vite/src/router.ts b/integration/templates/vue-vite/src/router.ts
index c598b2b0bff..31fc822e18e 100644
--- a/integration/templates/vue-vite/src/router.ts
+++ b/integration/templates/vue-vite/src/router.ts
@@ -47,6 +47,22 @@ const routes = [
path: '/user',
component: () => import('./views/Profile.vue'),
},
+ // Billing button routes
+ {
+ name: 'CheckoutBtn',
+ path: '/billing/checkout-btn',
+ component: () => import('./views/billing/CheckoutBtn.vue'),
+ },
+ {
+ name: 'PlanDetailsBtn',
+ path: '/billing/plan-details-btn',
+ component: () => import('./views/billing/PlanDetailsBtn.vue'),
+ },
+ {
+ name: 'SubscriptionDetailsBtn',
+ path: '/billing/subscription-details-btn',
+ component: () => import('./views/billing/SubscriptionDetailsBtn.vue'),
+ },
];
const router = createRouter({
diff --git a/integration/templates/vue-vite/src/views/billing/CheckoutBtn.vue b/integration/templates/vue-vite/src/views/billing/CheckoutBtn.vue
new file mode 100644
index 00000000000..39c23365733
--- /dev/null
+++ b/integration/templates/vue-vite/src/views/billing/CheckoutBtn.vue
@@ -0,0 +1,17 @@
+
+
+
+
+ Checkout Now
+
+
+
+
+
+
diff --git a/integration/templates/vue-vite/src/views/billing/PlanDetailsBtn.vue b/integration/templates/vue-vite/src/views/billing/PlanDetailsBtn.vue
new file mode 100644
index 00000000000..cc51a1035bc
--- /dev/null
+++ b/integration/templates/vue-vite/src/views/billing/PlanDetailsBtn.vue
@@ -0,0 +1,9 @@
+
+
+ Plan details
+
+
+
+
diff --git a/integration/templates/vue-vite/src/views/billing/SubscriptionDetailsBtn.vue b/integration/templates/vue-vite/src/views/billing/SubscriptionDetailsBtn.vue
new file mode 100644
index 00000000000..5ff010ab10c
--- /dev/null
+++ b/integration/templates/vue-vite/src/views/billing/SubscriptionDetailsBtn.vue
@@ -0,0 +1,9 @@
+
+
+ Subscription details
+
+
+
+
diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts
index 22b845f3deb..c8e25fdb64c 100644
--- a/integration/tests/pricing-table.test.ts
+++ b/integration/tests/pricing-table.test.ts
@@ -32,9 +32,8 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
});
test('renders pricing details of a specific plan', async ({ page, context }) => {
- if (!app.name.includes('next')) {
- return;
- }
+ test.skip(app.name.includes('astro'), 'Still working on it');
+
const u = createTestUtils({ app, page, context });
await u.po.page.goToRelative('/billing/plan-details-btn');
@@ -83,9 +82,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
page,
context,
}) => {
- if (!app.name.includes('next')) {
- return;
- }
+ test.skip(app.name.includes('astro'), 'Still working on it');
const u = createTestUtils({ app, page, context });
await u.po.signIn.goTo();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
@@ -100,9 +97,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
});
test('when signed in, clicking checkout button open checkout drawer', async ({ page, context }) => {
- if (!app.name.includes('next')) {
- return;
- }
+ test.skip(app.name.includes('astro'), 'Still working on it');
const u = createTestUtils({ app, page, context });
await u.po.signIn.goTo();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
@@ -137,9 +132,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
});
test('opens subscription details drawer', async ({ page, context }) => {
- if (!app.name.includes('next')) {
- return;
- }
+ test.skip(app.name.includes('astro'), 'Still working on it');
const u = createTestUtils({ app, page, context });
await u.po.signIn.goTo();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
diff --git a/packages/vue/package.json b/packages/vue/package.json
index 7409c069246..05295f89542 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -30,6 +30,10 @@
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
+ "./experimental": {
+ "types": "./dist/experimental.d.ts",
+ "default": "./dist/experimental.js"
+ },
"./internal": {
"types": "./dist/internal.d.ts",
"default": "./dist/internal.js"
diff --git a/packages/vue/src/components/CheckoutButton.vue b/packages/vue/src/components/CheckoutButton.vue
new file mode 100644
index 00000000000..c056d943c4e
--- /dev/null
+++ b/packages/vue/src/components/CheckoutButton.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
diff --git a/packages/vue/src/components/PlanDetailsButton.vue b/packages/vue/src/components/PlanDetailsButton.vue
new file mode 100644
index 00000000000..ba094c41412
--- /dev/null
+++ b/packages/vue/src/components/PlanDetailsButton.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/packages/vue/src/components/SubscriptionDetailsButton.vue b/packages/vue/src/components/SubscriptionDetailsButton.vue
new file mode 100644
index 00000000000..5dec21240ac
--- /dev/null
+++ b/packages/vue/src/components/SubscriptionDetailsButton.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
diff --git a/packages/vue/src/experimental.ts b/packages/vue/src/experimental.ts
new file mode 100644
index 00000000000..18816459452
--- /dev/null
+++ b/packages/vue/src/experimental.ts
@@ -0,0 +1,41 @@
+/**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+export { default as SubscriptionDetailsButton } from './components/SubscriptionDetailsButton.vue';
+
+/**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+export { default as CheckoutButton } from './components/CheckoutButton.vue';
+
+/**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+export { default as PlanDetailsButton } from './components/PlanDetailsButton.vue';
+
+export type {
+ /**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+ __experimental_SubscriptionDetailsButtonProps as SubscriptionDetailsButtonProps,
+ /**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+ __experimental_CheckoutButtonProps as CheckoutButtonProps,
+ /**
+ * @experimental
+ * These components and their prop types are unstable and may change in future releases.
+ * They are part of Clerk's Billing feature which is available under public beta.
+ */
+ __experimental_PlanDetailsButtonProps as PlanDetailsButtonProps,
+} from '@clerk/types';
diff --git a/packages/vue/src/utils/childrenUtils.ts b/packages/vue/src/utils/childrenUtils.ts
index 55b76b61c14..9cacf87b0db 100644
--- a/packages/vue/src/utils/childrenUtils.ts
+++ b/packages/vue/src/utils/childrenUtils.ts
@@ -3,7 +3,14 @@ import { h, Text, type VNode } from 'vue';
import { errorThrower } from '../errors/errorThrower';
import { multipleChildrenInButtonComponent } from '../errors/messages';
-type ButtonName = 'SignInButton' | 'SignUpButton' | 'SignOutButton' | 'SignInWithMetamaskButton';
+type ButtonName =
+ | 'SignInButton'
+ | 'SignUpButton'
+ | 'SignOutButton'
+ | 'SignInWithMetamaskButton'
+ | 'SubscriptionDetailsButton'
+ | 'CheckoutButton'
+ | 'PlanDetailsButton';
export const normalizeWithDefaultValue = (slotContent: VNode[] | undefined, defaultValue: string) => {
// Render a button with the default value if no slot content is provided
diff --git a/packages/vue/tsup.config.ts b/packages/vue/tsup.config.ts
index c5c1a246a46..fe7ddaac46c 100644
--- a/packages/vue/tsup.config.ts
+++ b/packages/vue/tsup.config.ts
@@ -9,7 +9,7 @@ type EsbuildPlugin = NonNullable[number];
export default defineConfig(() => {
return {
clean: true,
- entry: ['./src/index.ts', './src/internal.ts', './src/errors.ts'],
+ entry: ['./src/index.ts', './src/experimental.ts', './src/internal.ts', './src/errors.ts'],
format: ['esm'],
bundle: true,
sourcemap: true,
@@ -17,13 +17,13 @@ export default defineConfig(() => {
dts: false,
esbuildPlugins: [
// Adds .vue files support
- vuePlugin() as EsbuildPlugin,
+ vuePlugin(),
// Automatically generates runtime props from TypeScript types/interfaces for all
// control and UI components, adding them to Vue components during build via
// Object.defineProperty
autoPropsPlugin({
include: ['**/*.ts'],
- }) as EsbuildPlugin,
+ }),
],
define: {
PACKAGE_NAME: `"${name}"`,