@geekapps/auth-elements-nextjs 0.2.5 → 0.4.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/README.md CHANGED
@@ -1,17 +1,63 @@
1
1
  # @geekapps/auth-elements-nextjs
2
2
 
3
- Componentes headless/visuais simples para consumir `@geekapps/auth-nextjs`.
3
+ Componentes visuais simples para usar com `@geekapps/auth-nextjs`. Módulo separado: **não importa** o auth-nextjs em runtime, recebe o hook por `createAuthElements({ useAuth })`. Tem build, estilos (Tailwind) e versionamento próprios.
4
4
 
5
- Não usa shadcn/ui, Radix, GSAP ou bibliotecas de UI. Os componentes são React + classes Tailwind.
5
+ Não usa shadcn/ui, Radix, GSAP ou bibliotecas de UI. Apenas React + classes Tailwind.
6
6
 
7
- Componentes principais:
7
+ ## Instalação
8
8
 
9
- - `Avatar`
10
- - `AccountSwitcher`
11
- - `OrgSwitcher`
12
- - `ProfileModal`
13
- - `ManageOrganizationModal`
14
- - `UserButton`
15
- - `OrganizationButton`
16
- - `SignInButton`
17
- - `SignOutButton`
9
+ ```bash
10
+ bun add @geekapps/auth-nextjs @geekapps/auth-elements-nextjs
11
+ ```
12
+
13
+ ## Uso (Next.js)
14
+
15
+ Crie um módulo client, por exemplo `components/auth-elements.ts`:
16
+
17
+ ```tsx
18
+ "use client";
19
+
20
+ import { useAuth } from "@geekapps/auth-nextjs/client";
21
+ import { createAuthElements } from "@geekapps/auth-elements-nextjs";
22
+
23
+ export const {
24
+ SignInButton,
25
+ SignOutButton,
26
+ UserButton,
27
+ OrganizationButton,
28
+ OrgSwitcher,
29
+ AccountSwitcher,
30
+ ProfileModal,
31
+ ManageOrganizationModal,
32
+ CreateOrganizationForm,
33
+ WaitlistForm,
34
+ } = createAuthElements({ useAuth });
35
+ ```
36
+
37
+ No layout, importe os estilos uma vez:
38
+
39
+ ```tsx
40
+ import "@geekapps/auth-elements-nextjs/styles.css";
41
+ ```
42
+
43
+ Os componentes devem ficar dentro do `GeekappsAuthProvider` do auth-nextjs.
44
+
45
+ ## Elementos
46
+
47
+ - `Avatar`, `Modal` (exports diretos)
48
+ - `SignInButton`, `SignOutButton`
49
+ - `AccountSwitcher`, `OrgSwitcher`
50
+ - `UserButton`, `OrganizationButton`
51
+ - `ProfileModal`, `ManageOrganizationModal`
52
+ - `CreateOrganizationForm`
53
+ - `WaitlistForm` — nome + e-mail, usa `useAuth().joinWaitlist`; props `clientId` (obrigatória), `defaultEmail`, `onJoined`, `submitLabel`. Após entrar mostra a posição na fila.
54
+
55
+ Erros do auth-nextjs são traduzidos pelo `code` (`waitlist_required`, `waitlist_disabled`, `password_reset_required`, `account_locked` com `retryAfter`); sem código conhecido, usa o `error` original. O helper `authErrorMessage(result, fallback)` é exportado.
56
+
57
+ ## Compatibilidade
58
+
59
+ Testado contra `@geekapps/auth-nextjs` 0.26.x. Funciona com versões anteriores (>=0.20): membros novos do contrato são opcionais (`lookupTaxId?`, `joinWaitlist?`); sem `joinWaitlist` o `WaitlistForm` mostra um aviso para atualizar.
60
+
61
+ ## Guarda de contrato
62
+
63
+ `bun run check:contract` compila `tests/contract.ts`, que verifica (só tipos) que `typeof useAuth` de `@geekapps/auth-nextjs/client` é atribuível ao contrato do elements. O auth-nextjs é resolvido pelo workspace (`../auth-nextjs/dist`; rode o build dele antes). Falha de compilação = o contrato divergiu.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  type ElementSize = "sm" | "md" | "lg";
@@ -23,6 +23,10 @@ type Organization = {
23
23
  domain: string | null;
24
24
  imageUrl: string | null;
25
25
  faviconUrl: string | null;
26
+ type?: OrganizationType;
27
+ taxId?: string | null;
28
+ taxIdType?: TaxIdType | null;
29
+ legalName?: string | null;
26
30
  members?: Array<{
27
31
  id: string;
28
32
  user: {
@@ -41,6 +45,40 @@ type Organization = {
41
45
  }>;
42
46
  }>;
43
47
  };
48
+ type OrganizationType = "standard" | "legal";
49
+ type TaxIdType = "br_cnpj" | "generic";
50
+ type OrganizationLegalAddress = Partial<Record<"street" | "number" | "complement" | "district" | "city" | "state" | "postalCode" | "country", string | null>>;
51
+ type OrganizationCreateInput = {
52
+ name: string;
53
+ slug: string;
54
+ type?: OrganizationType;
55
+ taxId?: string | null;
56
+ taxIdType?: TaxIdType | null;
57
+ taxIdCountry?: string | null;
58
+ legalName?: string | null;
59
+ tradeName?: string | null;
60
+ legalEmail?: string | null;
61
+ legalPhone?: string | null;
62
+ legalAddress?: OrganizationLegalAddress | null;
63
+ };
64
+ type TaxIdLookupResult = {
65
+ taxId: string;
66
+ taxIdType: TaxIdType;
67
+ taxIdCountry: string | null;
68
+ alreadyRegistered: boolean;
69
+ lookupAvailable: boolean;
70
+ found: boolean;
71
+ registrationStatus: string | null;
72
+ suggestedName: string | null;
73
+ data: {
74
+ legalName: string | null;
75
+ tradeName: string | null;
76
+ legalEmail: string | null;
77
+ legalPhone: string | null;
78
+ legalAddress: OrganizationLegalAddress | null;
79
+ };
80
+ missingFields: string[];
81
+ };
44
82
  type Permission = {
45
83
  id: string;
46
84
  key: string;
@@ -65,13 +103,34 @@ type User = {
65
103
  imageUrl: string | null;
66
104
  phone?: string | null;
67
105
  };
106
+ /** Espelha `AuthResult` do auth-nextjs >=0.26 (campos extras são opcionais). */
68
107
  type AuthResult<T> = {
69
108
  success: true;
70
109
  data: T;
71
110
  } | {
72
111
  success: false;
73
112
  error?: string;
113
+ status?: number;
114
+ code?: string;
115
+ retryAfter?: number;
116
+ missingFields?: string[];
74
117
  };
118
+ type JoinWaitlistParams = {
119
+ clientId: string;
120
+ email: string;
121
+ name?: string;
122
+ };
123
+ type JoinWaitlistResponse = {
124
+ ok: true;
125
+ status: "waiting" | "approved" | "joined";
126
+ position: number | null;
127
+ };
128
+ /** Mensagem em português para um resultado de erro; `fallback` se o código for desconhecido. */
129
+ declare function authErrorMessage(result: {
130
+ error?: string;
131
+ code?: string;
132
+ retryAfter?: number;
133
+ }, fallback: string): string;
75
134
  type UseAuthHook = () => {
76
135
  user: User | null;
77
136
  signIn: (opts?: {
@@ -94,10 +153,11 @@ type UseAuthHook = () => {
94
153
  isLoadingOrganizations: boolean;
95
154
  refreshOrganizations: () => Promise<void>;
96
155
  setCurrentOrg: (id: string) => Promise<void>;
97
- createOrganization: (input: {
98
- name: string;
99
- slug: string;
100
- }) => Promise<AuthResult<Organization>>;
156
+ createOrganization: (input: OrganizationCreateInput) => Promise<AuthResult<Organization>>;
157
+ /** Opcional: SDKs antigos não têm — sem ele, o formulário só não busca os dados do CNPJ. */
158
+ lookupTaxId?: (value: string, type?: TaxIdType) => Promise<AuthResult<TaxIdLookupResult>>;
159
+ /** Opcional (auth-nextjs >=0.26): sem ele o WaitlistForm mostra um aviso. */
160
+ joinWaitlist?: (params: JoinWaitlistParams) => Promise<AuthResult<JoinWaitlistResponse>>;
101
161
  updateOrganization: (id: string, input: Partial<{
102
162
  name: string;
103
163
  slug: string;
@@ -134,7 +194,7 @@ declare function Avatar({ src, name, size, className, }: {
134
194
  name?: string | null;
135
195
  size?: ElementSize;
136
196
  className?: string;
137
- }): react_jsx_runtime.JSX.Element;
197
+ }): react.JSX.Element;
138
198
  declare function Modal({ open, onOpenChange, title, description, children, footer, }: {
139
199
  open: boolean;
140
200
  onOpenChange: (open: boolean) => void;
@@ -142,7 +202,7 @@ declare function Modal({ open, onOpenChange, title, description, children, foote
142
202
  description?: string;
143
203
  children: ReactNode;
144
204
  footer?: ReactNode;
145
- }): react_jsx_runtime.JSX.Element | null;
205
+ }): react.JSX.Element | null;
146
206
  /**
147
207
  * Creates auth UI components bound to the provided `useAuth` hook instance.
148
208
  * This lets consumers supply their own auth-nextjs instance without requiring
@@ -156,25 +216,36 @@ declare function Modal({ open, onOpenChange, title, description, children, foote
156
216
  declare function createAuthElements(hooks: {
157
217
  useAuth: UseAuthHook;
158
218
  }): {
219
+ WaitlistForm: ({ clientId, defaultEmail, onJoined, submitLabel, }: {
220
+ clientId: string;
221
+ defaultEmail?: string;
222
+ onJoined?: (response: JoinWaitlistResponse) => void;
223
+ submitLabel?: string;
224
+ }) => react.JSX.Element;
159
225
  SignInButton: ({ children, redirectTo, }: {
160
226
  children?: ReactNode;
161
227
  redirectTo?: string;
162
- }) => react_jsx_runtime.JSX.Element;
228
+ }) => react.JSX.Element;
163
229
  SignOutButton: ({ children }: {
164
230
  children?: ReactNode;
165
- }) => react_jsx_runtime.JSX.Element;
166
- AccountSwitcher: () => react_jsx_runtime.JSX.Element;
167
- OrgSwitcher: () => react_jsx_runtime.JSX.Element;
168
- UserButton: () => react_jsx_runtime.JSX.Element;
169
- OrganizationButton: () => react_jsx_runtime.JSX.Element;
231
+ }) => react.JSX.Element;
232
+ AccountSwitcher: () => react.JSX.Element;
233
+ OrgSwitcher: () => react.JSX.Element;
234
+ UserButton: () => react.JSX.Element;
235
+ OrganizationButton: () => react.JSX.Element;
170
236
  ProfileModal: ({ open, onOpenChange, }: {
171
237
  open: boolean;
172
238
  onOpenChange: (open: boolean) => void;
173
- }) => react_jsx_runtime.JSX.Element | null;
239
+ }) => react.JSX.Element | null;
174
240
  ManageOrganizationModal: ({ open, onOpenChange, }: {
175
241
  open: boolean;
176
242
  onOpenChange: (open: boolean) => void;
177
- }) => react_jsx_runtime.JSX.Element | null;
243
+ }) => react.JSX.Element | null;
244
+ CreateOrganizationForm: ({ onCreated, onCancel, compact, }: {
245
+ onCreated?: (organization: Organization) => void;
246
+ onCancel?: () => void;
247
+ compact?: boolean;
248
+ }) => react.JSX.Element;
178
249
  };
179
250
 
180
- export { Avatar, type ConnectedAccount, type ElementSize, type ElementTone, Modal, type Organization, type Permission, type Role, type UserSession, createAuthElements };
251
+ export { type AuthResult, Avatar, type ConnectedAccount, type ElementSize, type ElementTone, type JoinWaitlistParams, type JoinWaitlistResponse, Modal, type Organization, type OrganizationCreateInput, type OrganizationType, type Permission, type Role, type TaxIdLookupResult, type TaxIdType, type UserSession, authErrorMessage, createAuthElements };
package/dist/index.js CHANGED
@@ -6,6 +6,56 @@ import {
6
6
  useState
7
7
  } from "react";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ var ADDRESS_KEYS = [
10
+ "street",
11
+ "number",
12
+ "complement",
13
+ "district",
14
+ "city",
15
+ "state",
16
+ "postalCode",
17
+ "country"
18
+ ];
19
+ var REQUIRED_LEGAL = /* @__PURE__ */ new Set([
20
+ "taxIdCountry",
21
+ "legalName",
22
+ "legalAddress.street",
23
+ "legalAddress.city",
24
+ "legalAddress.postalCode",
25
+ "legalAddress.country"
26
+ ]);
27
+ var EMPTY_ORG_FORM = {
28
+ type: "standard",
29
+ taxIdType: "br_cnpj",
30
+ taxId: "",
31
+ name: "",
32
+ slug: ""
33
+ };
34
+ function slugify(value) {
35
+ return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
36
+ }
37
+ function authErrorMessage(result, fallback) {
38
+ switch (result.code) {
39
+ case "waitlist_required":
40
+ return "Esta aplica\xE7\xE3o est\xE1 com lista de espera. Entre na lista para receber acesso.";
41
+ case "waitlist_disabled":
42
+ return "A lista de espera n\xE3o est\xE1 ativa para esta aplica\xE7\xE3o.";
43
+ case "password_reset_required":
44
+ return "Sua senha precisa ser redefinida antes de continuar. Use a op\xE7\xE3o de recuperar senha.";
45
+ case "account_locked": {
46
+ const s = result.retryAfter;
47
+ if (typeof s === "number" && s > 0) {
48
+ const wait = s >= 60 ? `${Math.ceil(s / 60)} min` : `${s} s`;
49
+ return `Conta temporariamente bloqueada por tentativas excessivas. Tente novamente em ${wait}.`;
50
+ }
51
+ return "Conta temporariamente bloqueada. Tente novamente mais tarde.";
52
+ }
53
+ case "invalid_credentials":
54
+ return result.error ?? "E-mail ou senha incorretos.";
55
+ default:
56
+ return result.error ?? fallback;
57
+ }
58
+ }
9
59
  function cx(...classes) {
10
60
  return classes.filter(Boolean).join(" ");
11
61
  }
@@ -250,9 +300,199 @@ function createAuthElements(hooks) {
250
300
  ] })
251
301
  ] });
252
302
  }
303
+ function CreateOrganizationForm({
304
+ onCreated,
305
+ onCancel,
306
+ compact = false
307
+ }) {
308
+ const { createOrganization, lookupTaxId, setCurrentOrg } = useAuth();
309
+ const [values, setValues] = useState({ ...EMPTY_ORG_FORM });
310
+ const [missing, setMissing] = useState([]);
311
+ const [lookupInfo, setLookupInfo] = useState(null);
312
+ const [error, setError] = useState(null);
313
+ const [busy, setBusy] = useState(null);
314
+ const isLegal = values.type === "legal";
315
+ const isCnpj = values.taxIdType === "br_cnpj";
316
+ const set = (key, value) => setValues((current) => {
317
+ const next = { ...current, [key]: value };
318
+ if (key === "name" && !current.slugTouched) next.slug = slugify(value);
319
+ if (key === "slug") next.slugTouched = "1";
320
+ return next;
321
+ });
322
+ async function runLookup() {
323
+ if (!lookupTaxId || !values.taxId) return;
324
+ setBusy("lookup");
325
+ setError(null);
326
+ setLookupInfo(null);
327
+ const result = await lookupTaxId(values.taxId, values.taxIdType);
328
+ setBusy(null);
329
+ if (!result.success) {
330
+ setError(authErrorMessage(result, "Tax ID inv\xE1lido."));
331
+ return;
332
+ }
333
+ const { data } = result.data;
334
+ setValues((current) => {
335
+ const next = { ...current, taxId: result.data.taxId };
336
+ const fill = (key, value) => {
337
+ if (value && !current[key]) next[key] = value;
338
+ };
339
+ fill("legalName", data.legalName);
340
+ fill("tradeName", data.tradeName);
341
+ fill("legalEmail", data.legalEmail);
342
+ fill("legalPhone", data.legalPhone);
343
+ for (const key of ADDRESS_KEYS) fill(`legalAddress.${key}`, data.legalAddress?.[key]);
344
+ if (result.data.taxIdCountry) next.taxIdCountry = result.data.taxIdCountry;
345
+ if (!current.name && result.data.suggestedName) {
346
+ next.name = result.data.suggestedName;
347
+ if (!current.slugTouched) next.slug = slugify(result.data.suggestedName);
348
+ }
349
+ return next;
350
+ });
351
+ setMissing(result.data.missingFields);
352
+ if (result.data.alreadyRegistered) {
353
+ setError("J\xE1 existe uma organiza\xE7\xE3o com este documento neste app.");
354
+ } else if (result.data.found) {
355
+ setLookupInfo(
356
+ `Dados encontrados${result.data.registrationStatus ? ` \xB7 situa\xE7\xE3o ${result.data.registrationStatus}` : ""}. Revise e complete o que faltar.`
357
+ );
358
+ } else {
359
+ setLookupInfo(
360
+ result.data.lookupAvailable ? "Documento v\xE1lido, mas sem dados p\xFAblicos. Preencha os campos obrigat\xF3rios." : "Consulta indispon\xEDvel no momento. Preencha os campos obrigat\xF3rios."
361
+ );
362
+ }
363
+ }
364
+ async function onSubmit(event) {
365
+ event.preventDefault();
366
+ setBusy("create");
367
+ setError(null);
368
+ const blank = (key) => values[key]?.trim() || null;
369
+ const input = {
370
+ name: values.name.trim(),
371
+ slug: values.slug.trim(),
372
+ type: isLegal ? "legal" : "standard"
373
+ };
374
+ if (isLegal) {
375
+ Object.assign(input, {
376
+ taxId: blank("taxId"),
377
+ taxIdType: values.taxIdType,
378
+ taxIdCountry: isCnpj ? "BR" : blank("taxIdCountry"),
379
+ legalName: blank("legalName"),
380
+ tradeName: blank("tradeName"),
381
+ legalEmail: blank("legalEmail"),
382
+ legalPhone: blank("legalPhone"),
383
+ legalAddress: Object.fromEntries(
384
+ ADDRESS_KEYS.map((key) => [key, blank(`legalAddress.${key}`)])
385
+ )
386
+ });
387
+ if (!isCnpj && !input.legalAddress?.country) {
388
+ input.legalAddress.country = blank("taxIdCountry");
389
+ }
390
+ }
391
+ const result = await createOrganization(input);
392
+ setBusy(null);
393
+ if (!result.success) {
394
+ if (result.missingFields?.length) setMissing(result.missingFields);
395
+ setError(authErrorMessage(result, "Erro ao criar organiza\xE7\xE3o."));
396
+ return;
397
+ }
398
+ setValues({ ...EMPTY_ORG_FORM });
399
+ setMissing([]);
400
+ setLookupInfo(null);
401
+ if (result.data?.id) void setCurrentOrg(result.data.id);
402
+ onCreated?.(result.data);
403
+ }
404
+ const field = (key, label, props = {}) => {
405
+ const required = REQUIRED_LEGAL.has(key);
406
+ return /* @__PURE__ */ jsx(Field, { label: `${label}${required ? " *" : ""}`, children: /* @__PURE__ */ jsx(
407
+ Input,
408
+ {
409
+ ...props,
410
+ className: missing.includes(key) && !values[key] ? "border-red-300" : void 0,
411
+ name: key,
412
+ onChange: (event) => set(key, event.target.value),
413
+ required,
414
+ value: values[key] ?? ""
415
+ }
416
+ ) });
417
+ };
418
+ return /* @__PURE__ */ jsxs("form", { className: cx("grid", compact ? "gap-2" : "gap-4"), onSubmit, children: [
419
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1 rounded-lg bg-slate-100 p-1", children: [
420
+ ["standard", "Padr\xE3o"],
421
+ ["legal", "Empresa (CNPJ / Tax ID)"]
422
+ ].map(([type, label]) => /* @__PURE__ */ jsx(
423
+ "button",
424
+ {
425
+ className: cx(
426
+ "rounded-md px-2 py-1.5 text-xs font-medium transition",
427
+ values.type === type ? "bg-white text-slate-900 shadow-sm" : "text-slate-500"
428
+ ),
429
+ onClick: () => set("type", type),
430
+ type: "button",
431
+ children: label
432
+ },
433
+ type
434
+ )) }),
435
+ isLegal && /* @__PURE__ */ jsxs(Fragment, { children: [
436
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[auto_1fr] gap-2", children: [
437
+ /* @__PURE__ */ jsxs(
438
+ "select",
439
+ {
440
+ className: "h-10 rounded-lg border border-slate-200 bg-white px-2 text-sm text-slate-900",
441
+ onChange: (event) => set("taxIdType", event.target.value),
442
+ value: values.taxIdType,
443
+ children: [
444
+ /* @__PURE__ */ jsx("option", { value: "br_cnpj", children: "CNPJ" }),
445
+ /* @__PURE__ */ jsx("option", { value: "generic", children: "Outro Tax ID" })
446
+ ]
447
+ }
448
+ ),
449
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
450
+ /* @__PURE__ */ jsx(
451
+ Input,
452
+ {
453
+ name: "taxId",
454
+ onBlur: () => isCnpj && void runLookup(),
455
+ onChange: (event) => set("taxId", event.target.value),
456
+ placeholder: isCnpj ? "00.000.000/0000-00" : "Tax ID",
457
+ required: true,
458
+ value: values.taxId
459
+ }
460
+ ),
461
+ /* @__PURE__ */ jsx(Button, { disabled: busy !== null || !values.taxId, onClick: () => void runLookup(), size: "sm", type: "button", children: busy === "lookup" ? "Buscando\u2026" : isCnpj ? "Buscar" : "Validar" })
462
+ ] })
463
+ ] }),
464
+ !isCnpj && field("taxIdCountry", "Pa\xEDs do Tax ID (ISO, ex.: US)", { maxLength: 2 }),
465
+ lookupInfo && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-slate-50 px-3 py-2 text-xs text-slate-600", children: lookupInfo })
466
+ ] }),
467
+ field("name", "Nome", { placeholder: "Minha organiza\xE7\xE3o", required: true }),
468
+ field("slug", "Slug", { placeholder: "minha-org", required: true }),
469
+ isLegal && /* @__PURE__ */ jsxs(Fragment, { children: [
470
+ field("legalName", "Raz\xE3o social"),
471
+ field("tradeName", "Nome fantasia"),
472
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [
473
+ field("legalEmail", "E-mail", { type: "email" }),
474
+ field("legalPhone", "Telefone")
475
+ ] }),
476
+ field("legalAddress.street", "Logradouro"),
477
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [
478
+ field("legalAddress.number", "N\xFAmero"),
479
+ field("legalAddress.complement", "Complemento"),
480
+ field("legalAddress.district", "Bairro"),
481
+ field("legalAddress.city", "Cidade"),
482
+ field("legalAddress.state", "Estado"),
483
+ field("legalAddress.postalCode", "CEP / C\xF3digo postal")
484
+ ] }),
485
+ !isCnpj && field("legalAddress.country", "Pa\xEDs do endere\xE7o (ISO)", { maxLength: 2 })
486
+ ] }),
487
+ error && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: error }),
488
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
489
+ onCancel && /* @__PURE__ */ jsx(Button, { onClick: onCancel, size: "sm", tone: "ghost", type: "button", children: "Cancelar" }),
490
+ /* @__PURE__ */ jsx(Button, { disabled: busy !== null, size: "sm", tone: "primary", type: "submit", children: busy === "create" ? "Criando\u2026" : "Criar organiza\xE7\xE3o" })
491
+ ] })
492
+ ] });
493
+ }
253
494
  function OrgSwitcher() {
254
495
  const {
255
- createOrganization,
256
496
  currentOrg,
257
497
  isLoadingOrganizations,
258
498
  organizations,
@@ -261,18 +501,6 @@ function createAuthElements(hooks) {
261
501
  } = useAuth();
262
502
  const [open, setOpen] = useState(false);
263
503
  const [creating, setCreating] = useState(false);
264
- async function onCreate(event) {
265
- event.preventDefault();
266
- const form = new FormData(event.currentTarget);
267
- const name = String(form.get("name") ?? "");
268
- const slug = String(form.get("slug") ?? "");
269
- const result = await createOrganization({ name, slug });
270
- if (result.success) {
271
- setCreating(false);
272
- setOpen(false);
273
- await refreshOrganizations();
274
- }
275
- }
276
504
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
277
505
  /* @__PURE__ */ jsxs(
278
506
  "button",
@@ -318,40 +546,18 @@ function createAuthElements(hooks) {
318
546
  },
319
547
  organization.id
320
548
  )) }),
321
- creating ? /* @__PURE__ */ jsxs(
322
- "form",
549
+ creating ? /* @__PURE__ */ jsx("div", { className: "max-h-[70vh] overflow-y-auto border-t border-slate-200 p-3", children: /* @__PURE__ */ jsx(
550
+ CreateOrganizationForm,
323
551
  {
324
- className: "grid gap-2 border-t border-slate-200 p-3",
325
- onSubmit: onCreate,
326
- children: [
327
- /* @__PURE__ */ jsx(Input, { name: "name", placeholder: "Nome da org", required: true }),
328
- /* @__PURE__ */ jsx(Input, { name: "slug", placeholder: "slug-da-org", required: true }),
329
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
330
- /* @__PURE__ */ jsx(
331
- Button,
332
- {
333
- className: "flex-1",
334
- size: "sm",
335
- tone: "primary",
336
- type: "submit",
337
- children: "Criar"
338
- }
339
- ),
340
- /* @__PURE__ */ jsx(
341
- Button,
342
- {
343
- className: "flex-1",
344
- onClick: () => setCreating(false),
345
- size: "sm",
346
- tone: "ghost",
347
- type: "button",
348
- children: "Cancelar"
349
- }
350
- )
351
- ] })
352
- ]
552
+ compact: true,
553
+ onCancel: () => setCreating(false),
554
+ onCreated: () => {
555
+ setCreating(false);
556
+ setOpen(false);
557
+ void refreshOrganizations();
558
+ }
353
559
  }
354
- ) : /* @__PURE__ */ jsxs("div", { className: "flex gap-2 border-t border-slate-200 p-2", children: [
560
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "flex gap-2 border-t border-slate-200 p-2", children: [
355
561
  /* @__PURE__ */ jsx(
356
562
  Button,
357
563
  {
@@ -674,15 +880,11 @@ function createAuthElements(hooks) {
674
880
  const [saving, setSaving] = useState(false);
675
881
  const [saveSuccess, setSaveSuccess] = useState(false);
676
882
  const [saveError, setSaveError] = useState(null);
677
- const [creating, setCreating] = useState(false);
678
- const [createError, setCreateError] = useState(null);
679
883
  useEffect(() => {
680
884
  if (!open) {
681
885
  setTab("orgs");
682
886
  setSaveError(null);
683
887
  setSaveSuccess(false);
684
- setCreating(false);
685
- setCreateError(null);
686
888
  }
687
889
  }, [open]);
688
890
  useEffect(() => {
@@ -716,31 +918,6 @@ function createAuthElements(hooks) {
716
918
  setSaving(false);
717
919
  }
718
920
  }
719
- async function onCreateOrg(event) {
720
- event.preventDefault();
721
- const form = new FormData(event.currentTarget);
722
- setCreating(true);
723
- setCreateError(null);
724
- try {
725
- const result = await createOrganization({
726
- name: String(form.get("name") ?? ""),
727
- slug: String(form.get("slug") ?? "")
728
- });
729
- if (result.success) {
730
- await refreshOrganizations();
731
- if (result.data?.id) {
732
- void setCurrentOrg(result.data.id);
733
- }
734
- setTab("info");
735
- } else {
736
- setCreateError(result.error ?? "Erro ao criar organiza\xE7\xE3o.");
737
- }
738
- } catch (err) {
739
- setCreateError(err instanceof Error ? err.message : "Erro ao criar.");
740
- } finally {
741
- setCreating(false);
742
- }
743
- }
744
921
  if (!open) return null;
745
922
  const orgTabs = [
746
923
  { id: "orgs", label: "Organiza\xE7\xF5es" },
@@ -907,33 +1084,18 @@ function createAuthElements(hooks) {
907
1084
  member.id
908
1085
  ))
909
1086
  ] }),
910
- tab === "new" && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onCreateOrg, children: [
1087
+ tab === "new" && /* @__PURE__ */ jsxs("div", { className: "grid gap-4", children: [
911
1088
  /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Crie uma nova organiza\xE7\xE3o e alterne para ela automaticamente." }),
912
- /* @__PURE__ */ jsx(Field, { label: "Nome *", children: /* @__PURE__ */ jsx(Input, { name: "name", placeholder: "Minha organiza\xE7\xE3o", required: true }) }),
913
- /* @__PURE__ */ jsx(Field, { label: "Slug *", children: /* @__PURE__ */ jsx(Input, { name: "slug", placeholder: "minha-org", required: true }) }),
914
- createError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: createError }),
915
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
916
- /* @__PURE__ */ jsx(
917
- Button,
918
- {
919
- onClick: () => setTab("info"),
920
- size: "sm",
921
- tone: "ghost",
922
- type: "button",
923
- children: "Cancelar"
924
- }
925
- ),
926
- /* @__PURE__ */ jsx(
927
- Button,
928
- {
929
- disabled: creating,
930
- size: "sm",
931
- tone: "primary",
932
- type: "submit",
933
- children: creating ? "Criando\u2026" : "Criar organiza\xE7\xE3o"
1089
+ /* @__PURE__ */ jsx(
1090
+ CreateOrganizationForm,
1091
+ {
1092
+ onCancel: () => setTab("info"),
1093
+ onCreated: () => {
1094
+ void refreshOrganizations();
1095
+ setTab("info");
934
1096
  }
935
- )
936
- ] })
1097
+ }
1098
+ )
937
1099
  ] }),
938
1100
  tab === "roles" && /* @__PURE__ */ jsxs("div", { className: "grid gap-5 sm:grid-cols-2", children: [
939
1101
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
@@ -987,7 +1149,78 @@ function createAuthElements(hooks) {
987
1149
  ] })
988
1150
  ] }) });
989
1151
  }
1152
+ function WaitlistForm({
1153
+ clientId,
1154
+ defaultEmail = "",
1155
+ onJoined,
1156
+ submitLabel = "Entrar na lista de espera"
1157
+ }) {
1158
+ const { joinWaitlist } = useAuth();
1159
+ const [name, setName] = useState("");
1160
+ const [email, setEmail] = useState(defaultEmail);
1161
+ const [busy, setBusy] = useState(false);
1162
+ const [error, setError] = useState(null);
1163
+ const [done, setDone] = useState(null);
1164
+ async function submit(event) {
1165
+ event.preventDefault();
1166
+ if (!joinWaitlist) {
1167
+ setError("Lista de espera indispon\xEDvel: atualize @geekapps/auth-nextjs para 0.26 ou superior.");
1168
+ return;
1169
+ }
1170
+ setBusy(true);
1171
+ setError(null);
1172
+ const result = await joinWaitlist({
1173
+ clientId,
1174
+ email: email.trim(),
1175
+ name: name.trim() || void 0
1176
+ });
1177
+ setBusy(false);
1178
+ if (!result.success) {
1179
+ setError(authErrorMessage(result, "N\xE3o foi poss\xEDvel entrar na lista de espera."));
1180
+ return;
1181
+ }
1182
+ setDone(result.data);
1183
+ onJoined?.(result.data);
1184
+ }
1185
+ if (done) {
1186
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-1 rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-center", children: [
1187
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-emerald-800", children: done.status === "approved" ? "Seu acesso foi liberado!" : done.status === "joined" ? "Voc\xEA j\xE1 tem acesso." : "Voc\xEA est\xE1 na lista de espera." }),
1188
+ done.status === "waiting" && done.position != null && /* @__PURE__ */ jsxs("p", { className: "text-sm text-emerald-700", children: [
1189
+ "Sua posi\xE7\xE3o na fila: ",
1190
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold", children: [
1191
+ "#",
1192
+ done.position
1193
+ ] })
1194
+ ] })
1195
+ ] });
1196
+ }
1197
+ return /* @__PURE__ */ jsxs("form", { className: "grid gap-3", onSubmit: (event) => void submit(event), children: [
1198
+ /* @__PURE__ */ jsx(Field, { label: "Nome", children: /* @__PURE__ */ jsx(
1199
+ Input,
1200
+ {
1201
+ autoComplete: "name",
1202
+ onChange: (event) => setName(event.target.value),
1203
+ placeholder: "Seu nome",
1204
+ value: name
1205
+ }
1206
+ ) }),
1207
+ /* @__PURE__ */ jsx(Field, { label: "E-mail", children: /* @__PURE__ */ jsx(
1208
+ Input,
1209
+ {
1210
+ autoComplete: "email",
1211
+ onChange: (event) => setEmail(event.target.value),
1212
+ placeholder: "voce@exemplo.com",
1213
+ required: true,
1214
+ type: "email",
1215
+ value: email
1216
+ }
1217
+ ) }),
1218
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: error }),
1219
+ /* @__PURE__ */ jsx(Button, { disabled: busy || !email.trim(), tone: "primary", type: "submit", children: busy ? "Enviando..." : submitLabel })
1220
+ ] });
1221
+ }
990
1222
  return {
1223
+ WaitlistForm,
991
1224
  SignInButton,
992
1225
  SignOutButton,
993
1226
  AccountSwitcher,
@@ -995,12 +1228,14 @@ function createAuthElements(hooks) {
995
1228
  UserButton,
996
1229
  OrganizationButton,
997
1230
  ProfileModal,
998
- ManageOrganizationModal
1231
+ ManageOrganizationModal,
1232
+ CreateOrganizationForm
999
1233
  };
1000
1234
  }
1001
1235
  export {
1002
1236
  Avatar,
1003
1237
  Modal,
1238
+ authErrorMessage,
1004
1239
  createAuthElements
1005
1240
  };
1006
1241
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ButtonHTMLAttributes,\n type FormEvent,\n type ReactNode,\n useEffect,\n useState,\n} from \"react\";\n\n// ── Local type definitions ────────────────────────────────────────────────────\n\nexport type ElementSize = \"sm\" | \"md\" | \"lg\";\nexport type ElementTone = \"default\" | \"primary\" | \"danger\" | \"ghost\";\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: {\n id?: string;\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n phone?: string | null;\n };\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n members?: Array<{\n id: string;\n user: { name: string | null; email: string | null; imageUrl: string | null };\n roleAssignments?: Array<{\n id: string;\n roleDefinition?: { name: string } | null;\n customRole?: { name: string } | null;\n }>;\n }>;\n};\n\nexport type Permission = {\n id: string;\n key: string;\n category: string | null;\n};\n\nexport type Role = {\n id: string;\n key: string;\n name: string;\n permissions: unknown[];\n};\n\nexport type UserSession = {\n id: string;\n deviceName: string | null;\n ip: string | null;\n expiresAt: string | Date;\n};\n\ntype User = {\n id: string;\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n phone?: string | null;\n};\n\ntype AuthResult<T> = { success: true; data: T } | { success: false; error?: string };\n\n// ── Hook contract (structural — no import from auth-nextjs) ───────────────────\n\ntype UseAuthHook = () => {\n user: User | null;\n signIn: (opts?: { redirectTo?: string }) => Promise<void> | void;\n signOut: () => Promise<void> | void;\n signOutAll: () => Promise<void> | void;\n accounts: ConnectedAccount[];\n addAccount: (opts?: { redirectTo?: string }) => Promise<void> | void;\n isLoadingAccounts: boolean;\n refreshAccounts: () => Promise<void>;\n switchAccount: (id: string, opts?: { redirectTo?: string }) => Promise<void>;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId?: string | null;\n isLoadingOrganizations: boolean;\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (id: string) => Promise<void>;\n createOrganization: (input: {\n name: string;\n slug: string;\n }) => Promise<AuthResult<Organization>>;\n updateOrganization: (\n id: string,\n input: Partial<{\n name: string;\n slug: string;\n description: string | null;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n }>,\n ) => Promise<AuthResult<Organization>>;\n updateUser: (\n id: string,\n input: { name?: string | null; phone?: string | null; imageUrl?: string | null },\n ) => Promise<AuthResult<User>>;\n listUserSessions: (params: { userId?: string; organizationId?: string }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n listPermissions: (params: {\n applicationId?: string;\n roleId?: string | null;\n }) => Promise<Permission[]>;\n listRoles: (params?: {\n organizationId?: string;\n applicationId?: string;\n type?: \"system\" | \"custom\" | \"all\";\n }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n};\n\n// ── Primitive UI helpers ──────────────────────────────────────────────────────\n\ntype ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n tone?: ElementTone;\n size?: ElementSize;\n};\n\nfunction cx(...classes: Array<string | false | null | undefined>) {\n return classes.filter(Boolean).join(\" \");\n}\n\nfunction initials(value?: string | null) {\n const normalized = value?.trim();\n if (!normalized) return \"?\";\n const parts = normalized.split(/\\s+/).slice(0, 2);\n return parts.map((part) => part[0]?.toUpperCase()).join(\"\") || \"?\";\n}\n\nfunction formatDate(value?: string | Date | null) {\n if (!value) return \"-\";\n return new Intl.DateTimeFormat(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n }).format(new Date(value));\n}\n\nfunction isExpired(value: string | Date) {\n return new Date(value).getTime() <= Date.now();\n}\n\nfunction Button({\n className,\n tone = \"default\",\n size = \"md\",\n ...props\n}: ButtonProps) {\n return (\n <button\n {...props}\n className={cx(\n \"inline-flex items-center justify-center gap-2 rounded-lg font-medium transition disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"sm\" && \"h-8 px-3 text-xs\",\n size === \"md\" && \"h-10 px-4 text-sm\",\n size === \"lg\" && \"h-11 px-5 text-sm\",\n tone === \"default\" &&\n \"border border-slate-200 bg-white text-slate-800 hover:bg-slate-50\",\n tone === \"primary\" && \"bg-slate-950 text-white hover:bg-slate-800\",\n tone === \"danger\" && \"bg-red-600 text-white hover:bg-red-700\",\n tone === \"ghost\" &&\n \"bg-transparent text-slate-600 hover:bg-slate-100 hover:text-slate-950\",\n className,\n )}\n />\n );\n}\n\nfunction Input(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return (\n <input\n {...props}\n className={cx(\n \"h-10 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 outline-none placeholder:text-slate-400 focus:border-slate-400\",\n props.className,\n )}\n />\n );\n}\n\nfunction Textarea(props: React.TextareaHTMLAttributes<HTMLTextAreaElement>) {\n return (\n <textarea\n {...props}\n className={cx(\n \"min-h-[86px] w-full resize-none rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none placeholder:text-slate-400 focus:border-slate-400\",\n props.className,\n )}\n />\n );\n}\n\nfunction Field({ label, children }: { label: string; children: ReactNode }) {\n return (\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-slate-600\">{label}</span>\n {children}\n </label>\n );\n}\n\n// ── Standalone components (no hooks) ─────────────────────────────────────────\n\nexport function Avatar({\n src,\n name,\n size = \"md\",\n className,\n}: {\n src?: string | null;\n name?: string | null;\n size?: ElementSize;\n className?: string;\n}) {\n return (\n <span\n className={cx(\n \"inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-slate-100 font-semibold text-slate-700\",\n size === \"sm\" && \"h-8 w-8 text-xs\",\n size === \"md\" && \"h-10 w-10 text-sm\",\n size === \"lg\" && \"h-12 w-12 text-base\",\n className,\n )}\n >\n {src ? (\n <img\n alt={name ?? \"Avatar\"}\n className=\"h-full w-full object-cover\"\n src={src}\n />\n ) : (\n initials(name)\n )}\n </span>\n );\n}\n\nexport function Modal({\n open,\n onOpenChange,\n title,\n description,\n children,\n footer,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: string;\n description?: string;\n children: ReactNode;\n footer?: ReactNode;\n}) {\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-2xl bg-white shadow-xl\">\n <div className=\"flex items-start justify-between gap-4 border-b border-slate-200 p-5\">\n <div>\n <h2 className=\"text-lg font-semibold text-slate-950\">{title}</h2>\n {description && (\n <p className=\"mt-1 text-sm text-slate-500\">{description}</p>\n )}\n </div>\n <Button\n aria-label=\"Close\"\n onClick={() => onOpenChange(false)}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n ✕\n </Button>\n </div>\n <div className=\"max-h-[68vh] overflow-y-auto p-5\">{children}</div>\n {footer && (\n <div className=\"border-t border-slate-200 p-5\">{footer}</div>\n )}\n </div>\n </div>\n );\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Creates auth UI components bound to the provided `useAuth` hook instance.\n * This lets consumers supply their own auth-nextjs instance without requiring\n * a separate installed copy inside auth-elements-nextjs.\n *\n * @example\n * import { createAuthElements } from '@geekapps/auth-elements-nextjs'\n * import { useAuth } from '@geekapps/auth-nextjs/client'\n * export const { SignInButton, ProfileModal } = createAuthElements({ useAuth })\n */\nexport function createAuthElements(hooks: { useAuth: UseAuthHook }) {\n const { useAuth } = hooks;\n\n function SignInButton({\n children = \"Entrar\",\n redirectTo,\n }: {\n children?: ReactNode;\n redirectTo?: string;\n }) {\n const { signIn } = useAuth();\n return (\n <Button\n onClick={() => void signIn({ redirectTo })}\n tone=\"primary\"\n type=\"button\"\n >\n {children}\n </Button>\n );\n }\n\n function SignOutButton({ children = \"Sair\" }: { children?: ReactNode }) {\n const { signOut } = useAuth();\n return (\n <Button onClick={() => void signOut()} tone=\"ghost\" type=\"button\">\n {children}\n </Button>\n );\n }\n\n function AccountSwitcher() {\n const {\n accounts,\n addAccount,\n isLoadingAccounts,\n refreshAccounts,\n switchAccount,\n } = useAuth();\n const activeAccount =\n accounts.find((account) => account.isActive) ?? accounts[0] ?? null;\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"relative\">\n <button\n className=\"flex h-10 w-10 items-center justify-center rounded-xl transition hover:opacity-80\"\n onClick={() => setOpen((value) => !value)}\n title={activeAccount?.user.name ?? activeAccount?.user.email ?? \"Conta\"}\n type=\"button\"\n >\n <Avatar\n name={activeAccount?.user.name ?? activeAccount?.user.email}\n size=\"sm\"\n src={activeAccount?.user.imageUrl}\n />\n </button>\n\n {open && (\n <>\n <div className=\"fixed inset-0 z-20\" onClick={() => setOpen(false)} />\n <div className=\"absolute bottom-0 left-14 z-30 w-72 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg\">\n <div className=\"border-b border-slate-100 px-3 py-2.5\">\n <p className=\"text-[11px] font-medium uppercase tracking-wider text-slate-400\">\n Contas\n </p>\n </div>\n <div className=\"p-1.5\">\n {isLoadingAccounts && (\n <p className=\"px-2 py-3 text-xs text-slate-400\">\n Carregando...\n </p>\n )}\n {accounts.map((account) => (\n <button\n className={cx(\n \"flex w-full items-center gap-2.5 rounded-lg px-2 py-2 text-left transition hover:bg-slate-50\",\n account.isActive && \"bg-slate-50\",\n )}\n key={account.sessionId ?? account.id}\n onClick={() => {\n void switchAccount(account.sessionId ?? account.id);\n setOpen(false);\n }}\n type=\"button\"\n >\n <Avatar\n name={account.user.name ?? account.user.email}\n size=\"sm\"\n src={account.user.imageUrl}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-900\">\n {account.user.name ?? account.user.email}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {account.user.email}\n </span>\n </span>\n {account.isActive && (\n <span className=\"shrink-0 text-xs font-medium text-emerald-600\">\n ✓\n </span>\n )}\n </button>\n ))}\n </div>\n <div className=\"flex gap-1.5 border-t border-slate-100 p-1.5\">\n <Button\n className=\"flex-1\"\n onClick={() => void addAccount()}\n size=\"sm\"\n type=\"button\"\n >\n + Conta\n </Button>\n <Button\n className=\"flex-1\"\n onClick={() => void refreshAccounts()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Atualizar\n </Button>\n </div>\n </div>\n </>\n )}\n </div>\n );\n }\n\n function OrgSwitcher() {\n const {\n createOrganization,\n currentOrg,\n isLoadingOrganizations,\n organizations,\n refreshOrganizations,\n setCurrentOrg,\n } = useAuth();\n const [open, setOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n\n async function onCreate(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n const name = String(form.get(\"name\") ?? \"\");\n const slug = String(form.get(\"slug\") ?? \"\");\n const result = await createOrganization({ name, slug });\n if (result.success) {\n setCreating(false);\n setOpen(false);\n await refreshOrganizations();\n }\n }\n\n return (\n <div className=\"relative\">\n <button\n className=\"flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white p-2 text-left hover:bg-slate-50\"\n onClick={() => setOpen((value) => !value)}\n type=\"button\"\n >\n <Avatar name={currentOrg?.name} src={currentOrg?.imageUrl} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-950\">\n {currentOrg?.name ?? \"Selecionar organização\"}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {isLoadingOrganizations\n ? \"Carregando...\"\n : `${organizations.length} organizações`}\n </span>\n </span>\n <span className=\"text-slate-400\">⌄</span>\n </button>\n\n {open && (\n <div className=\"absolute right-0 z-30 mt-2 w-80 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg\">\n <div className=\"max-h-72 overflow-y-auto p-2\">\n {organizations.map((organization) => (\n <button\n className=\"flex w-full items-center gap-3 rounded-lg p-2 text-left hover:bg-slate-50\"\n key={organization.id}\n onClick={() => {\n void setCurrentOrg(organization.id);\n setOpen(false);\n }}\n type=\"button\"\n >\n <Avatar\n name={organization.name}\n size=\"sm\"\n src={organization.imageUrl}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-900\">\n {organization.name}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {organization.slug}\n </span>\n </span>\n {organization.id === currentOrg?.id && (\n <span className=\"text-xs font-medium text-emerald-600\">\n Atual\n </span>\n )}\n </button>\n ))}\n </div>\n\n {creating ? (\n <form\n className=\"grid gap-2 border-t border-slate-200 p-3\"\n onSubmit={onCreate}\n >\n <Input name=\"name\" placeholder=\"Nome da org\" required />\n <Input name=\"slug\" placeholder=\"slug-da-org\" required />\n <div className=\"flex gap-2\">\n <Button\n className=\"flex-1\"\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n Criar\n </Button>\n <Button\n className=\"flex-1\"\n onClick={() => setCreating(false)}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Cancelar\n </Button>\n </div>\n </form>\n ) : (\n <div className=\"flex gap-2 border-t border-slate-200 p-2\">\n <Button\n className=\"flex-1\"\n onClick={() => setCreating(true)}\n size=\"sm\"\n type=\"button\"\n >\n Nova org\n </Button>\n <Button\n className=\"flex-1\"\n onClick={() => void refreshOrganizations()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Atualizar\n </Button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n }\n\n function UserButton() {\n const { user } = useAuth();\n const [open, setOpen] = useState(false);\n return (\n <>\n <button onClick={() => setOpen(true)} type=\"button\">\n <Avatar name={user?.name ?? user?.email} src={user?.imageUrl} />\n </button>\n <ProfileModal open={open} onOpenChange={setOpen} />\n </>\n );\n }\n\n function OrganizationButton() {\n const { currentOrg } = useAuth();\n const [open, setOpen] = useState(false);\n return (\n <>\n <button\n className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-white border border-slate-200 text-xs font-semibold text-slate-700 transition hover:bg-slate-50 hover:border-slate-300\"\n onClick={() => setOpen(true)}\n title={currentOrg?.name ?? \"Organização\"}\n type=\"button\"\n >\n {currentOrg?.imageUrl ? (\n <img\n alt={currentOrg.name}\n className=\"h-full w-full rounded-xl object-cover\"\n src={currentOrg.imageUrl}\n />\n ) : (\n (currentOrg?.name ?? \"O\")[0]?.toUpperCase()\n )}\n </button>\n <ManageOrganizationModal open={open} onOpenChange={setOpen} />\n </>\n );\n }\n\n function ProfileModal({\n open,\n onOpenChange,\n }: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n }) {\n const {\n signOut,\n signOutAll,\n user,\n organizations,\n currentOrg,\n setCurrentOrg,\n updateUser,\n listUserSessions,\n revokeUserSession,\n } = useAuth();\n const [tab, setTab] = useState(\"profile\");\n const [sessions, setSessions] = useState<UserSession[]>([]);\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saveSuccess, setSaveSuccess] = useState(false);\n\n useEffect(() => {\n if (!open) {\n setTab(\"profile\");\n setSaveError(null);\n setSaveSuccess(false);\n }\n }, [open]);\n\n useEffect(() => {\n if (open && user && tab === \"sessions\") {\n void listUserSessions({ userId: user.id })\n .then(setSessions)\n .catch(() => setSessions([]));\n }\n }, [listUserSessions, open, tab, user]);\n\n async function onProfileSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!user) return;\n const form = new FormData(event.currentTarget);\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n try {\n await updateUser(user.id, {\n name: String(form.get(\"name\") ?? \"\") || null,\n phone: String(form.get(\"phone\") ?? \"\") || null,\n imageUrl: String(form.get(\"imageUrl\") ?? \"\") || null,\n });\n setSaveSuccess(true);\n setTimeout(() => setSaveSuccess(false), 2500);\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : \"Erro ao salvar.\");\n } finally {\n setSaving(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <Avatar\n name={user?.name ?? user?.email}\n size=\"sm\"\n src={user?.imageUrl}\n />\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {user?.name ?? user?.email ?? \"Minha conta\"}\n </p>\n <p className=\"text-xs text-slate-500\">{user?.email}</p>\n </div>\n </div>\n <button\n aria-label=\"Fechar\"\n className=\"rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700\"\n onClick={() => onOpenChange(false)}\n type=\"button\"\n >\n ✕\n </button>\n </div>\n\n {/* Tabs */}\n <div className=\"shrink-0 flex gap-1 border-b border-slate-100 px-6 pt-3\">\n {(\n [\n { id: \"profile\", label: \"Perfil\" },\n { id: \"sessions\", label: \"Sessões\" },\n { id: \"orgs\", label: \"Organizações\" },\n ] as const\n ).map((t) => (\n <button\n className={cx(\n \"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition\",\n tab === t.id\n ? \"border-slate-900 text-slate-900\"\n : \"border-transparent text-slate-500 hover:text-slate-700\",\n )}\n key={t.id}\n onClick={() => setTab(t.id)}\n type=\"button\"\n >\n {t.label}\n </button>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {tab === \"profile\" && user && (\n <form className=\"grid gap-4\" onSubmit={onProfileSubmit}>\n <div className=\"flex items-center gap-4 rounded-xl bg-slate-50 p-4\">\n <Avatar\n name={user.name ?? user.email}\n size=\"lg\"\n src={user.imageUrl}\n />\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {user.name ?? \"Sem nome\"}\n </p>\n <p className=\"text-xs text-slate-500\">{user.email}</p>\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Nome\">\n <Input\n defaultValue={user.name ?? \"\"}\n name=\"name\"\n placeholder=\"Seu nome\"\n />\n </Field>\n <Field label=\"Telefone\">\n <Input\n defaultValue={user.phone ?? \"\"}\n name=\"phone\"\n placeholder=\"+55 11 99999-9999\"\n />\n </Field>\n </div>\n <Field label=\"URL da imagem\">\n <Input\n defaultValue={user.imageUrl ?? \"\"}\n name=\"imageUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n\n {saveError && (\n <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">\n {saveError}\n </p>\n )}\n {saveSuccess && (\n <p className=\"rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600\">\n Perfil salvo com sucesso.\n </p>\n )}\n\n <div className=\"flex items-center justify-between border-t border-slate-100 pt-2\">\n <div className=\"flex gap-2\">\n <Button\n onClick={() => void signOut()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Sair\n </Button>\n <Button\n onClick={() => void signOutAll()}\n size=\"sm\"\n tone=\"danger\"\n type=\"button\"\n >\n Sair de todas\n </Button>\n </div>\n <Button\n disabled={saving}\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n {saving ? \"Salvando…\" : \"Salvar\"}\n </Button>\n </div>\n </form>\n )}\n\n {tab === \"sessions\" && (\n <div className=\"grid gap-2\">\n {sessions.length === 0 && (\n <p className=\"py-6 text-center text-sm text-slate-400\">\n Nenhuma sessão ativa.\n </p>\n )}\n {sessions.map((session) => {\n const expired = isExpired(session.expiresAt);\n return (\n <div\n className=\"flex items-center justify-between gap-4 rounded-xl border border-slate-200 p-4\"\n key={session.id}\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {session.deviceName ?? \"Dispositivo\"}\n </p>\n <p className=\"mt-0.5 truncate text-xs text-slate-500\">\n {session.ip ?? \"IP desconhecido\"} ·{\" \"}\n <span className={expired ? \"text-amber-600\" : \"\"}>\n {expired\n ? \"Expirada\"\n : `Expira ${formatDate(session.expiresAt)}`}\n </span>\n </p>\n </div>\n <Button\n onClick={async () => {\n await revokeUserSession(session.id);\n setSessions((s) =>\n s.filter((x) => x.id !== session.id),\n );\n }}\n size=\"sm\"\n tone=\"danger\"\n type=\"button\"\n >\n Revogar\n </Button>\n </div>\n );\n })}\n </div>\n )}\n\n {tab === \"orgs\" && (\n <div className=\"grid gap-2\">\n {organizations.length === 0 && (\n <p className=\"py-6 text-center text-sm text-slate-400\">\n Nenhuma organização.\n </p>\n )}\n {organizations.map((org) => (\n <button\n className={cx(\n \"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition\",\n org.id === currentOrg?.id\n ? \"border-slate-900 bg-slate-50\"\n : \"border-slate-200 hover:border-slate-300 hover:bg-slate-50\",\n )}\n key={org.id}\n onClick={() => void setCurrentOrg(org.id)}\n type=\"button\"\n >\n <Avatar name={org.name} size=\"sm\" src={org.imageUrl} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {org.name}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n /{org.slug}\n </p>\n </div>\n {org.id === currentOrg?.id && (\n <span className=\"shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white\">\n Ativa\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n function ManageOrganizationModal({\n open,\n onOpenChange,\n }: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n }) {\n const {\n createOrganization,\n currentOrg,\n organizations,\n refreshOrganizations,\n setCurrentOrg,\n updateOrganization,\n listPermissions,\n listRoles,\n } = useAuth();\n const [tab, setTab] = useState(\"orgs\");\n const [roles, setRoles] = useState<{\n systemRoles: Role[];\n customRoles: Role[];\n }>({ systemRoles: [], customRoles: [] });\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [saving, setSaving] = useState(false);\n const [saveSuccess, setSaveSuccess] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setTab(\"orgs\");\n setSaveError(null);\n setSaveSuccess(false);\n setCreating(false);\n setCreateError(null);\n }\n }, [open]);\n\n useEffect(() => {\n if (!open || !currentOrg) return;\n if (tab === \"members\" || tab === \"roles\") {\n void listRoles({ organizationId: currentOrg.id })\n .then(setRoles)\n .catch(() => setRoles({ systemRoles: [], customRoles: [] }));\n void listPermissions({})\n .then(setPermissions)\n .catch(() => setPermissions([]));\n }\n }, [currentOrg, listPermissions, listRoles, open, tab]);\n\n async function onOrgSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!currentOrg) return;\n const form = new FormData(event.currentTarget);\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n try {\n await updateOrganization(currentOrg.id, {\n name: String(form.get(\"name\") ?? \"\"),\n description: String(form.get(\"description\") ?? \"\") || null,\n slug: String(form.get(\"slug\") ?? \"\"),\n domain: String(form.get(\"domain\") ?? \"\") || null,\n imageUrl: String(form.get(\"imageUrl\") ?? \"\") || null,\n faviconUrl: String(form.get(\"faviconUrl\") ?? \"\") || null,\n });\n setSaveSuccess(true);\n setTimeout(() => setSaveSuccess(false), 2500);\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : \"Erro ao salvar.\");\n } finally {\n setSaving(false);\n }\n }\n\n async function onCreateOrg(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n setCreating(true);\n setCreateError(null);\n try {\n const result = await createOrganization({\n name: String(form.get(\"name\") ?? \"\"),\n slug: String(form.get(\"slug\") ?? \"\"),\n });\n if (result.success) {\n await refreshOrganizations();\n if (result.data?.id) {\n void setCurrentOrg(result.data.id);\n }\n setTab(\"info\");\n } else {\n setCreateError(result.error ?? \"Erro ao criar organização.\");\n }\n } catch (err) {\n setCreateError(err instanceof Error ? err.message : \"Erro ao criar.\");\n } finally {\n setCreating(false);\n }\n }\n\n if (!open) return null;\n\n const orgTabs = [\n { id: \"orgs\", label: \"Organizações\" },\n { id: \"info\", label: \"Geral\" },\n { id: \"members\", label: \"Membros\" },\n { id: \"roles\", label: \"Roles\" },\n { id: \"new\", label: \"+ Nova org\" },\n ] as const;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n {currentOrg?.imageUrl ? (\n <img\n alt={currentOrg.name}\n className=\"h-8 w-8 rounded-lg object-cover\"\n src={currentOrg.imageUrl}\n />\n ) : (\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-xs font-semibold text-slate-600\">\n {(currentOrg?.name ?? \"O\")[0]?.toUpperCase()}\n </span>\n )}\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {currentOrg?.name ?? \"Organização\"}\n </p>\n {currentOrg?.slug && (\n <p className=\"text-xs text-slate-500\">/{currentOrg.slug}</p>\n )}\n </div>\n </div>\n <button\n aria-label=\"Fechar\"\n className=\"rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700\"\n onClick={() => onOpenChange(false)}\n type=\"button\"\n >\n ✕\n </button>\n </div>\n\n {/* Tabs */}\n <div className=\"flex shrink-0 gap-1 border-b border-slate-100 px-6 pt-3\">\n {orgTabs.map((t) => (\n <button\n className={cx(\n \"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition\",\n tab === t.id\n ? \"border-slate-900 text-slate-900\"\n : \"border-transparent text-slate-500 hover:text-slate-700\",\n )}\n key={t.id}\n onClick={() => setTab(t.id)}\n type=\"button\"\n >\n {t.label}\n </button>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {!currentOrg && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhuma organização selecionada.\n </p>\n )}\n\n {tab === \"orgs\" && (\n <div className=\"grid gap-2\">\n {organizations.length === 0 && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhuma organização disponível.\n </p>\n )}\n {organizations.map((org) => (\n <button\n className={cx(\n \"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition\",\n org.id === currentOrg?.id\n ? \"border-slate-900 bg-slate-50\"\n : \"border-slate-200 hover:border-slate-300 hover:bg-slate-50\",\n )}\n key={org.id}\n onClick={() => {\n void setCurrentOrg(org.id);\n onOpenChange(false);\n }}\n type=\"button\"\n >\n <Avatar name={org.name} size=\"sm\" src={org.imageUrl} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {org.name}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n /{org.slug}\n </p>\n </div>\n {org.id === currentOrg?.id && (\n <span className=\"shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white\">\n Ativa\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n\n {tab === \"info\" && currentOrg && (\n <form className=\"grid gap-4\" onSubmit={onOrgSubmit}>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Nome *\">\n <Input defaultValue={currentOrg.name} name=\"name\" required />\n </Field>\n <Field label=\"Slug *\">\n <Input defaultValue={currentOrg.slug} name=\"slug\" required />\n </Field>\n </div>\n <Field label=\"Descrição\">\n <Textarea\n defaultValue={currentOrg.description ?? \"\"}\n name=\"description\"\n placeholder=\"Descreva a organização…\"\n />\n </Field>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Domínio\">\n <Input\n defaultValue={currentOrg.domain ?? \"\"}\n name=\"domain\"\n placeholder=\"acme.com\"\n />\n </Field>\n <Field label=\"URL da imagem\">\n <Input\n defaultValue={currentOrg.imageUrl ?? \"\"}\n name=\"imageUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n </div>\n <Field label=\"URL do favicon\">\n <Input\n defaultValue={currentOrg.faviconUrl ?? \"\"}\n name=\"faviconUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n\n {saveError && (\n <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">\n {saveError}\n </p>\n )}\n {saveSuccess && (\n <p className=\"rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600\">\n Organização atualizada.\n </p>\n )}\n\n <div className=\"flex justify-end pt-1\">\n <Button\n disabled={saving}\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n {saving ? \"Salvando…\" : \"Salvar organização\"}\n </Button>\n </div>\n </form>\n )}\n\n {tab === \"members\" && currentOrg && (\n <div className=\"grid gap-2\">\n {(currentOrg.members ?? []).length === 0 && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhum membro nesta organização.\n </p>\n )}\n {(currentOrg.members ?? []).map((member) => (\n <div\n className=\"flex items-center gap-3 rounded-xl border border-slate-200 p-4\"\n key={member.id}\n >\n <Avatar\n name={member.user.name ?? member.user.email}\n size=\"sm\"\n src={member.user.imageUrl}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {member.user.name ?? member.user.email}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n {member.user.email}\n </p>\n </div>\n <div className=\"flex shrink-0 flex-wrap justify-end gap-1\">\n {(member.roleAssignments ?? []).map((a) => (\n <span\n className=\"rounded-full bg-slate-900 px-2 py-0.5 text-[11px] font-medium text-white\"\n key={a.id}\n >\n {a.roleDefinition?.name ?? a.customRole?.name ?? a.id}\n </span>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {tab === \"new\" && (\n <form className=\"grid gap-4\" onSubmit={onCreateOrg}>\n <p className=\"text-sm text-slate-500\">\n Crie uma nova organização e alterne para ela automaticamente.\n </p>\n <Field label=\"Nome *\">\n <Input name=\"name\" placeholder=\"Minha organização\" required />\n </Field>\n <Field label=\"Slug *\">\n <Input name=\"slug\" placeholder=\"minha-org\" required />\n </Field>\n {createError && (\n <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">\n {createError}\n </p>\n )}\n <div className=\"flex justify-end gap-2\">\n <Button\n onClick={() => setTab(\"info\")}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Cancelar\n </Button>\n <Button\n disabled={creating}\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n {creating ? \"Criando…\" : \"Criar organização\"}\n </Button>\n </div>\n </form>\n )}\n\n {tab === \"roles\" && (\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <h3 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400\">\n Roles ({roles.systemRoles.length + roles.customRoles.length})\n </h3>\n <div className=\"max-h-[280px] space-y-2 overflow-y-auto pr-1\">\n {roles.systemRoles.length === 0 &&\n roles.customRoles.length === 0 && (\n <p className=\"text-sm text-slate-400\">Nenhuma role.</p>\n )}\n {[...roles.systemRoles, ...roles.customRoles].map((role) => (\n <div\n className=\"overflow-hidden rounded-xl border border-slate-200 p-3\"\n key={role.id}\n >\n <p className=\"truncate text-sm font-semibold text-slate-900\">\n {role.name}\n </p>\n <p className=\"truncate text-xs text-slate-400\">\n {role.key}\n </p>\n <p className=\"mt-1 text-xs text-slate-500\">\n {role.permissions.length} permission\n {role.permissions.length !== 1 ? \"s\" : \"\"}\n </p>\n </div>\n ))}\n </div>\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400\">\n Permissions ({permissions.length})\n </h3>\n <div className=\"max-h-[280px] space-y-2 overflow-y-auto pr-1\">\n {permissions.length === 0 && (\n <p className=\"text-sm text-slate-400\">\n Nenhuma permission.\n </p>\n )}\n {permissions.map((permission) => (\n <div\n className=\"overflow-hidden rounded-xl border border-slate-200 p-3\"\n key={permission.id}\n >\n <p className=\"truncate text-sm font-semibold text-slate-900\">\n {permission.key}\n </p>\n <p className=\"truncate text-xs text-slate-400\">\n {permission.category ?? \"custom\"}\n </p>\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n return {\n SignInButton,\n SignOutButton,\n AccountSwitcher,\n OrgSwitcher,\n UserButton,\n OrganizationButton,\n ProfileModal,\n ManageOrganizationModal,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ButtonHTMLAttributes,\n type FormEvent,\n type ReactNode,\n useEffect,\n useState,\n} from \"react\";\n\n// ── Local type definitions ────────────────────────────────────────────────────\n\nexport type ElementSize = \"sm\" | \"md\" | \"lg\";\nexport type ElementTone = \"default\" | \"primary\" | \"danger\" | \"ghost\";\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: {\n id?: string;\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n phone?: string | null;\n };\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n type?: OrganizationType;\n taxId?: string | null;\n taxIdType?: TaxIdType | null;\n legalName?: string | null;\n members?: Array<{\n id: string;\n user: { name: string | null; email: string | null; imageUrl: string | null };\n roleAssignments?: Array<{\n id: string;\n roleDefinition?: { name: string } | null;\n customRole?: { name: string } | null;\n }>;\n }>;\n};\n\nexport type OrganizationType = \"standard\" | \"legal\";\nexport type TaxIdType = \"br_cnpj\" | \"generic\";\n\ntype OrganizationLegalAddress = Partial<\n Record<\"street\" | \"number\" | \"complement\" | \"district\" | \"city\" | \"state\" | \"postalCode\" | \"country\", string | null>\n>;\n\nexport type OrganizationCreateInput = {\n name: string;\n slug: string;\n type?: OrganizationType;\n taxId?: string | null;\n taxIdType?: TaxIdType | null;\n taxIdCountry?: string | null;\n legalName?: string | null;\n tradeName?: string | null;\n legalEmail?: string | null;\n legalPhone?: string | null;\n legalAddress?: OrganizationLegalAddress | null;\n};\n\nexport type TaxIdLookupResult = {\n taxId: string;\n taxIdType: TaxIdType;\n taxIdCountry: string | null;\n alreadyRegistered: boolean;\n lookupAvailable: boolean;\n found: boolean;\n registrationStatus: string | null;\n suggestedName: string | null;\n data: {\n legalName: string | null;\n tradeName: string | null;\n legalEmail: string | null;\n legalPhone: string | null;\n legalAddress: OrganizationLegalAddress | null;\n };\n missingFields: string[];\n};\n\nconst ADDRESS_KEYS = [\n \"street\",\n \"number\",\n \"complement\",\n \"district\",\n \"city\",\n \"state\",\n \"postalCode\",\n \"country\",\n] as const;\n\nconst REQUIRED_LEGAL = new Set([\n \"taxIdCountry\",\n \"legalName\",\n \"legalAddress.street\",\n \"legalAddress.city\",\n \"legalAddress.postalCode\",\n \"legalAddress.country\",\n]);\n\nconst EMPTY_ORG_FORM: Record<string, string> = {\n type: \"standard\",\n taxIdType: \"br_cnpj\",\n taxId: \"\",\n name: \"\",\n slug: \"\",\n};\n\nfunction slugify(value: string) {\n return value\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60);\n}\n\nexport type Permission = {\n id: string;\n key: string;\n category: string | null;\n};\n\nexport type Role = {\n id: string;\n key: string;\n name: string;\n permissions: unknown[];\n};\n\nexport type UserSession = {\n id: string;\n deviceName: string | null;\n ip: string | null;\n expiresAt: string | Date;\n};\n\ntype User = {\n id: string;\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n phone?: string | null;\n};\n\n/** Espelha `AuthResult` do auth-nextjs >=0.26 (campos extras são opcionais). */\nexport type AuthResult<T> =\n | { success: true; data: T }\n | {\n success: false;\n error?: string;\n status?: number;\n code?: string;\n retryAfter?: number;\n missingFields?: string[];\n };\n\nexport type JoinWaitlistParams = { clientId: string; email: string; name?: string };\nexport type JoinWaitlistResponse = {\n ok: true;\n status: \"waiting\" | \"approved\" | \"joined\";\n position: number | null;\n};\n\n/** Mensagem em português para um resultado de erro; `fallback` se o código for desconhecido. */\nexport function authErrorMessage(\n result: { error?: string; code?: string; retryAfter?: number },\n fallback: string,\n): string {\n switch (result.code) {\n case \"waitlist_required\":\n return \"Esta aplicação está com lista de espera. Entre na lista para receber acesso.\";\n case \"waitlist_disabled\":\n return \"A lista de espera não está ativa para esta aplicação.\";\n case \"password_reset_required\":\n return \"Sua senha precisa ser redefinida antes de continuar. Use a opção de recuperar senha.\";\n case \"account_locked\": {\n const s = result.retryAfter;\n if (typeof s === \"number\" && s > 0) {\n const wait = s >= 60 ? `${Math.ceil(s / 60)} min` : `${s} s`;\n return `Conta temporariamente bloqueada por tentativas excessivas. Tente novamente em ${wait}.`;\n }\n return \"Conta temporariamente bloqueada. Tente novamente mais tarde.\";\n }\n case \"invalid_credentials\":\n return result.error ?? \"E-mail ou senha incorretos.\";\n default:\n return result.error ?? fallback;\n }\n}\n\n// ── Hook contract (structural — no import from auth-nextjs) ───────────────────\n\ntype UseAuthHook = () => {\n user: User | null;\n signIn: (opts?: { redirectTo?: string }) => Promise<void> | void;\n signOut: () => Promise<void> | void;\n signOutAll: () => Promise<void> | void;\n accounts: ConnectedAccount[];\n addAccount: (opts?: { redirectTo?: string }) => Promise<void> | void;\n isLoadingAccounts: boolean;\n refreshAccounts: () => Promise<void>;\n switchAccount: (id: string, opts?: { redirectTo?: string }) => Promise<void>;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId?: string | null;\n isLoadingOrganizations: boolean;\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (id: string) => Promise<void>;\n createOrganization: (input: OrganizationCreateInput) => Promise<AuthResult<Organization>>;\n /** Opcional: SDKs antigos não têm — sem ele, o formulário só não busca os dados do CNPJ. */\n lookupTaxId?: (value: string, type?: TaxIdType) => Promise<AuthResult<TaxIdLookupResult>>;\n /** Opcional (auth-nextjs >=0.26): sem ele o WaitlistForm mostra um aviso. */\n joinWaitlist?: (params: JoinWaitlistParams) => Promise<AuthResult<JoinWaitlistResponse>>;\n updateOrganization: (\n id: string,\n input: Partial<{\n name: string;\n slug: string;\n description: string | null;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n }>,\n ) => Promise<AuthResult<Organization>>;\n updateUser: (\n id: string,\n input: { name?: string | null; phone?: string | null; imageUrl?: string | null },\n ) => Promise<AuthResult<User>>;\n listUserSessions: (params: { userId?: string; organizationId?: string }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n listPermissions: (params: {\n applicationId?: string;\n roleId?: string | null;\n }) => Promise<Permission[]>;\n listRoles: (params?: {\n organizationId?: string;\n applicationId?: string;\n type?: \"system\" | \"custom\" | \"all\";\n }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n};\n\n// ── Primitive UI helpers ──────────────────────────────────────────────────────\n\ntype ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n tone?: ElementTone;\n size?: ElementSize;\n};\n\nfunction cx(...classes: Array<string | false | null | undefined>) {\n return classes.filter(Boolean).join(\" \");\n}\n\nfunction initials(value?: string | null) {\n const normalized = value?.trim();\n if (!normalized) return \"?\";\n const parts = normalized.split(/\\s+/).slice(0, 2);\n return parts.map((part) => part[0]?.toUpperCase()).join(\"\") || \"?\";\n}\n\nfunction formatDate(value?: string | Date | null) {\n if (!value) return \"-\";\n return new Intl.DateTimeFormat(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n }).format(new Date(value));\n}\n\nfunction isExpired(value: string | Date) {\n return new Date(value).getTime() <= Date.now();\n}\n\nfunction Button({\n className,\n tone = \"default\",\n size = \"md\",\n ...props\n}: ButtonProps) {\n return (\n <button\n {...props}\n className={cx(\n \"inline-flex items-center justify-center gap-2 rounded-lg font-medium transition disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"sm\" && \"h-8 px-3 text-xs\",\n size === \"md\" && \"h-10 px-4 text-sm\",\n size === \"lg\" && \"h-11 px-5 text-sm\",\n tone === \"default\" &&\n \"border border-slate-200 bg-white text-slate-800 hover:bg-slate-50\",\n tone === \"primary\" && \"bg-slate-950 text-white hover:bg-slate-800\",\n tone === \"danger\" && \"bg-red-600 text-white hover:bg-red-700\",\n tone === \"ghost\" &&\n \"bg-transparent text-slate-600 hover:bg-slate-100 hover:text-slate-950\",\n className,\n )}\n />\n );\n}\n\nfunction Input(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return (\n <input\n {...props}\n className={cx(\n \"h-10 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 outline-none placeholder:text-slate-400 focus:border-slate-400\",\n props.className,\n )}\n />\n );\n}\n\nfunction Textarea(props: React.TextareaHTMLAttributes<HTMLTextAreaElement>) {\n return (\n <textarea\n {...props}\n className={cx(\n \"min-h-[86px] w-full resize-none rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none placeholder:text-slate-400 focus:border-slate-400\",\n props.className,\n )}\n />\n );\n}\n\nfunction Field({ label, children }: { label: string; children: ReactNode }) {\n return (\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-slate-600\">{label}</span>\n {children}\n </label>\n );\n}\n\n// ── Standalone components (no hooks) ─────────────────────────────────────────\n\nexport function Avatar({\n src,\n name,\n size = \"md\",\n className,\n}: {\n src?: string | null;\n name?: string | null;\n size?: ElementSize;\n className?: string;\n}) {\n return (\n <span\n className={cx(\n \"inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-slate-100 font-semibold text-slate-700\",\n size === \"sm\" && \"h-8 w-8 text-xs\",\n size === \"md\" && \"h-10 w-10 text-sm\",\n size === \"lg\" && \"h-12 w-12 text-base\",\n className,\n )}\n >\n {src ? (\n <img\n alt={name ?? \"Avatar\"}\n className=\"h-full w-full object-cover\"\n src={src}\n />\n ) : (\n initials(name)\n )}\n </span>\n );\n}\n\nexport function Modal({\n open,\n onOpenChange,\n title,\n description,\n children,\n footer,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: string;\n description?: string;\n children: ReactNode;\n footer?: ReactNode;\n}) {\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-2xl bg-white shadow-xl\">\n <div className=\"flex items-start justify-between gap-4 border-b border-slate-200 p-5\">\n <div>\n <h2 className=\"text-lg font-semibold text-slate-950\">{title}</h2>\n {description && (\n <p className=\"mt-1 text-sm text-slate-500\">{description}</p>\n )}\n </div>\n <Button\n aria-label=\"Close\"\n onClick={() => onOpenChange(false)}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n ✕\n </Button>\n </div>\n <div className=\"max-h-[68vh] overflow-y-auto p-5\">{children}</div>\n {footer && (\n <div className=\"border-t border-slate-200 p-5\">{footer}</div>\n )}\n </div>\n </div>\n );\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Creates auth UI components bound to the provided `useAuth` hook instance.\n * This lets consumers supply their own auth-nextjs instance without requiring\n * a separate installed copy inside auth-elements-nextjs.\n *\n * @example\n * import { createAuthElements } from '@geekapps/auth-elements-nextjs'\n * import { useAuth } from '@geekapps/auth-nextjs/client'\n * export const { SignInButton, ProfileModal } = createAuthElements({ useAuth })\n */\nexport function createAuthElements(hooks: { useAuth: UseAuthHook }) {\n const { useAuth } = hooks;\n\n function SignInButton({\n children = \"Entrar\",\n redirectTo,\n }: {\n children?: ReactNode;\n redirectTo?: string;\n }) {\n const { signIn } = useAuth();\n return (\n <Button\n onClick={() => void signIn({ redirectTo })}\n tone=\"primary\"\n type=\"button\"\n >\n {children}\n </Button>\n );\n }\n\n function SignOutButton({ children = \"Sair\" }: { children?: ReactNode }) {\n const { signOut } = useAuth();\n return (\n <Button onClick={() => void signOut()} tone=\"ghost\" type=\"button\">\n {children}\n </Button>\n );\n }\n\n function AccountSwitcher() {\n const {\n accounts,\n addAccount,\n isLoadingAccounts,\n refreshAccounts,\n switchAccount,\n } = useAuth();\n const activeAccount =\n accounts.find((account) => account.isActive) ?? accounts[0] ?? null;\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"relative\">\n <button\n className=\"flex h-10 w-10 items-center justify-center rounded-xl transition hover:opacity-80\"\n onClick={() => setOpen((value) => !value)}\n title={activeAccount?.user.name ?? activeAccount?.user.email ?? \"Conta\"}\n type=\"button\"\n >\n <Avatar\n name={activeAccount?.user.name ?? activeAccount?.user.email}\n size=\"sm\"\n src={activeAccount?.user.imageUrl}\n />\n </button>\n\n {open && (\n <>\n <div className=\"fixed inset-0 z-20\" onClick={() => setOpen(false)} />\n <div className=\"absolute bottom-0 left-14 z-30 w-72 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg\">\n <div className=\"border-b border-slate-100 px-3 py-2.5\">\n <p className=\"text-[11px] font-medium uppercase tracking-wider text-slate-400\">\n Contas\n </p>\n </div>\n <div className=\"p-1.5\">\n {isLoadingAccounts && (\n <p className=\"px-2 py-3 text-xs text-slate-400\">\n Carregando...\n </p>\n )}\n {accounts.map((account) => (\n <button\n className={cx(\n \"flex w-full items-center gap-2.5 rounded-lg px-2 py-2 text-left transition hover:bg-slate-50\",\n account.isActive && \"bg-slate-50\",\n )}\n key={account.sessionId ?? account.id}\n onClick={() => {\n void switchAccount(account.sessionId ?? account.id);\n setOpen(false);\n }}\n type=\"button\"\n >\n <Avatar\n name={account.user.name ?? account.user.email}\n size=\"sm\"\n src={account.user.imageUrl}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-900\">\n {account.user.name ?? account.user.email}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {account.user.email}\n </span>\n </span>\n {account.isActive && (\n <span className=\"shrink-0 text-xs font-medium text-emerald-600\">\n ✓\n </span>\n )}\n </button>\n ))}\n </div>\n <div className=\"flex gap-1.5 border-t border-slate-100 p-1.5\">\n <Button\n className=\"flex-1\"\n onClick={() => void addAccount()}\n size=\"sm\"\n type=\"button\"\n >\n + Conta\n </Button>\n <Button\n className=\"flex-1\"\n onClick={() => void refreshAccounts()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Atualizar\n </Button>\n </div>\n </div>\n </>\n )}\n </div>\n );\n }\n\n // Formulário de criação compartilhado: organização padrão (sem documento)\n // ou legal (associada a CNPJ / Tax ID, com os dados da empresa buscados\n // automaticamente e os obrigatórios que faltarem pedidos ao usuário).\n function CreateOrganizationForm({\n onCreated,\n onCancel,\n compact = false,\n }: {\n onCreated?: (organization: Organization) => void;\n onCancel?: () => void;\n compact?: boolean;\n }) {\n const { createOrganization, lookupTaxId, setCurrentOrg } = useAuth();\n const [values, setValues] = useState<Record<string, string>>({ ...EMPTY_ORG_FORM });\n const [missing, setMissing] = useState<string[]>([]);\n const [lookupInfo, setLookupInfo] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState<\"lookup\" | \"create\" | null>(null);\n const isLegal = values.type === \"legal\";\n const isCnpj = values.taxIdType === \"br_cnpj\";\n\n const set = (key: string, value: string) =>\n setValues((current) => {\n const next = { ...current, [key]: value };\n if (key === \"name\" && !current.slugTouched) next.slug = slugify(value);\n if (key === \"slug\") next.slugTouched = \"1\";\n return next;\n });\n\n async function runLookup() {\n if (!lookupTaxId || !values.taxId) return;\n setBusy(\"lookup\");\n setError(null);\n setLookupInfo(null);\n const result = await lookupTaxId(values.taxId, values.taxIdType as TaxIdType);\n setBusy(null);\n if (!result.success) {\n setError(authErrorMessage(result, \"Tax ID inválido.\"));\n return;\n }\n const { data } = result.data;\n setValues((current) => {\n const next: Record<string, string> = { ...current, taxId: result.data.taxId };\n const fill = (key: string, value: string | null | undefined) => {\n if (value && !current[key]) next[key] = value;\n };\n fill(\"legalName\", data.legalName);\n fill(\"tradeName\", data.tradeName);\n fill(\"legalEmail\", data.legalEmail);\n fill(\"legalPhone\", data.legalPhone);\n for (const key of ADDRESS_KEYS) fill(`legalAddress.${key}`, data.legalAddress?.[key]);\n if (result.data.taxIdCountry) next.taxIdCountry = result.data.taxIdCountry;\n if (!current.name && result.data.suggestedName) {\n next.name = result.data.suggestedName;\n if (!current.slugTouched) next.slug = slugify(result.data.suggestedName);\n }\n return next;\n });\n setMissing(result.data.missingFields);\n if (result.data.alreadyRegistered) {\n setError(\"Já existe uma organização com este documento neste app.\");\n } else if (result.data.found) {\n setLookupInfo(\n `Dados encontrados${result.data.registrationStatus ? ` · situação ${result.data.registrationStatus}` : \"\"}. Revise e complete o que faltar.`,\n );\n } else {\n setLookupInfo(\n result.data.lookupAvailable\n ? \"Documento válido, mas sem dados públicos. Preencha os campos obrigatórios.\"\n : \"Consulta indisponível no momento. Preencha os campos obrigatórios.\",\n );\n }\n }\n\n async function onSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n setBusy(\"create\");\n setError(null);\n const blank = (key: string) => values[key]?.trim() || null;\n const input: OrganizationCreateInput = {\n name: values.name.trim(),\n slug: values.slug.trim(),\n type: isLegal ? \"legal\" : \"standard\",\n };\n if (isLegal) {\n Object.assign(input, {\n taxId: blank(\"taxId\"),\n taxIdType: values.taxIdType,\n taxIdCountry: isCnpj ? \"BR\" : blank(\"taxIdCountry\"),\n legalName: blank(\"legalName\"),\n tradeName: blank(\"tradeName\"),\n legalEmail: blank(\"legalEmail\"),\n legalPhone: blank(\"legalPhone\"),\n legalAddress: Object.fromEntries(\n ADDRESS_KEYS.map((key) => [key, blank(`legalAddress.${key}`)]),\n ),\n });\n if (!isCnpj && !input.legalAddress?.country) {\n (input.legalAddress as Record<string, string | null>).country = blank(\"taxIdCountry\");\n }\n }\n const result = await createOrganization(input);\n setBusy(null);\n if (!result.success) {\n if (result.missingFields?.length) setMissing(result.missingFields);\n setError(authErrorMessage(result, \"Erro ao criar organização.\"));\n return;\n }\n setValues({ ...EMPTY_ORG_FORM });\n setMissing([]);\n setLookupInfo(null);\n if (result.data?.id) void setCurrentOrg(result.data.id);\n onCreated?.(result.data);\n }\n\n const field = (key: string, label: string, props: React.InputHTMLAttributes<HTMLInputElement> = {}) => {\n const required = REQUIRED_LEGAL.has(key);\n return (\n <Field label={`${label}${required ? \" *\" : \"\"}`}>\n <Input\n {...props}\n className={missing.includes(key) && !values[key] ? \"border-red-300\" : undefined}\n name={key}\n onChange={(event) => set(key, event.target.value)}\n required={required}\n value={values[key] ?? \"\"}\n />\n </Field>\n );\n };\n\n return (\n <form className={cx(\"grid\", compact ? \"gap-2\" : \"gap-4\")} onSubmit={onSubmit}>\n <div className=\"grid grid-cols-2 gap-1 rounded-lg bg-slate-100 p-1\">\n {(\n [\n [\"standard\", \"Padrão\"],\n [\"legal\", \"Empresa (CNPJ / Tax ID)\"],\n ] as const\n ).map(([type, label]) => (\n <button\n className={cx(\n \"rounded-md px-2 py-1.5 text-xs font-medium transition\",\n values.type === type ? \"bg-white text-slate-900 shadow-sm\" : \"text-slate-500\",\n )}\n key={type}\n onClick={() => set(\"type\", type)}\n type=\"button\"\n >\n {label}\n </button>\n ))}\n </div>\n\n {isLegal && (\n <>\n <div className=\"grid grid-cols-[auto_1fr] gap-2\">\n <select\n className=\"h-10 rounded-lg border border-slate-200 bg-white px-2 text-sm text-slate-900\"\n onChange={(event) => set(\"taxIdType\", event.target.value)}\n value={values.taxIdType}\n >\n <option value=\"br_cnpj\">CNPJ</option>\n <option value=\"generic\">Outro Tax ID</option>\n </select>\n <div className=\"flex gap-2\">\n <Input\n name=\"taxId\"\n onBlur={() => isCnpj && void runLookup()}\n onChange={(event) => set(\"taxId\", event.target.value)}\n placeholder={isCnpj ? \"00.000.000/0000-00\" : \"Tax ID\"}\n required\n value={values.taxId}\n />\n <Button disabled={busy !== null || !values.taxId} onClick={() => void runLookup()} size=\"sm\" type=\"button\">\n {busy === \"lookup\" ? \"Buscando…\" : isCnpj ? \"Buscar\" : \"Validar\"}\n </Button>\n </div>\n </div>\n {!isCnpj && field(\"taxIdCountry\", \"País do Tax ID (ISO, ex.: US)\", { maxLength: 2 })}\n {lookupInfo && (\n <p className=\"rounded-lg bg-slate-50 px-3 py-2 text-xs text-slate-600\">{lookupInfo}</p>\n )}\n </>\n )}\n\n {field(\"name\", \"Nome\", { placeholder: \"Minha organização\", required: true })}\n {field(\"slug\", \"Slug\", { placeholder: \"minha-org\", required: true })}\n\n {isLegal && (\n <>\n {field(\"legalName\", \"Razão social\")}\n {field(\"tradeName\", \"Nome fantasia\")}\n <div className=\"grid gap-2 sm:grid-cols-2\">\n {field(\"legalEmail\", \"E-mail\", { type: \"email\" })}\n {field(\"legalPhone\", \"Telefone\")}\n </div>\n {field(\"legalAddress.street\", \"Logradouro\")}\n <div className=\"grid gap-2 sm:grid-cols-2\">\n {field(\"legalAddress.number\", \"Número\")}\n {field(\"legalAddress.complement\", \"Complemento\")}\n {field(\"legalAddress.district\", \"Bairro\")}\n {field(\"legalAddress.city\", \"Cidade\")}\n {field(\"legalAddress.state\", \"Estado\")}\n {field(\"legalAddress.postalCode\", \"CEP / Código postal\")}\n </div>\n {!isCnpj && field(\"legalAddress.country\", \"País do endereço (ISO)\", { maxLength: 2 })}\n </>\n )}\n\n {error && <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">{error}</p>}\n\n <div className=\"flex justify-end gap-2\">\n {onCancel && (\n <Button onClick={onCancel} size=\"sm\" tone=\"ghost\" type=\"button\">\n Cancelar\n </Button>\n )}\n <Button disabled={busy !== null} size=\"sm\" tone=\"primary\" type=\"submit\">\n {busy === \"create\" ? \"Criando…\" : \"Criar organização\"}\n </Button>\n </div>\n </form>\n );\n }\n\n function OrgSwitcher() {\n const {\n currentOrg,\n isLoadingOrganizations,\n organizations,\n refreshOrganizations,\n setCurrentOrg,\n } = useAuth();\n const [open, setOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n\n return (\n <div className=\"relative\">\n <button\n className=\"flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white p-2 text-left hover:bg-slate-50\"\n onClick={() => setOpen((value) => !value)}\n type=\"button\"\n >\n <Avatar name={currentOrg?.name} src={currentOrg?.imageUrl} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-950\">\n {currentOrg?.name ?? \"Selecionar organização\"}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {isLoadingOrganizations\n ? \"Carregando...\"\n : `${organizations.length} organizações`}\n </span>\n </span>\n <span className=\"text-slate-400\">⌄</span>\n </button>\n\n {open && (\n <div className=\"absolute right-0 z-30 mt-2 w-80 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg\">\n <div className=\"max-h-72 overflow-y-auto p-2\">\n {organizations.map((organization) => (\n <button\n className=\"flex w-full items-center gap-3 rounded-lg p-2 text-left hover:bg-slate-50\"\n key={organization.id}\n onClick={() => {\n void setCurrentOrg(organization.id);\n setOpen(false);\n }}\n type=\"button\"\n >\n <Avatar\n name={organization.name}\n size=\"sm\"\n src={organization.imageUrl}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-slate-900\">\n {organization.name}\n </span>\n <span className=\"block truncate text-xs text-slate-500\">\n {organization.slug}\n </span>\n </span>\n {organization.id === currentOrg?.id && (\n <span className=\"text-xs font-medium text-emerald-600\">\n Atual\n </span>\n )}\n </button>\n ))}\n </div>\n\n {creating ? (\n <div className=\"max-h-[70vh] overflow-y-auto border-t border-slate-200 p-3\">\n <CreateOrganizationForm\n compact\n onCancel={() => setCreating(false)}\n onCreated={() => {\n setCreating(false);\n setOpen(false);\n void refreshOrganizations();\n }}\n />\n </div>\n ) : (\n <div className=\"flex gap-2 border-t border-slate-200 p-2\">\n <Button\n className=\"flex-1\"\n onClick={() => setCreating(true)}\n size=\"sm\"\n type=\"button\"\n >\n Nova org\n </Button>\n <Button\n className=\"flex-1\"\n onClick={() => void refreshOrganizations()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Atualizar\n </Button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n }\n\n function UserButton() {\n const { user } = useAuth();\n const [open, setOpen] = useState(false);\n return (\n <>\n <button onClick={() => setOpen(true)} type=\"button\">\n <Avatar name={user?.name ?? user?.email} src={user?.imageUrl} />\n </button>\n <ProfileModal open={open} onOpenChange={setOpen} />\n </>\n );\n }\n\n function OrganizationButton() {\n const { currentOrg } = useAuth();\n const [open, setOpen] = useState(false);\n return (\n <>\n <button\n className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-white border border-slate-200 text-xs font-semibold text-slate-700 transition hover:bg-slate-50 hover:border-slate-300\"\n onClick={() => setOpen(true)}\n title={currentOrg?.name ?? \"Organização\"}\n type=\"button\"\n >\n {currentOrg?.imageUrl ? (\n <img\n alt={currentOrg.name}\n className=\"h-full w-full rounded-xl object-cover\"\n src={currentOrg.imageUrl}\n />\n ) : (\n (currentOrg?.name ?? \"O\")[0]?.toUpperCase()\n )}\n </button>\n <ManageOrganizationModal open={open} onOpenChange={setOpen} />\n </>\n );\n }\n\n function ProfileModal({\n open,\n onOpenChange,\n }: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n }) {\n const {\n signOut,\n signOutAll,\n user,\n organizations,\n currentOrg,\n setCurrentOrg,\n updateUser,\n listUserSessions,\n revokeUserSession,\n } = useAuth();\n const [tab, setTab] = useState(\"profile\");\n const [sessions, setSessions] = useState<UserSession[]>([]);\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saveSuccess, setSaveSuccess] = useState(false);\n\n useEffect(() => {\n if (!open) {\n setTab(\"profile\");\n setSaveError(null);\n setSaveSuccess(false);\n }\n }, [open]);\n\n useEffect(() => {\n if (open && user && tab === \"sessions\") {\n void listUserSessions({ userId: user.id })\n .then(setSessions)\n .catch(() => setSessions([]));\n }\n }, [listUserSessions, open, tab, user]);\n\n async function onProfileSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!user) return;\n const form = new FormData(event.currentTarget);\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n try {\n await updateUser(user.id, {\n name: String(form.get(\"name\") ?? \"\") || null,\n phone: String(form.get(\"phone\") ?? \"\") || null,\n imageUrl: String(form.get(\"imageUrl\") ?? \"\") || null,\n });\n setSaveSuccess(true);\n setTimeout(() => setSaveSuccess(false), 2500);\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : \"Erro ao salvar.\");\n } finally {\n setSaving(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <Avatar\n name={user?.name ?? user?.email}\n size=\"sm\"\n src={user?.imageUrl}\n />\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {user?.name ?? user?.email ?? \"Minha conta\"}\n </p>\n <p className=\"text-xs text-slate-500\">{user?.email}</p>\n </div>\n </div>\n <button\n aria-label=\"Fechar\"\n className=\"rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700\"\n onClick={() => onOpenChange(false)}\n type=\"button\"\n >\n ✕\n </button>\n </div>\n\n {/* Tabs */}\n <div className=\"shrink-0 flex gap-1 border-b border-slate-100 px-6 pt-3\">\n {(\n [\n { id: \"profile\", label: \"Perfil\" },\n { id: \"sessions\", label: \"Sessões\" },\n { id: \"orgs\", label: \"Organizações\" },\n ] as const\n ).map((t) => (\n <button\n className={cx(\n \"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition\",\n tab === t.id\n ? \"border-slate-900 text-slate-900\"\n : \"border-transparent text-slate-500 hover:text-slate-700\",\n )}\n key={t.id}\n onClick={() => setTab(t.id)}\n type=\"button\"\n >\n {t.label}\n </button>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {tab === \"profile\" && user && (\n <form className=\"grid gap-4\" onSubmit={onProfileSubmit}>\n <div className=\"flex items-center gap-4 rounded-xl bg-slate-50 p-4\">\n <Avatar\n name={user.name ?? user.email}\n size=\"lg\"\n src={user.imageUrl}\n />\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {user.name ?? \"Sem nome\"}\n </p>\n <p className=\"text-xs text-slate-500\">{user.email}</p>\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Nome\">\n <Input\n defaultValue={user.name ?? \"\"}\n name=\"name\"\n placeholder=\"Seu nome\"\n />\n </Field>\n <Field label=\"Telefone\">\n <Input\n defaultValue={user.phone ?? \"\"}\n name=\"phone\"\n placeholder=\"+55 11 99999-9999\"\n />\n </Field>\n </div>\n <Field label=\"URL da imagem\">\n <Input\n defaultValue={user.imageUrl ?? \"\"}\n name=\"imageUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n\n {saveError && (\n <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">\n {saveError}\n </p>\n )}\n {saveSuccess && (\n <p className=\"rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600\">\n Perfil salvo com sucesso.\n </p>\n )}\n\n <div className=\"flex items-center justify-between border-t border-slate-100 pt-2\">\n <div className=\"flex gap-2\">\n <Button\n onClick={() => void signOut()}\n size=\"sm\"\n tone=\"ghost\"\n type=\"button\"\n >\n Sair\n </Button>\n <Button\n onClick={() => void signOutAll()}\n size=\"sm\"\n tone=\"danger\"\n type=\"button\"\n >\n Sair de todas\n </Button>\n </div>\n <Button\n disabled={saving}\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n {saving ? \"Salvando…\" : \"Salvar\"}\n </Button>\n </div>\n </form>\n )}\n\n {tab === \"sessions\" && (\n <div className=\"grid gap-2\">\n {sessions.length === 0 && (\n <p className=\"py-6 text-center text-sm text-slate-400\">\n Nenhuma sessão ativa.\n </p>\n )}\n {sessions.map((session) => {\n const expired = isExpired(session.expiresAt);\n return (\n <div\n className=\"flex items-center justify-between gap-4 rounded-xl border border-slate-200 p-4\"\n key={session.id}\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {session.deviceName ?? \"Dispositivo\"}\n </p>\n <p className=\"mt-0.5 truncate text-xs text-slate-500\">\n {session.ip ?? \"IP desconhecido\"} ·{\" \"}\n <span className={expired ? \"text-amber-600\" : \"\"}>\n {expired\n ? \"Expirada\"\n : `Expira ${formatDate(session.expiresAt)}`}\n </span>\n </p>\n </div>\n <Button\n onClick={async () => {\n await revokeUserSession(session.id);\n setSessions((s) =>\n s.filter((x) => x.id !== session.id),\n );\n }}\n size=\"sm\"\n tone=\"danger\"\n type=\"button\"\n >\n Revogar\n </Button>\n </div>\n );\n })}\n </div>\n )}\n\n {tab === \"orgs\" && (\n <div className=\"grid gap-2\">\n {organizations.length === 0 && (\n <p className=\"py-6 text-center text-sm text-slate-400\">\n Nenhuma organização.\n </p>\n )}\n {organizations.map((org) => (\n <button\n className={cx(\n \"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition\",\n org.id === currentOrg?.id\n ? \"border-slate-900 bg-slate-50\"\n : \"border-slate-200 hover:border-slate-300 hover:bg-slate-50\",\n )}\n key={org.id}\n onClick={() => void setCurrentOrg(org.id)}\n type=\"button\"\n >\n <Avatar name={org.name} size=\"sm\" src={org.imageUrl} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {org.name}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n /{org.slug}\n </p>\n </div>\n {org.id === currentOrg?.id && (\n <span className=\"shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white\">\n Ativa\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n function ManageOrganizationModal({\n open,\n onOpenChange,\n }: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n }) {\n const {\n createOrganization,\n currentOrg,\n organizations,\n refreshOrganizations,\n setCurrentOrg,\n updateOrganization,\n listPermissions,\n listRoles,\n } = useAuth();\n const [tab, setTab] = useState(\"orgs\");\n const [roles, setRoles] = useState<{\n systemRoles: Role[];\n customRoles: Role[];\n }>({ systemRoles: [], customRoles: [] });\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [saving, setSaving] = useState(false);\n const [saveSuccess, setSaveSuccess] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setTab(\"orgs\");\n setSaveError(null);\n setSaveSuccess(false);\n }\n }, [open]);\n\n useEffect(() => {\n if (!open || !currentOrg) return;\n if (tab === \"members\" || tab === \"roles\") {\n void listRoles({ organizationId: currentOrg.id })\n .then(setRoles)\n .catch(() => setRoles({ systemRoles: [], customRoles: [] }));\n void listPermissions({})\n .then(setPermissions)\n .catch(() => setPermissions([]));\n }\n }, [currentOrg, listPermissions, listRoles, open, tab]);\n\n async function onOrgSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!currentOrg) return;\n const form = new FormData(event.currentTarget);\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n try {\n await updateOrganization(currentOrg.id, {\n name: String(form.get(\"name\") ?? \"\"),\n description: String(form.get(\"description\") ?? \"\") || null,\n slug: String(form.get(\"slug\") ?? \"\"),\n domain: String(form.get(\"domain\") ?? \"\") || null,\n imageUrl: String(form.get(\"imageUrl\") ?? \"\") || null,\n faviconUrl: String(form.get(\"faviconUrl\") ?? \"\") || null,\n });\n setSaveSuccess(true);\n setTimeout(() => setSaveSuccess(false), 2500);\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : \"Erro ao salvar.\");\n } finally {\n setSaving(false);\n }\n }\n\n if (!open) return null;\n\n const orgTabs = [\n { id: \"orgs\", label: \"Organizações\" },\n { id: \"info\", label: \"Geral\" },\n { id: \"members\", label: \"Membros\" },\n { id: \"roles\", label: \"Roles\" },\n { id: \"new\", label: \"+ Nova org\" },\n ] as const;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <div className=\"flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n {currentOrg?.imageUrl ? (\n <img\n alt={currentOrg.name}\n className=\"h-8 w-8 rounded-lg object-cover\"\n src={currentOrg.imageUrl}\n />\n ) : (\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-xs font-semibold text-slate-600\">\n {(currentOrg?.name ?? \"O\")[0]?.toUpperCase()}\n </span>\n )}\n <div>\n <p className=\"text-sm font-semibold text-slate-900\">\n {currentOrg?.name ?? \"Organização\"}\n </p>\n {currentOrg?.slug && (\n <p className=\"text-xs text-slate-500\">/{currentOrg.slug}</p>\n )}\n </div>\n </div>\n <button\n aria-label=\"Fechar\"\n className=\"rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700\"\n onClick={() => onOpenChange(false)}\n type=\"button\"\n >\n ✕\n </button>\n </div>\n\n {/* Tabs */}\n <div className=\"flex shrink-0 gap-1 border-b border-slate-100 px-6 pt-3\">\n {orgTabs.map((t) => (\n <button\n className={cx(\n \"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition\",\n tab === t.id\n ? \"border-slate-900 text-slate-900\"\n : \"border-transparent text-slate-500 hover:text-slate-700\",\n )}\n key={t.id}\n onClick={() => setTab(t.id)}\n type=\"button\"\n >\n {t.label}\n </button>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {!currentOrg && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhuma organização selecionada.\n </p>\n )}\n\n {tab === \"orgs\" && (\n <div className=\"grid gap-2\">\n {organizations.length === 0 && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhuma organização disponível.\n </p>\n )}\n {organizations.map((org) => (\n <button\n className={cx(\n \"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition\",\n org.id === currentOrg?.id\n ? \"border-slate-900 bg-slate-50\"\n : \"border-slate-200 hover:border-slate-300 hover:bg-slate-50\",\n )}\n key={org.id}\n onClick={() => {\n void setCurrentOrg(org.id);\n onOpenChange(false);\n }}\n type=\"button\"\n >\n <Avatar name={org.name} size=\"sm\" src={org.imageUrl} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {org.name}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n /{org.slug}\n </p>\n </div>\n {org.id === currentOrg?.id && (\n <span className=\"shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white\">\n Ativa\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n\n {tab === \"info\" && currentOrg && (\n <form className=\"grid gap-4\" onSubmit={onOrgSubmit}>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Nome *\">\n <Input defaultValue={currentOrg.name} name=\"name\" required />\n </Field>\n <Field label=\"Slug *\">\n <Input defaultValue={currentOrg.slug} name=\"slug\" required />\n </Field>\n </div>\n <Field label=\"Descrição\">\n <Textarea\n defaultValue={currentOrg.description ?? \"\"}\n name=\"description\"\n placeholder=\"Descreva a organização…\"\n />\n </Field>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Domínio\">\n <Input\n defaultValue={currentOrg.domain ?? \"\"}\n name=\"domain\"\n placeholder=\"acme.com\"\n />\n </Field>\n <Field label=\"URL da imagem\">\n <Input\n defaultValue={currentOrg.imageUrl ?? \"\"}\n name=\"imageUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n </div>\n <Field label=\"URL do favicon\">\n <Input\n defaultValue={currentOrg.faviconUrl ?? \"\"}\n name=\"faviconUrl\"\n placeholder=\"https://...\"\n />\n </Field>\n\n {saveError && (\n <p className=\"rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600\">\n {saveError}\n </p>\n )}\n {saveSuccess && (\n <p className=\"rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600\">\n Organização atualizada.\n </p>\n )}\n\n <div className=\"flex justify-end pt-1\">\n <Button\n disabled={saving}\n size=\"sm\"\n tone=\"primary\"\n type=\"submit\"\n >\n {saving ? \"Salvando…\" : \"Salvar organização\"}\n </Button>\n </div>\n </form>\n )}\n\n {tab === \"members\" && currentOrg && (\n <div className=\"grid gap-2\">\n {(currentOrg.members ?? []).length === 0 && (\n <p className=\"py-8 text-center text-sm text-slate-400\">\n Nenhum membro nesta organização.\n </p>\n )}\n {(currentOrg.members ?? []).map((member) => (\n <div\n className=\"flex items-center gap-3 rounded-xl border border-slate-200 p-4\"\n key={member.id}\n >\n <Avatar\n name={member.user.name ?? member.user.email}\n size=\"sm\"\n src={member.user.imageUrl}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-slate-900\">\n {member.user.name ?? member.user.email}\n </p>\n <p className=\"truncate text-xs text-slate-500\">\n {member.user.email}\n </p>\n </div>\n <div className=\"flex shrink-0 flex-wrap justify-end gap-1\">\n {(member.roleAssignments ?? []).map((a) => (\n <span\n className=\"rounded-full bg-slate-900 px-2 py-0.5 text-[11px] font-medium text-white\"\n key={a.id}\n >\n {a.roleDefinition?.name ?? a.customRole?.name ?? a.id}\n </span>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {tab === \"new\" && (\n <div className=\"grid gap-4\">\n <p className=\"text-sm text-slate-500\">\n Crie uma nova organização e alterne para ela automaticamente.\n </p>\n <CreateOrganizationForm\n onCancel={() => setTab(\"info\")}\n onCreated={() => {\n void refreshOrganizations();\n setTab(\"info\");\n }}\n />\n </div>\n )}\n\n {tab === \"roles\" && (\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <h3 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400\">\n Roles ({roles.systemRoles.length + roles.customRoles.length})\n </h3>\n <div className=\"max-h-[280px] space-y-2 overflow-y-auto pr-1\">\n {roles.systemRoles.length === 0 &&\n roles.customRoles.length === 0 && (\n <p className=\"text-sm text-slate-400\">Nenhuma role.</p>\n )}\n {[...roles.systemRoles, ...roles.customRoles].map((role) => (\n <div\n className=\"overflow-hidden rounded-xl border border-slate-200 p-3\"\n key={role.id}\n >\n <p className=\"truncate text-sm font-semibold text-slate-900\">\n {role.name}\n </p>\n <p className=\"truncate text-xs text-slate-400\">\n {role.key}\n </p>\n <p className=\"mt-1 text-xs text-slate-500\">\n {role.permissions.length} permission\n {role.permissions.length !== 1 ? \"s\" : \"\"}\n </p>\n </div>\n ))}\n </div>\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400\">\n Permissions ({permissions.length})\n </h3>\n <div className=\"max-h-[280px] space-y-2 overflow-y-auto pr-1\">\n {permissions.length === 0 && (\n <p className=\"text-sm text-slate-400\">\n Nenhuma permission.\n </p>\n )}\n {permissions.map((permission) => (\n <div\n className=\"overflow-hidden rounded-xl border border-slate-200 p-3\"\n key={permission.id}\n >\n <p className=\"truncate text-sm font-semibold text-slate-900\">\n {permission.key}\n </p>\n <p className=\"truncate text-xs text-slate-400\">\n {permission.category ?? \"custom\"}\n </p>\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n function WaitlistForm({\n clientId,\n defaultEmail = \"\",\n onJoined,\n submitLabel = \"Entrar na lista de espera\",\n }: {\n clientId: string;\n defaultEmail?: string;\n onJoined?: (response: JoinWaitlistResponse) => void;\n submitLabel?: string;\n }) {\n const { joinWaitlist } = useAuth();\n const [name, setName] = useState(\"\");\n const [email, setEmail] = useState(defaultEmail);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [done, setDone] = useState<JoinWaitlistResponse | null>(null);\n\n async function submit(event: FormEvent) {\n event.preventDefault();\n if (!joinWaitlist) {\n setError(\"Lista de espera indisponível: atualize @geekapps/auth-nextjs para 0.26 ou superior.\");\n return;\n }\n setBusy(true);\n setError(null);\n const result = await joinWaitlist({\n clientId,\n email: email.trim(),\n name: name.trim() || undefined,\n });\n setBusy(false);\n if (!result.success) {\n setError(authErrorMessage(result, \"Não foi possível entrar na lista de espera.\"));\n return;\n }\n setDone(result.data);\n onJoined?.(result.data);\n }\n\n if (done) {\n return (\n <div className=\"grid gap-1 rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-center\">\n <p className=\"text-sm font-semibold text-emerald-800\">\n {done.status === \"approved\"\n ? \"Seu acesso foi liberado!\"\n : done.status === \"joined\"\n ? \"Você já tem acesso.\"\n : \"Você está na lista de espera.\"}\n </p>\n {done.status === \"waiting\" && done.position != null && (\n <p className=\"text-sm text-emerald-700\">\n Sua posição na fila: <span className=\"font-semibold\">#{done.position}</span>\n </p>\n )}\n </div>\n );\n }\n\n return (\n <form className=\"grid gap-3\" onSubmit={(event) => void submit(event)}>\n <Field label=\"Nome\">\n <Input\n autoComplete=\"name\"\n onChange={(event) => setName(event.target.value)}\n placeholder=\"Seu nome\"\n value={name}\n />\n </Field>\n <Field label=\"E-mail\">\n <Input\n autoComplete=\"email\"\n onChange={(event) => setEmail(event.target.value)}\n placeholder=\"voce@exemplo.com\"\n required\n type=\"email\"\n value={email}\n />\n </Field>\n {error && <p className=\"text-xs text-red-600\">{error}</p>}\n <Button disabled={busy || !email.trim()} tone=\"primary\" type=\"submit\">\n {busy ? \"Enviando...\" : submitLabel}\n </Button>\n </form>\n );\n }\n\n return {\n WaitlistForm,\n SignInButton,\n SignOutButton,\n AccountSwitcher,\n OrgSwitcher,\n UserButton,\n OrganizationButton,\n ProfileModal,\n ManageOrganizationModal,\n CreateOrganizationForm,\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekapps/auth-elements-nextjs",
3
- "version": "0.2.5",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "./src/styles.css"
@@ -17,7 +17,8 @@
17
17
  "README.md"
18
18
  ],
19
19
  "scripts": {
20
- "build": "tsup && tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify"
20
+ "build": "tsup && tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
21
+ "check:contract": "tsc --noEmit -p tsconfig.contract.json"
21
22
  },
22
23
  "dependencies": {
23
24
  "tailwindcss": "^4.2.2"
@@ -26,7 +27,8 @@
26
27
  "next": ">=15",
27
28
  "react": ">=18",
28
29
  "react-dom": ">=18",
29
- "typescript": ">=5"
30
+ "typescript": ">=5",
31
+ "@geekapps/auth-nextjs": ">=0.20.0"
30
32
  },
31
33
  "devDependencies": {
32
34
  "@types/node": "^25.0.0",
@@ -34,5 +36,10 @@
34
36
  "tsup": "^8.5.1",
35
37
  "typescript": "^5.0.0",
36
38
  "@tailwindcss/cli": "^4.2.2"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "@geekapps/auth-nextjs": {
42
+ "optional": true
43
+ }
37
44
  }
38
- }
45
+ }