create-openfort 0.1.8 → 0.1.10

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +16 -16
  3. package/package.json +1 -1
  4. package/template/backend/package.json +7 -1
  5. package/template/backend/pnpm-lock.yaml +187 -33
  6. package/template/backend/src/app.ts +1 -1
  7. package/template/openfort-templates/firebase/biome.json +3 -3
  8. package/template/openfort-templates/firebase/package.json +1 -1
  9. package/template/openfort-templates/firebase/src/App.tsx +10 -10
  10. package/template/openfort-templates/firebase/src/components/cards/head.tsx +157 -145
  11. package/template/openfort-templates/firebase/src/components/cards/main.tsx +63 -52
  12. package/template/openfort-templates/firebase/src/components/ui/Sheet.tsx +14 -16
  13. package/template/openfort-templates/firebase/src/components/ui/Tabs.tsx +46 -36
  14. package/template/openfort-templates/firebase/src/components/ui/TruncateData.tsx +14 -8
  15. package/template/openfort-templates/firebase/src/integrations/firebase/client.ts +6 -6
  16. package/template/openfort-templates/firebase/src/integrations/firebase/components/FirebaseAuthCard.tsx +74 -46
  17. package/template/openfort-templates/firebase/src/integrations/firebase/errors.ts +57 -37
  18. package/template/openfort-templates/firebase/src/integrations/firebase/index.ts +3 -3
  19. package/template/openfort-templates/firebase/src/integrations/openfort/index.ts +1 -1
  20. package/template/openfort-templates/firebase/src/integrations/openfort/providers.tsx +23 -11
  21. package/template/openfort-templates/firebase/src/ui/openfort/blockchain/ActionsCard.tsx +47 -35
  22. package/template/openfort-templates/firebase/src/ui/openfort/blockchain/SignCard.tsx +30 -28
  23. package/template/openfort-templates/firebase/src/ui/openfort/index.ts +4 -6
  24. package/template/openfort-templates/firebase/src/ui/openfort/profile/UserProfileCard.tsx +32 -20
  25. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletCreation.tsx +51 -27
  26. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletListCard.tsx +66 -40
  27. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletPasswordSheets.tsx +65 -41
  28. package/template/openfort-templates/firebase/vite.config.ts +3 -3
  29. package/template/openfort-templates/headless/biome.json +3 -3
  30. package/template/openfort-templates/headless/package.json +1 -1
  31. package/template/openfort-templates/headless/src/components/cards/auth.tsx +2 -2
  32. package/template/openfort-templates/headless/src/components/cards/profile.tsx +1 -3
  33. package/template/openfort-templates/headless/src/components/providers.tsx +4 -1
  34. package/template/openfort-templates/headless/src/index.css +10 -4
  35. package/template/openfort-templates/openfort-ui/biome.json +3 -3
  36. package/template/openfort-templates/openfort-ui/package.json +1 -1
  37. package/template/openfort-templates/openfort-ui/src/App.tsx +1 -3
  38. package/template/openfort-templates/openfort-ui/src/components/cards/auth.tsx +9 -11
  39. package/template/openfort-templates/openfort-ui/src/components/cards/head.tsx +157 -145
  40. package/template/openfort-templates/openfort-ui/src/components/cards/main.tsx +50 -41
  41. package/template/openfort-templates/openfort-ui/src/components/cards/profile.tsx +29 -35
  42. package/template/openfort-templates/openfort-ui/src/components/cards/sign.tsx +35 -49
  43. package/template/openfort-templates/openfort-ui/src/components/cards/wallets.tsx +51 -37
  44. package/template/openfort-templates/openfort-ui/src/components/createWallet.tsx +63 -30
  45. package/template/openfort-templates/openfort-ui/src/components/passwordRecovery.tsx +61 -56
  46. package/template/openfort-templates/openfort-ui/src/components/providers.tsx +14 -15
  47. package/template/openfort-templates/openfort-ui/src/components/ui/Sheet.tsx +14 -16
  48. package/template/openfort-templates/openfort-ui/src/components/ui/Tabs.tsx +46 -36
  49. package/template/openfort-templates/openfort-ui/src/components/ui/TruncateData.tsx +14 -8
  50. package/template/openfort-templates/openfort-ui/vite.config.ts +2 -2
@@ -1,23 +1,39 @@
1
- import { HomeIcon, PencilIcon, PlayIcon, WalletIcon } from "@heroicons/react/24/outline";
2
- import { useState } from "react";
3
- import { DesktopTabGroup, MobileTabGroup, type TabType } from "../ui/Tabs";
4
- import { FirebaseAuthCard } from "../../integrations/firebase";
5
- import { ActionsCard, SignCard, UserProfileCard, WalletListCard } from "../../ui/openfort";
6
- import { Head } from "./head";
7
- import { useUser } from "@openfort/react";
8
- import { useAccount } from "wagmi";
1
+ import {
2
+ HomeIcon,
3
+ PencilIcon,
4
+ PlayIcon,
5
+ WalletIcon,
6
+ } from '@heroicons/react/24/outline'
7
+ import { useUser } from '@openfort/react'
8
+ import { useState } from 'react'
9
+ import { useAccount } from 'wagmi'
10
+ import { FirebaseAuthCard } from '../../integrations/firebase'
11
+ import {
12
+ ActionsCard,
13
+ SignCard,
14
+ UserProfileCard,
15
+ WalletListCard,
16
+ } from '../../ui/openfort'
17
+ import { DesktopTabGroup, MobileTabGroup, type TabType } from '../ui/Tabs'
18
+ import { Head } from './head'
9
19
 
10
20
  interface LayoutProps {
11
- children: React.ReactNode;
12
- step: number;
13
- tabs?: TabType[];
14
- currentTab?: TabType;
15
- setCurrentTab?: (tab: TabType) => void;
16
- showTabs?: boolean;
21
+ children: React.ReactNode
22
+ step: number
23
+ tabs?: TabType[]
24
+ currentTab?: TabType
25
+ setCurrentTab?: (tab: TabType) => void
26
+ showTabs?: boolean
17
27
  }
18
28
 
19
- const Layout = ({ children, step, tabs, currentTab, setCurrentTab, showTabs }: LayoutProps) => {
20
-
29
+ const Layout = ({
30
+ children,
31
+ step,
32
+ tabs,
33
+ currentTab,
34
+ setCurrentTab,
35
+ showTabs,
36
+ }: LayoutProps) => {
21
37
  return (
22
38
  <div className="min-h-screen min-w-screen bg-zinc-900 flex flex-col items-center justify-center">
23
39
  <div className="relative">
@@ -27,12 +43,12 @@ const Layout = ({ children, step, tabs, currentTab, setCurrentTab, showTabs }: L
27
43
  setCurrentTab={setCurrentTab}
28
44
  showTabs={showTabs}
29
45
  />
30
- <div
31
- className="w-(--card-group-width) layout-card-group"
32
- >
46
+ <div className="w-(--card-group-width) layout-card-group">
33
47
  <div
34
48
  className="h-(--card-group-height) grid grid-flow-col auto-cols-max transition-transform duration-500"
35
- style={{ transform: `translateX(calc(-${step} * var(--card-width)))` }}
49
+ style={{
50
+ transform: `translateX(calc(-${step} * var(--card-width)))`,
51
+ }}
36
52
  >
37
53
  {children}
38
54
  </div>
@@ -42,15 +58,14 @@ const Layout = ({ children, step, tabs, currentTab, setCurrentTab, showTabs }: L
42
58
  )
43
59
  }
44
60
 
45
-
46
61
  export const Main = () => {
47
- const {isConnected} = useAccount();
48
- const { isAuthenticated } = useUser();
49
- const [step, setStep] = useState(0);
62
+ const { isConnected } = useAccount()
63
+ const { isAuthenticated } = useUser()
64
+ const [step, setStep] = useState(0)
50
65
 
51
66
  const tabs: TabType[] = [
52
67
  {
53
- name: "Home",
68
+ name: 'Home',
54
69
  component: (
55
70
  <UserProfileCard
56
71
  sampleGithubUrl="https://github.com/openfort-xyz/quickstarts/tree/main/react/firebase"
@@ -60,22 +75,22 @@ export const Main = () => {
60
75
  icon: HomeIcon,
61
76
  },
62
77
  {
63
- name: "Signatures",
78
+ name: 'Signatures',
64
79
  component: <SignCard />,
65
- icon: PencilIcon
80
+ icon: PencilIcon,
66
81
  },
67
82
  {
68
- name: "Actions",
83
+ name: 'Actions',
69
84
  component: <ActionsCard />,
70
85
  icon: PlayIcon,
71
86
  },
72
87
  {
73
- name: "Wallets",
88
+ name: 'Wallets',
74
89
  component: <WalletListCard />,
75
90
  icon: WalletIcon,
76
91
  },
77
- ];
78
- const [currentTab, setCurrentTab] = useState<TabType>(tabs[0]);
92
+ ]
93
+ const [currentTab, setCurrentTab] = useState<TabType>(tabs[0])
79
94
 
80
95
  return (
81
96
  <Layout
@@ -88,31 +103,27 @@ export const Main = () => {
88
103
  <Head
89
104
  onStart={() => setStep(1)}
90
105
  sample="Firebase"
91
- color='rgb(255, 50, 0)'
92
- backgroundColor='rgb(255, 145, 0)'
106
+ color="rgb(255, 50, 0)"
107
+ backgroundColor="rgb(255, 145, 0)"
93
108
  logo="/firebase.svg"
94
109
  href="https://firebase.google.com/"
95
110
  subtitle="Example of integration of Openfort with Firebase Authentication"
96
111
  />
97
- {
98
- !isAuthenticated ? (
99
- <FirebaseAuthCard />
100
- ) : (
101
- <div className="block relative overflow-y-auto overflow-x-hidden">
102
- <div className="card flex-col min-h-full">
103
- <div className="w-full flex-1 flex">
104
- {currentTab.component}
105
- </div>
106
- <MobileTabGroup
107
- tabs={tabs}
108
- currentTab={currentTab}
109
- setCurrentTab={setCurrentTab}
110
- />
111
- </div>
112
+ {!isAuthenticated ? (
113
+ <FirebaseAuthCard />
114
+ ) : (
115
+ <div className="block relative overflow-y-auto overflow-x-hidden">
116
+ <div className="card flex-col min-h-full">
117
+ <div className="w-full flex-1 flex">{currentTab.component}</div>
118
+ <MobileTabGroup
119
+ tabs={tabs}
120
+ currentTab={currentTab}
121
+ setCurrentTab={setCurrentTab}
122
+ />
112
123
  </div>
113
- )
114
- }
124
+ </div>
125
+ )}
115
126
  <div className="card relative" />
116
127
  </Layout>
117
- );
118
- };
128
+ )
129
+ }
@@ -1,22 +1,22 @@
1
- import { ChevronLeftIcon } from "@heroicons/react/24/outline";
2
- import { useEffect, useState } from "react";
1
+ import { ChevronLeftIcon } from '@heroicons/react/24/outline'
2
+ import { useEffect, useState } from 'react'
3
3
 
4
4
  type SheetProps = {
5
- open: boolean,
6
- onClose: () => void,
7
- title: string,
8
- description: string,
5
+ open: boolean
6
+ onClose: () => void
7
+ title: string
8
+ description: string
9
9
  children: React.ReactNode
10
- };
10
+ }
11
11
 
12
12
  const SheetInner = ({ onClose, title, description, children }: SheetProps) => {
13
- const [isClosing, setIsClosing] = useState(false);
13
+ const [isClosing, setIsClosing] = useState(false)
14
14
  useEffect(() => {
15
15
  if (isClosing) {
16
- const timer = setTimeout(onClose, 300);
17
- return () => clearTimeout(timer);
16
+ const timer = setTimeout(onClose, 300)
17
+ return () => clearTimeout(timer)
18
18
  }
19
- }, [isClosing, onClose]);
19
+ }, [isClosing, onClose])
20
20
 
21
21
  return (
22
22
  <div
@@ -41,9 +41,7 @@ const SheetInner = ({ onClose, title, description, children }: SheetProps) => {
41
41
  }
42
42
 
43
43
  export const Sheet = (props: SheetProps) => {
44
- if (!props.open) return null;
44
+ if (!props.open) return null
45
45
 
46
- return (
47
- <SheetInner {...props} />
48
- )
49
- }
46
+ return <SheetInner {...props} />
47
+ }
@@ -1,22 +1,26 @@
1
1
  export type TabType = {
2
- name: string;
3
- component: React.ReactNode;
4
- icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
5
- };
2
+ name: string
3
+ component: React.ReactNode
4
+ icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
5
+ }
6
6
 
7
7
  type TabProps = {
8
- onClick?: () => void;
9
- isActive?: boolean;
10
- } & TabType;
8
+ onClick?: () => void
9
+ isActive?: boolean
10
+ } & TabType
11
11
 
12
12
  const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
13
13
  return (
14
14
  <button
15
15
  className="relative h-8 mx-2.5 transition-colors cursor-pointer"
16
- style={{
17
- "--tab-bg-color": isActive ? "var(--color-zinc-800)" : "var(--color-zinc-700)",
18
- opacity: isActive ? 1 : 0.6,
19
- } as React.CSSProperties}
16
+ style={
17
+ {
18
+ '--tab-bg-color': isActive
19
+ ? 'var(--color-zinc-800)'
20
+ : 'var(--color-zinc-700)',
21
+ opacity: isActive ? 1 : 0.6,
22
+ } as React.CSSProperties
23
+ }
20
24
  {...buttonProps}
21
25
  >
22
26
  <div className="absolute w-5 h-8 bg-(--tab-bg-color) rotate-20 transform origin-top-left top-1" />
@@ -24,7 +28,7 @@ const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
24
28
  <div className="absolute inset-0 rounded-md bg-(--tab-bg-color)" />
25
29
 
26
30
  <span
27
- className={`${isActive ? "text-white" : "text-zinc-400"} whitespace-nowrap bg-(--tab-bg-color) z-10 relative mx-2 pb-4`}
31
+ className={`${isActive ? 'text-white' : 'text-zinc-400'} whitespace-nowrap bg-(--tab-bg-color) z-10 relative mx-2 pb-4`}
28
32
  >
29
33
  {name}
30
34
  </span>
@@ -33,25 +37,30 @@ const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
33
37
  }
34
38
 
35
39
  type TabGroupProps = {
36
- tabs: TabType[],
37
- currentTab?: TabType,
40
+ tabs: TabType[]
41
+ currentTab?: TabType
38
42
  setCurrentTab?: (tab: TabType) => void
39
43
  showTabs?: boolean
40
44
  }
41
45
 
42
- export const DesktopTabGroup = ({ tabs, currentTab, setCurrentTab, showTabs }: TabGroupProps) => {
46
+ export const DesktopTabGroup = ({
47
+ tabs,
48
+ currentTab,
49
+ setCurrentTab,
50
+ showTabs,
51
+ }: TabGroupProps) => {
43
52
  return (
44
- <div
45
- className="absolute left-[100%] top-2 rotate-90 transform origin-top-left hidden xs:block"
46
- >
53
+ <div className="absolute left-[100%] top-2 rotate-90 transform origin-top-left hidden xs:block">
47
54
  <div
48
55
  className="flex gap-2 transition-transform duration-500"
49
- style={{ transform: showTabs ? "translateY(-100%)" : "translateY(10px)" }}
56
+ style={{
57
+ transform: showTabs ? 'translateY(-100%)' : 'translateY(10px)',
58
+ }}
50
59
  >
51
60
  {tabs?.map((tab) => (
52
61
  <DesktopTab
53
62
  key={tab.name}
54
- onClick={() => setCurrentTab && setCurrentTab(tab)}
63
+ onClick={() => setCurrentTab?.(tab)}
55
64
  isActive={currentTab?.name === tab.name}
56
65
  {...tab}
57
66
  />
@@ -61,9 +70,12 @@ export const DesktopTabGroup = ({ tabs, currentTab, setCurrentTab, showTabs }: T
61
70
  )
62
71
  }
63
72
 
64
-
65
-
66
- const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) => {
73
+ const MobileTab = ({
74
+ name,
75
+ isActive,
76
+ icon: Icon,
77
+ ...buttonProps
78
+ }: TabProps) => {
67
79
  return (
68
80
  <button
69
81
  className="relative h-8 mx-2.5 transition-colors cursor-pointer"
@@ -71,7 +83,7 @@ const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) =>
71
83
  >
72
84
  <Icon className="h-5 w-5 mx-auto mb-1" />
73
85
  <span
74
- className={`${isActive ? "text-white" : "text-zinc-400"} whitespace-nowrap`}
86
+ className={`${isActive ? 'text-white' : 'text-zinc-400'} whitespace-nowrap`}
75
87
  >
76
88
  {name}
77
89
  </span>
@@ -82,20 +94,18 @@ const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) =>
82
94
  export const MobileTabGroup = ({
83
95
  tabs,
84
96
  currentTab,
85
- setCurrentTab
97
+ setCurrentTab,
86
98
  }: TabGroupProps) => {
87
99
  return (
88
100
  <div className="mt-auto xs:hidden flex pt-6 pb-2 items-end justify-between text-zinc-400 text-sm">
89
- {
90
- tabs?.map((tab) => (
91
- <MobileTab
92
- key={tab.name}
93
- onClick={() => setCurrentTab && setCurrentTab(tab)}
94
- isActive={currentTab?.name === tab.name}
95
- {...tab}
96
- />
97
- ))
98
- }
101
+ {tabs?.map((tab) => (
102
+ <MobileTab
103
+ key={tab.name}
104
+ onClick={() => setCurrentTab?.(tab)}
105
+ isActive={currentTab?.name === tab.name}
106
+ {...tab}
107
+ />
108
+ ))}
99
109
  </div>
100
110
  )
101
- }
111
+ }
@@ -1,14 +1,20 @@
1
- import { useState } from "react"
1
+ import { useState } from 'react'
2
2
 
3
- export const TruncateData = ({ className, data }: { className?: string; data?: string }) => {
3
+ export const TruncateData = ({
4
+ className,
5
+ data,
6
+ }: {
7
+ className?: string
8
+ data?: string
9
+ }) => {
4
10
  const [viewMore, setViewMore] = useState(false)
5
11
  if (!data) return null
6
12
 
7
13
  return (
8
- <div className={`mt-4 p-2 border border-zinc-700 rounded bg-zinc-900 ${className}`}>
9
- <pre
10
- className="break-words whitespace-normal text-sm"
11
- >
14
+ <div
15
+ className={`mt-4 p-2 border border-zinc-700 rounded bg-zinc-900 ${className}`}
16
+ >
17
+ <pre className="break-words whitespace-normal text-sm">
12
18
  {viewMore ? data : data.length > 90 ? `${data.slice(0, 90)}...` : data}
13
19
  </pre>
14
20
  {data.length > 90 && (
@@ -17,9 +23,9 @@ export const TruncateData = ({ className, data }: { className?: string; data?: s
17
23
  onClick={() => setViewMore(!viewMore)}
18
24
  type="button"
19
25
  >
20
- {viewMore ? "View less" : "View more"}
26
+ {viewMore ? 'View less' : 'View more'}
21
27
  </button>
22
28
  )}
23
29
  </div>
24
30
  )
25
- }
31
+ }
@@ -1,5 +1,5 @@
1
- import { initializeApp } from "firebase/app";
2
- import { getAuth } from "firebase/auth";
1
+ import { initializeApp } from 'firebase/app'
2
+ import { getAuth } from 'firebase/auth'
3
3
 
4
4
  const firebaseConfig = {
5
5
  apiKey: import.meta.env.VITE_apiKey,
@@ -8,13 +8,13 @@ const firebaseConfig = {
8
8
  storageBucket: import.meta.env.VITE_storageBucket,
9
9
  messagingSenderId: import.meta.env.VITE_messagingSenderId,
10
10
  appId: import.meta.env.VITE_appId,
11
- };
11
+ }
12
12
 
13
13
  // Initialize Firebase
14
- const app = initializeApp(firebaseConfig);
14
+ const app = initializeApp(firebaseConfig)
15
15
 
16
16
  // Initialize Firebase Authentication and get a reference to the service
17
- const auth = getAuth(app);
17
+ const auth = getAuth(app)
18
18
 
19
19
  // Export the Firebase auth object and any other services you initialize
20
- export { auth, };
20
+ export { auth }
@@ -1,24 +1,29 @@
1
- import { createUserWithEmailAndPassword, GoogleAuthProvider, signInWithEmailAndPassword, signInWithPopup } from "firebase/auth";
2
- import { useState } from "react";
1
+ import {
2
+ createUserWithEmailAndPassword,
3
+ GoogleAuthProvider,
4
+ signInWithEmailAndPassword,
5
+ signInWithPopup,
6
+ } from 'firebase/auth'
7
+ import { useState } from 'react'
3
8
 
4
- import { auth } from "../client";
5
- import { getFirebaseErrorMessage, logFirebaseError } from "../errors";
9
+ import { auth } from '../client'
10
+ import { getFirebaseErrorMessage, logFirebaseError } from '../errors'
6
11
 
7
12
  function GoogleSignInButton({ onError }: { onError: (error: string) => void }) {
8
- const [loading, setLoading] = useState(false);
13
+ const [loading, setLoading] = useState(false)
9
14
 
10
15
  const signInWithGoogle = async () => {
11
16
  try {
12
- setLoading(true);
13
- const provider = new GoogleAuthProvider();
14
- await signInWithPopup(auth, provider);
17
+ setLoading(true)
18
+ const provider = new GoogleAuthProvider()
19
+ await signInWithPopup(auth, provider)
15
20
  } catch (error) {
16
- logFirebaseError(error, "Google Sign-In");
17
- onError(getFirebaseErrorMessage(error));
21
+ logFirebaseError(error, 'Google Sign-In')
22
+ onError(getFirebaseErrorMessage(error))
18
23
  } finally {
19
- setLoading(false);
24
+ setLoading(false)
20
25
  }
21
- };
26
+ }
22
27
 
23
28
  return (
24
29
  <button
@@ -26,77 +31,97 @@ function GoogleSignInButton({ onError }: { onError: (error: string) => void }) {
26
31
  disabled={loading}
27
32
  className="w-full py-2 px-4 border border-zinc-700 text-white rounded cursor-pointer transition-colors hover:bg-zinc-900/60 disabled:opacity-50 disabled:cursor-not-allowed"
28
33
  >
29
- {loading ? "Signing in..." : "Continue with Google"}
34
+ {loading ? 'Signing in...' : 'Continue with Google'}
30
35
  </button>
31
- );
36
+ )
32
37
  }
33
38
 
34
39
  function EmailPasswordForm({
35
40
  isLogin,
36
41
  onError,
37
42
  }: {
38
- isLogin: boolean;
39
- onError: (error: string) => void;
43
+ isLogin: boolean
44
+ onError: (error: string) => void
40
45
  }) {
41
- const [loading, setLoading] = useState(false);
46
+ const [loading, setLoading] = useState(false)
42
47
 
43
48
  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
44
- event.preventDefault();
45
- const form = event.target as HTMLFormElement;
46
- const email = (form.elements[0] as HTMLInputElement).value;
47
- const password = (form.elements[1] as HTMLInputElement).value;
49
+ event.preventDefault()
50
+ const form = event.target as HTMLFormElement
51
+ const email = (form.elements[0] as HTMLInputElement).value
52
+ const password = (form.elements[1] as HTMLInputElement).value
48
53
 
49
54
  try {
50
- setLoading(true);
51
- onError("");
55
+ setLoading(true)
56
+ onError('')
52
57
  if (isLogin) {
53
- await signInWithEmailAndPassword(auth, email, password);
58
+ await signInWithEmailAndPassword(auth, email, password)
54
59
  } else {
55
- await createUserWithEmailAndPassword(auth, email, password);
60
+ await createUserWithEmailAndPassword(auth, email, password)
56
61
  }
57
62
  } catch (error) {
58
- logFirebaseError(error, isLogin ? "Email Sign-In" : "Email Sign-Up");
59
- onError(getFirebaseErrorMessage(error));
63
+ logFirebaseError(error, isLogin ? 'Email Sign-In' : 'Email Sign-Up')
64
+ onError(getFirebaseErrorMessage(error))
60
65
  } finally {
61
- setLoading(false);
66
+ setLoading(false)
62
67
  }
63
- };
68
+ }
64
69
 
65
70
  return (
66
71
  <form onSubmit={handleSubmit} className="space-y-4 mb-4">
67
- <label className="block text-left text-sm font-medium mb-1" htmlFor="email">
72
+ <label
73
+ className="block text-left text-sm font-medium mb-1"
74
+ htmlFor="email"
75
+ >
68
76
  Email
69
77
  </label>
70
- <input id="email" type="email" placeholder="Enter your email address" required />
78
+ <input
79
+ id="email"
80
+ type="email"
81
+ placeholder="Enter your email address"
82
+ required
83
+ />
71
84
 
72
85
  <div>
73
- <label className="block text-left text-sm font-medium mb-1" htmlFor="password">
86
+ <label
87
+ className="block text-left text-sm font-medium mb-1"
88
+ htmlFor="password"
89
+ >
74
90
  Password
75
91
  </label>
76
- <input id="password" type="password" placeholder="Enter your password" required />
92
+ <input
93
+ id="password"
94
+ type="password"
95
+ placeholder="Enter your password"
96
+ required
97
+ />
77
98
  </div>
78
99
 
79
- <button type="submit" disabled={loading} className="btn mt-2 disabled:opacity-50 disabled:cursor-not-allowed">
80
- {loading ? "Loading..." : isLogin ? "Sign In" : "Sign Up"}
100
+ <button
101
+ type="submit"
102
+ disabled={loading}
103
+ className="btn mt-2 disabled:opacity-50 disabled:cursor-not-allowed"
104
+ >
105
+ {loading ? 'Loading...' : isLogin ? 'Sign In' : 'Sign Up'}
81
106
  </button>
82
107
  </form>
83
- );
108
+ )
84
109
  }
85
110
 
86
111
  export function FirebaseAuthCard() {
87
- const [isLogin, setIsLogin] = useState(true);
88
- const [error, setError] = useState<string>("");
112
+ const [isLogin, setIsLogin] = useState(true)
113
+ const [error, setError] = useState<string>('')
89
114
 
90
115
  const handleToggleMode = () => {
91
- setIsLogin((previous) => !previous);
92
- setError("");
93
- };
116
+ setIsLogin((previous) => !previous)
117
+ setError('')
118
+ }
94
119
 
95
120
  return (
96
121
  <div className="card relative space-y-6">
97
122
  <div className="relative">
98
123
  <h1 className="text-left text-2xl font-semibold tracking-tight">
99
- {isLogin ? "Sign in to account" : "Create an account"}
124
+ {isLogin ? 'Sign in to account' : 'Create an account'}
100
125
  </h1>
101
126
  </div>
102
127
 
@@ -120,11 +145,14 @@ export function FirebaseAuthCard() {
120
145
  <GoogleSignInButton onError={setError} />
121
146
 
122
147
  <div className="text-left text-sm">
123
- {isLogin ? "Already have an account? " : "Don't have an account? "}
124
- <button onClick={handleToggleMode} className="text-primary hover:underline cursor-pointer font-medium">
125
- {isLogin ? "Sign Up" : "Sign In"}
148
+ {isLogin ? 'Already have an account? ' : "Don't have an account? "}
149
+ <button
150
+ onClick={handleToggleMode}
151
+ className="text-primary hover:underline cursor-pointer font-medium"
152
+ >
153
+ {isLogin ? 'Sign Up' : 'Sign In'}
126
154
  </button>
127
155
  </div>
128
156
  </div>
129
- );
157
+ )
130
158
  }