@forge-connect/react 0.1.0
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/dist/index.cjs +1179 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +310 -0
- package/dist/index.d.ts +310 -0
- package/dist/index.js +1149 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +443 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/api/client.ts","../src/utils.ts","../src/hooks/use-forge-connect.ts","../src/components/modal-overlay.tsx","../src/components/tabs/email-password.tsx","../src/components/tabs/email-otp.tsx","../src/components/tabs/wallet-connect.tsx","../src/components/tabs/oauth-buttons.tsx","../src/components/login-modal.tsx","../src/components/login-button.tsx","../src/hooks/use-user.ts","../src/hooks/use-wallets.ts","../src/hooks/use-sessions.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, type ReactNode } from 'react';\nimport { ForgeConnectContext, type ForgeConnectContextValue } from './context';\nimport { createApiClient, ForgeConnectApiError } from './api/client';\nimport type { AuthState, ModalState, ForgeConnectConfig, User, ModalStep } from './types';\nimport { getStoredToken, setStoredToken, removeStoredToken, getRefreshDelay } from './utils';\nimport { LoginModal } from './components/login-modal';\n\ninterface ForgeConnectProviderProps {\n config: ForgeConnectConfig;\n children: ReactNode;\n /** Called when user successfully authenticates */\n onLogin?: (user: User) => void;\n /** Called when user logs out */\n onLogout?: () => void;\n}\n\nexport function ForgeConnectProvider({ config, children, onLogin, onLogout }: ForgeConnectProviderProps) {\n const [auth, setAuth] = useState<AuthState>({\n status: 'loading',\n user: null,\n accessToken: null,\n });\n\n const [modal, setModal] = useState<ModalState>({\n isOpen: false,\n step: 'method-select',\n });\n\n const apiRef = useRef(createApiClient(config.apiUrl));\n const refreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const api = apiRef.current;\n\n // ── Token Refresh Scheduling ──\n\n const scheduleRefresh = useCallback((token: string) => {\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n const delay = getRefreshDelay(token);\n if (delay === null) return;\n\n refreshTimerRef.current = setTimeout(async () => {\n try {\n const { accessToken } = await api.refresh();\n setStoredToken(accessToken);\n setAuth((prev) => ({ ...prev, accessToken }));\n scheduleRefresh(accessToken);\n } catch {\n // Refresh failed — log user out\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n }, delay);\n }, [api]);\n\n // ── Initialize from stored token ──\n\n useEffect(() => {\n const init = async () => {\n const token = getStoredToken();\n if (!token) {\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n return;\n }\n\n try {\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n } catch (err) {\n // Token expired — try refresh\n if (err instanceof ForgeConnectApiError && err.status === 401) {\n try {\n const { accessToken } = await api.refresh();\n const user = await api.getMe(accessToken);\n setStoredToken(accessToken);\n setAuth({ status: 'authenticated', user, accessToken });\n scheduleRefresh(accessToken);\n } catch {\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n } else {\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n }\n };\n init();\n\n return () => {\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n };\n }, [api, scheduleRefresh]);\n\n // ── OAuth popup/callback handler ──\n\n useEffect(() => {\n // Check if THIS window is the OAuth callback popup\n if (window.location.pathname === '/__fc_oauth_callback') {\n const params = new URLSearchParams(window.location.search);\n const token = params.get('fc_token');\n if (token && window.opener) {\n window.opener.postMessage(\n { type: 'fc_oauth_callback', accessToken: token },\n window.location.origin,\n );\n window.close();\n return;\n }\n }\n\n // Listen for messages from OAuth popup\n const handleMessage = async (event: MessageEvent) => {\n if (event.origin !== window.location.origin) return;\n if (event.data?.type !== 'fc_oauth_callback') return;\n\n const token = event.data.accessToken as string;\n if (!token) return;\n\n setStoredToken(token);\n try {\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n setModal({ isOpen: false, step: 'method-select' });\n onLogin?.(user);\n } catch {\n removeStoredToken();\n }\n };\n\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [api, config.apiUrl, scheduleRefresh, onLogin]);\n\n // ── Auth Actions ──\n\n const handleAuthSuccess = useCallback(\n async (token: string) => {\n setStoredToken(token);\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n setModal({ isOpen: false, step: 'method-select' });\n onLogin?.(user);\n },\n [api, scheduleRefresh, onLogin],\n );\n\n const loginWithEmail = useCallback(\n async (email: string, password: string) => {\n const { accessToken } = await api.login(email, password);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const register = useCallback(\n async (email: string, password: string, displayName?: string) => {\n await api.register(email, password, displayName);\n // Registration sends verification email, no token returned\n },\n [api],\n );\n\n const sendOtp = useCallback(\n async (email: string) => {\n await api.sendOtp(email);\n },\n [api],\n );\n\n const verifyOtp = useCallback(\n async (email: string, code: string) => {\n const { accessToken } = await api.verifyOtp(email, code);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const loginWithWallet = useCallback(\n async (\n walletAddress: string,\n signMessage: (message: Uint8Array) => Promise<Uint8Array>,\n chain: string = 'solana',\n ) => {\n const { challengeId, nonce } = await api.walletChallenge(walletAddress, chain);\n const message = new TextEncoder().encode(nonce);\n const signatureBytes = await signMessage(message);\n // Convert Uint8Array to base58 for Solana\n const signature = chain === 'solana'\n ? uint8ArrayToBase58(signatureBytes)\n : Array.from(signatureBytes).map((b) => b.toString(16).padStart(2, '0')).join('');\n const { accessToken } = await api.walletVerify(challengeId, signature, walletAddress);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const loginWithOAuth = useCallback(\n (provider: string) => {\n const callbackUrl = `${config.apiUrl}/auth/oauth/${provider}`;\n const redirectUri = encodeURIComponent(window.location.origin + '/__fc_oauth_callback');\n const url = `${callbackUrl}?redirect_uri=${redirectUri}`;\n const width = 500;\n const height = 600;\n const left = window.screenX + (window.innerWidth - width) / 2;\n const top = window.screenY + (window.innerHeight - height) / 2;\n window.open(url, 'fc_oauth', `width=${width},height=${height},left=${left},top=${top}`);\n },\n [config.apiUrl],\n );\n\n const logout = useCallback(async () => {\n const token = auth.accessToken;\n removeStoredToken();\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n onLogout?.();\n if (token) {\n try {\n await api.logout(token);\n } catch {\n // Already logged out client-side\n }\n }\n }, [auth.accessToken, api, onLogout]);\n\n const logoutAll = useCallback(async () => {\n const token = auth.accessToken;\n removeStoredToken();\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n onLogout?.();\n if (token) {\n try {\n await api.logoutAll(token);\n } catch {\n // Already logged out client-side\n }\n }\n }, [auth.accessToken, api, onLogout]);\n\n // ── Modal Actions ──\n\n const openModal = useCallback(() => {\n setModal({ isOpen: true, step: 'method-select' });\n }, []);\n\n const closeModal = useCallback(() => {\n setModal({ isOpen: false, step: 'method-select' });\n }, []);\n\n const setModalStep = useCallback((step: ModalStep) => {\n setModal((prev) => ({ ...prev, step }));\n }, []);\n\n const getAccessToken = useCallback(() => auth.accessToken, [auth.accessToken]);\n\n // ── Context Value ──\n\n const value: ForgeConnectContextValue = {\n auth,\n modal,\n config,\n api,\n loginWithEmail,\n register,\n sendOtp,\n verifyOtp,\n loginWithWallet,\n loginWithOAuth,\n logout,\n logoutAll,\n openModal,\n closeModal,\n setModalStep,\n getAccessToken,\n };\n\n return (\n <ForgeConnectContext.Provider value={value}>\n {children}\n <LoginModal />\n </ForgeConnectContext.Provider>\n );\n}\n\n// ── Helpers ──\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n\nfunction uint8ArrayToBase58(bytes: Uint8Array): string {\n const digits = [0];\n for (const byte of bytes) {\n let carry = byte;\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8;\n digits[j] = carry % 58;\n carry = (carry / 58) | 0;\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = (carry / 58) | 0;\n }\n }\n let str = '';\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {\n str += '1';\n }\n for (let i = digits.length - 1; i >= 0; i--) {\n str += BASE58_ALPHABET[digits[i]];\n }\n return str;\n}\n","import { createContext } from 'react';\nimport type { AuthState, ModalState, ForgeConnectConfig } from './types';\nimport type { ApiClient } from './api/client';\n\nexport interface ForgeConnectContextValue {\n // State\n auth: AuthState;\n modal: ModalState;\n config: ForgeConnectConfig;\n api: ApiClient;\n\n // Auth actions\n loginWithEmail: (email: string, password: string) => Promise<void>;\n register: (email: string, password: string, displayName?: string) => Promise<void>;\n sendOtp: (email: string) => Promise<void>;\n verifyOtp: (email: string, code: string) => Promise<void>;\n loginWithWallet: (walletAddress: string, signMessage: (message: Uint8Array) => Promise<Uint8Array>, chain?: string) => Promise<void>;\n loginWithOAuth: (provider: string) => void;\n logout: () => Promise<void>;\n logoutAll: () => Promise<void>;\n\n // Modal actions\n openModal: () => void;\n closeModal: () => void;\n setModalStep: (step: ModalState['step']) => void;\n\n // Token\n getAccessToken: () => string | null;\n}\n\nexport const ForgeConnectContext = createContext<ForgeConnectContextValue | null>(null);\n","import type { ApiErrorBody } from '../types';\n\nexport class ForgeConnectApiError extends Error {\n public readonly status: number;\n public readonly code: string;\n\n constructor(status: number, code: string, message: string) {\n super(message);\n this.name = 'ForgeConnectApiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport function createApiClient(apiUrl: string) {\n const base = apiUrl.replace(/\\/+$/, '');\n\n async function request<T>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n token?: string | null;\n } = {},\n ): Promise<T> {\n const { method = 'GET', body, token } = options;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n credentials: 'include',\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n let errorBody: ApiErrorBody;\n try {\n errorBody = await res.json() as ApiErrorBody;\n } catch {\n throw new ForgeConnectApiError(res.status, 'UNKNOWN', res.statusText);\n }\n throw new ForgeConnectApiError(res.status, errorBody.error.code, errorBody.error.message);\n }\n\n return res.json() as Promise<T>;\n }\n\n return {\n // ── Auth: Email ──\n register(email: string, password: string, displayName?: string) {\n return request<{ success: true }>('/auth/email/register', {\n method: 'POST',\n body: { email, password, displayName },\n });\n },\n\n login(email: string, password: string) {\n return request<{ accessToken: string; user: { id: string; displayName: string | null; email: string } }>(\n '/auth/email/login',\n { method: 'POST', body: { email, password } },\n );\n },\n\n sendOtp(email: string) {\n return request<{ success: true }>('/auth/email/send-code', {\n method: 'POST',\n body: { email },\n });\n },\n\n verifyOtp(email: string, code: string) {\n return request<{ accessToken: string; user: { id: string; email: string } }>(\n '/auth/email/verify-code',\n { method: 'POST', body: { email, code } },\n );\n },\n\n // ── Auth: Wallet ──\n walletChallenge(walletAddress: string, chain: string = 'solana') {\n return request<{ challengeId: string; nonce: string }>('/auth/wallet/challenge', {\n method: 'POST',\n body: { walletAddress, chain },\n });\n },\n\n walletVerify(challengeId: string, signature: string, walletAddress: string) {\n return request<{ accessToken: string }>('/auth/wallet/verify', {\n method: 'POST',\n body: { challengeId, signature, walletAddress },\n });\n },\n\n // ── Auth: Session ──\n refresh() {\n return request<{ accessToken: string }>('/auth/refresh', { method: 'POST' });\n },\n\n logout(token: string) {\n return request<{ success: true }>('/auth/logout', { method: 'POST', token });\n },\n\n logoutAll(token: string) {\n return request<{ success: true }>('/auth/logout-all', { method: 'POST', token });\n },\n\n // ── User ──\n getMe(token: string) {\n return request<{ id: string; displayName: string | null; avatarUrl: string | null; primaryEmail: string | null; status: string; createdAt: string; updatedAt: string }>(\n '/users/me',\n { token },\n );\n },\n\n updateMe(token: string, data: { displayName?: string; avatarUrl?: string }) {\n return request<{ id: string; displayName: string | null; avatarUrl: string | null; primaryEmail: string | null; status: string; createdAt: string; updatedAt: string }>(\n '/users/me',\n { method: 'PATCH', token, body: data },\n );\n },\n\n getAuthMethods(token: string) {\n return request<Array<{ id: string; provider: string; providerId: string; isVerified: boolean; verifiedAt: string | null; createdAt: string }>>(\n '/users/me/auth-methods',\n { token },\n );\n },\n\n linkAuthMethod(token: string, data: { provider: string; email?: string; password?: string; challengeId?: string; signature?: string; walletAddress?: string }) {\n return request<{ success: true }>('/users/me/auth-methods', {\n method: 'POST',\n token,\n body: data,\n });\n },\n\n unlinkAuthMethod(token: string, id: string) {\n return request<{ success: true }>(`/users/me/auth-methods/${id}`, {\n method: 'DELETE',\n token,\n });\n },\n\n getWallets(token: string) {\n return request<Array<{ id: string; userId: string; chain: string; address: string; label: string | null; isPrimary: boolean; verifiedAt: string | null; lastUsedAt: string | null }>>(\n '/users/me/wallets',\n { token },\n );\n },\n\n updateWallet(token: string, id: string, data: { label?: string; isPrimary?: boolean }) {\n return request<{ id: string; userId: string; chain: string; address: string; label: string | null; isPrimary: boolean; verifiedAt: string | null; lastUsedAt: string | null }>(\n `/users/me/wallets/${id}`,\n { method: 'PATCH', token, body: data },\n );\n },\n\n getSessions(token: string) {\n return request<Array<{ id: string; createdAt: string; expiresAt: string; lastActiveAt: string; deviceInfo: Record<string, unknown> | null; ipAddress: string }>>(\n '/users/me/sessions',\n { token },\n );\n },\n\n revokeSession(token: string, id: string) {\n return request<{ success: true }>(`/users/me/sessions/${id}`, {\n method: 'DELETE',\n token,\n });\n },\n };\n}\n\nexport type ApiClient = ReturnType<typeof createApiClient>;\n","const TOKEN_KEY = 'fc_access_token';\n\nexport function getStoredToken(): string | null {\n try {\n return localStorage.getItem(TOKEN_KEY);\n } catch {\n return null;\n }\n}\n\nexport function setStoredToken(token: string): void {\n try {\n localStorage.setItem(TOKEN_KEY, token);\n } catch {\n // SSR or storage unavailable\n }\n}\n\nexport function removeStoredToken(): void {\n try {\n localStorage.removeItem(TOKEN_KEY);\n } catch {\n // SSR or storage unavailable\n }\n}\n\ninterface DecodedJWT {\n sub: string;\n tid?: string;\n scopes: string[];\n iat?: number;\n exp?: number;\n}\n\nexport function decodeJWT(token: string): DecodedJWT | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));\n return payload as DecodedJWT;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns milliseconds until 80% of the token's TTL has elapsed.\n * Returns null if the token cannot be decoded or has no exp.\n */\nexport function getRefreshDelay(token: string): number | null {\n const decoded = decodeJWT(token);\n if (!decoded?.exp || !decoded.iat) return null;\n const ttl = (decoded.exp - decoded.iat) * 1000;\n const elapsed = Date.now() - decoded.iat * 1000;\n const delay = ttl * 0.8 - elapsed;\n return delay > 0 ? delay : 0;\n}\n","import { useContext } from 'react';\nimport { ForgeConnectContext, type ForgeConnectContextValue } from '../context';\n\nexport function useForgeConnect(): ForgeConnectContextValue {\n const ctx = useContext(ForgeConnectContext);\n if (!ctx) {\n throw new Error('useForgeConnect must be used within a <ForgeConnectProvider>');\n }\n return ctx;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface ModalOverlayProps {\n isOpen: boolean;\n onClose: () => void;\n children: ReactNode;\n}\n\nexport function ModalOverlay({ isOpen, onClose, children }: ModalOverlayProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n document.body.style.overflow = 'hidden';\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === overlayRef.current) onClose();\n };\n\n return createPortal(\n <div className=\"fc-overlay\" ref={overlayRef} onClick={handleBackdropClick}>\n <div className=\"fc-modal\" role=\"dialog\" aria-modal=\"true\">\n <button className=\"fc-modal-close\" onClick={onClose} aria-label=\"Close\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M15 5L5 15M5 5l10 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","import { useState, type FormEvent } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\nexport function EmailLoginForm() {\n const { loginWithEmail, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await loginWithEmail(email, password);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Login failed');\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Sign in with email</h3>\n <form onSubmit={handleSubmit} className=\"fc-form\">\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n <label className=\"fc-label\">\n Password\n <input\n type=\"password\"\n className=\"fc-input\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"Enter your password\"\n required\n autoComplete=\"current-password\"\n minLength={8}\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Signing in...' : 'Sign in'}\n </button>\n </form>\n <p className=\"fc-switch\">\n Don't have an account?{' '}\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('email-register')}>\n Sign up\n </button>\n </p>\n </div>\n );\n}\n\nexport function EmailRegisterForm() {\n const { register, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [error, setError] = useState('');\n const [success, setSuccess] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await register(email, password, displayName || undefined);\n setSuccess(true);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Registration failed');\n } finally {\n setLoading(false);\n }\n };\n\n if (success) {\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Check your email</h3>\n <p className=\"fc-text\">We sent a verification link to <strong>{email}</strong>. Click it to activate your account, then sign in.</p>\n <button type=\"button\" className=\"fc-btn fc-btn-secondary\" onClick={() => setModalStep('email-login')}>\n Back to sign in\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Create an account</h3>\n <form onSubmit={handleSubmit} className=\"fc-form\">\n <label className=\"fc-label\">\n Display name\n <input\n type=\"text\"\n className=\"fc-input\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n placeholder=\"Your name\"\n autoComplete=\"name\"\n />\n </label>\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n <label className=\"fc-label\">\n Password\n <input\n type=\"password\"\n className=\"fc-input\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"8+ characters\"\n required\n autoComplete=\"new-password\"\n minLength={8}\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Creating account...' : 'Create account'}\n </button>\n </form>\n <p className=\"fc-switch\">\n Already have an account?{' '}\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('email-login')}>\n Sign in\n </button>\n </p>\n </div>\n );\n}\n","import { useState, useRef, type FormEvent, type KeyboardEvent, type ClipboardEvent } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\nexport function EmailOtpForm() {\n const { sendOtp, verifyOtp, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [code, setCode] = useState(['', '', '', '', '', '']);\n const [step, setStep] = useState<'email' | 'code'>('email');\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n\n const handleSendCode = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await sendOtp(email);\n setStep('code');\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Failed to send code');\n } finally {\n setLoading(false);\n }\n };\n\n const handleVerify = async (digits: string[]) => {\n const codeStr = digits.join('');\n if (codeStr.length !== 6) return;\n setError('');\n setLoading(true);\n try {\n await verifyOtp(email, codeStr);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Invalid code');\n setLoading(false);\n }\n };\n\n const handleDigitChange = (index: number, value: string) => {\n if (!/^\\d*$/.test(value)) return;\n const digit = value.slice(-1);\n const newCode = [...code];\n newCode[index] = digit;\n setCode(newCode);\n\n if (digit && index < 5) {\n inputRefs.current[index + 1]?.focus();\n }\n\n if (newCode.every((d) => d !== '')) {\n handleVerify(newCode);\n }\n };\n\n const handleKeyDown = (index: number, e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace' && !code[index] && index > 0) {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const pasted = e.clipboardData.getData('text').replace(/\\D/g, '').slice(0, 6);\n if (!pasted) return;\n const newCode = [...code];\n for (let i = 0; i < pasted.length; i++) {\n newCode[i] = pasted[i];\n }\n setCode(newCode);\n if (newCode.every((d) => d !== '')) {\n handleVerify(newCode);\n }\n };\n\n if (step === 'email') {\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Passwordless sign in</h3>\n <form onSubmit={handleSendCode} className=\"fc-form\">\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Sending...' : 'Send code'}\n </button>\n </form>\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Enter verification code</h3>\n <p className=\"fc-text\">We sent a 6-digit code to <strong>{email}</strong></p>\n <div className=\"fc-otp-inputs\">\n {code.map((digit, i) => (\n <input\n key={i}\n ref={(el) => { inputRefs.current[i] = el; }}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={1}\n className=\"fc-otp-digit\"\n value={digit}\n onChange={(e) => handleDigitChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={i === 0 ? handlePaste : undefined}\n autoFocus={i === 0}\n />\n ))}\n </div>\n {error && <p className=\"fc-error\">{error}</p>}\n {loading && <p className=\"fc-text\">Verifying...</p>}\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => { setStep('email'); setCode(['', '', '', '', '', '']); setError(''); }}>\n Use a different email\n </button>\n </p>\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\n// Type definition for the wallet adapter hook — avoids hard import\ninterface WalletContext {\n publicKey: { toBase58(): string } | null;\n signMessage: ((message: Uint8Array) => Promise<Uint8Array>) | undefined;\n wallets: Array<{ adapter: { name: string; icon: string; connected: boolean }; readyState: string }>;\n select: (name: string) => void;\n connect: () => Promise<void>;\n}\n\n/**\n * Attempts to import `@solana/wallet-adapter-react` at runtime.\n * Returns the `useWallet` hook if available, undefined otherwise.\n */\nfunction tryGetUseWallet(): (() => WalletContext) | undefined {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@solana/wallet-adapter-react');\n return mod.useWallet;\n } catch {\n return undefined;\n }\n}\n\nconst resolvedUseWallet = tryGetUseWallet();\n\nexport function WalletConnectForm() {\n const { setModalStep } = useForgeConnect();\n\n if (resolvedUseWallet) {\n return <WalletAdapterFlow useWallet={resolvedUseWallet} />;\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Connect wallet</h3>\n <p className=\"fc-text\">\n Install a Solana wallet extension (Phantom, Solflare, etc.) and ensure{' '}\n <code>@solana/wallet-adapter-react</code> is configured in your app.\n </p>\n <p className=\"fc-text fc-text-muted\">\n Wallet connection requires the Solana wallet adapter provider in your app.\n </p>\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n}\n\nfunction WalletAdapterFlow({ useWallet }: { useWallet: () => WalletContext }) {\n const { loginWithWallet, setModalStep } = useForgeConnect();\n const wallet = useWallet();\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n\n const handleConnect = async () => {\n if (!wallet.publicKey || !wallet.signMessage) {\n setError('Please connect your wallet first');\n return;\n }\n setError('');\n setLoading(true);\n try {\n await loginWithWallet(\n wallet.publicKey.toBase58(),\n wallet.signMessage,\n 'solana',\n );\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Wallet verification failed');\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Connect wallet</h3>\n {wallet.publicKey ? (\n <>\n <p className=\"fc-text fc-wallet-address\">\n {wallet.publicKey.toBase58().slice(0, 4)}...{wallet.publicKey.toBase58().slice(-4)}\n </p>\n {error && <p className=\"fc-error\">{error}</p>}\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-primary\"\n onClick={handleConnect}\n disabled={loading}\n >\n {loading ? 'Signing...' : 'Sign to verify'}\n </button>\n </>\n ) : (\n <>\n <div className=\"fc-wallet-list\">\n {wallet.wallets\n .filter((w) => w.readyState === 'Installed')\n .map((w) => (\n <button\n key={w.adapter.name}\n type=\"button\"\n className=\"fc-btn fc-btn-wallet\"\n onClick={async () => {\n wallet.select(w.adapter.name as any);\n try {\n await wallet.connect();\n } catch {\n setError('Failed to connect wallet');\n }\n }}\n >\n <img src={w.adapter.icon} alt=\"\" className=\"fc-wallet-icon\" />\n {w.adapter.name}\n </button>\n ))}\n </div>\n {wallet.wallets.filter((w) => w.readyState === 'Installed').length === 0 && (\n <p className=\"fc-text\">No wallets detected. Install a Solana wallet extension.</p>\n )}\n {error && <p className=\"fc-error\">{error}</p>}\n </>\n )}\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n}\n","import { useForgeConnect } from '../../hooks/use-forge-connect';\nimport type { OAuthProvider } from '../../types';\n\nconst PROVIDER_INFO: Record<OAuthProvider, { label: string; icon: string }> = {\n google: {\n label: 'Google',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" fill=\"#4285F4\"/><path 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\" fill=\"#34A853\"/><path 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\" fill=\"#FBBC05\"/><path 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\" fill=\"#EA4335\"/></svg>',\n },\n discord: {\n label: 'Discord',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z\" fill=\"#5865F2\"/></svg>',\n },\n twitter: {\n label: 'Twitter',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" fill=\"currentColor\"/></svg>',\n },\n apple: {\n label: 'Apple',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z\" fill=\"currentColor\"/></svg>',\n },\n};\n\nexport function OAuthButtons() {\n const { config, loginWithOAuth } = useForgeConnect();\n const providers = config.oauthProviders ?? [];\n\n if (providers.length === 0) return null;\n\n return (\n <div className=\"fc-oauth-buttons\">\n {providers.map((provider) => {\n const info = PROVIDER_INFO[provider];\n return (\n <button\n key={provider}\n type=\"button\"\n className=\"fc-btn fc-btn-oauth\"\n onClick={() => loginWithOAuth(provider)}\n >\n <span className=\"fc-oauth-icon\" dangerouslySetInnerHTML={{ __html: info.icon }} />\n Continue with {info.label}\n </button>\n );\n })}\n </div>\n );\n}\n","import { useForgeConnect } from '../hooks/use-forge-connect';\nimport { ModalOverlay } from './modal-overlay';\nimport { EmailLoginForm, EmailRegisterForm } from './tabs/email-password';\nimport { EmailOtpForm } from './tabs/email-otp';\nimport { WalletConnectForm } from './tabs/wallet-connect';\nimport { OAuthButtons } from './tabs/oauth-buttons';\n\nexport function LoginModal() {\n const { modal, closeModal, setModalStep, config } = useForgeConnect();\n\n const renderStep = () => {\n switch (modal.step) {\n case 'email-login':\n return <EmailLoginForm />;\n case 'email-register':\n return <EmailRegisterForm />;\n case 'email-otp':\n return <EmailOtpForm />;\n case 'wallet-connect':\n return <WalletConnectForm />;\n case 'method-select':\n default:\n return <MethodSelect />;\n }\n };\n\n return (\n <ModalOverlay isOpen={modal.isOpen} onClose={closeModal}>\n <div\n className=\"fc-modal-content\"\n style={{\n '--fc-accent': config.appearance?.accentColor ?? '#8b5cf6',\n } as React.CSSProperties}\n data-theme={config.appearance?.theme ?? 'light'}\n >\n {config.appearance?.logo && (\n <img src={config.appearance.logo} alt=\"\" className=\"fc-logo\" />\n )}\n <h2 className=\"fc-modal-title\">\n {config.appearance?.title ?? 'Sign in'}\n </h2>\n {renderStep()}\n </div>\n </ModalOverlay>\n );\n}\n\nfunction MethodSelect() {\n const { setModalStep, config } = useForgeConnect();\n\n return (\n <div className=\"fc-method-select\">\n <OAuthButtons />\n\n {(config.oauthProviders?.length ?? 0) > 0 && (\n <div className=\"fc-divider\">\n <span>or</span>\n </div>\n )}\n\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('email-login')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"2\" y=\"4\" width=\"16\" height=\"12\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M2 6l8 5 8-5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n Continue with email\n </button>\n\n {config.passwordlessLogin !== false && (\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('email-otp')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"3\" y=\"6\" width=\"14\" height=\"9\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <circle cx=\"6.5\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"10\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"13.5\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n </svg>\n Continue with code\n </button>\n )}\n\n {config.walletLogin !== false && (\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('wallet-connect')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"2\" y=\"5\" width=\"16\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <rect x=\"13\" y=\"9\" width=\"5\" height=\"3\" rx=\"1\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n Continue with wallet\n </button>\n )}\n </div>\n );\n}\n","import { useForgeConnect } from '../hooks/use-forge-connect';\n\ninterface LoginButtonProps {\n className?: string;\n label?: string;\n}\n\nexport function LoginButton({ className, label }: LoginButtonProps) {\n const { auth, openModal, logout } = useForgeConnect();\n\n if (auth.status === 'loading') {\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} disabled>\n Loading...\n </button>\n );\n }\n\n if (auth.status === 'authenticated') {\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} onClick={logout}>\n {label ?? 'Log out'}\n </button>\n );\n }\n\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} onClick={openModal}>\n {label ?? 'Sign in'}\n </button>\n );\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { AuthMethod } from '../types';\n\nexport function useUser() {\n const { auth, api, getAccessToken } = useForgeConnect();\n const [authMethods, setAuthMethods] = useState<AuthMethod[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const updateProfile = useCallback(\n async (data: { displayName?: string; avatarUrl?: string }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n return api.updateMe(token, data);\n },\n [api, getAccessToken],\n );\n\n const fetchAuthMethods = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const methods = await api.getAuthMethods(token);\n setAuthMethods(methods as AuthMethod[]);\n return methods;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const linkAuthMethod = useCallback(\n async (data: { provider: string; email?: string; password?: string; challengeId?: string; signature?: string; walletAddress?: string }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.linkAuthMethod(token, data);\n await fetchAuthMethods();\n },\n [api, getAccessToken, fetchAuthMethods],\n );\n\n const unlinkAuthMethod = useCallback(\n async (id: string) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.unlinkAuthMethod(token, id);\n await fetchAuthMethods();\n },\n [api, getAccessToken, fetchAuthMethods],\n );\n\n return {\n user: auth.user,\n authMethods,\n loading,\n updateProfile,\n fetchAuthMethods,\n linkAuthMethod,\n unlinkAuthMethod,\n };\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { Wallet } from '../types';\n\nexport function useWallets() {\n const { api, getAccessToken } = useForgeConnect();\n const [wallets, setWallets] = useState<Wallet[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const fetchWallets = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const data = await api.getWallets(token);\n setWallets(data as Wallet[]);\n return data;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const updateWallet = useCallback(\n async (id: string, data: { label?: string; isPrimary?: boolean }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.updateWallet(token, id, data);\n await fetchWallets();\n },\n [api, getAccessToken, fetchWallets],\n );\n\n return {\n wallets,\n loading,\n fetchWallets,\n updateWallet,\n };\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { Session } from '../types';\n\nexport function useSessions() {\n const { api, getAccessToken } = useForgeConnect();\n const [sessions, setSessions] = useState<Session[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const fetchSessions = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const data = await api.getSessions(token);\n setSessions(data as Session[]);\n return data;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const revokeSession = useCallback(\n async (id: string) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.revokeSession(token, id);\n await fetchSessions();\n },\n [api, getAccessToken, fetchSessions],\n );\n\n return {\n sessions,\n loading,\n fetchSessions,\n revokeSession,\n };\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","jsx","jsxs","useState","useRef","jsx","jsxs","useState","useRef","useState","jsx","jsxs","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useRef","useEffect","jsx","useState","useCallback","useState","useCallback","useState","useCallback","useState","useCallback","useState","useCallback","useState","useCallback"]}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/* ForgeConnect Modal – all classes prefixed with fc- */
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
--fc-accent: #8b5cf6;
|
|
5
|
+
--fc-radius: 12px;
|
|
6
|
+
--fc-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* ── Overlay ── */
|
|
10
|
+
|
|
11
|
+
.fc-overlay {
|
|
12
|
+
position: fixed;
|
|
13
|
+
inset: 0;
|
|
14
|
+
z-index: 99999;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
background: rgba(0, 0, 0, 0.5);
|
|
19
|
+
backdrop-filter: blur(4px);
|
|
20
|
+
animation: fc-fade-in 0.15s ease-out;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.fc-modal {
|
|
24
|
+
position: relative;
|
|
25
|
+
width: 100%;
|
|
26
|
+
max-width: 420px;
|
|
27
|
+
max-height: 90vh;
|
|
28
|
+
overflow-y: auto;
|
|
29
|
+
margin: 16px;
|
|
30
|
+
border-radius: var(--fc-radius);
|
|
31
|
+
animation: fc-slide-up 0.2s ease-out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.fc-modal-close {
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: 12px;
|
|
37
|
+
right: 12px;
|
|
38
|
+
z-index: 1;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
width: 32px;
|
|
43
|
+
height: 32px;
|
|
44
|
+
padding: 0;
|
|
45
|
+
border: none;
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
background: transparent;
|
|
48
|
+
color: inherit;
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
opacity: 0.5;
|
|
51
|
+
transition: opacity 0.15s, background 0.15s;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.fc-modal-close:hover {
|
|
55
|
+
opacity: 1;
|
|
56
|
+
background: rgba(128, 128, 128, 0.15);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ── Content ── */
|
|
60
|
+
|
|
61
|
+
.fc-modal-content {
|
|
62
|
+
padding: 32px 28px 28px;
|
|
63
|
+
font-family: var(--fc-font);
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
line-height: 1.5;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.fc-modal-content[data-theme='light'] {
|
|
69
|
+
background: #ffffff;
|
|
70
|
+
color: #1a1a2e;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.fc-modal-content[data-theme='dark'] {
|
|
74
|
+
background: #1a1a2e;
|
|
75
|
+
color: #e4e4eb;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.fc-logo {
|
|
79
|
+
display: block;
|
|
80
|
+
width: 48px;
|
|
81
|
+
height: 48px;
|
|
82
|
+
margin: 0 auto 16px;
|
|
83
|
+
object-fit: contain;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.fc-modal-title {
|
|
87
|
+
margin: 0 0 24px;
|
|
88
|
+
font-size: 22px;
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
text-align: center;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ── Buttons ── */
|
|
94
|
+
|
|
95
|
+
.fc-btn {
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
gap: 10px;
|
|
100
|
+
width: 100%;
|
|
101
|
+
padding: 10px 16px;
|
|
102
|
+
border: none;
|
|
103
|
+
border-radius: 8px;
|
|
104
|
+
font-family: var(--fc-font);
|
|
105
|
+
font-size: 14px;
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
transition: background 0.15s, opacity 0.15s, box-shadow 0.15s;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.fc-btn:disabled {
|
|
112
|
+
opacity: 0.6;
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.fc-btn-primary {
|
|
117
|
+
background: var(--fc-accent);
|
|
118
|
+
color: #fff;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.fc-btn-primary:hover:not(:disabled) {
|
|
122
|
+
filter: brightness(1.1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.fc-btn-secondary {
|
|
126
|
+
background: transparent;
|
|
127
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
[data-theme='light'] .fc-btn-secondary {
|
|
131
|
+
color: #1a1a2e;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
[data-theme='dark'] .fc-btn-secondary {
|
|
135
|
+
color: #e4e4eb;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.fc-btn-secondary:hover:not(:disabled) {
|
|
139
|
+
background: rgba(128, 128, 128, 0.08);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.fc-btn-method {
|
|
143
|
+
background: transparent;
|
|
144
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
145
|
+
margin-bottom: 8px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
[data-theme='light'] .fc-btn-method {
|
|
149
|
+
color: #1a1a2e;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
[data-theme='dark'] .fc-btn-method {
|
|
153
|
+
color: #e4e4eb;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.fc-btn-method:hover:not(:disabled) {
|
|
157
|
+
background: rgba(128, 128, 128, 0.08);
|
|
158
|
+
border-color: var(--fc-accent);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.fc-btn-oauth {
|
|
162
|
+
background: transparent;
|
|
163
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
164
|
+
margin-bottom: 8px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
[data-theme='light'] .fc-btn-oauth {
|
|
168
|
+
color: #1a1a2e;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
[data-theme='dark'] .fc-btn-oauth {
|
|
172
|
+
color: #e4e4eb;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.fc-btn-oauth:hover:not(:disabled) {
|
|
176
|
+
background: rgba(128, 128, 128, 0.08);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.fc-btn-wallet {
|
|
180
|
+
background: transparent;
|
|
181
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
182
|
+
margin-bottom: 8px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
[data-theme='light'] .fc-btn-wallet {
|
|
186
|
+
color: #1a1a2e;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
[data-theme='dark'] .fc-btn-wallet {
|
|
190
|
+
color: #e4e4eb;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.fc-btn-wallet:hover:not(:disabled) {
|
|
194
|
+
background: rgba(128, 128, 128, 0.08);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.fc-btn-login {
|
|
198
|
+
display: inline-flex;
|
|
199
|
+
width: auto;
|
|
200
|
+
padding: 8px 20px;
|
|
201
|
+
background: var(--fc-accent);
|
|
202
|
+
color: #fff;
|
|
203
|
+
border: none;
|
|
204
|
+
border-radius: 8px;
|
|
205
|
+
font-family: var(--fc-font);
|
|
206
|
+
font-size: 14px;
|
|
207
|
+
font-weight: 500;
|
|
208
|
+
cursor: pointer;
|
|
209
|
+
transition: filter 0.15s;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.fc-btn-login:hover:not(:disabled) {
|
|
213
|
+
filter: brightness(1.1);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* ── Form Elements ── */
|
|
217
|
+
|
|
218
|
+
.fc-form {
|
|
219
|
+
display: flex;
|
|
220
|
+
flex-direction: column;
|
|
221
|
+
gap: 14px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.fc-label {
|
|
225
|
+
display: flex;
|
|
226
|
+
flex-direction: column;
|
|
227
|
+
gap: 6px;
|
|
228
|
+
font-size: 13px;
|
|
229
|
+
font-weight: 500;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.fc-input {
|
|
233
|
+
width: 100%;
|
|
234
|
+
padding: 10px 12px;
|
|
235
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
236
|
+
border-radius: 8px;
|
|
237
|
+
font-family: var(--fc-font);
|
|
238
|
+
font-size: 14px;
|
|
239
|
+
outline: none;
|
|
240
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
241
|
+
box-sizing: border-box;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
[data-theme='light'] .fc-input {
|
|
245
|
+
background: #fff;
|
|
246
|
+
color: #1a1a2e;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
[data-theme='dark'] .fc-input {
|
|
250
|
+
background: rgba(255, 255, 255, 0.06);
|
|
251
|
+
color: #e4e4eb;
|
|
252
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.fc-input:focus {
|
|
256
|
+
border-color: var(--fc-accent);
|
|
257
|
+
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.fc-input::placeholder {
|
|
261
|
+
opacity: 0.5;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* ── OTP Digits ── */
|
|
265
|
+
|
|
266
|
+
.fc-otp-inputs {
|
|
267
|
+
display: flex;
|
|
268
|
+
gap: 8px;
|
|
269
|
+
justify-content: center;
|
|
270
|
+
margin: 16px 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.fc-otp-digit {
|
|
274
|
+
width: 44px;
|
|
275
|
+
height: 52px;
|
|
276
|
+
text-align: center;
|
|
277
|
+
font-size: 20px;
|
|
278
|
+
font-weight: 600;
|
|
279
|
+
font-family: var(--fc-font);
|
|
280
|
+
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
281
|
+
border-radius: 8px;
|
|
282
|
+
outline: none;
|
|
283
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
[data-theme='light'] .fc-otp-digit {
|
|
287
|
+
background: #fff;
|
|
288
|
+
color: #1a1a2e;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
[data-theme='dark'] .fc-otp-digit {
|
|
292
|
+
background: rgba(255, 255, 255, 0.06);
|
|
293
|
+
color: #e4e4eb;
|
|
294
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.fc-otp-digit:focus {
|
|
298
|
+
border-color: var(--fc-accent);
|
|
299
|
+
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* ── Text & Links ── */
|
|
303
|
+
|
|
304
|
+
.fc-tab {
|
|
305
|
+
animation: fc-fade-in 0.15s ease-out;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.fc-tab-title {
|
|
309
|
+
margin: 0 0 16px;
|
|
310
|
+
font-size: 16px;
|
|
311
|
+
font-weight: 600;
|
|
312
|
+
text-align: center;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.fc-text {
|
|
316
|
+
margin: 8px 0;
|
|
317
|
+
font-size: 13px;
|
|
318
|
+
text-align: center;
|
|
319
|
+
opacity: 0.8;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.fc-text-muted {
|
|
323
|
+
opacity: 0.5;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.fc-error {
|
|
327
|
+
margin: 4px 0;
|
|
328
|
+
padding: 8px 12px;
|
|
329
|
+
border-radius: 6px;
|
|
330
|
+
font-size: 13px;
|
|
331
|
+
text-align: center;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
[data-theme='light'] .fc-error {
|
|
335
|
+
background: #fef2f2;
|
|
336
|
+
color: #dc2626;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
[data-theme='dark'] .fc-error {
|
|
340
|
+
background: rgba(220, 38, 38, 0.15);
|
|
341
|
+
color: #fca5a5;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.fc-switch {
|
|
345
|
+
margin: 16px 0 0;
|
|
346
|
+
font-size: 13px;
|
|
347
|
+
text-align: center;
|
|
348
|
+
opacity: 0.7;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.fc-link {
|
|
352
|
+
background: none;
|
|
353
|
+
border: none;
|
|
354
|
+
padding: 0;
|
|
355
|
+
font-family: var(--fc-font);
|
|
356
|
+
font-size: 13px;
|
|
357
|
+
color: var(--fc-accent);
|
|
358
|
+
cursor: pointer;
|
|
359
|
+
text-decoration: underline;
|
|
360
|
+
text-underline-offset: 2px;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.fc-link:hover {
|
|
364
|
+
opacity: 0.8;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* ── Divider ── */
|
|
368
|
+
|
|
369
|
+
.fc-divider {
|
|
370
|
+
display: flex;
|
|
371
|
+
align-items: center;
|
|
372
|
+
gap: 12px;
|
|
373
|
+
margin: 16px 0;
|
|
374
|
+
font-size: 12px;
|
|
375
|
+
text-transform: uppercase;
|
|
376
|
+
letter-spacing: 0.05em;
|
|
377
|
+
opacity: 0.5;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.fc-divider::before,
|
|
381
|
+
.fc-divider::after {
|
|
382
|
+
content: '';
|
|
383
|
+
flex: 1;
|
|
384
|
+
height: 1px;
|
|
385
|
+
background: currentColor;
|
|
386
|
+
opacity: 0.3;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* ── OAuth Icons ── */
|
|
390
|
+
|
|
391
|
+
.fc-oauth-icon {
|
|
392
|
+
display: flex;
|
|
393
|
+
align-items: center;
|
|
394
|
+
width: 20px;
|
|
395
|
+
height: 20px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.fc-oauth-icon svg {
|
|
399
|
+
width: 20px;
|
|
400
|
+
height: 20px;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* ── Wallet ── */
|
|
404
|
+
|
|
405
|
+
.fc-method-icon {
|
|
406
|
+
flex-shrink: 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.fc-wallet-list {
|
|
410
|
+
display: flex;
|
|
411
|
+
flex-direction: column;
|
|
412
|
+
gap: 0;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.fc-wallet-icon {
|
|
416
|
+
width: 24px;
|
|
417
|
+
height: 24px;
|
|
418
|
+
border-radius: 4px;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.fc-wallet-address {
|
|
422
|
+
font-family: monospace;
|
|
423
|
+
font-size: 15px;
|
|
424
|
+
font-weight: 600;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* ── Animations ── */
|
|
428
|
+
|
|
429
|
+
@keyframes fc-fade-in {
|
|
430
|
+
from { opacity: 0; }
|
|
431
|
+
to { opacity: 1; }
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
@keyframes fc-slide-up {
|
|
435
|
+
from {
|
|
436
|
+
opacity: 0;
|
|
437
|
+
transform: translateY(12px) scale(0.97);
|
|
438
|
+
}
|
|
439
|
+
to {
|
|
440
|
+
opacity: 1;
|
|
441
|
+
transform: translateY(0) scale(1);
|
|
442
|
+
}
|
|
443
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forge-connect/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./styles.css": "./dist/styles.css"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
26
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
27
|
+
"@solana/wallet-adapter-react": ">=0.15.0"
|
|
28
|
+
},
|
|
29
|
+
"peerDependenciesMeta": {
|
|
30
|
+
"@solana/wallet-adapter-react": {
|
|
31
|
+
"optional": true
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/react": "^19.1.6",
|
|
36
|
+
"@types/react-dom": "^19.1.6",
|
|
37
|
+
"react": "^19.1.0",
|
|
38
|
+
"react-dom": "^19.1.0",
|
|
39
|
+
"tsup": "^8.4.0",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch"
|
|
45
|
+
}
|
|
46
|
+
}
|