@hook-sdk/template 0.25.1 → 0.27.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 +934 -397
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -4
- package/dist/index.d.ts +84 -4
- package/dist/index.js +897 -360
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/AppRoot.tsx
|
|
2
2
|
import { useMemo as useMemo3 } from "react";
|
|
3
3
|
import { BrowserRouter, MemoryRouter, Navigate, Route, Routes } from "react-router-dom";
|
|
4
|
-
import { useHook as
|
|
4
|
+
import { useHook as useHook7 } from "@hook-sdk/sdk";
|
|
5
5
|
|
|
6
6
|
// src/config/AppConfigContext.tsx
|
|
7
7
|
import { createContext, useContext } from "react";
|
|
@@ -31,7 +31,9 @@ var AuthFlowSchema = z.object({
|
|
|
31
31
|
requiresEmailVerify: z.boolean(),
|
|
32
32
|
googleOAuth: z.boolean(),
|
|
33
33
|
postAuthLanding: z.string().startsWith("/"),
|
|
34
|
-
preAuthRoutes: z.array(z.string().startsWith("/"))
|
|
34
|
+
preAuthRoutes: z.array(z.string().startsWith("/")),
|
|
35
|
+
// Plan-V — pay-first signup mode. See types/AppConfig.ts AuthFlowConfig.
|
|
36
|
+
signupMode: z.enum(["pre_signup", "pay_first"]).optional()
|
|
35
37
|
});
|
|
36
38
|
var PaywallNonFreeSchema = z.object({
|
|
37
39
|
mode: z.enum(["trial", "pay_first"]),
|
|
@@ -2031,53 +2033,9 @@ function SessionExpiredBanner() {
|
|
|
2031
2033
|
] });
|
|
2032
2034
|
}
|
|
2033
2035
|
|
|
2034
|
-
// src/internal/EmailVerifyBanner.tsx
|
|
2035
|
-
import { useState as useState5 } from "react";
|
|
2036
|
-
import { useHook as useHook5 } from "@hook-sdk/sdk";
|
|
2037
|
-
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2038
|
-
function EmailVerifyBanner() {
|
|
2039
|
-
const { user, auth } = useHook5();
|
|
2040
|
-
const [sending, setSending] = useState5(false);
|
|
2041
|
-
const [sent, setSent] = useState5(false);
|
|
2042
|
-
if (!user || user.emailVerified) return null;
|
|
2043
|
-
async function handleResend() {
|
|
2044
|
-
if (sending || sent) return;
|
|
2045
|
-
setSending(true);
|
|
2046
|
-
try {
|
|
2047
|
-
await auth.resendVerify();
|
|
2048
|
-
setSent(true);
|
|
2049
|
-
} catch {
|
|
2050
|
-
} finally {
|
|
2051
|
-
setSending(false);
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
const label = sent ? "Enviado!" : sending ? "Enviando..." : "Reenviar link";
|
|
2055
|
-
return /* @__PURE__ */ jsxs12(
|
|
2056
|
-
"div",
|
|
2057
|
-
{
|
|
2058
|
-
role: "status",
|
|
2059
|
-
"data-testid": "email-verify-banner",
|
|
2060
|
-
className: "sticky top-0 inset-x-0 z-50 bg-yellow-100 text-yellow-900 border-b border-yellow-200 px-4 py-2 flex items-center justify-between gap-3 text-sm",
|
|
2061
|
-
children: [
|
|
2062
|
-
/* @__PURE__ */ jsx18("span", { children: "Confirma teu e-mail pra liberar tudo." }),
|
|
2063
|
-
/* @__PURE__ */ jsx18(
|
|
2064
|
-
"button",
|
|
2065
|
-
{
|
|
2066
|
-
type: "button",
|
|
2067
|
-
onClick: handleResend,
|
|
2068
|
-
disabled: sending || sent,
|
|
2069
|
-
className: "px-3 py-1 rounded text-xs font-medium bg-yellow-900 text-yellow-50 hover:bg-yellow-800 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
2070
|
-
children: label
|
|
2071
|
-
}
|
|
2072
|
-
)
|
|
2073
|
-
]
|
|
2074
|
-
}
|
|
2075
|
-
);
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
2036
|
// src/defaults/ErrorBoundary.tsx
|
|
2079
2037
|
import { Component } from "react";
|
|
2080
|
-
import { Fragment as Fragment4, jsx as
|
|
2038
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2081
2039
|
var ErrorBoundary = class extends Component {
|
|
2082
2040
|
state = { error: null };
|
|
2083
2041
|
static getDerivedStateFromError(error) {
|
|
@@ -2095,12 +2053,12 @@ var ErrorBoundary = class extends Component {
|
|
|
2095
2053
|
}
|
|
2096
2054
|
render() {
|
|
2097
2055
|
if (this.state.error) {
|
|
2098
|
-
return this.props.fallback ?? /* @__PURE__ */
|
|
2099
|
-
/* @__PURE__ */
|
|
2100
|
-
/* @__PURE__ */
|
|
2056
|
+
return this.props.fallback ?? /* @__PURE__ */ jsxs12("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
2057
|
+
/* @__PURE__ */ jsx18("h2", { children: "Algo deu errado" }),
|
|
2058
|
+
/* @__PURE__ */ jsx18("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
2101
2059
|
] });
|
|
2102
2060
|
}
|
|
2103
|
-
return /* @__PURE__ */
|
|
2061
|
+
return /* @__PURE__ */ jsx18(Fragment4, { children: this.props.children });
|
|
2104
2062
|
}
|
|
2105
2063
|
};
|
|
2106
2064
|
|
|
@@ -2109,7 +2067,7 @@ import { useEffect as useEffect7 } from "react";
|
|
|
2109
2067
|
import i18n from "i18next";
|
|
2110
2068
|
import { I18nextProvider, initReactI18next } from "react-i18next";
|
|
2111
2069
|
import { usePersistedState } from "@hook-sdk/sdk";
|
|
2112
|
-
import { jsx as
|
|
2070
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2113
2071
|
function ensureInitialized(defaultLocale, supportedLocales, resources, initialLocale) {
|
|
2114
2072
|
if (i18n.isInitialized) return;
|
|
2115
2073
|
i18n.use(initReactI18next).init({
|
|
@@ -2138,7 +2096,7 @@ function I18nProvider({
|
|
|
2138
2096
|
i18n.changeLanguage(userLocale);
|
|
2139
2097
|
}
|
|
2140
2098
|
}, [userLocale]);
|
|
2141
|
-
return /* @__PURE__ */
|
|
2099
|
+
return /* @__PURE__ */ jsx19(I18nextProvider, { i18n, children });
|
|
2142
2100
|
}
|
|
2143
2101
|
|
|
2144
2102
|
// src/dev/env.ts
|
|
@@ -2149,9 +2107,9 @@ function isDevToolsEnabled() {
|
|
|
2149
2107
|
}
|
|
2150
2108
|
|
|
2151
2109
|
// src/dev/DevSkipOnboardingFab.tsx
|
|
2152
|
-
import { useCallback as useCallback3, useRef as useRef4, useState as
|
|
2153
|
-
import { useHook as
|
|
2154
|
-
import { jsx as
|
|
2110
|
+
import { useCallback as useCallback3, useRef as useRef4, useState as useState5 } from "react";
|
|
2111
|
+
import { useHook as useHook5 } from "@hook-sdk/sdk";
|
|
2112
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
2155
2113
|
var STORAGE_KEY = "hook_dev_skip_email";
|
|
2156
2114
|
var TEST_EMAIL_DOMAIN = "@hook.test";
|
|
2157
2115
|
var TEST_PASSWORD = "SkipTest!2026";
|
|
@@ -2218,10 +2176,10 @@ var STYLES = {
|
|
|
2218
2176
|
};
|
|
2219
2177
|
var CONFIRM_TIMEOUT_MS = 3e3;
|
|
2220
2178
|
function DevSkipOnboardingFab({ defaults }) {
|
|
2221
|
-
const hook =
|
|
2179
|
+
const hook = useHook5();
|
|
2222
2180
|
const { slug } = useAppConfig();
|
|
2223
|
-
const [state, setState] =
|
|
2224
|
-
const [errorMsg, setErrorMsg] =
|
|
2181
|
+
const [state, setState] = useState5("idle");
|
|
2182
|
+
const [errorMsg, setErrorMsg] = useState5(null);
|
|
2225
2183
|
const timerRef = useRef4(null);
|
|
2226
2184
|
const clearTimer = useCallback3(() => {
|
|
2227
2185
|
if (timerRef.current) {
|
|
@@ -2258,7 +2216,7 @@ function DevSkipOnboardingFab({ defaults }) {
|
|
|
2258
2216
|
...state === "confirm" || state === "error" ? STYLES.confirm : {},
|
|
2259
2217
|
...state === "busy" ? STYLES.busy : {}
|
|
2260
2218
|
};
|
|
2261
|
-
return /* @__PURE__ */
|
|
2219
|
+
return /* @__PURE__ */ jsx20(
|
|
2262
2220
|
"button",
|
|
2263
2221
|
{
|
|
2264
2222
|
type: "button",
|
|
@@ -2273,20 +2231,20 @@ function DevSkipOnboardingFab({ defaults }) {
|
|
|
2273
2231
|
}
|
|
2274
2232
|
|
|
2275
2233
|
// src/internal/PaymentReturnHandler.tsx
|
|
2276
|
-
import { useCallback as useCallback4, useEffect as useEffect8, useRef as useRef5, useState as
|
|
2277
|
-
import { useHook as
|
|
2278
|
-
import { Fragment as Fragment5, jsx as
|
|
2234
|
+
import { useCallback as useCallback4, useEffect as useEffect8, useRef as useRef5, useState as useState6 } from "react";
|
|
2235
|
+
import { useHook as useHook6 } from "@hook-sdk/sdk";
|
|
2236
|
+
import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2279
2237
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
2280
2238
|
var MAX_CYCLES = 3;
|
|
2281
2239
|
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
2282
2240
|
function PaymentReturnHandler({ children }) {
|
|
2283
|
-
const { subscription, track: track2 } =
|
|
2241
|
+
const { subscription, track: track2 } = useHook6();
|
|
2284
2242
|
const subRef = useRef5(subscription);
|
|
2285
2243
|
subRef.current = subscription;
|
|
2286
2244
|
const runIdRef = useRef5(0);
|
|
2287
2245
|
const cyclesRef = useRef5(0);
|
|
2288
2246
|
const startMsRef = useRef5(0);
|
|
2289
|
-
const [state, setState] =
|
|
2247
|
+
const [state, setState] = useState6("idle");
|
|
2290
2248
|
const runPoll = useCallback4(() => {
|
|
2291
2249
|
const runId = ++runIdRef.current;
|
|
2292
2250
|
const isFirstRun = cyclesRef.current === 0;
|
|
@@ -2352,19 +2310,19 @@ function PaymentReturnHandler({ children }) {
|
|
|
2352
2310
|
window.location.href = cleanUrl.toString();
|
|
2353
2311
|
}, []);
|
|
2354
2312
|
if (state === "confirming") {
|
|
2355
|
-
return /* @__PURE__ */
|
|
2313
|
+
return /* @__PURE__ */ jsx21("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
|
|
2356
2314
|
}
|
|
2357
2315
|
if (state === "waiting") {
|
|
2358
|
-
return /* @__PURE__ */
|
|
2359
|
-
/* @__PURE__ */
|
|
2360
|
-
/* @__PURE__ */
|
|
2316
|
+
return /* @__PURE__ */ jsx21("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2317
|
+
/* @__PURE__ */ jsx21("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2318
|
+
/* @__PURE__ */ jsx21("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
|
|
2361
2319
|
] }) });
|
|
2362
2320
|
}
|
|
2363
2321
|
if (state === "timeout") {
|
|
2364
|
-
return /* @__PURE__ */
|
|
2365
|
-
/* @__PURE__ */
|
|
2366
|
-
/* @__PURE__ */
|
|
2367
|
-
/* @__PURE__ */
|
|
2322
|
+
return /* @__PURE__ */ jsx21("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2323
|
+
/* @__PURE__ */ jsx21("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
|
|
2324
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2325
|
+
/* @__PURE__ */ jsx21(
|
|
2368
2326
|
"button",
|
|
2369
2327
|
{
|
|
2370
2328
|
type: "button",
|
|
@@ -2377,7 +2335,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2377
2335
|
children: "Tentar de novo"
|
|
2378
2336
|
}
|
|
2379
2337
|
),
|
|
2380
|
-
/* @__PURE__ */
|
|
2338
|
+
/* @__PURE__ */ jsx21(
|
|
2381
2339
|
"button",
|
|
2382
2340
|
{
|
|
2383
2341
|
type: "button",
|
|
@@ -2387,7 +2345,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2387
2345
|
children: "Voltar pro app"
|
|
2388
2346
|
}
|
|
2389
2347
|
),
|
|
2390
|
-
/* @__PURE__ */
|
|
2348
|
+
/* @__PURE__ */ jsx21(
|
|
2391
2349
|
"a",
|
|
2392
2350
|
{
|
|
2393
2351
|
href: SUPPORT_MAILTO,
|
|
@@ -2399,7 +2357,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2399
2357
|
] })
|
|
2400
2358
|
] }) });
|
|
2401
2359
|
}
|
|
2402
|
-
return /* @__PURE__ */
|
|
2360
|
+
return /* @__PURE__ */ jsx21(Fragment5, { children });
|
|
2403
2361
|
}
|
|
2404
2362
|
var overlayStyle2 = {
|
|
2405
2363
|
position: "fixed",
|
|
@@ -2438,7 +2396,7 @@ var linkStyle = {
|
|
|
2438
2396
|
};
|
|
2439
2397
|
|
|
2440
2398
|
// src/AppRoot.tsx
|
|
2441
|
-
import { Fragment as Fragment6, jsx as
|
|
2399
|
+
import { Fragment as Fragment6, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2442
2400
|
function buildLegacyConfigShim(config) {
|
|
2443
2401
|
const paywall = config.paywall;
|
|
2444
2402
|
const isFree = paywall.mode === "free";
|
|
@@ -2517,17 +2475,14 @@ function AppRoot(props) {
|
|
|
2517
2475
|
const basename = `/app/${config.slug}`;
|
|
2518
2476
|
const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
|
|
2519
2477
|
const position = config.install_prompt?.position ?? "post-paywall";
|
|
2520
|
-
const subscriptionGated = /* @__PURE__ */
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
] })
|
|
2529
|
-
] });
|
|
2530
|
-
const authGated = /* @__PURE__ */ jsx23(
|
|
2478
|
+
const subscriptionGated = /* @__PURE__ */ jsx22(SubscriptionGate, { Paywall: Paywall2 ?? FallbackPaywall, children: position === "post-paywall" ? /* @__PURE__ */ jsxs14(InstallGate, { position: "post-paywall", children: [
|
|
2479
|
+
children,
|
|
2480
|
+
/* @__PURE__ */ jsx22(PushPrompt, {})
|
|
2481
|
+
] }) : /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
2482
|
+
children,
|
|
2483
|
+
/* @__PURE__ */ jsx22(PushPrompt, {})
|
|
2484
|
+
] }) });
|
|
2485
|
+
const authGated = /* @__PURE__ */ jsx22(
|
|
2531
2486
|
AuthGated,
|
|
2532
2487
|
{
|
|
2533
2488
|
config,
|
|
@@ -2542,13 +2497,13 @@ function AppRoot(props) {
|
|
|
2542
2497
|
children: subscriptionGated
|
|
2543
2498
|
}
|
|
2544
2499
|
);
|
|
2545
|
-
const routedTree = /* @__PURE__ */
|
|
2546
|
-
/* @__PURE__ */
|
|
2547
|
-
/* @__PURE__ */
|
|
2548
|
-
position === "pre-auth" ? /* @__PURE__ */
|
|
2549
|
-
isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */
|
|
2500
|
+
const routedTree = /* @__PURE__ */ jsxs14(Router, { ...routerProps, children: [
|
|
2501
|
+
/* @__PURE__ */ jsx22(DeepLinkHandler, { deepLinks: config.deepLinks }),
|
|
2502
|
+
/* @__PURE__ */ jsx22(SessionExpiredBanner, {}),
|
|
2503
|
+
position === "pre-auth" ? /* @__PURE__ */ jsx22(InstallGate, { position: "pre-auth", children: authGated }) : authGated,
|
|
2504
|
+
isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */ jsx22(DevSkipOnboardingFab, { defaults: devSkipOnboarding.defaults }) : null
|
|
2550
2505
|
] });
|
|
2551
|
-
return /* @__PURE__ */
|
|
2506
|
+
return /* @__PURE__ */ jsx22(ErrorBoundary, { children: /* @__PURE__ */ jsx22(AppConfigProvider, { config, children: /* @__PURE__ */ jsx22(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ jsx22(ThemeProvider, { children: /* @__PURE__ */ jsx22(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ jsx22(
|
|
2552
2507
|
I18nProvider,
|
|
2553
2508
|
{
|
|
2554
2509
|
defaultLocale: config.i18n.defaultLocale,
|
|
@@ -2568,37 +2523,46 @@ function AuthGated({
|
|
|
2568
2523
|
EmailVerify,
|
|
2569
2524
|
PreAuthFlow
|
|
2570
2525
|
}) {
|
|
2571
|
-
const { authStatus } =
|
|
2526
|
+
const { authStatus } = useHook7();
|
|
2572
2527
|
if (authStatus === "loading") return null;
|
|
2573
2528
|
if (authStatus !== "authenticated") {
|
|
2529
|
+
if (config.authFlow.signupMode === "pay_first" && PreAuthFlow) {
|
|
2530
|
+
return /* @__PURE__ */ jsxs14(Routes, { children: [
|
|
2531
|
+
/* @__PURE__ */ jsx22(Route, { path: "/signin", element: /* @__PURE__ */ jsx22(Login, {}) }),
|
|
2532
|
+
/* @__PURE__ */ jsx22(Route, { path: "/forgot", element: /* @__PURE__ */ jsx22(Forgot, {}) }),
|
|
2533
|
+
/* @__PURE__ */ jsx22(Route, { path: "/reset", element: /* @__PURE__ */ jsx22(Reset, {}) }),
|
|
2534
|
+
EmailVerify ? /* @__PURE__ */ jsx22(Route, { path: "/verify", element: /* @__PURE__ */ jsx22(EmailVerify, {}) }) : null,
|
|
2535
|
+
/* @__PURE__ */ jsx22(Route, { path: "/*", element: /* @__PURE__ */ jsx22(PreAuthFlow, {}) })
|
|
2536
|
+
] });
|
|
2537
|
+
}
|
|
2574
2538
|
if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
|
|
2575
|
-
return /* @__PURE__ */
|
|
2576
|
-
/* @__PURE__ */
|
|
2577
|
-
/* @__PURE__ */
|
|
2578
|
-
/* @__PURE__ */
|
|
2579
|
-
/* @__PURE__ */
|
|
2580
|
-
EmailVerify ? /* @__PURE__ */
|
|
2581
|
-
/* @__PURE__ */
|
|
2539
|
+
return /* @__PURE__ */ jsxs14(Routes, { children: [
|
|
2540
|
+
/* @__PURE__ */ jsx22(Route, { path: "/signin", element: /* @__PURE__ */ jsx22(Login, {}) }),
|
|
2541
|
+
/* @__PURE__ */ jsx22(Route, { path: "/signup", element: /* @__PURE__ */ jsx22(Signup, {}) }),
|
|
2542
|
+
/* @__PURE__ */ jsx22(Route, { path: "/forgot", element: /* @__PURE__ */ jsx22(Forgot, {}) }),
|
|
2543
|
+
/* @__PURE__ */ jsx22(Route, { path: "/reset", element: /* @__PURE__ */ jsx22(Reset, {}) }),
|
|
2544
|
+
EmailVerify ? /* @__PURE__ */ jsx22(Route, { path: "/verify", element: /* @__PURE__ */ jsx22(EmailVerify, {}) }) : null,
|
|
2545
|
+
/* @__PURE__ */ jsx22(Route, { path: "/*", element: /* @__PURE__ */ jsx22(PreAuthFlow, {}) })
|
|
2582
2546
|
] });
|
|
2583
2547
|
}
|
|
2584
|
-
return /* @__PURE__ */
|
|
2585
|
-
/* @__PURE__ */
|
|
2586
|
-
/* @__PURE__ */
|
|
2587
|
-
/* @__PURE__ */
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
EmailVerify ? /* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2548
|
+
return /* @__PURE__ */ jsxs14(Routes, { children: [
|
|
2549
|
+
/* @__PURE__ */ jsx22(Route, { path: "/", element: /* @__PURE__ */ jsx22(Login, {}) }),
|
|
2550
|
+
/* @__PURE__ */ jsx22(Route, { path: "/signup", element: /* @__PURE__ */ jsx22(Signup, {}) }),
|
|
2551
|
+
/* @__PURE__ */ jsx22(Route, { path: "/forgot", element: /* @__PURE__ */ jsx22(Forgot, {}) }),
|
|
2552
|
+
/* @__PURE__ */ jsx22(Route, { path: "/reset", element: /* @__PURE__ */ jsx22(Reset, {}) }),
|
|
2553
|
+
EmailVerify ? /* @__PURE__ */ jsx22(Route, { path: "/verify", element: /* @__PURE__ */ jsx22(EmailVerify, {}) }) : null,
|
|
2554
|
+
/* @__PURE__ */ jsx22(Route, { path: "*", element: /* @__PURE__ */ jsx22(Navigate, { to: "/", replace: true }) })
|
|
2591
2555
|
] });
|
|
2592
2556
|
}
|
|
2593
|
-
return /* @__PURE__ */
|
|
2557
|
+
return /* @__PURE__ */ jsx22(Fragment6, { children });
|
|
2594
2558
|
}
|
|
2595
2559
|
function FallbackPaywall() {
|
|
2596
2560
|
return null;
|
|
2597
2561
|
}
|
|
2598
2562
|
|
|
2599
2563
|
// src/hooks/usePush.ts
|
|
2600
|
-
import { useCallback as useCallback5, useEffect as useEffect9, useState as
|
|
2601
|
-
import { useHook as
|
|
2564
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useState as useState7 } from "react";
|
|
2565
|
+
import { useHook as useHook8 } from "@hook-sdk/sdk";
|
|
2602
2566
|
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2603
2567
|
var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
2604
2568
|
function detectIosNeedsInstall() {
|
|
@@ -2642,8 +2606,8 @@ function deriveState(push) {
|
|
|
2642
2606
|
return { kind: "prompt" };
|
|
2643
2607
|
}
|
|
2644
2608
|
function usePush() {
|
|
2645
|
-
const { push } =
|
|
2646
|
-
const [state, setState] =
|
|
2609
|
+
const { push } = useHook8();
|
|
2610
|
+
const [state, setState] = useState7(() => deriveState(push));
|
|
2647
2611
|
useEffect9(() => {
|
|
2648
2612
|
setState(deriveState(push));
|
|
2649
2613
|
}, [push]);
|
|
@@ -2681,27 +2645,27 @@ function usePush() {
|
|
|
2681
2645
|
}
|
|
2682
2646
|
|
|
2683
2647
|
// src/components/PushPrompt.tsx
|
|
2684
|
-
import { jsx as
|
|
2648
|
+
import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2685
2649
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
2686
2650
|
const { state, subscribe } = usePush();
|
|
2687
2651
|
if (state.kind === "denied" || state.kind === "dismissed" || state.kind === "subscribed") {
|
|
2688
2652
|
return null;
|
|
2689
2653
|
}
|
|
2690
2654
|
if (state.kind === "ios_needs_install") {
|
|
2691
|
-
return /* @__PURE__ */
|
|
2692
|
-
/* @__PURE__ */
|
|
2693
|
-
/* @__PURE__ */
|
|
2694
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */
|
|
2655
|
+
return /* @__PURE__ */ jsxs15("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2656
|
+
/* @__PURE__ */ jsx23("h3", { children: texts.iosInstallTitle }),
|
|
2657
|
+
/* @__PURE__ */ jsx23("p", { children: texts.iosInstallBody }),
|
|
2658
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ jsx23("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
2695
2659
|
] });
|
|
2696
2660
|
}
|
|
2697
2661
|
if (state.kind === "unsupported") {
|
|
2698
|
-
return /* @__PURE__ */
|
|
2662
|
+
return /* @__PURE__ */ jsx23("div", { className, role: "region", children: /* @__PURE__ */ jsx23("p", { children: texts.unsupportedBody }) });
|
|
2699
2663
|
}
|
|
2700
2664
|
if (state.kind === "error") {
|
|
2701
|
-
return /* @__PURE__ */
|
|
2665
|
+
return /* @__PURE__ */ jsx23("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ jsx23("p", { children: state.message }) });
|
|
2702
2666
|
}
|
|
2703
|
-
return /* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
2667
|
+
return /* @__PURE__ */ jsxs15("div", { className, role: "region", children: [
|
|
2668
|
+
/* @__PURE__ */ jsx23(
|
|
2705
2669
|
"button",
|
|
2706
2670
|
{
|
|
2707
2671
|
type: "button",
|
|
@@ -2715,13 +2679,13 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2715
2679
|
children: texts.cta
|
|
2716
2680
|
}
|
|
2717
2681
|
),
|
|
2718
|
-
onDeclined && /* @__PURE__ */
|
|
2682
|
+
onDeclined && /* @__PURE__ */ jsx23("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
2719
2683
|
] });
|
|
2720
2684
|
}
|
|
2721
2685
|
|
|
2722
2686
|
// src/components/LanguageSwitcher.tsx
|
|
2723
2687
|
import { usePersistedState as usePersistedState2 } from "@hook-sdk/sdk";
|
|
2724
|
-
import { jsx as
|
|
2688
|
+
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2725
2689
|
function LanguageSwitcher({ id, className, label = "Language" }) {
|
|
2726
2690
|
const config = useAppConfig();
|
|
2727
2691
|
const i18nConfig = config.i18n;
|
|
@@ -2730,43 +2694,50 @@ function LanguageSwitcher({ id, className, label = "Language" }) {
|
|
|
2730
2694
|
i18nConfig?.defaultLocale ?? "en-US"
|
|
2731
2695
|
);
|
|
2732
2696
|
if (!i18nConfig) return null;
|
|
2733
|
-
return /* @__PURE__ */
|
|
2734
|
-
label ? /* @__PURE__ */
|
|
2735
|
-
/* @__PURE__ */
|
|
2697
|
+
return /* @__PURE__ */ jsxs16("label", { className, children: [
|
|
2698
|
+
label ? /* @__PURE__ */ jsx24("span", { children: label }) : null,
|
|
2699
|
+
/* @__PURE__ */ jsx24(
|
|
2736
2700
|
"select",
|
|
2737
2701
|
{
|
|
2738
2702
|
id,
|
|
2739
2703
|
value: userLocale,
|
|
2740
2704
|
onChange: (e) => setUserLocale(e.target.value),
|
|
2741
2705
|
"data-testid": "language-switcher",
|
|
2742
|
-
children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */
|
|
2706
|
+
children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ jsx24("option", { value: loc, children: loc }, loc))
|
|
2743
2707
|
}
|
|
2744
2708
|
)
|
|
2745
2709
|
] });
|
|
2746
2710
|
}
|
|
2747
2711
|
|
|
2748
2712
|
// src/defaults/LoadingState.tsx
|
|
2749
|
-
import { jsx as
|
|
2713
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
2750
2714
|
function LoadingState({ message }) {
|
|
2751
|
-
return /* @__PURE__ */
|
|
2715
|
+
return /* @__PURE__ */ jsx25("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ jsx25("span", { children: message ?? "Carregando..." }) });
|
|
2752
2716
|
}
|
|
2753
2717
|
|
|
2754
2718
|
// src/defaults/EmptyState.tsx
|
|
2755
|
-
import { jsx as
|
|
2719
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2756
2720
|
function EmptyState({ title, description, action }) {
|
|
2757
|
-
return /* @__PURE__ */
|
|
2758
|
-
/* @__PURE__ */
|
|
2759
|
-
description && /* @__PURE__ */
|
|
2760
|
-
action && /* @__PURE__ */
|
|
2721
|
+
return /* @__PURE__ */ jsxs17("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2722
|
+
/* @__PURE__ */ jsx26("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2723
|
+
description && /* @__PURE__ */ jsx26("p", { style: { opacity: 0.7 }, children: description }),
|
|
2724
|
+
action && /* @__PURE__ */ jsx26("div", { style: { marginTop: 16 }, children: action })
|
|
2761
2725
|
] });
|
|
2762
2726
|
}
|
|
2763
2727
|
|
|
2764
|
-
// src/
|
|
2765
|
-
import {
|
|
2766
|
-
import {
|
|
2728
|
+
// src/defaults/CheckoutPageDefault.tsx
|
|
2729
|
+
import { useEffect as useEffect11, useMemo as useMemo5 } from "react";
|
|
2730
|
+
import { useNavigate as useNavigate2 } from "react-router-dom";
|
|
2731
|
+
|
|
2732
|
+
// src/hooks/useCheckoutForm.ts
|
|
2733
|
+
import { useCallback as useCallback6, useEffect as useEffect10, useMemo as useMemo4, useRef as useRef6, useState as useState8 } from "react";
|
|
2734
|
+
import {
|
|
2735
|
+
useHook as useHook9,
|
|
2736
|
+
EmailTakenError
|
|
2737
|
+
} from "@hook-sdk/sdk";
|
|
2767
2738
|
|
|
2768
2739
|
// src/errors.ts
|
|
2769
|
-
import { SdkError, SdkAuthError, SdkRateLimitError
|
|
2740
|
+
import { SdkError, SdkAuthError, SdkRateLimitError } from "@hook-sdk/sdk";
|
|
2770
2741
|
function mapSdkError(err) {
|
|
2771
2742
|
if (err instanceof SdkRateLimitError) {
|
|
2772
2743
|
return {
|
|
@@ -2785,9 +2756,6 @@ function mapSdkError(err) {
|
|
|
2785
2756
|
}
|
|
2786
2757
|
return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
|
|
2787
2758
|
}
|
|
2788
|
-
if (err instanceof SdkValidationError && err.code === "auth.email_taken") {
|
|
2789
|
-
return { code: "email_taken", message: "Esse e-mail j\xE1 tem conta." };
|
|
2790
|
-
}
|
|
2791
2759
|
if (err instanceof SdkError && err.httpStatus === 0) {
|
|
2792
2760
|
return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
|
|
2793
2761
|
}
|
|
@@ -2797,24 +2765,597 @@ function mapSdkError(err) {
|
|
|
2797
2765
|
return { code: "server", message: "Algo deu errado. Tente novamente em instantes." };
|
|
2798
2766
|
}
|
|
2799
2767
|
|
|
2800
|
-
// src/hooks/
|
|
2768
|
+
// src/hooks/useCheckoutForm.ts
|
|
2801
2769
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2802
|
-
var
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
const
|
|
2806
|
-
const [
|
|
2807
|
-
const [
|
|
2808
|
-
const [
|
|
2809
|
-
const [
|
|
2810
|
-
const [
|
|
2811
|
-
const [
|
|
2770
|
+
var PHONE_RE = /^[0-9()+\-\s]{8,20}$/;
|
|
2771
|
+
var CHECK_DEBOUNCE_MS = 400;
|
|
2772
|
+
function useCheckoutForm(args) {
|
|
2773
|
+
const { auth } = useHook9();
|
|
2774
|
+
const [name, setName] = useState8("");
|
|
2775
|
+
const [email, setEmail] = useState8("");
|
|
2776
|
+
const [emailConfirm, setEmailConfirm] = useState8("");
|
|
2777
|
+
const [phone, setPhone] = useState8("");
|
|
2778
|
+
const [cpf, setCpf] = useState8("");
|
|
2779
|
+
const [method, setMethod] = useState8(args.defaultMethod);
|
|
2780
|
+
const [cycle, setCycle] = useState8(args.defaultCycle);
|
|
2781
|
+
const [card, setCardState] = useState8({
|
|
2782
|
+
number: "",
|
|
2783
|
+
expiryMonth: "",
|
|
2784
|
+
expiryYear: "",
|
|
2785
|
+
ccv: "",
|
|
2786
|
+
holderName: ""
|
|
2787
|
+
});
|
|
2788
|
+
const setCard = useCallback6((patch) => {
|
|
2789
|
+
setCardState((prev) => ({ ...prev, ...patch }));
|
|
2790
|
+
}, []);
|
|
2791
|
+
const [touchedName, setTouchedName] = useState8(false);
|
|
2792
|
+
const [touchedEmail, setTouchedEmail] = useState8(false);
|
|
2793
|
+
const [touchedEmailConfirm, setTouchedEmailConfirm] = useState8(false);
|
|
2794
|
+
const [touchedPhone, setTouchedPhone] = useState8(false);
|
|
2795
|
+
const [touchedCpf, setTouchedCpf] = useState8(false);
|
|
2796
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = useState8(false);
|
|
2797
|
+
const [submitting, setSubmitting] = useState8(false);
|
|
2798
|
+
const [error, setError] = useState8(null);
|
|
2799
|
+
const [emailTaken, setEmailTaken] = useState8(false);
|
|
2800
|
+
const [loginUrl, setLoginUrl] = useState8(null);
|
|
2801
|
+
const [emailStatus, setEmailStatus] = useState8("idle");
|
|
2802
|
+
const lastCheckedEmail = useRef6("");
|
|
2803
|
+
useEffect10(() => {
|
|
2804
|
+
if (!email || !EMAIL_RE.test(email)) {
|
|
2805
|
+
setEmailStatus("idle");
|
|
2806
|
+
return;
|
|
2807
|
+
}
|
|
2808
|
+
if (email === lastCheckedEmail.current) return;
|
|
2809
|
+
const timer = setTimeout(async () => {
|
|
2810
|
+
setEmailStatus("checking");
|
|
2811
|
+
try {
|
|
2812
|
+
const result = await auth.checkEmailExists({ email });
|
|
2813
|
+
lastCheckedEmail.current = email;
|
|
2814
|
+
setEmailStatus(result.exists ? "exists" : "available");
|
|
2815
|
+
} catch {
|
|
2816
|
+
setEmailStatus("idle");
|
|
2817
|
+
}
|
|
2818
|
+
}, CHECK_DEBOUNCE_MS);
|
|
2819
|
+
return () => clearTimeout(timer);
|
|
2820
|
+
}, [email, auth]);
|
|
2821
|
+
const validateName = useMemo4(() => {
|
|
2822
|
+
if (name.length === 0) return null;
|
|
2823
|
+
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2824
|
+
return null;
|
|
2825
|
+
}, [name]);
|
|
2812
2826
|
const validateEmail = useMemo4(() => {
|
|
2813
2827
|
if (email.length === 0) return null;
|
|
2814
2828
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2815
2829
|
return null;
|
|
2816
2830
|
}, [email]);
|
|
2817
|
-
const
|
|
2831
|
+
const validateEmailConfirm = useMemo4(() => {
|
|
2832
|
+
if (emailConfirm.length === 0) return null;
|
|
2833
|
+
if (emailConfirm !== email) return "Os e-mails n\xE3o coincidem.";
|
|
2834
|
+
return null;
|
|
2835
|
+
}, [emailConfirm, email]);
|
|
2836
|
+
const validatePhone = useMemo4(() => {
|
|
2837
|
+
if (phone.length === 0) return null;
|
|
2838
|
+
if (!PHONE_RE.test(phone)) return "Telefone inv\xE1lido.";
|
|
2839
|
+
return null;
|
|
2840
|
+
}, [phone]);
|
|
2841
|
+
const validateCpf = useMemo4(() => {
|
|
2842
|
+
if (cpf.length === 0) return null;
|
|
2843
|
+
const digits = cpf.replace(/\D/g, "");
|
|
2844
|
+
if (digits.length !== 11) return "CPF deve ter 11 d\xEDgitos.";
|
|
2845
|
+
if (/^(\d)\1+$/.test(digits)) return "CPF inv\xE1lido.";
|
|
2846
|
+
const ok = mod11(digits, 9) === digits[9] && mod11(digits, 10) === digits[10];
|
|
2847
|
+
return ok ? null : "CPF inv\xE1lido.";
|
|
2848
|
+
}, [cpf]);
|
|
2849
|
+
const nameError = touchedName || formSubmitAttempted ? validateName : null;
|
|
2850
|
+
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2851
|
+
const emailConfirmError = touchedEmailConfirm || formSubmitAttempted ? validateEmailConfirm : null;
|
|
2852
|
+
const phoneError = touchedPhone || formSubmitAttempted ? validatePhone : null;
|
|
2853
|
+
const cpfError = touchedCpf || formSubmitAttempted ? validateCpf : null;
|
|
2854
|
+
const canSubmit = name.trim().length >= 2 && EMAIL_RE.test(email) && emailConfirm === email && PHONE_RE.test(phone) && validateCpf === null && cpf.replace(/\D/g, "").length === 11 && emailStatus !== "exists" && !submitting && (method !== "card" || card.number.length >= 12 && card.ccv.length >= 3 && card.expiryMonth.length >= 1 && card.expiryYear.length >= 2 && card.holderName.length >= 1);
|
|
2855
|
+
const submit = useCallback6(async () => {
|
|
2856
|
+
setFormSubmitAttempted(true);
|
|
2857
|
+
setError(null);
|
|
2858
|
+
setEmailTaken(false);
|
|
2859
|
+
setLoginUrl(null);
|
|
2860
|
+
if (!canSubmit) return null;
|
|
2861
|
+
setSubmitting(true);
|
|
2862
|
+
try {
|
|
2863
|
+
let args2;
|
|
2864
|
+
if (method === "card") {
|
|
2865
|
+
args2 = {
|
|
2866
|
+
method: "card",
|
|
2867
|
+
name: name.trim(),
|
|
2868
|
+
email,
|
|
2869
|
+
emailConfirm,
|
|
2870
|
+
phone,
|
|
2871
|
+
cpf: cpf.replace(/\D/g, ""),
|
|
2872
|
+
cycle,
|
|
2873
|
+
card: {
|
|
2874
|
+
number: card.number.replace(/\s/g, ""),
|
|
2875
|
+
expiryMonth: card.expiryMonth,
|
|
2876
|
+
expiryYear: card.expiryYear,
|
|
2877
|
+
ccv: card.ccv,
|
|
2878
|
+
holderName: card.holderName
|
|
2879
|
+
},
|
|
2880
|
+
cardHolderInfo: {
|
|
2881
|
+
name: card.holderName || name.trim(),
|
|
2882
|
+
email,
|
|
2883
|
+
cpfCnpj: cpf.replace(/\D/g, ""),
|
|
2884
|
+
// Empty postal/address: backend defaults if Asaas requires.
|
|
2885
|
+
// Apps that need full address should override via custom form.
|
|
2886
|
+
postalCode: "00000000",
|
|
2887
|
+
addressNumber: "0",
|
|
2888
|
+
phone
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
} else {
|
|
2892
|
+
args2 = {
|
|
2893
|
+
method: "pix-auto",
|
|
2894
|
+
name: name.trim(),
|
|
2895
|
+
email,
|
|
2896
|
+
emailConfirm,
|
|
2897
|
+
phone,
|
|
2898
|
+
cpf: cpf.replace(/\D/g, ""),
|
|
2899
|
+
cycle
|
|
2900
|
+
};
|
|
2901
|
+
}
|
|
2902
|
+
const result = await auth.subscribeAnonymous(args2);
|
|
2903
|
+
return result;
|
|
2904
|
+
} catch (err) {
|
|
2905
|
+
if (err instanceof EmailTakenError) {
|
|
2906
|
+
setEmailTaken(true);
|
|
2907
|
+
setLoginUrl(err.loginUrl);
|
|
2908
|
+
setEmailStatus("exists");
|
|
2909
|
+
return null;
|
|
2910
|
+
}
|
|
2911
|
+
setError(mapSdkError(err));
|
|
2912
|
+
return null;
|
|
2913
|
+
} finally {
|
|
2914
|
+
setSubmitting(false);
|
|
2915
|
+
}
|
|
2916
|
+
}, [auth, canSubmit, method, cycle, name, email, emailConfirm, phone, cpf, card]);
|
|
2917
|
+
return {
|
|
2918
|
+
name,
|
|
2919
|
+
setName,
|
|
2920
|
+
email,
|
|
2921
|
+
setEmail,
|
|
2922
|
+
emailConfirm,
|
|
2923
|
+
setEmailConfirm,
|
|
2924
|
+
phone,
|
|
2925
|
+
setPhone,
|
|
2926
|
+
cpf,
|
|
2927
|
+
setCpf,
|
|
2928
|
+
method,
|
|
2929
|
+
setMethod,
|
|
2930
|
+
cycle,
|
|
2931
|
+
setCycle,
|
|
2932
|
+
card,
|
|
2933
|
+
setCard,
|
|
2934
|
+
nameError,
|
|
2935
|
+
emailError,
|
|
2936
|
+
emailConfirmError,
|
|
2937
|
+
phoneError,
|
|
2938
|
+
cpfError,
|
|
2939
|
+
markNameTouched: () => setTouchedName(true),
|
|
2940
|
+
markEmailTouched: () => setTouchedEmail(true),
|
|
2941
|
+
markEmailConfirmTouched: () => setTouchedEmailConfirm(true),
|
|
2942
|
+
markPhoneTouched: () => setTouchedPhone(true),
|
|
2943
|
+
markCpfTouched: () => setTouchedCpf(true),
|
|
2944
|
+
emailStatus,
|
|
2945
|
+
submit,
|
|
2946
|
+
submitting,
|
|
2947
|
+
canSubmit,
|
|
2948
|
+
formSubmitAttempted,
|
|
2949
|
+
error,
|
|
2950
|
+
emailTaken,
|
|
2951
|
+
loginUrl
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
function mod11(digits, len) {
|
|
2955
|
+
let sum = 0;
|
|
2956
|
+
for (let i = 0; i < len; i++) sum += parseInt(digits.charAt(i), 10) * (len + 1 - i);
|
|
2957
|
+
const r = sum * 10 % 11;
|
|
2958
|
+
return String(r === 10 ? 0 : r);
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2961
|
+
// src/hooks/usePlan.ts
|
|
2962
|
+
import { useHook as useHook10 } from "@hook-sdk/sdk";
|
|
2963
|
+
function usePlan() {
|
|
2964
|
+
const { plan } = useHook10();
|
|
2965
|
+
return plan;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
// src/defaults/CheckoutPageDefault.tsx
|
|
2969
|
+
import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2970
|
+
var INTENT_KEY = "hook:paywall:intent";
|
|
2971
|
+
var PIX_PAYLOAD_KEY = "hook:paywall:pix-pending";
|
|
2972
|
+
function readIntent() {
|
|
2973
|
+
if (typeof window === "undefined") return {};
|
|
2974
|
+
try {
|
|
2975
|
+
const raw = sessionStorage.getItem(INTENT_KEY);
|
|
2976
|
+
if (!raw) return {};
|
|
2977
|
+
return JSON.parse(raw);
|
|
2978
|
+
} catch {
|
|
2979
|
+
return {};
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
function formatBrl(cents) {
|
|
2983
|
+
return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(cents / 100);
|
|
2984
|
+
}
|
|
2985
|
+
function CheckoutPageDefault() {
|
|
2986
|
+
const navigate = useNavigate2();
|
|
2987
|
+
const plan = usePlan();
|
|
2988
|
+
const intent = useMemo5(readIntent, []);
|
|
2989
|
+
const defaultMethod = intent.method === "pix-auto" ? "pix-auto" : "card";
|
|
2990
|
+
const defaultCycle = intent.cycle === "YEARLY" ? "YEARLY" : "MONTHLY";
|
|
2991
|
+
const form = useCheckoutForm({ defaultMethod, defaultCycle });
|
|
2992
|
+
useEffect11(() => {
|
|
2993
|
+
if (form.emailTaken && form.loginUrl) {
|
|
2994
|
+
const t = setTimeout(() => navigate(form.loginUrl), 1200);
|
|
2995
|
+
return () => clearTimeout(t);
|
|
2996
|
+
}
|
|
2997
|
+
}, [form.emailTaken, form.loginUrl, navigate]);
|
|
2998
|
+
const planInfo = plan.data ? {
|
|
2999
|
+
priceCents: plan.data.priceCents,
|
|
3000
|
+
yearlyPriceCents: plan.data.yearlyPriceCents,
|
|
3001
|
+
trialDays: plan.data.trialDays
|
|
3002
|
+
} : null;
|
|
3003
|
+
const cyclePrice = useMemo5(() => {
|
|
3004
|
+
if (!planInfo) return null;
|
|
3005
|
+
return form.cycle === "YEARLY" ? planInfo.yearlyPriceCents ?? planInfo.priceCents * 12 : planInfo.priceCents;
|
|
3006
|
+
}, [planInfo, form.cycle]);
|
|
3007
|
+
const submitLabel = useMemo5(() => {
|
|
3008
|
+
if (form.submitting) return "Processando\u2026";
|
|
3009
|
+
if (form.method === "card") {
|
|
3010
|
+
const trial = planInfo?.trialDays ?? 0;
|
|
3011
|
+
if (trial > 0 && cyclePrice) {
|
|
3012
|
+
return `Come\xE7ar ${trial} dias gr\xE1tis \xB7 ${formatBrl(cyclePrice)} depois`;
|
|
3013
|
+
}
|
|
3014
|
+
return cyclePrice ? `Pagar ${formatBrl(cyclePrice)}` : "Continuar";
|
|
3015
|
+
}
|
|
3016
|
+
return cyclePrice ? `Pagar ${formatBrl(cyclePrice)} via PIX` : "Continuar via PIX";
|
|
3017
|
+
}, [form.method, form.submitting, planInfo, cyclePrice]);
|
|
3018
|
+
async function onSubmit(e) {
|
|
3019
|
+
e.preventDefault();
|
|
3020
|
+
const result = await form.submit();
|
|
3021
|
+
if (!result) return;
|
|
3022
|
+
if (form.method === "pix-auto" && result.pix_qr_payload) {
|
|
3023
|
+
try {
|
|
3024
|
+
sessionStorage.setItem(
|
|
3025
|
+
PIX_PAYLOAD_KEY,
|
|
3026
|
+
JSON.stringify({
|
|
3027
|
+
payload: result.pix_qr_payload,
|
|
3028
|
+
base64: result.pix_qr_base64 ?? null,
|
|
3029
|
+
subscriptionId: result.subscription_id,
|
|
3030
|
+
pixAuthorizationId: result.pix_authorization_id ?? null
|
|
3031
|
+
})
|
|
3032
|
+
);
|
|
3033
|
+
} catch {
|
|
3034
|
+
}
|
|
3035
|
+
navigate(result.redirect.replace(/^.*\/app\/[^/]+/, ""));
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
navigate(result.redirect.replace(/^.*\/app\/[^/]+/, "") || "/");
|
|
3039
|
+
}
|
|
3040
|
+
return /* @__PURE__ */ jsx27("div", { className: "flex-1 flex flex-col bg-background min-h-0", children: /* @__PURE__ */ jsxs18("form", { onSubmit, className: "flex-1 overflow-y-auto px-5 py-6 space-y-6", children: [
|
|
3041
|
+
/* @__PURE__ */ jsxs18("header", { className: "space-y-2", children: [
|
|
3042
|
+
/* @__PURE__ */ jsx27("h1", { className: "font-display text-2xl text-foreground", children: "Finalizar assinatura" }),
|
|
3043
|
+
/* @__PURE__ */ jsx27("p", { className: "text-sm text-muted-foreground", children: "Preencha seus dados pra liberar o app. Voc\xEA j\xE1 entra com acesso na hora." })
|
|
3044
|
+
] }),
|
|
3045
|
+
form.emailTaken ? /* @__PURE__ */ jsxs18("div", { role: "alert", className: "rounded-xl bg-destructive/10 p-4 text-sm text-destructive border border-destructive/20", children: [
|
|
3046
|
+
"Esse e-mail j\xE1 tem conta nesse app.",
|
|
3047
|
+
" ",
|
|
3048
|
+
/* @__PURE__ */ jsx27("a", { href: form.loginUrl ?? "/signin", className: "underline font-medium", children: "Entrar agora" })
|
|
3049
|
+
] }) : null,
|
|
3050
|
+
form.error ? /* @__PURE__ */ jsx27("div", { role: "alert", className: "rounded-xl bg-destructive/10 p-4 text-sm text-destructive border border-destructive/20", children: form.error.message || "N\xE3o foi poss\xEDvel concluir o pagamento. Tente novamente." }) : null,
|
|
3051
|
+
/* @__PURE__ */ jsxs18("section", { className: "space-y-3", children: [
|
|
3052
|
+
/* @__PURE__ */ jsx27("h2", { className: "text-sm font-semibold text-foreground uppercase tracking-wide", children: "Voc\xEA" }),
|
|
3053
|
+
/* @__PURE__ */ jsx27(
|
|
3054
|
+
FieldRow,
|
|
3055
|
+
{
|
|
3056
|
+
label: "Nome completo",
|
|
3057
|
+
value: form.name,
|
|
3058
|
+
onChange: form.setName,
|
|
3059
|
+
onBlur: form.markNameTouched,
|
|
3060
|
+
error: form.nameError,
|
|
3061
|
+
autoComplete: "name"
|
|
3062
|
+
}
|
|
3063
|
+
),
|
|
3064
|
+
/* @__PURE__ */ jsx27(
|
|
3065
|
+
FieldRow,
|
|
3066
|
+
{
|
|
3067
|
+
label: "E-mail",
|
|
3068
|
+
type: "email",
|
|
3069
|
+
value: form.email,
|
|
3070
|
+
onChange: form.setEmail,
|
|
3071
|
+
onBlur: form.markEmailTouched,
|
|
3072
|
+
error: form.emailError,
|
|
3073
|
+
autoComplete: "email",
|
|
3074
|
+
autoCapitalize: "none",
|
|
3075
|
+
autoCorrect: "off",
|
|
3076
|
+
spellCheck: false,
|
|
3077
|
+
hint: form.emailStatus === "checking" ? "Verificando\u2026" : form.emailStatus === "available" ? "\u2713 Dispon\xEDvel" : form.emailStatus === "exists" ? null : null
|
|
3078
|
+
}
|
|
3079
|
+
),
|
|
3080
|
+
/* @__PURE__ */ jsx27(
|
|
3081
|
+
FieldRow,
|
|
3082
|
+
{
|
|
3083
|
+
label: "Confirme o e-mail",
|
|
3084
|
+
type: "email",
|
|
3085
|
+
value: form.emailConfirm,
|
|
3086
|
+
onChange: form.setEmailConfirm,
|
|
3087
|
+
onBlur: form.markEmailConfirmTouched,
|
|
3088
|
+
error: form.emailConfirmError,
|
|
3089
|
+
autoComplete: "email",
|
|
3090
|
+
autoCapitalize: "none",
|
|
3091
|
+
autoCorrect: "off",
|
|
3092
|
+
spellCheck: false
|
|
3093
|
+
}
|
|
3094
|
+
),
|
|
3095
|
+
/* @__PURE__ */ jsx27(
|
|
3096
|
+
FieldRow,
|
|
3097
|
+
{
|
|
3098
|
+
label: "Telefone",
|
|
3099
|
+
type: "tel",
|
|
3100
|
+
value: form.phone,
|
|
3101
|
+
onChange: form.setPhone,
|
|
3102
|
+
onBlur: form.markPhoneTouched,
|
|
3103
|
+
error: form.phoneError,
|
|
3104
|
+
autoComplete: "tel",
|
|
3105
|
+
placeholder: "(11) 99999-9999"
|
|
3106
|
+
}
|
|
3107
|
+
),
|
|
3108
|
+
/* @__PURE__ */ jsx27(
|
|
3109
|
+
FieldRow,
|
|
3110
|
+
{
|
|
3111
|
+
label: "CPF",
|
|
3112
|
+
type: "text",
|
|
3113
|
+
inputMode: "numeric",
|
|
3114
|
+
value: form.cpf,
|
|
3115
|
+
onChange: form.setCpf,
|
|
3116
|
+
onBlur: form.markCpfTouched,
|
|
3117
|
+
error: form.cpfError,
|
|
3118
|
+
autoComplete: "off",
|
|
3119
|
+
placeholder: "000.000.000-00"
|
|
3120
|
+
}
|
|
3121
|
+
)
|
|
3122
|
+
] }),
|
|
3123
|
+
/* @__PURE__ */ jsxs18("section", { className: "space-y-3", children: [
|
|
3124
|
+
/* @__PURE__ */ jsx27("h2", { className: "text-sm font-semibold text-foreground uppercase tracking-wide", children: "Pagamento" }),
|
|
3125
|
+
/* @__PURE__ */ jsxs18("div", { className: "grid grid-cols-2 gap-2", role: "tablist", children: [
|
|
3126
|
+
/* @__PURE__ */ jsx27(MethodTab, { active: form.method === "card", onClick: () => form.setMethod("card"), children: "Cart\xE3o" }),
|
|
3127
|
+
/* @__PURE__ */ jsx27(MethodTab, { active: form.method === "pix-auto", onClick: () => form.setMethod("pix-auto"), children: "PIX" })
|
|
3128
|
+
] }),
|
|
3129
|
+
/* @__PURE__ */ jsxs18("div", { className: "grid grid-cols-2 gap-2", role: "tablist", children: [
|
|
3130
|
+
/* @__PURE__ */ jsx27(MethodTab, { active: form.cycle === "MONTHLY", onClick: () => form.setCycle("MONTHLY"), children: "Mensal" }),
|
|
3131
|
+
/* @__PURE__ */ jsx27(MethodTab, { active: form.cycle === "YEARLY", onClick: () => form.setCycle("YEARLY"), children: "Anual" })
|
|
3132
|
+
] }),
|
|
3133
|
+
form.method === "card" ? /* @__PURE__ */ jsxs18("div", { className: "space-y-3 rounded-xl border border-border p-4", children: [
|
|
3134
|
+
/* @__PURE__ */ jsx27(
|
|
3135
|
+
FieldRow,
|
|
3136
|
+
{
|
|
3137
|
+
label: "Nome no cart\xE3o",
|
|
3138
|
+
value: form.card.holderName,
|
|
3139
|
+
onChange: (v) => form.setCard({ holderName: v }),
|
|
3140
|
+
autoComplete: "cc-name"
|
|
3141
|
+
}
|
|
3142
|
+
),
|
|
3143
|
+
/* @__PURE__ */ jsx27(
|
|
3144
|
+
FieldRow,
|
|
3145
|
+
{
|
|
3146
|
+
label: "N\xFAmero",
|
|
3147
|
+
value: form.card.number,
|
|
3148
|
+
onChange: (v) => form.setCard({ number: v }),
|
|
3149
|
+
autoComplete: "cc-number",
|
|
3150
|
+
inputMode: "numeric",
|
|
3151
|
+
placeholder: "0000 0000 0000 0000"
|
|
3152
|
+
}
|
|
3153
|
+
),
|
|
3154
|
+
/* @__PURE__ */ jsxs18("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
3155
|
+
/* @__PURE__ */ jsx27(
|
|
3156
|
+
FieldRow,
|
|
3157
|
+
{
|
|
3158
|
+
label: "M\xEAs",
|
|
3159
|
+
value: form.card.expiryMonth,
|
|
3160
|
+
onChange: (v) => form.setCard({ expiryMonth: v }),
|
|
3161
|
+
autoComplete: "cc-exp-month",
|
|
3162
|
+
inputMode: "numeric",
|
|
3163
|
+
placeholder: "MM"
|
|
3164
|
+
}
|
|
3165
|
+
),
|
|
3166
|
+
/* @__PURE__ */ jsx27(
|
|
3167
|
+
FieldRow,
|
|
3168
|
+
{
|
|
3169
|
+
label: "Ano",
|
|
3170
|
+
value: form.card.expiryYear,
|
|
3171
|
+
onChange: (v) => form.setCard({ expiryYear: v }),
|
|
3172
|
+
autoComplete: "cc-exp-year",
|
|
3173
|
+
inputMode: "numeric",
|
|
3174
|
+
placeholder: "AA"
|
|
3175
|
+
}
|
|
3176
|
+
),
|
|
3177
|
+
/* @__PURE__ */ jsx27(
|
|
3178
|
+
FieldRow,
|
|
3179
|
+
{
|
|
3180
|
+
label: "CVV",
|
|
3181
|
+
value: form.card.ccv,
|
|
3182
|
+
onChange: (v) => form.setCard({ ccv: v }),
|
|
3183
|
+
autoComplete: "cc-csc",
|
|
3184
|
+
inputMode: "numeric",
|
|
3185
|
+
placeholder: "123"
|
|
3186
|
+
}
|
|
3187
|
+
)
|
|
3188
|
+
] })
|
|
3189
|
+
] }) : /* @__PURE__ */ jsx27("div", { className: "rounded-xl border border-border p-4 text-sm text-muted-foreground", children: "Ap\xF3s confirmar, mostraremos o QR Code PIX. Pagamento \xE0 vista." })
|
|
3190
|
+
] }),
|
|
3191
|
+
/* @__PURE__ */ jsx27(
|
|
3192
|
+
"button",
|
|
3193
|
+
{
|
|
3194
|
+
type: "submit",
|
|
3195
|
+
disabled: !form.canSubmit,
|
|
3196
|
+
className: "w-full rounded-xl bg-primary py-4 text-base font-semibold text-primary-foreground disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3197
|
+
children: submitLabel
|
|
3198
|
+
}
|
|
3199
|
+
),
|
|
3200
|
+
/* @__PURE__ */ jsx27("p", { className: "text-center text-xs text-muted-foreground", children: "\u{1F512} SSL \xB7 via Asaas \xB7 Garantia 7 dias" })
|
|
3201
|
+
] }) });
|
|
3202
|
+
}
|
|
3203
|
+
function FieldRow(props) {
|
|
3204
|
+
return /* @__PURE__ */ jsxs18("label", { className: "block space-y-1", children: [
|
|
3205
|
+
/* @__PURE__ */ jsx27("span", { className: "block text-sm font-medium text-foreground", children: props.label }),
|
|
3206
|
+
/* @__PURE__ */ jsx27(
|
|
3207
|
+
"input",
|
|
3208
|
+
{
|
|
3209
|
+
type: props.type ?? "text",
|
|
3210
|
+
value: props.value,
|
|
3211
|
+
onChange: (e) => props.onChange(e.target.value),
|
|
3212
|
+
onBlur: props.onBlur,
|
|
3213
|
+
autoComplete: props.autoComplete,
|
|
3214
|
+
autoCapitalize: props.autoCapitalize,
|
|
3215
|
+
autoCorrect: props.autoCorrect,
|
|
3216
|
+
spellCheck: props.spellCheck,
|
|
3217
|
+
inputMode: props.inputMode,
|
|
3218
|
+
placeholder: props.placeholder,
|
|
3219
|
+
className: `w-full rounded-xl border bg-card px-3 py-2 text-base text-foreground outline-none focus:ring-2 focus:ring-primary ${props.error ? "border-destructive" : "border-border"}`
|
|
3220
|
+
}
|
|
3221
|
+
),
|
|
3222
|
+
props.error ? /* @__PURE__ */ jsx27("span", { className: "block text-xs text-destructive", children: props.error }) : props.hint ? /* @__PURE__ */ jsx27("span", { className: "block text-xs text-muted-foreground", children: props.hint }) : null
|
|
3223
|
+
] });
|
|
3224
|
+
}
|
|
3225
|
+
function MethodTab({ active, onClick, children }) {
|
|
3226
|
+
return /* @__PURE__ */ jsx27(
|
|
3227
|
+
"button",
|
|
3228
|
+
{
|
|
3229
|
+
type: "button",
|
|
3230
|
+
role: "tab",
|
|
3231
|
+
"aria-selected": active,
|
|
3232
|
+
onClick,
|
|
3233
|
+
className: `rounded-xl border px-4 py-2 text-sm font-medium transition ${active ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-foreground"}`,
|
|
3234
|
+
children
|
|
3235
|
+
}
|
|
3236
|
+
);
|
|
3237
|
+
}
|
|
3238
|
+
|
|
3239
|
+
// src/defaults/PixWaitingPageDefault.tsx
|
|
3240
|
+
import { useEffect as useEffect12, useMemo as useMemo6, useState as useState9 } from "react";
|
|
3241
|
+
import { useNavigate as useNavigate3 } from "react-router-dom";
|
|
3242
|
+
import { useHook as useHook11 } from "@hook-sdk/sdk";
|
|
3243
|
+
import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3244
|
+
var PIX_PAYLOAD_KEY2 = "hook:paywall:pix-pending";
|
|
3245
|
+
var TIMEOUT_MS = 30 * 60 * 1e3;
|
|
3246
|
+
function readPixPayload() {
|
|
3247
|
+
if (typeof window === "undefined") return null;
|
|
3248
|
+
try {
|
|
3249
|
+
const raw = sessionStorage.getItem(PIX_PAYLOAD_KEY2);
|
|
3250
|
+
if (!raw) return null;
|
|
3251
|
+
return JSON.parse(raw);
|
|
3252
|
+
} catch {
|
|
3253
|
+
return null;
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
function clearPixPayload() {
|
|
3257
|
+
if (typeof window === "undefined") return;
|
|
3258
|
+
try {
|
|
3259
|
+
sessionStorage.removeItem(PIX_PAYLOAD_KEY2);
|
|
3260
|
+
} catch {
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
function PixWaitingPageDefault() {
|
|
3264
|
+
const navigate = useNavigate3();
|
|
3265
|
+
const { subscription } = useHook11();
|
|
3266
|
+
const payload = useMemo6(readPixPayload, []);
|
|
3267
|
+
const [copied, setCopied] = useState9(false);
|
|
3268
|
+
const [timedOut, setTimedOut] = useState9(false);
|
|
3269
|
+
useEffect12(() => {
|
|
3270
|
+
if (!payload) navigate("/paywall/checkout", { replace: true });
|
|
3271
|
+
}, [payload, navigate]);
|
|
3272
|
+
useEffect12(() => {
|
|
3273
|
+
const t = setTimeout(() => setTimedOut(true), TIMEOUT_MS);
|
|
3274
|
+
return () => clearTimeout(t);
|
|
3275
|
+
}, []);
|
|
3276
|
+
const hasAccess = subscription.hasAccess;
|
|
3277
|
+
useEffect12(() => {
|
|
3278
|
+
if (hasAccess) {
|
|
3279
|
+
clearPixPayload();
|
|
3280
|
+
navigate("/", { replace: true });
|
|
3281
|
+
}
|
|
3282
|
+
}, [hasAccess, navigate]);
|
|
3283
|
+
async function copyPayload() {
|
|
3284
|
+
if (!payload?.payload) return;
|
|
3285
|
+
try {
|
|
3286
|
+
await navigator.clipboard.writeText(payload.payload);
|
|
3287
|
+
setCopied(true);
|
|
3288
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
3289
|
+
} catch {
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
if (!payload) return null;
|
|
3293
|
+
if (timedOut) {
|
|
3294
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex-1 flex flex-col items-center justify-center px-6 py-10 text-center bg-background space-y-4", children: [
|
|
3295
|
+
/* @__PURE__ */ jsx28("h1", { className: "font-display text-2xl text-foreground", children: "PIX expirado" }),
|
|
3296
|
+
/* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: "O tempo pra pagar acabou. Gere um novo PIX." }),
|
|
3297
|
+
/* @__PURE__ */ jsx28(
|
|
3298
|
+
"button",
|
|
3299
|
+
{
|
|
3300
|
+
onClick: () => {
|
|
3301
|
+
clearPixPayload();
|
|
3302
|
+
navigate("/paywall/checkout", { replace: true });
|
|
3303
|
+
},
|
|
3304
|
+
className: "rounded-xl bg-primary px-6 py-3 text-base font-semibold text-primary-foreground",
|
|
3305
|
+
children: "Tentar novamente"
|
|
3306
|
+
}
|
|
3307
|
+
)
|
|
3308
|
+
] });
|
|
3309
|
+
}
|
|
3310
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex-1 flex flex-col items-center px-6 py-8 bg-background space-y-6", children: [
|
|
3311
|
+
/* @__PURE__ */ jsxs19("header", { className: "text-center space-y-2", children: [
|
|
3312
|
+
/* @__PURE__ */ jsx28("h1", { className: "font-display text-2xl text-foreground", children: "Pague o PIX" }),
|
|
3313
|
+
/* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: "Escaneie o QR Code no app do seu banco. O acesso libera assim que confirmarmos o pagamento." })
|
|
3314
|
+
] }),
|
|
3315
|
+
payload.base64 ? /* @__PURE__ */ jsx28(
|
|
3316
|
+
"img",
|
|
3317
|
+
{
|
|
3318
|
+
src: `data:image/png;base64,${payload.base64}`,
|
|
3319
|
+
alt: "QR Code PIX",
|
|
3320
|
+
className: "w-64 h-64 rounded-2xl border border-border bg-card p-2"
|
|
3321
|
+
}
|
|
3322
|
+
) : /* @__PURE__ */ jsx28("div", { className: "w-64 h-64 rounded-2xl border border-border bg-card flex items-center justify-center text-sm text-muted-foreground", children: "QR indispon\xEDvel" }),
|
|
3323
|
+
payload.payload ? /* @__PURE__ */ jsx28(
|
|
3324
|
+
"button",
|
|
3325
|
+
{
|
|
3326
|
+
onClick: copyPayload,
|
|
3327
|
+
className: "w-full max-w-xs rounded-xl border border-border bg-card px-4 py-3 text-sm font-medium text-foreground",
|
|
3328
|
+
children: copied ? "\u2713 Copiado!" : "Copiar c\xF3digo PIX"
|
|
3329
|
+
}
|
|
3330
|
+
) : null,
|
|
3331
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
3332
|
+
/* @__PURE__ */ jsx28("span", { className: "inline-block w-2 h-2 rounded-full bg-primary animate-pulse" }),
|
|
3333
|
+
"Aguardando pagamento\u2026"
|
|
3334
|
+
] }),
|
|
3335
|
+
/* @__PURE__ */ jsx28("p", { className: "text-center text-xs text-muted-foreground", children: "Pode fechar essa janela \u2014 tamb\xE9m enviamos um link de acesso pro seu e-mail." })
|
|
3336
|
+
] });
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
// src/hooks/useLoginForm.ts
|
|
3340
|
+
import { useCallback as useCallback7, useMemo as useMemo7, useState as useState10 } from "react";
|
|
3341
|
+
import { useHook as useHook12 } from "@hook-sdk/sdk";
|
|
3342
|
+
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3343
|
+
var MIN_PASSWORD = 8;
|
|
3344
|
+
function useLoginForm() {
|
|
3345
|
+
const { auth } = useHook12();
|
|
3346
|
+
const [email, setEmail] = useState10("");
|
|
3347
|
+
const [password, setPassword] = useState10("");
|
|
3348
|
+
const [submitting, setSubmitting] = useState10(false);
|
|
3349
|
+
const [error, setError] = useState10(null);
|
|
3350
|
+
const [touchedEmail, setTouchedEmail] = useState10(false);
|
|
3351
|
+
const [touchedPassword, setTouchedPassword] = useState10(false);
|
|
3352
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = useState10(false);
|
|
3353
|
+
const validateEmail = useMemo7(() => {
|
|
3354
|
+
if (email.length === 0) return null;
|
|
3355
|
+
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
3356
|
+
return null;
|
|
3357
|
+
}, [email]);
|
|
3358
|
+
const validatePassword = useMemo7(() => {
|
|
2818
3359
|
if (password.length === 0) return null;
|
|
2819
3360
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2820
3361
|
return null;
|
|
@@ -2822,7 +3363,7 @@ function useLoginForm() {
|
|
|
2822
3363
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2823
3364
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2824
3365
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2825
|
-
const submit =
|
|
3366
|
+
const submit = useCallback7(async () => {
|
|
2826
3367
|
setFormSubmitAttempted(true);
|
|
2827
3368
|
if (!canSubmit) return false;
|
|
2828
3369
|
setSubmitting(true);
|
|
@@ -2856,32 +3397,32 @@ function useLoginForm() {
|
|
|
2856
3397
|
}
|
|
2857
3398
|
|
|
2858
3399
|
// src/hooks/useSignupForm.ts
|
|
2859
|
-
import { useCallback as
|
|
2860
|
-
import { useHook as
|
|
2861
|
-
var
|
|
3400
|
+
import { useCallback as useCallback8, useMemo as useMemo8, useState as useState11 } from "react";
|
|
3401
|
+
import { useHook as useHook13 } from "@hook-sdk/sdk";
|
|
3402
|
+
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2862
3403
|
var MIN_PASSWORD2 = 8;
|
|
2863
3404
|
function useSignupForm() {
|
|
2864
|
-
const { auth } =
|
|
2865
|
-
const [name, setName] =
|
|
2866
|
-
const [email, setEmail] =
|
|
2867
|
-
const [password, setPassword] =
|
|
2868
|
-
const [submitting, setSubmitting] =
|
|
2869
|
-
const [error, setError] =
|
|
2870
|
-
const [touchedName, setTouchedName] =
|
|
2871
|
-
const [touchedEmail, setTouchedEmail] =
|
|
2872
|
-
const [touchedPassword, setTouchedPassword] =
|
|
2873
|
-
const [formSubmitAttempted, setFormSubmitAttempted] =
|
|
2874
|
-
const validateName =
|
|
3405
|
+
const { auth } = useHook13();
|
|
3406
|
+
const [name, setName] = useState11("");
|
|
3407
|
+
const [email, setEmail] = useState11("");
|
|
3408
|
+
const [password, setPassword] = useState11("");
|
|
3409
|
+
const [submitting, setSubmitting] = useState11(false);
|
|
3410
|
+
const [error, setError] = useState11(null);
|
|
3411
|
+
const [touchedName, setTouchedName] = useState11(false);
|
|
3412
|
+
const [touchedEmail, setTouchedEmail] = useState11(false);
|
|
3413
|
+
const [touchedPassword, setTouchedPassword] = useState11(false);
|
|
3414
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = useState11(false);
|
|
3415
|
+
const validateName = useMemo8(() => {
|
|
2875
3416
|
if (name.length === 0) return null;
|
|
2876
3417
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2877
3418
|
return null;
|
|
2878
3419
|
}, [name]);
|
|
2879
|
-
const validateEmail =
|
|
3420
|
+
const validateEmail = useMemo8(() => {
|
|
2880
3421
|
if (email.length === 0) return null;
|
|
2881
|
-
if (!
|
|
3422
|
+
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2882
3423
|
return null;
|
|
2883
3424
|
}, [email]);
|
|
2884
|
-
const validatePassword =
|
|
3425
|
+
const validatePassword = useMemo8(() => {
|
|
2885
3426
|
if (password.length === 0) return null;
|
|
2886
3427
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2887
3428
|
return null;
|
|
@@ -2890,7 +3431,7 @@ function useSignupForm() {
|
|
|
2890
3431
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2891
3432
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2892
3433
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2893
|
-
const submit =
|
|
3434
|
+
const submit = useCallback8(async () => {
|
|
2894
3435
|
setFormSubmitAttempted(true);
|
|
2895
3436
|
if (!canSubmit) return false;
|
|
2896
3437
|
setSubmitting(true);
|
|
@@ -2928,25 +3469,25 @@ function useSignupForm() {
|
|
|
2928
3469
|
}
|
|
2929
3470
|
|
|
2930
3471
|
// src/hooks/useForgotForm.ts
|
|
2931
|
-
import { useCallback as
|
|
2932
|
-
import { useHook as
|
|
2933
|
-
var
|
|
3472
|
+
import { useCallback as useCallback9, useMemo as useMemo9, useState as useState12 } from "react";
|
|
3473
|
+
import { useHook as useHook14 } from "@hook-sdk/sdk";
|
|
3474
|
+
var EMAIL_RE4 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2934
3475
|
function useForgotForm() {
|
|
2935
|
-
const { auth } =
|
|
2936
|
-
const [email, setEmail] =
|
|
2937
|
-
const [submitting, setSubmitting] =
|
|
2938
|
-
const [sent, setSent] =
|
|
2939
|
-
const [error, setError] =
|
|
2940
|
-
const [touchedEmail, setTouchedEmail] =
|
|
2941
|
-
const [formSubmitAttempted, setFormSubmitAttempted] =
|
|
2942
|
-
const validateEmail =
|
|
3476
|
+
const { auth } = useHook14();
|
|
3477
|
+
const [email, setEmail] = useState12("");
|
|
3478
|
+
const [submitting, setSubmitting] = useState12(false);
|
|
3479
|
+
const [sent, setSent] = useState12(false);
|
|
3480
|
+
const [error, setError] = useState12(null);
|
|
3481
|
+
const [touchedEmail, setTouchedEmail] = useState12(false);
|
|
3482
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = useState12(false);
|
|
3483
|
+
const validateEmail = useMemo9(() => {
|
|
2943
3484
|
if (email.length === 0) return null;
|
|
2944
|
-
if (!
|
|
3485
|
+
if (!EMAIL_RE4.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2945
3486
|
return null;
|
|
2946
3487
|
}, [email]);
|
|
2947
3488
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2948
3489
|
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2949
|
-
const submit =
|
|
3490
|
+
const submit = useCallback9(async () => {
|
|
2950
3491
|
setFormSubmitAttempted(true);
|
|
2951
3492
|
if (!canSubmit) return false;
|
|
2952
3493
|
setSubmitting(true);
|
|
@@ -2977,32 +3518,32 @@ function useForgotForm() {
|
|
|
2977
3518
|
}
|
|
2978
3519
|
|
|
2979
3520
|
// src/hooks/useResetForm.ts
|
|
2980
|
-
import { useCallback as
|
|
2981
|
-
import { useHook as
|
|
2982
|
-
var MIN_PASSWORD3 =
|
|
3521
|
+
import { useCallback as useCallback10, useEffect as useEffect13, useMemo as useMemo10, useState as useState13 } from "react";
|
|
3522
|
+
import { useHook as useHook15 } from "@hook-sdk/sdk";
|
|
3523
|
+
var MIN_PASSWORD3 = 12;
|
|
2983
3524
|
function useResetForm() {
|
|
2984
|
-
const { auth } =
|
|
2985
|
-
const [token, setToken] =
|
|
2986
|
-
const [password, setPassword] =
|
|
2987
|
-
const [confirm, setConfirm] =
|
|
2988
|
-
const [submitting, setSubmitting] =
|
|
2989
|
-
const [done, setDone] =
|
|
2990
|
-
const [error, setError] =
|
|
2991
|
-
const [touchedPassword, setTouchedPassword] =
|
|
2992
|
-
const [touchedConfirm, setTouchedConfirm] =
|
|
2993
|
-
const [formSubmitAttempted, setFormSubmitAttempted] =
|
|
2994
|
-
|
|
3525
|
+
const { auth } = useHook15();
|
|
3526
|
+
const [token, setToken] = useState13(null);
|
|
3527
|
+
const [password, setPassword] = useState13("");
|
|
3528
|
+
const [confirm, setConfirm] = useState13("");
|
|
3529
|
+
const [submitting, setSubmitting] = useState13(false);
|
|
3530
|
+
const [done, setDone] = useState13(false);
|
|
3531
|
+
const [error, setError] = useState13(null);
|
|
3532
|
+
const [touchedPassword, setTouchedPassword] = useState13(false);
|
|
3533
|
+
const [touchedConfirm, setTouchedConfirm] = useState13(false);
|
|
3534
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = useState13(false);
|
|
3535
|
+
useEffect13(() => {
|
|
2995
3536
|
if (typeof window === "undefined") return;
|
|
2996
3537
|
const params = new URLSearchParams(window.location.search);
|
|
2997
3538
|
const t = params.get("token");
|
|
2998
3539
|
setToken(t && t.length > 0 ? t : null);
|
|
2999
3540
|
}, []);
|
|
3000
|
-
const validatePassword =
|
|
3541
|
+
const validatePassword = useMemo10(() => {
|
|
3001
3542
|
if (password.length === 0) return null;
|
|
3002
3543
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
3003
3544
|
return null;
|
|
3004
3545
|
}, [password]);
|
|
3005
|
-
const validateConfirm =
|
|
3546
|
+
const validateConfirm = useMemo10(() => {
|
|
3006
3547
|
if (confirm.length === 0) return null;
|
|
3007
3548
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
3008
3549
|
return null;
|
|
@@ -3010,7 +3551,7 @@ function useResetForm() {
|
|
|
3010
3551
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
3011
3552
|
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
3012
3553
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
3013
|
-
const submit =
|
|
3554
|
+
const submit = useCallback10(async () => {
|
|
3014
3555
|
setFormSubmitAttempted(true);
|
|
3015
3556
|
if (!canSubmit || token === null) return;
|
|
3016
3557
|
setSubmitting(true);
|
|
@@ -3049,13 +3590,6 @@ function useResetForm() {
|
|
|
3049
3590
|
};
|
|
3050
3591
|
}
|
|
3051
3592
|
|
|
3052
|
-
// src/hooks/usePlan.ts
|
|
3053
|
-
import { useHook as useHook14 } from "@hook-sdk/sdk";
|
|
3054
|
-
function usePlan() {
|
|
3055
|
-
const { plan } = useHook14();
|
|
3056
|
-
return plan;
|
|
3057
|
-
}
|
|
3058
|
-
|
|
3059
3593
|
// src/utils/price.ts
|
|
3060
3594
|
function formatBRL(cents) {
|
|
3061
3595
|
if (cents === null || cents === void 0) return "";
|
|
@@ -3085,12 +3619,12 @@ function discountPercent(anchorCents, realCents) {
|
|
|
3085
3619
|
}
|
|
3086
3620
|
|
|
3087
3621
|
// src/hooks/useAuthPrimitives.ts
|
|
3088
|
-
import { useEffect as
|
|
3089
|
-
import { useHook as
|
|
3622
|
+
import { useEffect as useEffect14 } from "react";
|
|
3623
|
+
import { useHook as useHook16 } from "@hook-sdk/sdk";
|
|
3090
3624
|
var warned = false;
|
|
3091
3625
|
function useAuthPrimitives() {
|
|
3092
|
-
const { auth } =
|
|
3093
|
-
|
|
3626
|
+
const { auth } = useHook16();
|
|
3627
|
+
useEffect14(() => {
|
|
3094
3628
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
3095
3629
|
warned = true;
|
|
3096
3630
|
console.warn(
|
|
@@ -3112,9 +3646,9 @@ function useAuthPrimitives() {
|
|
|
3112
3646
|
}
|
|
3113
3647
|
|
|
3114
3648
|
// src/hooks/useAuth.ts
|
|
3115
|
-
import { useHook as
|
|
3649
|
+
import { useHook as useHook17 } from "@hook-sdk/sdk";
|
|
3116
3650
|
function useAuth() {
|
|
3117
|
-
const { user, authStatus, auth } =
|
|
3651
|
+
const { user, authStatus, auth } = useHook17();
|
|
3118
3652
|
return {
|
|
3119
3653
|
user,
|
|
3120
3654
|
authStatus,
|
|
@@ -3126,23 +3660,23 @@ function useAuth() {
|
|
|
3126
3660
|
import { useTrackOnboardingStep } from "@hook-sdk/sdk";
|
|
3127
3661
|
|
|
3128
3662
|
// src/hooks/useSubscription.ts
|
|
3129
|
-
import { useHook as
|
|
3663
|
+
import { useHook as useHook18 } from "@hook-sdk/sdk";
|
|
3130
3664
|
function useSubscription() {
|
|
3131
|
-
const { subscription } =
|
|
3665
|
+
const { subscription } = useHook18();
|
|
3132
3666
|
return {
|
|
3133
3667
|
status: subscription.status()
|
|
3134
3668
|
};
|
|
3135
3669
|
}
|
|
3136
3670
|
|
|
3137
3671
|
// src/hooks/useReminders.ts
|
|
3138
|
-
import { useCallback as
|
|
3139
|
-
import { useHook as
|
|
3672
|
+
import { useCallback as useCallback11, useEffect as useEffect15, useState as useState14 } from "react";
|
|
3673
|
+
import { useHook as useHook19 } from "@hook-sdk/sdk";
|
|
3140
3674
|
function useReminders() {
|
|
3141
|
-
const { push } =
|
|
3675
|
+
const { push } = useHook19();
|
|
3142
3676
|
const r = push.reminders;
|
|
3143
|
-
const [reminders, setReminders] =
|
|
3144
|
-
const [loading, setLoading] =
|
|
3145
|
-
const reload =
|
|
3677
|
+
const [reminders, setReminders] = useState14([]);
|
|
3678
|
+
const [loading, setLoading] = useState14(true);
|
|
3679
|
+
const reload = useCallback11(async () => {
|
|
3146
3680
|
setLoading(true);
|
|
3147
3681
|
try {
|
|
3148
3682
|
const next = await r.list();
|
|
@@ -3151,38 +3685,38 @@ function useReminders() {
|
|
|
3151
3685
|
setLoading(false);
|
|
3152
3686
|
}
|
|
3153
3687
|
}, [r]);
|
|
3154
|
-
|
|
3688
|
+
useEffect15(() => {
|
|
3155
3689
|
void reload();
|
|
3156
3690
|
}, [reload]);
|
|
3157
|
-
const setReminder =
|
|
3691
|
+
const setReminder = useCallback11(async (input) => {
|
|
3158
3692
|
await r.set(input);
|
|
3159
3693
|
await reload();
|
|
3160
3694
|
}, [r, reload]);
|
|
3161
|
-
const deleteReminder =
|
|
3695
|
+
const deleteReminder = useCallback11(async (slot) => {
|
|
3162
3696
|
await r.delete(slot);
|
|
3163
3697
|
await reload();
|
|
3164
3698
|
}, [r, reload]);
|
|
3165
|
-
const schedule =
|
|
3699
|
+
const schedule = useCallback11(async (items) => {
|
|
3166
3700
|
return r.schedule(items);
|
|
3167
3701
|
}, [r]);
|
|
3168
|
-
const setFallbacks =
|
|
3702
|
+
const setFallbacks = useCallback11(async (items) => {
|
|
3169
3703
|
return r.setFallbacks(items);
|
|
3170
3704
|
}, [r]);
|
|
3171
3705
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
3172
3706
|
}
|
|
3173
3707
|
|
|
3174
3708
|
// src/hooks/useToast.ts
|
|
3175
|
-
import { useCallback as
|
|
3709
|
+
import { useCallback as useCallback12, useState as useState15 } from "react";
|
|
3176
3710
|
function useToast() {
|
|
3177
|
-
const [items, setItems] =
|
|
3178
|
-
const show =
|
|
3711
|
+
const [items, setItems] = useState15([]);
|
|
3712
|
+
const show = useCallback12((message, kind = "info") => {
|
|
3179
3713
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
3180
3714
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
3181
3715
|
setTimeout(() => {
|
|
3182
3716
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
3183
3717
|
}, 4e3);
|
|
3184
3718
|
}, []);
|
|
3185
|
-
const dismiss =
|
|
3719
|
+
const dismiss = useCallback12((id) => {
|
|
3186
3720
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
3187
3721
|
}, []);
|
|
3188
3722
|
return { items, show, dismiss };
|
|
@@ -3190,20 +3724,20 @@ function useToast() {
|
|
|
3190
3724
|
|
|
3191
3725
|
// src/RouteBoundary.tsx
|
|
3192
3726
|
import { Routes as Routes2, Route as Route2 } from "react-router-dom";
|
|
3193
|
-
import { jsx as
|
|
3727
|
+
import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3194
3728
|
function RouteBoundary({ children }) {
|
|
3195
|
-
return /* @__PURE__ */
|
|
3729
|
+
return /* @__PURE__ */ jsxs20(Routes2, { children: [
|
|
3196
3730
|
children,
|
|
3197
|
-
/* @__PURE__ */
|
|
3731
|
+
/* @__PURE__ */ jsx29(Route2, { path: "*", element: /* @__PURE__ */ jsx29(DefaultNotFound, {}) })
|
|
3198
3732
|
] });
|
|
3199
3733
|
}
|
|
3200
3734
|
function DefaultNotFound() {
|
|
3201
|
-
return /* @__PURE__ */
|
|
3735
|
+
return /* @__PURE__ */ jsx29("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
|
|
3202
3736
|
}
|
|
3203
3737
|
|
|
3204
3738
|
// src/PreAuthShell.tsx
|
|
3205
3739
|
import { BrowserRouter as BrowserRouter2, MemoryRouter as MemoryRouter2, Routes as Routes3 } from "react-router-dom";
|
|
3206
|
-
import { jsx as
|
|
3740
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
3207
3741
|
function PreAuthShell({
|
|
3208
3742
|
basename,
|
|
3209
3743
|
testRouter,
|
|
@@ -3211,14 +3745,14 @@ function PreAuthShell({
|
|
|
3211
3745
|
children
|
|
3212
3746
|
}) {
|
|
3213
3747
|
if (testRouter === "memory") {
|
|
3214
|
-
return /* @__PURE__ */
|
|
3748
|
+
return /* @__PURE__ */ jsx30(MemoryRouter2, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ jsx30(Routes3, { children }) });
|
|
3215
3749
|
}
|
|
3216
|
-
return /* @__PURE__ */
|
|
3750
|
+
return /* @__PURE__ */ jsx30(BrowserRouter2, { basename, children: /* @__PURE__ */ jsx30(Routes3, { children }) });
|
|
3217
3751
|
}
|
|
3218
3752
|
|
|
3219
3753
|
// src/OnboardingFlow.tsx
|
|
3220
|
-
import { useCallback as
|
|
3221
|
-
import { usePersistedState as usePersistedState3, useHook as
|
|
3754
|
+
import { useCallback as useCallback13, useEffect as useEffect16, useMemo as useMemo11, useRef as useRef7 } from "react";
|
|
3755
|
+
import { usePersistedState as usePersistedState3, useHook as useHook20 } from "@hook-sdk/sdk";
|
|
3222
3756
|
|
|
3223
3757
|
// src/hooks/useOnboardingStep.ts
|
|
3224
3758
|
import { createContext as createContext3, useContext as useContext4 } from "react";
|
|
@@ -3234,7 +3768,7 @@ function useOnboardingStep() {
|
|
|
3234
3768
|
}
|
|
3235
3769
|
|
|
3236
3770
|
// src/OnboardingFlow.tsx
|
|
3237
|
-
import { jsx as
|
|
3771
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
3238
3772
|
var isFilled = (v) => v != null && v !== "";
|
|
3239
3773
|
var CURRENT_STEP_FIELD = "currentStep";
|
|
3240
3774
|
function readPersistedStepIdx(draft) {
|
|
@@ -3248,11 +3782,11 @@ function OnboardingFlow({
|
|
|
3248
3782
|
persistKey
|
|
3249
3783
|
}) {
|
|
3250
3784
|
const [draft, setDraft, status] = usePersistedState3(persistKey, {});
|
|
3251
|
-
const draftRef =
|
|
3785
|
+
const draftRef = useRef7(draft);
|
|
3252
3786
|
draftRef.current = draft;
|
|
3253
3787
|
const idx = readPersistedStepIdx(draft);
|
|
3254
3788
|
const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
|
|
3255
|
-
const setIdx =
|
|
3789
|
+
const setIdx = useCallback13(
|
|
3256
3790
|
(n) => {
|
|
3257
3791
|
setDraft((prev) => {
|
|
3258
3792
|
const prevIdx = readPersistedStepIdx(prev);
|
|
@@ -3262,7 +3796,7 @@ function OnboardingFlow({
|
|
|
3262
3796
|
},
|
|
3263
3797
|
[setDraft]
|
|
3264
3798
|
);
|
|
3265
|
-
const setValue =
|
|
3799
|
+
const setValue = useCallback13(
|
|
3266
3800
|
(patch) => {
|
|
3267
3801
|
draftRef.current = { ...draftRef.current, ...patch };
|
|
3268
3802
|
setDraft((prev) => ({ ...prev, ...patch }));
|
|
@@ -3270,9 +3804,9 @@ function OnboardingFlow({
|
|
|
3270
3804
|
[setDraft]
|
|
3271
3805
|
);
|
|
3272
3806
|
const step = steps[clampedIdx];
|
|
3273
|
-
const hookCtx =
|
|
3807
|
+
const hookCtx = useHook20();
|
|
3274
3808
|
const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
|
|
3275
|
-
|
|
3809
|
+
useEffect16(() => {
|
|
3276
3810
|
if (status.loading) return;
|
|
3277
3811
|
if (!step) return;
|
|
3278
3812
|
if (!track2) return;
|
|
@@ -3282,11 +3816,11 @@ function OnboardingFlow({
|
|
|
3282
3816
|
total_steps: steps.length
|
|
3283
3817
|
});
|
|
3284
3818
|
}, [step?.id, clampedIdx, steps.length, status.loading, track2]);
|
|
3285
|
-
const valid =
|
|
3819
|
+
const valid = useMemo11(
|
|
3286
3820
|
() => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
|
|
3287
3821
|
[draft, step]
|
|
3288
3822
|
);
|
|
3289
|
-
const next =
|
|
3823
|
+
const next = useCallback13(() => {
|
|
3290
3824
|
if (!step) return;
|
|
3291
3825
|
const current = draftRef.current;
|
|
3292
3826
|
const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
|
|
@@ -3297,8 +3831,8 @@ function OnboardingFlow({
|
|
|
3297
3831
|
setIdx(clampedIdx + 1);
|
|
3298
3832
|
}
|
|
3299
3833
|
}, [clampedIdx, onComplete, step, steps.length, setIdx]);
|
|
3300
|
-
const prevStep =
|
|
3301
|
-
const ctx =
|
|
3834
|
+
const prevStep = useCallback13(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
|
|
3835
|
+
const ctx = useMemo11(
|
|
3302
3836
|
() => ({
|
|
3303
3837
|
stepIndex: clampedIdx,
|
|
3304
3838
|
totalSteps: steps.length,
|
|
@@ -3324,7 +3858,7 @@ function OnboardingFlow({
|
|
|
3324
3858
|
`[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
|
|
3325
3859
|
);
|
|
3326
3860
|
}
|
|
3327
|
-
return /* @__PURE__ */
|
|
3861
|
+
return /* @__PURE__ */ jsx31(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx31(Screen, {}) });
|
|
3328
3862
|
}
|
|
3329
3863
|
|
|
3330
3864
|
// src/hooks/useFeature.ts
|
|
@@ -3334,16 +3868,16 @@ function useFeature(name) {
|
|
|
3334
3868
|
}
|
|
3335
3869
|
|
|
3336
3870
|
// src/components/paywall/Paywall.tsx
|
|
3337
|
-
import { useEffect as
|
|
3338
|
-
import { useHook as
|
|
3871
|
+
import { useEffect as useEffect17, useMemo as useMemo12 } from "react";
|
|
3872
|
+
import { useHook as useHook21 } from "@hook-sdk/sdk";
|
|
3339
3873
|
|
|
3340
3874
|
// src/components/paywall/PaywallProvider.tsx
|
|
3341
3875
|
import { createContext as createContext4 } from "react";
|
|
3342
|
-
import { jsx as
|
|
3876
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
3343
3877
|
var PaywallContext = createContext4(null);
|
|
3344
3878
|
function PaywallProvider({ children }) {
|
|
3345
3879
|
const state = usePaywallState();
|
|
3346
|
-
return /* @__PURE__ */
|
|
3880
|
+
return /* @__PURE__ */ jsx32(PaywallContext.Provider, { value: state, children });
|
|
3347
3881
|
}
|
|
3348
3882
|
|
|
3349
3883
|
// src/components/paywall/usePaywallContext.ts
|
|
@@ -3357,7 +3891,7 @@ function usePaywallContext() {
|
|
|
3357
3891
|
}
|
|
3358
3892
|
|
|
3359
3893
|
// src/components/paywall/PaywallMethodTabs.tsx
|
|
3360
|
-
import { jsx as
|
|
3894
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
3361
3895
|
function PaywallMethodTabs({
|
|
3362
3896
|
labels,
|
|
3363
3897
|
className,
|
|
@@ -3366,10 +3900,10 @@ function PaywallMethodTabs({
|
|
|
3366
3900
|
}) {
|
|
3367
3901
|
const { methods, selectedMethod, selectMethod } = usePaywallContext();
|
|
3368
3902
|
if (methods.length < 2) return null;
|
|
3369
|
-
return /* @__PURE__ */
|
|
3903
|
+
return /* @__PURE__ */ jsx33("div", { role: "tablist", "aria-label": "M\xE9todo de pagamento", className, children: methods.map((m) => {
|
|
3370
3904
|
const active = m === selectedMethod;
|
|
3371
3905
|
const label = labels[m] ?? m;
|
|
3372
|
-
return /* @__PURE__ */
|
|
3906
|
+
return /* @__PURE__ */ jsx33(
|
|
3373
3907
|
"button",
|
|
3374
3908
|
{
|
|
3375
3909
|
type: "button",
|
|
@@ -3387,16 +3921,16 @@ function PaywallMethodTabs({
|
|
|
3387
3921
|
}
|
|
3388
3922
|
|
|
3389
3923
|
// src/components/paywall/PaywallMethodContent.tsx
|
|
3390
|
-
import { jsx as
|
|
3924
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
3391
3925
|
function PaywallMethodContent({ copy, className, rowClassName }) {
|
|
3392
3926
|
const { selectedMethod, hasConsumedTrial } = usePaywallContext();
|
|
3393
3927
|
const useCardConsumed = selectedMethod === "card" && hasConsumedTrial && copy.cardConsumedTrial;
|
|
3394
3928
|
const rows = useCardConsumed ? copy.cardConsumedTrial.bodyRows : selectedMethod === "pix-auto" || selectedMethod === "pix-once" ? copy.pix.bodyRows : copy.card.bodyRows;
|
|
3395
|
-
return /* @__PURE__ */
|
|
3929
|
+
return /* @__PURE__ */ jsx34("div", { role: "tabpanel", id: `paywall-tab-${selectedMethod}`, className, children: rows.map((row, i) => /* @__PURE__ */ jsx34("div", { className: rowClassName, children: row }, i)) });
|
|
3396
3930
|
}
|
|
3397
3931
|
|
|
3398
3932
|
// src/components/paywall/PaywallCyclePicker.tsx
|
|
3399
|
-
import { jsx as
|
|
3933
|
+
import { jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3400
3934
|
var VARIANT_CLASSES = {
|
|
3401
3935
|
default: { card: "", cardSelected: "" },
|
|
3402
3936
|
"premium-gold": {
|
|
@@ -3421,7 +3955,7 @@ function PaywallCyclePicker({
|
|
|
3421
3955
|
const { cycle: selected, setCycle, plan, anchorPriceCents } = ctx;
|
|
3422
3956
|
const cycles = ["MONTHLY", "YEARLY"];
|
|
3423
3957
|
if (render) {
|
|
3424
|
-
return /* @__PURE__ */
|
|
3958
|
+
return /* @__PURE__ */ jsx35("div", { className, children: render({ cycles, selected, setCycle, plan, anchorPriceCents }) });
|
|
3425
3959
|
}
|
|
3426
3960
|
if (cycles.length < 2) return null;
|
|
3427
3961
|
const v = VARIANT_CLASSES[variant];
|
|
@@ -3431,7 +3965,7 @@ function PaywallCyclePicker({
|
|
|
3431
3965
|
const yearlyCents = plan?.yearlyCents ?? 0;
|
|
3432
3966
|
const anchorMonthly = plan?.anchorMonthlyCents ?? null;
|
|
3433
3967
|
const anchorYearly = plan?.anchorYearlyCents ?? null;
|
|
3434
|
-
return /* @__PURE__ */
|
|
3968
|
+
return /* @__PURE__ */ jsx35(
|
|
3435
3969
|
"div",
|
|
3436
3970
|
{
|
|
3437
3971
|
role: "radiogroup",
|
|
@@ -3443,7 +3977,7 @@ function PaywallCyclePicker({
|
|
|
3443
3977
|
const suffix = c === "YEARLY" ? labels.annualSuffix : labels.monthlySuffix;
|
|
3444
3978
|
const mainCents = c === "YEARLY" ? Math.round(yearlyCents / 12) : monthlyCents;
|
|
3445
3979
|
const anchorCents = c === "YEARLY" ? anchorYearly : anchorMonthly;
|
|
3446
|
-
return /* @__PURE__ */
|
|
3980
|
+
return /* @__PURE__ */ jsxs21(
|
|
3447
3981
|
"button",
|
|
3448
3982
|
{
|
|
3449
3983
|
type: "button",
|
|
@@ -3456,10 +3990,10 @@ function PaywallCyclePicker({
|
|
|
3456
3990
|
active ? composedCardSelectedClassName : ""
|
|
3457
3991
|
].filter(Boolean).join(" "),
|
|
3458
3992
|
children: [
|
|
3459
|
-
/* @__PURE__ */
|
|
3460
|
-
/* @__PURE__ */
|
|
3461
|
-
/* @__PURE__ */
|
|
3462
|
-
anchorCents != null && anchorCents > mainCents ? /* @__PURE__ */
|
|
3993
|
+
/* @__PURE__ */ jsx35("span", { className: "font-bold text-base leading-tight", children: formatBRL(mainCents) }),
|
|
3994
|
+
/* @__PURE__ */ jsx35("span", { className: "text-xs opacity-70 leading-tight", children: suffix }),
|
|
3995
|
+
/* @__PURE__ */ jsx35("span", { className: "text-xs opacity-60 leading-tight", children: label }),
|
|
3996
|
+
anchorCents != null && anchorCents > mainCents ? /* @__PURE__ */ jsx35("span", { className: anchorClassName ?? "text-xs opacity-50", children: /* @__PURE__ */ jsx35("s", { children: formatBRL(anchorCents) }) }) : null
|
|
3463
3997
|
]
|
|
3464
3998
|
},
|
|
3465
3999
|
c
|
|
@@ -3470,7 +4004,7 @@ function PaywallCyclePicker({
|
|
|
3470
4004
|
}
|
|
3471
4005
|
|
|
3472
4006
|
// src/components/paywall/Paywall.tsx
|
|
3473
|
-
import { jsx as
|
|
4007
|
+
import { jsx as jsx36, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3474
4008
|
var NBSP = "\xA0";
|
|
3475
4009
|
function Paywall({
|
|
3476
4010
|
copy,
|
|
@@ -3478,7 +4012,7 @@ function Paywall({
|
|
|
3478
4012
|
slots = {},
|
|
3479
4013
|
onBeforeCheckout
|
|
3480
4014
|
}) {
|
|
3481
|
-
return /* @__PURE__ */
|
|
4015
|
+
return /* @__PURE__ */ jsx36(PaywallProvider, { children: /* @__PURE__ */ jsx36(
|
|
3482
4016
|
PaywallInner,
|
|
3483
4017
|
{
|
|
3484
4018
|
copy,
|
|
@@ -3494,11 +4028,11 @@ function PaywallInner({
|
|
|
3494
4028
|
slots = {},
|
|
3495
4029
|
onBeforeCheckout
|
|
3496
4030
|
}) {
|
|
3497
|
-
const { track: track2 } =
|
|
4031
|
+
const { track: track2 } = useHook21();
|
|
3498
4032
|
const s = usePaywallContext();
|
|
3499
4033
|
const priceLabel = formatBRL(s.currentPriceCents).replace(new RegExp(NBSP, "g"), " ");
|
|
3500
4034
|
const trialDaysCardLabel = String(s.trialDaysCard);
|
|
3501
|
-
const ctaLabel =
|
|
4035
|
+
const ctaLabel = useMemo12(() => {
|
|
3502
4036
|
if (s.isFree) return copy.freeCta ?? "Come\xE7ar agora";
|
|
3503
4037
|
if (s.selectedMethod === "card") {
|
|
3504
4038
|
if (s.hasConsumedTrial && copy.cardConsumedTrial) {
|
|
@@ -3525,11 +4059,11 @@ function PaywallInner({
|
|
|
3525
4059
|
priceLabel,
|
|
3526
4060
|
trialDaysCardLabel
|
|
3527
4061
|
]);
|
|
3528
|
-
const switchHint =
|
|
4062
|
+
const switchHint = useMemo12(() => {
|
|
3529
4063
|
if (s.methods.length < 2) return void 0;
|
|
3530
4064
|
return s.selectedMethod === "card" ? copy.card.switchHint : copy.pix.switchHint;
|
|
3531
4065
|
}, [s.methods.length, s.selectedMethod, copy]);
|
|
3532
|
-
|
|
4066
|
+
useEffect17(() => {
|
|
3533
4067
|
if (!s.initialLoadComplete) return;
|
|
3534
4068
|
track2("paywall_view", {
|
|
3535
4069
|
default_method: s.selectedMethod,
|
|
@@ -3551,15 +4085,15 @@ function PaywallInner({
|
|
|
3551
4085
|
await s.submit();
|
|
3552
4086
|
};
|
|
3553
4087
|
const ctaTheme = s.selectedMethod === "card" ? themeClasses.ctaCard : themeClasses.ctaPix;
|
|
3554
|
-
return /* @__PURE__ */
|
|
4088
|
+
return /* @__PURE__ */ jsxs22("div", { className: themeClasses.container, children: [
|
|
3555
4089
|
slots.heroSlot,
|
|
3556
|
-
/* @__PURE__ */
|
|
3557
|
-
/* @__PURE__ */
|
|
4090
|
+
/* @__PURE__ */ jsx36("h1", { className: themeClasses.headline, children: copy.headline }),
|
|
4091
|
+
/* @__PURE__ */ jsx36("ul", { children: copy.features.map((f) => /* @__PURE__ */ jsxs22("li", { className: themeClasses.feature, children: [
|
|
3558
4092
|
"\u2713 ",
|
|
3559
|
-
/* @__PURE__ */
|
|
4093
|
+
/* @__PURE__ */ jsx36("span", { children: f })
|
|
3560
4094
|
] }, f)) }),
|
|
3561
|
-
copy.socialProof ? /* @__PURE__ */
|
|
3562
|
-
slots.cyclePickerSlot ?? /* @__PURE__ */
|
|
4095
|
+
copy.socialProof ? /* @__PURE__ */ jsx36("p", { className: themeClasses.socialProof, children: copy.socialProof }) : null,
|
|
4096
|
+
slots.cyclePickerSlot ?? /* @__PURE__ */ jsx36(
|
|
3563
4097
|
PaywallCyclePicker,
|
|
3564
4098
|
{
|
|
3565
4099
|
labels: copy.cycle,
|
|
@@ -3568,7 +4102,7 @@ function PaywallInner({
|
|
|
3568
4102
|
anchorClassName: themeClasses.anchorPrice
|
|
3569
4103
|
}
|
|
3570
4104
|
),
|
|
3571
|
-
/* @__PURE__ */
|
|
4105
|
+
/* @__PURE__ */ jsx36(
|
|
3572
4106
|
PaywallMethodTabs,
|
|
3573
4107
|
{
|
|
3574
4108
|
labels: { "pix-auto": copy.pix.tabLabel, card: copy.card.tabLabel },
|
|
@@ -3577,7 +4111,7 @@ function PaywallInner({
|
|
|
3577
4111
|
tabActiveClassName: themeClasses.tabActive
|
|
3578
4112
|
}
|
|
3579
4113
|
),
|
|
3580
|
-
/* @__PURE__ */
|
|
4114
|
+
/* @__PURE__ */ jsx36(
|
|
3581
4115
|
PaywallMethodContent,
|
|
3582
4116
|
{
|
|
3583
4117
|
copy: {
|
|
@@ -3595,8 +4129,8 @@ function PaywallInner({
|
|
|
3595
4129
|
}
|
|
3596
4130
|
),
|
|
3597
4131
|
slots.beforeCtaSlot,
|
|
3598
|
-
/* @__PURE__ */
|
|
3599
|
-
/* @__PURE__ */
|
|
4132
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4133
|
+
/* @__PURE__ */ jsx36(
|
|
3600
4134
|
"button",
|
|
3601
4135
|
{
|
|
3602
4136
|
type: "button",
|
|
@@ -3608,8 +4142,8 @@ function PaywallInner({
|
|
|
3608
4142
|
children: s.submitting ? "Abrindo checkout\u2026" : ctaLabel
|
|
3609
4143
|
}
|
|
3610
4144
|
),
|
|
3611
|
-
switchHint ? /* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
4145
|
+
switchHint ? /* @__PURE__ */ jsx36("p", { className: themeClasses.switchHint, children: switchHint }) : null,
|
|
4146
|
+
/* @__PURE__ */ jsx36("p", { className: themeClasses.trustLine, children: copy.trustLine })
|
|
3613
4147
|
] })
|
|
3614
4148
|
] });
|
|
3615
4149
|
}
|
|
@@ -3626,7 +4160,7 @@ function interpolateCopy(m, price, days) {
|
|
|
3626
4160
|
}
|
|
3627
4161
|
|
|
3628
4162
|
// src/components/paywall/PaywallCta.tsx
|
|
3629
|
-
import { jsx as
|
|
4163
|
+
import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3630
4164
|
function PaywallCta({
|
|
3631
4165
|
ctaLabel,
|
|
3632
4166
|
loadingLabel,
|
|
@@ -3639,8 +4173,8 @@ function PaywallCta({
|
|
|
3639
4173
|
}) {
|
|
3640
4174
|
const { submit, submitting } = usePaywallContext();
|
|
3641
4175
|
const label = submitting && loadingLabel ? loadingLabel : ctaLabel;
|
|
3642
|
-
return /* @__PURE__ */
|
|
3643
|
-
/* @__PURE__ */
|
|
4176
|
+
return /* @__PURE__ */ jsxs23("div", { className, children: [
|
|
4177
|
+
/* @__PURE__ */ jsx37(
|
|
3644
4178
|
"button",
|
|
3645
4179
|
{
|
|
3646
4180
|
type: "button",
|
|
@@ -3652,20 +4186,20 @@ function PaywallCta({
|
|
|
3652
4186
|
children: label
|
|
3653
4187
|
}
|
|
3654
4188
|
),
|
|
3655
|
-
switchHint ? /* @__PURE__ */
|
|
3656
|
-
/* @__PURE__ */
|
|
4189
|
+
switchHint ? /* @__PURE__ */ jsx37("p", { className: switchHintClassName, children: switchHint }) : null,
|
|
4190
|
+
/* @__PURE__ */ jsx37("p", { className: trustClassName, children: trustLine })
|
|
3657
4191
|
] });
|
|
3658
4192
|
}
|
|
3659
4193
|
|
|
3660
4194
|
// src/components/paywall/blocks/PaywallEyebrow.tsx
|
|
3661
|
-
import { jsx as
|
|
4195
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
3662
4196
|
var DEFAULT_EYEBROW_CLASSES = "text-xs uppercase tracking-widest font-semibold opacity-70";
|
|
3663
4197
|
function PaywallEyebrow({ text, className }) {
|
|
3664
|
-
return /* @__PURE__ */
|
|
4198
|
+
return /* @__PURE__ */ jsx38("div", { className: [DEFAULT_EYEBROW_CLASSES, className].filter(Boolean).join(" "), children: text });
|
|
3665
4199
|
}
|
|
3666
4200
|
|
|
3667
4201
|
// src/components/paywall/blocks/PaywallHero.tsx
|
|
3668
|
-
import { jsx as
|
|
4202
|
+
import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3669
4203
|
var DEFAULT_GRADIENT = "absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent";
|
|
3670
4204
|
function PaywallHero({
|
|
3671
4205
|
src,
|
|
@@ -3679,15 +4213,15 @@ function PaywallHero({
|
|
|
3679
4213
|
render
|
|
3680
4214
|
}) {
|
|
3681
4215
|
if (render) {
|
|
3682
|
-
return /* @__PURE__ */
|
|
4216
|
+
return /* @__PURE__ */ jsx39("div", { className, children: render({ src, headline }) });
|
|
3683
4217
|
}
|
|
3684
|
-
return /* @__PURE__ */
|
|
4218
|
+
return /* @__PURE__ */ jsxs24(
|
|
3685
4219
|
"div",
|
|
3686
4220
|
{
|
|
3687
4221
|
className: ["relative overflow-hidden", className].filter(Boolean).join(" "),
|
|
3688
4222
|
style: { aspectRatio },
|
|
3689
4223
|
children: [
|
|
3690
|
-
/* @__PURE__ */
|
|
4224
|
+
/* @__PURE__ */ jsx39(
|
|
3691
4225
|
"img",
|
|
3692
4226
|
{
|
|
3693
4227
|
src,
|
|
@@ -3695,8 +4229,8 @@ function PaywallHero({
|
|
|
3695
4229
|
className: ["absolute inset-0 w-full h-full object-cover", imgClassName].filter(Boolean).join(" ")
|
|
3696
4230
|
}
|
|
3697
4231
|
),
|
|
3698
|
-
/* @__PURE__ */
|
|
3699
|
-
headline ? /* @__PURE__ */
|
|
4232
|
+
/* @__PURE__ */ jsx39("div", { className: gradientClassName ?? DEFAULT_GRADIENT, "aria-hidden": "true" }),
|
|
4233
|
+
headline ? /* @__PURE__ */ jsx39(
|
|
3700
4234
|
"h1",
|
|
3701
4235
|
{
|
|
3702
4236
|
className: ["absolute bottom-0 left-0 right-0 p-4 text-white font-bold text-2xl", headlineClassName].filter(Boolean).join(" "),
|
|
@@ -3709,15 +4243,15 @@ function PaywallHero({
|
|
|
3709
4243
|
}
|
|
3710
4244
|
|
|
3711
4245
|
// src/components/paywall/blocks/PaywallHeadline.tsx
|
|
3712
|
-
import { jsx as
|
|
4246
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
3713
4247
|
var DEFAULT_HEADLINE_CLASSES = "text-2xl font-bold leading-tight";
|
|
3714
4248
|
function PaywallHeadline({ text, className, as = "h1" }) {
|
|
3715
4249
|
const Tag = as;
|
|
3716
|
-
return /* @__PURE__ */
|
|
4250
|
+
return /* @__PURE__ */ jsx40(Tag, { className: [DEFAULT_HEADLINE_CLASSES, className].filter(Boolean).join(" "), children: text });
|
|
3717
4251
|
}
|
|
3718
4252
|
|
|
3719
4253
|
// src/components/paywall/blocks/PaywallPriceHeadline.tsx
|
|
3720
|
-
import { jsx as
|
|
4254
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
3721
4255
|
var DEFAULT_CLASS = "text-2xl font-bold leading-tight";
|
|
3722
4256
|
var CYCLE_LABEL = {
|
|
3723
4257
|
MONTHLY: "mensal",
|
|
@@ -3737,16 +4271,16 @@ function PaywallPriceHeadline({
|
|
|
3737
4271
|
const rootClasses = [DEFAULT_CLASS, className].filter(Boolean).join(" ");
|
|
3738
4272
|
if (render) {
|
|
3739
4273
|
const RootTag2 = as;
|
|
3740
|
-
return /* @__PURE__ */
|
|
4274
|
+
return /* @__PURE__ */ jsx41(RootTag2, { className: [className].filter(Boolean).join(" ") || void 0, children: render({ pricePerDay, currentMonthlyEquivCents: monthlyEquiv, cycle }) });
|
|
3741
4275
|
}
|
|
3742
4276
|
const text = template.replaceAll("{pricePerDay}", pricePerDay).replaceAll("{currentMonthlyEquiv}", formatBRL(monthlyEquiv)).replaceAll("{cycle}", cycleLabel);
|
|
3743
4277
|
const RootTag = as;
|
|
3744
|
-
return /* @__PURE__ */
|
|
4278
|
+
return /* @__PURE__ */ jsx41(RootTag, { className: rootClasses, children: text });
|
|
3745
4279
|
}
|
|
3746
4280
|
|
|
3747
4281
|
// src/components/paywall/blocks/PaywallCountdown.tsx
|
|
3748
|
-
import { useEffect as
|
|
3749
|
-
import { jsx as
|
|
4282
|
+
import { useEffect as useEffect18, useRef as useRef8, useState as useState16 } from "react";
|
|
4283
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
3750
4284
|
var DEFAULT_COUNTDOWN_CLASSES = "font-mono tabular-nums";
|
|
3751
4285
|
function resolveDeadlineMs(deadline) {
|
|
3752
4286
|
if (deadline instanceof Date) return deadline.getTime();
|
|
@@ -3783,13 +4317,13 @@ function PaywallCountdown({
|
|
|
3783
4317
|
className,
|
|
3784
4318
|
render
|
|
3785
4319
|
}) {
|
|
3786
|
-
const deadlineMsRef =
|
|
4320
|
+
const deadlineMsRef = useRef8(null);
|
|
3787
4321
|
if (deadlineMsRef.current === null) {
|
|
3788
4322
|
deadlineMsRef.current = resolveDeadlineMs(deadline);
|
|
3789
4323
|
}
|
|
3790
|
-
const [state, setState] =
|
|
3791
|
-
const expiredCalledRef =
|
|
3792
|
-
|
|
4324
|
+
const [state, setState] = useState16(() => computeRemaining(deadlineMsRef.current));
|
|
4325
|
+
const expiredCalledRef = useRef8(false);
|
|
4326
|
+
useEffect18(() => {
|
|
3793
4327
|
if (state.expired) {
|
|
3794
4328
|
if (!expiredCalledRef.current) {
|
|
3795
4329
|
expiredCalledRef.current = true;
|
|
@@ -3809,14 +4343,14 @@ function PaywallCountdown({
|
|
|
3809
4343
|
return () => clearInterval(id);
|
|
3810
4344
|
}, [state.expired]);
|
|
3811
4345
|
if (render) {
|
|
3812
|
-
return /* @__PURE__ */
|
|
4346
|
+
return /* @__PURE__ */ jsx42("div", { className, children: render(state) });
|
|
3813
4347
|
}
|
|
3814
4348
|
const formatted = format === "h:m:s" ? `${pad(state.h)}:${pad(state.m)}:${pad(state.s)}` : `${pad(state.h * 60 + state.m)}:${pad(state.s)}`;
|
|
3815
|
-
return /* @__PURE__ */
|
|
4349
|
+
return /* @__PURE__ */ jsx42("div", { className: [DEFAULT_COUNTDOWN_CLASSES, className].filter(Boolean).join(" "), children: formatted });
|
|
3816
4350
|
}
|
|
3817
4351
|
|
|
3818
4352
|
// src/components/paywall/blocks/PaywallFeatures.tsx
|
|
3819
|
-
import { jsx as
|
|
4353
|
+
import { jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3820
4354
|
function PaywallFeatures({
|
|
3821
4355
|
items,
|
|
3822
4356
|
IconComponent,
|
|
@@ -3827,19 +4361,19 @@ function PaywallFeatures({
|
|
|
3827
4361
|
renderItem
|
|
3828
4362
|
}) {
|
|
3829
4363
|
if (render) {
|
|
3830
|
-
return /* @__PURE__ */
|
|
4364
|
+
return /* @__PURE__ */ jsx43("div", { className, children: render({ items }) });
|
|
3831
4365
|
}
|
|
3832
4366
|
if (renderItem) {
|
|
3833
|
-
return /* @__PURE__ */
|
|
4367
|
+
return /* @__PURE__ */ jsx43("ul", { className, children: items.map((item, idx) => /* @__PURE__ */ jsx43("li", { children: renderItem(item, idx) }, idx)) });
|
|
3834
4368
|
}
|
|
3835
|
-
return /* @__PURE__ */
|
|
3836
|
-
IconComponent ? /* @__PURE__ */
|
|
3837
|
-
/* @__PURE__ */
|
|
4369
|
+
return /* @__PURE__ */ jsx43("ul", { className, children: items.map((item, idx) => /* @__PURE__ */ jsxs25("li", { className: itemClassName, children: [
|
|
4370
|
+
IconComponent ? /* @__PURE__ */ jsx43(IconComponent, { className: iconClassName }) : /* @__PURE__ */ jsx43("span", { className: iconClassName, "aria-hidden": "true", children: "\u2713" }),
|
|
4371
|
+
/* @__PURE__ */ jsx43("span", { children: item })
|
|
3838
4372
|
] }, idx)) });
|
|
3839
4373
|
}
|
|
3840
4374
|
|
|
3841
4375
|
// src/components/paywall/blocks/PaywallFeaturesCard.tsx
|
|
3842
|
-
import { jsx as
|
|
4376
|
+
import { jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3843
4377
|
var DEFAULT_CARD_CLASSES = "rounded-xl border p-4";
|
|
3844
4378
|
function PaywallFeaturesCard({
|
|
3845
4379
|
title,
|
|
@@ -3850,20 +4384,20 @@ function PaywallFeaturesCard({
|
|
|
3850
4384
|
itemClassName,
|
|
3851
4385
|
renderItem
|
|
3852
4386
|
}) {
|
|
3853
|
-
return /* @__PURE__ */
|
|
3854
|
-
title ? /* @__PURE__ */
|
|
3855
|
-
/* @__PURE__ */
|
|
3856
|
-
(item, idx) => renderItem ? /* @__PURE__ */
|
|
3857
|
-
/* @__PURE__ */
|
|
4387
|
+
return /* @__PURE__ */ jsx44("div", { className, children: /* @__PURE__ */ jsxs26("div", { className: [DEFAULT_CARD_CLASSES, cardClassName].filter(Boolean).join(" "), children: [
|
|
4388
|
+
title ? /* @__PURE__ */ jsx44("div", { className: ["font-semibold mb-2", titleClassName].filter(Boolean).join(" "), children: title }) : null,
|
|
4389
|
+
/* @__PURE__ */ jsx44("ul", { children: items.map(
|
|
4390
|
+
(item, idx) => renderItem ? /* @__PURE__ */ jsx44("li", { children: renderItem(item, idx) }, idx) : /* @__PURE__ */ jsxs26("li", { className: itemClassName, children: [
|
|
4391
|
+
/* @__PURE__ */ jsx44("span", { "aria-hidden": "true", children: "\u2022" }),
|
|
3858
4392
|
" ",
|
|
3859
|
-
/* @__PURE__ */
|
|
4393
|
+
/* @__PURE__ */ jsx44("span", { children: item })
|
|
3860
4394
|
] }, idx)
|
|
3861
4395
|
) })
|
|
3862
4396
|
] }) });
|
|
3863
4397
|
}
|
|
3864
4398
|
|
|
3865
4399
|
// src/components/paywall/blocks/PaywallTrophyBadge.tsx
|
|
3866
|
-
import { jsx as
|
|
4400
|
+
import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
3867
4401
|
var DEFAULT_CHIP_CLASSES = "inline-flex items-center gap-1 px-3 py-1 rounded-full bg-yellow-100 text-yellow-900 text-sm font-medium";
|
|
3868
4402
|
var FLOATING_CLASSES = "absolute top-2 right-2 z-10 shadow-md";
|
|
3869
4403
|
function PaywallTrophyBadge({
|
|
@@ -3874,21 +4408,21 @@ function PaywallTrophyBadge({
|
|
|
3874
4408
|
render
|
|
3875
4409
|
}) {
|
|
3876
4410
|
if (render) {
|
|
3877
|
-
return /* @__PURE__ */
|
|
4411
|
+
return /* @__PURE__ */ jsx45("div", { className, children: render({ text }) });
|
|
3878
4412
|
}
|
|
3879
4413
|
const rootClasses = [
|
|
3880
4414
|
DEFAULT_CHIP_CLASSES,
|
|
3881
4415
|
floating ? FLOATING_CLASSES : "",
|
|
3882
4416
|
className
|
|
3883
4417
|
].filter(Boolean).join(" ");
|
|
3884
|
-
return /* @__PURE__ */
|
|
3885
|
-
/* @__PURE__ */
|
|
3886
|
-
/* @__PURE__ */
|
|
4418
|
+
return /* @__PURE__ */ jsxs27("div", { className: rootClasses, children: [
|
|
4419
|
+
/* @__PURE__ */ jsx45("span", { className: iconClassName, "aria-hidden": "true", children: "\u{1F3C6}" }),
|
|
4420
|
+
/* @__PURE__ */ jsx45("span", { children: text })
|
|
3887
4421
|
] });
|
|
3888
4422
|
}
|
|
3889
4423
|
|
|
3890
4424
|
// src/components/paywall/blocks/PaywallAnchorPrice.tsx
|
|
3891
|
-
import { jsx as
|
|
4425
|
+
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
3892
4426
|
var DEFAULT_CLASS2 = "text-sm opacity-60 line-through";
|
|
3893
4427
|
function PaywallAnchorPrice({
|
|
3894
4428
|
className,
|
|
@@ -3902,13 +4436,13 @@ function PaywallAnchorPrice({
|
|
|
3902
4436
|
const formatted = formatBRL(anchorPriceCents);
|
|
3903
4437
|
const rootClasses = [DEFAULT_CLASS2, className].filter(Boolean).join(" ");
|
|
3904
4438
|
if (render) {
|
|
3905
|
-
return /* @__PURE__ */
|
|
4439
|
+
return /* @__PURE__ */ jsx46("span", { className: className || void 0, children: render({ anchorCents: anchorPriceCents, formatted }) });
|
|
3906
4440
|
}
|
|
3907
|
-
return /* @__PURE__ */
|
|
4441
|
+
return /* @__PURE__ */ jsx46("span", { className: rootClasses, children: formatted });
|
|
3908
4442
|
}
|
|
3909
4443
|
|
|
3910
4444
|
// src/components/paywall/blocks/PaywallTestimonials.tsx
|
|
3911
|
-
import { jsx as
|
|
4445
|
+
import { jsx as jsx47, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
3912
4446
|
var DEFAULT_ROOT = "flex gap-3 overflow-x-auto snap-x snap-mandatory pb-2";
|
|
3913
4447
|
var DEFAULT_CARD = "snap-start shrink-0 w-72 rounded-2xl border p-4 flex flex-col gap-2";
|
|
3914
4448
|
var DEFAULT_AVATAR = "w-10 h-10 rounded-full object-cover";
|
|
@@ -3934,13 +4468,13 @@ function PaywallTestimonials({
|
|
|
3934
4468
|
const quoteClasses = [DEFAULT_QUOTE, quoteClassName].filter(Boolean).join(" ");
|
|
3935
4469
|
const nameClasses = [DEFAULT_NAME, nameClassName].filter(Boolean).join(" ");
|
|
3936
4470
|
const starsClasses = [DEFAULT_STARS, starsClassName].filter(Boolean).join(" ");
|
|
3937
|
-
return /* @__PURE__ */
|
|
4471
|
+
return /* @__PURE__ */ jsx47("div", { className: rootClasses, children: items.map((item, idx) => {
|
|
3938
4472
|
if (renderItem) return renderItem(item, idx);
|
|
3939
4473
|
const filled = clampStars(item.stars);
|
|
3940
4474
|
const empty = 5 - filled;
|
|
3941
|
-
return /* @__PURE__ */
|
|
3942
|
-
/* @__PURE__ */
|
|
3943
|
-
item.avatar ? /* @__PURE__ */
|
|
4475
|
+
return /* @__PURE__ */ jsxs28("div", { className: cardClasses, children: [
|
|
4476
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
4477
|
+
item.avatar ? /* @__PURE__ */ jsx47(
|
|
3944
4478
|
"img",
|
|
3945
4479
|
{
|
|
3946
4480
|
src: item.avatar,
|
|
@@ -3950,19 +4484,19 @@ function PaywallTestimonials({
|
|
|
3950
4484
|
"aria-hidden": "true"
|
|
3951
4485
|
}
|
|
3952
4486
|
) : null,
|
|
3953
|
-
/* @__PURE__ */
|
|
4487
|
+
/* @__PURE__ */ jsx47("div", { className: nameClasses, children: item.name })
|
|
3954
4488
|
] }),
|
|
3955
|
-
/* @__PURE__ */
|
|
4489
|
+
/* @__PURE__ */ jsxs28("div", { className: starsClasses, "aria-label": `${filled} de 5 estrelas`, children: [
|
|
3956
4490
|
"\u2605".repeat(filled),
|
|
3957
4491
|
"\u2606".repeat(empty)
|
|
3958
4492
|
] }),
|
|
3959
|
-
/* @__PURE__ */
|
|
4493
|
+
/* @__PURE__ */ jsx47("p", { className: quoteClasses, children: item.quote })
|
|
3960
4494
|
] }, idx);
|
|
3961
4495
|
}) });
|
|
3962
4496
|
}
|
|
3963
4497
|
|
|
3964
4498
|
// src/components/paywall/blocks/PaywallStatsRow.tsx
|
|
3965
|
-
import { jsx as
|
|
4499
|
+
import { jsx as jsx48, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
3966
4500
|
var DEFAULT_ROOT2 = "grid grid-cols-3 gap-4";
|
|
3967
4501
|
var DEFAULT_CELL = "flex flex-col items-center text-center";
|
|
3968
4502
|
var DEFAULT_VALUE = "text-2xl font-bold";
|
|
@@ -3979,18 +4513,18 @@ function PaywallStatsRow({
|
|
|
3979
4513
|
const cellClasses = [DEFAULT_CELL, cellClassName].filter(Boolean).join(" ");
|
|
3980
4514
|
const valueClasses = [DEFAULT_VALUE, valueClassName].filter(Boolean).join(" ");
|
|
3981
4515
|
const labelClasses = [DEFAULT_LABEL, labelClassName].filter(Boolean).join(" ");
|
|
3982
|
-
return /* @__PURE__ */
|
|
4516
|
+
return /* @__PURE__ */ jsx48("div", { className: rootClasses, children: stats.map((stat, idx) => {
|
|
3983
4517
|
if (renderCell) return renderCell(stat, idx);
|
|
3984
|
-
return /* @__PURE__ */
|
|
3985
|
-
stat.icon ? /* @__PURE__ */
|
|
3986
|
-
/* @__PURE__ */
|
|
3987
|
-
/* @__PURE__ */
|
|
4518
|
+
return /* @__PURE__ */ jsxs29("div", { className: cellClasses, children: [
|
|
4519
|
+
stat.icon ? /* @__PURE__ */ jsx48("div", { "aria-hidden": "true", children: stat.icon }) : null,
|
|
4520
|
+
/* @__PURE__ */ jsx48("div", { className: valueClasses, children: stat.value }),
|
|
4521
|
+
/* @__PURE__ */ jsx48("div", { className: labelClasses, children: stat.label })
|
|
3988
4522
|
] }, idx);
|
|
3989
4523
|
}) });
|
|
3990
4524
|
}
|
|
3991
4525
|
|
|
3992
4526
|
// src/components/paywall/blocks/PaywallFinePrint.tsx
|
|
3993
|
-
import { jsx as
|
|
4527
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
3994
4528
|
var DEFAULT_CLASS3 = "text-xs opacity-60 leading-snug";
|
|
3995
4529
|
var CYCLE_LABEL2 = {
|
|
3996
4530
|
MONTHLY: "mensal",
|
|
@@ -4013,7 +4547,7 @@ function PaywallFinePrint({
|
|
|
4013
4547
|
const priceFormatted = formatBRL(currentPriceCents ?? 0);
|
|
4014
4548
|
const rootClasses = [DEFAULT_CLASS3, className].filter(Boolean).join(" ");
|
|
4015
4549
|
if (render) {
|
|
4016
|
-
return /* @__PURE__ */
|
|
4550
|
+
return /* @__PURE__ */ jsx49("p", { className: className || void 0, children: render({
|
|
4017
4551
|
currentPriceCents: currentPriceCents ?? 0,
|
|
4018
4552
|
cycle,
|
|
4019
4553
|
trialDays: trialDays ?? 0,
|
|
@@ -4021,11 +4555,11 @@ function PaywallFinePrint({
|
|
|
4021
4555
|
}) });
|
|
4022
4556
|
}
|
|
4023
4557
|
const text = template.replaceAll("{price}", priceFormatted).replaceAll("{trialDays}", String(trialDays ?? 0)).replaceAll("{cycle}", cycleLabel);
|
|
4024
|
-
return /* @__PURE__ */
|
|
4558
|
+
return /* @__PURE__ */ jsx49("p", { className: rootClasses, children: text });
|
|
4025
4559
|
}
|
|
4026
4560
|
|
|
4027
4561
|
// src/components/paywall/blocks/PaywallTrustLine.tsx
|
|
4028
|
-
import { jsx as
|
|
4562
|
+
import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4029
4563
|
var DEFAULT_ROOT3 = "flex items-center gap-3";
|
|
4030
4564
|
var DEFAULT_ITEM = "flex items-center gap-1.5 text-xs";
|
|
4031
4565
|
function PaywallTrustLine({
|
|
@@ -4036,17 +4570,17 @@ function PaywallTrustLine({
|
|
|
4036
4570
|
}) {
|
|
4037
4571
|
const rootClasses = [DEFAULT_ROOT3, className].filter(Boolean).join(" ");
|
|
4038
4572
|
const itemClasses = [DEFAULT_ITEM, itemClassName].filter(Boolean).join(" ");
|
|
4039
|
-
return /* @__PURE__ */
|
|
4573
|
+
return /* @__PURE__ */ jsx50("div", { className: rootClasses, children: items.map((item, idx) => {
|
|
4040
4574
|
if (renderItem) return renderItem(item, idx);
|
|
4041
|
-
return /* @__PURE__ */
|
|
4042
|
-
/* @__PURE__ */
|
|
4043
|
-
/* @__PURE__ */
|
|
4575
|
+
return /* @__PURE__ */ jsxs30("span", { className: itemClasses, children: [
|
|
4576
|
+
/* @__PURE__ */ jsx50("span", { "aria-hidden": "true", children: item.icon }),
|
|
4577
|
+
/* @__PURE__ */ jsx50("span", { children: item.text })
|
|
4044
4578
|
] }, idx);
|
|
4045
4579
|
}) });
|
|
4046
4580
|
}
|
|
4047
4581
|
|
|
4048
4582
|
// src/components/paywall/blocks/PaywallStickyFooter.tsx
|
|
4049
|
-
import { jsx as
|
|
4583
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
4050
4584
|
var DEFAULT_CLASSES = "sticky bottom-0 left-0 right-0 bg-background";
|
|
4051
4585
|
var SAFE_AREA_CLASS = "pb-[env(safe-area-inset-bottom)]";
|
|
4052
4586
|
function PaywallStickyFooter({
|
|
@@ -4055,12 +4589,13 @@ function PaywallStickyFooter({
|
|
|
4055
4589
|
safeAreaInsets = true
|
|
4056
4590
|
}) {
|
|
4057
4591
|
const classes = [DEFAULT_CLASSES, safeAreaInsets ? SAFE_AREA_CLASS : null, className].filter(Boolean).join(" ");
|
|
4058
|
-
return /* @__PURE__ */
|
|
4592
|
+
return /* @__PURE__ */ jsx51("div", { className: classes, children });
|
|
4059
4593
|
}
|
|
4060
4594
|
export {
|
|
4061
4595
|
AppConfigProvider,
|
|
4062
4596
|
AppConfigSchema,
|
|
4063
4597
|
AppRoot,
|
|
4598
|
+
CheckoutPageDefault,
|
|
4064
4599
|
DeepLinkHandler,
|
|
4065
4600
|
DevSkipOnboardingFab,
|
|
4066
4601
|
EmptyState,
|
|
@@ -4094,6 +4629,7 @@ export {
|
|
|
4094
4629
|
PaywallTrophyBadge,
|
|
4095
4630
|
PaywallTrustLine,
|
|
4096
4631
|
PersistenceRegistry,
|
|
4632
|
+
PixWaitingPageDefault,
|
|
4097
4633
|
PreAuthShell,
|
|
4098
4634
|
PushPrompt2 as PushPrompt,
|
|
4099
4635
|
RouteBoundary,
|
|
@@ -4116,6 +4652,7 @@ export {
|
|
|
4116
4652
|
useAppConfig,
|
|
4117
4653
|
useAuth,
|
|
4118
4654
|
useAuthPrimitives,
|
|
4655
|
+
useCheckoutForm,
|
|
4119
4656
|
useFeature,
|
|
4120
4657
|
useForgotForm,
|
|
4121
4658
|
useInstallPrompt,
|