Skip to content

Commit

Permalink
chore(vue,types): Add initial support for SFC files to improve runtim…
Browse files Browse the repository at this point in the history
…e prop checking (#4902)
  • Loading branch information
wobsoriano authored Jan 16, 2025
1 parent 8d8c2f3 commit 4af3538
Show file tree
Hide file tree
Showing 15 changed files with 540 additions and 344 deletions.
6 changes: 6 additions & 0 deletions .changeset/dry-pears-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@clerk/types': patch
'@clerk/vue': patch
---

Improve runtime prop checking for single-file components
2 changes: 1 addition & 1 deletion packages/types/src/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ export type SignInCombinedProps = RoutingOptions & {
LegacyRedirectProps &
AfterSignOutUrl;

interface TransferableOption {
export interface TransferableOption {
/**
* Indicates whether or not sign in attempts are transferable to the sign up flow.
* When set to false, prevents opaque sign ups when a user attempts to sign in via OAuth with an email that doesn't exist.
Expand Down
10 changes: 7 additions & 3 deletions packages/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@
"dist"
],
"scripts": {
"build": "tsup",
"build": "tsup --onSuccess \"pnpm build:dts\"",
"build:dts": "vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json",
"dev": "tsup --watch",
"lint": "eslint src/",
"lint:attw": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm",
"lint:attw": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm internal-resolution-error",
"lint:publint": "publint",
"publish:local": "pnpm yalc push --replace --sig",
"test": "vitest",
Expand All @@ -56,8 +57,11 @@
},
"devDependencies": {
"@testing-library/vue": "^8.1.0",
"@vitejs/plugin-vue": "^5.2.1",
"@vue.ts/tsx-auto-props": "^0.6.0",
"vue": "3.5.12"
"unplugin-vue": "^5.2.1",
"vue": "3.5.12",
"vue-tsc": "^2.0.24"
},
"peerDependencies": {
"vue": "^3.2.0"
Expand Down
54 changes: 0 additions & 54 deletions packages/vue/src/components/SignInButton.ts

This file was deleted.

48 changes: 48 additions & 0 deletions packages/vue/src/components/SignInButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { useAttrs, useSlots } from 'vue';
import type { SignInProps } from '@clerk/types';
import { useClerk } from '../composables/useClerk';
import { assertSingleChild, normalizeWithDefaultValue } from '../utils';
type SignInButtonProps = Pick<
SignInProps,
'fallbackRedirectUrl' | 'forceRedirectUrl' | 'signUpForceRedirectUrl' | 'signUpFallbackRedirectUrl' | 'initialValues'
> & {
mode?: 'modal' | 'redirect';
};
const props = defineProps<SignInButtonProps>();
const clerk = useClerk();
const slots = useSlots();
const attrs = useAttrs();
function getChildComponent() {
const children = normalizeWithDefaultValue(slots.default?.({}), 'Sign in');
return assertSingleChild(children, 'SignInButton');
}
function clickHandler() {
const { mode, ...opts } = props;
if (mode === 'modal') {
return clerk.value?.openSignIn(opts);
}
void clerk.value?.redirectToSignIn({
...opts,
signInFallbackRedirectUrl: props.fallbackRedirectUrl,
signInForceRedirectUrl: props.forceRedirectUrl,
});
}
</script>

<template>
<component
:is="getChildComponent"
v-bind="attrs"
@click="clickHandler"
>
<slot />
</component>
</template>
2 changes: 1 addition & 1 deletion packages/vue/src/components/__tests__/SignInButton.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/vue';
import { vi } from 'vitest';
import { defineComponent, h, ref } from 'vue';

import { SignInButton } from '../SignInButton';
import SignInButton from '../SignInButton.vue';

const mockRedirectToSignIn = vi.fn();
const originalError = console.error;
Expand Down
4 changes: 2 additions & 2 deletions packages/vue/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export {
SignUp,
SignIn,
UserProfile,
UserButton,
OrganizationSwitcher,
Expand All @@ -10,6 +9,7 @@ export {
GoogleOneTap,
Waitlist,
} from './uiComponents';
export { default as SignIn } from './ui-components/SignIn.vue';

export {
ClerkLoaded,
Expand All @@ -25,7 +25,7 @@ export {
RedirectToOrganizationProfile,
} from './controlComponents';

export { SignInButton } from './SignInButton';
export { default as SignInButton } from './SignInButton.vue';
export { SignUpButton } from './SignUpButton';
export { SignOutButton } from './SignOutButton';
export { SignInWithMetamaskButton } from './SignInWithMetamaskButton';
18 changes: 18 additions & 0 deletions packages/vue/src/components/ui-components/SignIn.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { Portal } from '../uiComponents';
import { useClerk } from '../../composables';
import type { SignInProps } from '@clerk/types';
const clerk = useClerk();
const props = defineProps<SignInProps>();
</script>

<template>
<Portal
:mount="clerk?.mountSignIn"
:unmount="clerk?.unmountSignIn"
:props="props"
:update-props="(clerk as any)?.__unstable__updateProps"
/>
</template>
15 changes: 1 addition & 14 deletions packages/vue/src/components/uiComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type {
OrganizationListProps,
OrganizationProfileProps,
OrganizationSwitcherProps,
SignInProps,
SignUpProps,
UserButtonProps,
UserProfileProps,
Expand Down Expand Up @@ -61,7 +60,7 @@ const CustomPortalsRenderer = defineComponent((props: CustomPortalsRendererProps
* The component only mounts when Clerk is fully loaded and automatically
* handles cleanup on unmount.
*/
const Portal = defineComponent((props: MountProps) => {
export const Portal = defineComponent((props: MountProps) => {
const portalRef = ref<HTMLDivElement | null>(null);
const isPortalMounted = ref(false);
// Make the props reactive so the watcher can react to changes
Expand Down Expand Up @@ -258,18 +257,6 @@ export const GoogleOneTap = defineComponent((props: GoogleOneTapProps) => {
});
});

export const SignIn = defineComponent((props: SignInProps) => {
const clerk = useClerk();

return () =>
h(Portal, {
mount: clerk.value?.mountSignIn,
unmount: clerk.value?.unmountSignIn,
updateProps: (clerk.value as any)?.__unstable__updateProps,
props,
});
});

export const SignUp = defineComponent((props: SignUpProps) => {
const clerk = useClerk();

Expand Down
6 changes: 6 additions & 0 deletions packages/vue/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare module '*.vue' {
import type { DefineComponent } from 'vue';

const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, any>;
export default component;
}
9 changes: 9 additions & 0 deletions packages/vue/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": true,
"declarationDir": "./dist"
},
"include": ["src/**/*.ts", "src/**/*.vue"],
"exclude": ["src/**/*.test.ts"]
}
1 change: 0 additions & 1 deletion packages/vue/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"strict": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noEmit": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": false,
"skipLibCheck": true
Expand Down
5 changes: 4 additions & 1 deletion packages/vue/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import autoPropsPlugin from '@vue.ts/tsx-auto-props/esbuild';
import { defineConfig, type Options } from 'tsup';
import vuePlugin from 'unplugin-vue/esbuild';

import { name, version } from './package.json';

Expand All @@ -13,8 +14,10 @@ export default defineConfig(() => {
bundle: true,
sourcemap: true,
minify: false,
dts: true,
dts: false,
esbuildPlugins: [
// Adds .vue files support
vuePlugin() as EsbuildPlugin,
// Automatically generates runtime props from TypeScript types/interfaces for all
// control and UI components, adding them to Vue components during build via
// Object.defineProperty
Expand Down
2 changes: 2 additions & 0 deletions packages/vue/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
},
plugins: [vue()],
});
Loading

0 comments on commit 4af3538

Please sign in to comment.