@fayz-ai/plugin-auth 0.8.0 → 0.9.0-next.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.
@@ -1,275 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var Dialog = require('@radix-ui/react-dialog');
5
- var lucideReact = require('lucide-react');
6
- var core = require('@fayz-ai/core');
7
- var auth = require('@fayz-ai/auth');
8
- var jsxRuntime = require('react/jsx-runtime');
9
-
10
- function _interopNamespace(e) {
11
- if (e && e.__esModule) return e;
12
- var n = Object.create(null);
13
- if (e) {
14
- Object.keys(e).forEach(function (k) {
15
- if (k !== 'default') {
16
- var d = Object.getOwnPropertyDescriptor(e, k);
17
- Object.defineProperty(n, k, d.get ? d : {
18
- enumerable: true,
19
- get: function () { return e[k]; }
20
- });
21
- }
22
- });
23
- }
24
- n.default = e;
25
- return Object.freeze(n);
26
- }
27
-
28
- var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
29
-
30
- // src/website/AuthModalProvider.tsx
31
- function phoneToEmail(phoneWithDial) {
32
- const digits = core.unmaskPhone(phoneWithDial);
33
- return `${digits || "anon"}@phone.fayz.local`;
34
- }
35
- function PhoneAuthModal({
36
- open,
37
- onClose,
38
- config
39
- }) {
40
- const { signUp } = auth.useAuth();
41
- const [mode, setMode] = react.useState("signup");
42
- const [step, setStep] = react.useState("phone");
43
- const [countryIso, setCountryIso] = react.useState(core.DEFAULT_COUNTRY);
44
- const country = core.getCountry(countryIso);
45
- const [phone, setPhone] = react.useState("");
46
- const [name, setName] = react.useState("");
47
- const [code, setCode] = react.useState("");
48
- const [codeError, setCodeError] = react.useState(false);
49
- const [busy, setBusy] = react.useState(false);
50
- react.useEffect(() => {
51
- if (open) {
52
- setStep("phone");
53
- setCode("");
54
- setCodeError(false);
55
- setBusy(false);
56
- }
57
- }, [open]);
58
- function sendCode() {
59
- if (core.unmaskPhone(phone).length < 8) return;
60
- setCode("");
61
- setCodeError(false);
62
- setStep("code");
63
- }
64
- async function confirmCode() {
65
- if (code.trim() !== "0000") {
66
- setCodeError(true);
67
- return;
68
- }
69
- setBusy(true);
70
- try {
71
- await signUp(phoneToEmail(`${country.dial} ${phone}`), core.unmaskPhone(phone), name.trim() || "Cliente");
72
- onClose();
73
- } catch {
74
- setCodeError(true);
75
- } finally {
76
- setBusy(false);
77
- }
78
- }
79
- const brandLabel = config?.brand ? ` na ${config.brand}` : "";
80
- return /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Root, { open, onOpenChange: (o) => {
81
- if (!o) onClose();
82
- }, children: /* @__PURE__ */ jsxRuntime.jsxs(Dialog__namespace.Portal, { children: [
83
- /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.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" }),
84
- /* @__PURE__ */ jsxRuntime.jsxs(
85
- Dialog__namespace.Content,
86
- {
87
- onOpenAutoFocus: (e) => e.preventDefault(),
88
- 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",
89
- children: [
90
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
91
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-accent text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Smartphone, { className: "h-5 w-5" }) }),
92
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
93
- /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Title, { className: "text-base font-semibold text-foreground", children: config?.title ?? "Acessar sua conta" }),
94
- /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Description, { className: "text-xs text-muted-foreground", children: mode === "signup" ? `Crie sua conta${brandLabel} em segundos` : `Bem-vindo de volta${brandLabel}` })
95
- ] })
96
- ] }),
97
- /* @__PURE__ */ jsxRuntime.jsx(
98
- Dialog__namespace.Close,
99
- {
100
- "aria-label": "Fechar",
101
- 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",
102
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
103
- }
104
- ),
105
- step === "phone" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-5 grid grid-cols-2 gap-1 rounded-lg bg-muted p-1 text-sm", children: ["signin", "signup"].map((m) => /* @__PURE__ */ jsxRuntime.jsx(
106
- "button",
107
- {
108
- type: "button",
109
- onClick: () => setMode(m),
110
- className: `rounded-md py-1.5 font-medium transition-colors ${mode === m ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
111
- children: m === "signin" ? "Entrar" : "Criar conta"
112
- },
113
- m
114
- )) }) : null,
115
- step === "phone" ? /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => {
116
- e.preventDefault();
117
- sendCode();
118
- }, className: "mt-4 space-y-3", children: [
119
- mode === "signup" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
120
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "auth-name", className: "mb-1 block text-sm font-medium text-foreground", children: "Nome" }),
121
- /* @__PURE__ */ jsxRuntime.jsx(
122
- "input",
123
- {
124
- id: "auth-name",
125
- type: "text",
126
- autoComplete: "name",
127
- value: name,
128
- onChange: (e) => setName(e.target.value),
129
- 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",
130
- placeholder: "Seu nome"
131
- }
132
- )
133
- ] }) : null,
134
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
135
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "auth-phone", className: "mb-1 block text-sm font-medium text-foreground", children: "Celular" }),
136
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
137
- /* @__PURE__ */ jsxRuntime.jsx(
138
- "select",
139
- {
140
- "aria-label": "Pa\xEDs",
141
- value: countryIso,
142
- onChange: (e) => {
143
- const c = core.getCountry(e.target.value);
144
- setCountryIso(c.iso2);
145
- setPhone(core.maskPhone(core.unmaskPhone(phone), c.mask));
146
- },
147
- 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",
148
- children: core.COUNTRIES.map((c) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: c.iso2, children: [
149
- c.flag,
150
- " ",
151
- c.dial
152
- ] }, c.iso2))
153
- }
154
- ),
155
- /* @__PURE__ */ jsxRuntime.jsx(
156
- "input",
157
- {
158
- id: "auth-phone",
159
- type: "tel",
160
- autoComplete: "tel",
161
- inputMode: "tel",
162
- value: phone,
163
- autoFocus: true,
164
- onChange: (e) => setPhone(core.maskPhone(e.target.value, country.mask)),
165
- 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",
166
- placeholder: `Ex.: ${core.maskPhone("11987654321", country.mask)}`
167
- }
168
- )
169
- ] })
170
- ] }),
171
- /* @__PURE__ */ jsxRuntime.jsx(
172
- "button",
173
- {
174
- type: "submit",
175
- disabled: core.unmaskPhone(phone).length < 8,
176
- 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",
177
- children: "Enviar c\xF3digo via WhatsApp"
178
- }
179
- ),
180
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-xs text-muted-foreground", children: "Enviaremos um c\xF3digo para confirmar seu n\xFAmero." })
181
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => {
182
- e.preventDefault();
183
- void confirmCode();
184
- }, className: "mt-5 space-y-3", children: [
185
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
186
- "Enviamos um c\xF3digo via WhatsApp para ",
187
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium text-foreground", children: [
188
- country.flag,
189
- " ",
190
- country.dial,
191
- " ",
192
- phone
193
- ] }),
194
- "."
195
- ] }),
196
- /* @__PURE__ */ jsxRuntime.jsx(
197
- "input",
198
- {
199
- type: "text",
200
- inputMode: "numeric",
201
- value: code,
202
- autoFocus: true,
203
- onChange: (e) => {
204
- setCode(e.target.value);
205
- setCodeError(false);
206
- },
207
- 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",
208
- placeholder: "Digite o c\xF3digo"
209
- }
210
- ),
211
- codeError ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-sm text-destructive", children: "C\xF3digo inv\xE1lido. Para testar, use 0000." }) : null,
212
- /* @__PURE__ */ jsxRuntime.jsx(
213
- "button",
214
- {
215
- type: "submit",
216
- disabled: busy,
217
- 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",
218
- children: busy ? "Entrando\u2026" : mode === "signup" ? "Criar conta e entrar" : "Confirmar e entrar"
219
- }
220
- ),
221
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: () => setStep("phone"), className: "mx-auto flex items-center gap-1 text-sm font-medium text-primary hover:underline", children: [
222
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-3.5 w-3.5" }),
223
- " Trocar n\xFAmero"
224
- ] })
225
- ] })
226
- ]
227
- }
228
- )
229
- ] }) });
230
- }
231
- var AuthModalContext = react.createContext(null);
232
- function AuthModalProvider({ phoneAuth = true, config, children }) {
233
- const [open, setOpen] = react.useState(false);
234
- const value = {
235
- openAuthModal: () => setOpen(true),
236
- closeAuthModal: () => setOpen(false),
237
- isAuthModalOpen: open
238
- };
239
- return /* @__PURE__ */ jsxRuntime.jsxs(AuthModalContext.Provider, { value, children: [
240
- children,
241
- phoneAuth ? /* @__PURE__ */ jsxRuntime.jsx(PhoneAuthModal, { open, onClose: () => setOpen(false), config }) : null
242
- ] });
243
- }
244
- function useAuthModal() {
245
- return react.useContext(AuthModalContext) ?? {
246
- openAuthModal: () => {
247
- },
248
- closeAuthModal: () => {
249
- },
250
- isAuthModalOpen: false
251
- };
252
- }
253
-
254
- Object.defineProperty(exports, "AuthProvider", {
255
- enumerable: true,
256
- get: function () { return auth.AuthProvider; }
257
- });
258
- Object.defineProperty(exports, "createMockAuthAdapter", {
259
- enumerable: true,
260
- get: function () { return auth.createMockAuthAdapter; }
261
- });
262
- Object.defineProperty(exports, "createSupabaseAuthAdapter", {
263
- enumerable: true,
264
- get: function () { return auth.createSupabaseAuthAdapter; }
265
- });
266
- Object.defineProperty(exports, "useAuth", {
267
- enumerable: true,
268
- get: function () { return auth.useAuth; }
269
- });
270
- exports.AuthModalProvider = AuthModalProvider;
271
- exports.PhoneAuthModal = PhoneAuthModal;
272
- exports.phoneToEmail = phoneToEmail;
273
- exports.useAuthModal = useAuthModal;
274
- //# sourceMappingURL=index.cjs.map
275
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/website/phone.ts","../../src/website/PhoneAuthModal.tsx","../../src/website/AuthModalProvider.tsx"],"names":["unmaskPhone","useAuth","useState","DEFAULT_COUNTRY","getCountry","useEffect","Dialog","jsxs","jsx","Smartphone","X","maskPhone","COUNTRIES","ArrowLeft","createContext","useContext"],"mappings":"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","file":"index.cjs","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"]}