@drmhse/authos-vue 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -398,7 +398,40 @@ export default defineEventHandler(async (event) => {
398
398
 
399
399
  ## Styling
400
400
 
401
- All components use data attributes for styling hooks:
401
+ AuthOS components come with **polished default styling** out of the box, similar to best-in-class auth providers. The styling is fully customizable via the `appearance` option or by overriding CSS variables.
402
+
403
+ ### Customization
404
+
405
+ You can customize the theme colors, fonts, and more by passing an `appearance` object to `createAuthOS`.
406
+
407
+ ```ts
408
+ app.use(createAuthOS({
409
+ // ... other options
410
+ appearance: {
411
+ variables: {
412
+ colorPrimary: '#0066cc',
413
+ colorBackground: '#f5f5f5',
414
+ borderRadius: '0.25rem',
415
+ fontFamily: 'Inter, sans-serif',
416
+ },
417
+ },
418
+ }));
419
+ ```
420
+
421
+ ### CSS Variables
422
+
423
+ You can also override these CSS variables in your own stylesheet:
424
+
425
+ ```css
426
+ :root {
427
+ --authos-color-primary: #0066cc;
428
+ --authos-border-radius: 4px;
429
+ }
430
+ ```
431
+
432
+ ### Headless Styling
433
+
434
+ If you prefer to completely style the components yourself, you can target the data attributes. The default styles have low specificity, so your CSS classes will easily override them.
402
435
 
403
436
  ```css
404
437
  [data-authos-signin] { /* Container */ }
@@ -409,6 +442,8 @@ All components use data attributes for styling hooks:
409
442
  [data-authos-oauth] { /* OAuth button */ }
410
443
  [data-authos-oauth][data-provider="github"] { /* GitHub button */ }
411
444
  [data-authos-divider] { /* "or" divider */ }
445
+ [data-authos-magic-link] { /* Magic Link container */ }
446
+ [data-authos-passkey] { /* Passkey container */ }
412
447
  ```
413
448
 
414
449
  ## Migration from v1
package/dist/index.d.mts CHANGED
@@ -158,7 +158,7 @@ declare const AUTH_OS_INJECTION_KEY: unique symbol;
158
158
  /**
159
159
  * Supported OAuth providers
160
160
  */
161
- type SupportedOAuthProvider = 'github' | 'google' | 'microsoft';
161
+ type SupportedOAuthProvider$1 = 'github' | 'google' | 'microsoft';
162
162
 
163
163
  declare function createAuthOS(options: AuthOSPluginOptions): {
164
164
  install(app: App): void;
@@ -383,6 +383,7 @@ declare const SignIn: vue.DefineComponent<vue.ExtractPropTypes<{
383
383
  onError: (error: Error) => void;
384
384
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
385
385
 
386
+ type SupportedOAuthProvider = 'github' | 'google' | 'microsoft';
386
387
  interface SignUpSlotProps {
387
388
  email: string;
388
389
  password: string;
@@ -411,6 +412,21 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
411
412
  type: StringConstructor;
412
413
  default: undefined;
413
414
  };
415
+ /** List of OAuth providers to display buttons for */
416
+ providers: {
417
+ type: PropType<SupportedOAuthProvider[] | false>;
418
+ default: boolean;
419
+ };
420
+ /** Show divider between OAuth and email form */
421
+ showDivider: {
422
+ type: BooleanConstructor;
423
+ default: boolean;
424
+ };
425
+ /** Show sign in link */
426
+ showSignIn: {
427
+ type: BooleanConstructor;
428
+ default: boolean;
429
+ };
414
430
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
415
431
  [key: string]: any;
416
432
  }> | vue.VNode<vue.RendererNode, vue.RendererElement, {
@@ -434,6 +450,21 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
434
450
  type: StringConstructor;
435
451
  default: undefined;
436
452
  };
453
+ /** List of OAuth providers to display buttons for */
454
+ providers: {
455
+ type: PropType<SupportedOAuthProvider[] | false>;
456
+ default: boolean;
457
+ };
458
+ /** Show divider between OAuth and email form */
459
+ showDivider: {
460
+ type: BooleanConstructor;
461
+ default: boolean;
462
+ };
463
+ /** Show sign in link */
464
+ showSignIn: {
465
+ type: BooleanConstructor;
466
+ default: boolean;
467
+ };
437
468
  }>> & Readonly<{
438
469
  onSuccess?: ((...args: any[]) => any) | undefined;
439
470
  onError?: ((...args: any[]) => any) | undefined;
@@ -442,6 +473,9 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
442
473
  onError: (error: Error) => void;
443
474
  orgSlug: string;
444
475
  serviceSlug: string;
476
+ providers: false | SupportedOAuthProvider[];
477
+ showDivider: boolean;
478
+ showSignIn: boolean;
445
479
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
446
480
 
447
481
  interface OrganizationSwitcherSlotProps {
@@ -542,7 +576,7 @@ declare const Protect: vue.DefineComponent<vue.ExtractPropTypes<{
542
576
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
543
577
 
544
578
  interface OAuthButtonSlotProps {
545
- provider: SupportedOAuthProvider;
579
+ provider: SupportedOAuthProvider$1;
546
580
  providerName: string;
547
581
  isConfigured: boolean;
548
582
  disabled: boolean;
@@ -568,7 +602,7 @@ interface OAuthButtonSlotProps {
568
602
  */
569
603
  declare const OAuthButton: vue.DefineComponent<vue.ExtractPropTypes<{
570
604
  provider: {
571
- type: PropType<SupportedOAuthProvider>;
605
+ type: PropType<SupportedOAuthProvider$1>;
572
606
  required: true;
573
607
  };
574
608
  disabled: {
@@ -581,7 +615,7 @@ declare const OAuthButton: vue.DefineComponent<vue.ExtractPropTypes<{
581
615
  [key: string]: any;
582
616
  }>[], {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, "redirect"[], "redirect", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
583
617
  provider: {
584
- type: PropType<SupportedOAuthProvider>;
618
+ type: PropType<SupportedOAuthProvider$1>;
585
619
  required: true;
586
620
  };
587
621
  disabled: {
@@ -721,4 +755,4 @@ declare const PasskeySignIn: vue.DefineComponent<vue.ExtractPropTypes<{
721
755
  showPasswordSignIn: boolean;
722
756
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
723
757
 
724
- export { AUTH_OS_INJECTION_KEY, type AppearanceOptions, type AppearanceVariables, type AuthOSContext, type AuthOSPluginOptions, AuthOSProvider, type AuthOSState, MagicLinkSignIn, OAuthButton, type OAuthButtonSlotProps, OrganizationSwitcher, type OrganizationSwitcherSlotProps, PasskeySignIn, Protect, SignIn, type SignInSlotProps, SignUp, type SignUpSlotProps, SignedIn, SignedOut, type SupportedOAuthProvider, UserButton, type UserButtonSlotProps, createAuthOS, useAllPermissions, useAnyPermission, useAuthOS, useOrganization, usePermission, useUser };
758
+ export { AUTH_OS_INJECTION_KEY, type AppearanceOptions, type AppearanceVariables, type AuthOSContext, type AuthOSPluginOptions, AuthOSProvider, type AuthOSState, MagicLinkSignIn, OAuthButton, type OAuthButtonSlotProps, OrganizationSwitcher, type OrganizationSwitcherSlotProps, PasskeySignIn, Protect, SignIn, type SignInSlotProps, SignUp, type SignUpSlotProps, SignedIn, SignedOut, type SupportedOAuthProvider$1 as SupportedOAuthProvider, UserButton, type UserButtonSlotProps, createAuthOS, useAllPermissions, useAnyPermission, useAuthOS, useOrganization, usePermission, useUser };
package/dist/index.d.ts CHANGED
@@ -158,7 +158,7 @@ declare const AUTH_OS_INJECTION_KEY: unique symbol;
158
158
  /**
159
159
  * Supported OAuth providers
160
160
  */
161
- type SupportedOAuthProvider = 'github' | 'google' | 'microsoft';
161
+ type SupportedOAuthProvider$1 = 'github' | 'google' | 'microsoft';
162
162
 
163
163
  declare function createAuthOS(options: AuthOSPluginOptions): {
164
164
  install(app: App): void;
@@ -383,6 +383,7 @@ declare const SignIn: vue.DefineComponent<vue.ExtractPropTypes<{
383
383
  onError: (error: Error) => void;
384
384
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
385
385
 
386
+ type SupportedOAuthProvider = 'github' | 'google' | 'microsoft';
386
387
  interface SignUpSlotProps {
387
388
  email: string;
388
389
  password: string;
@@ -411,6 +412,21 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
411
412
  type: StringConstructor;
412
413
  default: undefined;
413
414
  };
415
+ /** List of OAuth providers to display buttons for */
416
+ providers: {
417
+ type: PropType<SupportedOAuthProvider[] | false>;
418
+ default: boolean;
419
+ };
420
+ /** Show divider between OAuth and email form */
421
+ showDivider: {
422
+ type: BooleanConstructor;
423
+ default: boolean;
424
+ };
425
+ /** Show sign in link */
426
+ showSignIn: {
427
+ type: BooleanConstructor;
428
+ default: boolean;
429
+ };
414
430
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
415
431
  [key: string]: any;
416
432
  }> | vue.VNode<vue.RendererNode, vue.RendererElement, {
@@ -434,6 +450,21 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
434
450
  type: StringConstructor;
435
451
  default: undefined;
436
452
  };
453
+ /** List of OAuth providers to display buttons for */
454
+ providers: {
455
+ type: PropType<SupportedOAuthProvider[] | false>;
456
+ default: boolean;
457
+ };
458
+ /** Show divider between OAuth and email form */
459
+ showDivider: {
460
+ type: BooleanConstructor;
461
+ default: boolean;
462
+ };
463
+ /** Show sign in link */
464
+ showSignIn: {
465
+ type: BooleanConstructor;
466
+ default: boolean;
467
+ };
437
468
  }>> & Readonly<{
438
469
  onSuccess?: ((...args: any[]) => any) | undefined;
439
470
  onError?: ((...args: any[]) => any) | undefined;
@@ -442,6 +473,9 @@ declare const SignUp: vue.DefineComponent<vue.ExtractPropTypes<{
442
473
  onError: (error: Error) => void;
443
474
  orgSlug: string;
444
475
  serviceSlug: string;
476
+ providers: false | SupportedOAuthProvider[];
477
+ showDivider: boolean;
478
+ showSignIn: boolean;
445
479
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
446
480
 
447
481
  interface OrganizationSwitcherSlotProps {
@@ -542,7 +576,7 @@ declare const Protect: vue.DefineComponent<vue.ExtractPropTypes<{
542
576
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
543
577
 
544
578
  interface OAuthButtonSlotProps {
545
- provider: SupportedOAuthProvider;
579
+ provider: SupportedOAuthProvider$1;
546
580
  providerName: string;
547
581
  isConfigured: boolean;
548
582
  disabled: boolean;
@@ -568,7 +602,7 @@ interface OAuthButtonSlotProps {
568
602
  */
569
603
  declare const OAuthButton: vue.DefineComponent<vue.ExtractPropTypes<{
570
604
  provider: {
571
- type: PropType<SupportedOAuthProvider>;
605
+ type: PropType<SupportedOAuthProvider$1>;
572
606
  required: true;
573
607
  };
574
608
  disabled: {
@@ -581,7 +615,7 @@ declare const OAuthButton: vue.DefineComponent<vue.ExtractPropTypes<{
581
615
  [key: string]: any;
582
616
  }>[], {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, "redirect"[], "redirect", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
583
617
  provider: {
584
- type: PropType<SupportedOAuthProvider>;
618
+ type: PropType<SupportedOAuthProvider$1>;
585
619
  required: true;
586
620
  };
587
621
  disabled: {
@@ -721,4 +755,4 @@ declare const PasskeySignIn: vue.DefineComponent<vue.ExtractPropTypes<{
721
755
  showPasswordSignIn: boolean;
722
756
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
723
757
 
724
- export { AUTH_OS_INJECTION_KEY, type AppearanceOptions, type AppearanceVariables, type AuthOSContext, type AuthOSPluginOptions, AuthOSProvider, type AuthOSState, MagicLinkSignIn, OAuthButton, type OAuthButtonSlotProps, OrganizationSwitcher, type OrganizationSwitcherSlotProps, PasskeySignIn, Protect, SignIn, type SignInSlotProps, SignUp, type SignUpSlotProps, SignedIn, SignedOut, type SupportedOAuthProvider, UserButton, type UserButtonSlotProps, createAuthOS, useAllPermissions, useAnyPermission, useAuthOS, useOrganization, usePermission, useUser };
758
+ export { AUTH_OS_INJECTION_KEY, type AppearanceOptions, type AppearanceVariables, type AuthOSContext, type AuthOSPluginOptions, AuthOSProvider, type AuthOSState, MagicLinkSignIn, OAuthButton, type OAuthButtonSlotProps, OrganizationSwitcher, type OrganizationSwitcherSlotProps, PasskeySignIn, Protect, SignIn, type SignInSlotProps, SignUp, type SignUpSlotProps, SignedIn, SignedOut, type SupportedOAuthProvider$1 as SupportedOAuthProvider, UserButton, type UserButtonSlotProps, createAuthOS, useAllPermissions, useAnyPermission, useAuthOS, useOrganization, usePermission, useUser };
package/dist/index.js CHANGED
@@ -92,23 +92,38 @@ var AUTHOS_STYLES = `
92
92
  Base Form Styles
93
93
  ========================================================================== */
94
94
 
95
+ /* ==========================================================================
96
+ Base Form Styles (Card Layout)
97
+ ========================================================================== */
98
+
95
99
  [data-authos-signin],
96
100
  [data-authos-signup],
97
- [data-authos-magiclink],
101
+ [data-authos-magic-link],
98
102
  [data-authos-passkey] {
99
103
  font-family: var(--authos-font-family);
100
104
  font-size: var(--authos-font-size-sm);
101
105
  color: var(--authos-color-foreground);
106
+
107
+ /* Card Styling */
108
+ background-color: var(--authos-color-surface);
109
+ border: 1px solid var(--authos-color-border);
110
+ border-radius: var(--authos-border-radius-lg);
111
+ box-shadow: var(--authos-shadow);
112
+ padding: 2rem;
102
113
  width: 100%;
114
+ max-width: 25rem; /* 400px */
115
+ margin: 0 auto; /* Center horizontally */
103
116
  }
104
117
 
118
+ /* Ensure forms inside take full width */
105
119
  [data-authos-signin] form,
106
120
  [data-authos-signup] form,
107
- [data-authos-magiclink] form,
121
+ [data-authos-magic-link] form,
108
122
  [data-authos-passkey] form {
109
123
  display: flex;
110
124
  flex-direction: column;
111
125
  gap: var(--authos-spacing-md);
126
+ width: 100%;
112
127
  }
113
128
 
114
129
  /* ==========================================================================
@@ -857,6 +872,133 @@ var SignIn = vue.defineComponent({
857
872
  };
858
873
  }
859
874
  });
875
+ var PROVIDER_NAMES = {
876
+ github: "GitHub",
877
+ google: "Google",
878
+ microsoft: "Microsoft"
879
+ };
880
+ function getProviderIcon(provider) {
881
+ switch (provider) {
882
+ case "github":
883
+ return vue.h("svg", {
884
+ xmlns: "http://www.w3.org/2000/svg",
885
+ viewBox: "0 0 24 24",
886
+ fill: "currentColor",
887
+ "aria-hidden": "true"
888
+ }, [
889
+ vue.h("path", {
890
+ d: "M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
891
+ })
892
+ ]);
893
+ case "google":
894
+ return vue.h("svg", {
895
+ xmlns: "http://www.w3.org/2000/svg",
896
+ viewBox: "0 0 24 24",
897
+ "aria-hidden": "true"
898
+ }, [
899
+ vue.h("path", {
900
+ fill: "#4285F4",
901
+ d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
902
+ }),
903
+ vue.h("path", {
904
+ fill: "#34A853",
905
+ d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
906
+ }),
907
+ vue.h("path", {
908
+ fill: "#FBBC05",
909
+ d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
910
+ }),
911
+ vue.h("path", {
912
+ fill: "#EA4335",
913
+ d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
914
+ })
915
+ ]);
916
+ case "microsoft":
917
+ return vue.h("svg", {
918
+ xmlns: "http://www.w3.org/2000/svg",
919
+ viewBox: "0 0 23 23",
920
+ "aria-hidden": "true"
921
+ }, [
922
+ vue.h("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
923
+ vue.h("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
924
+ vue.h("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
925
+ vue.h("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
926
+ ]);
927
+ }
928
+ }
929
+ var OAuthButton = vue.defineComponent({
930
+ name: "OAuthButton",
931
+ props: {
932
+ provider: {
933
+ type: String,
934
+ required: true
935
+ },
936
+ disabled: {
937
+ type: Boolean,
938
+ default: false
939
+ }
940
+ },
941
+ emits: ["redirect"],
942
+ setup(props, { slots, emit }) {
943
+ const { client, options } = useAuthOS();
944
+ const isConfigured = vue.computed(() => !!(options.org && options.service));
945
+ const providerName = vue.computed(() => PROVIDER_NAMES[props.provider]);
946
+ function handleClick() {
947
+ if (!options.org || !options.service) {
948
+ console.error(
949
+ `[AuthOS] OAuth login requires "org" and "service" in createAuthOS options.
950
+ Current options: { org: ${options.org ? `"${options.org}"` : "undefined"}, service: ${options.service ? `"${options.service}"` : "undefined"} }
951
+
952
+ Example:
953
+ app.use(createAuthOS({
954
+ baseURL: "${options.baseURL}",
955
+ org: "your-org-slug",
956
+ service: "your-service-slug",
957
+ }));
958
+
959
+ See: https://docs.authos.dev/vue/oauth-setup`
960
+ );
961
+ return;
962
+ }
963
+ const redirectUri = options.redirectUri ?? (typeof window !== "undefined" ? window.location.origin + "/callback" : void 0);
964
+ const url = client.auth.getLoginUrl(props.provider, {
965
+ org: options.org,
966
+ service: options.service,
967
+ redirect_uri: redirectUri
968
+ });
969
+ emit("redirect");
970
+ window.location.href = url;
971
+ }
972
+ return () => {
973
+ const slotProps = {
974
+ provider: props.provider,
975
+ providerName: providerName.value,
976
+ isConfigured: isConfigured.value,
977
+ disabled: props.disabled,
978
+ handleClick
979
+ };
980
+ if (slots.default) {
981
+ return slots.default(slotProps);
982
+ }
983
+ return vue.h(
984
+ "button",
985
+ {
986
+ type: "button",
987
+ onClick: handleClick,
988
+ disabled: props.disabled || !isConfigured.value,
989
+ "data-authos-oauth": "",
990
+ "data-provider": props.provider
991
+ },
992
+ [
993
+ getProviderIcon(props.provider),
994
+ vue.h("span", `Continue with ${providerName.value}`)
995
+ ]
996
+ );
997
+ };
998
+ }
999
+ });
1000
+
1001
+ // src/components/SignUp.ts
860
1002
  var SignUp = vue.defineComponent({
861
1003
  name: "SignUp",
862
1004
  props: {
@@ -877,17 +1019,44 @@ var SignUp = vue.defineComponent({
877
1019
  serviceSlug: {
878
1020
  type: String,
879
1021
  default: void 0
1022
+ },
1023
+ /** List of OAuth providers to display buttons for */
1024
+ providers: {
1025
+ type: [Array, Boolean],
1026
+ default: false
1027
+ },
1028
+ /** Show divider between OAuth and email form */
1029
+ showDivider: {
1030
+ type: Boolean,
1031
+ default: true
1032
+ },
1033
+ /** Show sign in link */
1034
+ showSignIn: {
1035
+ type: Boolean,
1036
+ default: true
880
1037
  }
881
1038
  },
882
1039
  emits: ["success", "error"],
883
1040
  setup(props, { slots, emit }) {
884
- const { client } = useAuthOS();
1041
+ const { client, options } = useAuthOS();
885
1042
  const email = vue.ref("");
886
1043
  const password = vue.ref("");
1044
+ const confirmPassword = vue.ref("");
887
1045
  const error = vue.ref(null);
888
1046
  const isSubmitting = vue.ref(false);
1047
+ const isSuccess = vue.ref(false);
1048
+ const hasOAuthConfig = !!(options.org && options.service);
1049
+ const oauthProviders = Array.isArray(props.providers) ? props.providers : [];
889
1050
  async function submit() {
890
1051
  error.value = null;
1052
+ if (password.value !== confirmPassword.value) {
1053
+ error.value = "Passwords do not match";
1054
+ return;
1055
+ }
1056
+ if (password.value.length < 8) {
1057
+ error.value = "Password must be at least 8 characters";
1058
+ return;
1059
+ }
891
1060
  isSubmitting.value = true;
892
1061
  try {
893
1062
  await client.auth.register({
@@ -896,6 +1065,7 @@ var SignUp = vue.defineComponent({
896
1065
  org_slug: props.orgSlug,
897
1066
  service_slug: props.serviceSlug
898
1067
  });
1068
+ isSuccess.value = true;
899
1069
  emit("success");
900
1070
  props.onSuccess?.();
901
1071
  } catch (err) {
@@ -921,7 +1091,33 @@ var SignUp = vue.defineComponent({
921
1091
  if (slots.default) {
922
1092
  return slots.default(slotProps);
923
1093
  }
1094
+ if (isSuccess.value) {
1095
+ return vue.h("div", { "data-authos-signup": "", "data-state": "success" }, [
1096
+ vue.h("div", { "data-authos-success": "" }, [
1097
+ vue.h("h2", "Check your email"),
1098
+ vue.h("p", `We've sent a verification link to ${email.value}. Please click the link to verify your account.`)
1099
+ ])
1100
+ ]);
1101
+ }
924
1102
  return vue.h("div", { "data-authos-signup": "", "data-state": "credentials" }, [
1103
+ // OAuth Section
1104
+ oauthProviders.length > 0 && vue.h("div", { "data-authos-oauth-section": "" }, [
1105
+ oauthProviders.map(
1106
+ (provider) => vue.h(OAuthButton, {
1107
+ key: provider,
1108
+ provider,
1109
+ disabled: isSubmitting.value || !hasOAuthConfig
1110
+ })
1111
+ ),
1112
+ !hasOAuthConfig && vue.h("p", {
1113
+ "data-authos-oauth-warning": "",
1114
+ style: { color: "orange", fontSize: "0.875rem" }
1115
+ }, "OAuth requires org and service in plugin options")
1116
+ ]),
1117
+ // Divider
1118
+ oauthProviders.length > 0 && props.showDivider && vue.h("div", { "data-authos-divider": "" }, [
1119
+ vue.h("span", "or")
1120
+ ]),
925
1121
  vue.h("form", { onSubmit: (e) => {
926
1122
  e.preventDefault();
927
1123
  submit();
@@ -952,12 +1148,31 @@ var SignUp = vue.defineComponent({
952
1148
  onInput: (e) => password.value = e.target.value
953
1149
  })
954
1150
  ]),
1151
+ // Confirm Password
1152
+ vue.h("div", { "data-authos-field": "confirm-password" }, [
1153
+ vue.h("label", { for: "authos-signup-confirm" }, "Confirm Password"),
1154
+ vue.h("input", {
1155
+ id: "authos-signup-confirm",
1156
+ type: "password",
1157
+ autocomplete: "new-password",
1158
+ value: confirmPassword.value,
1159
+ placeholder: "Confirm your password",
1160
+ required: true,
1161
+ disabled: isSubmitting.value,
1162
+ onInput: (e) => confirmPassword.value = e.target.value
1163
+ })
1164
+ ]),
955
1165
  error.value && vue.h("div", { "data-authos-error": "" }, error.value),
956
1166
  vue.h("button", {
957
1167
  type: "submit",
958
1168
  disabled: isSubmitting.value,
959
1169
  "data-authos-submit": ""
960
- }, isSubmitting.value ? "Creating account..." : "Sign Up")
1170
+ }, isSubmitting.value ? "Creating account..." : "Sign Up"),
1171
+ // Sign In Link
1172
+ props.showSignIn && vue.h("div", { "data-authos-signin-prompt": "" }, [
1173
+ "Already have an account? ",
1174
+ vue.h("a", { href: "/signin", "data-authos-link": "signin" }, "Sign in")
1175
+ ])
961
1176
  ])
962
1177
  ]);
963
1178
  };
@@ -1125,131 +1340,6 @@ var Protect = vue.defineComponent({
1125
1340
  };
1126
1341
  }
1127
1342
  });
1128
- var PROVIDER_NAMES = {
1129
- github: "GitHub",
1130
- google: "Google",
1131
- microsoft: "Microsoft"
1132
- };
1133
- function getProviderIcon(provider) {
1134
- switch (provider) {
1135
- case "github":
1136
- return vue.h("svg", {
1137
- xmlns: "http://www.w3.org/2000/svg",
1138
- viewBox: "0 0 24 24",
1139
- fill: "currentColor",
1140
- "aria-hidden": "true"
1141
- }, [
1142
- vue.h("path", {
1143
- d: "M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
1144
- })
1145
- ]);
1146
- case "google":
1147
- return vue.h("svg", {
1148
- xmlns: "http://www.w3.org/2000/svg",
1149
- viewBox: "0 0 24 24",
1150
- "aria-hidden": "true"
1151
- }, [
1152
- vue.h("path", {
1153
- fill: "#4285F4",
1154
- d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
1155
- }),
1156
- vue.h("path", {
1157
- fill: "#34A853",
1158
- d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
1159
- }),
1160
- vue.h("path", {
1161
- fill: "#FBBC05",
1162
- d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
1163
- }),
1164
- vue.h("path", {
1165
- fill: "#EA4335",
1166
- d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
1167
- })
1168
- ]);
1169
- case "microsoft":
1170
- return vue.h("svg", {
1171
- xmlns: "http://www.w3.org/2000/svg",
1172
- viewBox: "0 0 23 23",
1173
- "aria-hidden": "true"
1174
- }, [
1175
- vue.h("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
1176
- vue.h("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
1177
- vue.h("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
1178
- vue.h("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
1179
- ]);
1180
- }
1181
- }
1182
- var OAuthButton = vue.defineComponent({
1183
- name: "OAuthButton",
1184
- props: {
1185
- provider: {
1186
- type: String,
1187
- required: true
1188
- },
1189
- disabled: {
1190
- type: Boolean,
1191
- default: false
1192
- }
1193
- },
1194
- emits: ["redirect"],
1195
- setup(props, { slots, emit }) {
1196
- const { client, options } = useAuthOS();
1197
- const isConfigured = vue.computed(() => !!(options.org && options.service));
1198
- const providerName = vue.computed(() => PROVIDER_NAMES[props.provider]);
1199
- function handleClick() {
1200
- if (!options.org || !options.service) {
1201
- console.error(
1202
- `[AuthOS] OAuth login requires "org" and "service" in createAuthOS options.
1203
- Current options: { org: ${options.org ? `"${options.org}"` : "undefined"}, service: ${options.service ? `"${options.service}"` : "undefined"} }
1204
-
1205
- Example:
1206
- app.use(createAuthOS({
1207
- baseURL: "${options.baseURL}",
1208
- org: "your-org-slug",
1209
- service: "your-service-slug",
1210
- }));
1211
-
1212
- See: https://docs.authos.dev/vue/oauth-setup`
1213
- );
1214
- return;
1215
- }
1216
- const redirectUri = options.redirectUri ?? (typeof window !== "undefined" ? window.location.origin + "/callback" : void 0);
1217
- const url = client.auth.getLoginUrl(props.provider, {
1218
- org: options.org,
1219
- service: options.service,
1220
- redirect_uri: redirectUri
1221
- });
1222
- emit("redirect");
1223
- window.location.href = url;
1224
- }
1225
- return () => {
1226
- const slotProps = {
1227
- provider: props.provider,
1228
- providerName: providerName.value,
1229
- isConfigured: isConfigured.value,
1230
- disabled: props.disabled,
1231
- handleClick
1232
- };
1233
- if (slots.default) {
1234
- return slots.default(slotProps);
1235
- }
1236
- return vue.h(
1237
- "button",
1238
- {
1239
- type: "button",
1240
- onClick: handleClick,
1241
- disabled: props.disabled || !isConfigured.value,
1242
- "data-authos-oauth": "",
1243
- "data-provider": props.provider
1244
- },
1245
- [
1246
- getProviderIcon(props.provider),
1247
- vue.h("span", `Continue with ${providerName.value}`)
1248
- ]
1249
- );
1250
- };
1251
- }
1252
- });
1253
1343
  var SignedIn = vue.defineComponent({
1254
1344
  name: "SignedIn",
1255
1345
  setup(_, { slots }) {
package/dist/index.mjs CHANGED
@@ -89,23 +89,38 @@ var AUTHOS_STYLES = `
89
89
  Base Form Styles
90
90
  ========================================================================== */
91
91
 
92
+ /* ==========================================================================
93
+ Base Form Styles (Card Layout)
94
+ ========================================================================== */
95
+
92
96
  [data-authos-signin],
93
97
  [data-authos-signup],
94
- [data-authos-magiclink],
98
+ [data-authos-magic-link],
95
99
  [data-authos-passkey] {
96
100
  font-family: var(--authos-font-family);
97
101
  font-size: var(--authos-font-size-sm);
98
102
  color: var(--authos-color-foreground);
103
+
104
+ /* Card Styling */
105
+ background-color: var(--authos-color-surface);
106
+ border: 1px solid var(--authos-color-border);
107
+ border-radius: var(--authos-border-radius-lg);
108
+ box-shadow: var(--authos-shadow);
109
+ padding: 2rem;
99
110
  width: 100%;
111
+ max-width: 25rem; /* 400px */
112
+ margin: 0 auto; /* Center horizontally */
100
113
  }
101
114
 
115
+ /* Ensure forms inside take full width */
102
116
  [data-authos-signin] form,
103
117
  [data-authos-signup] form,
104
- [data-authos-magiclink] form,
118
+ [data-authos-magic-link] form,
105
119
  [data-authos-passkey] form {
106
120
  display: flex;
107
121
  flex-direction: column;
108
122
  gap: var(--authos-spacing-md);
123
+ width: 100%;
109
124
  }
110
125
 
111
126
  /* ==========================================================================
@@ -828,6 +843,133 @@ var SignIn = defineComponent({
828
843
  };
829
844
  }
830
845
  });
846
+ var PROVIDER_NAMES = {
847
+ github: "GitHub",
848
+ google: "Google",
849
+ microsoft: "Microsoft"
850
+ };
851
+ function getProviderIcon(provider) {
852
+ switch (provider) {
853
+ case "github":
854
+ return h("svg", {
855
+ xmlns: "http://www.w3.org/2000/svg",
856
+ viewBox: "0 0 24 24",
857
+ fill: "currentColor",
858
+ "aria-hidden": "true"
859
+ }, [
860
+ h("path", {
861
+ d: "M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
862
+ })
863
+ ]);
864
+ case "google":
865
+ return h("svg", {
866
+ xmlns: "http://www.w3.org/2000/svg",
867
+ viewBox: "0 0 24 24",
868
+ "aria-hidden": "true"
869
+ }, [
870
+ h("path", {
871
+ fill: "#4285F4",
872
+ d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
873
+ }),
874
+ h("path", {
875
+ fill: "#34A853",
876
+ d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
877
+ }),
878
+ h("path", {
879
+ fill: "#FBBC05",
880
+ d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
881
+ }),
882
+ h("path", {
883
+ fill: "#EA4335",
884
+ d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
885
+ })
886
+ ]);
887
+ case "microsoft":
888
+ return h("svg", {
889
+ xmlns: "http://www.w3.org/2000/svg",
890
+ viewBox: "0 0 23 23",
891
+ "aria-hidden": "true"
892
+ }, [
893
+ h("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
894
+ h("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
895
+ h("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
896
+ h("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
897
+ ]);
898
+ }
899
+ }
900
+ var OAuthButton = defineComponent({
901
+ name: "OAuthButton",
902
+ props: {
903
+ provider: {
904
+ type: String,
905
+ required: true
906
+ },
907
+ disabled: {
908
+ type: Boolean,
909
+ default: false
910
+ }
911
+ },
912
+ emits: ["redirect"],
913
+ setup(props, { slots, emit }) {
914
+ const { client, options } = useAuthOS();
915
+ const isConfigured = computed(() => !!(options.org && options.service));
916
+ const providerName = computed(() => PROVIDER_NAMES[props.provider]);
917
+ function handleClick() {
918
+ if (!options.org || !options.service) {
919
+ console.error(
920
+ `[AuthOS] OAuth login requires "org" and "service" in createAuthOS options.
921
+ Current options: { org: ${options.org ? `"${options.org}"` : "undefined"}, service: ${options.service ? `"${options.service}"` : "undefined"} }
922
+
923
+ Example:
924
+ app.use(createAuthOS({
925
+ baseURL: "${options.baseURL}",
926
+ org: "your-org-slug",
927
+ service: "your-service-slug",
928
+ }));
929
+
930
+ See: https://docs.authos.dev/vue/oauth-setup`
931
+ );
932
+ return;
933
+ }
934
+ const redirectUri = options.redirectUri ?? (typeof window !== "undefined" ? window.location.origin + "/callback" : void 0);
935
+ const url = client.auth.getLoginUrl(props.provider, {
936
+ org: options.org,
937
+ service: options.service,
938
+ redirect_uri: redirectUri
939
+ });
940
+ emit("redirect");
941
+ window.location.href = url;
942
+ }
943
+ return () => {
944
+ const slotProps = {
945
+ provider: props.provider,
946
+ providerName: providerName.value,
947
+ isConfigured: isConfigured.value,
948
+ disabled: props.disabled,
949
+ handleClick
950
+ };
951
+ if (slots.default) {
952
+ return slots.default(slotProps);
953
+ }
954
+ return h(
955
+ "button",
956
+ {
957
+ type: "button",
958
+ onClick: handleClick,
959
+ disabled: props.disabled || !isConfigured.value,
960
+ "data-authos-oauth": "",
961
+ "data-provider": props.provider
962
+ },
963
+ [
964
+ getProviderIcon(props.provider),
965
+ h("span", `Continue with ${providerName.value}`)
966
+ ]
967
+ );
968
+ };
969
+ }
970
+ });
971
+
972
+ // src/components/SignUp.ts
831
973
  var SignUp = defineComponent({
832
974
  name: "SignUp",
833
975
  props: {
@@ -848,17 +990,44 @@ var SignUp = defineComponent({
848
990
  serviceSlug: {
849
991
  type: String,
850
992
  default: void 0
993
+ },
994
+ /** List of OAuth providers to display buttons for */
995
+ providers: {
996
+ type: [Array, Boolean],
997
+ default: false
998
+ },
999
+ /** Show divider between OAuth and email form */
1000
+ showDivider: {
1001
+ type: Boolean,
1002
+ default: true
1003
+ },
1004
+ /** Show sign in link */
1005
+ showSignIn: {
1006
+ type: Boolean,
1007
+ default: true
851
1008
  }
852
1009
  },
853
1010
  emits: ["success", "error"],
854
1011
  setup(props, { slots, emit }) {
855
- const { client } = useAuthOS();
1012
+ const { client, options } = useAuthOS();
856
1013
  const email = ref("");
857
1014
  const password = ref("");
1015
+ const confirmPassword = ref("");
858
1016
  const error = ref(null);
859
1017
  const isSubmitting = ref(false);
1018
+ const isSuccess = ref(false);
1019
+ const hasOAuthConfig = !!(options.org && options.service);
1020
+ const oauthProviders = Array.isArray(props.providers) ? props.providers : [];
860
1021
  async function submit() {
861
1022
  error.value = null;
1023
+ if (password.value !== confirmPassword.value) {
1024
+ error.value = "Passwords do not match";
1025
+ return;
1026
+ }
1027
+ if (password.value.length < 8) {
1028
+ error.value = "Password must be at least 8 characters";
1029
+ return;
1030
+ }
862
1031
  isSubmitting.value = true;
863
1032
  try {
864
1033
  await client.auth.register({
@@ -867,6 +1036,7 @@ var SignUp = defineComponent({
867
1036
  org_slug: props.orgSlug,
868
1037
  service_slug: props.serviceSlug
869
1038
  });
1039
+ isSuccess.value = true;
870
1040
  emit("success");
871
1041
  props.onSuccess?.();
872
1042
  } catch (err) {
@@ -892,7 +1062,33 @@ var SignUp = defineComponent({
892
1062
  if (slots.default) {
893
1063
  return slots.default(slotProps);
894
1064
  }
1065
+ if (isSuccess.value) {
1066
+ return h("div", { "data-authos-signup": "", "data-state": "success" }, [
1067
+ h("div", { "data-authos-success": "" }, [
1068
+ h("h2", "Check your email"),
1069
+ h("p", `We've sent a verification link to ${email.value}. Please click the link to verify your account.`)
1070
+ ])
1071
+ ]);
1072
+ }
895
1073
  return h("div", { "data-authos-signup": "", "data-state": "credentials" }, [
1074
+ // OAuth Section
1075
+ oauthProviders.length > 0 && h("div", { "data-authos-oauth-section": "" }, [
1076
+ oauthProviders.map(
1077
+ (provider) => h(OAuthButton, {
1078
+ key: provider,
1079
+ provider,
1080
+ disabled: isSubmitting.value || !hasOAuthConfig
1081
+ })
1082
+ ),
1083
+ !hasOAuthConfig && h("p", {
1084
+ "data-authos-oauth-warning": "",
1085
+ style: { color: "orange", fontSize: "0.875rem" }
1086
+ }, "OAuth requires org and service in plugin options")
1087
+ ]),
1088
+ // Divider
1089
+ oauthProviders.length > 0 && props.showDivider && h("div", { "data-authos-divider": "" }, [
1090
+ h("span", "or")
1091
+ ]),
896
1092
  h("form", { onSubmit: (e) => {
897
1093
  e.preventDefault();
898
1094
  submit();
@@ -923,12 +1119,31 @@ var SignUp = defineComponent({
923
1119
  onInput: (e) => password.value = e.target.value
924
1120
  })
925
1121
  ]),
1122
+ // Confirm Password
1123
+ h("div", { "data-authos-field": "confirm-password" }, [
1124
+ h("label", { for: "authos-signup-confirm" }, "Confirm Password"),
1125
+ h("input", {
1126
+ id: "authos-signup-confirm",
1127
+ type: "password",
1128
+ autocomplete: "new-password",
1129
+ value: confirmPassword.value,
1130
+ placeholder: "Confirm your password",
1131
+ required: true,
1132
+ disabled: isSubmitting.value,
1133
+ onInput: (e) => confirmPassword.value = e.target.value
1134
+ })
1135
+ ]),
926
1136
  error.value && h("div", { "data-authos-error": "" }, error.value),
927
1137
  h("button", {
928
1138
  type: "submit",
929
1139
  disabled: isSubmitting.value,
930
1140
  "data-authos-submit": ""
931
- }, isSubmitting.value ? "Creating account..." : "Sign Up")
1141
+ }, isSubmitting.value ? "Creating account..." : "Sign Up"),
1142
+ // Sign In Link
1143
+ props.showSignIn && h("div", { "data-authos-signin-prompt": "" }, [
1144
+ "Already have an account? ",
1145
+ h("a", { href: "/signin", "data-authos-link": "signin" }, "Sign in")
1146
+ ])
932
1147
  ])
933
1148
  ]);
934
1149
  };
@@ -1096,131 +1311,6 @@ var Protect = defineComponent({
1096
1311
  };
1097
1312
  }
1098
1313
  });
1099
- var PROVIDER_NAMES = {
1100
- github: "GitHub",
1101
- google: "Google",
1102
- microsoft: "Microsoft"
1103
- };
1104
- function getProviderIcon(provider) {
1105
- switch (provider) {
1106
- case "github":
1107
- return h("svg", {
1108
- xmlns: "http://www.w3.org/2000/svg",
1109
- viewBox: "0 0 24 24",
1110
- fill: "currentColor",
1111
- "aria-hidden": "true"
1112
- }, [
1113
- h("path", {
1114
- d: "M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
1115
- })
1116
- ]);
1117
- case "google":
1118
- return h("svg", {
1119
- xmlns: "http://www.w3.org/2000/svg",
1120
- viewBox: "0 0 24 24",
1121
- "aria-hidden": "true"
1122
- }, [
1123
- h("path", {
1124
- fill: "#4285F4",
1125
- d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
1126
- }),
1127
- h("path", {
1128
- fill: "#34A853",
1129
- d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
1130
- }),
1131
- h("path", {
1132
- fill: "#FBBC05",
1133
- d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
1134
- }),
1135
- h("path", {
1136
- fill: "#EA4335",
1137
- d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
1138
- })
1139
- ]);
1140
- case "microsoft":
1141
- return h("svg", {
1142
- xmlns: "http://www.w3.org/2000/svg",
1143
- viewBox: "0 0 23 23",
1144
- "aria-hidden": "true"
1145
- }, [
1146
- h("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
1147
- h("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
1148
- h("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
1149
- h("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
1150
- ]);
1151
- }
1152
- }
1153
- var OAuthButton = defineComponent({
1154
- name: "OAuthButton",
1155
- props: {
1156
- provider: {
1157
- type: String,
1158
- required: true
1159
- },
1160
- disabled: {
1161
- type: Boolean,
1162
- default: false
1163
- }
1164
- },
1165
- emits: ["redirect"],
1166
- setup(props, { slots, emit }) {
1167
- const { client, options } = useAuthOS();
1168
- const isConfigured = computed(() => !!(options.org && options.service));
1169
- const providerName = computed(() => PROVIDER_NAMES[props.provider]);
1170
- function handleClick() {
1171
- if (!options.org || !options.service) {
1172
- console.error(
1173
- `[AuthOS] OAuth login requires "org" and "service" in createAuthOS options.
1174
- Current options: { org: ${options.org ? `"${options.org}"` : "undefined"}, service: ${options.service ? `"${options.service}"` : "undefined"} }
1175
-
1176
- Example:
1177
- app.use(createAuthOS({
1178
- baseURL: "${options.baseURL}",
1179
- org: "your-org-slug",
1180
- service: "your-service-slug",
1181
- }));
1182
-
1183
- See: https://docs.authos.dev/vue/oauth-setup`
1184
- );
1185
- return;
1186
- }
1187
- const redirectUri = options.redirectUri ?? (typeof window !== "undefined" ? window.location.origin + "/callback" : void 0);
1188
- const url = client.auth.getLoginUrl(props.provider, {
1189
- org: options.org,
1190
- service: options.service,
1191
- redirect_uri: redirectUri
1192
- });
1193
- emit("redirect");
1194
- window.location.href = url;
1195
- }
1196
- return () => {
1197
- const slotProps = {
1198
- provider: props.provider,
1199
- providerName: providerName.value,
1200
- isConfigured: isConfigured.value,
1201
- disabled: props.disabled,
1202
- handleClick
1203
- };
1204
- if (slots.default) {
1205
- return slots.default(slotProps);
1206
- }
1207
- return h(
1208
- "button",
1209
- {
1210
- type: "button",
1211
- onClick: handleClick,
1212
- disabled: props.disabled || !isConfigured.value,
1213
- "data-authos-oauth": "",
1214
- "data-provider": props.provider
1215
- },
1216
- [
1217
- getProviderIcon(props.provider),
1218
- h("span", `Continue with ${providerName.value}`)
1219
- ]
1220
- );
1221
- };
1222
- }
1223
- });
1224
1314
  var SignedIn = defineComponent({
1225
1315
  name: "SignedIn",
1226
1316
  setup(_, { slots }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drmhse/authos-vue",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Vue and Nuxt adapter for AuthOS authentication",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",