azirid-react 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,3333 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactHookForm = require('react-hook-form');
5
+ var zod$1 = require('@hookform/resolvers/zod');
6
+ var zod = require('zod');
7
+ var clsx = require('clsx');
8
+ var tailwindMerge = require('tailwind-merge');
9
+ var reactQuery = require('@tanstack/react-query');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+ var classVarianceAuthority = require('class-variance-authority');
12
+ var radixUi = require('radix-ui');
13
+
14
+ function createLoginSchema(v) {
15
+ return zod.z.object({
16
+ email: zod.z.string({ required_error: v.emailRequired }).min(1, v.emailRequired).email(v.emailInvalid),
17
+ password: zod.z.string({ required_error: v.passwordRequired }).min(1, v.passwordRequired)
18
+ });
19
+ }
20
+ function createSignupSchema(v) {
21
+ return zod.z.object({
22
+ email: zod.z.string({ required_error: v.emailRequired }).min(1, v.emailRequired).email(v.emailInvalid),
23
+ password: zod.z.string({ required_error: v.passwordRequired }).min(10, v.passwordMinLength),
24
+ acceptedTosVersion: zod.z.string().optional(),
25
+ acceptedPrivacyVersion: zod.z.string().optional()
26
+ });
27
+ }
28
+ var loginSchema = zod.z.object({
29
+ email: zod.z.string({ required_error: "El correo es requerido" }).min(1, "El correo es requerido").email("Correo electr\xF3nico inv\xE1lido"),
30
+ password: zod.z.string({ required_error: "La contrase\xF1a es requerida" }).min(1, "La contrase\xF1a es requerida")
31
+ });
32
+ var signupSchema = zod.z.object({
33
+ email: zod.z.string({ required_error: "El correo es requerido" }).min(1, "El correo es requerido").email("Correo electr\xF3nico inv\xE1lido"),
34
+ password: zod.z.string({ required_error: "La contrase\xF1a es requerida" }).min(10, "La contrase\xF1a debe tener al menos 10 caracteres"),
35
+ acceptedTosVersion: zod.z.string().optional(),
36
+ acceptedPrivacyVersion: zod.z.string().optional()
37
+ });
38
+ var changePasswordSchema = zod.z.object({
39
+ currentPassword: zod.z.string({ required_error: "La contrase\xF1a actual es requerida" }).min(1, "La contrase\xF1a actual es requerida"),
40
+ newPassword: zod.z.string({ required_error: "La nueva contrase\xF1a es requerida" }).min(10, "La contrase\xF1a debe tener al menos 10 caracteres")
41
+ });
42
+ var magicLinkRequestSchema = zod.z.object({
43
+ email: zod.z.string({ required_error: "El correo es requerido" }).min(1, "El correo es requerido").email("Correo electr\xF3nico inv\xE1lido")
44
+ });
45
+ var magicLinkVerifySchema = zod.z.object({
46
+ token: zod.z.string({ required_error: "El token es requerido" }).min(1, "El token es requerido")
47
+ });
48
+ var socialLoginSchema = zod.z.object({
49
+ provider: zod.z.enum(["google", "github"], {
50
+ required_error: "El proveedor es requerido"
51
+ }),
52
+ providerAccountId: zod.z.string({ required_error: "El ID de proveedor es requerido" }).min(1, "El ID de proveedor es requerido"),
53
+ email: zod.z.string({ required_error: "El correo es requerido" }).min(1, "El correo es requerido").email("Correo electr\xF3nico inv\xE1lido"),
54
+ emailVerified: zod.z.boolean().optional(),
55
+ firstName: zod.z.string().optional(),
56
+ lastName: zod.z.string().optional(),
57
+ createUserIfNotExists: zod.z.boolean().optional(),
58
+ turnstileToken: zod.z.string().optional(),
59
+ acceptedTosVersion: zod.z.string().optional(),
60
+ acceptedPrivacyVersion: zod.z.string().optional()
61
+ });
62
+ var passkeyRegisterStartSchema = zod.z.object({
63
+ deviceName: zod.z.string().optional()
64
+ });
65
+ function cn(...inputs) {
66
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
67
+ }
68
+
69
+ // src/client/index.ts
70
+ function isAuthError(err) {
71
+ return err instanceof Error && typeof err.status === "number" && (err.status === 401 || err.status === 403);
72
+ }
73
+ var SUFFIXES = {
74
+ login: "login",
75
+ signup: "signup",
76
+ logout: "logout",
77
+ me: "me",
78
+ refresh: "refresh",
79
+ bootstrap: "session/bootstrap",
80
+ magicLinkRequest: "magic-link/request",
81
+ magicLinkVerify: "magic-link/verify",
82
+ socialLogin: "social/login",
83
+ changePassword: "password/change",
84
+ passkeyLogin: "passkeys/login",
85
+ passkeyLoginStart: "passkeys/login/start",
86
+ passkeyLoginVerify: "passkeys/login/verify",
87
+ passkeyRegisterStart: "passkeys/register/start",
88
+ passkeyRegisterVerify: "passkeys/register/verify",
89
+ passkeys: "passkeys",
90
+ providers: "billing/providers",
91
+ plans: "billing/plans",
92
+ subscription: "billing/subscription",
93
+ checkout: "billing/checkout",
94
+ billingPortal: "billing/portal",
95
+ invoices: "billing/invoices",
96
+ submitTransferProof: "billing/transfer-proof",
97
+ transferProofs: "billing/transfer-proofs",
98
+ payphoneConfirm: "billing/payphone/confirm",
99
+ referralMe: "referrals/me",
100
+ referralStats: "referrals/stats"
101
+ };
102
+ var BASE_PATHS = {
103
+ /** Proxy mode (Next.js): requests go to the same origin via route handler */
104
+ proxy: "/api/auth",
105
+ /** Direct mode: requests go straight to the Azirid API */
106
+ direct: "/v1/users/auth"
107
+ };
108
+ function buildPaths(basePath) {
109
+ const bp = basePath.replace(/\/$/, "");
110
+ return Object.fromEntries(
111
+ Object.entries(SUFFIXES).map(([key, suffix]) => [key, `${bp}/${suffix}`])
112
+ );
113
+ }
114
+ var PATHS = buildPaths(BASE_PATHS.direct);
115
+ function createAccessClient(config, appContext) {
116
+ const baseUrl = config.baseUrl.replace(/\/$/, "");
117
+ const paths = config.basePath ? buildPaths(config.basePath) : PATHS;
118
+ const storageKeyRt = "__azrt";
119
+ const storageKeyCsrf = "__azxc";
120
+ function ssGet(key) {
121
+ try {
122
+ return typeof sessionStorage !== "undefined" ? sessionStorage.getItem(key) : null;
123
+ } catch {
124
+ return null;
125
+ }
126
+ }
127
+ function ssSet(key, value) {
128
+ try {
129
+ if (typeof sessionStorage === "undefined") return;
130
+ if (value) sessionStorage.setItem(key, value);
131
+ else sessionStorage.removeItem(key);
132
+ } catch {
133
+ }
134
+ }
135
+ let accessToken = null;
136
+ let refreshToken = ssGet(storageKeyRt);
137
+ let csrfToken = ssGet(storageKeyCsrf);
138
+ let refreshPromise = null;
139
+ function setAccessToken(token) {
140
+ accessToken = token;
141
+ }
142
+ function getAccessToken() {
143
+ return accessToken;
144
+ }
145
+ function setRefreshToken(token) {
146
+ refreshToken = token;
147
+ ssSet(storageKeyRt, token);
148
+ }
149
+ function getRefreshToken() {
150
+ return refreshToken;
151
+ }
152
+ function setCsrfToken(token) {
153
+ csrfToken = token;
154
+ ssSet(storageKeyCsrf, token);
155
+ }
156
+ const csrfCookieName = "_axc";
157
+ function getCsrfToken() {
158
+ if (csrfToken) return csrfToken;
159
+ if (typeof document === "undefined") return null;
160
+ const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${csrfCookieName}=([^;]*)`));
161
+ return match ? decodeURIComponent(match[1]) : null;
162
+ }
163
+ const sessionPaths = [paths.refresh, paths.bootstrap, paths.logout];
164
+ async function refreshTokensInternal() {
165
+ const reqHeaders = {
166
+ "Content-Type": "application/json",
167
+ ...config.headers
168
+ };
169
+ if (appContext?.publishableKey) {
170
+ reqHeaders["X-Publishable-Key"] = appContext.publishableKey;
171
+ }
172
+ const csrf = getCsrfToken();
173
+ if (csrf) reqHeaders["X-CSRF-Token"] = csrf;
174
+ const bodyPayload = {};
175
+ if (refreshToken) {
176
+ bodyPayload["rt"] = refreshToken;
177
+ }
178
+ const res = await fetch(`${baseUrl}${paths.refresh}`, {
179
+ method: "POST",
180
+ headers: reqHeaders,
181
+ credentials: "include",
182
+ body: JSON.stringify(bodyPayload)
183
+ });
184
+ if (!res.ok) {
185
+ accessToken = null;
186
+ setRefreshToken(null);
187
+ setCsrfToken(null);
188
+ throw new Error("Session expired");
189
+ }
190
+ const raw = await res.json();
191
+ const json = raw && typeof raw === "object" && "data" in raw && "meta" in raw ? raw.data : raw;
192
+ accessToken = json.at ?? json.accessToken ?? null;
193
+ const rt = json.rt ?? json.refreshToken;
194
+ const xc = json.xc ?? json.csrfToken;
195
+ if (rt) setRefreshToken(rt);
196
+ if (xc) setCsrfToken(xc);
197
+ }
198
+ function refreshTokens() {
199
+ if (refreshPromise) return refreshPromise;
200
+ refreshPromise = refreshTokensInternal().finally(() => {
201
+ refreshPromise = null;
202
+ });
203
+ return refreshPromise;
204
+ }
205
+ async function request(method, path, body) {
206
+ const headers = {
207
+ "Content-Type": "application/json",
208
+ ...config.headers
209
+ };
210
+ if (appContext?.publishableKey) {
211
+ headers["X-Publishable-Key"] = appContext.publishableKey;
212
+ }
213
+ const isSessionPath = sessionPaths.includes(path);
214
+ if (accessToken && !isSessionPath) {
215
+ headers["Authorization"] = `Bearer ${accessToken}`;
216
+ }
217
+ const csrf = getCsrfToken();
218
+ if (csrf) {
219
+ headers["X-CSRF-Token"] = csrf;
220
+ }
221
+ let requestBody = body;
222
+ if (isSessionPath && refreshToken) {
223
+ const existing = typeof body === "object" && body !== null ? body : {};
224
+ if (!existing["rt"]) {
225
+ requestBody = { ...existing, rt: refreshToken };
226
+ }
227
+ }
228
+ let res = await fetch(`${baseUrl}${path}`, {
229
+ method,
230
+ headers,
231
+ credentials: "include",
232
+ ...requestBody !== void 0 ? { body: JSON.stringify(requestBody) } : {}
233
+ });
234
+ const skipRefreshPaths = [
235
+ paths.refresh,
236
+ paths.login,
237
+ paths.signup,
238
+ paths.bootstrap,
239
+ paths.logout
240
+ ];
241
+ if (res.status === 401 && !skipRefreshPaths.includes(path)) {
242
+ try {
243
+ await refreshTokens();
244
+ } catch {
245
+ let msg = "Session expired";
246
+ try {
247
+ const json2 = await res.json();
248
+ msg = json2.message || json2.error?.message || (typeof json2.error === "string" ? json2.error : null) || msg;
249
+ } catch {
250
+ }
251
+ throw new Error(msg);
252
+ }
253
+ const retryHeaders = {
254
+ "Content-Type": "application/json",
255
+ ...config.headers
256
+ };
257
+ if (appContext?.publishableKey) {
258
+ retryHeaders["X-Publishable-Key"] = appContext.publishableKey;
259
+ }
260
+ if (accessToken && !isSessionPath) {
261
+ retryHeaders["Authorization"] = `Bearer ${accessToken}`;
262
+ }
263
+ const retryCsrf = getCsrfToken();
264
+ if (retryCsrf) {
265
+ retryHeaders["X-CSRF-Token"] = retryCsrf;
266
+ }
267
+ res = await fetch(`${baseUrl}${path}`, {
268
+ method,
269
+ headers: retryHeaders,
270
+ credentials: "include",
271
+ ...requestBody !== void 0 ? { body: JSON.stringify(requestBody) } : {}
272
+ });
273
+ }
274
+ if (!res.ok) {
275
+ let msg = `Error ${res.status}`;
276
+ try {
277
+ const json2 = await res.json();
278
+ msg = json2.message || json2.error?.message || (typeof json2.error === "string" ? json2.error : null) || msg;
279
+ } catch {
280
+ }
281
+ const err = new Error(msg);
282
+ err.status = res.status;
283
+ throw err;
284
+ }
285
+ if (res.status === 204) return void 0;
286
+ const json = await res.json();
287
+ if (json && typeof json === "object" && "data" in json && "meta" in json) {
288
+ return json.data;
289
+ }
290
+ return json;
291
+ }
292
+ return {
293
+ post: (path, body) => request("POST", path, body),
294
+ get: (path) => request("GET", path),
295
+ patch: (path, body) => request("PATCH", path, body),
296
+ del: (path) => request("DELETE", path),
297
+ paths,
298
+ baseUrl,
299
+ appContext,
300
+ setAccessToken,
301
+ getAccessToken,
302
+ setRefreshToken,
303
+ getRefreshToken,
304
+ setCsrfToken,
305
+ getCsrfToken,
306
+ refreshSession: refreshTokens
307
+ };
308
+ }
309
+
310
+ // src/i18n/es.ts
311
+ var es = {
312
+ login: {
313
+ title: "Inicia sesi\xF3n en tu cuenta",
314
+ description: "Ingresa tus credenciales para acceder al dashboard.",
315
+ submit: "Iniciar sesi\xF3n",
316
+ emailLabel: "Correo electr\xF3nico",
317
+ emailPlaceholder: "tu@empresa.com",
318
+ passwordLabel: "Contrase\xF1a",
319
+ passwordPlaceholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
320
+ },
321
+ signup: {
322
+ title: "Crea tu cuenta",
323
+ description: "Ingresa tus datos para registrarte.",
324
+ submit: "Crear cuenta",
325
+ emailLabel: "Correo electr\xF3nico",
326
+ emailPlaceholder: "tu@empresa.com",
327
+ passwordLabel: "Contrase\xF1a",
328
+ passwordPlaceholder: "M\xEDn. 10 caracteres",
329
+ confirmPasswordLabel: "Confirmar contrase\xF1a",
330
+ confirmPasswordPlaceholder: "Repite tu contrase\xF1a"
331
+ },
332
+ forgotPassword: {
333
+ title: "Recuperar contrase\xF1a",
334
+ description: "Ingresa tu correo electr\xF3nico y te enviaremos un enlace para restablecer tu contrase\xF1a.",
335
+ submit: "Enviar enlace",
336
+ emailLabel: "Correo electr\xF3nico",
337
+ emailPlaceholder: "tu@empresa.com",
338
+ successMessage: "Revisa tu correo electr\xF3nico para restablecer tu contrase\xF1a."
339
+ },
340
+ resetPassword: {
341
+ title: "Restablecer contrase\xF1a",
342
+ description: "Ingresa tu nueva contrase\xF1a.",
343
+ submit: "Restablecer contrase\xF1a",
344
+ newPasswordLabel: "Nueva contrase\xF1a",
345
+ newPasswordPlaceholder: "M\xEDn. 10 caracteres",
346
+ confirmPasswordLabel: "Confirmar contrase\xF1a",
347
+ confirmPasswordPlaceholder: "Repite tu contrase\xF1a"
348
+ },
349
+ social: {
350
+ google: "Continuar con Google",
351
+ apple: "Continuar con Apple",
352
+ separator: "o continuar con correo",
353
+ comingSoon: "Pr\xF3ximamente"
354
+ },
355
+ passwordToggle: {
356
+ show: "Ver",
357
+ hide: "Ocultar"
358
+ },
359
+ securedBy: "Protegido por",
360
+ billing: {
361
+ pay: "Pagar",
362
+ selectPaymentMethod: "Selecciona m\xE9todo de pago",
363
+ creditCard: "Tarjeta de cr\xE9dito/d\xE9bito",
364
+ paypal: "PayPal",
365
+ payphone: "Payphone",
366
+ bankTransfer: "Transferencia bancaria",
367
+ cancel: "Cancelar",
368
+ processing: "Procesando..."
369
+ },
370
+ validation: {
371
+ emailRequired: "El correo es requerido",
372
+ emailInvalid: "Correo electr\xF3nico inv\xE1lido",
373
+ passwordRequired: "La contrase\xF1a es requerida",
374
+ passwordMinLength: "La contrase\xF1a debe tener al menos 10 caracteres",
375
+ confirmPasswordRequired: "Confirma tu contrase\xF1a",
376
+ passwordsMismatch: "Las contrase\xF1as no coinciden",
377
+ tokenRequired: "El token es requerido",
378
+ newPasswordRequired: "La nueva contrase\xF1a es requerida",
379
+ currentPasswordRequired: "La contrase\xF1a actual es requerida",
380
+ mfaCodeRequired: "El c\xF3digo es requerido",
381
+ mfaCodeLength: "El c\xF3digo debe tener 6 d\xEDgitos",
382
+ providerRequired: "El proveedor es requerido",
383
+ providerIdRequired: "El ID de proveedor es requerido",
384
+ urlInvalid: "URL inv\xE1lida"
385
+ }
386
+ };
387
+
388
+ // src/i18n/en.ts
389
+ var en = {
390
+ login: {
391
+ title: "Sign in to your account",
392
+ description: "Enter your credentials to access the dashboard.",
393
+ submit: "Sign in",
394
+ emailLabel: "Email",
395
+ emailPlaceholder: "you@company.com",
396
+ passwordLabel: "Password",
397
+ passwordPlaceholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
398
+ },
399
+ signup: {
400
+ title: "Create your account",
401
+ description: "Enter your details to sign up.",
402
+ submit: "Create account",
403
+ emailLabel: "Email",
404
+ emailPlaceholder: "you@company.com",
405
+ passwordLabel: "Password",
406
+ passwordPlaceholder: "Min. 10 characters",
407
+ confirmPasswordLabel: "Confirm password",
408
+ confirmPasswordPlaceholder: "Repeat your password"
409
+ },
410
+ forgotPassword: {
411
+ title: "Reset password",
412
+ description: "Enter your email and we'll send you a link to reset your password.",
413
+ submit: "Send link",
414
+ emailLabel: "Email",
415
+ emailPlaceholder: "you@company.com",
416
+ successMessage: "Check your email to reset your password."
417
+ },
418
+ resetPassword: {
419
+ title: "Reset password",
420
+ description: "Enter your new password.",
421
+ submit: "Reset password",
422
+ newPasswordLabel: "New password",
423
+ newPasswordPlaceholder: "Min. 10 characters",
424
+ confirmPasswordLabel: "Confirm password",
425
+ confirmPasswordPlaceholder: "Repeat your password"
426
+ },
427
+ social: {
428
+ google: "Continue with Google",
429
+ apple: "Continue with Apple",
430
+ separator: "or continue with email",
431
+ comingSoon: "Coming soon"
432
+ },
433
+ passwordToggle: {
434
+ show: "Show",
435
+ hide: "Hide"
436
+ },
437
+ securedBy: "Secured by",
438
+ billing: {
439
+ pay: "Pay",
440
+ selectPaymentMethod: "Select payment method",
441
+ creditCard: "Credit/Debit Card",
442
+ paypal: "PayPal",
443
+ payphone: "Payphone",
444
+ bankTransfer: "Bank Transfer",
445
+ cancel: "Cancel",
446
+ processing: "Processing..."
447
+ },
448
+ validation: {
449
+ emailRequired: "Email is required",
450
+ emailInvalid: "Invalid email address",
451
+ passwordRequired: "Password is required",
452
+ passwordMinLength: "Password must be at least 10 characters",
453
+ confirmPasswordRequired: "Please confirm your password",
454
+ passwordsMismatch: "Passwords do not match",
455
+ tokenRequired: "Token is required",
456
+ newPasswordRequired: "New password is required",
457
+ currentPasswordRequired: "Current password is required",
458
+ mfaCodeRequired: "Code is required",
459
+ mfaCodeLength: "Code must be 6 digits",
460
+ providerRequired: "Provider is required",
461
+ providerIdRequired: "Provider ID is required",
462
+ urlInvalid: "Invalid URL"
463
+ }
464
+ };
465
+
466
+ // src/i18n/index.ts
467
+ var dictionaries = { es, en };
468
+ function resolveMessages(locale = "es", overrides) {
469
+ const base = dictionaries[locale] ?? dictionaries.es;
470
+ if (!overrides) return base;
471
+ return {
472
+ login: { ...base.login, ...overrides.login },
473
+ signup: { ...base.signup, ...overrides.signup },
474
+ forgotPassword: { ...base.forgotPassword, ...overrides.forgotPassword },
475
+ resetPassword: { ...base.resetPassword, ...overrides.resetPassword },
476
+ social: { ...base.social, ...overrides.social },
477
+ passwordToggle: { ...base.passwordToggle, ...overrides.passwordToggle },
478
+ securedBy: overrides.securedBy ?? base.securedBy,
479
+ billing: { ...base.billing, ...overrides.billing },
480
+ validation: { ...base.validation, ...overrides.validation }
481
+ };
482
+ }
483
+
484
+ // src/styles/generated.ts
485
+ var css = `/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
486
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){[data-azirid] *,[data-azirid] :before,[data-azirid] :after,[data-azirid] ::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-content:""}}[data-azirid]{--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-blue-500:oklch(62.3% .214 259.815);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--leading-snug:1.375;--radius-md:calc(var(--aa-radius) - 2px);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--aa-font-sans,ui-sans-serif, system-ui, sans-serif);--default-mono-font-family:var(--font-mono)}.\\@container\\/card-header{container:card-header/inline-size}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.start{inset-inline-start:var(--spacing)}.z-10{z-index:10}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.w-4{width:calc(var(--spacing) * 4)}.w-auto{width:auto}.w-full{width:100%}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.auto-rows-min{grid-auto-rows:min-content}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.self-center{align-self:center}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.overflow-hidden{overflow:hidden}.rounded-\\[min\\(var\\(--radius-md\\)\\,10px\\)\\]{border-radius:min(var(--radius-md), 10px)}.rounded-\\[min\\(var\\(--radius-md\\)\\,12px\\)\\]{border-radius:min(var(--radius-md), 12px)}.rounded-lg{border-radius:var(--aa-radius)}.rounded-md{border-radius:calc(var(--aa-radius) - 2px)}.rounded-xl{border-radius:calc(var(--aa-radius) + 4px)}.rounded-t-xl{border-top-left-radius:calc(var(--aa-radius) + 4px);border-top-right-radius:calc(var(--aa-radius) + 4px)}.rounded-b-xl{border-bottom-right-radius:calc(var(--aa-radius) + 4px);border-bottom-left-radius:calc(var(--aa-radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--aa-border)}.border-destructive,.border-destructive\\/50{border-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\\/50{border-color:color-mix(in oklab, var(--aa-destructive) 50%, transparent)}}.border-input{border-color:var(--aa-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--aa-background)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--aa-border)}.bg-card{background-color:var(--aa-card)}.bg-destructive,.bg-destructive\\/10{background-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\\/10{background-color:color-mix(in oklab, var(--aa-destructive) 10%, transparent)}}.bg-muted,.bg-muted\\/50{background-color:var(--aa-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/50{background-color:color-mix(in oklab, var(--aa-muted) 50%, transparent)}}.bg-primary{background-color:var(--aa-primary)}.bg-secondary{background-color:var(--aa-secondary)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-clip-padding{background-clip:padding-box}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[0\\.8rem\\]{font-size:.8rem}.leading-none{--tw-leading:1;line-height:1}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.text-card-foreground{color:var(--aa-card-foreground)}.text-destructive{color:var(--aa-destructive)}.text-muted-foreground{color:var(--aa-muted-foreground)}.text-primary{color:var(--aa-primary)}.text-primary-foreground{color:var(--aa-primary-foreground)}.text-secondary-foreground{color:var(--aa-secondary-foreground)}.uppercase{text-transform:uppercase}.underline-offset-4{text-underline-offset:4px}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground,.ring-foreground\\/10{--tw-ring-color:var(--aa-foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\\/10{--tw-ring-color:color-mix(in oklab, var(--aa-foreground) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-data-\\[disabled\\=true\\]\\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\\[disabled\\=true\\]\\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\\[size\\=sm\\]\\/card\\:p-3:is(:where(.group\\/card)[data-size=sm] *){padding:calc(var(--spacing) * 3)}.group-data-\\[size\\=sm\\]\\/card\\:px-3:is(:where(.group\\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 3)}.group-data-\\[size\\=sm\\]\\/card\\:text-sm:is(:where(.group\\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.peer-disabled\\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}.file\\:inline-flex::file-selector-button{display:inline-flex}.file\\:h-6::file-selector-button{height:calc(var(--spacing) * 6)}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--aa-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--aa-muted-foreground)}.after\\:absolute:after{content:var(--tw-content);position:absolute}.after\\:inset-0:after{content:var(--tw-content);inset:calc(var(--spacing) * 0)}.after\\:top-1\\/2:after{content:var(--tw-content);top:50%}.after\\:z-0:after{content:var(--tw-content);z-index:0}.after\\:flex:after{content:var(--tw-content);display:flex}.after\\:items-center:after{content:var(--tw-content);align-items:center}.after\\:border-t:after{content:var(--tw-content);border-top-style:var(--tw-border-style);border-top-width:1px}.after\\:border-border:after{content:var(--tw-content);border-color:var(--aa-border)}@media (hover:hover){.hover\\:bg-destructive\\/20:hover{background-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/20:hover{background-color:color-mix(in oklab, var(--aa-destructive) 20%, transparent)}}.hover\\:bg-muted:hover{background-color:var(--aa-muted)}.hover\\:bg-secondary\\/80:hover{background-color:var(--aa-secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab, var(--aa-secondary) 80%, transparent)}}.hover\\:text-foreground:hover{color:var(--aa-foreground)}.hover\\:underline:hover{text-decoration-line:underline}}.focus-visible\\:border-destructive\\/40:focus-visible{border-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:border-destructive\\/40:focus-visible{border-color:color-mix(in oklab, var(--aa-destructive) 40%, transparent)}}.focus-visible\\:border-ring:focus-visible{border-color:var(--aa-ring)}.focus-visible\\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--aa-destructive) 20%, transparent)}}.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--aa-ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--aa-ring) 50%, transparent)}}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:bg-input\\/50:disabled{background-color:var(--aa-input)}@supports (color:color-mix(in lab, red, red)){.disabled\\:bg-input\\/50:disabled{background-color:color-mix(in oklab, var(--aa-input) 50%, transparent)}}.disabled\\:opacity-50:disabled{opacity:.5}:where([data-slot=button-group]) .in-data-\\[slot\\=button-group\\]\\:rounded-lg{border-radius:var(--aa-radius)}.has-data-\\[icon\\=inline-end\\]\\:pr-1\\.5:has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-end\\]\\:pr-2:has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-end\\]\\:pr-3:has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 3)}.has-data-\\[icon\\=inline-start\\]\\:pl-1\\.5:has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-start\\]\\:pl-2:has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-start\\]\\:pl-3:has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 3)}.has-data-\\[slot\\=card-action\\]\\:grid-cols-\\[1fr_auto\\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\\[slot\\=card-description\\]\\:grid-rows-\\[auto_auto\\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-data-\\[slot\\=card-footer\\]\\:pb-0:has([data-slot=card-footer]){padding-bottom:calc(var(--spacing) * 0)}.has-\\[\\>img\\:first-child\\]\\:pt-0:has(>img:first-child){padding-top:calc(var(--spacing) * 0)}.aria-expanded\\:bg-muted[aria-expanded=true]{background-color:var(--aa-muted)}.aria-expanded\\:bg-secondary[aria-expanded=true]{background-color:var(--aa-secondary)}.aria-expanded\\:text-foreground[aria-expanded=true]{color:var(--aa-foreground)}.aria-expanded\\:text-secondary-foreground[aria-expanded=true]{color:var(--aa-secondary-foreground)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--aa-destructive)}.aria-invalid\\:ring-3[aria-invalid=true]{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--aa-destructive) 20%, transparent)}}.data-horizontal\\:h-px[data-horizontal]{height:1px}.data-horizontal\\:w-full[data-horizontal]{width:100%}.data-vertical\\:w-px[data-vertical]{width:1px}.data-vertical\\:self-stretch[data-vertical]{align-self:stretch}.data-\\[size\\=sm\\]\\:gap-3[data-size=sm]{gap:calc(var(--spacing) * 3)}.data-\\[size\\=sm\\]\\:py-3[data-size=sm]{padding-block:calc(var(--spacing) * 3)}.data-\\[size\\=sm\\]\\:has-data-\\[slot\\=card-footer\\]\\:pb-0[data-size=sm]:has([data-slot=card-footer]){padding-bottom:calc(var(--spacing) * 0)}@media (min-width:48rem){.md\\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.dark\\:border-input:is(.dark *){border-color:var(--aa-input)}.dark\\:bg-destructive\\/20:is(.dark *){background-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-destructive\\/20:is(.dark *){background-color:color-mix(in oklab, var(--aa-destructive) 20%, transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--aa-input)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab, var(--aa-input) 30%, transparent)}}@media (hover:hover){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:color-mix(in oklab, var(--aa-destructive) 30%, transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--aa-input)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--aa-input) 50%, transparent)}}.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:var(--aa-muted)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--aa-muted) 50%, transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--aa-destructive) 40%, transparent)}}.dark\\:disabled\\:bg-input\\/80:is(.dark *):disabled{background-color:var(--aa-input)}@supports (color:color-mix(in lab, red, red)){.dark\\:disabled\\:bg-input\\/80:is(.dark *):disabled{background-color:color-mix(in oklab, var(--aa-input) 80%, transparent)}}.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--aa-destructive) 50%, transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--aa-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--aa-destructive) 40%, transparent)}}.\\[\\&_a\\]\\:underline a{text-decoration-line:underline}.\\[\\&_a\\]\\:underline-offset-4 a{text-underline-offset:4px}@media (hover:hover){.\\[\\&_a\\]\\:hover\\:text-primary a:hover{color:var(--aa-primary)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-3\\.5 svg:not([class*=size-]){width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\\[\\.border-b\\]\\:pb-4.border-b{padding-bottom:calc(var(--spacing) * 4)}.group-data-\\[size\\=sm\\]\\/card\\:\\[\\.border-b\\]\\:pb-3:is(:where(.group\\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 3)}@media (hover:hover){.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:var(--aa-primary)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:color-mix(in oklab, var(--aa-primary) 80%, transparent)}}}:is(.\\*\\:\\[img\\:first-child\\]\\:rounded-t-xl>*):is(img:first-child){border-top-left-radius:calc(var(--aa-radius) + 4px);border-top-right-radius:calc(var(--aa-radius) + 4px)}:is(.\\*\\:\\[img\\:last-child\\]\\:rounded-b-xl>*):is(img:last-child){border-bottom-right-radius:calc(var(--aa-radius) + 4px);border-bottom-left-radius:calc(var(--aa-radius) + 4px)}[data-azirid]{--aa-radius:.625rem;--aa-background:oklch(100% 0 0);--aa-foreground:oklch(14.5% 0 0);--aa-card:oklch(100% 0 0);--aa-card-foreground:oklch(14.5% 0 0);--aa-popover:oklch(100% 0 0);--aa-popover-foreground:oklch(14.5% 0 0);--aa-primary:oklch(20.5% 0 0);--aa-primary-foreground:oklch(98.5% 0 0);--aa-secondary:oklch(97% 0 0);--aa-secondary-foreground:oklch(20.5% 0 0);--aa-muted:oklch(97% 0 0);--aa-muted-foreground:oklch(55.6% 0 0);--aa-accent:oklch(97% 0 0);--aa-accent-foreground:oklch(20.5% 0 0);--aa-destructive:oklch(57.7% .245 27.325);--aa-border:oklch(92.2% 0 0);--aa-input:oklch(92.2% 0 0);--aa-ring:oklch(70.8% 0 0);--aa-font-sans:ui-sans-serif, system-ui, sans-serif}@layer base{[data-azirid]{font-family:var(--aa-font-sans);color:var(--aa-foreground);background-color:var(--aa-background);-webkit-text-size-adjust:100%;tab-size:4;-webkit-font-smoothing:antialiased;line-height:1.5}[data-azirid] *,[data-azirid] :before,[data-azirid] :after{box-sizing:border-box;border:0 solid;border-color:var(--aa-border);margin:0;padding:0}[data-azirid] hr{height:0;color:inherit;border-top-width:1px}[data-azirid] h1,[data-azirid] h2,[data-azirid] h3,[data-azirid] h4,[data-azirid] h5,[data-azirid] h6{font-size:inherit;font-weight:inherit}[data-azirid] a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}[data-azirid] b,[data-azirid] strong{font-weight:bolder}[data-azirid] code,[data-azirid] kbd,[data-azirid] samp,[data-azirid] pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}[data-azirid] small{font-size:80%}[data-azirid] table{text-indent:0;border-color:inherit;border-collapse:collapse}[data-azirid] button,[data-azirid] input,[data-azirid] optgroup,[data-azirid] select,[data-azirid] textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}[data-azirid] button,[data-azirid] select{text-transform:none}[data-azirid] button,[data-azirid] input[type=button],[data-azirid] input[type=reset],[data-azirid] input[type=submit]{-webkit-appearance:button;background-color:#0000;background-image:none}[data-azirid] :-moz-focusring{outline:auto}[data-azirid] ::-moz-focus-inner{border-style:none;padding:0}[data-azirid] :-moz-ui-invalid{box-shadow:none}[data-azirid] progress{vertical-align:baseline}[data-azirid] ::-webkit-inner-spin-button{height:auto}[data-azirid] ::-webkit-outer-spin-button{height:auto}[data-azirid] [type=search]{-webkit-appearance:textfield;outline-offset:-2px}[data-azirid] ::-webkit-search-decoration{-webkit-appearance:none}[data-azirid] ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}[data-azirid] summary{display:list-item}[data-azirid] ol,[data-azirid] ul,[data-azirid] menu{margin:0;padding:0;list-style:none}[data-azirid] textarea{resize:vertical}[data-azirid] ::placeholder{opacity:1;color:currentColor}@supports (color:color-mix(in lab, red, red)){[data-azirid] ::placeholder{color:color-mix(in oklch, currentColor 50%, transparent)}}[data-azirid] img,[data-azirid] svg,[data-azirid] video,[data-azirid] canvas,[data-azirid] audio,[data-azirid] iframe,[data-azirid] embed,[data-azirid] object{vertical-align:middle;display:block}[data-azirid] img,[data-azirid] video{max-width:100%;height:auto}[data-azirid] [hidden]:not([hidden=until-found]){display:none}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}`;
487
+
488
+ // src/utils/inject-styles.ts
489
+ var STYLE_ID = "azirid-access-styles";
490
+ var injected = false;
491
+ function injectStyles() {
492
+ if (injected || typeof document === "undefined") return;
493
+ if (document.getElementById(STYLE_ID)) {
494
+ injected = true;
495
+ return;
496
+ }
497
+ const style = document.createElement("style");
498
+ style.id = STYLE_ID;
499
+ style.textContent = css;
500
+ document.head.appendChild(style);
501
+ injected = true;
502
+ }
503
+ function removeStyles() {
504
+ if (typeof document === "undefined") return;
505
+ document.getElementById(STYLE_ID)?.remove();
506
+ injected = false;
507
+ }
508
+ var AziridContext = react.createContext(null);
509
+ AziridContext.displayName = "AziridContext";
510
+ var ClientContext = react.createContext(null);
511
+ ClientContext.displayName = "AccessClientContext";
512
+ var BrandingContext = react.createContext(null);
513
+ BrandingContext.displayName = "BrandingContext";
514
+ function useAccessClient() {
515
+ const ctx = react.useContext(ClientContext);
516
+ if (!ctx) {
517
+ throw new Error("useAccessClient must be used within an <AziridProvider>.");
518
+ }
519
+ return ctx;
520
+ }
521
+ function useBranding() {
522
+ const ctx = react.useContext(BrandingContext);
523
+ return ctx?.branding ?? null;
524
+ }
525
+ function useMessages() {
526
+ const ctx = react.useContext(BrandingContext);
527
+ if (ctx) return ctx.messages;
528
+ return resolveMessages("es");
529
+ }
530
+ var defaultQueryClient = new reactQuery.QueryClient({
531
+ defaultOptions: {
532
+ queries: { retry: false, refetchOnWindowFocus: false }
533
+ }
534
+ });
535
+ function AziridProviderInner({
536
+ children,
537
+ client,
538
+ props
539
+ }) {
540
+ const queryClient = reactQuery.useQueryClient();
541
+ const [user, setUser] = react.useState(null);
542
+ const [accessToken, setAccessToken] = react.useState(null);
543
+ const [error, setError] = react.useState(null);
544
+ const [branding, setBranding] = react.useState(null);
545
+ const [isBootstrapping, setIsBootstrapping] = react.useState(props.autoBootstrap ?? true);
546
+ const messages = react.useMemo(
547
+ () => resolveMessages(props.locale ?? "es", props.messages),
548
+ [props.locale, props.messages]
549
+ );
550
+ const brandingValue = react.useMemo(
551
+ () => ({ branding, messages }),
552
+ [branding, messages]
553
+ );
554
+ const isProxyMode = !props.apiUrl;
555
+ const syncUrl = react.useMemo(() => {
556
+ if (props.sessionSyncUrl === false) return null;
557
+ if (props.sessionSyncUrl) return props.sessionSyncUrl;
558
+ if (isProxyMode) return null;
559
+ if (client.appContext?.publishableKey?.startsWith("pk_dev")) {
560
+ return "/api/auth/session";
561
+ }
562
+ return null;
563
+ }, [props.sessionSyncUrl, client.appContext?.publishableKey, isProxyMode]);
564
+ const syncSession = react.useCallback(
565
+ (token) => {
566
+ if (!syncUrl) return;
567
+ if (token) {
568
+ fetch(syncUrl, {
569
+ method: "POST",
570
+ headers: { "Content-Type": "application/json" },
571
+ body: JSON.stringify({ token })
572
+ }).catch(() => {
573
+ });
574
+ } else {
575
+ fetch(syncUrl, { method: "DELETE" }).catch(() => {
576
+ });
577
+ }
578
+ },
579
+ [syncUrl]
580
+ );
581
+ const updateAccessToken = react.useCallback(
582
+ (token) => {
583
+ setAccessToken(token);
584
+ client.setAccessToken(token);
585
+ syncSession(token);
586
+ },
587
+ [client, syncSession]
588
+ );
589
+ const saveSessionTokens = react.useCallback(
590
+ (data) => {
591
+ const rt = data.rt ?? data.refreshToken;
592
+ const xc = data.xc ?? data.csrfToken;
593
+ if (rt) client.setRefreshToken(rt);
594
+ if (xc) client.setCsrfToken(xc);
595
+ },
596
+ [client]
597
+ );
598
+ const clearSession = react.useCallback(() => {
599
+ setUser(null);
600
+ updateAccessToken(null);
601
+ client.setRefreshToken(null);
602
+ client.setCsrfToken(null);
603
+ }, [client, updateAccessToken]);
604
+ const withAppContext = react.useCallback(
605
+ (body) => {
606
+ if (client.appContext?.tenantId) {
607
+ return { ...body, tenantId: client.appContext.tenantId };
608
+ }
609
+ return body;
610
+ },
611
+ [client]
612
+ );
613
+ react.useEffect(() => {
614
+ const autoBootstrap = props.autoBootstrap ?? true;
615
+ if (!autoBootstrap) return;
616
+ let cancelled = false;
617
+ async function bootstrap() {
618
+ setIsBootstrapping(true);
619
+ try {
620
+ const response = await client.post(client.paths.bootstrap);
621
+ if (cancelled) return;
622
+ if (response.branding) {
623
+ setBranding(response.branding);
624
+ }
625
+ if (response.authenticated) {
626
+ const r = response;
627
+ setUser(response.user);
628
+ updateAccessToken(r.at ?? r.accessToken);
629
+ saveSessionTokens(r);
630
+ }
631
+ } catch (err) {
632
+ if (typeof console !== "undefined") {
633
+ const msg = err instanceof Error ? err.message : JSON.stringify(err);
634
+ console.warn("[azirid-access] bootstrap failed:", msg);
635
+ }
636
+ } finally {
637
+ if (!cancelled) {
638
+ setIsBootstrapping(false);
639
+ }
640
+ }
641
+ }
642
+ bootstrap();
643
+ return () => {
644
+ cancelled = true;
645
+ };
646
+ }, [client, props.autoBootstrap, updateAccessToken, saveSessionTokens]);
647
+ const silentRefresh = react.useCallback(async () => {
648
+ if (!client.getAccessToken()) return;
649
+ try {
650
+ await client.refreshSession();
651
+ updateAccessToken(client.getAccessToken());
652
+ } catch (err) {
653
+ if (isAuthError(err)) {
654
+ clearSession();
655
+ props.onSessionExpired?.();
656
+ }
657
+ }
658
+ }, [client, updateAccessToken, clearSession, props]);
659
+ react.useEffect(() => {
660
+ const intervalMs = props.refreshInterval ?? 5e4;
661
+ if (intervalMs <= 0) return;
662
+ const id = setInterval(silentRefresh, intervalMs);
663
+ return () => clearInterval(id);
664
+ }, [props.refreshInterval, silentRefresh]);
665
+ react.useEffect(() => {
666
+ function handleVisibilityChange() {
667
+ if (document.visibilityState === "visible") {
668
+ silentRefresh();
669
+ }
670
+ }
671
+ document.addEventListener("visibilitychange", handleVisibilityChange);
672
+ return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
673
+ }, [silentRefresh]);
674
+ const normalizeToken = react.useCallback(
675
+ (data) => data.at ?? data.accessToken,
676
+ []
677
+ );
678
+ const loginMutation = reactQuery.useMutation({
679
+ mutationFn: (data) => client.post(client.paths.login, withAppContext(data)),
680
+ onSuccess: (data) => {
681
+ setUser(data.user);
682
+ updateAccessToken(normalizeToken(data));
683
+ saveSessionTokens(data);
684
+ setError(null);
685
+ props.onLoginSuccess?.(data);
686
+ },
687
+ onError: (err) => {
688
+ setError(err.message);
689
+ props.onError?.(err.message);
690
+ }
691
+ });
692
+ const signupMutation = reactQuery.useMutation({
693
+ mutationFn: (data) => {
694
+ const { confirmPassword: _, ...payload } = data;
695
+ return client.post(client.paths.signup, withAppContext({ ...payload }));
696
+ },
697
+ onSuccess: (data) => {
698
+ setUser(data.user);
699
+ updateAccessToken(normalizeToken(data));
700
+ saveSessionTokens(data);
701
+ setError(null);
702
+ props.onSignupSuccess?.(data);
703
+ },
704
+ onError: (err) => {
705
+ setError(err.message);
706
+ props.onError?.(err.message);
707
+ }
708
+ });
709
+ const logoutMutation = reactQuery.useMutation({
710
+ mutationFn: () => client.post(client.paths.logout),
711
+ onSettled: () => {
712
+ clearSession();
713
+ setError(null);
714
+ queryClient.clear();
715
+ props.onLogoutSuccess?.();
716
+ }
717
+ });
718
+ const refreshFn = react.useCallback(async () => {
719
+ try {
720
+ await client.refreshSession();
721
+ updateAccessToken(client.getAccessToken());
722
+ } catch (err) {
723
+ clearSession();
724
+ queryClient.clear();
725
+ props.onSessionExpired?.();
726
+ throw err;
727
+ }
728
+ }, [client, queryClient, props, updateAccessToken, clearSession]);
729
+ const login = react.useCallback(
730
+ (data) => loginMutation.mutate(data),
731
+ [loginMutation]
732
+ );
733
+ const signup = react.useCallback((data) => signupMutation.mutate(data), [signupMutation]);
734
+ const logout = react.useCallback(() => logoutMutation.mutate(), [logoutMutation]);
735
+ const clearError = react.useCallback(() => setError(null), []);
736
+ const setUserFn = react.useCallback((u) => {
737
+ setUser(u);
738
+ }, []);
739
+ const value = react.useMemo(
740
+ () => ({
741
+ user,
742
+ accessToken,
743
+ isAuthenticated: user !== null,
744
+ isLoading: loginMutation.isPending || signupMutation.isPending,
745
+ error,
746
+ login,
747
+ signup,
748
+ logout,
749
+ clearError,
750
+ refresh: refreshFn,
751
+ setUser: setUserFn,
752
+ isLoginPending: loginMutation.isPending,
753
+ isSignupPending: signupMutation.isPending,
754
+ isBootstrapping,
755
+ loginMutation,
756
+ signupMutation,
757
+ logoutMutation
758
+ }),
759
+ [
760
+ user,
761
+ accessToken,
762
+ error,
763
+ login,
764
+ signup,
765
+ logout,
766
+ clearError,
767
+ refreshFn,
768
+ setUserFn,
769
+ loginMutation,
770
+ signupMutation,
771
+ logoutMutation,
772
+ isBootstrapping
773
+ ]
774
+ );
775
+ return /* @__PURE__ */ jsxRuntime.jsx(ClientContext.Provider, { value: client, children: /* @__PURE__ */ jsxRuntime.jsx(AziridContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(BrandingContext.Provider, { value: brandingValue, children }) }) });
776
+ }
777
+ function AziridProvider(props) {
778
+ react.useEffect(() => {
779
+ injectStyles();
780
+ return () => removeStyles();
781
+ }, []);
782
+ const client = react.useMemo(() => {
783
+ const appContext = props.publishableKey ? {
784
+ publishableKey: props.publishableKey,
785
+ tenantId: props.tenantId
786
+ } : void 0;
787
+ const isProxy = !props.apiUrl;
788
+ const baseUrl = isProxy ? "" : props.apiUrl.replace(/\/$/, "");
789
+ const basePath = isProxy ? BASE_PATHS.proxy : BASE_PATHS.direct;
790
+ return createAccessClient(
791
+ { baseUrl, basePath, headers: props.fetchOptions },
792
+ appContext
793
+ );
794
+ }, [props.publishableKey, props.tenantId, props.fetchOptions, props.apiUrl]);
795
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: defaultQueryClient, children: /* @__PURE__ */ jsxRuntime.jsx(AziridProviderInner, { client, props, children: props.children }) });
796
+ }
797
+ function useAzirid() {
798
+ const ctx = react.useContext(AziridContext);
799
+ if (!ctx) {
800
+ throw new Error(
801
+ "useAzirid must be used within an <AziridProvider>. Wrap your app (or the relevant subtree) with <AziridProvider>."
802
+ );
803
+ }
804
+ return ctx;
805
+ }
806
+ var buttonVariants = classVarianceAuthority.cva(
807
+ "cursor-pointer focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
808
+ {
809
+ variants: {
810
+ variant: {
811
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
812
+ outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
813
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
814
+ ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
815
+ destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
816
+ link: "text-primary underline-offset-4 hover:underline"
817
+ },
818
+ size: {
819
+ default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
820
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
821
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
822
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
823
+ icon: "size-8",
824
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
825
+ "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
826
+ "icon-lg": "size-9"
827
+ }
828
+ },
829
+ defaultVariants: {
830
+ variant: "default",
831
+ size: "default"
832
+ }
833
+ }
834
+ );
835
+ function Button({
836
+ className,
837
+ variant = "default",
838
+ size = "default",
839
+ asChild = false,
840
+ ...props
841
+ }) {
842
+ const Comp = asChild ? radixUi.Slot.Root : "button";
843
+ return /* @__PURE__ */ jsxRuntime.jsx(
844
+ Comp,
845
+ {
846
+ "data-slot": "button",
847
+ "data-variant": variant,
848
+ "data-size": size,
849
+ className: cn(buttonVariants({ variant, size, className })),
850
+ ...props
851
+ }
852
+ );
853
+ }
854
+ function Card({
855
+ className,
856
+ size = "default",
857
+ ...props
858
+ }) {
859
+ return /* @__PURE__ */ jsxRuntime.jsx(
860
+ "div",
861
+ {
862
+ "data-slot": "card",
863
+ "data-size": size,
864
+ className: cn(
865
+ "ring-foreground/10 bg-card text-card-foreground group/card flex flex-col gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
866
+ className
867
+ ),
868
+ ...props
869
+ }
870
+ );
871
+ }
872
+ function CardHeader({ className, ...props }) {
873
+ return /* @__PURE__ */ jsxRuntime.jsx(
874
+ "div",
875
+ {
876
+ "data-slot": "card-header",
877
+ className: cn(
878
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
879
+ className
880
+ ),
881
+ ...props
882
+ }
883
+ );
884
+ }
885
+ function CardTitle({ className, ...props }) {
886
+ return /* @__PURE__ */ jsxRuntime.jsx(
887
+ "div",
888
+ {
889
+ "data-slot": "card-title",
890
+ className: cn(
891
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
892
+ className
893
+ ),
894
+ ...props
895
+ }
896
+ );
897
+ }
898
+ function CardDescription({ className, ...props }) {
899
+ return /* @__PURE__ */ jsxRuntime.jsx(
900
+ "div",
901
+ {
902
+ "data-slot": "card-description",
903
+ className: cn("text-muted-foreground text-sm", className),
904
+ ...props
905
+ }
906
+ );
907
+ }
908
+ function CardContent({ className, ...props }) {
909
+ return /* @__PURE__ */ jsxRuntime.jsx(
910
+ "div",
911
+ {
912
+ "data-slot": "card-content",
913
+ className: cn("px-4 group-data-[size=sm]/card:px-3", className),
914
+ ...props
915
+ }
916
+ );
917
+ }
918
+ function FieldGroup({ className, ...props }) {
919
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "field-group", className: cn("flex flex-col gap-6", className), ...props });
920
+ }
921
+ function Field({ className, ...props }) {
922
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "field", className: cn("grid gap-3", className), ...props });
923
+ }
924
+ function FieldLabel({ className, ...props }) {
925
+ return /* @__PURE__ */ jsxRuntime.jsx(
926
+ "label",
927
+ {
928
+ "data-slot": "field-label",
929
+ className: cn("text-sm leading-none font-medium", className),
930
+ ...props
931
+ }
932
+ );
933
+ }
934
+ function FieldDescription({ className, ...props }) {
935
+ return /* @__PURE__ */ jsxRuntime.jsx(
936
+ "div",
937
+ {
938
+ "data-slot": "field-description",
939
+ className: cn(
940
+ "text-muted-foreground [&_a]:hover:text-primary text-sm [&_a]:underline [&_a]:underline-offset-4",
941
+ className
942
+ ),
943
+ ...props
944
+ }
945
+ );
946
+ }
947
+ function FieldSeparator({ className, children, ...props }) {
948
+ return /* @__PURE__ */ jsxRuntime.jsx(
949
+ "div",
950
+ {
951
+ "data-slot": "field-separator",
952
+ className: cn(
953
+ "after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t",
954
+ className
955
+ ),
956
+ ...props,
957
+ children: /* @__PURE__ */ jsxRuntime.jsx(
958
+ "span",
959
+ {
960
+ "data-slot": "field-separator-content",
961
+ className: "bg-card text-muted-foreground relative z-10 px-2",
962
+ children
963
+ }
964
+ )
965
+ }
966
+ );
967
+ }
968
+ function Input({ className, type, ...props }) {
969
+ return /* @__PURE__ */ jsxRuntime.jsx(
970
+ "input",
971
+ {
972
+ type,
973
+ "data-slot": "input",
974
+ className: cn(
975
+ "dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 file:text-foreground placeholder:text-muted-foreground h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
976
+ className
977
+ ),
978
+ ...props
979
+ }
980
+ );
981
+ }
982
+ var LoginForm = react.forwardRef(
983
+ ({
984
+ onSubmit: onSubmitProp,
985
+ schema: schemaProp,
986
+ isLoading: externalLoading,
987
+ error: externalError,
988
+ className,
989
+ style,
990
+ title: titleProp,
991
+ description: descriptionProp,
992
+ logo: logoProp,
993
+ submitText: submitTextProp,
994
+ footer,
995
+ forgotPassword,
996
+ showSocialButtons = true,
997
+ labels,
998
+ defaultValues
999
+ }, ref) => {
1000
+ const msg = useMessages();
1001
+ const branding = useBranding();
1002
+ const title = titleProp ?? (branding?.displayName || msg.login.title);
1003
+ const description = descriptionProp ?? msg.login.description;
1004
+ const submitText = submitTextProp ?? msg.login.submit;
1005
+ const logo = logoProp !== void 0 ? logoProp : branding?.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: branding.logoUrl, alt: branding.displayName ?? "", className: "h-10 w-auto" }) : null;
1006
+ const schema = react.useMemo(
1007
+ () => schemaProp ?? createLoginSchema(msg.validation),
1008
+ [schemaProp, msg.validation]
1009
+ );
1010
+ let ctxLogin;
1011
+ let ctxError = null;
1012
+ let ctxLoading = false;
1013
+ try {
1014
+ const ctx = useAzirid();
1015
+ ctxLogin = ctx.login;
1016
+ ctxError = ctx.error;
1017
+ ctxLoading = ctx.isLoginPending;
1018
+ } catch {
1019
+ }
1020
+ const {
1021
+ register,
1022
+ handleSubmit,
1023
+ formState: { errors, isSubmitting }
1024
+ } = reactHookForm.useForm({
1025
+ resolver: zod$1.zodResolver(schema),
1026
+ defaultValues: { email: "", password: "", ...defaultValues }
1027
+ });
1028
+ const onSubmit = react.useCallback(
1029
+ async (values) => {
1030
+ if (onSubmitProp) {
1031
+ await onSubmitProp(values);
1032
+ } else if (ctxLogin) {
1033
+ ctxLogin(values);
1034
+ }
1035
+ },
1036
+ [onSubmitProp, ctxLogin]
1037
+ );
1038
+ const loading = externalLoading ?? ctxLoading ?? isSubmitting;
1039
+ const error = externalError ?? ctxError;
1040
+ const wrapperStyle = react.useMemo(() => {
1041
+ if (!branding?.primaryColor) return style ?? {};
1042
+ return {
1043
+ ...style,
1044
+ "--aa-primary": branding.primaryColor,
1045
+ "--aa-primary-foreground": "#fff"
1046
+ };
1047
+ }, [style, branding?.primaryColor]);
1048
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-azirid": true, className: cn("flex flex-col gap-6", className), style: wrapperStyle, children: [
1049
+ logo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 self-center font-medium", children: logo }),
1050
+ /* @__PURE__ */ jsxRuntime.jsxs(Card, { children: [
1051
+ /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "text-center", children: [
1052
+ title && /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl", children: title }),
1053
+ description && /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: description })
1054
+ ] }),
1055
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsx("form", { ref, onSubmit: handleSubmit(onSubmit), noValidate: true, children: /* @__PURE__ */ jsxRuntime.jsxs(FieldGroup, { children: [
1056
+ error && /* @__PURE__ */ jsxRuntime.jsx(
1057
+ "div",
1058
+ {
1059
+ role: "alert",
1060
+ className: "border-destructive/50 bg-destructive/10 text-destructive rounded-md border px-4 py-3 text-sm",
1061
+ children: error
1062
+ }
1063
+ ),
1064
+ showSocialButtons && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1065
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1066
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", type: "button", className: "w-full", children: [
1067
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
1068
+ "path",
1069
+ {
1070
+ d: "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701",
1071
+ fill: "currentColor"
1072
+ }
1073
+ ) }),
1074
+ msg.social.apple
1075
+ ] }),
1076
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", type: "button", className: "w-full", children: [
1077
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
1078
+ "path",
1079
+ {
1080
+ d: "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
1081
+ fill: "currentColor"
1082
+ }
1083
+ ) }),
1084
+ msg.social.google
1085
+ ] })
1086
+ ] }),
1087
+ /* @__PURE__ */ jsxRuntime.jsx(FieldSeparator, { children: msg.social.separator })
1088
+ ] }),
1089
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1090
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { htmlFor: "aa-login-email", children: labels?.email ?? msg.login.emailLabel }),
1091
+ /* @__PURE__ */ jsxRuntime.jsx(
1092
+ Input,
1093
+ {
1094
+ id: "aa-login-email",
1095
+ type: "email",
1096
+ autoComplete: "email",
1097
+ placeholder: labels?.emailPlaceholder ?? msg.login.emailPlaceholder,
1098
+ disabled: loading,
1099
+ "aria-invalid": !!errors.email,
1100
+ "aria-describedby": errors.email ? "aa-login-email-err" : void 0,
1101
+ ...register("email")
1102
+ }
1103
+ ),
1104
+ errors.email && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "aa-login-email-err", className: "text-destructive text-xs", children: errors.email.message })
1105
+ ] }),
1106
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1107
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
1108
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { htmlFor: "aa-login-password", children: labels?.password ?? msg.login.passwordLabel }),
1109
+ forgotPassword && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-sm underline-offset-4 hover:underline", children: forgotPassword })
1110
+ ] }),
1111
+ /* @__PURE__ */ jsxRuntime.jsx(
1112
+ Input,
1113
+ {
1114
+ id: "aa-login-password",
1115
+ type: "password",
1116
+ autoComplete: "current-password",
1117
+ placeholder: labels?.passwordPlaceholder ?? msg.login.passwordPlaceholder,
1118
+ disabled: loading,
1119
+ "aria-invalid": !!errors.password,
1120
+ "aria-describedby": errors.password ? "aa-login-pass-err" : void 0,
1121
+ ...register("password")
1122
+ }
1123
+ ),
1124
+ errors.password && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "aa-login-pass-err", className: "text-destructive text-xs", children: errors.password.message })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1127
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "submit", disabled: loading, className: "w-full", children: [
1128
+ loading && /* @__PURE__ */ jsxRuntime.jsxs(
1129
+ "svg",
1130
+ {
1131
+ className: "mr-2 h-4 w-4 animate-spin",
1132
+ xmlns: "http://www.w3.org/2000/svg",
1133
+ fill: "none",
1134
+ viewBox: "0 0 24 24",
1135
+ "aria-hidden": "true",
1136
+ children: [
1137
+ /* @__PURE__ */ jsxRuntime.jsx(
1138
+ "circle",
1139
+ {
1140
+ className: "opacity-25",
1141
+ cx: "12",
1142
+ cy: "12",
1143
+ r: "10",
1144
+ stroke: "currentColor",
1145
+ strokeWidth: "4"
1146
+ }
1147
+ ),
1148
+ /* @__PURE__ */ jsxRuntime.jsx(
1149
+ "path",
1150
+ {
1151
+ className: "opacity-75",
1152
+ fill: "currentColor",
1153
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
1154
+ }
1155
+ )
1156
+ ]
1157
+ }
1158
+ ),
1159
+ submitText
1160
+ ] }),
1161
+ footer && /* @__PURE__ */ jsxRuntime.jsx(FieldDescription, { className: "text-center", children: footer })
1162
+ ] })
1163
+ ] }) }) })
1164
+ ] })
1165
+ ] });
1166
+ }
1167
+ );
1168
+ LoginForm.displayName = "LoginForm";
1169
+ var SignupForm = react.forwardRef(
1170
+ ({
1171
+ onSubmit: onSubmitProp,
1172
+ schema: schemaProp,
1173
+ isLoading: externalLoading,
1174
+ error: externalError,
1175
+ className,
1176
+ style,
1177
+ title: titleProp,
1178
+ description: descriptionProp,
1179
+ logo: logoProp,
1180
+ submitText: submitTextProp,
1181
+ footer,
1182
+ showSocialButtons = true,
1183
+ labels
1184
+ }, ref) => {
1185
+ const msg = useMessages();
1186
+ const branding = useBranding();
1187
+ const title = titleProp ?? (branding?.displayName || msg.signup.title);
1188
+ const description = descriptionProp ?? msg.signup.description;
1189
+ const submitText = submitTextProp ?? msg.signup.submit;
1190
+ const logo = logoProp !== void 0 ? logoProp : branding?.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: branding.logoUrl, alt: branding.displayName ?? "", className: "h-10 w-auto" }) : null;
1191
+ const schema = react.useMemo(
1192
+ () => schemaProp ?? createSignupSchema(msg.validation),
1193
+ [schemaProp, msg.validation]
1194
+ );
1195
+ let ctxSignup;
1196
+ let ctxError = null;
1197
+ let ctxLoading = false;
1198
+ try {
1199
+ const ctx = useAzirid();
1200
+ ctxSignup = ctx.signup;
1201
+ ctxError = ctx.error;
1202
+ ctxLoading = ctx.isSignupPending;
1203
+ } catch {
1204
+ }
1205
+ const {
1206
+ register,
1207
+ handleSubmit,
1208
+ formState: { errors, isSubmitting }
1209
+ } = reactHookForm.useForm({
1210
+ resolver: zod$1.zodResolver(schema),
1211
+ defaultValues: { email: "", password: "" }
1212
+ });
1213
+ const onSubmit = react.useCallback(
1214
+ async (values) => {
1215
+ if (onSubmitProp) {
1216
+ await onSubmitProp(values);
1217
+ } else if (ctxSignup) {
1218
+ ctxSignup(values);
1219
+ }
1220
+ },
1221
+ [onSubmitProp, ctxSignup]
1222
+ );
1223
+ const loading = externalLoading ?? ctxLoading ?? isSubmitting;
1224
+ const error = externalError ?? ctxError;
1225
+ const wrapperStyle = react.useMemo(() => {
1226
+ if (!branding?.primaryColor) return style ?? {};
1227
+ return {
1228
+ ...style,
1229
+ "--aa-primary": branding.primaryColor,
1230
+ "--aa-primary-foreground": "#fff"
1231
+ };
1232
+ }, [style, branding?.primaryColor]);
1233
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-azirid": true, className: cn("flex flex-col gap-6", className), style: wrapperStyle, children: [
1234
+ logo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 self-center font-medium", children: logo }),
1235
+ /* @__PURE__ */ jsxRuntime.jsxs(Card, { children: [
1236
+ /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "text-center", children: [
1237
+ title && /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl", children: title }),
1238
+ description && /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: description })
1239
+ ] }),
1240
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsx("form", { ref, onSubmit: handleSubmit(onSubmit), noValidate: true, children: /* @__PURE__ */ jsxRuntime.jsxs(FieldGroup, { children: [
1241
+ error && /* @__PURE__ */ jsxRuntime.jsx(
1242
+ "div",
1243
+ {
1244
+ role: "alert",
1245
+ className: "border-destructive/50 bg-destructive/10 text-destructive rounded-md border px-4 py-3 text-sm",
1246
+ children: error
1247
+ }
1248
+ ),
1249
+ showSocialButtons && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1250
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1251
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", type: "button", className: "w-full", children: [
1252
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
1253
+ "path",
1254
+ {
1255
+ d: "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701",
1256
+ fill: "currentColor"
1257
+ }
1258
+ ) }),
1259
+ msg.social.apple
1260
+ ] }),
1261
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", type: "button", className: "w-full", children: [
1262
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
1263
+ "path",
1264
+ {
1265
+ d: "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
1266
+ fill: "currentColor"
1267
+ }
1268
+ ) }),
1269
+ msg.social.google
1270
+ ] })
1271
+ ] }),
1272
+ /* @__PURE__ */ jsxRuntime.jsx(FieldSeparator, { children: msg.social.separator })
1273
+ ] }),
1274
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1275
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { htmlFor: "aa-signup-email", children: labels?.email ?? msg.signup.emailLabel }),
1276
+ /* @__PURE__ */ jsxRuntime.jsx(
1277
+ Input,
1278
+ {
1279
+ id: "aa-signup-email",
1280
+ type: "email",
1281
+ autoComplete: "email",
1282
+ placeholder: labels?.emailPlaceholder ?? msg.signup.emailPlaceholder,
1283
+ disabled: loading,
1284
+ "aria-invalid": !!errors.email,
1285
+ "aria-describedby": errors.email ? "aa-signup-email-err" : void 0,
1286
+ ...register("email")
1287
+ }
1288
+ ),
1289
+ errors.email && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "aa-signup-email-err", className: "text-destructive text-xs", children: errors.email.message })
1290
+ ] }),
1291
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1292
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { htmlFor: "aa-signup-password", children: labels?.password ?? msg.signup.passwordLabel }),
1293
+ /* @__PURE__ */ jsxRuntime.jsx(
1294
+ Input,
1295
+ {
1296
+ id: "aa-signup-password",
1297
+ type: "password",
1298
+ autoComplete: "new-password",
1299
+ placeholder: labels?.passwordPlaceholder ?? msg.signup.passwordPlaceholder,
1300
+ disabled: loading,
1301
+ "aria-invalid": !!errors.password,
1302
+ "aria-describedby": errors.password ? "aa-signup-pass-err" : void 0,
1303
+ ...register("password")
1304
+ }
1305
+ ),
1306
+ errors.password && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "aa-signup-pass-err", className: "text-destructive text-xs", children: errors.password.message })
1307
+ ] }),
1308
+ /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
1309
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "submit", disabled: loading, className: "w-full", children: [
1310
+ loading && /* @__PURE__ */ jsxRuntime.jsxs(
1311
+ "svg",
1312
+ {
1313
+ className: "mr-2 h-4 w-4 animate-spin",
1314
+ xmlns: "http://www.w3.org/2000/svg",
1315
+ fill: "none",
1316
+ viewBox: "0 0 24 24",
1317
+ "aria-hidden": "true",
1318
+ children: [
1319
+ /* @__PURE__ */ jsxRuntime.jsx(
1320
+ "circle",
1321
+ {
1322
+ className: "opacity-25",
1323
+ cx: "12",
1324
+ cy: "12",
1325
+ r: "10",
1326
+ stroke: "currentColor",
1327
+ strokeWidth: "4"
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsxRuntime.jsx(
1331
+ "path",
1332
+ {
1333
+ className: "opacity-75",
1334
+ fill: "currentColor",
1335
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
1336
+ }
1337
+ )
1338
+ ]
1339
+ }
1340
+ ),
1341
+ submitText
1342
+ ] }),
1343
+ footer && /* @__PURE__ */ jsxRuntime.jsx(FieldDescription, { className: "text-center", children: footer })
1344
+ ] })
1345
+ ] }) }) })
1346
+ ] })
1347
+ ] });
1348
+ }
1349
+ );
1350
+ SignupForm.displayName = "SignupForm";
1351
+ function useReferral() {
1352
+ const client = useAccessClient();
1353
+ const query = reactQuery.useQuery({
1354
+ queryKey: ["azirid-access", "referral", "me"],
1355
+ queryFn: () => client.get(client.paths.referralMe),
1356
+ enabled: !!client.getAccessToken()
1357
+ });
1358
+ const copyToClipboard = react.useCallback(async () => {
1359
+ if (query.data?.referralUrl) {
1360
+ await navigator.clipboard.writeText(query.data.referralUrl);
1361
+ return true;
1362
+ }
1363
+ return false;
1364
+ }, [query.data?.referralUrl]);
1365
+ return react.useMemo(
1366
+ () => ({ ...query, copyToClipboard }),
1367
+ [query, copyToClipboard]
1368
+ );
1369
+ }
1370
+ var styles = {
1371
+ card: {
1372
+ border: "1px solid #e5e7eb",
1373
+ borderRadius: "12px",
1374
+ padding: "24px",
1375
+ backgroundColor: "#ffffff",
1376
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
1377
+ },
1378
+ title: {
1379
+ margin: "0 0 4px 0",
1380
+ fontSize: "18px",
1381
+ fontWeight: 600,
1382
+ color: "#111827"
1383
+ },
1384
+ description: {
1385
+ margin: "0 0 16px 0",
1386
+ fontSize: "14px",
1387
+ color: "#6b7280"
1388
+ },
1389
+ codeContainer: {
1390
+ display: "flex",
1391
+ alignItems: "center",
1392
+ gap: "8px",
1393
+ marginBottom: "16px"
1394
+ },
1395
+ codeInput: {
1396
+ flex: 1,
1397
+ padding: "10px 12px",
1398
+ border: "1px solid #d1d5db",
1399
+ borderRadius: "8px",
1400
+ backgroundColor: "#f9fafb",
1401
+ fontSize: "14px",
1402
+ fontFamily: "monospace",
1403
+ color: "#374151",
1404
+ outline: "none"
1405
+ },
1406
+ copyButton: {
1407
+ padding: "10px 16px",
1408
+ border: "1px solid #d1d5db",
1409
+ borderRadius: "8px",
1410
+ backgroundColor: "#ffffff",
1411
+ fontSize: "14px",
1412
+ fontWeight: 500,
1413
+ color: "#374151",
1414
+ cursor: "pointer",
1415
+ whiteSpace: "nowrap",
1416
+ transition: "background-color 0.15s"
1417
+ },
1418
+ copyButtonCopied: {
1419
+ backgroundColor: "#ecfdf5",
1420
+ borderColor: "#a7f3d0",
1421
+ color: "#065f46"
1422
+ },
1423
+ statsRow: {
1424
+ display: "flex",
1425
+ gap: "24px"
1426
+ },
1427
+ stat: {
1428
+ display: "flex",
1429
+ flexDirection: "column",
1430
+ gap: "2px"
1431
+ },
1432
+ statValue: {
1433
+ fontSize: "20px",
1434
+ fontWeight: 600,
1435
+ color: "#111827"
1436
+ },
1437
+ statLabel: {
1438
+ fontSize: "12px",
1439
+ color: "#6b7280"
1440
+ },
1441
+ skeleton: {
1442
+ backgroundColor: "#f3f4f6",
1443
+ borderRadius: "8px",
1444
+ animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite"
1445
+ },
1446
+ emptyMessage: {
1447
+ fontSize: "14px",
1448
+ color: "#9ca3af",
1449
+ textAlign: "center",
1450
+ padding: "12px 0"
1451
+ }
1452
+ };
1453
+ function ReferralCard({
1454
+ className,
1455
+ style,
1456
+ title = "Refer a Friend",
1457
+ description = "Share your referral link and earn rewards for every friend who signs up."
1458
+ }) {
1459
+ const { data, isLoading } = useReferral();
1460
+ const [copied, setCopied] = react.useState(false);
1461
+ const handleCopy = react.useCallback(async () => {
1462
+ if (!data?.referralUrl) return;
1463
+ try {
1464
+ await navigator.clipboard.writeText(data.referralUrl);
1465
+ setCopied(true);
1466
+ setTimeout(() => setCopied(false), 2e3);
1467
+ } catch {
1468
+ }
1469
+ }, [data?.referralUrl]);
1470
+ if (isLoading) {
1471
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles.card, ...style }, children: [
1472
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "20px", width: "140px", marginBottom: "8px" } }),
1473
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "14px", width: "260px", marginBottom: "16px" } }),
1474
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "42px", width: "100%", marginBottom: "16px" } }),
1475
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "24px" }, children: [
1476
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "40px", width: "80px" } }),
1477
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "40px", width: "80px" } }),
1478
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles.skeleton, height: "40px", width: "80px" } })
1479
+ ] })
1480
+ ] });
1481
+ }
1482
+ if (!data?.referralCode) {
1483
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles.card, ...style }, children: [
1484
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles.title, children: title }),
1485
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.emptyMessage, children: "Referral program is not available at this time." })
1486
+ ] });
1487
+ }
1488
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles.card, ...style }, children: [
1489
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles.title, children: title }),
1490
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.description, children: description }),
1491
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.codeContainer, children: [
1492
+ /* @__PURE__ */ jsxRuntime.jsx(
1493
+ "input",
1494
+ {
1495
+ type: "text",
1496
+ readOnly: true,
1497
+ value: data.referralUrl,
1498
+ style: styles.codeInput,
1499
+ onClick: (e) => e.target.select()
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ jsxRuntime.jsx(
1503
+ "button",
1504
+ {
1505
+ type: "button",
1506
+ onClick: handleCopy,
1507
+ style: {
1508
+ ...styles.copyButton,
1509
+ ...copied ? styles.copyButtonCopied : {}
1510
+ },
1511
+ children: copied ? "Copied!" : "Copy"
1512
+ }
1513
+ )
1514
+ ] }),
1515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.statsRow, children: [
1516
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.stat, children: [
1517
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statValue, children: data.totalReferred }),
1518
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statLabel, children: "Total Referred" })
1519
+ ] }),
1520
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.stat, children: [
1521
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statValue, children: data.completedReferrals }),
1522
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statLabel, children: "Completed" })
1523
+ ] }),
1524
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.stat, children: [
1525
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statValue, children: data.pendingReferrals }),
1526
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.statLabel, children: "Pending" })
1527
+ ] })
1528
+ ] })
1529
+ ] });
1530
+ }
1531
+ ReferralCard.displayName = "ReferralCard";
1532
+ function useReferralStats() {
1533
+ const client = useAccessClient();
1534
+ return reactQuery.useQuery({
1535
+ queryKey: ["azirid-access", "referral", "stats"],
1536
+ queryFn: () => client.get(client.paths.referralStats),
1537
+ enabled: !!client.getAccessToken()
1538
+ });
1539
+ }
1540
+ var statusColors = {
1541
+ PENDING: { bg: "#fef3c7", color: "#92400e" },
1542
+ COMPLETED: { bg: "#d1fae5", color: "#065f46" },
1543
+ EXPIRED: { bg: "#fee2e2", color: "#991b1b" }
1544
+ };
1545
+ var rewardStatusColors = {
1546
+ PENDING: { bg: "#fef3c7", color: "#92400e" },
1547
+ GRANTED: { bg: "#d1fae5", color: "#065f46" },
1548
+ EXPIRED: { bg: "#fee2e2", color: "#991b1b" },
1549
+ FAILED: { bg: "#fee2e2", color: "#991b1b" }
1550
+ };
1551
+ var styles2 = {
1552
+ container: {
1553
+ border: "1px solid #e5e7eb",
1554
+ borderRadius: "12px",
1555
+ backgroundColor: "#ffffff",
1556
+ overflow: "hidden",
1557
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
1558
+ },
1559
+ header: {
1560
+ padding: "16px 24px",
1561
+ borderBottom: "1px solid #e5e7eb"
1562
+ },
1563
+ title: {
1564
+ margin: 0,
1565
+ fontSize: "16px",
1566
+ fontWeight: 600,
1567
+ color: "#111827"
1568
+ },
1569
+ summaryRow: {
1570
+ display: "flex",
1571
+ gap: "24px",
1572
+ padding: "12px 24px",
1573
+ backgroundColor: "#f9fafb",
1574
+ borderBottom: "1px solid #e5e7eb"
1575
+ },
1576
+ summaryItem: {
1577
+ display: "flex",
1578
+ alignItems: "center",
1579
+ gap: "6px",
1580
+ fontSize: "13px",
1581
+ color: "#6b7280"
1582
+ },
1583
+ summaryValue: {
1584
+ fontWeight: 600,
1585
+ color: "#111827"
1586
+ },
1587
+ table: {
1588
+ width: "100%",
1589
+ borderCollapse: "collapse",
1590
+ fontSize: "14px"
1591
+ },
1592
+ th: {
1593
+ padding: "12px 24px",
1594
+ textAlign: "left",
1595
+ fontSize: "12px",
1596
+ fontWeight: 500,
1597
+ color: "#6b7280",
1598
+ textTransform: "uppercase",
1599
+ letterSpacing: "0.05em",
1600
+ borderBottom: "1px solid #e5e7eb",
1601
+ backgroundColor: "#f9fafb"
1602
+ },
1603
+ td: {
1604
+ padding: "12px 24px",
1605
+ borderBottom: "1px solid #f3f4f6",
1606
+ color: "#374151"
1607
+ },
1608
+ badge: (bg, color) => ({
1609
+ display: "inline-block",
1610
+ padding: "2px 8px",
1611
+ borderRadius: "9999px",
1612
+ fontSize: "12px",
1613
+ fontWeight: 500,
1614
+ backgroundColor: bg,
1615
+ color
1616
+ }),
1617
+ skeleton: {
1618
+ backgroundColor: "#f3f4f6",
1619
+ borderRadius: "4px",
1620
+ height: "14px"
1621
+ },
1622
+ emptyRow: {
1623
+ padding: "24px",
1624
+ textAlign: "center",
1625
+ color: "#9ca3af",
1626
+ fontSize: "14px"
1627
+ }
1628
+ };
1629
+ function formatDate(dateStr) {
1630
+ try {
1631
+ return new Date(dateStr).toLocaleDateString(void 0, {
1632
+ year: "numeric",
1633
+ month: "short",
1634
+ day: "numeric"
1635
+ });
1636
+ } catch {
1637
+ return dateStr;
1638
+ }
1639
+ }
1640
+ function ReferralStats({ className, style }) {
1641
+ const { data, isLoading } = useReferralStats();
1642
+ if (isLoading) {
1643
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles2.container, ...style }, children: [
1644
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles2.header, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles2.skeleton, width: "140px", height: "18px" } }) }),
1645
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px" }, children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
1646
+ "div",
1647
+ {
1648
+ style: { ...styles2.skeleton, width: "100%", height: "16px", marginBottom: "16px" }
1649
+ },
1650
+ i
1651
+ )) })
1652
+ ] });
1653
+ }
1654
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles2.container, ...style }, children: [
1655
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles2.header, children: /* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles2.title, children: "Referral History" }) }),
1656
+ data && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles2.summaryRow, children: [
1657
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles2.summaryItem, children: [
1658
+ "Total: ",
1659
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles2.summaryValue, children: data.totalReferred })
1660
+ ] }),
1661
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles2.summaryItem, children: [
1662
+ "Completed: ",
1663
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles2.summaryValue, children: data.completedReferrals })
1664
+ ] }),
1665
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles2.summaryItem, children: [
1666
+ "Pending: ",
1667
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles2.summaryValue, children: data.pendingReferrals })
1668
+ ] }),
1669
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles2.summaryItem, children: [
1670
+ "Rewards: ",
1671
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles2.summaryValue, children: data.totalRewards })
1672
+ ] })
1673
+ ] }),
1674
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { style: styles2.table, children: [
1675
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1676
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles2.th, children: "Email" }),
1677
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles2.th, children: "Status" }),
1678
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles2.th, children: "Reward" }),
1679
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles2.th, children: "Date" })
1680
+ ] }) }),
1681
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
1682
+ (!data?.referrals || data.referrals.length === 0) && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 4, style: styles2.emptyRow, children: "No referrals yet." }) }),
1683
+ data?.referrals.map((item) => {
1684
+ const sc = statusColors[item.status];
1685
+ const rc = rewardStatusColors[item.rewardStatus];
1686
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1687
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles2.td, children: item.referredEmail }),
1688
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles2.td, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles2.badge(sc.bg, sc.color), children: item.status }) }),
1689
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles2.td, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles2.badge(rc.bg, rc.color), children: [
1690
+ item.rewardStatus,
1691
+ item.rewardAmount != null && ` ($${item.rewardAmount})`
1692
+ ] }) }),
1693
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles2.td, children: formatDate(item.createdAt) })
1694
+ ] }, item.id);
1695
+ })
1696
+ ] })
1697
+ ] })
1698
+ ] });
1699
+ }
1700
+ ReferralStats.displayName = "ReferralStats";
1701
+ function usePlans() {
1702
+ const client = useAccessClient();
1703
+ return reactQuery.useQuery({
1704
+ queryKey: ["azirid-access", "billing", "plans"],
1705
+ queryFn: () => client.get(client.paths.plans)
1706
+ });
1707
+ }
1708
+ function useSubscription() {
1709
+ const client = useAccessClient();
1710
+ return reactQuery.useQuery({
1711
+ queryKey: ["azirid-access", "billing", "subscription"],
1712
+ queryFn: () => client.get(client.paths.subscription),
1713
+ enabled: !!client.getAccessToken()
1714
+ });
1715
+ }
1716
+ function useCheckout(options) {
1717
+ const client = useAccessClient();
1718
+ const mutation = reactQuery.useMutation({
1719
+ mutationFn: (params) => client.post(client.paths.checkout, params),
1720
+ onSuccess: (data) => {
1721
+ if (options?.redirectOnSuccess !== false && data.url && data.provider !== "MANUAL_TRANSFER" && data.provider !== "PAYPHONE") {
1722
+ window.location.href = data.url;
1723
+ }
1724
+ options?.onSuccess?.(data);
1725
+ },
1726
+ onError: options?.onError
1727
+ });
1728
+ const checkout = react.useCallback(
1729
+ (params) => {
1730
+ mutation.mutate(params);
1731
+ },
1732
+ [mutation]
1733
+ );
1734
+ return react.useMemo(() => ({ ...mutation, checkout }), [mutation, checkout]);
1735
+ }
1736
+ function usePaymentProviders() {
1737
+ const client = useAccessClient();
1738
+ return reactQuery.useQuery({
1739
+ queryKey: ["azirid-access", "billing", "providers"],
1740
+ queryFn: () => client.get(client.paths.providers)
1741
+ });
1742
+ }
1743
+
1744
+ // src/utils/payphone-loader.ts
1745
+ var PAYPHONE_CSS_URL = "https://cdn.payphonetodoesposible.com/box/v1.1/payphone-payment-box.css";
1746
+ var PAYPHONE_JS_URL = "https://cdn.payphonetodoesposible.com/box/v1.1/payphone-payment-box.js";
1747
+ var loadPromise = null;
1748
+ function loadCss(href) {
1749
+ if (document.querySelector(`link[href="${href}"]`)) return;
1750
+ const link = document.createElement("link");
1751
+ link.rel = "stylesheet";
1752
+ link.href = href;
1753
+ document.head.appendChild(link);
1754
+ }
1755
+ function loadScript(src) {
1756
+ return new Promise((resolve, reject) => {
1757
+ if (document.querySelector(`script[src="${src}"]`)) {
1758
+ resolve();
1759
+ return;
1760
+ }
1761
+ const script = document.createElement("script");
1762
+ script.src = src;
1763
+ script.onload = () => resolve();
1764
+ script.onerror = () => reject(new Error(`Failed to load Payphone SDK: ${src}`));
1765
+ document.head.appendChild(script);
1766
+ });
1767
+ }
1768
+ function loadPayphoneSdk() {
1769
+ if (loadPromise) return loadPromise;
1770
+ loadPromise = (async () => {
1771
+ loadCss(PAYPHONE_CSS_URL);
1772
+ await loadScript(PAYPHONE_JS_URL);
1773
+ })();
1774
+ return loadPromise;
1775
+ }
1776
+ function PayphoneModal({ config, successUrl, onClose }) {
1777
+ const [loading, setLoading] = react.useState(true);
1778
+ const [error, setError] = react.useState(null);
1779
+ const initialized = react.useRef(false);
1780
+ react.useEffect(() => {
1781
+ if (initialized.current) return;
1782
+ initialized.current = true;
1783
+ loadPayphoneSdk().then(() => {
1784
+ setLoading(false);
1785
+ requestAnimationFrame(() => {
1786
+ if (typeof window.PPaymentButtonBox === "undefined") {
1787
+ setError("Payphone SDK failed to initialize");
1788
+ return;
1789
+ }
1790
+ new window.PPaymentButtonBox({
1791
+ token: config.token,
1792
+ clientTransactionId: config.clientTransactionId,
1793
+ amount: config.amount,
1794
+ amountWithoutTax: config.amountWithoutTax,
1795
+ currency: config.currency,
1796
+ storeId: config.storeId,
1797
+ reference: config.reference,
1798
+ responseUrl: successUrl
1799
+ }).render("pp-button-azirid");
1800
+ });
1801
+ }).catch(() => {
1802
+ setLoading(false);
1803
+ setError("Failed to load Payphone payment widget");
1804
+ });
1805
+ }, [config, successUrl]);
1806
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, onClick: (e) => e.stopPropagation(), children: [
1807
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: titleStyle, children: "Payphone" }),
1808
+ loading && /* @__PURE__ */ jsxRuntime.jsx("p", { style: messageStyle, children: "Loading payment widget..." }),
1809
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...messageStyle, color: "#ef4444" }, children: error }),
1810
+ /* @__PURE__ */ jsxRuntime.jsx("div", { id: "pp-button-azirid", style: { minHeight: "80px" } }),
1811
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: warningStyle, children: "Do not close this window until the payment is complete." }),
1812
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: cancelStyle, onClick: onClose, children: "Cancel" })
1813
+ ] }) });
1814
+ }
1815
+ var overlayStyle = {
1816
+ position: "fixed",
1817
+ inset: 0,
1818
+ backgroundColor: "rgba(0,0,0,0.5)",
1819
+ display: "flex",
1820
+ alignItems: "center",
1821
+ justifyContent: "center",
1822
+ zIndex: 9999,
1823
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
1824
+ };
1825
+ var cardStyle = {
1826
+ backgroundColor: "#fff",
1827
+ borderRadius: "12px",
1828
+ padding: "24px",
1829
+ maxWidth: "480px",
1830
+ width: "90%",
1831
+ boxShadow: "0 25px 50px -12px rgba(0,0,0,0.25)"
1832
+ };
1833
+ var titleStyle = {
1834
+ fontSize: "18px",
1835
+ fontWeight: 700,
1836
+ color: "#111827",
1837
+ margin: "0 0 16px 0",
1838
+ textAlign: "center"
1839
+ };
1840
+ var messageStyle = {
1841
+ fontSize: "14px",
1842
+ color: "#6b7280",
1843
+ textAlign: "center",
1844
+ margin: "12px 0"
1845
+ };
1846
+ var warningStyle = {
1847
+ fontSize: "12px",
1848
+ color: "#d97706",
1849
+ textAlign: "center",
1850
+ margin: "16px 0 0 0"
1851
+ };
1852
+ var cancelStyle = {
1853
+ display: "block",
1854
+ width: "100%",
1855
+ marginTop: "12px",
1856
+ padding: "10px",
1857
+ border: "none",
1858
+ borderRadius: "8px",
1859
+ backgroundColor: "#f3f4f6",
1860
+ color: "#6b7280",
1861
+ fontSize: "14px",
1862
+ fontWeight: 500,
1863
+ cursor: "pointer",
1864
+ fontFamily: "inherit"
1865
+ };
1866
+ var intervalLabels = {
1867
+ MONTHLY: "/mo",
1868
+ YEARLY: "/yr",
1869
+ ONE_TIME: ""
1870
+ };
1871
+ function formatAmount(amount, currency) {
1872
+ try {
1873
+ return new Intl.NumberFormat(void 0, {
1874
+ style: "currency",
1875
+ currency,
1876
+ minimumFractionDigits: 0,
1877
+ maximumFractionDigits: 2
1878
+ }).format(amount / 100);
1879
+ } catch {
1880
+ return `${currency} ${(amount / 100).toFixed(2)}`;
1881
+ }
1882
+ }
1883
+ var styles3 = {
1884
+ grid: (columns) => ({
1885
+ display: "grid",
1886
+ gridTemplateColumns: `repeat(${columns}, 1fr)`,
1887
+ gap: "24px",
1888
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
1889
+ }),
1890
+ card: (isCurrentPlan) => ({
1891
+ border: isCurrentPlan ? "2px solid #6366f1" : "1px solid #e5e7eb",
1892
+ borderRadius: "12px",
1893
+ padding: "24px",
1894
+ backgroundColor: "#ffffff",
1895
+ display: "flex",
1896
+ flexDirection: "column",
1897
+ position: "relative"
1898
+ }),
1899
+ currentBadge: {
1900
+ position: "absolute",
1901
+ top: "-12px",
1902
+ left: "50%",
1903
+ transform: "translateX(-50%)",
1904
+ backgroundColor: "#6366f1",
1905
+ color: "#ffffff",
1906
+ fontSize: "12px",
1907
+ fontWeight: 600,
1908
+ padding: "2px 12px",
1909
+ borderRadius: "9999px",
1910
+ whiteSpace: "nowrap"
1911
+ },
1912
+ planName: {
1913
+ margin: "0 0 4px 0",
1914
+ fontSize: "20px",
1915
+ fontWeight: 600,
1916
+ color: "#111827"
1917
+ },
1918
+ planDescription: {
1919
+ margin: "0 0 16px 0",
1920
+ fontSize: "14px",
1921
+ color: "#6b7280",
1922
+ lineHeight: "1.5"
1923
+ },
1924
+ priceRow: {
1925
+ display: "flex",
1926
+ alignItems: "baseline",
1927
+ gap: "4px",
1928
+ marginBottom: "20px"
1929
+ },
1930
+ priceAmount: {
1931
+ fontSize: "36px",
1932
+ fontWeight: 700,
1933
+ color: "#111827",
1934
+ lineHeight: 1
1935
+ },
1936
+ priceInterval: {
1937
+ fontSize: "16px",
1938
+ color: "#6b7280"
1939
+ },
1940
+ featuresList: {
1941
+ listStyle: "none",
1942
+ padding: 0,
1943
+ margin: "0 0 24px 0",
1944
+ flex: 1
1945
+ },
1946
+ featureItem: {
1947
+ display: "flex",
1948
+ alignItems: "center",
1949
+ gap: "8px",
1950
+ padding: "6px 0",
1951
+ fontSize: "14px",
1952
+ color: "#374151"
1953
+ },
1954
+ checkmark: {
1955
+ color: "#10b981",
1956
+ fontSize: "16px",
1957
+ fontWeight: 700,
1958
+ flexShrink: 0
1959
+ },
1960
+ selectButton: (isCurrentPlan) => ({
1961
+ width: "100%",
1962
+ padding: "12px 24px",
1963
+ borderRadius: "8px",
1964
+ border: isCurrentPlan ? "1px solid #d1d5db" : "none",
1965
+ backgroundColor: isCurrentPlan ? "#ffffff" : "#111827",
1966
+ color: isCurrentPlan ? "#6b7280" : "#ffffff",
1967
+ fontSize: "14px",
1968
+ fontWeight: 600,
1969
+ cursor: isCurrentPlan ? "default" : "pointer",
1970
+ transition: "background-color 0.15s"
1971
+ }),
1972
+ skeleton: {
1973
+ backgroundColor: "#f3f4f6",
1974
+ borderRadius: "12px"
1975
+ },
1976
+ skeletonCard: {
1977
+ border: "1px solid #e5e7eb",
1978
+ borderRadius: "12px",
1979
+ padding: "24px",
1980
+ backgroundColor: "#ffffff"
1981
+ },
1982
+ skeletonLine: {
1983
+ backgroundColor: "#f3f4f6",
1984
+ borderRadius: "4px",
1985
+ marginBottom: "12px"
1986
+ },
1987
+ overlay: {
1988
+ position: "fixed",
1989
+ top: 0,
1990
+ left: 0,
1991
+ right: 0,
1992
+ bottom: 0,
1993
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
1994
+ display: "flex",
1995
+ alignItems: "center",
1996
+ justifyContent: "center",
1997
+ zIndex: 9999
1998
+ },
1999
+ modal: {
2000
+ backgroundColor: "#ffffff",
2001
+ borderRadius: "16px",
2002
+ padding: "32px",
2003
+ maxWidth: "480px",
2004
+ width: "90%",
2005
+ maxHeight: "80vh",
2006
+ overflow: "auto"
2007
+ },
2008
+ modalTitle: {
2009
+ margin: "0 0 8px 0",
2010
+ fontSize: "20px",
2011
+ fontWeight: 600,
2012
+ color: "#111827"
2013
+ },
2014
+ modalSubtitle: {
2015
+ margin: "0 0 24px 0",
2016
+ fontSize: "14px",
2017
+ color: "#6b7280"
2018
+ },
2019
+ bankDetailRow: {
2020
+ display: "flex",
2021
+ justifyContent: "space-between",
2022
+ padding: "8px 0",
2023
+ borderBottom: "1px solid #f3f4f6",
2024
+ fontSize: "14px"
2025
+ },
2026
+ bankDetailLabel: {
2027
+ color: "#6b7280",
2028
+ fontWeight: 500
2029
+ },
2030
+ bankDetailValue: {
2031
+ color: "#111827",
2032
+ fontWeight: 600,
2033
+ fontFamily: "monospace"
2034
+ },
2035
+ instructions: {
2036
+ margin: "16px 0",
2037
+ padding: "12px 16px",
2038
+ backgroundColor: "#f9fafb",
2039
+ borderRadius: "8px",
2040
+ fontSize: "14px",
2041
+ color: "#374151",
2042
+ lineHeight: "1.5"
2043
+ },
2044
+ closeButton: {
2045
+ width: "100%",
2046
+ padding: "12px 24px",
2047
+ borderRadius: "8px",
2048
+ border: "1px solid #d1d5db",
2049
+ backgroundColor: "#ffffff",
2050
+ color: "#374151",
2051
+ fontSize: "14px",
2052
+ fontWeight: 600,
2053
+ cursor: "pointer",
2054
+ marginTop: "16px"
2055
+ }
2056
+ };
2057
+ var PROVIDER_LABELS = {
2058
+ STRIPE: "Credit/Debit Card",
2059
+ PAYPAL: "PayPal",
2060
+ PAYPHONE: "Payphone",
2061
+ NUVEI: "Nuvei",
2062
+ MANUAL_TRANSFER: "Bank Transfer"
2063
+ };
2064
+ var PROVIDER_ICONS = {
2065
+ STRIPE: "\u{1F4B3}",
2066
+ PAYPAL: "\u{1F17F}\uFE0F",
2067
+ PAYPHONE: "\u{1F4F1}",
2068
+ NUVEI: "\u{1F4B3}",
2069
+ MANUAL_TRANSFER: "\u{1F3E6}"
2070
+ };
2071
+ function ProviderSelectModal({
2072
+ providers,
2073
+ isPending,
2074
+ onSelect,
2075
+ onClose
2076
+ }) {
2077
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles3.overlay, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.modal, onClick: (e) => e.stopPropagation(), children: [
2078
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: styles3.modalTitle, children: "Select payment method" }),
2079
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
2080
+ "button",
2081
+ {
2082
+ type: "button",
2083
+ onClick: () => onSelect(p.provider),
2084
+ disabled: isPending,
2085
+ style: {
2086
+ display: "flex",
2087
+ alignItems: "center",
2088
+ width: "100%",
2089
+ padding: "12px 16px",
2090
+ border: "1px solid #e5e7eb",
2091
+ borderRadius: "8px",
2092
+ backgroundColor: "#fff",
2093
+ cursor: isPending ? "not-allowed" : "pointer",
2094
+ fontSize: "14px",
2095
+ fontWeight: 500,
2096
+ color: "#111827",
2097
+ fontFamily: "inherit"
2098
+ },
2099
+ children: [
2100
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "20px", marginRight: "12px" }, children: PROVIDER_ICONS[p.provider] }),
2101
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: PROVIDER_LABELS[p.provider] ?? p.provider })
2102
+ ]
2103
+ },
2104
+ p.provider
2105
+ )) }),
2106
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: styles3.closeButton, onClick: onClose, children: "Cancel" })
2107
+ ] }) });
2108
+ }
2109
+ function TransferModal({
2110
+ data,
2111
+ onClose
2112
+ }) {
2113
+ const bankDetails = data.bankDetails;
2114
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles3.overlay, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.modal, onClick: (e) => e.stopPropagation(), children: [
2115
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: styles3.modalTitle, children: "Manual Transfer" }),
2116
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles3.modalSubtitle, children: [
2117
+ "Transfer the amount below to subscribe to",
2118
+ " ",
2119
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: data.plan?.name })
2120
+ ] }),
2121
+ /* @__PURE__ */ jsxRuntime.jsxs(
2122
+ "div",
2123
+ {
2124
+ style: {
2125
+ textAlign: "center",
2126
+ padding: "16px",
2127
+ backgroundColor: "#f9fafb",
2128
+ borderRadius: "8px",
2129
+ marginBottom: "20px"
2130
+ },
2131
+ children: [
2132
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "32px", fontWeight: 700, color: "#111827" }, children: data.plan ? formatAmount(data.plan.amount, data.plan.currency) : "" }),
2133
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#6b7280" }, children: data.plan?.interval ? intervalLabels[data.plan.interval] ?? "" : "" })
2134
+ ]
2135
+ }
2136
+ ),
2137
+ bankDetails && Object.keys(bankDetails).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "16px" }, children: [
2138
+ /* @__PURE__ */ jsxRuntime.jsx(
2139
+ "div",
2140
+ {
2141
+ style: {
2142
+ fontSize: "14px",
2143
+ fontWeight: 600,
2144
+ color: "#111827",
2145
+ marginBottom: "8px"
2146
+ },
2147
+ children: "Bank Details"
2148
+ }
2149
+ ),
2150
+ Object.entries(bankDetails).filter(([, v]) => v).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.bankDetailRow, children: [
2151
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.bankDetailLabel, children: key.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()) }),
2152
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.bankDetailValue, children: value })
2153
+ ] }, key))
2154
+ ] }),
2155
+ data.transferInstructions && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles3.instructions, children: data.transferInstructions }),
2156
+ /* @__PURE__ */ jsxRuntime.jsx(
2157
+ "p",
2158
+ {
2159
+ style: {
2160
+ fontSize: "13px",
2161
+ color: "#9ca3af",
2162
+ margin: "12px 0 0 0"
2163
+ },
2164
+ children: "After completing the transfer, submit your proof of payment. Your subscription will be activated once the transfer is verified."
2165
+ }
2166
+ ),
2167
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: styles3.closeButton, onClick: onClose, children: "Close" })
2168
+ ] }) });
2169
+ }
2170
+ function PricingTable({
2171
+ className,
2172
+ style,
2173
+ successUrl,
2174
+ cancelUrl,
2175
+ columns = 3,
2176
+ onPlanSelect
2177
+ }) {
2178
+ const { data: plans, isLoading: plansLoading } = usePlans();
2179
+ const { data: subscription } = useSubscription();
2180
+ const { data: providers } = usePaymentProviders();
2181
+ const [transferData, setTransferData] = react.useState(
2182
+ null
2183
+ );
2184
+ const [payphoneData, setPayphoneData] = react.useState(null);
2185
+ const [pendingPlan, setPendingPlan] = react.useState(null);
2186
+ const [showProviderModal, setShowProviderModal] = react.useState(false);
2187
+ const { checkout, isPending: checkoutPending } = useCheckout({
2188
+ redirectOnSuccess: true,
2189
+ onSuccess: (data) => {
2190
+ setShowProviderModal(false);
2191
+ setPendingPlan(null);
2192
+ if (data.provider === "MANUAL_TRANSFER") {
2193
+ setTransferData(data);
2194
+ } else if (data.provider === "PAYPHONE" && data.widgetConfig) {
2195
+ setPayphoneData(data);
2196
+ }
2197
+ }
2198
+ });
2199
+ const doCheckout = (planId, provider) => {
2200
+ checkout({ planId, provider, successUrl, cancelUrl });
2201
+ };
2202
+ const handleSelect = (plan) => {
2203
+ if (subscription?.planId === plan.id && subscription.status === "ACTIVE")
2204
+ return;
2205
+ if (onPlanSelect) {
2206
+ onPlanSelect(plan);
2207
+ return;
2208
+ }
2209
+ if (providers && providers.length > 1) {
2210
+ setPendingPlan(plan);
2211
+ setShowProviderModal(true);
2212
+ return;
2213
+ }
2214
+ const provider = providers?.[0]?.provider;
2215
+ checkout({ planId: plan.id, provider, successUrl, cancelUrl });
2216
+ };
2217
+ if (plansLoading) {
2218
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...styles3.grid(columns), ...style }, children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.skeletonCard, children: [
2219
+ /* @__PURE__ */ jsxRuntime.jsx(
2220
+ "div",
2221
+ {
2222
+ style: {
2223
+ ...styles3.skeletonLine,
2224
+ width: "60%",
2225
+ height: "20px"
2226
+ }
2227
+ }
2228
+ ),
2229
+ /* @__PURE__ */ jsxRuntime.jsx(
2230
+ "div",
2231
+ {
2232
+ style: {
2233
+ ...styles3.skeletonLine,
2234
+ width: "80%",
2235
+ height: "14px"
2236
+ }
2237
+ }
2238
+ ),
2239
+ /* @__PURE__ */ jsxRuntime.jsx(
2240
+ "div",
2241
+ {
2242
+ style: {
2243
+ ...styles3.skeletonLine,
2244
+ width: "40%",
2245
+ height: "36px",
2246
+ marginTop: "8px"
2247
+ }
2248
+ }
2249
+ ),
2250
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "16px" }, children: [1, 2, 3].map((j) => /* @__PURE__ */ jsxRuntime.jsx(
2251
+ "div",
2252
+ {
2253
+ style: {
2254
+ ...styles3.skeletonLine,
2255
+ width: "90%",
2256
+ height: "14px"
2257
+ }
2258
+ },
2259
+ j
2260
+ )) }),
2261
+ /* @__PURE__ */ jsxRuntime.jsx(
2262
+ "div",
2263
+ {
2264
+ style: {
2265
+ ...styles3.skeletonLine,
2266
+ width: "100%",
2267
+ height: "44px",
2268
+ marginTop: "16px"
2269
+ }
2270
+ }
2271
+ )
2272
+ ] }, i)) });
2273
+ }
2274
+ const sortedPlans = plans ? [...plans].sort((a, b) => a.sortOrder - b.sortOrder) : [];
2275
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2276
+ /* @__PURE__ */ jsxRuntime.jsx(
2277
+ "div",
2278
+ {
2279
+ className,
2280
+ style: { ...styles3.grid(columns), ...style },
2281
+ children: sortedPlans.map((plan) => {
2282
+ const isCurrentPlan = subscription?.planId === plan.id && subscription.status === "ACTIVE";
2283
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.card(isCurrentPlan), children: [
2284
+ isCurrentPlan && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.currentBadge, children: "Current Plan" }),
2285
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles3.planName, children: plan.name }),
2286
+ plan.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles3.planDescription, children: plan.description }),
2287
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles3.priceRow, children: [
2288
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.priceAmount, children: formatAmount(plan.amount, plan.currency) }),
2289
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.priceInterval, children: intervalLabels[plan.interval] })
2290
+ ] }),
2291
+ plan.features && plan.features.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { style: styles3.featuresList, children: plan.features.map((feature, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: styles3.featureItem, children: [
2292
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles3.checkmark, "aria-hidden": "true", children: "\u2713" }),
2293
+ feature
2294
+ ] }, i)) }),
2295
+ /* @__PURE__ */ jsxRuntime.jsx(
2296
+ "button",
2297
+ {
2298
+ type: "button",
2299
+ onClick: () => handleSelect(plan),
2300
+ disabled: isCurrentPlan || checkoutPending,
2301
+ style: {
2302
+ ...styles3.selectButton(isCurrentPlan),
2303
+ ...checkoutPending && !isCurrentPlan ? { opacity: 0.6 } : {}
2304
+ },
2305
+ children: isCurrentPlan ? "Current Plan" : "Subscribe"
2306
+ }
2307
+ )
2308
+ ] }, plan.id);
2309
+ })
2310
+ }
2311
+ ),
2312
+ showProviderModal && pendingPlan && providers && providers.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
2313
+ ProviderSelectModal,
2314
+ {
2315
+ providers,
2316
+ isPending: checkoutPending,
2317
+ onSelect: (provider) => doCheckout(pendingPlan.id, provider),
2318
+ onClose: () => {
2319
+ setShowProviderModal(false);
2320
+ setPendingPlan(null);
2321
+ }
2322
+ }
2323
+ ),
2324
+ transferData && /* @__PURE__ */ jsxRuntime.jsx(
2325
+ TransferModal,
2326
+ {
2327
+ data: transferData,
2328
+ onClose: () => setTransferData(null)
2329
+ }
2330
+ ),
2331
+ payphoneData?.widgetConfig && /* @__PURE__ */ jsxRuntime.jsx(
2332
+ PayphoneModal,
2333
+ {
2334
+ config: payphoneData.widgetConfig,
2335
+ successUrl,
2336
+ onClose: () => setPayphoneData(null)
2337
+ }
2338
+ )
2339
+ ] });
2340
+ }
2341
+ PricingTable.displayName = "PricingTable";
2342
+ var defaultStyle = {
2343
+ padding: "12px 24px",
2344
+ borderRadius: "8px",
2345
+ border: "none",
2346
+ backgroundColor: "#111827",
2347
+ color: "#ffffff",
2348
+ fontSize: "14px",
2349
+ fontWeight: 600,
2350
+ cursor: "pointer",
2351
+ transition: "background-color 0.15s",
2352
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
2353
+ };
2354
+ function CheckoutButton({
2355
+ planId,
2356
+ successUrl,
2357
+ cancelUrl,
2358
+ className,
2359
+ style,
2360
+ children
2361
+ }) {
2362
+ const { checkout, isPending } = useCheckout({ redirectOnSuccess: true });
2363
+ return /* @__PURE__ */ jsxRuntime.jsx(
2364
+ "button",
2365
+ {
2366
+ type: "button",
2367
+ className,
2368
+ style: {
2369
+ ...defaultStyle,
2370
+ ...style,
2371
+ ...isPending ? { opacity: 0.6, cursor: "not-allowed" } : {}
2372
+ },
2373
+ disabled: isPending,
2374
+ onClick: () => checkout({ planId, successUrl, cancelUrl }),
2375
+ children: isPending ? "Loading..." : children ?? "Subscribe"
2376
+ }
2377
+ );
2378
+ }
2379
+ CheckoutButton.displayName = "CheckoutButton";
2380
+ var PROVIDER_LABELS2 = {
2381
+ STRIPE: { en: "Credit/Debit Card", es: "Tarjeta de cr\xE9dito/d\xE9bito" },
2382
+ PAYPAL: { en: "PayPal", es: "PayPal" },
2383
+ PAYPHONE: { en: "Payphone", es: "Payphone" },
2384
+ NUVEI: { en: "Nuvei", es: "Nuvei" },
2385
+ MANUAL_TRANSFER: { en: "Bank Transfer", es: "Transferencia bancaria" }
2386
+ };
2387
+ var PROVIDER_ICONS2 = {
2388
+ STRIPE: "\u{1F4B3}",
2389
+ PAYPAL: "\u{1F17F}\uFE0F",
2390
+ PAYPHONE: "\u{1F4F1}",
2391
+ NUVEI: "\u{1F4B3}",
2392
+ MANUAL_TRANSFER: "\u{1F3E6}"
2393
+ };
2394
+ function formatAmount2(amount, currency) {
2395
+ try {
2396
+ return new Intl.NumberFormat(void 0, {
2397
+ style: "currency",
2398
+ currency,
2399
+ minimumFractionDigits: 0,
2400
+ maximumFractionDigits: 2
2401
+ }).format(amount / 100);
2402
+ } catch {
2403
+ return `${currency} ${(amount / 100).toFixed(2)}`;
2404
+ }
2405
+ }
2406
+ function PayButton({
2407
+ planId,
2408
+ intentId,
2409
+ successUrl,
2410
+ cancelUrl,
2411
+ className,
2412
+ style,
2413
+ children,
2414
+ disabled,
2415
+ onSuccess,
2416
+ onError,
2417
+ onProviderSelect
2418
+ }) {
2419
+ const messages = useMessages();
2420
+ const billing = messages?.billing;
2421
+ const [showProviderModal, setShowProviderModal] = react.useState(false);
2422
+ const [showTransferModal, setShowTransferModal] = react.useState(false);
2423
+ const [transferData, setTransferData] = react.useState(null);
2424
+ const [payphoneData, setPayphoneData] = react.useState(null);
2425
+ const { data: providers, isLoading: providersLoading } = usePaymentProviders();
2426
+ const { checkout, isPending } = useCheckout({
2427
+ redirectOnSuccess: true,
2428
+ onSuccess: (data) => {
2429
+ if (data.provider === "MANUAL_TRANSFER") {
2430
+ setTransferData(data);
2431
+ setShowTransferModal(true);
2432
+ setShowProviderModal(false);
2433
+ } else if (data.provider === "PAYPHONE" && data.widgetConfig) {
2434
+ setPayphoneData(data);
2435
+ setShowProviderModal(false);
2436
+ }
2437
+ onSuccess?.(data);
2438
+ },
2439
+ onError
2440
+ });
2441
+ const handleClick = () => {
2442
+ if (!providers || providers.length === 0) return;
2443
+ if (providers.length === 1) {
2444
+ doCheckout(providers[0].provider);
2445
+ } else {
2446
+ setShowProviderModal(true);
2447
+ }
2448
+ };
2449
+ const doCheckout = (provider) => {
2450
+ onProviderSelect?.(provider);
2451
+ checkout({
2452
+ planId,
2453
+ intentId,
2454
+ provider,
2455
+ successUrl,
2456
+ cancelUrl
2457
+ });
2458
+ };
2459
+ const isDisabled = disabled || isPending || providersLoading || !planId && !intentId;
2460
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2461
+ /* @__PURE__ */ jsxRuntime.jsx(
2462
+ "button",
2463
+ {
2464
+ type: "button",
2465
+ className,
2466
+ style: {
2467
+ padding: "10px 24px",
2468
+ fontSize: "14px",
2469
+ fontWeight: 600,
2470
+ color: "#fff",
2471
+ backgroundColor: isDisabled ? "#9ca3af" : "#111827",
2472
+ border: "none",
2473
+ borderRadius: "8px",
2474
+ cursor: isDisabled ? "not-allowed" : "pointer",
2475
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2476
+ ...style
2477
+ },
2478
+ onClick: handleClick,
2479
+ disabled: isDisabled,
2480
+ children: isPending ? billing?.processing ?? "Processing..." : children ?? (billing?.pay ?? "Pay")
2481
+ }
2482
+ ),
2483
+ showProviderModal && providers && providers.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
2484
+ ProviderModal,
2485
+ {
2486
+ providers,
2487
+ isPending,
2488
+ onSelect: doCheckout,
2489
+ onClose: () => setShowProviderModal(false),
2490
+ labels: billing
2491
+ }
2492
+ ),
2493
+ showTransferModal && transferData && /* @__PURE__ */ jsxRuntime.jsx(
2494
+ TransferModal2,
2495
+ {
2496
+ data: transferData,
2497
+ onClose: () => {
2498
+ setShowTransferModal(false);
2499
+ setTransferData(null);
2500
+ },
2501
+ labels: billing
2502
+ }
2503
+ ),
2504
+ payphoneData?.widgetConfig && /* @__PURE__ */ jsxRuntime.jsx(
2505
+ PayphoneModal,
2506
+ {
2507
+ config: payphoneData.widgetConfig,
2508
+ successUrl,
2509
+ onClose: () => setPayphoneData(null)
2510
+ }
2511
+ )
2512
+ ] });
2513
+ }
2514
+ function ProviderModal({
2515
+ providers,
2516
+ isPending,
2517
+ onSelect,
2518
+ onClose,
2519
+ labels
2520
+ }) {
2521
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: modalStyles.overlay, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyles.card, onClick: (e) => e.stopPropagation(), children: [
2522
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: modalStyles.title, children: labels?.selectPaymentMethod ?? "Select payment method" }),
2523
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: providers.map((p) => {
2524
+ const label = PROVIDER_LABELS2[p.provider];
2525
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2526
+ "button",
2527
+ {
2528
+ type: "button",
2529
+ style: modalStyles.providerButton,
2530
+ onClick: () => onSelect(p.provider),
2531
+ disabled: isPending,
2532
+ children: [
2533
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "20px", marginRight: "12px" }, children: PROVIDER_ICONS2[p.provider] }),
2534
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label?.en ?? p.provider })
2535
+ ]
2536
+ },
2537
+ p.provider
2538
+ );
2539
+ }) }),
2540
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: modalStyles.cancelButton, onClick: onClose, children: labels?.cancel ?? "Cancel" })
2541
+ ] }) });
2542
+ }
2543
+ function TransferModal2({
2544
+ data,
2545
+ onClose,
2546
+ labels
2547
+ }) {
2548
+ const bankDetails = data.bankDetails;
2549
+ const plan = data.plan;
2550
+ const intent = data.intent;
2551
+ const displayAmount = plan ? formatAmount2(plan.amount, plan.currency) : intent ? formatAmount2(intent.amount * 100, intent.currency) : "";
2552
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: modalStyles.overlay, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyles.card, onClick: (e) => e.stopPropagation(), children: [
2553
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: modalStyles.title, children: labels?.bankTransfer ?? "Bank Transfer" }),
2554
+ displayAmount && /* @__PURE__ */ jsxRuntime.jsxs(
2555
+ "div",
2556
+ {
2557
+ style: {
2558
+ textAlign: "center",
2559
+ padding: "16px",
2560
+ backgroundColor: "#f9fafb",
2561
+ borderRadius: "8px",
2562
+ marginBottom: "20px"
2563
+ },
2564
+ children: [
2565
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "32px", fontWeight: 700, color: "#111827" }, children: displayAmount }),
2566
+ plan?.name && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#6b7280" }, children: plan.name }),
2567
+ intent?.description && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#6b7280" }, children: intent.description })
2568
+ ]
2569
+ }
2570
+ ),
2571
+ bankDetails && Object.keys(bankDetails).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "16px" }, children: [
2572
+ /* @__PURE__ */ jsxRuntime.jsx(
2573
+ "div",
2574
+ {
2575
+ style: {
2576
+ fontSize: "14px",
2577
+ fontWeight: 600,
2578
+ color: "#111827",
2579
+ marginBottom: "8px"
2580
+ },
2581
+ children: "Bank Details"
2582
+ }
2583
+ ),
2584
+ Object.entries(bankDetails).filter(([, v]) => v).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(
2585
+ "div",
2586
+ {
2587
+ style: {
2588
+ display: "flex",
2589
+ justifyContent: "space-between",
2590
+ padding: "6px 0",
2591
+ borderBottom: "1px solid #f3f4f6",
2592
+ fontSize: "13px"
2593
+ },
2594
+ children: [
2595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#6b7280" }, children: key.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()) }),
2596
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#111827", fontWeight: 500 }, children: value })
2597
+ ]
2598
+ },
2599
+ key
2600
+ ))
2601
+ ] }),
2602
+ data.transferInstructions && /* @__PURE__ */ jsxRuntime.jsx(
2603
+ "div",
2604
+ {
2605
+ style: {
2606
+ padding: "12px",
2607
+ backgroundColor: "#eff6ff",
2608
+ borderRadius: "6px",
2609
+ fontSize: "13px",
2610
+ color: "#1e40af",
2611
+ lineHeight: 1.5,
2612
+ marginBottom: "16px"
2613
+ },
2614
+ children: data.transferInstructions
2615
+ }
2616
+ ),
2617
+ /* @__PURE__ */ jsxRuntime.jsx(
2618
+ "p",
2619
+ {
2620
+ style: {
2621
+ fontSize: "13px",
2622
+ color: "#9ca3af",
2623
+ margin: "12px 0 0 0"
2624
+ },
2625
+ children: "After completing the transfer, submit your proof of payment. Your access will be activated once the transfer is verified."
2626
+ }
2627
+ ),
2628
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: modalStyles.cancelButton, onClick: onClose, children: "Close" })
2629
+ ] }) });
2630
+ }
2631
+ var modalStyles = {
2632
+ overlay: {
2633
+ position: "fixed",
2634
+ inset: 0,
2635
+ backgroundColor: "rgba(0,0,0,0.5)",
2636
+ display: "flex",
2637
+ alignItems: "center",
2638
+ justifyContent: "center",
2639
+ zIndex: 9999,
2640
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
2641
+ },
2642
+ card: {
2643
+ backgroundColor: "#fff",
2644
+ borderRadius: "12px",
2645
+ padding: "24px",
2646
+ maxWidth: "420px",
2647
+ width: "90%",
2648
+ boxShadow: "0 25px 50px -12px rgba(0,0,0,0.25)"
2649
+ },
2650
+ title: {
2651
+ fontSize: "18px",
2652
+ fontWeight: 700,
2653
+ color: "#111827",
2654
+ margin: "0 0 20px 0",
2655
+ textAlign: "center"
2656
+ },
2657
+ providerButton: {
2658
+ display: "flex",
2659
+ alignItems: "center",
2660
+ width: "100%",
2661
+ padding: "12px 16px",
2662
+ border: "1px solid #e5e7eb",
2663
+ borderRadius: "8px",
2664
+ backgroundColor: "#fff",
2665
+ cursor: "pointer",
2666
+ fontSize: "14px",
2667
+ fontWeight: 500,
2668
+ color: "#111827",
2669
+ transition: "background-color 0.15s",
2670
+ fontFamily: "inherit"
2671
+ },
2672
+ cancelButton: {
2673
+ display: "block",
2674
+ width: "100%",
2675
+ marginTop: "16px",
2676
+ padding: "10px",
2677
+ border: "none",
2678
+ borderRadius: "8px",
2679
+ backgroundColor: "#f3f4f6",
2680
+ color: "#6b7280",
2681
+ fontSize: "14px",
2682
+ fontWeight: 500,
2683
+ cursor: "pointer",
2684
+ fontFamily: "inherit"
2685
+ }
2686
+ };
2687
+ function usePayphoneConfirm(options) {
2688
+ const client = useAccessClient();
2689
+ return reactQuery.useMutation({
2690
+ mutationFn: (params) => client.post(client.paths.payphoneConfirm, params),
2691
+ onSuccess: options?.onSuccess,
2692
+ onError: options?.onError
2693
+ });
2694
+ }
2695
+ function PayphoneCallback({
2696
+ onSuccess,
2697
+ onError,
2698
+ className,
2699
+ style
2700
+ }) {
2701
+ const { mutate, isPending, isSuccess, isError, error, data } = usePayphoneConfirm({
2702
+ onSuccess,
2703
+ onError
2704
+ });
2705
+ const called = react.useRef(false);
2706
+ react.useEffect(() => {
2707
+ if (called.current) return;
2708
+ called.current = true;
2709
+ const params = new URLSearchParams(window.location.search);
2710
+ const id = params.get("id");
2711
+ const clientTransactionId = params.get("clientTransactionId");
2712
+ if (!id || !clientTransactionId) return;
2713
+ mutate({ id: Number(id), clientTransactionId });
2714
+ }, [mutate]);
2715
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { textAlign: "center", padding: "32px", ...style }, children: [
2716
+ isPending && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2717
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: textStyle, children: "Confirming your payment..." }),
2718
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtextStyle, children: "Please do not close this page." })
2719
+ ] }),
2720
+ isSuccess && data && /* @__PURE__ */ jsxRuntime.jsx("div", { children: data.status === "confirmed" || data.status === "already_confirmed" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2721
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...textStyle, color: "#059669" }, children: "Payment confirmed!" }),
2722
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtextStyle, children: "Your payment has been processed successfully." })
2723
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2724
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...textStyle, color: "#d97706" }, children: "Payment was cancelled" }),
2725
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtextStyle, children: "The transaction was not completed." })
2726
+ ] }) }),
2727
+ isError && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2728
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...textStyle, color: "#dc2626" }, children: "Payment confirmation failed" }),
2729
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtextStyle, children: error?.message ?? "An error occurred" })
2730
+ ] })
2731
+ ] });
2732
+ }
2733
+ var textStyle = {
2734
+ fontSize: "18px",
2735
+ fontWeight: 600,
2736
+ color: "#111827",
2737
+ margin: "0 0 8px 0"
2738
+ };
2739
+ var subtextStyle = {
2740
+ fontSize: "14px",
2741
+ color: "#6b7280",
2742
+ margin: 0
2743
+ };
2744
+ var statusConfig = {
2745
+ ACTIVE: { bg: "#d1fae5", color: "#065f46", label: "Active" },
2746
+ TRIALING: { bg: "#dbeafe", color: "#1e40af", label: "Trial" },
2747
+ PAST_DUE: { bg: "#fef3c7", color: "#92400e", label: "Past Due" },
2748
+ CANCELED: { bg: "#fee2e2", color: "#991b1b", label: "Canceled" },
2749
+ UNPAID: { bg: "#fee2e2", color: "#991b1b", label: "Unpaid" },
2750
+ INCOMPLETE: { bg: "#f3f4f6", color: "#6b7280", label: "Incomplete" }
2751
+ };
2752
+ var styles4 = {
2753
+ badge: {
2754
+ display: "inline-flex",
2755
+ alignItems: "center",
2756
+ gap: "6px",
2757
+ padding: "6px 12px",
2758
+ borderRadius: "9999px",
2759
+ fontSize: "13px",
2760
+ fontWeight: 500,
2761
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
2762
+ },
2763
+ dot: (color) => ({
2764
+ width: "6px",
2765
+ height: "6px",
2766
+ borderRadius: "50%",
2767
+ backgroundColor: color,
2768
+ flexShrink: 0
2769
+ }),
2770
+ skeleton: {
2771
+ display: "inline-block",
2772
+ width: "120px",
2773
+ height: "32px",
2774
+ borderRadius: "9999px",
2775
+ backgroundColor: "#f3f4f6"
2776
+ }
2777
+ };
2778
+ function SubscriptionBadge({ className, style }) {
2779
+ const { data: subscription, isLoading } = useSubscription();
2780
+ if (isLoading) {
2781
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className, style: { ...styles4.skeleton, ...style } });
2782
+ }
2783
+ if (!subscription) {
2784
+ return /* @__PURE__ */ jsxRuntime.jsx(
2785
+ "span",
2786
+ {
2787
+ className,
2788
+ style: {
2789
+ ...styles4.badge,
2790
+ backgroundColor: "#f3f4f6",
2791
+ color: "#6b7280",
2792
+ ...style
2793
+ },
2794
+ children: "No Plan"
2795
+ }
2796
+ );
2797
+ }
2798
+ const config = statusConfig[subscription.status];
2799
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2800
+ "span",
2801
+ {
2802
+ className,
2803
+ style: {
2804
+ ...styles4.badge,
2805
+ backgroundColor: config.bg,
2806
+ color: config.color,
2807
+ ...style
2808
+ },
2809
+ children: [
2810
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles4.dot(config.color), "aria-hidden": "true" }),
2811
+ subscription.plan.name,
2812
+ " \xB7 ",
2813
+ config.label
2814
+ ]
2815
+ }
2816
+ );
2817
+ }
2818
+ SubscriptionBadge.displayName = "SubscriptionBadge";
2819
+ function useInvoices() {
2820
+ const client = useAccessClient();
2821
+ return reactQuery.useQuery({
2822
+ queryKey: ["azirid-access", "billing", "invoices"],
2823
+ queryFn: () => client.get(client.paths.invoices),
2824
+ enabled: !!client.getAccessToken()
2825
+ });
2826
+ }
2827
+ var statusColors2 = {
2828
+ PENDING: { bg: "#fef3c7", color: "#92400e" },
2829
+ PAID: { bg: "#d1fae5", color: "#065f46" },
2830
+ FAILED: { bg: "#fee2e2", color: "#991b1b" },
2831
+ REFUNDED: { bg: "#f3f4f6", color: "#6b7280" }
2832
+ };
2833
+ function formatDate2(dateStr) {
2834
+ try {
2835
+ return new Date(dateStr).toLocaleDateString(void 0, {
2836
+ year: "numeric",
2837
+ month: "short",
2838
+ day: "numeric"
2839
+ });
2840
+ } catch {
2841
+ return dateStr;
2842
+ }
2843
+ }
2844
+ function formatAmount3(amount, currency) {
2845
+ try {
2846
+ return new Intl.NumberFormat(void 0, {
2847
+ style: "currency",
2848
+ currency,
2849
+ minimumFractionDigits: 0,
2850
+ maximumFractionDigits: 2
2851
+ }).format(amount / 100);
2852
+ } catch {
2853
+ return `${currency} ${(amount / 100).toFixed(2)}`;
2854
+ }
2855
+ }
2856
+ var styles5 = {
2857
+ container: {
2858
+ border: "1px solid #e5e7eb",
2859
+ borderRadius: "12px",
2860
+ backgroundColor: "#ffffff",
2861
+ overflow: "hidden",
2862
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
2863
+ },
2864
+ header: {
2865
+ padding: "16px 24px",
2866
+ borderBottom: "1px solid #e5e7eb"
2867
+ },
2868
+ title: {
2869
+ margin: 0,
2870
+ fontSize: "16px",
2871
+ fontWeight: 600,
2872
+ color: "#111827"
2873
+ },
2874
+ table: {
2875
+ width: "100%",
2876
+ borderCollapse: "collapse",
2877
+ fontSize: "14px"
2878
+ },
2879
+ th: {
2880
+ padding: "12px 24px",
2881
+ textAlign: "left",
2882
+ fontSize: "12px",
2883
+ fontWeight: 500,
2884
+ color: "#6b7280",
2885
+ textTransform: "uppercase",
2886
+ letterSpacing: "0.05em",
2887
+ borderBottom: "1px solid #e5e7eb",
2888
+ backgroundColor: "#f9fafb"
2889
+ },
2890
+ td: {
2891
+ padding: "12px 24px",
2892
+ borderBottom: "1px solid #f3f4f6",
2893
+ color: "#374151"
2894
+ },
2895
+ badge: (bg, color) => ({
2896
+ display: "inline-block",
2897
+ padding: "2px 8px",
2898
+ borderRadius: "9999px",
2899
+ fontSize: "12px",
2900
+ fontWeight: 500,
2901
+ backgroundColor: bg,
2902
+ color
2903
+ }),
2904
+ link: {
2905
+ color: "#6366f1",
2906
+ textDecoration: "none",
2907
+ fontWeight: 500,
2908
+ fontSize: "13px"
2909
+ },
2910
+ skeleton: {
2911
+ backgroundColor: "#f3f4f6",
2912
+ borderRadius: "4px",
2913
+ height: "14px"
2914
+ },
2915
+ emptyRow: {
2916
+ padding: "24px",
2917
+ textAlign: "center",
2918
+ color: "#9ca3af",
2919
+ fontSize: "14px"
2920
+ }
2921
+ };
2922
+ function InvoiceList({ className, style }) {
2923
+ const { data: invoices, isLoading } = useInvoices();
2924
+ if (isLoading) {
2925
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles5.container, ...style }, children: [
2926
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles5.header, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...styles5.skeleton, width: "100px", height: "18px" } }) }),
2927
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px" }, children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
2928
+ "div",
2929
+ {
2930
+ style: { ...styles5.skeleton, width: "100%", height: "16px", marginBottom: "16px" }
2931
+ },
2932
+ i
2933
+ )) })
2934
+ ] });
2935
+ }
2936
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...styles5.container, ...style }, children: [
2937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles5.header, children: /* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles5.title, children: "Invoices" }) }),
2938
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { style: styles5.table, children: [
2939
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
2940
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles5.th, children: "Date" }),
2941
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles5.th, children: "Amount" }),
2942
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles5.th, children: "Status" }),
2943
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: styles5.th, children: "Invoice" })
2944
+ ] }) }),
2945
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
2946
+ (!invoices || invoices.length === 0) && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 4, style: styles5.emptyRow, children: "No invoices yet." }) }),
2947
+ invoices?.map((invoice) => {
2948
+ const sc = statusColors2[invoice.status];
2949
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
2950
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles5.td, children: formatDate2(invoice.createdAt) }),
2951
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles5.td, children: formatAmount3(invoice.amount, invoice.currency) }),
2952
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles5.td, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.badge(sc.bg, sc.color), children: invoice.status }) }),
2953
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: styles5.td, children: invoice.invoiceUrl ? /* @__PURE__ */ jsxRuntime.jsx(
2954
+ "a",
2955
+ {
2956
+ href: invoice.invoiceUrl,
2957
+ target: "_blank",
2958
+ rel: "noopener noreferrer",
2959
+ style: styles5.link,
2960
+ children: "View"
2961
+ }
2962
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#d1d5db" }, children: "\u2014" }) })
2963
+ ] }, invoice.id);
2964
+ })
2965
+ ] })
2966
+ ] })
2967
+ ] });
2968
+ }
2969
+ InvoiceList.displayName = "InvoiceList";
2970
+ function useLogin(options) {
2971
+ const { loginMutation } = useAzirid();
2972
+ const login = react.useCallback(
2973
+ (data) => {
2974
+ loginMutation.mutate(data, {
2975
+ onSuccess: options?.onSuccess,
2976
+ onError: options?.onError
2977
+ });
2978
+ },
2979
+ [loginMutation, options?.onSuccess, options?.onError]
2980
+ );
2981
+ return react.useMemo(() => Object.assign({}, loginMutation, { login }), [loginMutation, login]);
2982
+ }
2983
+ function useSignup(options) {
2984
+ const { signupMutation } = useAzirid();
2985
+ const signup = react.useCallback(
2986
+ (data) => {
2987
+ signupMutation.mutate(data, {
2988
+ onSuccess: options?.onSuccess,
2989
+ onError: options?.onError
2990
+ });
2991
+ },
2992
+ [signupMutation, options?.onSuccess, options?.onError]
2993
+ );
2994
+ return react.useMemo(() => Object.assign({}, signupMutation, { signup }), [signupMutation, signup]);
2995
+ }
2996
+ function useLogout(options) {
2997
+ const { logoutMutation } = useAzirid();
2998
+ const logout = react.useCallback(() => {
2999
+ logoutMutation.mutate(void 0, {
3000
+ onSuccess: options?.onSuccess,
3001
+ onError: options?.onError
3002
+ });
3003
+ }, [logoutMutation, options?.onSuccess, options?.onError]);
3004
+ return react.useMemo(() => Object.assign({}, logoutMutation, { logout }), [logoutMutation, logout]);
3005
+ }
3006
+ function useSession(options) {
3007
+ const client = useAccessClient();
3008
+ const query = reactQuery.useQuery({
3009
+ queryKey: ["azirid-access", "session"],
3010
+ queryFn: () => client.get(client.paths.me),
3011
+ retry: false,
3012
+ enabled: options?.enabled ?? true,
3013
+ refetchInterval: options?.refetchInterval,
3014
+ refetchOnWindowFocus: options?.refetchOnWindowFocus ?? false
3015
+ });
3016
+ return {
3017
+ ...query,
3018
+ isAuthenticated: query.isSuccess && query.data !== null
3019
+ };
3020
+ }
3021
+ function useMagicLink(options) {
3022
+ const client = useAccessClient();
3023
+ const request = reactQuery.useMutation({
3024
+ mutationKey: ["azirid-access", "magic-link", "request"],
3025
+ mutationFn: (data) => client.post(client.paths.magicLinkRequest, data),
3026
+ onSuccess: () => options?.onRequestSuccess?.(),
3027
+ onError: options?.onError
3028
+ });
3029
+ const verify = reactQuery.useMutation({
3030
+ mutationKey: ["azirid-access", "magic-link", "verify"],
3031
+ mutationFn: (data) => client.post(client.paths.magicLinkVerify, data),
3032
+ onSuccess: options?.onVerifySuccess,
3033
+ onError: options?.onError
3034
+ });
3035
+ return { request, verify };
3036
+ }
3037
+ function useSocialLogin(options) {
3038
+ const client = useAccessClient();
3039
+ return reactQuery.useMutation({
3040
+ mutationKey: ["azirid-access", "social-login"],
3041
+ mutationFn: async (data) => {
3042
+ const body = { ...data };
3043
+ if (client.appContext?.tenantId) {
3044
+ body.tenantId = client.appContext.tenantId;
3045
+ }
3046
+ return client.post(client.paths.socialLogin, body);
3047
+ },
3048
+ onSuccess: options?.onSuccess,
3049
+ onError: options?.onError
3050
+ });
3051
+ }
3052
+ function useChangePassword(options) {
3053
+ const client = useAccessClient();
3054
+ return reactQuery.useMutation({
3055
+ mutationKey: ["azirid-access", "change-password"],
3056
+ mutationFn: (data) => client.post(client.paths.changePassword, data),
3057
+ onSuccess: options?.onSuccess,
3058
+ onError: options?.onError
3059
+ });
3060
+ }
3061
+ function useRefresh(options) {
3062
+ const client = useAccessClient();
3063
+ return reactQuery.useMutation({
3064
+ mutationKey: ["azirid-access", "refresh"],
3065
+ mutationFn: async () => {
3066
+ await client.refreshSession();
3067
+ return { accessToken: client.getAccessToken() };
3068
+ },
3069
+ onSuccess: (data) => {
3070
+ options?.onSuccess?.(data);
3071
+ },
3072
+ onError: options?.onError
3073
+ });
3074
+ }
3075
+ function useBootstrap(options) {
3076
+ const client = useAccessClient();
3077
+ const query = reactQuery.useQuery({
3078
+ queryKey: ["azirid-access", "bootstrap"],
3079
+ queryFn: async () => {
3080
+ const response = await client.post(client.paths.bootstrap);
3081
+ if (response.authenticated) {
3082
+ client.setAccessToken(response.accessToken);
3083
+ options?.onAuthenticated?.(response);
3084
+ } else {
3085
+ options?.onUnauthenticated?.();
3086
+ }
3087
+ return response;
3088
+ },
3089
+ retry: false,
3090
+ enabled: options?.enabled ?? true,
3091
+ staleTime: Infinity,
3092
+ refetchOnWindowFocus: false
3093
+ });
3094
+ const isAuthenticated = query.isSuccess && query.data !== void 0 && query.data.authenticated === true;
3095
+ return {
3096
+ ...query,
3097
+ isAuthenticated
3098
+ };
3099
+ }
3100
+ function usePasskeys(options) {
3101
+ const client = useAccessClient();
3102
+ const queryClient = reactQuery.useQueryClient();
3103
+ const list = reactQuery.useQuery({
3104
+ queryKey: ["azirid-access", "passkeys"],
3105
+ queryFn: () => client.get(client.paths.passkeys),
3106
+ enabled: options?.listEnabled ?? false
3107
+ });
3108
+ const registerStart = reactQuery.useMutation({
3109
+ mutationKey: ["azirid-access", "passkeys", "register-start"],
3110
+ mutationFn: (data) => client.post(client.paths.passkeyRegisterStart, data),
3111
+ onError: options?.onError
3112
+ });
3113
+ const registerVerify = reactQuery.useMutation({
3114
+ mutationKey: ["azirid-access", "passkeys", "register-verify"],
3115
+ mutationFn: (data) => client.post(client.paths.passkeyRegisterVerify, data),
3116
+ onSuccess: () => {
3117
+ queryClient.invalidateQueries({ queryKey: ["azirid-access", "passkeys"] });
3118
+ options?.onRegisterSuccess?.();
3119
+ },
3120
+ onError: options?.onError
3121
+ });
3122
+ const register = reactQuery.useMutation({
3123
+ mutationKey: ["azirid-access", "passkeys", "register"],
3124
+ mutationFn: (data) => client.post(client.paths.passkeys, data),
3125
+ onSuccess: () => {
3126
+ queryClient.invalidateQueries({ queryKey: ["azirid-access", "passkeys"] });
3127
+ options?.onRegisterSuccess?.();
3128
+ },
3129
+ onError: options?.onError
3130
+ });
3131
+ const revoke = reactQuery.useMutation({
3132
+ mutationKey: ["azirid-access", "passkeys", "revoke"],
3133
+ mutationFn: (passkeyId) => client.post(
3134
+ `${client.paths.passkeys}/${passkeyId}/revoke`
3135
+ ),
3136
+ onSuccess: (data) => {
3137
+ queryClient.invalidateQueries({ queryKey: ["azirid-access", "passkeys"] });
3138
+ options?.onRevokeSuccess?.(data);
3139
+ },
3140
+ onError: options?.onError
3141
+ });
3142
+ const login = reactQuery.useMutation({
3143
+ mutationKey: ["azirid-access", "passkeys", "login"],
3144
+ mutationFn: async (data) => {
3145
+ const body = { ...data };
3146
+ if (client.appContext?.tenantId) {
3147
+ body.tenantId = client.appContext.tenantId;
3148
+ }
3149
+ return client.post(client.paths.passkeyLogin, body);
3150
+ },
3151
+ onSuccess: options?.onLoginSuccess,
3152
+ onError: options?.onError
3153
+ });
3154
+ const loginStart = reactQuery.useMutation({
3155
+ mutationKey: ["azirid-access", "passkeys", "login-start"],
3156
+ mutationFn: async (data) => {
3157
+ const body = {};
3158
+ if (client.appContext?.tenantId) {
3159
+ body.tenantId = client.appContext.tenantId;
3160
+ }
3161
+ if (data) {
3162
+ Object.assign(body, data);
3163
+ }
3164
+ return client.post(client.paths.passkeyLoginStart, body);
3165
+ },
3166
+ onError: options?.onError
3167
+ });
3168
+ const loginVerify = reactQuery.useMutation({
3169
+ mutationKey: ["azirid-access", "passkeys", "login-verify"],
3170
+ mutationFn: async (data) => {
3171
+ const body = { ...data };
3172
+ if (client.appContext?.tenantId) {
3173
+ body.tenantId = client.appContext.tenantId;
3174
+ }
3175
+ return client.post(client.paths.passkeyLoginVerify, body);
3176
+ },
3177
+ onSuccess: options?.onLoginSuccess,
3178
+ onError: options?.onError
3179
+ });
3180
+ return {
3181
+ list,
3182
+ registerStart,
3183
+ registerVerify,
3184
+ register,
3185
+ revoke,
3186
+ login,
3187
+ loginStart,
3188
+ loginVerify
3189
+ };
3190
+ }
3191
+ function useSubmitTransferProof(options) {
3192
+ const client = useAccessClient();
3193
+ const queryClient = reactQuery.useQueryClient();
3194
+ const mutation = reactQuery.useMutation({
3195
+ mutationFn: (data) => client.post(client.paths.submitTransferProof, data),
3196
+ onSuccess: (data) => {
3197
+ void queryClient.invalidateQueries({ queryKey: ["transferProofs"] });
3198
+ options?.onSuccess?.(data);
3199
+ },
3200
+ onError: options?.onError
3201
+ });
3202
+ const submit = react.useCallback(
3203
+ (data) => {
3204
+ mutation.mutate(data);
3205
+ },
3206
+ [mutation]
3207
+ );
3208
+ return react.useMemo(() => ({ ...mutation, submit }), [mutation, submit]);
3209
+ }
3210
+ function useTransferProofs() {
3211
+ const client = useAccessClient();
3212
+ return reactQuery.useQuery({
3213
+ queryKey: ["transferProofs"],
3214
+ queryFn: () => client.get(client.paths.transferProofs)
3215
+ });
3216
+ }
3217
+ function zodToFieldErrors(zodError) {
3218
+ return zodError.issues.map((issue) => ({
3219
+ field: issue.path.join("."),
3220
+ message: issue.message
3221
+ }));
3222
+ }
3223
+ function useFormState(initialValues, schema, onSubmit) {
3224
+ const [values, setValues] = react.useState(initialValues);
3225
+ const [errors, setErrors] = react.useState([]);
3226
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
3227
+ const mountedRef = react.useRef(true);
3228
+ const handleChange = react.useCallback(
3229
+ (field) => (e) => {
3230
+ const next = { ...values, [field]: e.target.value };
3231
+ setValues(next);
3232
+ setErrors((prev) => prev.filter((err) => err.field !== field));
3233
+ },
3234
+ [values]
3235
+ );
3236
+ const setFieldValue = react.useCallback((field, value) => {
3237
+ setValues((prev) => ({ ...prev, [field]: value }));
3238
+ setErrors((prev) => prev.filter((err) => err.field !== field));
3239
+ }, []);
3240
+ const handleSubmit = react.useCallback(
3241
+ async (e) => {
3242
+ e.preventDefault();
3243
+ const result = schema.safeParse(values);
3244
+ if (!result.success) {
3245
+ setErrors(zodToFieldErrors(result.error));
3246
+ return;
3247
+ }
3248
+ setIsSubmitting(true);
3249
+ try {
3250
+ await onSubmit(values);
3251
+ } finally {
3252
+ if (mountedRef.current) {
3253
+ setIsSubmitting(false);
3254
+ }
3255
+ }
3256
+ },
3257
+ [values, schema, onSubmit]
3258
+ );
3259
+ const reset = react.useCallback(() => {
3260
+ setValues(initialValues);
3261
+ setErrors([]);
3262
+ setIsSubmitting(false);
3263
+ }, [initialValues]);
3264
+ return { values, errors, isSubmitting, handleChange, handleSubmit, setFieldValue, reset };
3265
+ }
3266
+ function usePasswordToggle() {
3267
+ const [visible, setVisible] = react.useState(false);
3268
+ const toggle = react.useCallback(() => setVisible((v) => !v), []);
3269
+ return { visible, toggle, type: visible ? "text" : "password" };
3270
+ }
3271
+
3272
+ // src/index.ts
3273
+ var SDK_VERSION = "0.6.0";
3274
+
3275
+ exports.AziridProvider = AziridProvider;
3276
+ exports.BASE_PATHS = BASE_PATHS;
3277
+ exports.CheckoutButton = CheckoutButton;
3278
+ exports.InvoiceList = InvoiceList;
3279
+ exports.LoginForm = LoginForm;
3280
+ exports.PATHS = PATHS;
3281
+ exports.PayButton = PayButton;
3282
+ exports.PayphoneCallback = PayphoneCallback;
3283
+ exports.PricingTable = PricingTable;
3284
+ exports.ReferralCard = ReferralCard;
3285
+ exports.ReferralStats = ReferralStats;
3286
+ exports.SDK_VERSION = SDK_VERSION;
3287
+ exports.SignupForm = SignupForm;
3288
+ exports.SubscriptionBadge = SubscriptionBadge;
3289
+ exports.buildPaths = buildPaths;
3290
+ exports.changePasswordSchema = changePasswordSchema;
3291
+ exports.cn = cn;
3292
+ exports.createAccessClient = createAccessClient;
3293
+ exports.createLoginSchema = createLoginSchema;
3294
+ exports.createSignupSchema = createSignupSchema;
3295
+ exports.en = en;
3296
+ exports.es = es;
3297
+ exports.isAuthError = isAuthError;
3298
+ exports.loginSchema = loginSchema;
3299
+ exports.magicLinkRequestSchema = magicLinkRequestSchema;
3300
+ exports.magicLinkVerifySchema = magicLinkVerifySchema;
3301
+ exports.passkeyRegisterStartSchema = passkeyRegisterStartSchema;
3302
+ exports.removeStyles = removeStyles;
3303
+ exports.resolveMessages = resolveMessages;
3304
+ exports.signupSchema = signupSchema;
3305
+ exports.socialLoginSchema = socialLoginSchema;
3306
+ exports.useAccessClient = useAccessClient;
3307
+ exports.useAzirid = useAzirid;
3308
+ exports.useBootstrap = useBootstrap;
3309
+ exports.useBranding = useBranding;
3310
+ exports.useChangePassword = useChangePassword;
3311
+ exports.useCheckout = useCheckout;
3312
+ exports.useFormState = useFormState;
3313
+ exports.useInvoices = useInvoices;
3314
+ exports.useLogin = useLogin;
3315
+ exports.useLogout = useLogout;
3316
+ exports.useMagicLink = useMagicLink;
3317
+ exports.useMessages = useMessages;
3318
+ exports.usePasskeys = usePasskeys;
3319
+ exports.usePasswordToggle = usePasswordToggle;
3320
+ exports.usePaymentProviders = usePaymentProviders;
3321
+ exports.usePayphoneConfirm = usePayphoneConfirm;
3322
+ exports.usePlans = usePlans;
3323
+ exports.useReferral = useReferral;
3324
+ exports.useReferralStats = useReferralStats;
3325
+ exports.useRefresh = useRefresh;
3326
+ exports.useSession = useSession;
3327
+ exports.useSignup = useSignup;
3328
+ exports.useSocialLogin = useSocialLogin;
3329
+ exports.useSubmitTransferProof = useSubmitTransferProof;
3330
+ exports.useSubscription = useSubscription;
3331
+ exports.useTransferProofs = useTransferProofs;
3332
+ //# sourceMappingURL=index.cjs.map
3333
+ //# sourceMappingURL=index.cjs.map