@fayz-ai/plugin-auth 0.9.0 → 0.10.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.
Files changed (46) hide show
  1. package/dist/{AmbassadorBubbles.d.ts → components/AmbassadorBubbles.d.ts} +1 -1
  2. package/dist/components/AmbassadorBubbles.d.ts.map +1 -0
  3. package/dist/{forms.d.ts → components/forms.d.ts} +12 -2
  4. package/dist/components/forms.d.ts.map +1 -0
  5. package/dist/index.d.ts +9 -9
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +42 -19
  8. package/dist/index.js.map +1 -1
  9. package/dist/{runtime.d.ts → lib/runtime.d.ts} +1 -1
  10. package/dist/lib/runtime.d.ts.map +1 -0
  11. package/dist/types.d.ts +6 -0
  12. package/dist/types.d.ts.map +1 -1
  13. package/dist/{pages.d.ts → views/pages.d.ts} +4 -2
  14. package/dist/views/pages.d.ts.map +1 -0
  15. package/dist/views/set-password.d.ts.map +1 -0
  16. package/dist/website/components/AuthModalProvider.d.ts.map +1 -0
  17. package/dist/website/components/PhoneAuthModal.d.ts.map +1 -0
  18. package/dist/website/index.d.ts +5 -5
  19. package/dist/website/index.d.ts.map +1 -1
  20. package/dist/website/index.js +1 -1
  21. package/dist/website/index.js.map +1 -1
  22. package/dist/website/lib/phone.d.ts.map +1 -0
  23. package/package.json +5 -8
  24. package/dist/AmbassadorBubbles.d.ts.map +0 -1
  25. package/dist/forms.d.ts.map +0 -1
  26. package/dist/pages.d.ts.map +0 -1
  27. package/dist/runtime.d.ts.map +0 -1
  28. package/dist/set-password.d.ts.map +0 -1
  29. package/dist/website/AuthModalProvider.d.ts.map +0 -1
  30. package/dist/website/PhoneAuthModal.d.ts.map +0 -1
  31. package/dist/website/phone.d.ts.map +0 -1
  32. package/src/AmbassadorBubbles.tsx +0 -61
  33. package/src/forms.tsx +0 -307
  34. package/src/index.ts +0 -56
  35. package/src/pages.tsx +0 -209
  36. package/src/runtime.ts +0 -67
  37. package/src/set-password.tsx +0 -229
  38. package/src/types.ts +0 -65
  39. package/src/website/AuthModalProvider.tsx +0 -48
  40. package/src/website/PhoneAuthModal.tsx +0 -178
  41. package/src/website/index.tsx +0 -17
  42. package/src/website/phone.ts +0 -12
  43. /package/dist/{set-password.d.ts → views/set-password.d.ts} +0 -0
  44. /package/dist/website/{AuthModalProvider.d.ts → components/AuthModalProvider.d.ts} +0 -0
  45. /package/dist/website/{PhoneAuthModal.d.ts → components/PhoneAuthModal.d.ts} +0 -0
  46. /package/dist/website/{phone.d.ts → lib/phone.d.ts} +0 -0
@@ -6,7 +6,7 @@ import { useAuth } from '@fayz-ai/auth';
6
6
  export { AuthProvider, createMockAuthAdapter, createSupabaseAuthAdapter, useAuth } from '@fayz-ai/auth';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
8
 
9
- // src/website/AuthModalProvider.tsx
9
+ // src/website/components/AuthModalProvider.tsx
10
10
  function phoneToEmail(phoneWithDial) {
11
11
  const digits = unmaskPhone(phoneWithDial);
12
12
  return `${digits || "anon"}@phone.fayz.local`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/website/phone.ts","../../src/website/PhoneAuthModal.tsx","../../src/website/AuthModalProvider.tsx"],"names":["unmaskPhone","useState","jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import { unmaskPhone } from '@fayz-ai/core'\n\n/**\n * Canonical phone → auth email. Used by BOTH the phone-auth modal and any host\n * booking→auth bridge so the same number always maps to the same account\n * (Quaddro model: phone = identity). Pass the phone WITH its country dial so the\n * digits are globally unique.\n */\nexport function phoneToEmail(phoneWithDial: string): string {\n const digits = unmaskPhone(phoneWithDial)\n return `${digits || 'anon'}@phone.fayz.local`\n}\n","import { useEffect, useState } from 'react'\nimport * as Dialog from '@radix-ui/react-dialog'\nimport { X, Smartphone, ArrowLeft } from 'lucide-react'\nimport { COUNTRIES, DEFAULT_COUNTRY, getCountry, maskPhone, unmaskPhone } from '@fayz-ai/core'\nimport { useAuth } from '@fayz-ai/auth'\nimport { phoneToEmail } from './phone'\n\nexport interface PhoneAuthModalConfig {\n /** Business/brand name shown in the copy. */\n brand?: string\n title?: string\n}\n\ntype Mode = 'signin' | 'signup'\n\n/**\n * Default phone sign-in / sign-up modal for dogfood Fayz sites. Built on Radix\n * Dialog (backdrop, focus-trap, Esc, scroll-lock, enter/exit animation via\n * tailwindcss-animate) — no reinvented modal chrome. Entrar / Criar conta\n * toggle, phone → WhatsApp code (POC bypass `0000`) → signs the user in via the\n * mounted auth adapter (phone = account). Token-only; render inside <AuthProvider>.\n */\nexport function PhoneAuthModal({\n open, onClose, config,\n}: { open: boolean; onClose: () => void; config?: PhoneAuthModalConfig }) {\n const { signUp } = useAuth()\n\n const [mode, setMode] = useState<Mode>('signup')\n const [step, setStep] = useState<'phone' | 'code'>('phone')\n const [countryIso, setCountryIso] = useState(DEFAULT_COUNTRY)\n const country = getCountry(countryIso)\n const [phone, setPhone] = useState('')\n const [name, setName] = useState('')\n const [code, setCode] = useState('')\n const [codeError, setCodeError] = useState(false)\n const [busy, setBusy] = useState(false)\n\n // Fresh flow each time it opens.\n useEffect(() => {\n if (open) { setStep('phone'); setCode(''); setCodeError(false); setBusy(false) }\n }, [open])\n\n function sendCode() {\n if (unmaskPhone(phone).length < 8) return\n setCode(''); setCodeError(false); setStep('code')\n }\n\n async function confirmCode() {\n if (code.trim() !== '0000') { setCodeError(true); return }\n setBusy(true)\n try {\n await signUp(phoneToEmail(`${country.dial} ${phone}`), unmaskPhone(phone), name.trim() || 'Cliente')\n onClose()\n } catch {\n setCodeError(true)\n } finally {\n setBusy(false)\n }\n }\n\n const brandLabel = config?.brand ? ` na ${config.brand}` : ''\n\n return (\n <Dialog.Root open={open} onOpenChange={(o) => { if (!o) onClose() }}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 z-[100] bg-foreground/40 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0\" />\n <Dialog.Content\n onOpenAutoFocus={(e) => e.preventDefault()}\n className=\"fixed left-1/2 top-1/2 z-[101] w-[calc(100%-2rem)] max-w-[26rem] -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-border bg-card p-6 shadow-2xl duration-200 focus:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95 data-[state=open]:slide-in-from-bottom-2 motion-reduce:animate-none\"\n >\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-accent text-primary\">\n <Smartphone className=\"h-5 w-5\" />\n </span>\n <div className=\"min-w-0\">\n <Dialog.Title className=\"text-base font-semibold text-foreground\">\n {config?.title ?? 'Acessar sua conta'}\n </Dialog.Title>\n <Dialog.Description className=\"text-xs text-muted-foreground\">\n {mode === 'signup' ? `Crie sua conta${brandLabel} em segundos` : `Bem-vindo de volta${brandLabel}`}\n </Dialog.Description>\n </div>\n </div>\n\n <Dialog.Close\n aria-label=\"Fechar\"\n className=\"absolute right-4 top-4 flex h-7 w-7 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <X className=\"h-4 w-4\" />\n </Dialog.Close>\n\n {/* Mode toggle (only on the phone step) */}\n {step === 'phone' ? (\n <div className=\"mt-5 grid grid-cols-2 gap-1 rounded-lg bg-muted p-1 text-sm\">\n {(['signin', 'signup'] as Mode[]).map((m) => (\n <button\n key={m}\n type=\"button\"\n onClick={() => setMode(m)}\n className={`rounded-md py-1.5 font-medium transition-colors ${mode === m ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}`}\n >\n {m === 'signin' ? 'Entrar' : 'Criar conta'}\n </button>\n ))}\n </div>\n ) : null}\n\n {step === 'phone' ? (\n <form onSubmit={(e) => { e.preventDefault(); sendCode() }} className=\"mt-4 space-y-3\">\n {mode === 'signup' ? (\n <div>\n <label htmlFor=\"auth-name\" className=\"mb-1 block text-sm font-medium text-foreground\">Nome</label>\n <input\n id=\"auth-name\" type=\"text\" autoComplete=\"name\" value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full rounded-xl border border-border bg-background px-3.5 py-2.5 text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder=\"Seu nome\"\n />\n </div>\n ) : null}\n <div>\n <label htmlFor=\"auth-phone\" className=\"mb-1 block text-sm font-medium text-foreground\">Celular</label>\n <div className=\"flex\">\n <select\n aria-label=\"País\"\n value={countryIso}\n onChange={(e) => { const c = getCountry(e.target.value); setCountryIso(c.iso2); setPhone(maskPhone(unmaskPhone(phone), c.mask)) }}\n className=\"appearance-none rounded-l-xl border border-r-0 border-border bg-muted py-2.5 pl-3 pr-6 text-sm font-medium text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {COUNTRIES.map((c) => <option key={c.iso2} value={c.iso2}>{c.flag} {c.dial}</option>)}\n </select>\n <input\n id=\"auth-phone\" type=\"tel\" autoComplete=\"tel\" inputMode=\"tel\" value={phone} autoFocus\n onChange={(e) => setPhone(maskPhone(e.target.value, country.mask))}\n className=\"w-full rounded-r-xl border border-border bg-background px-3.5 py-2.5 text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={`Ex.: ${maskPhone('11987654321', country.mask)}`}\n />\n </div>\n </div>\n <button\n type=\"submit\"\n disabled={unmaskPhone(phone).length < 8}\n className=\"w-full rounded-xl bg-primary py-2.5 font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Enviar código via WhatsApp\n </button>\n <p className=\"text-center text-xs text-muted-foreground\">Enviaremos um código para confirmar seu número.</p>\n </form>\n ) : (\n <form onSubmit={(e) => { e.preventDefault(); void confirmCode() }} className=\"mt-5 space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n Enviamos um código via WhatsApp para <span className=\"font-medium text-foreground\">{country.flag} {country.dial} {phone}</span>.\n </p>\n <input\n type=\"text\" inputMode=\"numeric\" value={code} autoFocus\n onChange={(e) => { setCode(e.target.value); setCodeError(false) }}\n className=\"w-full rounded-xl border border-border bg-background px-4 py-3 text-center text-lg tracking-[0.4em] text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring placeholder:text-sm placeholder:tracking-normal\"\n placeholder=\"Digite o código\"\n />\n {codeError ? <p role=\"alert\" className=\"text-sm text-destructive\">Código inválido. Para testar, use 0000.</p> : null}\n <button\n type=\"submit\"\n disabled={busy}\n className=\"w-full rounded-xl bg-primary py-2.5 font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {busy ? 'Entrando…' : mode === 'signup' ? 'Criar conta e entrar' : 'Confirmar e entrar'}\n </button>\n <button type=\"button\" onClick={() => setStep('phone')} className=\"mx-auto flex items-center gap-1 text-sm font-medium text-primary hover:underline\">\n <ArrowLeft className=\"h-3.5 w-3.5\" /> Trocar número\n </button>\n </form>\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { createContext, useContext, useState, type ReactNode } from 'react'\nimport { PhoneAuthModal, type PhoneAuthModalConfig } from './PhoneAuthModal'\n\ninterface AuthModalContextValue {\n openAuthModal: () => void\n closeAuthModal: () => void\n isAuthModalOpen: boolean\n}\n\nconst AuthModalContext = createContext<AuthModalContextValue | null>(null)\n\nexport interface AuthModalProviderProps {\n /** Enables the phone sign-in/up modal (default for dogfood sites). */\n phoneAuth?: boolean\n config?: PhoneAuthModalConfig\n children: ReactNode\n}\n\n/**\n * Mounts the default phone-auth login modal and exposes openAuthModal() to the\n * host (e.g. an \"Acessar área do cliente\" button). Render INSIDE <AuthProvider>\n * so the modal can sign the user in through the mounted adapter.\n */\nexport function AuthModalProvider({ phoneAuth = true, config, children }: AuthModalProviderProps) {\n const [open, setOpen] = useState(false)\n const value: AuthModalContextValue = {\n openAuthModal: () => setOpen(true),\n closeAuthModal: () => setOpen(false),\n isAuthModalOpen: open,\n }\n return (\n <AuthModalContext.Provider value={value}>\n {children}\n {phoneAuth ? <PhoneAuthModal open={open} onClose={() => setOpen(false)} config={config} /> : null}\n </AuthModalContext.Provider>\n )\n}\n\n/** Access the auth modal controls. Returns a no-op opener if no provider is mounted. */\nexport function useAuthModal(): AuthModalContextValue {\n return (\n useContext(AuthModalContext) ?? {\n openAuthModal: () => {},\n closeAuthModal: () => {},\n isAuthModalOpen: false,\n }\n )\n}\n"]}
1
+ {"version":3,"sources":["../../src/website/lib/phone.ts","../../src/website/components/PhoneAuthModal.tsx","../../src/website/components/AuthModalProvider.tsx"],"names":["unmaskPhone","useState","jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import { unmaskPhone } from '@fayz-ai/core'\n\n/**\n * Canonical phone → auth email. Used by BOTH the phone-auth modal and any host\n * booking→auth bridge so the same number always maps to the same account\n * (Quaddro model: phone = identity). Pass the phone WITH its country dial so the\n * digits are globally unique.\n */\nexport function phoneToEmail(phoneWithDial: string): string {\n const digits = unmaskPhone(phoneWithDial)\n return `${digits || 'anon'}@phone.fayz.local`\n}\n","import { useEffect, useState } from 'react'\nimport * as Dialog from '@radix-ui/react-dialog'\nimport { X, Smartphone, ArrowLeft } from 'lucide-react'\nimport { COUNTRIES, DEFAULT_COUNTRY, getCountry, maskPhone, unmaskPhone } from '@fayz-ai/core'\nimport { useAuth } from '@fayz-ai/auth'\nimport { phoneToEmail } from '../lib/phone'\n\nexport interface PhoneAuthModalConfig {\n /** Business/brand name shown in the copy. */\n brand?: string\n title?: string\n}\n\ntype Mode = 'signin' | 'signup'\n\n/**\n * Default phone sign-in / sign-up modal for dogfood Fayz sites. Built on Radix\n * Dialog (backdrop, focus-trap, Esc, scroll-lock, enter/exit animation via\n * tailwindcss-animate) — no reinvented modal chrome. Entrar / Criar conta\n * toggle, phone → WhatsApp code (POC bypass `0000`) → signs the user in via the\n * mounted auth adapter (phone = account). Token-only; render inside <AuthProvider>.\n */\nexport function PhoneAuthModal({\n open, onClose, config,\n}: { open: boolean; onClose: () => void; config?: PhoneAuthModalConfig }) {\n const { signUp } = useAuth()\n\n const [mode, setMode] = useState<Mode>('signup')\n const [step, setStep] = useState<'phone' | 'code'>('phone')\n const [countryIso, setCountryIso] = useState(DEFAULT_COUNTRY)\n const country = getCountry(countryIso)\n const [phone, setPhone] = useState('')\n const [name, setName] = useState('')\n const [code, setCode] = useState('')\n const [codeError, setCodeError] = useState(false)\n const [busy, setBusy] = useState(false)\n\n // Fresh flow each time it opens.\n useEffect(() => {\n if (open) { setStep('phone'); setCode(''); setCodeError(false); setBusy(false) }\n }, [open])\n\n function sendCode() {\n if (unmaskPhone(phone).length < 8) return\n setCode(''); setCodeError(false); setStep('code')\n }\n\n async function confirmCode() {\n if (code.trim() !== '0000') { setCodeError(true); return }\n setBusy(true)\n try {\n await signUp(phoneToEmail(`${country.dial} ${phone}`), unmaskPhone(phone), name.trim() || 'Cliente')\n onClose()\n } catch {\n setCodeError(true)\n } finally {\n setBusy(false)\n }\n }\n\n const brandLabel = config?.brand ? ` na ${config.brand}` : ''\n\n return (\n <Dialog.Root open={open} onOpenChange={(o) => { if (!o) onClose() }}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 z-[100] bg-foreground/40 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0\" />\n <Dialog.Content\n onOpenAutoFocus={(e) => e.preventDefault()}\n className=\"fixed left-1/2 top-1/2 z-[101] w-[calc(100%-2rem)] max-w-[26rem] -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-border bg-card p-6 shadow-2xl duration-200 focus:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95 data-[state=open]:slide-in-from-bottom-2 motion-reduce:animate-none\"\n >\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-accent text-primary\">\n <Smartphone className=\"h-5 w-5\" />\n </span>\n <div className=\"min-w-0\">\n <Dialog.Title className=\"text-base font-semibold text-foreground\">\n {config?.title ?? 'Acessar sua conta'}\n </Dialog.Title>\n <Dialog.Description className=\"text-xs text-muted-foreground\">\n {mode === 'signup' ? `Crie sua conta${brandLabel} em segundos` : `Bem-vindo de volta${brandLabel}`}\n </Dialog.Description>\n </div>\n </div>\n\n <Dialog.Close\n aria-label=\"Fechar\"\n className=\"absolute right-4 top-4 flex h-7 w-7 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <X className=\"h-4 w-4\" />\n </Dialog.Close>\n\n {/* Mode toggle (only on the phone step) */}\n {step === 'phone' ? (\n <div className=\"mt-5 grid grid-cols-2 gap-1 rounded-lg bg-muted p-1 text-sm\">\n {(['signin', 'signup'] as Mode[]).map((m) => (\n <button\n key={m}\n type=\"button\"\n onClick={() => setMode(m)}\n className={`rounded-md py-1.5 font-medium transition-colors ${mode === m ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}`}\n >\n {m === 'signin' ? 'Entrar' : 'Criar conta'}\n </button>\n ))}\n </div>\n ) : null}\n\n {step === 'phone' ? (\n <form onSubmit={(e) => { e.preventDefault(); sendCode() }} className=\"mt-4 space-y-3\">\n {mode === 'signup' ? (\n <div>\n <label htmlFor=\"auth-name\" className=\"mb-1 block text-sm font-medium text-foreground\">Nome</label>\n <input\n id=\"auth-name\" type=\"text\" autoComplete=\"name\" value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full rounded-xl border border-border bg-background px-3.5 py-2.5 text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder=\"Seu nome\"\n />\n </div>\n ) : null}\n <div>\n <label htmlFor=\"auth-phone\" className=\"mb-1 block text-sm font-medium text-foreground\">Celular</label>\n <div className=\"flex\">\n <select\n aria-label=\"País\"\n value={countryIso}\n onChange={(e) => { const c = getCountry(e.target.value); setCountryIso(c.iso2); setPhone(maskPhone(unmaskPhone(phone), c.mask)) }}\n className=\"appearance-none rounded-l-xl border border-r-0 border-border bg-muted py-2.5 pl-3 pr-6 text-sm font-medium text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {COUNTRIES.map((c) => <option key={c.iso2} value={c.iso2}>{c.flag} {c.dial}</option>)}\n </select>\n <input\n id=\"auth-phone\" type=\"tel\" autoComplete=\"tel\" inputMode=\"tel\" value={phone} autoFocus\n onChange={(e) => setPhone(maskPhone(e.target.value, country.mask))}\n className=\"w-full rounded-r-xl border border-border bg-background px-3.5 py-2.5 text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={`Ex.: ${maskPhone('11987654321', country.mask)}`}\n />\n </div>\n </div>\n <button\n type=\"submit\"\n disabled={unmaskPhone(phone).length < 8}\n className=\"w-full rounded-xl bg-primary py-2.5 font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Enviar código via WhatsApp\n </button>\n <p className=\"text-center text-xs text-muted-foreground\">Enviaremos um código para confirmar seu número.</p>\n </form>\n ) : (\n <form onSubmit={(e) => { e.preventDefault(); void confirmCode() }} className=\"mt-5 space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n Enviamos um código via WhatsApp para <span className=\"font-medium text-foreground\">{country.flag} {country.dial} {phone}</span>.\n </p>\n <input\n type=\"text\" inputMode=\"numeric\" value={code} autoFocus\n onChange={(e) => { setCode(e.target.value); setCodeError(false) }}\n className=\"w-full rounded-xl border border-border bg-background px-4 py-3 text-center text-lg tracking-[0.4em] text-foreground outline-none transition-colors focus:border-primary focus-visible:ring-2 focus-visible:ring-ring placeholder:text-sm placeholder:tracking-normal\"\n placeholder=\"Digite o código\"\n />\n {codeError ? <p role=\"alert\" className=\"text-sm text-destructive\">Código inválido. Para testar, use 0000.</p> : null}\n <button\n type=\"submit\"\n disabled={busy}\n className=\"w-full rounded-xl bg-primary py-2.5 font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {busy ? 'Entrando…' : mode === 'signup' ? 'Criar conta e entrar' : 'Confirmar e entrar'}\n </button>\n <button type=\"button\" onClick={() => setStep('phone')} className=\"mx-auto flex items-center gap-1 text-sm font-medium text-primary hover:underline\">\n <ArrowLeft className=\"h-3.5 w-3.5\" /> Trocar número\n </button>\n </form>\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { createContext, useContext, useState, type ReactNode } from 'react'\nimport { PhoneAuthModal, type PhoneAuthModalConfig } from './PhoneAuthModal'\n\ninterface AuthModalContextValue {\n openAuthModal: () => void\n closeAuthModal: () => void\n isAuthModalOpen: boolean\n}\n\nconst AuthModalContext = createContext<AuthModalContextValue | null>(null)\n\nexport interface AuthModalProviderProps {\n /** Enables the phone sign-in/up modal (default for dogfood sites). */\n phoneAuth?: boolean\n config?: PhoneAuthModalConfig\n children: ReactNode\n}\n\n/**\n * Mounts the default phone-auth login modal and exposes openAuthModal() to the\n * host (e.g. an \"Acessar área do cliente\" button). Render INSIDE <AuthProvider>\n * so the modal can sign the user in through the mounted adapter.\n */\nexport function AuthModalProvider({ phoneAuth = true, config, children }: AuthModalProviderProps) {\n const [open, setOpen] = useState(false)\n const value: AuthModalContextValue = {\n openAuthModal: () => setOpen(true),\n closeAuthModal: () => setOpen(false),\n isAuthModalOpen: open,\n }\n return (\n <AuthModalContext.Provider value={value}>\n {children}\n {phoneAuth ? <PhoneAuthModal open={open} onClose={() => setOpen(false)} config={config} /> : null}\n </AuthModalContext.Provider>\n )\n}\n\n/** Access the auth modal controls. Returns a no-op opener if no provider is mounted. */\nexport function useAuthModal(): AuthModalContextValue {\n return (\n useContext(AuthModalContext) ?? {\n openAuthModal: () => {},\n closeAuthModal: () => {},\n isAuthModalOpen: false,\n }\n )\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../src/website/lib/phone.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAG1D"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "fayz": {
4
4
  "status": "preview"
5
5
  },
6
- "version": "0.9.0",
6
+ "version": "0.10.0",
7
7
  "description": "Fayz SDK — reusable auth runtime and UI integration plugin",
8
8
  "type": "module",
9
9
  "sideEffects": false,
@@ -12,19 +12,16 @@
12
12
  "types": "./dist/index.d.ts",
13
13
  "exports": {
14
14
  ".": {
15
- "source": "./src/index.ts",
16
15
  "types": "./dist/index.d.ts",
17
16
  "import": "./dist/index.js"
18
17
  },
19
18
  "./website": {
20
- "source": "./src/website/index.tsx",
21
19
  "types": "./dist/website/index.d.ts",
22
20
  "import": "./dist/website/index.js"
23
21
  }
24
22
  },
25
23
  "files": [
26
- "dist",
27
- "src"
24
+ "dist"
28
25
  ],
29
26
  "peerDependencies": {
30
27
  "react": "^18.0.0 || ^19.0.0",
@@ -33,9 +30,9 @@
33
30
  },
34
31
  "dependencies": {
35
32
  "@radix-ui/react-dialog": "^1.1.0",
36
- "@fayz-ai/auth": "^0.9.0",
37
- "@fayz-ai/core": "^0.9.0",
38
- "@fayz-ai/ui": "^0.9.0"
33
+ "@fayz-ai/auth": "^0.11.0",
34
+ "@fayz-ai/core": "^0.11.0",
35
+ "@fayz-ai/ui": "^0.11.0"
39
36
  },
40
37
  "devDependencies": {
41
38
  "@types/react": "^18.3.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmbassadorBubbles.d.ts","sourceRoot":"","sources":["../src/AmbassadorBubbles.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAwB9C,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;IAC/B,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,sBAAsB,4BA6B/E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../src/forms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAkBjD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAsB,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,iBAAiB,qBAmBpG;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IACjD;yCACqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC;AAED,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,YAAiB,EACjB,aAAa,GACd,EAAE,cAAc,qBAqDhB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,EAAE,eAAe,qBAsDxD;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;kEAC8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,UAAU,EACV,MAAM,EACN,aAAa,EACb,YAAiB,EACjB,aAAa,EACb,UAAoB,EACpB,WAA+B,EAC/B,YAA2B,EAC3B,SAA+C,EAC/C,SAA2B,GAC5B,EAAE,uBAAuB,qBAiDzB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBA4CtE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAIjD,OAAO,KAAK,EAAgB,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAExE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;yFACqF;IACrF,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAA;IACpC,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAe,EACf,IAAI,EACJ,SAAS,EACT,MAAgB,EAChB,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,SAAS,GACV,EAAE,cAAc,qBAmGhB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,QAAQ,CAAC,EAAE,WAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,aAAa,qBAevG;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,qBAAqB,qBA8B7E;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;gFACgF;AAChF,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBAEtE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAQpE,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,iBAAsB,GAAG,WAAW,CA0B/E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAwBrF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAEpF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"set-password.d.ts","sourceRoot":"","sources":["../src/set-password.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAA;AAuBrD,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChC,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAA;IAChB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAmBxD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,OAAe,EACf,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,SAAS,GACV,EAAE,oBAAoB,qBA+HtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AuthModalProvider.d.ts","sourceRoot":"","sources":["../../src/website/AuthModalProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3E,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE5E,UAAU,qBAAqB;IAC7B,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,eAAe,EAAE,OAAO,CAAA;CACzB;AAID,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,SAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,sBAAsB,+BAa/F;AAED,wFAAwF;AACxF,wBAAgB,YAAY,IAAI,qBAAqB,CAQpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"PhoneAuthModal.d.ts","sourceRoot":"","sources":["../../src/website/PhoneAuthModal.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAID;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EAAE,OAAO,EAAE,MAAM,GACtB,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;CAAE,+BAyJvE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../src/website/phone.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAG1D"}
@@ -1,61 +0,0 @@
1
- import * as React from 'react'
2
- import type { LoginAmbassador } from './types'
3
-
4
- /**
5
- * Social-proof "ambassador" strip for the split-login brand panel. Restores
6
- * (modernized) the old login avatar cluster: a short row of small, softly
7
- * overlapping circular portraits sitting just above the tagline, optionally
8
- * followed by a microtext label ("+2 mil profissionais").
9
- *
10
- * Small (40px), subtle, no flashy motion — a very gentle idle float only, which
11
- * fully disables under prefers-reduced-motion. Degrades to nothing when no
12
- * usable images are supplied, so it is always safe to render. Purely
13
- * presentational — never touches the auth flow.
14
- */
15
-
16
- const FLOAT_STYLES = `
17
- @keyframes fayz-amb-drift {
18
- 0%, 100% { transform: translateY(0); }
19
- 50% { transform: translateY(-2px); }
20
- }
21
- @media (prefers-reduced-motion: reduce) {
22
- .fayz-amb-avatar { animation: none !important; }
23
- }
24
- `
25
-
26
- export interface AmbassadorBubblesProps {
27
- ambassadors?: LoginAmbassador[]
28
- /** Optional social-proof caption shown beside the avatars, e.g. "+2 mil profissionais". */
29
- label?: string
30
- }
31
-
32
- export function AmbassadorBubbles({ ambassadors, label }: AmbassadorBubblesProps) {
33
- const items = (ambassadors ?? []).filter((a) => a && typeof a.image === 'string' && a.image.trim() !== '')
34
- if (items.length === 0) return null
35
- const shown = items.slice(0, 5)
36
-
37
- return (
38
- <div className="flex items-center gap-3">
39
- <style>{FLOAT_STYLES}</style>
40
- <div className="flex -space-x-2">
41
- {shown.map((ambassador, index) => (
42
- <div
43
- key={`${ambassador.name}-${index}`}
44
- title={ambassador.role ? `${ambassador.name} · ${ambassador.role}` : ambassador.name}
45
- className="fayz-amb-avatar relative h-10 w-10 shrink-0 overflow-hidden rounded-full border-2 border-sidebar bg-sidebar-accent shadow-md ring-1 ring-sidebar-foreground/10 transition-transform duration-200 hover:z-10 hover:scale-110"
46
- style={{ animation: `fayz-amb-drift 4s ease-in-out ${index * 0.4}s infinite` }}
47
- >
48
- <img
49
- src={ambassador.image}
50
- alt={ambassador.name}
51
- className="h-full w-full object-cover"
52
- loading="lazy"
53
- draggable={false}
54
- />
55
- </div>
56
- ))}
57
- </div>
58
- {label ? <p className="text-xs font-medium text-sidebar-foreground/80">{label}</p> : null}
59
- </div>
60
- )
61
- }
package/src/forms.tsx DELETED
@@ -1,307 +0,0 @@
1
- import * as React from 'react'
2
- import { useAuth } from '@fayz-ai/auth'
3
- import type { AuthProvider } from '@fayz-ai/core'
4
-
5
- function providerLabel(provider: string): string {
6
- return provider.charAt(0).toUpperCase() + provider.slice(1)
7
- }
8
-
9
- function fieldClass() {
10
- return 'h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50'
11
- }
12
-
13
- function buttonClass(variant: 'primary' | 'outline' | 'ghost' = 'primary') {
14
- if (variant === 'outline') {
15
- return 'inline-flex h-10 w-full items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50'
16
- }
17
- if (variant === 'ghost') return 'text-sm font-medium text-primary hover:underline'
18
- return 'inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50'
19
- }
20
-
21
- export interface OAuthButtonsProps {
22
- providers?: Exclude<AuthProvider, 'email'>[]
23
- disabled?: boolean
24
- onProviderClick?: (provider: AuthProvider) => void | Promise<void>
25
- }
26
-
27
- export function OAuthButtons({ providers = ['google'], disabled, onProviderClick }: OAuthButtonsProps) {
28
- const { signInWithOAuth } = useAuth()
29
- return (
30
- <div className="space-y-2">
31
- {providers.map((provider) => (
32
- <button
33
- key={provider}
34
- type="button"
35
- className={buttonClass('outline')}
36
- disabled={disabled}
37
- onClick={() => {
38
- void (onProviderClick ? onProviderClick(provider) : signInWithOAuth(provider))
39
- }}
40
- >
41
- Continue with {providerLabel(provider)}
42
- </button>
43
- ))}
44
- </div>
45
- )
46
- }
47
-
48
- export interface LoginFormProps {
49
- onSuccess?: () => void
50
- onForgotPassword?: () => void
51
- showOAuth?: boolean
52
- oauthProviders?: Exclude<AuthProvider, 'email'>[]
53
- /** Seeds the field, so switching between login and recovery never asks for the
54
- * e-mail the user already typed. */
55
- initialEmail?: string
56
- onEmailChange?: (email: string) => void
57
- }
58
-
59
- export function LoginForm({
60
- onSuccess,
61
- onForgotPassword,
62
- showOAuth,
63
- oauthProviders,
64
- initialEmail = '',
65
- onEmailChange,
66
- }: LoginFormProps) {
67
- const { signIn, error, isLoading } = useAuth()
68
- const [email, setEmail] = React.useState(initialEmail)
69
- const [password, setPassword] = React.useState('')
70
- const [busy, setBusy] = React.useState(false)
71
- const disabled = busy || isLoading
72
-
73
- async function submit(event: React.FormEvent) {
74
- event.preventDefault()
75
- setBusy(true)
76
- try {
77
- await signIn(email, password)
78
- onSuccess?.()
79
- } finally {
80
- setBusy(false)
81
- }
82
- }
83
-
84
- return (
85
- <form onSubmit={submit} className="space-y-4">
86
- <label className="block space-y-1.5 text-sm font-medium">
87
- <span>Email</span>
88
- <input
89
- className={fieldClass()}
90
- type="email"
91
- autoComplete="username"
92
- required
93
- value={email}
94
- onChange={(e) => {
95
- setEmail(e.target.value)
96
- onEmailChange?.(e.target.value)
97
- }}
98
- disabled={disabled}
99
- />
100
- </label>
101
- <label className="block space-y-1.5 text-sm font-medium">
102
- <span>Password</span>
103
- <input className={fieldClass()} type="password" autoComplete="current-password" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />
104
- </label>
105
- {onForgotPassword && (
106
- <div className="-mt-1 flex justify-end">
107
- <button type="button" className={buttonClass('ghost')} onClick={onForgotPassword}>
108
- Forgot password?
109
- </button>
110
- </div>
111
- )}
112
- {error && <p className="text-sm text-destructive">{error.message}</p>}
113
- <button className={buttonClass()} type="submit" disabled={disabled}>
114
- {disabled ? 'Signing in...' : 'Sign in'}
115
- </button>
116
- {showOAuth && <OAuthButtons providers={oauthProviders} disabled={disabled} />}
117
- </form>
118
- )
119
- }
120
-
121
- export interface SignupFormProps {
122
- onSuccess?: () => void
123
- }
124
-
125
- export function SignupForm({ onSuccess }: SignupFormProps) {
126
- const { signUp, error, isLoading } = useAuth()
127
- const [fullName, setFullName] = React.useState('')
128
- const [email, setEmail] = React.useState('')
129
- const [password, setPassword] = React.useState('')
130
- const [confirmPassword, setConfirmPassword] = React.useState('')
131
- const [localError, setLocalError] = React.useState<string | null>(null)
132
- const [busy, setBusy] = React.useState(false)
133
- const disabled = busy || isLoading
134
-
135
- async function submit(event: React.FormEvent) {
136
- event.preventDefault()
137
- setLocalError(null)
138
- if (password.length < 8) {
139
- setLocalError('Password must be at least 8 characters.')
140
- return
141
- }
142
- if (password !== confirmPassword) {
143
- setLocalError('Passwords do not match.')
144
- return
145
- }
146
- setBusy(true)
147
- try {
148
- await signUp(email, password, fullName)
149
- onSuccess?.()
150
- } finally {
151
- setBusy(false)
152
- }
153
- }
154
-
155
- return (
156
- <form onSubmit={submit} className="space-y-4">
157
- <label className="block space-y-1.5 text-sm font-medium">
158
- <span>Full name</span>
159
- <input className={fieldClass()} required value={fullName} onChange={(e) => setFullName(e.target.value)} disabled={disabled} />
160
- </label>
161
- <label className="block space-y-1.5 text-sm font-medium">
162
- <span>Email</span>
163
- <input className={fieldClass()} type="email" autoComplete="username" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />
164
- </label>
165
- <label className="block space-y-1.5 text-sm font-medium">
166
- <span>Password</span>
167
- <input className={fieldClass()} type="password" autoComplete="new-password" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />
168
- </label>
169
- <label className="block space-y-1.5 text-sm font-medium">
170
- <span>Confirm password</span>
171
- <input className={fieldClass()} type="password" autoComplete="new-password" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />
172
- </label>
173
- {(localError || error) && <p className="text-sm text-destructive">{localError ?? error?.message}</p>}
174
- <button className={buttonClass()} type="submit" disabled={disabled}>
175
- {disabled ? 'Creating account...' : 'Create account'}
176
- </button>
177
- </form>
178
- )
179
- }
180
-
181
- export interface ForgotPasswordFormProps {
182
- redirectTo?: string
183
- onSent?: (email: string) => void
184
- onBackToLogin?: () => void
185
- /** Pre-filled with whatever the user already typed on the login form. */
186
- initialEmail?: string
187
- onEmailChange?: (email: string) => void
188
- /** Copy overrides — the set-password screen reuses this form to hand out a
189
- * fresh link, where "Send reset link" is the wrong label. */
190
- emailLabel?: string
191
- submitLabel?: string
192
- sendingLabel?: string
193
- sentLabel?: string
194
- backLabel?: string
195
- }
196
-
197
- export function ForgotPasswordForm({
198
- redirectTo,
199
- onSent,
200
- onBackToLogin,
201
- initialEmail = '',
202
- onEmailChange,
203
- emailLabel = 'Email',
204
- submitLabel = 'Send reset link',
205
- sendingLabel = 'Sending...',
206
- sentLabel = 'Password reset instructions sent.',
207
- backLabel = 'Back to login',
208
- }: ForgotPasswordFormProps) {
209
- const { resetPassword, error, isLoading } = useAuth()
210
- const [email, setEmail] = React.useState(initialEmail)
211
- const [sent, setSent] = React.useState(false)
212
- const [busy, setBusy] = React.useState(false)
213
- const disabled = busy || isLoading
214
-
215
- async function submit(event: React.FormEvent) {
216
- event.preventDefault()
217
- setBusy(true)
218
- try {
219
- await resetPassword(email, { redirectTo })
220
- setSent(true)
221
- onSent?.(email)
222
- } finally {
223
- setBusy(false)
224
- }
225
- }
226
-
227
- return (
228
- <form onSubmit={submit} className="space-y-4">
229
- <label className="block space-y-1.5 text-sm font-medium">
230
- <span>{emailLabel}</span>
231
- <input
232
- className={fieldClass()}
233
- type="email"
234
- autoComplete="username"
235
- required
236
- autoFocus={!email}
237
- value={email}
238
- onChange={(e) => {
239
- setEmail(e.target.value)
240
- onEmailChange?.(e.target.value)
241
- }}
242
- disabled={disabled}
243
- />
244
- </label>
245
- {error && <p className="text-sm text-destructive">{error.message}</p>}
246
- {sent && <p className="text-sm text-emerald-600">{sentLabel}</p>}
247
- <button className={buttonClass()} type="submit" disabled={disabled}>
248
- {disabled ? sendingLabel : submitLabel}
249
- </button>
250
- {onBackToLogin && (
251
- <button type="button" className={buttonClass('ghost')} onClick={onBackToLogin}>
252
- {backLabel}
253
- </button>
254
- )}
255
- </form>
256
- )
257
- }
258
-
259
- export interface ResetPasswordFormProps {
260
- onSuccess?: () => void
261
- }
262
-
263
- export function ResetPasswordForm({ onSuccess }: ResetPasswordFormProps) {
264
- const { updatePassword, error, isLoading } = useAuth()
265
- const [password, setPassword] = React.useState('')
266
- const [confirmPassword, setConfirmPassword] = React.useState('')
267
- const [localError, setLocalError] = React.useState<string | null>(null)
268
- const [busy, setBusy] = React.useState(false)
269
- const disabled = busy || isLoading
270
-
271
- async function submit(event: React.FormEvent) {
272
- event.preventDefault()
273
- setLocalError(null)
274
- if (password.length < 8) {
275
- setLocalError('Password must be at least 8 characters.')
276
- return
277
- }
278
- if (password !== confirmPassword) {
279
- setLocalError('Passwords do not match.')
280
- return
281
- }
282
- setBusy(true)
283
- try {
284
- await updatePassword(password)
285
- onSuccess?.()
286
- } finally {
287
- setBusy(false)
288
- }
289
- }
290
-
291
- return (
292
- <form onSubmit={submit} className="space-y-4">
293
- <label className="block space-y-1.5 text-sm font-medium">
294
- <span>New password</span>
295
- <input className={fieldClass()} type="password" autoComplete="new-password" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />
296
- </label>
297
- <label className="block space-y-1.5 text-sm font-medium">
298
- <span>Confirm password</span>
299
- <input className={fieldClass()} type="password" autoComplete="new-password" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />
300
- </label>
301
- {(localError || error) && <p className="text-sm text-destructive">{localError ?? error?.message}</p>}
302
- <button className={buttonClass()} type="submit" disabled={disabled}>
303
- {disabled ? 'Saving...' : 'Update password'}
304
- </button>
305
- </form>
306
- )
307
- }
package/src/index.ts DELETED
@@ -1,56 +0,0 @@
1
- export {
2
- createAuthPlugin,
3
- createAuthRuntime,
4
- resolveAuthAdapter,
5
- } from './runtime'
6
- export {
7
- AuthGate,
8
- LoginPage,
9
- AuthCallbackPage,
10
- ResetPasswordPage,
11
- } from './pages'
12
- export type {
13
- AuthCallbackPageProps,
14
- AuthGateProps,
15
- LoginPageProps,
16
- ResetPasswordPageProps,
17
- } from './pages'
18
- export { SetPasswordPage, usePasswordSetupGate } from './set-password'
19
- export type { SetPasswordPageProps, SetPasswordReason, PasswordSetupGate } from './set-password'
20
- export { AmbassadorBubbles } from './AmbassadorBubbles'
21
- export type { AmbassadorBubblesProps } from './AmbassadorBubbles'
22
- export {
23
- LoginForm,
24
- SignupForm,
25
- ForgotPasswordForm,
26
- ResetPasswordForm,
27
- OAuthButtons,
28
- } from './forms'
29
- export type {
30
- ForgotPasswordFormProps,
31
- LoginFormProps,
32
- OAuthButtonsProps,
33
- ResetPasswordFormProps,
34
- SignupFormProps,
35
- } from './forms'
36
- export {
37
- createMockAuthAdapter,
38
- createSupabaseAuthAdapter,
39
- AuthProvider,
40
- useAuth,
41
- useAuthStore,
42
- readAuthUrlIntent,
43
- clearAuthUrlTokens,
44
- } from '@fayz-ai/auth'
45
- export type {
46
- AuthPluginOptions,
47
- ResolvedAuthPlugin,
48
- AuthRoutesConfig,
49
- AuthOAuthConfig,
50
- AuthSupabaseConfig,
51
- AuthProviderKey,
52
- AuthLayout,
53
- AuthFormView,
54
- LoginAmbassador,
55
- } from './types'
56
- export type { AuthAdapter, AuthSession, AuthUser, AuthProvider as OAuthProvider } from '@fayz-ai/core'