@hook-sdk/template 0.1.4 → 0.3.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 +463 -153
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -11
- package/dist/index.d.ts +96 -11
- package/dist/index.js +449 -141
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -29,12 +29,14 @@ __export(index_exports, {
|
|
|
29
29
|
EmptyState: () => EmptyState,
|
|
30
30
|
ErrorBoundary: () => ErrorBoundary,
|
|
31
31
|
LoadingState: () => LoadingState,
|
|
32
|
+
PushPrompt: () => PushPrompt2,
|
|
32
33
|
useAuth: () => useAuth,
|
|
33
34
|
useAuthPrimitives: () => useAuthPrimitives,
|
|
34
35
|
useForgotForm: () => useForgotForm,
|
|
35
36
|
useLoginForm: () => useLoginForm,
|
|
36
37
|
usePaywallState: () => usePaywallState,
|
|
37
38
|
usePush: () => usePush,
|
|
39
|
+
useReminders: () => useReminders,
|
|
38
40
|
useResetForm: () => useResetForm,
|
|
39
41
|
useSignupForm: () => useSignupForm,
|
|
40
42
|
useSubscription: () => useSubscription,
|
|
@@ -43,7 +45,7 @@ __export(index_exports, {
|
|
|
43
45
|
module.exports = __toCommonJS(index_exports);
|
|
44
46
|
|
|
45
47
|
// src/AppRoot.tsx
|
|
46
|
-
var
|
|
48
|
+
var import_react12 = require("react");
|
|
47
49
|
var import_sdk9 = require("@hook-sdk/sdk");
|
|
48
50
|
|
|
49
51
|
// src/internal/TemplateConfigContext.tsx
|
|
@@ -307,25 +309,183 @@ function useLoginForm() {
|
|
|
307
309
|
submit,
|
|
308
310
|
submitting,
|
|
309
311
|
canSubmit,
|
|
310
|
-
error
|
|
312
|
+
error,
|
|
313
|
+
loginWithGoogle: () => auth.loginWithGoogle()
|
|
311
314
|
};
|
|
312
315
|
}
|
|
313
316
|
|
|
314
|
-
// src/
|
|
317
|
+
// src/internal/GoogleSignInButton.tsx
|
|
315
318
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
319
|
+
function GoogleSignInButton({
|
|
320
|
+
onClick,
|
|
321
|
+
testId = "oauth-google",
|
|
322
|
+
label = "Continuar com Google"
|
|
323
|
+
}) {
|
|
324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
325
|
+
"button",
|
|
326
|
+
{
|
|
327
|
+
"data-testid": testId,
|
|
328
|
+
type: "button",
|
|
329
|
+
onClick,
|
|
330
|
+
style: {
|
|
331
|
+
width: "100%",
|
|
332
|
+
padding: "10px 12px",
|
|
333
|
+
display: "flex",
|
|
334
|
+
alignItems: "center",
|
|
335
|
+
justifyContent: "center",
|
|
336
|
+
gap: 10,
|
|
337
|
+
background: "#fff",
|
|
338
|
+
color: "#1f1f1f",
|
|
339
|
+
border: "1px solid #dadce0",
|
|
340
|
+
borderRadius: 8,
|
|
341
|
+
cursor: "pointer",
|
|
342
|
+
fontSize: 14,
|
|
343
|
+
fontWeight: 500,
|
|
344
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
345
|
+
},
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(GoogleGlyph, {}),
|
|
348
|
+
label
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
function GoogleGlyph() {
|
|
354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
356
|
+
"path",
|
|
357
|
+
{
|
|
358
|
+
d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.874 2.684-6.615z",
|
|
359
|
+
fill: "#4285F4"
|
|
360
|
+
}
|
|
361
|
+
),
|
|
362
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
363
|
+
"path",
|
|
364
|
+
{
|
|
365
|
+
d: "M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z",
|
|
366
|
+
fill: "#34A853"
|
|
367
|
+
}
|
|
368
|
+
),
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
370
|
+
"path",
|
|
371
|
+
{
|
|
372
|
+
d: "M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z",
|
|
373
|
+
fill: "#FBBC05"
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
377
|
+
"path",
|
|
378
|
+
{
|
|
379
|
+
d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z",
|
|
380
|
+
fill: "#EA4335"
|
|
381
|
+
}
|
|
382
|
+
)
|
|
383
|
+
] });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/internal/OAuthErrorBanner.tsx
|
|
387
|
+
var import_react7 = require("react");
|
|
388
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
389
|
+
var ERROR_MESSAGES = {
|
|
390
|
+
invalid_state: "Sess\xE3o expirou, tente de novo.",
|
|
391
|
+
access_denied: "Voc\xEA cancelou o login com Google.",
|
|
392
|
+
provider_error: "O Google recusou a autentica\xE7\xE3o. Tente de novo em alguns segundos.",
|
|
393
|
+
invalid_return_to: "Link inv\xE1lido. Tente entrar novamente."
|
|
394
|
+
};
|
|
395
|
+
function readErrorCode() {
|
|
396
|
+
if (typeof window === "undefined") return null;
|
|
397
|
+
const code = new URLSearchParams(window.location.search).get("oauth_error");
|
|
398
|
+
if (!code) return null;
|
|
399
|
+
return code;
|
|
400
|
+
}
|
|
401
|
+
function stripErrorFromUrl() {
|
|
402
|
+
if (typeof window === "undefined") return;
|
|
403
|
+
const url = new URL(window.location.href);
|
|
404
|
+
url.searchParams.delete("oauth_error");
|
|
405
|
+
window.history.replaceState({}, "", url.toString());
|
|
406
|
+
}
|
|
407
|
+
function OAuthErrorBanner() {
|
|
408
|
+
const [code, setCode] = (0, import_react7.useState)(() => readErrorCode());
|
|
409
|
+
(0, import_react7.useEffect)(() => {
|
|
410
|
+
if (code !== null) stripErrorFromUrl();
|
|
411
|
+
}, [code]);
|
|
412
|
+
if (!code) return null;
|
|
413
|
+
const message = ERROR_MESSAGES[code] ?? "N\xE3o conseguimos conectar ao Google. Tente de novo.";
|
|
414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
415
|
+
"div",
|
|
416
|
+
{
|
|
417
|
+
role: "alert",
|
|
418
|
+
"data-testid": "oauth-error-banner",
|
|
419
|
+
style: {
|
|
420
|
+
padding: "10px 12px",
|
|
421
|
+
marginBottom: 16,
|
|
422
|
+
background: "#fce8e6",
|
|
423
|
+
color: "#a50e0e",
|
|
424
|
+
borderRadius: 8,
|
|
425
|
+
fontSize: 14
|
|
426
|
+
},
|
|
427
|
+
children: [
|
|
428
|
+
message,
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
430
|
+
"button",
|
|
431
|
+
{
|
|
432
|
+
type: "button",
|
|
433
|
+
onClick: () => setCode(null),
|
|
434
|
+
"aria-label": "Fechar",
|
|
435
|
+
style: {
|
|
436
|
+
float: "right",
|
|
437
|
+
background: "none",
|
|
438
|
+
border: "none",
|
|
439
|
+
color: "#a50e0e",
|
|
440
|
+
cursor: "pointer",
|
|
441
|
+
fontSize: 16,
|
|
442
|
+
lineHeight: 1,
|
|
443
|
+
padding: 0
|
|
444
|
+
},
|
|
445
|
+
children: "\xD7"
|
|
446
|
+
}
|
|
447
|
+
)
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/defaults/DefaultLoginScreen.tsx
|
|
454
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
316
455
|
function DefaultLoginScreen({ onNavigate }) {
|
|
317
456
|
const { name } = useTemplateConfig();
|
|
318
457
|
const f = useLoginForm();
|
|
319
|
-
return /* @__PURE__ */ (0,
|
|
320
|
-
/* @__PURE__ */ (0,
|
|
321
|
-
/* @__PURE__ */ (0,
|
|
322
|
-
/* @__PURE__ */ (0,
|
|
458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(OAuthErrorBanner, {}),
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "login-oauth-google" }),
|
|
463
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
464
|
+
"div",
|
|
465
|
+
{
|
|
466
|
+
"aria-hidden": "true",
|
|
467
|
+
style: {
|
|
468
|
+
display: "flex",
|
|
469
|
+
alignItems: "center",
|
|
470
|
+
gap: 8,
|
|
471
|
+
margin: "16px 0",
|
|
472
|
+
color: "rgba(0,0,0,0.45)",
|
|
473
|
+
fontSize: 12
|
|
474
|
+
},
|
|
475
|
+
children: [
|
|
476
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
477
|
+
"ou",
|
|
478
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
479
|
+
]
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: (e) => {
|
|
323
483
|
e.preventDefault();
|
|
324
484
|
void f.submit();
|
|
325
485
|
}, children: [
|
|
326
|
-
/* @__PURE__ */ (0,
|
|
486
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
327
487
|
"E-mail",
|
|
328
|
-
/* @__PURE__ */ (0,
|
|
488
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
329
489
|
"input",
|
|
330
490
|
{
|
|
331
491
|
"data-testid": "login-email",
|
|
@@ -335,11 +495,11 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
335
495
|
style: { display: "block", width: "100%" }
|
|
336
496
|
}
|
|
337
497
|
),
|
|
338
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
498
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
339
499
|
] }),
|
|
340
|
-
/* @__PURE__ */ (0,
|
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
341
501
|
"Senha",
|
|
342
|
-
/* @__PURE__ */ (0,
|
|
502
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
343
503
|
"input",
|
|
344
504
|
{
|
|
345
505
|
"data-testid": "login-password",
|
|
@@ -349,10 +509,10 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
349
509
|
style: { display: "block", width: "100%" }
|
|
350
510
|
}
|
|
351
511
|
),
|
|
352
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
512
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
353
513
|
] }),
|
|
354
|
-
f.error && /* @__PURE__ */ (0,
|
|
355
|
-
/* @__PURE__ */ (0,
|
|
514
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
356
516
|
"button",
|
|
357
517
|
{
|
|
358
518
|
"data-testid": "login-submit",
|
|
@@ -371,42 +531,42 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
371
531
|
}
|
|
372
532
|
)
|
|
373
533
|
] }),
|
|
374
|
-
/* @__PURE__ */ (0,
|
|
375
|
-
/* @__PURE__ */ (0,
|
|
376
|
-
/* @__PURE__ */ (0,
|
|
534
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
|
|
535
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
|
|
536
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
|
|
377
537
|
] })
|
|
378
538
|
] });
|
|
379
539
|
}
|
|
380
540
|
|
|
381
541
|
// src/hooks/useSignupForm.ts
|
|
382
|
-
var
|
|
542
|
+
var import_react8 = require("react");
|
|
383
543
|
var import_sdk6 = require("@hook-sdk/sdk");
|
|
384
544
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
385
545
|
var MIN_PASSWORD2 = 8;
|
|
386
546
|
function useSignupForm() {
|
|
387
547
|
const { auth } = (0, import_sdk6.useHook)();
|
|
388
|
-
const [name, setName] = (0,
|
|
389
|
-
const [email, setEmail] = (0,
|
|
390
|
-
const [password, setPassword] = (0,
|
|
391
|
-
const [submitting, setSubmitting] = (0,
|
|
392
|
-
const [error, setError] = (0,
|
|
393
|
-
const nameError = (0,
|
|
548
|
+
const [name, setName] = (0, import_react8.useState)("");
|
|
549
|
+
const [email, setEmail] = (0, import_react8.useState)("");
|
|
550
|
+
const [password, setPassword] = (0, import_react8.useState)("");
|
|
551
|
+
const [submitting, setSubmitting] = (0, import_react8.useState)(false);
|
|
552
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
553
|
+
const nameError = (0, import_react8.useMemo)(() => {
|
|
394
554
|
if (name.length === 0) return null;
|
|
395
555
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
396
556
|
return null;
|
|
397
557
|
}, [name]);
|
|
398
|
-
const emailError = (0,
|
|
558
|
+
const emailError = (0, import_react8.useMemo)(() => {
|
|
399
559
|
if (email.length === 0) return null;
|
|
400
560
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
401
561
|
return null;
|
|
402
562
|
}, [email]);
|
|
403
|
-
const passwordError = (0,
|
|
563
|
+
const passwordError = (0, import_react8.useMemo)(() => {
|
|
404
564
|
if (password.length === 0) return null;
|
|
405
565
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
406
566
|
return null;
|
|
407
567
|
}, [password]);
|
|
408
568
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
|
|
409
|
-
const submit = (0,
|
|
569
|
+
const submit = (0, import_react8.useCallback)(async () => {
|
|
410
570
|
if (!canSubmit) return false;
|
|
411
571
|
setSubmitting(true);
|
|
412
572
|
setError(null);
|
|
@@ -433,61 +593,83 @@ function useSignupForm() {
|
|
|
433
593
|
submit,
|
|
434
594
|
submitting,
|
|
435
595
|
canSubmit,
|
|
436
|
-
error
|
|
596
|
+
error,
|
|
597
|
+
loginWithGoogle: () => auth.loginWithGoogle()
|
|
437
598
|
};
|
|
438
599
|
}
|
|
439
600
|
|
|
440
601
|
// src/defaults/DefaultSignupScreen.tsx
|
|
441
|
-
var
|
|
602
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
442
603
|
function DefaultSignupScreen({ onNavigate }) {
|
|
443
604
|
const { name } = useTemplateConfig();
|
|
444
605
|
const f = useSignupForm();
|
|
445
|
-
return /* @__PURE__ */ (0,
|
|
446
|
-
/* @__PURE__ */ (0,
|
|
447
|
-
/* @__PURE__ */ (0,
|
|
448
|
-
/* @__PURE__ */ (0,
|
|
606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OAuthErrorBanner, {}),
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "signup-oauth-google" }),
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
612
|
+
"div",
|
|
613
|
+
{
|
|
614
|
+
"aria-hidden": "true",
|
|
615
|
+
style: {
|
|
616
|
+
display: "flex",
|
|
617
|
+
alignItems: "center",
|
|
618
|
+
gap: 8,
|
|
619
|
+
margin: "16px 0",
|
|
620
|
+
color: "rgba(0,0,0,0.45)",
|
|
621
|
+
fontSize: 12
|
|
622
|
+
},
|
|
623
|
+
children: [
|
|
624
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
625
|
+
"ou",
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
),
|
|
630
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("form", { onSubmit: (e) => {
|
|
449
631
|
e.preventDefault();
|
|
450
632
|
void f.submit();
|
|
451
633
|
}, children: [
|
|
452
|
-
/* @__PURE__ */ (0,
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
453
635
|
"Nome",
|
|
454
|
-
/* @__PURE__ */ (0,
|
|
455
|
-
f.nameError && /* @__PURE__ */ (0,
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
|
|
637
|
+
f.nameError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { style: { color: "#c00" }, children: f.nameError })
|
|
456
638
|
] }),
|
|
457
|
-
/* @__PURE__ */ (0,
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
458
640
|
"E-mail",
|
|
459
|
-
/* @__PURE__ */ (0,
|
|
460
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
642
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
461
643
|
] }),
|
|
462
|
-
/* @__PURE__ */ (0,
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
463
645
|
"Senha",
|
|
464
|
-
/* @__PURE__ */ (0,
|
|
465
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
|
|
647
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
466
648
|
] }),
|
|
467
|
-
f.error && /* @__PURE__ */ (0,
|
|
468
|
-
/* @__PURE__ */ (0,
|
|
649
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
650
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { "data-testid": "signup-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Criando..." : "Criar conta" })
|
|
469
651
|
] }),
|
|
470
|
-
/* @__PURE__ */ (0,
|
|
652
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { "data-testid": "signup-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "J\xE1 tem conta? Entre" }) })
|
|
471
653
|
] });
|
|
472
654
|
}
|
|
473
655
|
|
|
474
656
|
// src/hooks/useForgotForm.ts
|
|
475
|
-
var
|
|
657
|
+
var import_react9 = require("react");
|
|
476
658
|
var import_sdk7 = require("@hook-sdk/sdk");
|
|
477
659
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
478
660
|
function useForgotForm() {
|
|
479
661
|
const { auth } = (0, import_sdk7.useHook)();
|
|
480
|
-
const [email, setEmail] = (0,
|
|
481
|
-
const [submitting, setSubmitting] = (0,
|
|
482
|
-
const [sent, setSent] = (0,
|
|
483
|
-
const [error, setError] = (0,
|
|
484
|
-
const emailError = (0,
|
|
662
|
+
const [email, setEmail] = (0, import_react9.useState)("");
|
|
663
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
664
|
+
const [sent, setSent] = (0, import_react9.useState)(false);
|
|
665
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
666
|
+
const emailError = (0, import_react9.useMemo)(() => {
|
|
485
667
|
if (email.length === 0) return null;
|
|
486
668
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
487
669
|
return null;
|
|
488
670
|
}, [email]);
|
|
489
671
|
const canSubmit = email.length > 0 && emailError === null && !submitting;
|
|
490
|
-
const submit = (0,
|
|
672
|
+
const submit = (0, import_react9.useCallback)(async () => {
|
|
491
673
|
if (!canSubmit) return false;
|
|
492
674
|
setSubmitting(true);
|
|
493
675
|
setError(null);
|
|
@@ -515,66 +697,66 @@ function useForgotForm() {
|
|
|
515
697
|
}
|
|
516
698
|
|
|
517
699
|
// src/defaults/DefaultForgotScreen.tsx
|
|
518
|
-
var
|
|
700
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
519
701
|
function DefaultForgotScreen({ onNavigate }) {
|
|
520
702
|
const { name } = useTemplateConfig();
|
|
521
703
|
const f = useForgotForm();
|
|
522
704
|
if (f.sent) {
|
|
523
|
-
return /* @__PURE__ */ (0,
|
|
524
|
-
/* @__PURE__ */ (0,
|
|
525
|
-
/* @__PURE__ */ (0,
|
|
526
|
-
/* @__PURE__ */ (0,
|
|
705
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { children: "Verifique seu e-mail" }),
|
|
707
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
|
|
527
709
|
] });
|
|
528
710
|
}
|
|
529
|
-
return /* @__PURE__ */ (0,
|
|
530
|
-
/* @__PURE__ */ (0,
|
|
531
|
-
/* @__PURE__ */ (0,
|
|
532
|
-
/* @__PURE__ */ (0,
|
|
711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
|
|
714
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("form", { onSubmit: (e) => {
|
|
533
715
|
e.preventDefault();
|
|
534
716
|
void f.submit();
|
|
535
717
|
}, children: [
|
|
536
|
-
/* @__PURE__ */ (0,
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
537
719
|
"E-mail",
|
|
538
|
-
/* @__PURE__ */ (0,
|
|
539
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
720
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
721
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
540
722
|
] }),
|
|
541
|
-
f.error && /* @__PURE__ */ (0,
|
|
542
|
-
/* @__PURE__ */ (0,
|
|
723
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { "data-testid": "forgot-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Enviando..." : "Enviar link" })
|
|
543
725
|
] }),
|
|
544
|
-
/* @__PURE__ */ (0,
|
|
726
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
|
|
545
727
|
] });
|
|
546
728
|
}
|
|
547
729
|
|
|
548
730
|
// src/hooks/useResetForm.ts
|
|
549
|
-
var
|
|
731
|
+
var import_react10 = require("react");
|
|
550
732
|
var import_sdk8 = require("@hook-sdk/sdk");
|
|
551
733
|
var MIN_PASSWORD3 = 12;
|
|
552
734
|
function useResetForm() {
|
|
553
735
|
const { auth } = (0, import_sdk8.useHook)();
|
|
554
|
-
const [token, setToken] = (0,
|
|
555
|
-
const [password, setPassword] = (0,
|
|
556
|
-
const [confirm, setConfirm] = (0,
|
|
557
|
-
const [submitting, setSubmitting] = (0,
|
|
558
|
-
const [done, setDone] = (0,
|
|
559
|
-
const [error, setError] = (0,
|
|
560
|
-
(0,
|
|
736
|
+
const [token, setToken] = (0, import_react10.useState)(null);
|
|
737
|
+
const [password, setPassword] = (0, import_react10.useState)("");
|
|
738
|
+
const [confirm, setConfirm] = (0, import_react10.useState)("");
|
|
739
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
740
|
+
const [done, setDone] = (0, import_react10.useState)(false);
|
|
741
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
742
|
+
(0, import_react10.useEffect)(() => {
|
|
561
743
|
if (typeof window === "undefined") return;
|
|
562
744
|
const params = new URLSearchParams(window.location.search);
|
|
563
745
|
const t = params.get("token");
|
|
564
746
|
setToken(t && t.length > 0 ? t : null);
|
|
565
747
|
}, []);
|
|
566
|
-
const passwordError = (0,
|
|
748
|
+
const passwordError = (0, import_react10.useMemo)(() => {
|
|
567
749
|
if (password.length === 0) return null;
|
|
568
750
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
569
751
|
return null;
|
|
570
752
|
}, [password]);
|
|
571
|
-
const confirmError = (0,
|
|
753
|
+
const confirmError = (0, import_react10.useMemo)(() => {
|
|
572
754
|
if (confirm.length === 0) return null;
|
|
573
755
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
574
756
|
return null;
|
|
575
757
|
}, [confirm, password]);
|
|
576
758
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && passwordError === null && confirmError === null && !submitting && !done;
|
|
577
|
-
const submit = (0,
|
|
759
|
+
const submit = (0, import_react10.useCallback)(async () => {
|
|
578
760
|
if (!canSubmit || token === null) return;
|
|
579
761
|
setSubmitting(true);
|
|
580
762
|
setError(null);
|
|
@@ -610,67 +792,67 @@ function useResetForm() {
|
|
|
610
792
|
}
|
|
611
793
|
|
|
612
794
|
// src/defaults/DefaultResetScreen.tsx
|
|
613
|
-
var
|
|
795
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
614
796
|
function DefaultResetScreen({ onNavigate }) {
|
|
615
797
|
const { name } = useTemplateConfig();
|
|
616
798
|
const f = useResetForm();
|
|
617
799
|
if (f.done) {
|
|
618
|
-
return /* @__PURE__ */ (0,
|
|
619
|
-
/* @__PURE__ */ (0,
|
|
620
|
-
/* @__PURE__ */ (0,
|
|
621
|
-
/* @__PURE__ */ (0,
|
|
800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
801
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { children: "Senha alterada" }),
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
|
|
803
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
|
|
622
804
|
] });
|
|
623
805
|
}
|
|
624
806
|
if (f.token === null) {
|
|
625
|
-
return /* @__PURE__ */ (0,
|
|
626
|
-
/* @__PURE__ */ (0,
|
|
627
|
-
/* @__PURE__ */ (0,
|
|
628
|
-
/* @__PURE__ */ (0,
|
|
807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { children: "Link inv\xE1lido" }),
|
|
809
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
|
|
629
811
|
] });
|
|
630
812
|
}
|
|
631
|
-
return /* @__PURE__ */ (0,
|
|
632
|
-
/* @__PURE__ */ (0,
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
634
|
-
/* @__PURE__ */ (0,
|
|
813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("form", { onSubmit: (e) => {
|
|
635
817
|
e.preventDefault();
|
|
636
818
|
void f.submit();
|
|
637
819
|
}, children: [
|
|
638
|
-
/* @__PURE__ */ (0,
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
639
821
|
"Nova senha",
|
|
640
|
-
/* @__PURE__ */ (0,
|
|
641
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { "data-testid": "reset-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
|
|
823
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
642
824
|
] }),
|
|
643
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
644
826
|
"Confirmar senha",
|
|
645
|
-
/* @__PURE__ */ (0,
|
|
646
|
-
f.confirmError && /* @__PURE__ */ (0,
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { "data-testid": "reset-confirm", type: "password", value: f.confirm, onChange: (e) => f.setConfirm(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
|
|
828
|
+
f.confirmError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("small", { style: { color: "#c00" }, children: f.confirmError })
|
|
647
829
|
] }),
|
|
648
|
-
f.error && /* @__PURE__ */ (0,
|
|
649
|
-
/* @__PURE__ */ (0,
|
|
830
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { "data-testid": "reset-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Alterando..." : "Alterar senha" })
|
|
650
832
|
] })
|
|
651
833
|
] });
|
|
652
834
|
}
|
|
653
835
|
|
|
654
836
|
// src/defaults/DefaultPaywall.tsx
|
|
655
|
-
var
|
|
656
|
-
var
|
|
837
|
+
var import_react11 = require("react");
|
|
838
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
657
839
|
function DefaultPaywall() {
|
|
658
840
|
const config = useTemplateConfig();
|
|
659
841
|
const { checkout, opening, error } = usePaywallState();
|
|
660
842
|
const p = config.subscription.paywall_config;
|
|
661
|
-
const [cpf, setCpf] = (0,
|
|
843
|
+
const [cpf, setCpf] = (0, import_react11.useState)("");
|
|
662
844
|
const cpfDigits = cpf.replace(/\D/g, "");
|
|
663
845
|
const canCheckout = cpfDigits.length === 11 && !opening;
|
|
664
|
-
return /* @__PURE__ */ (0,
|
|
665
|
-
/* @__PURE__ */ (0,
|
|
666
|
-
p.subtitle && /* @__PURE__ */ (0,
|
|
667
|
-
/* @__PURE__ */ (0,
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
|
|
847
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
|
|
848
|
+
p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: b })
|
|
670
852
|
] }, b)) }),
|
|
671
|
-
/* @__PURE__ */ (0,
|
|
672
|
-
/* @__PURE__ */ (0,
|
|
673
|
-
/* @__PURE__ */ (0,
|
|
853
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
674
856
|
"input",
|
|
675
857
|
{
|
|
676
858
|
"data-testid": "paywall-cpf",
|
|
@@ -683,8 +865,8 @@ function DefaultPaywall() {
|
|
|
683
865
|
}
|
|
684
866
|
)
|
|
685
867
|
] }),
|
|
686
|
-
error && /* @__PURE__ */ (0,
|
|
687
|
-
/* @__PURE__ */ (0,
|
|
868
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
|
|
869
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
688
870
|
"button",
|
|
689
871
|
{
|
|
690
872
|
"data-testid": "paywall-cta",
|
|
@@ -705,21 +887,21 @@ function DefaultPaywall() {
|
|
|
705
887
|
children: opening ? "Abrindo..." : p.cta
|
|
706
888
|
}
|
|
707
889
|
),
|
|
708
|
-
p.priceHint && /* @__PURE__ */ (0,
|
|
709
|
-
p.footerNote && /* @__PURE__ */ (0,
|
|
890
|
+
p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
|
|
891
|
+
p.footerNote && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
|
|
710
892
|
] });
|
|
711
893
|
}
|
|
712
894
|
|
|
713
895
|
// src/AppRoot.tsx
|
|
714
|
-
var
|
|
896
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
715
897
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
716
898
|
function PaymentReturnHandler({ children }) {
|
|
717
899
|
const { subscription } = (0, import_sdk9.useHook)();
|
|
718
|
-
const subRef = (0,
|
|
900
|
+
const subRef = (0, import_react12.useRef)(subscription);
|
|
719
901
|
subRef.current = subscription;
|
|
720
|
-
const runIdRef = (0,
|
|
721
|
-
const [state, setState] = (0,
|
|
722
|
-
const runPoll = (0,
|
|
902
|
+
const runIdRef = (0, import_react12.useRef)(0);
|
|
903
|
+
const [state, setState] = (0, import_react12.useState)("idle");
|
|
904
|
+
const runPoll = (0, import_react12.useCallback)(() => {
|
|
723
905
|
const runId = ++runIdRef.current;
|
|
724
906
|
setState("confirming");
|
|
725
907
|
let attempts = 0;
|
|
@@ -748,7 +930,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
748
930
|
};
|
|
749
931
|
void tick();
|
|
750
932
|
}, []);
|
|
751
|
-
(0,
|
|
933
|
+
(0, import_react12.useEffect)(() => {
|
|
752
934
|
if (typeof window === "undefined") return;
|
|
753
935
|
const url = new URL(window.location.href);
|
|
754
936
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -758,7 +940,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
758
940
|
};
|
|
759
941
|
}, [runPoll]);
|
|
760
942
|
if (state === "confirming") {
|
|
761
|
-
return /* @__PURE__ */ (0,
|
|
943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
762
944
|
"div",
|
|
763
945
|
{
|
|
764
946
|
role: "status",
|
|
@@ -769,9 +951,9 @@ function PaymentReturnHandler({ children }) {
|
|
|
769
951
|
);
|
|
770
952
|
}
|
|
771
953
|
if (state === "waiting") {
|
|
772
|
-
return /* @__PURE__ */ (0,
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
775
957
|
"button",
|
|
776
958
|
{
|
|
777
959
|
type: "button",
|
|
@@ -782,7 +964,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
782
964
|
)
|
|
783
965
|
] }) });
|
|
784
966
|
}
|
|
785
|
-
return /* @__PURE__ */ (0,
|
|
967
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
|
|
786
968
|
}
|
|
787
969
|
var overlayStyle = {
|
|
788
970
|
position: "fixed",
|
|
@@ -815,29 +997,129 @@ function AppRoot({
|
|
|
815
997
|
Reset = DefaultResetScreen,
|
|
816
998
|
Paywall = DefaultPaywall
|
|
817
999
|
}) {
|
|
818
|
-
return /* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PaymentReturnHandler, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TemplateConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PersistedKeysPrefetch, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(SubscriptionGate, { Paywall, children: [
|
|
819
1001
|
children,
|
|
820
|
-
/* @__PURE__ */ (0,
|
|
1002
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PushPrompt, {})
|
|
821
1003
|
] }) }) }) }) }) }) });
|
|
822
1004
|
}
|
|
823
1005
|
|
|
1006
|
+
// src/hooks/usePush.ts
|
|
1007
|
+
var import_react13 = require("react");
|
|
1008
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
1009
|
+
function detectIosNeedsInstall() {
|
|
1010
|
+
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
1011
|
+
const ua = navigator.userAgent || "";
|
|
1012
|
+
const isIos = /iPhone|iPad|iPod/.test(ua);
|
|
1013
|
+
if (!isIos) return false;
|
|
1014
|
+
const mm = window.matchMedia?.("(display-mode: standalone)");
|
|
1015
|
+
const standalone = mm?.matches === true;
|
|
1016
|
+
const legacyStandalone = typeof navigator.standalone === "boolean" ? navigator.standalone : false;
|
|
1017
|
+
return !(standalone || legacyStandalone);
|
|
1018
|
+
}
|
|
1019
|
+
function deriveState(push) {
|
|
1020
|
+
if (!push.isAvailable()) {
|
|
1021
|
+
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
1022
|
+
return { kind: "unsupported" };
|
|
1023
|
+
}
|
|
1024
|
+
const status = push.status();
|
|
1025
|
+
if (status === "granted") return { kind: "subscribed" };
|
|
1026
|
+
if (status === "denied") return { kind: "denied" };
|
|
1027
|
+
if (status === "unsupported") {
|
|
1028
|
+
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
1029
|
+
return { kind: "unsupported" };
|
|
1030
|
+
}
|
|
1031
|
+
return { kind: "prompt" };
|
|
1032
|
+
}
|
|
1033
|
+
function usePush() {
|
|
1034
|
+
const { push } = (0, import_sdk10.useHook)();
|
|
1035
|
+
const [state, setState] = (0, import_react13.useState)(() => deriveState(push));
|
|
1036
|
+
(0, import_react13.useEffect)(() => {
|
|
1037
|
+
setState(deriveState(push));
|
|
1038
|
+
}, [push]);
|
|
1039
|
+
const subscribe = (0, import_react13.useCallback)(async () => {
|
|
1040
|
+
try {
|
|
1041
|
+
await push.subscribe();
|
|
1042
|
+
setState({ kind: "subscribed" });
|
|
1043
|
+
} catch (e) {
|
|
1044
|
+
const code = e?.code ?? "push.unknown";
|
|
1045
|
+
const message = e?.message ?? "Push subscription failed";
|
|
1046
|
+
if (code === "push.permission_denied") setState({ kind: "denied" });
|
|
1047
|
+
else setState({ kind: "error", code, message });
|
|
1048
|
+
throw e;
|
|
1049
|
+
}
|
|
1050
|
+
}, [push]);
|
|
1051
|
+
const unsubscribe = (0, import_react13.useCallback)(async () => {
|
|
1052
|
+
try {
|
|
1053
|
+
await push.unsubscribe();
|
|
1054
|
+
setState({ kind: "prompt" });
|
|
1055
|
+
} catch (e) {
|
|
1056
|
+
setState({ kind: "error", code: e?.code ?? "push.unknown", message: e?.message ?? "failed" });
|
|
1057
|
+
throw e;
|
|
1058
|
+
}
|
|
1059
|
+
}, [push]);
|
|
1060
|
+
return { state, subscribe, unsubscribe };
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// src/components/PushPrompt.tsx
|
|
1064
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1065
|
+
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
1066
|
+
const { state, subscribe } = usePush();
|
|
1067
|
+
if (state.kind === "subscribed") return null;
|
|
1068
|
+
if (state.kind === "ios_needs_install") {
|
|
1069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
1070
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: texts.iosInstallBody }),
|
|
1072
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
1073
|
+
] });
|
|
1074
|
+
}
|
|
1075
|
+
if (state.kind === "denied") {
|
|
1076
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { children: texts.deniedTitle }),
|
|
1078
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: texts.deniedBody })
|
|
1079
|
+
] });
|
|
1080
|
+
}
|
|
1081
|
+
if (state.kind === "unsupported") {
|
|
1082
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: texts.unsupportedBody }) });
|
|
1083
|
+
}
|
|
1084
|
+
if (state.kind === "error") {
|
|
1085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: state.message }) });
|
|
1086
|
+
}
|
|
1087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, role: "region", children: [
|
|
1088
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1089
|
+
"button",
|
|
1090
|
+
{
|
|
1091
|
+
type: "button",
|
|
1092
|
+
onClick: async () => {
|
|
1093
|
+
try {
|
|
1094
|
+
await subscribe();
|
|
1095
|
+
onSubscribed?.();
|
|
1096
|
+
} catch {
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
1099
|
+
children: texts.cta
|
|
1100
|
+
}
|
|
1101
|
+
),
|
|
1102
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
1103
|
+
] });
|
|
1104
|
+
}
|
|
1105
|
+
|
|
824
1106
|
// src/defaults/EmptyState.tsx
|
|
825
|
-
var
|
|
1107
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
826
1108
|
function EmptyState({ title, description, action }) {
|
|
827
|
-
return /* @__PURE__ */ (0,
|
|
828
|
-
/* @__PURE__ */ (0,
|
|
829
|
-
description && /* @__PURE__ */ (0,
|
|
830
|
-
action && /* @__PURE__ */ (0,
|
|
1109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
1111
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
1112
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
831
1113
|
] });
|
|
832
1114
|
}
|
|
833
1115
|
|
|
834
1116
|
// src/hooks/useAuthPrimitives.ts
|
|
835
|
-
var
|
|
836
|
-
var
|
|
1117
|
+
var import_react14 = require("react");
|
|
1118
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
837
1119
|
var warned = false;
|
|
838
1120
|
function useAuthPrimitives() {
|
|
839
|
-
const { auth } = (0,
|
|
840
|
-
(0,
|
|
1121
|
+
const { auth } = (0, import_sdk11.useHook)();
|
|
1122
|
+
(0, import_react14.useEffect)(() => {
|
|
841
1123
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
842
1124
|
warned = true;
|
|
843
1125
|
console.warn(
|
|
@@ -859,37 +1141,63 @@ function useAuthPrimitives() {
|
|
|
859
1141
|
}
|
|
860
1142
|
|
|
861
1143
|
// src/hooks/useSubscription.ts
|
|
862
|
-
var
|
|
1144
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
863
1145
|
function useSubscription() {
|
|
864
|
-
const { subscription } = (0,
|
|
1146
|
+
const { subscription } = (0, import_sdk12.useHook)();
|
|
865
1147
|
return {
|
|
866
1148
|
status: subscription.status()
|
|
867
1149
|
};
|
|
868
1150
|
}
|
|
869
1151
|
|
|
870
|
-
// src/hooks/
|
|
871
|
-
var
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1152
|
+
// src/hooks/useReminders.ts
|
|
1153
|
+
var import_react15 = require("react");
|
|
1154
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
1155
|
+
function useReminders() {
|
|
1156
|
+
const { push } = (0, import_sdk13.useHook)();
|
|
1157
|
+
const r = push.reminders;
|
|
1158
|
+
const [reminders, setReminders] = (0, import_react15.useState)([]);
|
|
1159
|
+
const [loading, setLoading] = (0, import_react15.useState)(true);
|
|
1160
|
+
const reload = (0, import_react15.useCallback)(async () => {
|
|
1161
|
+
setLoading(true);
|
|
1162
|
+
try {
|
|
1163
|
+
const next = await r.list();
|
|
1164
|
+
setReminders(next);
|
|
1165
|
+
} finally {
|
|
1166
|
+
setLoading(false);
|
|
1167
|
+
}
|
|
1168
|
+
}, [r]);
|
|
1169
|
+
(0, import_react15.useEffect)(() => {
|
|
1170
|
+
void reload();
|
|
1171
|
+
}, [reload]);
|
|
1172
|
+
const setReminder = (0, import_react15.useCallback)(async (input) => {
|
|
1173
|
+
await r.set(input);
|
|
1174
|
+
await reload();
|
|
1175
|
+
}, [r, reload]);
|
|
1176
|
+
const deleteReminder = (0, import_react15.useCallback)(async (slot) => {
|
|
1177
|
+
await r.delete(slot);
|
|
1178
|
+
await reload();
|
|
1179
|
+
}, [r, reload]);
|
|
1180
|
+
const schedule = (0, import_react15.useCallback)(async (items) => {
|
|
1181
|
+
return r.schedule(items);
|
|
1182
|
+
}, [r]);
|
|
1183
|
+
const setFallbacks = (0, import_react15.useCallback)(async (items) => {
|
|
1184
|
+
return r.setFallbacks(items);
|
|
1185
|
+
}, [r]);
|
|
1186
|
+
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
879
1187
|
}
|
|
880
1188
|
|
|
881
1189
|
// src/hooks/useToast.ts
|
|
882
|
-
var
|
|
1190
|
+
var import_react16 = require("react");
|
|
883
1191
|
function useToast() {
|
|
884
|
-
const [items, setItems] = (0,
|
|
885
|
-
const show = (0,
|
|
1192
|
+
const [items, setItems] = (0, import_react16.useState)([]);
|
|
1193
|
+
const show = (0, import_react16.useCallback)((message, kind = "info") => {
|
|
886
1194
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
887
1195
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
888
1196
|
setTimeout(() => {
|
|
889
1197
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
890
1198
|
}, 4e3);
|
|
891
1199
|
}, []);
|
|
892
|
-
const dismiss = (0,
|
|
1200
|
+
const dismiss = (0, import_react16.useCallback)((id) => {
|
|
893
1201
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
894
1202
|
}, []);
|
|
895
1203
|
return { items, show, dismiss };
|
|
@@ -905,12 +1213,14 @@ function useToast() {
|
|
|
905
1213
|
EmptyState,
|
|
906
1214
|
ErrorBoundary,
|
|
907
1215
|
LoadingState,
|
|
1216
|
+
PushPrompt,
|
|
908
1217
|
useAuth,
|
|
909
1218
|
useAuthPrimitives,
|
|
910
1219
|
useForgotForm,
|
|
911
1220
|
useLoginForm,
|
|
912
1221
|
usePaywallState,
|
|
913
1222
|
usePush,
|
|
1223
|
+
useReminders,
|
|
914
1224
|
useResetForm,
|
|
915
1225
|
useSignupForm,
|
|
916
1226
|
useSubscription,
|