@cabin-id/nextjs 1.2.3 → 1.2.4

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.
@@ -35,20 +35,15 @@ module.exports = __toCommonJS(SignOutButton_exports);
35
35
  var import_react = __toESM(require("react"));
36
36
  var import_useUser = require("../hooks/useUser");
37
37
  var import_constants = require("../constants");
38
- var import_subdomain = require("../utils/subdomain");
39
38
  var import_constants2 = require("../constants");
40
39
  const SignOutButton = ({
41
40
  children = "Sign Out",
42
41
  className = "px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50",
43
- signOutOptions,
44
42
  onSignOutStart,
45
43
  onSignOutSuccess,
46
44
  onSignOutError,
47
45
  showLoading = true,
48
- loadingText = "Signing out...",
49
- callBackend = true,
50
- cabinIdSubdomain,
51
- useCrossDomainLogout = true
46
+ loadingText = "Signing out..."
52
47
  }) => {
53
48
  const { signOut, isSignedIn, user } = (0, import_useUser.useUser)();
54
49
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
@@ -57,37 +52,7 @@ const SignOutButton = ({
57
52
  try {
58
53
  setIsLoading(true);
59
54
  onSignOutStart == null ? void 0 : onSignOutStart();
60
- const subdomain = cabinIdSubdomain || (0, import_subdomain.detectCabinIdSubdomain)();
61
- if (useCrossDomainLogout && subdomain) {
62
- if (callBackend && user) {
63
- try {
64
- const token = getCookieValue("__client") || getCookieValue("__user");
65
- if (token) {
66
- await fetch(`${import_constants.baseApiUrl}/auth/sign-out`, {
67
- method: "POST",
68
- headers: {
69
- "Content-Type": "application/json",
70
- "Authorization": `Bearer ${token}`,
71
- "Origin": typeof window !== "undefined" ? window.location.origin : ""
72
- }
73
- });
74
- }
75
- } catch (backendError) {
76
- console.warn("Backend sign-out failed, proceeding with logout:", backendError);
77
- }
78
- }
79
- await signOut(() => {
80
- });
81
- const origin = typeof window !== "undefined" ? window.location.origin : "";
82
- const params = new URLSearchParams({
83
- redirect_url: `${origin}${import_constants2.SIGN_IN_URL}` || "/"
84
- });
85
- const logoutUrl = `https://${import_constants2.frontendApi}.cabinid.dev/logout?${params.toString()}`;
86
- onSignOutSuccess == null ? void 0 : onSignOutSuccess();
87
- window.location.href = logoutUrl;
88
- return;
89
- }
90
- if (callBackend && user) {
55
+ if (user) {
91
56
  try {
92
57
  const token = getCookieValue("__client") || getCookieValue("__user");
93
58
  if (token) {
@@ -101,15 +66,20 @@ const SignOutButton = ({
101
66
  });
102
67
  }
103
68
  } catch (backendError) {
104
- console.warn("Backend sign-out failed, proceeding with client-side cleanup:", backendError);
69
+ console.warn("Backend sign-out failed, proceeding with logout:", backendError);
105
70
  }
106
71
  }
107
- await signOut(signOutOptions);
72
+ await signOut();
73
+ const origin = typeof window !== "undefined" ? window.location.origin : "";
74
+ const params = new URLSearchParams({
75
+ redirect_url: `${origin}${import_constants2.AFTER_SIGN_IN_URL}`
76
+ });
77
+ const logoutUrl = `https://${import_constants2.frontendApi}.cabinid.dev/logout?${params.toString()}`;
108
78
  onSignOutSuccess == null ? void 0 : onSignOutSuccess();
79
+ window.location.href = logoutUrl;
109
80
  } catch (error) {
110
81
  console.error("Sign out error:", error);
111
82
  onSignOutError == null ? void 0 : onSignOutError(error);
112
- } finally {
113
83
  setIsLoading(false);
114
84
  }
115
85
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/SignOutButton.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { useUser, SignOutOptions } from '../hooks/useUser';\nimport { baseApiUrl } from '../constants';\nimport { detectCabinIdSubdomain } from '../utils/subdomain';\nimport { SIGN_IN_URL, frontendApi } from '../constants';\n\n\nexport interface SignOutButtonProps {\n /**\n * Custom text to display on the button\n * @default \"Sign Out\"\n */\n children?: React.ReactNode;\n /**\n * Custom CSS class name\n */\n className?: string;\n /**\n * Sign out options\n */\n signOutOptions?: SignOutOptions;\n /**\n * Callback function called before sign out\n */\n onSignOutStart?: () => void;\n /**\n * Callback function called after successful sign out\n */\n onSignOutSuccess?: () => void;\n /**\n * Callback function called when sign out fails\n */\n onSignOutError?: (error: Error) => void;\n /**\n * Whether to show loading state\n * @default true\n */\n showLoading?: boolean;\n /**\n * Custom loading text\n * @default \"Signing out...\"\n */\n loadingText?: string;\n /**\n * Whether to call the backend sign-out endpoint\n * @default true\n */\n callBackend?: boolean;\n /**\n * CabinID subdomain for cross-domain logout\n * @example \"myapp\" for myapp.cabinid.dev\n */\n cabinIdSubdomain?: string;\n /**\n * Whether to use cross-domain logout flow\n * @default true\n */\n useCrossDomainLogout?: boolean;\n}\n\n/**\n * SignOutButton component that handles user logout with CabinID backend integration\n */\nexport const SignOutButton: React.FC<SignOutButtonProps> = ({\n children = 'Sign Out',\n className = 'px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50',\n signOutOptions,\n onSignOutStart,\n onSignOutSuccess,\n onSignOutError,\n showLoading = true,\n loadingText = 'Signing out...',\n callBackend = true,\n cabinIdSubdomain,\n useCrossDomainLogout = true,\n}) => {\n const { signOut, isSignedIn, user } = useUser();\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSignOut = async () => {\n if (isLoading || !isSignedIn) return;\n\n try {\n setIsLoading(true);\n onSignOutStart?.();\n\n // Cross-domain logout flow\n const subdomain = cabinIdSubdomain || detectCabinIdSubdomain();\n if (useCrossDomainLogout && subdomain) {\n // Call backend sign-out endpoint first\n if (callBackend && user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with logout:', backendError);\n }\n }\n\n // Clear local cookies and storage\n await signOut(() => {\n // Don't redirect yet, we'll handle it manually\n });\n\n // Redirect to CabinID logout page for complete cleanup\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const params = new URLSearchParams({\n redirect_url: `${origin}${SIGN_IN_URL}` || '/',\n });\n const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;\n \n onSignOutSuccess?.();\n window.location.href = logoutUrl;\n return;\n }\n\n // Standard logout flow (backward compatibility)\n if (callBackend && user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with client-side cleanup:', backendError);\n }\n }\n\n await signOut(signOutOptions);\n onSignOutSuccess?.();\n } catch (error) {\n console.error('Sign out error:', error);\n onSignOutError?.(error as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n // Helper function to get cookie value\n const getCookieValue = (name: string): string | null => {\n if (typeof window === 'undefined') return null;\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift() || null;\n }\n return null;\n };\n\n // Don't render if user is not signed in\n if (!isSignedIn) {\n return null;\n }\n\n return (\n <button\n onClick={handleSignOut}\n disabled={isLoading}\n className={className}\n type=\"button\"\n >\n {isLoading && showLoading ? loadingText : children}\n </button>\n );\n};"],"mappings":"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","names":["import_constants","React"]}
1
+ {"version":3,"sources":["../../../src/components/SignOutButton.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { useUser } from '../hooks/useUser';\nimport { baseApiUrl } from '../constants';\nimport { AFTER_SIGN_IN_URL, frontendApi } from '../constants';\n\nexport interface SignOutButtonProps {\n /**\n * Custom text to display on the button\n * @default \"Sign Out\"\n */\n children?: React.ReactNode;\n /**\n * Custom CSS class name\n */\n className?: string;\n /**\n * Callback function called before sign out\n */\n onSignOutStart?: () => void;\n /**\n * Callback function called after successful sign out\n */\n onSignOutSuccess?: () => void;\n /**\n * Callback function called when sign out fails\n */\n onSignOutError?: (error: Error) => void;\n /**\n * Whether to show loading state\n * @default true\n */\n showLoading?: boolean;\n /**\n * Custom loading text\n * @default \"Signing out...\"\n */\n loadingText?: string;\n}\n\n/**\n * SignOutButton component that handles user logout with CabinID backend integration\n */\nexport const SignOutButton: React.FC<SignOutButtonProps> = ({\n children = 'Sign Out',\n className = 'px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50',\n onSignOutStart,\n onSignOutSuccess,\n onSignOutError,\n showLoading = true,\n loadingText = 'Signing out...',\n}) => {\n const { signOut, isSignedIn, user } = useUser();\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSignOut = async () => {\n if (isLoading || !isSignedIn) return;\n\n try {\n setIsLoading(true);\n onSignOutStart?.();\n\n // 1. Call backend sign-out endpoint first\n if (user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with logout:', backendError);\n }\n }\n\n // 2. Clear local cookies and storage\n await signOut();\n\n // 3. Redirect to CabinID logout page with redirect_url\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const params = new URLSearchParams({\n redirect_url: `${origin}${AFTER_SIGN_IN_URL}`,\n });\n const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;\n \n onSignOutSuccess?.();\n window.location.href = logoutUrl;\n } catch (error) {\n console.error('Sign out error:', error);\n onSignOutError?.(error as Error);\n setIsLoading(false);\n }\n };\n\n // Helper function to get cookie value\n const getCookieValue = (name: string): string | null => {\n if (typeof window === 'undefined') return null;\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift() || null;\n }\n return null;\n };\n\n // Don't render if user is not signed in\n if (!isSignedIn) {\n return null;\n }\n\n return (\n <button\n onClick={handleSignOut}\n disabled={isLoading}\n className={className}\n type=\"button\"\n >\n {isLoading && showLoading ? loadingText : children}\n </button>\n );\n};"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAgC;AAChC,qBAAwB;AACxB,uBAA2B;AAC3B,IAAAA,oBAA+C;AAuCxC,MAAM,gBAA8C,CAAC;AAAA,EAC1D,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAChB,MAAM;AACJ,QAAM,EAAE,SAAS,YAAY,KAAK,QAAI,wBAAQ;AAC9C,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,KAAK;AAEhD,QAAM,gBAAgB,YAAY;AAChC,QAAI,aAAa,CAAC,WAAY;AAE9B,QAAI;AACF,mBAAa,IAAI;AACjB;AAGA,UAAI,MAAM;AACR,YAAI;AACF,gBAAM,QAAQ,eAAe,UAAU,KAAK,eAAe,QAAQ;AACnE,cAAI,OAAO;AACT,kBAAM,MAAM,GAAG,2BAAU,kBAAkB;AAAA,cACzC,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,gBAAgB;AAAA,gBAChB,iBAAiB,UAAU,KAAK;AAAA,gBAChC,UAAU,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AAAA,cACrE;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,SAAS,cAAc;AACrB,kBAAQ,KAAK,oDAAoD,YAAY;AAAA,QAC/E;AAAA,MACF;AAGA,YAAM,QAAQ;AAGd,YAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,cAAc,GAAG,MAAM,GAAG,mCAAiB;AAAA,MAC7C,CAAC;AACD,YAAM,YAAY,WAAW,6BAAW,uBAAuB,OAAO,SAAS,CAAC;AAEhF;AACA,aAAO,SAAS,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,uDAAiB;AACjB,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,iBAAiB,CAAC,SAAgC;AAtG1D;AAuGI,QAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,UAAM,QAAQ,KAAK,SAAS,MAAM;AAClC,UAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,GAAG;AACtC,QAAI,MAAM,WAAW,GAAG;AACtB,eAAO,WAAM,IAAI,MAAV,mBAAa,MAAM,KAAK,YAAW;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,SACE,6BAAAC,QAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,MAAK;AAAA;AAAA,IAEJ,aAAa,cAAc,cAAc;AAAA,EAC5C;AAEJ;","names":["import_constants","React"]}
@@ -2,20 +2,15 @@
2
2
  import React, { useState } from "react";
3
3
  import { useUser } from "../hooks/useUser";
4
4
  import { baseApiUrl } from "../constants";
5
- import { detectCabinIdSubdomain } from "../utils/subdomain";
6
- import { SIGN_IN_URL, frontendApi } from "../constants";
5
+ import { AFTER_SIGN_IN_URL, frontendApi } from "../constants";
7
6
  const SignOutButton = ({
8
7
  children = "Sign Out",
9
8
  className = "px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50",
10
- signOutOptions,
11
9
  onSignOutStart,
12
10
  onSignOutSuccess,
13
11
  onSignOutError,
14
12
  showLoading = true,
15
- loadingText = "Signing out...",
16
- callBackend = true,
17
- cabinIdSubdomain,
18
- useCrossDomainLogout = true
13
+ loadingText = "Signing out..."
19
14
  }) => {
20
15
  const { signOut, isSignedIn, user } = useUser();
21
16
  const [isLoading, setIsLoading] = useState(false);
@@ -24,37 +19,7 @@ const SignOutButton = ({
24
19
  try {
25
20
  setIsLoading(true);
26
21
  onSignOutStart == null ? void 0 : onSignOutStart();
27
- const subdomain = cabinIdSubdomain || detectCabinIdSubdomain();
28
- if (useCrossDomainLogout && subdomain) {
29
- if (callBackend && user) {
30
- try {
31
- const token = getCookieValue("__client") || getCookieValue("__user");
32
- if (token) {
33
- await fetch(`${baseApiUrl}/auth/sign-out`, {
34
- method: "POST",
35
- headers: {
36
- "Content-Type": "application/json",
37
- "Authorization": `Bearer ${token}`,
38
- "Origin": typeof window !== "undefined" ? window.location.origin : ""
39
- }
40
- });
41
- }
42
- } catch (backendError) {
43
- console.warn("Backend sign-out failed, proceeding with logout:", backendError);
44
- }
45
- }
46
- await signOut(() => {
47
- });
48
- const origin = typeof window !== "undefined" ? window.location.origin : "";
49
- const params = new URLSearchParams({
50
- redirect_url: `${origin}${SIGN_IN_URL}` || "/"
51
- });
52
- const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;
53
- onSignOutSuccess == null ? void 0 : onSignOutSuccess();
54
- window.location.href = logoutUrl;
55
- return;
56
- }
57
- if (callBackend && user) {
22
+ if (user) {
58
23
  try {
59
24
  const token = getCookieValue("__client") || getCookieValue("__user");
60
25
  if (token) {
@@ -68,15 +33,20 @@ const SignOutButton = ({
68
33
  });
69
34
  }
70
35
  } catch (backendError) {
71
- console.warn("Backend sign-out failed, proceeding with client-side cleanup:", backendError);
36
+ console.warn("Backend sign-out failed, proceeding with logout:", backendError);
72
37
  }
73
38
  }
74
- await signOut(signOutOptions);
39
+ await signOut();
40
+ const origin = typeof window !== "undefined" ? window.location.origin : "";
41
+ const params = new URLSearchParams({
42
+ redirect_url: `${origin}${AFTER_SIGN_IN_URL}`
43
+ });
44
+ const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;
75
45
  onSignOutSuccess == null ? void 0 : onSignOutSuccess();
46
+ window.location.href = logoutUrl;
76
47
  } catch (error) {
77
48
  console.error("Sign out error:", error);
78
49
  onSignOutError == null ? void 0 : onSignOutError(error);
79
- } finally {
80
50
  setIsLoading(false);
81
51
  }
82
52
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/SignOutButton.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { useUser, SignOutOptions } from '../hooks/useUser';\nimport { baseApiUrl } from '../constants';\nimport { detectCabinIdSubdomain } from '../utils/subdomain';\nimport { SIGN_IN_URL, frontendApi } from '../constants';\n\n\nexport interface SignOutButtonProps {\n /**\n * Custom text to display on the button\n * @default \"Sign Out\"\n */\n children?: React.ReactNode;\n /**\n * Custom CSS class name\n */\n className?: string;\n /**\n * Sign out options\n */\n signOutOptions?: SignOutOptions;\n /**\n * Callback function called before sign out\n */\n onSignOutStart?: () => void;\n /**\n * Callback function called after successful sign out\n */\n onSignOutSuccess?: () => void;\n /**\n * Callback function called when sign out fails\n */\n onSignOutError?: (error: Error) => void;\n /**\n * Whether to show loading state\n * @default true\n */\n showLoading?: boolean;\n /**\n * Custom loading text\n * @default \"Signing out...\"\n */\n loadingText?: string;\n /**\n * Whether to call the backend sign-out endpoint\n * @default true\n */\n callBackend?: boolean;\n /**\n * CabinID subdomain for cross-domain logout\n * @example \"myapp\" for myapp.cabinid.dev\n */\n cabinIdSubdomain?: string;\n /**\n * Whether to use cross-domain logout flow\n * @default true\n */\n useCrossDomainLogout?: boolean;\n}\n\n/**\n * SignOutButton component that handles user logout with CabinID backend integration\n */\nexport const SignOutButton: React.FC<SignOutButtonProps> = ({\n children = 'Sign Out',\n className = 'px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50',\n signOutOptions,\n onSignOutStart,\n onSignOutSuccess,\n onSignOutError,\n showLoading = true,\n loadingText = 'Signing out...',\n callBackend = true,\n cabinIdSubdomain,\n useCrossDomainLogout = true,\n}) => {\n const { signOut, isSignedIn, user } = useUser();\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSignOut = async () => {\n if (isLoading || !isSignedIn) return;\n\n try {\n setIsLoading(true);\n onSignOutStart?.();\n\n // Cross-domain logout flow\n const subdomain = cabinIdSubdomain || detectCabinIdSubdomain();\n if (useCrossDomainLogout && subdomain) {\n // Call backend sign-out endpoint first\n if (callBackend && user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with logout:', backendError);\n }\n }\n\n // Clear local cookies and storage\n await signOut(() => {\n // Don't redirect yet, we'll handle it manually\n });\n\n // Redirect to CabinID logout page for complete cleanup\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const params = new URLSearchParams({\n redirect_url: `${origin}${SIGN_IN_URL}` || '/',\n });\n const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;\n \n onSignOutSuccess?.();\n window.location.href = logoutUrl;\n return;\n }\n\n // Standard logout flow (backward compatibility)\n if (callBackend && user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with client-side cleanup:', backendError);\n }\n }\n\n await signOut(signOutOptions);\n onSignOutSuccess?.();\n } catch (error) {\n console.error('Sign out error:', error);\n onSignOutError?.(error as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n // Helper function to get cookie value\n const getCookieValue = (name: string): string | null => {\n if (typeof window === 'undefined') return null;\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift() || null;\n }\n return null;\n };\n\n // Don't render if user is not signed in\n if (!isSignedIn) {\n return null;\n }\n\n return (\n <button\n onClick={handleSignOut}\n disabled={isLoading}\n className={className}\n type=\"button\"\n >\n {isLoading && showLoading ? loadingText : children}\n </button>\n );\n};"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/SignOutButton.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { useUser } from '../hooks/useUser';\nimport { baseApiUrl } from '../constants';\nimport { AFTER_SIGN_IN_URL, frontendApi } from '../constants';\n\nexport interface SignOutButtonProps {\n /**\n * Custom text to display on the button\n * @default \"Sign Out\"\n */\n children?: React.ReactNode;\n /**\n * Custom CSS class name\n */\n className?: string;\n /**\n * Callback function called before sign out\n */\n onSignOutStart?: () => void;\n /**\n * Callback function called after successful sign out\n */\n onSignOutSuccess?: () => void;\n /**\n * Callback function called when sign out fails\n */\n onSignOutError?: (error: Error) => void;\n /**\n * Whether to show loading state\n * @default true\n */\n showLoading?: boolean;\n /**\n * Custom loading text\n * @default \"Signing out...\"\n */\n loadingText?: string;\n}\n\n/**\n * SignOutButton component that handles user logout with CabinID backend integration\n */\nexport const SignOutButton: React.FC<SignOutButtonProps> = ({\n children = 'Sign Out',\n className = 'px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50',\n onSignOutStart,\n onSignOutSuccess,\n onSignOutError,\n showLoading = true,\n loadingText = 'Signing out...',\n}) => {\n const { signOut, isSignedIn, user } = useUser();\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSignOut = async () => {\n if (isLoading || !isSignedIn) return;\n\n try {\n setIsLoading(true);\n onSignOutStart?.();\n\n // 1. Call backend sign-out endpoint first\n if (user) {\n try {\n const token = getCookieValue('__client') || getCookieValue('__user');\n if (token) {\n await fetch(`${baseApiUrl}/auth/sign-out`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : '',\n },\n });\n }\n } catch (backendError) {\n console.warn('Backend sign-out failed, proceeding with logout:', backendError);\n }\n }\n\n // 2. Clear local cookies and storage\n await signOut();\n\n // 3. Redirect to CabinID logout page with redirect_url\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const params = new URLSearchParams({\n redirect_url: `${origin}${AFTER_SIGN_IN_URL}`,\n });\n const logoutUrl = `https://${frontendApi}.cabinid.dev/logout?${params.toString()}`;\n \n onSignOutSuccess?.();\n window.location.href = logoutUrl;\n } catch (error) {\n console.error('Sign out error:', error);\n onSignOutError?.(error as Error);\n setIsLoading(false);\n }\n };\n\n // Helper function to get cookie value\n const getCookieValue = (name: string): string | null => {\n if (typeof window === 'undefined') return null;\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift() || null;\n }\n return null;\n };\n\n // Don't render if user is not signed in\n if (!isSignedIn) {\n return null;\n }\n\n return (\n <button\n onClick={handleSignOut}\n disabled={isLoading}\n className={className}\n type=\"button\"\n >\n {isLoading && showLoading ? loadingText : children}\n </button>\n );\n};"],"mappings":";AAEA,OAAO,SAAS,gBAAgB;AAChC,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB,mBAAmB;AAuCxC,MAAM,gBAA8C,CAAC;AAAA,EAC1D,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAChB,MAAM;AACJ,QAAM,EAAE,SAAS,YAAY,KAAK,IAAI,QAAQ;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,gBAAgB,YAAY;AAChC,QAAI,aAAa,CAAC,WAAY;AAE9B,QAAI;AACF,mBAAa,IAAI;AACjB;AAGA,UAAI,MAAM;AACR,YAAI;AACF,gBAAM,QAAQ,eAAe,UAAU,KAAK,eAAe,QAAQ;AACnE,cAAI,OAAO;AACT,kBAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,cACzC,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,gBAAgB;AAAA,gBAChB,iBAAiB,UAAU,KAAK;AAAA,gBAChC,UAAU,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AAAA,cACrE;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,SAAS,cAAc;AACrB,kBAAQ,KAAK,oDAAoD,YAAY;AAAA,QAC/E;AAAA,MACF;AAGA,YAAM,QAAQ;AAGd,YAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,cAAc,GAAG,MAAM,GAAG,iBAAiB;AAAA,MAC7C,CAAC;AACD,YAAM,YAAY,WAAW,WAAW,uBAAuB,OAAO,SAAS,CAAC;AAEhF;AACA,aAAO,SAAS,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,uDAAiB;AACjB,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,iBAAiB,CAAC,SAAgC;AAtG1D;AAuGI,QAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,UAAM,QAAQ,KAAK,SAAS,MAAM;AAClC,UAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,GAAG;AACtC,QAAI,MAAM,WAAW,GAAG;AACtB,eAAO,WAAM,IAAI,MAAV,mBAAa,MAAM,KAAK,YAAW;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,MAAK;AAAA;AAAA,IAEJ,aAAa,cAAc,cAAc;AAAA,EAC5C;AAEJ;","names":[]}
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import { SignOutOptions } from '../hooks/useUser';
3
2
  export interface SignOutButtonProps {
4
3
  /**
5
4
  * Custom text to display on the button
@@ -10,10 +9,6 @@ export interface SignOutButtonProps {
10
9
  * Custom CSS class name
11
10
  */
12
11
  className?: string;
13
- /**
14
- * Sign out options
15
- */
16
- signOutOptions?: SignOutOptions;
17
12
  /**
18
13
  * Callback function called before sign out
19
14
  */
@@ -36,21 +31,6 @@ export interface SignOutButtonProps {
36
31
  * @default "Signing out..."
37
32
  */
38
33
  loadingText?: string;
39
- /**
40
- * Whether to call the backend sign-out endpoint
41
- * @default true
42
- */
43
- callBackend?: boolean;
44
- /**
45
- * CabinID subdomain for cross-domain logout
46
- * @example "myapp" for myapp.cabinid.dev
47
- */
48
- cabinIdSubdomain?: string;
49
- /**
50
- * Whether to use cross-domain logout flow
51
- * @default true
52
- */
53
- useCrossDomainLogout?: boolean;
54
34
  }
55
35
  /**
56
36
  * SignOutButton component that handles user logout with CabinID backend integration
@@ -1 +1 @@
1
- {"version":3,"file":"SignOutButton.d.ts","sourceRoot":"","sources":["../../../src/components/SignOutButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,EAAW,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAM3D,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqHtD,CAAC"}
1
+ {"version":3,"file":"SignOutButton.d.ts","sourceRoot":"","sources":["../../../src/components/SignOutButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAmFtD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cabin-id/nextjs",
3
3
  "description": "NextJS SDK for CabinID",
4
- "version": "1.2.3",
4
+ "version": "1.2.4",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "author": "CabinVN",