@hook-sdk/template 0.23.3 → 0.25.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 +868 -353
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +330 -24
- package/dist/index.d.ts +330 -24
- package/dist/index.js +782 -284
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -45,10 +45,26 @@ __export(index_exports, {
|
|
|
45
45
|
OnboardingFlow: () => OnboardingFlow,
|
|
46
46
|
PaymentReturnHandler: () => PaymentReturnHandler,
|
|
47
47
|
Paywall: () => Paywall,
|
|
48
|
+
PaywallAnchorPrice: () => PaywallAnchorPrice,
|
|
49
|
+
PaywallContext: () => PaywallContext,
|
|
50
|
+
PaywallCountdown: () => PaywallCountdown,
|
|
48
51
|
PaywallCta: () => PaywallCta,
|
|
49
52
|
PaywallCyclePicker: () => PaywallCyclePicker,
|
|
53
|
+
PaywallEyebrow: () => PaywallEyebrow,
|
|
54
|
+
PaywallFeatures: () => PaywallFeatures,
|
|
55
|
+
PaywallFeaturesCard: () => PaywallFeaturesCard,
|
|
56
|
+
PaywallFinePrint: () => PaywallFinePrint,
|
|
57
|
+
PaywallHeadline: () => PaywallHeadline,
|
|
58
|
+
PaywallHero: () => PaywallHero,
|
|
50
59
|
PaywallMethodContent: () => PaywallMethodContent,
|
|
51
60
|
PaywallMethodTabs: () => PaywallMethodTabs,
|
|
61
|
+
PaywallPriceHeadline: () => PaywallPriceHeadline,
|
|
62
|
+
PaywallProvider: () => PaywallProvider,
|
|
63
|
+
PaywallStatsRow: () => PaywallStatsRow,
|
|
64
|
+
PaywallStickyFooter: () => PaywallStickyFooter,
|
|
65
|
+
PaywallTestimonials: () => PaywallTestimonials,
|
|
66
|
+
PaywallTrophyBadge: () => PaywallTrophyBadge,
|
|
67
|
+
PaywallTrustLine: () => PaywallTrustLine,
|
|
52
68
|
PersistenceRegistry: () => PersistenceRegistry,
|
|
53
69
|
PreAuthShell: () => PreAuthShell,
|
|
54
70
|
PushPrompt: () => PushPrompt2,
|
|
@@ -77,6 +93,7 @@ __export(index_exports, {
|
|
|
77
93
|
useInstallPrompt: () => useInstallPrompt,
|
|
78
94
|
useLoginForm: () => useLoginForm,
|
|
79
95
|
useOnboardingStep: () => useOnboardingStep,
|
|
96
|
+
usePaywallContext: () => usePaywallContext,
|
|
80
97
|
usePaywallState: () => usePaywallState,
|
|
81
98
|
usePlan: () => usePlan,
|
|
82
99
|
usePush: () => usePush,
|
|
@@ -85,14 +102,14 @@ __export(index_exports, {
|
|
|
85
102
|
useSignupForm: () => useSignupForm,
|
|
86
103
|
useSubscription: () => useSubscription,
|
|
87
104
|
useToast: () => useToast,
|
|
88
|
-
useTrackOnboardingStep: () =>
|
|
105
|
+
useTrackOnboardingStep: () => import_sdk24.useTrackOnboardingStep
|
|
89
106
|
});
|
|
90
107
|
module.exports = __toCommonJS(index_exports);
|
|
91
108
|
|
|
92
109
|
// src/AppRoot.tsx
|
|
93
|
-
var
|
|
110
|
+
var import_react16 = require("react");
|
|
94
111
|
var import_react_router_dom2 = require("react-router-dom");
|
|
95
|
-
var
|
|
112
|
+
var import_sdk9 = require("@hook-sdk/sdk");
|
|
96
113
|
|
|
97
114
|
// src/config/AppConfigContext.tsx
|
|
98
115
|
var import_react = require("react");
|
|
@@ -721,8 +738,8 @@ function usePaywallState() {
|
|
|
721
738
|
opening: submitting,
|
|
722
739
|
availableMethods: methods,
|
|
723
740
|
monthlyEquivalent,
|
|
724
|
-
|
|
725
|
-
|
|
741
|
+
// G154 fix (template 0.24.0 + SDK 0.26.0): wired to SDK action.
|
|
742
|
+
dismissPix: subscription.clearPixPending,
|
|
726
743
|
refreshPlan: () => {
|
|
727
744
|
}
|
|
728
745
|
};
|
|
@@ -2122,10 +2139,54 @@ function SessionExpiredBanner() {
|
|
|
2122
2139
|
] });
|
|
2123
2140
|
}
|
|
2124
2141
|
|
|
2125
|
-
// src/
|
|
2142
|
+
// src/internal/EmailVerifyBanner.tsx
|
|
2126
2143
|
var import_react11 = require("react");
|
|
2144
|
+
var import_sdk5 = require("@hook-sdk/sdk");
|
|
2127
2145
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2128
|
-
|
|
2146
|
+
function EmailVerifyBanner() {
|
|
2147
|
+
const { user, auth } = (0, import_sdk5.useHook)();
|
|
2148
|
+
const [sending, setSending] = (0, import_react11.useState)(false);
|
|
2149
|
+
const [sent, setSent] = (0, import_react11.useState)(false);
|
|
2150
|
+
if (!user || user.emailVerified) return null;
|
|
2151
|
+
async function handleResend() {
|
|
2152
|
+
if (sending || sent) return;
|
|
2153
|
+
setSending(true);
|
|
2154
|
+
try {
|
|
2155
|
+
await auth.resendVerify();
|
|
2156
|
+
setSent(true);
|
|
2157
|
+
} catch {
|
|
2158
|
+
} finally {
|
|
2159
|
+
setSending(false);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
const label = sent ? "Enviado!" : sending ? "Enviando..." : "Reenviar link";
|
|
2163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2164
|
+
"div",
|
|
2165
|
+
{
|
|
2166
|
+
role: "status",
|
|
2167
|
+
"data-testid": "email-verify-banner",
|
|
2168
|
+
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",
|
|
2169
|
+
children: [
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Confirma teu e-mail pra liberar tudo." }),
|
|
2171
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2172
|
+
"button",
|
|
2173
|
+
{
|
|
2174
|
+
type: "button",
|
|
2175
|
+
onClick: handleResend,
|
|
2176
|
+
disabled: sending || sent,
|
|
2177
|
+
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",
|
|
2178
|
+
children: label
|
|
2179
|
+
}
|
|
2180
|
+
)
|
|
2181
|
+
]
|
|
2182
|
+
}
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
// src/defaults/ErrorBoundary.tsx
|
|
2187
|
+
var import_react12 = require("react");
|
|
2188
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2189
|
+
var ErrorBoundary = class extends import_react12.Component {
|
|
2129
2190
|
state = { error: null };
|
|
2130
2191
|
static getDerivedStateFromError(error) {
|
|
2131
2192
|
return { error };
|
|
@@ -2142,21 +2203,21 @@ var ErrorBoundary = class extends import_react11.Component {
|
|
|
2142
2203
|
}
|
|
2143
2204
|
render() {
|
|
2144
2205
|
if (this.state.error) {
|
|
2145
|
-
return this.props.fallback ?? /* @__PURE__ */ (0,
|
|
2146
|
-
/* @__PURE__ */ (0,
|
|
2147
|
-
/* @__PURE__ */ (0,
|
|
2206
|
+
return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
2207
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { children: "Algo deu errado" }),
|
|
2208
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
2148
2209
|
] });
|
|
2149
2210
|
}
|
|
2150
|
-
return /* @__PURE__ */ (0,
|
|
2211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children: this.props.children });
|
|
2151
2212
|
}
|
|
2152
2213
|
};
|
|
2153
2214
|
|
|
2154
2215
|
// src/i18n/I18nProvider.tsx
|
|
2155
|
-
var
|
|
2216
|
+
var import_react13 = require("react");
|
|
2156
2217
|
var import_i18next = __toESM(require("i18next"), 1);
|
|
2157
2218
|
var import_react_i18next = require("react-i18next");
|
|
2158
|
-
var
|
|
2159
|
-
var
|
|
2219
|
+
var import_sdk6 = require("@hook-sdk/sdk");
|
|
2220
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2160
2221
|
function ensureInitialized(defaultLocale, supportedLocales, resources, initialLocale) {
|
|
2161
2222
|
if (import_i18next.default.isInitialized) return;
|
|
2162
2223
|
import_i18next.default.use(import_react_i18next.initReactI18next).init({
|
|
@@ -2178,14 +2239,14 @@ function I18nProvider({
|
|
|
2178
2239
|
resources,
|
|
2179
2240
|
children
|
|
2180
2241
|
}) {
|
|
2181
|
-
const [userLocale] = (0,
|
|
2242
|
+
const [userLocale] = (0, import_sdk6.usePersistedState)("user-locale", defaultLocale);
|
|
2182
2243
|
ensureInitialized(defaultLocale, supportedLocales, resources, userLocale);
|
|
2183
|
-
(0,
|
|
2244
|
+
(0, import_react13.useEffect)(() => {
|
|
2184
2245
|
if (import_i18next.default.isInitialized && import_i18next.default.language !== userLocale) {
|
|
2185
2246
|
import_i18next.default.changeLanguage(userLocale);
|
|
2186
2247
|
}
|
|
2187
2248
|
}, [userLocale]);
|
|
2188
|
-
return /* @__PURE__ */ (0,
|
|
2249
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_i18next.I18nextProvider, { i18n: import_i18next.default, children });
|
|
2189
2250
|
}
|
|
2190
2251
|
|
|
2191
2252
|
// src/dev/env.ts
|
|
@@ -2196,9 +2257,9 @@ function isDevToolsEnabled() {
|
|
|
2196
2257
|
}
|
|
2197
2258
|
|
|
2198
2259
|
// src/dev/DevSkipOnboardingFab.tsx
|
|
2199
|
-
var
|
|
2200
|
-
var
|
|
2201
|
-
var
|
|
2260
|
+
var import_react14 = require("react");
|
|
2261
|
+
var import_sdk7 = require("@hook-sdk/sdk");
|
|
2262
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2202
2263
|
var STORAGE_KEY = "hook_dev_skip_email";
|
|
2203
2264
|
var TEST_EMAIL_DOMAIN = "@hook.test";
|
|
2204
2265
|
var TEST_PASSWORD = "SkipTest!2026";
|
|
@@ -2265,18 +2326,18 @@ var STYLES = {
|
|
|
2265
2326
|
};
|
|
2266
2327
|
var CONFIRM_TIMEOUT_MS = 3e3;
|
|
2267
2328
|
function DevSkipOnboardingFab({ defaults }) {
|
|
2268
|
-
const hook = (0,
|
|
2329
|
+
const hook = (0, import_sdk7.useHook)();
|
|
2269
2330
|
const { slug } = useAppConfig();
|
|
2270
|
-
const [state, setState] = (0,
|
|
2271
|
-
const [errorMsg, setErrorMsg] = (0,
|
|
2272
|
-
const timerRef = (0,
|
|
2273
|
-
const clearTimer = (0,
|
|
2331
|
+
const [state, setState] = (0, import_react14.useState)("idle");
|
|
2332
|
+
const [errorMsg, setErrorMsg] = (0, import_react14.useState)(null);
|
|
2333
|
+
const timerRef = (0, import_react14.useRef)(null);
|
|
2334
|
+
const clearTimer = (0, import_react14.useCallback)(() => {
|
|
2274
2335
|
if (timerRef.current) {
|
|
2275
2336
|
clearTimeout(timerRef.current);
|
|
2276
2337
|
timerRef.current = null;
|
|
2277
2338
|
}
|
|
2278
2339
|
}, []);
|
|
2279
|
-
const onClick = (0,
|
|
2340
|
+
const onClick = (0, import_react14.useCallback)(async () => {
|
|
2280
2341
|
if (state === "busy") return;
|
|
2281
2342
|
if (state === "idle" || state === "error") {
|
|
2282
2343
|
setState("confirm");
|
|
@@ -2305,7 +2366,7 @@ function DevSkipOnboardingFab({ defaults }) {
|
|
|
2305
2366
|
...state === "confirm" || state === "error" ? STYLES.confirm : {},
|
|
2306
2367
|
...state === "busy" ? STYLES.busy : {}
|
|
2307
2368
|
};
|
|
2308
|
-
return /* @__PURE__ */ (0,
|
|
2369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2309
2370
|
"button",
|
|
2310
2371
|
{
|
|
2311
2372
|
type: "button",
|
|
@@ -2320,21 +2381,21 @@ function DevSkipOnboardingFab({ defaults }) {
|
|
|
2320
2381
|
}
|
|
2321
2382
|
|
|
2322
2383
|
// src/internal/PaymentReturnHandler.tsx
|
|
2323
|
-
var
|
|
2324
|
-
var
|
|
2325
|
-
var
|
|
2384
|
+
var import_react15 = require("react");
|
|
2385
|
+
var import_sdk8 = require("@hook-sdk/sdk");
|
|
2386
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2326
2387
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
2327
2388
|
var MAX_CYCLES = 3;
|
|
2328
2389
|
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
2329
2390
|
function PaymentReturnHandler({ children }) {
|
|
2330
|
-
const { subscription, track: track2 } = (0,
|
|
2331
|
-
const subRef = (0,
|
|
2391
|
+
const { subscription, track: track2 } = (0, import_sdk8.useHook)();
|
|
2392
|
+
const subRef = (0, import_react15.useRef)(subscription);
|
|
2332
2393
|
subRef.current = subscription;
|
|
2333
|
-
const runIdRef = (0,
|
|
2334
|
-
const cyclesRef = (0,
|
|
2335
|
-
const startMsRef = (0,
|
|
2336
|
-
const [state, setState] = (0,
|
|
2337
|
-
const runPoll = (0,
|
|
2394
|
+
const runIdRef = (0, import_react15.useRef)(0);
|
|
2395
|
+
const cyclesRef = (0, import_react15.useRef)(0);
|
|
2396
|
+
const startMsRef = (0, import_react15.useRef)(0);
|
|
2397
|
+
const [state, setState] = (0, import_react15.useState)("idle");
|
|
2398
|
+
const runPoll = (0, import_react15.useCallback)(() => {
|
|
2338
2399
|
const runId = ++runIdRef.current;
|
|
2339
2400
|
const isFirstRun = cyclesRef.current === 0;
|
|
2340
2401
|
cyclesRef.current += 1;
|
|
@@ -2382,7 +2443,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2382
2443
|
};
|
|
2383
2444
|
void tick();
|
|
2384
2445
|
}, [track2]);
|
|
2385
|
-
(0,
|
|
2446
|
+
(0, import_react15.useEffect)(() => {
|
|
2386
2447
|
if (typeof window === "undefined") return;
|
|
2387
2448
|
const url = new URL(window.location.href);
|
|
2388
2449
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -2392,26 +2453,26 @@ function PaymentReturnHandler({ children }) {
|
|
|
2392
2453
|
runIdRef.current++;
|
|
2393
2454
|
};
|
|
2394
2455
|
}, [runPoll]);
|
|
2395
|
-
const goHome = (0,
|
|
2456
|
+
const goHome = (0, import_react15.useCallback)(() => {
|
|
2396
2457
|
const cleanUrl = new URL(window.location.href);
|
|
2397
2458
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
2398
2459
|
cleanUrl.pathname = "/app/home";
|
|
2399
2460
|
window.location.href = cleanUrl.toString();
|
|
2400
2461
|
}, []);
|
|
2401
2462
|
if (state === "confirming") {
|
|
2402
|
-
return /* @__PURE__ */ (0,
|
|
2463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
|
|
2403
2464
|
}
|
|
2404
2465
|
if (state === "waiting") {
|
|
2405
|
-
return /* @__PURE__ */ (0,
|
|
2406
|
-
/* @__PURE__ */ (0,
|
|
2407
|
-
/* @__PURE__ */ (0,
|
|
2466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2467
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2468
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
|
|
2408
2469
|
] }) });
|
|
2409
2470
|
}
|
|
2410
2471
|
if (state === "timeout") {
|
|
2411
|
-
return /* @__PURE__ */ (0,
|
|
2412
|
-
/* @__PURE__ */ (0,
|
|
2413
|
-
/* @__PURE__ */ (0,
|
|
2414
|
-
/* @__PURE__ */ (0,
|
|
2472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2473
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("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." }),
|
|
2474
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2475
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2415
2476
|
"button",
|
|
2416
2477
|
{
|
|
2417
2478
|
type: "button",
|
|
@@ -2424,7 +2485,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2424
2485
|
children: "Tentar de novo"
|
|
2425
2486
|
}
|
|
2426
2487
|
),
|
|
2427
|
-
/* @__PURE__ */ (0,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2428
2489
|
"button",
|
|
2429
2490
|
{
|
|
2430
2491
|
type: "button",
|
|
@@ -2434,7 +2495,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2434
2495
|
children: "Voltar pro app"
|
|
2435
2496
|
}
|
|
2436
2497
|
),
|
|
2437
|
-
/* @__PURE__ */ (0,
|
|
2498
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2438
2499
|
"a",
|
|
2439
2500
|
{
|
|
2440
2501
|
href: SUPPORT_MAILTO,
|
|
@@ -2446,7 +2507,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2446
2507
|
] })
|
|
2447
2508
|
] }) });
|
|
2448
2509
|
}
|
|
2449
|
-
return /* @__PURE__ */ (0,
|
|
2510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, { children });
|
|
2450
2511
|
}
|
|
2451
2512
|
var overlayStyle2 = {
|
|
2452
2513
|
position: "fixed",
|
|
@@ -2485,7 +2546,7 @@ var linkStyle = {
|
|
|
2485
2546
|
};
|
|
2486
2547
|
|
|
2487
2548
|
// src/AppRoot.tsx
|
|
2488
|
-
var
|
|
2549
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2489
2550
|
function buildLegacyConfigShim(config) {
|
|
2490
2551
|
const paywall = config.paywall;
|
|
2491
2552
|
const isFree = paywall.mode === "free";
|
|
@@ -2559,19 +2620,22 @@ function AppRoot(props) {
|
|
|
2559
2620
|
"[hook-template] <AppRoot>: PreAuthFlow slot prop is required when config.onboarding.trigger === 'pre_signup_custom'."
|
|
2560
2621
|
);
|
|
2561
2622
|
}
|
|
2562
|
-
const legacyShim = (0,
|
|
2623
|
+
const legacyShim = (0, import_react16.useMemo)(() => buildLegacyConfigShim(config), [config]);
|
|
2563
2624
|
const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
|
|
2564
2625
|
const basename = `/app/${config.slug}`;
|
|
2565
2626
|
const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
|
|
2566
2627
|
const position = config.install_prompt?.position ?? "post-paywall";
|
|
2567
|
-
const subscriptionGated = /* @__PURE__ */ (0,
|
|
2568
|
-
|
|
2569
|
-
/* @__PURE__ */ (0,
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
2573
|
-
|
|
2574
|
-
|
|
2628
|
+
const subscriptionGated = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(SubscriptionGate, { Paywall: Paywall2 ?? FallbackPaywall, children: [
|
|
2629
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EmailVerifyBanner, {}),
|
|
2630
|
+
position === "post-paywall" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(InstallGate, { position: "post-paywall", children: [
|
|
2631
|
+
children,
|
|
2632
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PushPrompt, {})
|
|
2633
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
2634
|
+
children,
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PushPrompt, {})
|
|
2636
|
+
] })
|
|
2637
|
+
] });
|
|
2638
|
+
const authGated = /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2575
2639
|
AuthGated,
|
|
2576
2640
|
{
|
|
2577
2641
|
config,
|
|
@@ -2586,13 +2650,13 @@ function AppRoot(props) {
|
|
|
2586
2650
|
children: subscriptionGated
|
|
2587
2651
|
}
|
|
2588
2652
|
);
|
|
2589
|
-
const routedTree = /* @__PURE__ */ (0,
|
|
2590
|
-
/* @__PURE__ */ (0,
|
|
2591
|
-
/* @__PURE__ */ (0,
|
|
2592
|
-
position === "pre-auth" ? /* @__PURE__ */ (0,
|
|
2593
|
-
isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */ (0,
|
|
2653
|
+
const routedTree = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Router, { ...routerProps, children: [
|
|
2654
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SessionExpiredBanner, {}),
|
|
2656
|
+
position === "pre-auth" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InstallGate, { position: "pre-auth", children: authGated }) : authGated,
|
|
2657
|
+
isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DevSkipOnboardingFab, { defaults: devSkipOnboarding.defaults }) : null
|
|
2594
2658
|
] });
|
|
2595
|
-
return /* @__PURE__ */ (0,
|
|
2659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2596
2660
|
I18nProvider,
|
|
2597
2661
|
{
|
|
2598
2662
|
defaultLocale: config.i18n.defaultLocale,
|
|
@@ -2612,37 +2676,37 @@ function AuthGated({
|
|
|
2612
2676
|
EmailVerify,
|
|
2613
2677
|
PreAuthFlow
|
|
2614
2678
|
}) {
|
|
2615
|
-
const { authStatus } = (0,
|
|
2679
|
+
const { authStatus } = (0, import_sdk9.useHook)();
|
|
2616
2680
|
if (authStatus === "loading") return null;
|
|
2617
2681
|
if (authStatus !== "authenticated") {
|
|
2618
2682
|
if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
|
|
2619
|
-
return /* @__PURE__ */ (0,
|
|
2620
|
-
/* @__PURE__ */ (0,
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
2622
|
-
/* @__PURE__ */ (0,
|
|
2623
|
-
/* @__PURE__ */ (0,
|
|
2624
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2625
|
-
/* @__PURE__ */ (0,
|
|
2683
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Login, {}) }),
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Signup, {}) }),
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Forgot, {}) }),
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Reset, {}) }),
|
|
2688
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EmailVerify, {}) }) : null,
|
|
2689
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PreAuthFlow, {}) })
|
|
2626
2690
|
] });
|
|
2627
2691
|
}
|
|
2628
|
-
return /* @__PURE__ */ (0,
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
2630
|
-
/* @__PURE__ */ (0,
|
|
2631
|
-
/* @__PURE__ */ (0,
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2633
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2634
|
-
/* @__PURE__ */ (0,
|
|
2692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2693
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Login, {}) }),
|
|
2694
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Signup, {}) }),
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Forgot, {}) }),
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Reset, {}) }),
|
|
2697
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EmailVerify, {}) }) : null,
|
|
2698
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
|
|
2635
2699
|
] });
|
|
2636
2700
|
}
|
|
2637
|
-
return /* @__PURE__ */ (0,
|
|
2701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_jsx_runtime23.Fragment, { children });
|
|
2638
2702
|
}
|
|
2639
2703
|
function FallbackPaywall() {
|
|
2640
2704
|
return null;
|
|
2641
2705
|
}
|
|
2642
2706
|
|
|
2643
2707
|
// src/hooks/usePush.ts
|
|
2644
|
-
var
|
|
2645
|
-
var
|
|
2708
|
+
var import_react17 = require("react");
|
|
2709
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
2646
2710
|
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2647
2711
|
var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
2648
2712
|
function detectIosNeedsInstall() {
|
|
@@ -2686,12 +2750,12 @@ function deriveState(push) {
|
|
|
2686
2750
|
return { kind: "prompt" };
|
|
2687
2751
|
}
|
|
2688
2752
|
function usePush() {
|
|
2689
|
-
const { push } = (0,
|
|
2690
|
-
const [state, setState] = (0,
|
|
2691
|
-
(0,
|
|
2753
|
+
const { push } = (0, import_sdk10.useHook)();
|
|
2754
|
+
const [state, setState] = (0, import_react17.useState)(() => deriveState(push));
|
|
2755
|
+
(0, import_react17.useEffect)(() => {
|
|
2692
2756
|
setState(deriveState(push));
|
|
2693
2757
|
}, [push]);
|
|
2694
|
-
const subscribe = (0,
|
|
2758
|
+
const subscribe = (0, import_react17.useCallback)(async () => {
|
|
2695
2759
|
try {
|
|
2696
2760
|
await push.subscribe();
|
|
2697
2761
|
setState({ kind: "subscribed" });
|
|
@@ -2703,7 +2767,7 @@ function usePush() {
|
|
|
2703
2767
|
throw e;
|
|
2704
2768
|
}
|
|
2705
2769
|
}, [push]);
|
|
2706
|
-
const unsubscribe = (0,
|
|
2770
|
+
const unsubscribe = (0, import_react17.useCallback)(async () => {
|
|
2707
2771
|
try {
|
|
2708
2772
|
await push.unsubscribe();
|
|
2709
2773
|
setState({ kind: "prompt" });
|
|
@@ -2712,7 +2776,7 @@ function usePush() {
|
|
|
2712
2776
|
throw e;
|
|
2713
2777
|
}
|
|
2714
2778
|
}, [push]);
|
|
2715
|
-
const dismiss = (0,
|
|
2779
|
+
const dismiss = (0, import_react17.useCallback)(() => {
|
|
2716
2780
|
if (typeof localStorage !== "undefined") {
|
|
2717
2781
|
try {
|
|
2718
2782
|
localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS2));
|
|
@@ -2725,27 +2789,27 @@ function usePush() {
|
|
|
2725
2789
|
}
|
|
2726
2790
|
|
|
2727
2791
|
// src/components/PushPrompt.tsx
|
|
2728
|
-
var
|
|
2792
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2729
2793
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
2730
2794
|
const { state, subscribe } = usePush();
|
|
2731
2795
|
if (state.kind === "denied" || state.kind === "dismissed" || state.kind === "subscribed") {
|
|
2732
2796
|
return null;
|
|
2733
2797
|
}
|
|
2734
2798
|
if (state.kind === "ios_needs_install") {
|
|
2735
|
-
return /* @__PURE__ */ (0,
|
|
2736
|
-
/* @__PURE__ */ (0,
|
|
2737
|
-
/* @__PURE__ */ (0,
|
|
2738
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0,
|
|
2799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2800
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
2801
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { children: texts.iosInstallBody }),
|
|
2802
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
2739
2803
|
] });
|
|
2740
2804
|
}
|
|
2741
2805
|
if (state.kind === "unsupported") {
|
|
2742
|
-
return /* @__PURE__ */ (0,
|
|
2806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { children: texts.unsupportedBody }) });
|
|
2743
2807
|
}
|
|
2744
2808
|
if (state.kind === "error") {
|
|
2745
|
-
return /* @__PURE__ */ (0,
|
|
2809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { children: state.message }) });
|
|
2746
2810
|
}
|
|
2747
|
-
return /* @__PURE__ */ (0,
|
|
2748
|
-
/* @__PURE__ */ (0,
|
|
2811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className, role: "region", children: [
|
|
2812
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2749
2813
|
"button",
|
|
2750
2814
|
{
|
|
2751
2815
|
type: "button",
|
|
@@ -2759,67 +2823,67 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2759
2823
|
children: texts.cta
|
|
2760
2824
|
}
|
|
2761
2825
|
),
|
|
2762
|
-
onDeclined && /* @__PURE__ */ (0,
|
|
2826
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
2763
2827
|
] });
|
|
2764
2828
|
}
|
|
2765
2829
|
|
|
2766
2830
|
// src/components/LanguageSwitcher.tsx
|
|
2767
|
-
var
|
|
2768
|
-
var
|
|
2831
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2832
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2769
2833
|
function LanguageSwitcher({ id, className, label = "Language" }) {
|
|
2770
2834
|
const config = useAppConfig();
|
|
2771
2835
|
const i18nConfig = config.i18n;
|
|
2772
|
-
const [userLocale, setUserLocale] = (0,
|
|
2836
|
+
const [userLocale, setUserLocale] = (0, import_sdk11.usePersistedState)(
|
|
2773
2837
|
"user-locale",
|
|
2774
2838
|
i18nConfig?.defaultLocale ?? "en-US"
|
|
2775
2839
|
);
|
|
2776
2840
|
if (!i18nConfig) return null;
|
|
2777
|
-
return /* @__PURE__ */ (0,
|
|
2778
|
-
label ? /* @__PURE__ */ (0,
|
|
2779
|
-
/* @__PURE__ */ (0,
|
|
2841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className, children: [
|
|
2842
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: label }) : null,
|
|
2843
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2780
2844
|
"select",
|
|
2781
2845
|
{
|
|
2782
2846
|
id,
|
|
2783
2847
|
value: userLocale,
|
|
2784
2848
|
onChange: (e) => setUserLocale(e.target.value),
|
|
2785
2849
|
"data-testid": "language-switcher",
|
|
2786
|
-
children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ (0,
|
|
2850
|
+
children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: loc, children: loc }, loc))
|
|
2787
2851
|
}
|
|
2788
2852
|
)
|
|
2789
2853
|
] });
|
|
2790
2854
|
}
|
|
2791
2855
|
|
|
2792
2856
|
// src/defaults/LoadingState.tsx
|
|
2793
|
-
var
|
|
2857
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2794
2858
|
function LoadingState({ message }) {
|
|
2795
|
-
return /* @__PURE__ */ (0,
|
|
2859
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: message ?? "Carregando..." }) });
|
|
2796
2860
|
}
|
|
2797
2861
|
|
|
2798
2862
|
// src/defaults/EmptyState.tsx
|
|
2799
|
-
var
|
|
2863
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2800
2864
|
function EmptyState({ title, description, action }) {
|
|
2801
|
-
return /* @__PURE__ */ (0,
|
|
2802
|
-
/* @__PURE__ */ (0,
|
|
2803
|
-
description && /* @__PURE__ */ (0,
|
|
2804
|
-
action && /* @__PURE__ */ (0,
|
|
2865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2866
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2867
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
2868
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
2805
2869
|
] });
|
|
2806
2870
|
}
|
|
2807
2871
|
|
|
2808
2872
|
// src/hooks/useLoginForm.ts
|
|
2809
|
-
var
|
|
2810
|
-
var
|
|
2873
|
+
var import_react18 = require("react");
|
|
2874
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
2811
2875
|
|
|
2812
2876
|
// src/errors.ts
|
|
2813
|
-
var
|
|
2877
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
2814
2878
|
function mapSdkError(err) {
|
|
2815
|
-
if (err instanceof
|
|
2879
|
+
if (err instanceof import_sdk12.SdkRateLimitError) {
|
|
2816
2880
|
return {
|
|
2817
2881
|
code: "rate_limited",
|
|
2818
2882
|
message: `Aguarde ${err.retryAfter}s e tente novamente.`,
|
|
2819
2883
|
retryAfter: err.retryAfter
|
|
2820
2884
|
};
|
|
2821
2885
|
}
|
|
2822
|
-
if (err instanceof
|
|
2886
|
+
if (err instanceof import_sdk12.SdkAuthError) {
|
|
2823
2887
|
const detail = err.detail;
|
|
2824
2888
|
if (detail === "email_unverified") {
|
|
2825
2889
|
return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
|
|
@@ -2829,7 +2893,10 @@ function mapSdkError(err) {
|
|
|
2829
2893
|
}
|
|
2830
2894
|
return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
|
|
2831
2895
|
}
|
|
2832
|
-
if (err instanceof
|
|
2896
|
+
if (err instanceof import_sdk12.SdkValidationError && err.code === "auth.email_taken") {
|
|
2897
|
+
return { code: "email_taken", message: "Esse e-mail j\xE1 tem conta." };
|
|
2898
|
+
}
|
|
2899
|
+
if (err instanceof import_sdk12.SdkError && err.httpStatus === 0) {
|
|
2833
2900
|
return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
|
|
2834
2901
|
}
|
|
2835
2902
|
if (err instanceof TypeError) {
|
|
@@ -2842,20 +2909,20 @@ function mapSdkError(err) {
|
|
|
2842
2909
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2843
2910
|
var MIN_PASSWORD = 8;
|
|
2844
2911
|
function useLoginForm() {
|
|
2845
|
-
const { auth } = (0,
|
|
2846
|
-
const [email, setEmail] = (0,
|
|
2847
|
-
const [password, setPassword] = (0,
|
|
2848
|
-
const [submitting, setSubmitting] = (0,
|
|
2849
|
-
const [error, setError] = (0,
|
|
2850
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2851
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2852
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2853
|
-
const validateEmail = (0,
|
|
2912
|
+
const { auth } = (0, import_sdk13.useHook)();
|
|
2913
|
+
const [email, setEmail] = (0, import_react18.useState)("");
|
|
2914
|
+
const [password, setPassword] = (0, import_react18.useState)("");
|
|
2915
|
+
const [submitting, setSubmitting] = (0, import_react18.useState)(false);
|
|
2916
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
2917
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react18.useState)(false);
|
|
2918
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react18.useState)(false);
|
|
2919
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
|
|
2920
|
+
const validateEmail = (0, import_react18.useMemo)(() => {
|
|
2854
2921
|
if (email.length === 0) return null;
|
|
2855
2922
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2856
2923
|
return null;
|
|
2857
2924
|
}, [email]);
|
|
2858
|
-
const validatePassword = (0,
|
|
2925
|
+
const validatePassword = (0, import_react18.useMemo)(() => {
|
|
2859
2926
|
if (password.length === 0) return null;
|
|
2860
2927
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2861
2928
|
return null;
|
|
@@ -2863,7 +2930,7 @@ function useLoginForm() {
|
|
|
2863
2930
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2864
2931
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2865
2932
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2866
|
-
const submit = (0,
|
|
2933
|
+
const submit = (0, import_react18.useCallback)(async () => {
|
|
2867
2934
|
setFormSubmitAttempted(true);
|
|
2868
2935
|
if (!canSubmit) return false;
|
|
2869
2936
|
setSubmitting(true);
|
|
@@ -2897,32 +2964,32 @@ function useLoginForm() {
|
|
|
2897
2964
|
}
|
|
2898
2965
|
|
|
2899
2966
|
// src/hooks/useSignupForm.ts
|
|
2900
|
-
var
|
|
2901
|
-
var
|
|
2967
|
+
var import_react19 = require("react");
|
|
2968
|
+
var import_sdk14 = require("@hook-sdk/sdk");
|
|
2902
2969
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2903
2970
|
var MIN_PASSWORD2 = 8;
|
|
2904
2971
|
function useSignupForm() {
|
|
2905
|
-
const { auth } = (0,
|
|
2906
|
-
const [name, setName] = (0,
|
|
2907
|
-
const [email, setEmail] = (0,
|
|
2908
|
-
const [password, setPassword] = (0,
|
|
2909
|
-
const [submitting, setSubmitting] = (0,
|
|
2910
|
-
const [error, setError] = (0,
|
|
2911
|
-
const [touchedName, setTouchedName] = (0,
|
|
2912
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2913
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2914
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2915
|
-
const validateName = (0,
|
|
2972
|
+
const { auth } = (0, import_sdk14.useHook)();
|
|
2973
|
+
const [name, setName] = (0, import_react19.useState)("");
|
|
2974
|
+
const [email, setEmail] = (0, import_react19.useState)("");
|
|
2975
|
+
const [password, setPassword] = (0, import_react19.useState)("");
|
|
2976
|
+
const [submitting, setSubmitting] = (0, import_react19.useState)(false);
|
|
2977
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
2978
|
+
const [touchedName, setTouchedName] = (0, import_react19.useState)(false);
|
|
2979
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react19.useState)(false);
|
|
2980
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react19.useState)(false);
|
|
2981
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react19.useState)(false);
|
|
2982
|
+
const validateName = (0, import_react19.useMemo)(() => {
|
|
2916
2983
|
if (name.length === 0) return null;
|
|
2917
2984
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2918
2985
|
return null;
|
|
2919
2986
|
}, [name]);
|
|
2920
|
-
const validateEmail = (0,
|
|
2987
|
+
const validateEmail = (0, import_react19.useMemo)(() => {
|
|
2921
2988
|
if (email.length === 0) return null;
|
|
2922
2989
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2923
2990
|
return null;
|
|
2924
2991
|
}, [email]);
|
|
2925
|
-
const validatePassword = (0,
|
|
2992
|
+
const validatePassword = (0, import_react19.useMemo)(() => {
|
|
2926
2993
|
if (password.length === 0) return null;
|
|
2927
2994
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2928
2995
|
return null;
|
|
@@ -2931,7 +2998,7 @@ function useSignupForm() {
|
|
|
2931
2998
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2932
2999
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2933
3000
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2934
|
-
const submit = (0,
|
|
3001
|
+
const submit = (0, import_react19.useCallback)(async () => {
|
|
2935
3002
|
setFormSubmitAttempted(true);
|
|
2936
3003
|
if (!canSubmit) return false;
|
|
2937
3004
|
setSubmitting(true);
|
|
@@ -2969,25 +3036,25 @@ function useSignupForm() {
|
|
|
2969
3036
|
}
|
|
2970
3037
|
|
|
2971
3038
|
// src/hooks/useForgotForm.ts
|
|
2972
|
-
var
|
|
2973
|
-
var
|
|
3039
|
+
var import_react20 = require("react");
|
|
3040
|
+
var import_sdk15 = require("@hook-sdk/sdk");
|
|
2974
3041
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2975
3042
|
function useForgotForm() {
|
|
2976
|
-
const { auth } = (0,
|
|
2977
|
-
const [email, setEmail] = (0,
|
|
2978
|
-
const [submitting, setSubmitting] = (0,
|
|
2979
|
-
const [sent, setSent] = (0,
|
|
2980
|
-
const [error, setError] = (0,
|
|
2981
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2982
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2983
|
-
const validateEmail = (0,
|
|
3043
|
+
const { auth } = (0, import_sdk15.useHook)();
|
|
3044
|
+
const [email, setEmail] = (0, import_react20.useState)("");
|
|
3045
|
+
const [submitting, setSubmitting] = (0, import_react20.useState)(false);
|
|
3046
|
+
const [sent, setSent] = (0, import_react20.useState)(false);
|
|
3047
|
+
const [error, setError] = (0, import_react20.useState)(null);
|
|
3048
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react20.useState)(false);
|
|
3049
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react20.useState)(false);
|
|
3050
|
+
const validateEmail = (0, import_react20.useMemo)(() => {
|
|
2984
3051
|
if (email.length === 0) return null;
|
|
2985
3052
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2986
3053
|
return null;
|
|
2987
3054
|
}, [email]);
|
|
2988
3055
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2989
3056
|
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2990
|
-
const submit = (0,
|
|
3057
|
+
const submit = (0, import_react20.useCallback)(async () => {
|
|
2991
3058
|
setFormSubmitAttempted(true);
|
|
2992
3059
|
if (!canSubmit) return false;
|
|
2993
3060
|
setSubmitting(true);
|
|
@@ -3018,32 +3085,32 @@ function useForgotForm() {
|
|
|
3018
3085
|
}
|
|
3019
3086
|
|
|
3020
3087
|
// src/hooks/useResetForm.ts
|
|
3021
|
-
var
|
|
3022
|
-
var
|
|
3088
|
+
var import_react21 = require("react");
|
|
3089
|
+
var import_sdk16 = require("@hook-sdk/sdk");
|
|
3023
3090
|
var MIN_PASSWORD3 = 12;
|
|
3024
3091
|
function useResetForm() {
|
|
3025
|
-
const { auth } = (0,
|
|
3026
|
-
const [token, setToken] = (0,
|
|
3027
|
-
const [password, setPassword] = (0,
|
|
3028
|
-
const [confirm, setConfirm] = (0,
|
|
3029
|
-
const [submitting, setSubmitting] = (0,
|
|
3030
|
-
const [done, setDone] = (0,
|
|
3031
|
-
const [error, setError] = (0,
|
|
3032
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
3033
|
-
const [touchedConfirm, setTouchedConfirm] = (0,
|
|
3034
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
3035
|
-
(0,
|
|
3092
|
+
const { auth } = (0, import_sdk16.useHook)();
|
|
3093
|
+
const [token, setToken] = (0, import_react21.useState)(null);
|
|
3094
|
+
const [password, setPassword] = (0, import_react21.useState)("");
|
|
3095
|
+
const [confirm, setConfirm] = (0, import_react21.useState)("");
|
|
3096
|
+
const [submitting, setSubmitting] = (0, import_react21.useState)(false);
|
|
3097
|
+
const [done, setDone] = (0, import_react21.useState)(false);
|
|
3098
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
3099
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react21.useState)(false);
|
|
3100
|
+
const [touchedConfirm, setTouchedConfirm] = (0, import_react21.useState)(false);
|
|
3101
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react21.useState)(false);
|
|
3102
|
+
(0, import_react21.useEffect)(() => {
|
|
3036
3103
|
if (typeof window === "undefined") return;
|
|
3037
3104
|
const params = new URLSearchParams(window.location.search);
|
|
3038
3105
|
const t = params.get("token");
|
|
3039
3106
|
setToken(t && t.length > 0 ? t : null);
|
|
3040
3107
|
}, []);
|
|
3041
|
-
const validatePassword = (0,
|
|
3108
|
+
const validatePassword = (0, import_react21.useMemo)(() => {
|
|
3042
3109
|
if (password.length === 0) return null;
|
|
3043
3110
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
3044
3111
|
return null;
|
|
3045
3112
|
}, [password]);
|
|
3046
|
-
const validateConfirm = (0,
|
|
3113
|
+
const validateConfirm = (0, import_react21.useMemo)(() => {
|
|
3047
3114
|
if (confirm.length === 0) return null;
|
|
3048
3115
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
3049
3116
|
return null;
|
|
@@ -3051,7 +3118,7 @@ function useResetForm() {
|
|
|
3051
3118
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
3052
3119
|
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
3053
3120
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
3054
|
-
const submit = (0,
|
|
3121
|
+
const submit = (0, import_react21.useCallback)(async () => {
|
|
3055
3122
|
setFormSubmitAttempted(true);
|
|
3056
3123
|
if (!canSubmit || token === null) return;
|
|
3057
3124
|
setSubmitting(true);
|
|
@@ -3091,9 +3158,9 @@ function useResetForm() {
|
|
|
3091
3158
|
}
|
|
3092
3159
|
|
|
3093
3160
|
// src/hooks/usePlan.ts
|
|
3094
|
-
var
|
|
3161
|
+
var import_sdk17 = require("@hook-sdk/sdk");
|
|
3095
3162
|
function usePlan() {
|
|
3096
|
-
const { plan } = (0,
|
|
3163
|
+
const { plan } = (0, import_sdk17.useHook)();
|
|
3097
3164
|
return plan;
|
|
3098
3165
|
}
|
|
3099
3166
|
|
|
@@ -3126,12 +3193,12 @@ function discountPercent(anchorCents, realCents) {
|
|
|
3126
3193
|
}
|
|
3127
3194
|
|
|
3128
3195
|
// src/hooks/useAuthPrimitives.ts
|
|
3129
|
-
var
|
|
3130
|
-
var
|
|
3196
|
+
var import_react22 = require("react");
|
|
3197
|
+
var import_sdk18 = require("@hook-sdk/sdk");
|
|
3131
3198
|
var warned = false;
|
|
3132
3199
|
function useAuthPrimitives() {
|
|
3133
|
-
const { auth } = (0,
|
|
3134
|
-
(0,
|
|
3200
|
+
const { auth } = (0, import_sdk18.useHook)();
|
|
3201
|
+
(0, import_react22.useEffect)(() => {
|
|
3135
3202
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
3136
3203
|
warned = true;
|
|
3137
3204
|
console.warn(
|
|
@@ -3153,9 +3220,9 @@ function useAuthPrimitives() {
|
|
|
3153
3220
|
}
|
|
3154
3221
|
|
|
3155
3222
|
// src/hooks/useAuth.ts
|
|
3156
|
-
var
|
|
3223
|
+
var import_sdk19 = require("@hook-sdk/sdk");
|
|
3157
3224
|
function useAuth() {
|
|
3158
|
-
const { user, authStatus, auth } = (0,
|
|
3225
|
+
const { user, authStatus, auth } = (0, import_sdk19.useHook)();
|
|
3159
3226
|
return {
|
|
3160
3227
|
user,
|
|
3161
3228
|
authStatus,
|
|
@@ -3164,26 +3231,26 @@ function useAuth() {
|
|
|
3164
3231
|
}
|
|
3165
3232
|
|
|
3166
3233
|
// src/index.ts
|
|
3167
|
-
var
|
|
3234
|
+
var import_sdk24 = require("@hook-sdk/sdk");
|
|
3168
3235
|
|
|
3169
3236
|
// src/hooks/useSubscription.ts
|
|
3170
|
-
var
|
|
3237
|
+
var import_sdk20 = require("@hook-sdk/sdk");
|
|
3171
3238
|
function useSubscription() {
|
|
3172
|
-
const { subscription } = (0,
|
|
3239
|
+
const { subscription } = (0, import_sdk20.useHook)();
|
|
3173
3240
|
return {
|
|
3174
3241
|
status: subscription.status()
|
|
3175
3242
|
};
|
|
3176
3243
|
}
|
|
3177
3244
|
|
|
3178
3245
|
// src/hooks/useReminders.ts
|
|
3179
|
-
var
|
|
3180
|
-
var
|
|
3246
|
+
var import_react23 = require("react");
|
|
3247
|
+
var import_sdk21 = require("@hook-sdk/sdk");
|
|
3181
3248
|
function useReminders() {
|
|
3182
|
-
const { push } = (0,
|
|
3249
|
+
const { push } = (0, import_sdk21.useHook)();
|
|
3183
3250
|
const r = push.reminders;
|
|
3184
|
-
const [reminders, setReminders] = (0,
|
|
3185
|
-
const [loading, setLoading] = (0,
|
|
3186
|
-
const reload = (0,
|
|
3251
|
+
const [reminders, setReminders] = (0, import_react23.useState)([]);
|
|
3252
|
+
const [loading, setLoading] = (0, import_react23.useState)(true);
|
|
3253
|
+
const reload = (0, import_react23.useCallback)(async () => {
|
|
3187
3254
|
setLoading(true);
|
|
3188
3255
|
try {
|
|
3189
3256
|
const next = await r.list();
|
|
@@ -3192,38 +3259,38 @@ function useReminders() {
|
|
|
3192
3259
|
setLoading(false);
|
|
3193
3260
|
}
|
|
3194
3261
|
}, [r]);
|
|
3195
|
-
(0,
|
|
3262
|
+
(0, import_react23.useEffect)(() => {
|
|
3196
3263
|
void reload();
|
|
3197
3264
|
}, [reload]);
|
|
3198
|
-
const setReminder = (0,
|
|
3265
|
+
const setReminder = (0, import_react23.useCallback)(async (input) => {
|
|
3199
3266
|
await r.set(input);
|
|
3200
3267
|
await reload();
|
|
3201
3268
|
}, [r, reload]);
|
|
3202
|
-
const deleteReminder = (0,
|
|
3269
|
+
const deleteReminder = (0, import_react23.useCallback)(async (slot) => {
|
|
3203
3270
|
await r.delete(slot);
|
|
3204
3271
|
await reload();
|
|
3205
3272
|
}, [r, reload]);
|
|
3206
|
-
const schedule = (0,
|
|
3273
|
+
const schedule = (0, import_react23.useCallback)(async (items) => {
|
|
3207
3274
|
return r.schedule(items);
|
|
3208
3275
|
}, [r]);
|
|
3209
|
-
const setFallbacks = (0,
|
|
3276
|
+
const setFallbacks = (0, import_react23.useCallback)(async (items) => {
|
|
3210
3277
|
return r.setFallbacks(items);
|
|
3211
3278
|
}, [r]);
|
|
3212
3279
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
3213
3280
|
}
|
|
3214
3281
|
|
|
3215
3282
|
// src/hooks/useToast.ts
|
|
3216
|
-
var
|
|
3283
|
+
var import_react24 = require("react");
|
|
3217
3284
|
function useToast() {
|
|
3218
|
-
const [items, setItems] = (0,
|
|
3219
|
-
const show = (0,
|
|
3285
|
+
const [items, setItems] = (0, import_react24.useState)([]);
|
|
3286
|
+
const show = (0, import_react24.useCallback)((message, kind = "info") => {
|
|
3220
3287
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
3221
3288
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
3222
3289
|
setTimeout(() => {
|
|
3223
3290
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
3224
3291
|
}, 4e3);
|
|
3225
3292
|
}, []);
|
|
3226
|
-
const dismiss = (0,
|
|
3293
|
+
const dismiss = (0, import_react24.useCallback)((id) => {
|
|
3227
3294
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
3228
3295
|
}, []);
|
|
3229
3296
|
return { items, show, dismiss };
|
|
@@ -3231,20 +3298,20 @@ function useToast() {
|
|
|
3231
3298
|
|
|
3232
3299
|
// src/RouteBoundary.tsx
|
|
3233
3300
|
var import_react_router_dom3 = require("react-router-dom");
|
|
3234
|
-
var
|
|
3301
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3235
3302
|
function RouteBoundary({ children }) {
|
|
3236
|
-
return /* @__PURE__ */ (0,
|
|
3303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react_router_dom3.Routes, { children: [
|
|
3237
3304
|
children,
|
|
3238
|
-
/* @__PURE__ */ (0,
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(DefaultNotFound, {}) })
|
|
3239
3306
|
] });
|
|
3240
3307
|
}
|
|
3241
3308
|
function DefaultNotFound() {
|
|
3242
|
-
return /* @__PURE__ */ (0,
|
|
3309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
|
|
3243
3310
|
}
|
|
3244
3311
|
|
|
3245
3312
|
// src/PreAuthShell.tsx
|
|
3246
3313
|
var import_react_router_dom4 = require("react-router-dom");
|
|
3247
|
-
var
|
|
3314
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
3248
3315
|
function PreAuthShell({
|
|
3249
3316
|
basename,
|
|
3250
3317
|
testRouter,
|
|
@@ -3252,20 +3319,20 @@ function PreAuthShell({
|
|
|
3252
3319
|
children
|
|
3253
3320
|
}) {
|
|
3254
3321
|
if (testRouter === "memory") {
|
|
3255
|
-
return /* @__PURE__ */ (0,
|
|
3322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
3256
3323
|
}
|
|
3257
|
-
return /* @__PURE__ */ (0,
|
|
3324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
3258
3325
|
}
|
|
3259
3326
|
|
|
3260
3327
|
// src/OnboardingFlow.tsx
|
|
3261
|
-
var
|
|
3262
|
-
var
|
|
3328
|
+
var import_react26 = require("react");
|
|
3329
|
+
var import_sdk22 = require("@hook-sdk/sdk");
|
|
3263
3330
|
|
|
3264
3331
|
// src/hooks/useOnboardingStep.ts
|
|
3265
|
-
var
|
|
3266
|
-
var OnboardingStepContext = (0,
|
|
3332
|
+
var import_react25 = require("react");
|
|
3333
|
+
var OnboardingStepContext = (0, import_react25.createContext)(null);
|
|
3267
3334
|
function useOnboardingStep() {
|
|
3268
|
-
const ctx = (0,
|
|
3335
|
+
const ctx = (0, import_react25.useContext)(OnboardingStepContext);
|
|
3269
3336
|
if (!ctx) {
|
|
3270
3337
|
throw new Error(
|
|
3271
3338
|
"[hook-template] useOnboardingStep must be used inside <OnboardingFlow>. (G75)"
|
|
@@ -3275,7 +3342,7 @@ function useOnboardingStep() {
|
|
|
3275
3342
|
}
|
|
3276
3343
|
|
|
3277
3344
|
// src/OnboardingFlow.tsx
|
|
3278
|
-
var
|
|
3345
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3279
3346
|
var isFilled = (v) => v != null && v !== "";
|
|
3280
3347
|
var CURRENT_STEP_FIELD = "currentStep";
|
|
3281
3348
|
function readPersistedStepIdx(draft) {
|
|
@@ -3288,12 +3355,12 @@ function OnboardingFlow({
|
|
|
3288
3355
|
onComplete,
|
|
3289
3356
|
persistKey
|
|
3290
3357
|
}) {
|
|
3291
|
-
const [draft, setDraft, status] = (0,
|
|
3292
|
-
const draftRef = (0,
|
|
3358
|
+
const [draft, setDraft, status] = (0, import_sdk22.usePersistedState)(persistKey, {});
|
|
3359
|
+
const draftRef = (0, import_react26.useRef)(draft);
|
|
3293
3360
|
draftRef.current = draft;
|
|
3294
3361
|
const idx = readPersistedStepIdx(draft);
|
|
3295
3362
|
const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
|
|
3296
|
-
const setIdx = (0,
|
|
3363
|
+
const setIdx = (0, import_react26.useCallback)(
|
|
3297
3364
|
(n) => {
|
|
3298
3365
|
setDraft((prev) => {
|
|
3299
3366
|
const prevIdx = readPersistedStepIdx(prev);
|
|
@@ -3303,7 +3370,7 @@ function OnboardingFlow({
|
|
|
3303
3370
|
},
|
|
3304
3371
|
[setDraft]
|
|
3305
3372
|
);
|
|
3306
|
-
const setValue = (0,
|
|
3373
|
+
const setValue = (0, import_react26.useCallback)(
|
|
3307
3374
|
(patch) => {
|
|
3308
3375
|
draftRef.current = { ...draftRef.current, ...patch };
|
|
3309
3376
|
setDraft((prev) => ({ ...prev, ...patch }));
|
|
@@ -3311,9 +3378,9 @@ function OnboardingFlow({
|
|
|
3311
3378
|
[setDraft]
|
|
3312
3379
|
);
|
|
3313
3380
|
const step = steps[clampedIdx];
|
|
3314
|
-
const hookCtx = (0,
|
|
3381
|
+
const hookCtx = (0, import_sdk22.useHook)();
|
|
3315
3382
|
const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
|
|
3316
|
-
(0,
|
|
3383
|
+
(0, import_react26.useEffect)(() => {
|
|
3317
3384
|
if (status.loading) return;
|
|
3318
3385
|
if (!step) return;
|
|
3319
3386
|
if (!track2) return;
|
|
@@ -3323,11 +3390,11 @@ function OnboardingFlow({
|
|
|
3323
3390
|
total_steps: steps.length
|
|
3324
3391
|
});
|
|
3325
3392
|
}, [step?.id, clampedIdx, steps.length, status.loading, track2]);
|
|
3326
|
-
const valid = (0,
|
|
3393
|
+
const valid = (0, import_react26.useMemo)(
|
|
3327
3394
|
() => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
|
|
3328
3395
|
[draft, step]
|
|
3329
3396
|
);
|
|
3330
|
-
const next = (0,
|
|
3397
|
+
const next = (0, import_react26.useCallback)(() => {
|
|
3331
3398
|
if (!step) return;
|
|
3332
3399
|
const current = draftRef.current;
|
|
3333
3400
|
const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
|
|
@@ -3338,8 +3405,8 @@ function OnboardingFlow({
|
|
|
3338
3405
|
setIdx(clampedIdx + 1);
|
|
3339
3406
|
}
|
|
3340
3407
|
}, [clampedIdx, onComplete, step, steps.length, setIdx]);
|
|
3341
|
-
const prevStep = (0,
|
|
3342
|
-
const ctx = (0,
|
|
3408
|
+
const prevStep = (0, import_react26.useCallback)(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
|
|
3409
|
+
const ctx = (0, import_react26.useMemo)(
|
|
3343
3410
|
() => ({
|
|
3344
3411
|
stepIndex: clampedIdx,
|
|
3345
3412
|
totalSteps: steps.length,
|
|
@@ -3365,7 +3432,7 @@ function OnboardingFlow({
|
|
|
3365
3432
|
`[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
|
|
3366
3433
|
);
|
|
3367
3434
|
}
|
|
3368
|
-
return /* @__PURE__ */ (0,
|
|
3435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Screen, {}) });
|
|
3369
3436
|
}
|
|
3370
3437
|
|
|
3371
3438
|
// src/hooks/useFeature.ts
|
|
@@ -3375,25 +3442,42 @@ function useFeature(name) {
|
|
|
3375
3442
|
}
|
|
3376
3443
|
|
|
3377
3444
|
// src/components/paywall/Paywall.tsx
|
|
3378
|
-
var
|
|
3379
|
-
var
|
|
3445
|
+
var import_react29 = require("react");
|
|
3446
|
+
var import_sdk23 = require("@hook-sdk/sdk");
|
|
3447
|
+
|
|
3448
|
+
// src/components/paywall/PaywallProvider.tsx
|
|
3449
|
+
var import_react27 = require("react");
|
|
3450
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
3451
|
+
var PaywallContext = (0, import_react27.createContext)(null);
|
|
3452
|
+
function PaywallProvider({ children }) {
|
|
3453
|
+
const state = usePaywallState();
|
|
3454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(PaywallContext.Provider, { value: state, children });
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
// src/components/paywall/usePaywallContext.ts
|
|
3458
|
+
var import_react28 = require("react");
|
|
3459
|
+
function usePaywallContext() {
|
|
3460
|
+
const ctx = (0, import_react28.useContext)(PaywallContext);
|
|
3461
|
+
if (!ctx) {
|
|
3462
|
+
throw new Error("usePaywallContext must be used within <PaywallProvider>");
|
|
3463
|
+
}
|
|
3464
|
+
return ctx;
|
|
3465
|
+
}
|
|
3380
3466
|
|
|
3381
3467
|
// src/components/paywall/PaywallMethodTabs.tsx
|
|
3382
|
-
var
|
|
3468
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
3383
3469
|
function PaywallMethodTabs({
|
|
3384
|
-
methods,
|
|
3385
|
-
selected,
|
|
3386
|
-
onSelect,
|
|
3387
3470
|
labels,
|
|
3388
3471
|
className,
|
|
3389
3472
|
tabClassName,
|
|
3390
3473
|
tabActiveClassName
|
|
3391
3474
|
}) {
|
|
3475
|
+
const { methods, selectedMethod, selectMethod } = usePaywallContext();
|
|
3392
3476
|
if (methods.length < 2) return null;
|
|
3393
|
-
return /* @__PURE__ */ (0,
|
|
3394
|
-
const active = m ===
|
|
3477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "tablist", "aria-label": "M\xE9todo de pagamento", className, children: methods.map((m) => {
|
|
3478
|
+
const active = m === selectedMethod;
|
|
3395
3479
|
const label = labels[m] ?? m;
|
|
3396
|
-
return /* @__PURE__ */ (0,
|
|
3480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
3397
3481
|
"button",
|
|
3398
3482
|
{
|
|
3399
3483
|
type: "button",
|
|
@@ -3401,7 +3485,7 @@ function PaywallMethodTabs({
|
|
|
3401
3485
|
"aria-selected": active,
|
|
3402
3486
|
"aria-controls": `paywall-tab-${m}`,
|
|
3403
3487
|
tabIndex: active ? 0 : -1,
|
|
3404
|
-
onClick: () =>
|
|
3488
|
+
onClick: () => selectMethod(m),
|
|
3405
3489
|
className: [tabClassName, active ? tabActiveClassName : ""].filter(Boolean).join(" "),
|
|
3406
3490
|
children: label
|
|
3407
3491
|
},
|
|
@@ -3411,36 +3495,51 @@ function PaywallMethodTabs({
|
|
|
3411
3495
|
}
|
|
3412
3496
|
|
|
3413
3497
|
// src/components/paywall/PaywallMethodContent.tsx
|
|
3414
|
-
var
|
|
3415
|
-
function PaywallMethodContent({
|
|
3416
|
-
|
|
3417
|
-
copy
|
|
3418
|
-
|
|
3419
|
-
className,
|
|
3420
|
-
rowClassName
|
|
3421
|
-
}) {
|
|
3422
|
-
const useCardConsumed = method === "card" && hasConsumedTrial && copy.cardConsumedTrial;
|
|
3423
|
-
const rows = useCardConsumed ? copy.cardConsumedTrial.bodyRows : method === "pix-auto" || method === "pix-once" ? copy.pix.bodyRows : copy.card.bodyRows;
|
|
3424
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { role: "tabpanel", id: `paywall-tab-${method}`, className, children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: rowClassName, children: row }, i)) });
|
|
3498
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
3499
|
+
function PaywallMethodContent({ copy, className, rowClassName }) {
|
|
3500
|
+
const { selectedMethod, hasConsumedTrial } = usePaywallContext();
|
|
3501
|
+
const useCardConsumed = selectedMethod === "card" && hasConsumedTrial && copy.cardConsumedTrial;
|
|
3502
|
+
const rows = useCardConsumed ? copy.cardConsumedTrial.bodyRows : selectedMethod === "pix-auto" || selectedMethod === "pix-once" ? copy.pix.bodyRows : copy.card.bodyRows;
|
|
3503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { role: "tabpanel", id: `paywall-tab-${selectedMethod}`, className, children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: rowClassName, children: row }, i)) });
|
|
3425
3504
|
}
|
|
3426
3505
|
|
|
3427
3506
|
// src/components/paywall/PaywallCyclePicker.tsx
|
|
3428
|
-
var
|
|
3507
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
3508
|
+
var VARIANT_CLASSES = {
|
|
3509
|
+
default: { card: "", cardSelected: "" },
|
|
3510
|
+
"premium-gold": {
|
|
3511
|
+
card: "",
|
|
3512
|
+
cardSelected: "border-2 border-yellow-400/80 ring-2 ring-yellow-400/20"
|
|
3513
|
+
},
|
|
3514
|
+
"pink-pill": {
|
|
3515
|
+
card: "rounded-2xl",
|
|
3516
|
+
cardSelected: "border-2 border-pink-500"
|
|
3517
|
+
}
|
|
3518
|
+
};
|
|
3429
3519
|
function PaywallCyclePicker({
|
|
3430
|
-
cycles,
|
|
3431
|
-
selected,
|
|
3432
|
-
onSelect,
|
|
3433
|
-
priceCentsByCycle,
|
|
3434
|
-
anchorCentsByCycle,
|
|
3435
|
-
monthlyEquivByCycle,
|
|
3436
3520
|
labels,
|
|
3437
3521
|
className,
|
|
3438
3522
|
cardClassName,
|
|
3439
3523
|
cardSelectedClassName,
|
|
3440
|
-
anchorClassName
|
|
3524
|
+
anchorClassName,
|
|
3525
|
+
variant = "default",
|
|
3526
|
+
render
|
|
3441
3527
|
}) {
|
|
3528
|
+
const ctx = usePaywallContext();
|
|
3529
|
+
const { cycle: selected, setCycle, plan, anchorPriceCents } = ctx;
|
|
3530
|
+
const cycles = ["MONTHLY", "YEARLY"];
|
|
3531
|
+
if (render) {
|
|
3532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className, children: render({ cycles, selected, setCycle, plan, anchorPriceCents }) });
|
|
3533
|
+
}
|
|
3442
3534
|
if (cycles.length < 2) return null;
|
|
3443
|
-
|
|
3535
|
+
const v = VARIANT_CLASSES[variant];
|
|
3536
|
+
const composedCardClassName = [v.card, cardClassName].filter(Boolean).join(" ");
|
|
3537
|
+
const composedCardSelectedClassName = [v.cardSelected, cardSelectedClassName].filter(Boolean).join(" ");
|
|
3538
|
+
const monthlyCents = plan?.monthlyCents ?? 0;
|
|
3539
|
+
const yearlyCents = plan?.yearlyCents ?? 0;
|
|
3540
|
+
const anchorMonthly = plan?.anchorMonthlyCents ?? null;
|
|
3541
|
+
const anchorYearly = plan?.anchorYearlyCents ?? null;
|
|
3542
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
3444
3543
|
"div",
|
|
3445
3544
|
{
|
|
3446
3545
|
role: "radiogroup",
|
|
@@ -3450,21 +3549,25 @@ function PaywallCyclePicker({
|
|
|
3450
3549
|
const active = c === selected;
|
|
3451
3550
|
const label = c === "YEARLY" ? labels.annualLabel : labels.monthlyLabel;
|
|
3452
3551
|
const suffix = c === "YEARLY" ? labels.annualSuffix : labels.monthlySuffix;
|
|
3453
|
-
const mainCents = c === "YEARLY" ?
|
|
3454
|
-
const anchorCents =
|
|
3455
|
-
return /* @__PURE__ */ (0,
|
|
3552
|
+
const mainCents = c === "YEARLY" ? Math.round(yearlyCents / 12) : monthlyCents;
|
|
3553
|
+
const anchorCents = c === "YEARLY" ? anchorYearly : anchorMonthly;
|
|
3554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
3456
3555
|
"button",
|
|
3457
3556
|
{
|
|
3458
3557
|
type: "button",
|
|
3459
3558
|
role: "radio",
|
|
3460
3559
|
"aria-checked": active,
|
|
3461
|
-
onClick: () =>
|
|
3462
|
-
className: [
|
|
3560
|
+
onClick: () => setCycle(c),
|
|
3561
|
+
className: [
|
|
3562
|
+
"flex flex-col items-center gap-0.5",
|
|
3563
|
+
composedCardClassName,
|
|
3564
|
+
active ? composedCardSelectedClassName : ""
|
|
3565
|
+
].filter(Boolean).join(" "),
|
|
3463
3566
|
children: [
|
|
3464
|
-
/* @__PURE__ */ (0,
|
|
3465
|
-
/* @__PURE__ */ (0,
|
|
3466
|
-
/* @__PURE__ */ (0,
|
|
3467
|
-
anchorCents != null && anchorCents > mainCents ? /* @__PURE__ */ (0,
|
|
3567
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "font-bold text-base leading-tight", children: formatBRL(mainCents) }),
|
|
3568
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-xs opacity-70 leading-tight", children: suffix }),
|
|
3569
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-xs opacity-60 leading-tight", children: label }),
|
|
3570
|
+
anchorCents != null && anchorCents > mainCents ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: anchorClassName ?? "text-xs opacity-50", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("s", { children: formatBRL(anchorCents) }) }) : null
|
|
3468
3571
|
]
|
|
3469
3572
|
},
|
|
3470
3573
|
c
|
|
@@ -3474,40 +3577,8 @@ function PaywallCyclePicker({
|
|
|
3474
3577
|
);
|
|
3475
3578
|
}
|
|
3476
3579
|
|
|
3477
|
-
// src/components/paywall/PaywallCta.tsx
|
|
3478
|
-
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
3479
|
-
function PaywallCta({
|
|
3480
|
-
ctaLabel,
|
|
3481
|
-
loadingLabel,
|
|
3482
|
-
switchHint,
|
|
3483
|
-
trustLine,
|
|
3484
|
-
onClick,
|
|
3485
|
-
disabled = false,
|
|
3486
|
-
loading = false,
|
|
3487
|
-
className,
|
|
3488
|
-
buttonClassName,
|
|
3489
|
-
switchHintClassName,
|
|
3490
|
-
trustClassName
|
|
3491
|
-
}) {
|
|
3492
|
-
const label = loading && loadingLabel ? loadingLabel : ctaLabel;
|
|
3493
|
-
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className, children: [
|
|
3494
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
3495
|
-
"button",
|
|
3496
|
-
{
|
|
3497
|
-
type: "button",
|
|
3498
|
-
onClick,
|
|
3499
|
-
disabled: disabled || loading,
|
|
3500
|
-
className: buttonClassName,
|
|
3501
|
-
children: label
|
|
3502
|
-
}
|
|
3503
|
-
),
|
|
3504
|
-
switchHint ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: switchHintClassName, children: switchHint }) : null,
|
|
3505
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: trustClassName, children: trustLine })
|
|
3506
|
-
] });
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
3580
|
// src/components/paywall/Paywall.tsx
|
|
3510
|
-
var
|
|
3581
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
3511
3582
|
var NBSP = "\xA0";
|
|
3512
3583
|
function Paywall({
|
|
3513
3584
|
copy,
|
|
@@ -3515,21 +3586,42 @@ function Paywall({
|
|
|
3515
3586
|
slots = {},
|
|
3516
3587
|
onBeforeCheckout
|
|
3517
3588
|
}) {
|
|
3518
|
-
|
|
3519
|
-
|
|
3589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(PaywallProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3590
|
+
PaywallInner,
|
|
3591
|
+
{
|
|
3592
|
+
copy,
|
|
3593
|
+
themeClasses,
|
|
3594
|
+
slots,
|
|
3595
|
+
onBeforeCheckout
|
|
3596
|
+
}
|
|
3597
|
+
) });
|
|
3598
|
+
}
|
|
3599
|
+
function PaywallInner({
|
|
3600
|
+
copy,
|
|
3601
|
+
themeClasses = {},
|
|
3602
|
+
slots = {},
|
|
3603
|
+
onBeforeCheckout
|
|
3604
|
+
}) {
|
|
3605
|
+
const { track: track2 } = (0, import_sdk23.useHook)();
|
|
3606
|
+
const s = usePaywallContext();
|
|
3520
3607
|
const priceLabel = formatBRL(s.currentPriceCents).replace(new RegExp(NBSP, "g"), " ");
|
|
3521
|
-
const monthlyEquivLabel = formatBRL(s.currentMonthlyEquivCents).replace(new RegExp(NBSP, "g"), " ");
|
|
3522
3608
|
const trialDaysCardLabel = String(s.trialDaysCard);
|
|
3523
|
-
const ctaLabel = (0,
|
|
3609
|
+
const ctaLabel = (0, import_react29.useMemo)(() => {
|
|
3524
3610
|
if (s.isFree) return copy.freeCta ?? "Come\xE7ar agora";
|
|
3525
3611
|
if (s.selectedMethod === "card") {
|
|
3526
3612
|
if (s.hasConsumedTrial && copy.cardConsumedTrial) {
|
|
3527
|
-
return interp(copy.cardConsumedTrial.ctaTemplate, {
|
|
3613
|
+
return interp(copy.cardConsumedTrial.ctaTemplate, {
|
|
3614
|
+
price: priceLabel,
|
|
3615
|
+
days: trialDaysCardLabel
|
|
3616
|
+
});
|
|
3528
3617
|
}
|
|
3529
3618
|
if (s.trialDaysCard > 0) {
|
|
3530
3619
|
return interp(copy.card.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel });
|
|
3531
3620
|
}
|
|
3532
|
-
return copy.cardConsumedTrial ? interp(copy.cardConsumedTrial.ctaTemplate, {
|
|
3621
|
+
return copy.cardConsumedTrial ? interp(copy.cardConsumedTrial.ctaTemplate, {
|
|
3622
|
+
price: priceLabel,
|
|
3623
|
+
days: trialDaysCardLabel
|
|
3624
|
+
}) : `Assinar por ${priceLabel}`;
|
|
3533
3625
|
}
|
|
3534
3626
|
return interp(copy.pix.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel });
|
|
3535
3627
|
}, [
|
|
@@ -3541,11 +3633,11 @@ function Paywall({
|
|
|
3541
3633
|
priceLabel,
|
|
3542
3634
|
trialDaysCardLabel
|
|
3543
3635
|
]);
|
|
3544
|
-
const switchHint = (0,
|
|
3636
|
+
const switchHint = (0, import_react29.useMemo)(() => {
|
|
3545
3637
|
if (s.methods.length < 2) return void 0;
|
|
3546
3638
|
return s.selectedMethod === "card" ? copy.card.switchHint : copy.pix.switchHint;
|
|
3547
3639
|
}, [s.methods.length, s.selectedMethod, copy]);
|
|
3548
|
-
(0,
|
|
3640
|
+
(0, import_react29.useEffect)(() => {
|
|
3549
3641
|
if (!s.initialLoadComplete) return;
|
|
3550
3642
|
track2("paywall_view", {
|
|
3551
3643
|
default_method: s.selectedMethod,
|
|
@@ -3567,54 +3659,35 @@ function Paywall({
|
|
|
3567
3659
|
await s.submit();
|
|
3568
3660
|
};
|
|
3569
3661
|
const ctaTheme = s.selectedMethod === "card" ? themeClasses.ctaCard : themeClasses.ctaPix;
|
|
3570
|
-
return /* @__PURE__ */ (0,
|
|
3662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: themeClasses.container, children: [
|
|
3571
3663
|
slots.heroSlot,
|
|
3572
|
-
/* @__PURE__ */ (0,
|
|
3573
|
-
/* @__PURE__ */ (0,
|
|
3664
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { className: themeClasses.headline, children: copy.headline }),
|
|
3665
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { children: copy.features.map((f) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: themeClasses.feature, children: [
|
|
3574
3666
|
"\u2713 ",
|
|
3575
|
-
/* @__PURE__ */ (0,
|
|
3667
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: f })
|
|
3576
3668
|
] }, f)) }),
|
|
3577
|
-
copy.socialProof ? /* @__PURE__ */ (0,
|
|
3578
|
-
slots.cyclePickerSlot ?? /* @__PURE__ */ (0,
|
|
3669
|
+
copy.socialProof ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: themeClasses.socialProof, children: copy.socialProof }) : null,
|
|
3670
|
+
slots.cyclePickerSlot ?? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3579
3671
|
PaywallCyclePicker,
|
|
3580
3672
|
{
|
|
3581
|
-
cycles: ["MONTHLY", "YEARLY"],
|
|
3582
|
-
selected: s.cycle,
|
|
3583
|
-
onSelect: s.selectCycle,
|
|
3584
|
-
priceCentsByCycle: {
|
|
3585
|
-
MONTHLY: priceCentsForCycle(s, "MONTHLY"),
|
|
3586
|
-
YEARLY: priceCentsForCycle(s, "YEARLY")
|
|
3587
|
-
},
|
|
3588
|
-
anchorCentsByCycle: {
|
|
3589
|
-
MONTHLY: anchorForCycle(s, "MONTHLY"),
|
|
3590
|
-
YEARLY: anchorForCycle(s, "YEARLY")
|
|
3591
|
-
},
|
|
3592
|
-
monthlyEquivByCycle: {
|
|
3593
|
-
MONTHLY: priceCentsForCycle(s, "MONTHLY"),
|
|
3594
|
-
YEARLY: Math.round(priceCentsForCycle(s, "YEARLY") / 12)
|
|
3595
|
-
},
|
|
3596
3673
|
labels: copy.cycle,
|
|
3597
3674
|
cardClassName: themeClasses.cycleCard,
|
|
3598
3675
|
cardSelectedClassName: themeClasses.cycleCardSelected,
|
|
3599
3676
|
anchorClassName: themeClasses.anchorPrice
|
|
3600
3677
|
}
|
|
3601
3678
|
),
|
|
3602
|
-
/* @__PURE__ */ (0,
|
|
3679
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3603
3680
|
PaywallMethodTabs,
|
|
3604
3681
|
{
|
|
3605
|
-
methods: s.methods,
|
|
3606
|
-
selected: s.selectedMethod,
|
|
3607
|
-
onSelect: s.selectMethod,
|
|
3608
3682
|
labels: { "pix-auto": copy.pix.tabLabel, card: copy.card.tabLabel },
|
|
3609
3683
|
className: themeClasses.tabs,
|
|
3610
3684
|
tabClassName: themeClasses.tab,
|
|
3611
3685
|
tabActiveClassName: themeClasses.tabActive
|
|
3612
3686
|
}
|
|
3613
3687
|
),
|
|
3614
|
-
/* @__PURE__ */ (0,
|
|
3688
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3615
3689
|
PaywallMethodContent,
|
|
3616
3690
|
{
|
|
3617
|
-
method: s.selectedMethod,
|
|
3618
3691
|
copy: {
|
|
3619
3692
|
pix: interpolateCopy(copy.pix, priceLabel, trialDaysCardLabel),
|
|
3620
3693
|
card: interpolateCopy(copy.card, priceLabel, trialDaysCardLabel),
|
|
@@ -3625,27 +3698,27 @@ function Paywall({
|
|
|
3625
3698
|
ctaTemplate: copy.cardConsumedTrial.ctaTemplate
|
|
3626
3699
|
} : void 0
|
|
3627
3700
|
},
|
|
3628
|
-
hasConsumedTrial: s.hasConsumedTrial,
|
|
3629
3701
|
className: themeClasses.tabContent,
|
|
3630
3702
|
rowClassName: themeClasses.tabContentRow
|
|
3631
3703
|
}
|
|
3632
3704
|
),
|
|
3633
3705
|
slots.beforeCtaSlot,
|
|
3634
|
-
/* @__PURE__ */ (0,
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
}
|
|
3648
|
-
|
|
3706
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
3707
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3708
|
+
"button",
|
|
3709
|
+
{
|
|
3710
|
+
type: "button",
|
|
3711
|
+
onClick: () => {
|
|
3712
|
+
void handleCta();
|
|
3713
|
+
},
|
|
3714
|
+
disabled: s.submitting,
|
|
3715
|
+
className: ctaTheme,
|
|
3716
|
+
children: s.submitting ? "Abrindo checkout\u2026" : ctaLabel
|
|
3717
|
+
}
|
|
3718
|
+
),
|
|
3719
|
+
switchHint ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: themeClasses.switchHint, children: switchHint }) : null,
|
|
3720
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: themeClasses.trustLine, children: copy.trustLine })
|
|
3721
|
+
] })
|
|
3649
3722
|
] });
|
|
3650
3723
|
}
|
|
3651
3724
|
function interp(tpl, vars) {
|
|
@@ -3659,13 +3732,438 @@ function interpolateCopy(m, price, days) {
|
|
|
3659
3732
|
switchHint: m.switchHint
|
|
3660
3733
|
};
|
|
3661
3734
|
}
|
|
3662
|
-
|
|
3663
|
-
|
|
3735
|
+
|
|
3736
|
+
// src/components/paywall/PaywallCta.tsx
|
|
3737
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
3738
|
+
function PaywallCta({
|
|
3739
|
+
ctaLabel,
|
|
3740
|
+
loadingLabel,
|
|
3741
|
+
switchHint,
|
|
3742
|
+
trustLine,
|
|
3743
|
+
className,
|
|
3744
|
+
buttonClassName,
|
|
3745
|
+
switchHintClassName,
|
|
3746
|
+
trustClassName
|
|
3747
|
+
}) {
|
|
3748
|
+
const { submit, submitting } = usePaywallContext();
|
|
3749
|
+
const label = submitting && loadingLabel ? loadingLabel : ctaLabel;
|
|
3750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className, children: [
|
|
3751
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
3752
|
+
"button",
|
|
3753
|
+
{
|
|
3754
|
+
type: "button",
|
|
3755
|
+
onClick: () => {
|
|
3756
|
+
void submit();
|
|
3757
|
+
},
|
|
3758
|
+
disabled: submitting,
|
|
3759
|
+
className: buttonClassName,
|
|
3760
|
+
children: label
|
|
3761
|
+
}
|
|
3762
|
+
),
|
|
3763
|
+
switchHint ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: switchHintClassName, children: switchHint }) : null,
|
|
3764
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: trustClassName, children: trustLine })
|
|
3765
|
+
] });
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
// src/components/paywall/blocks/PaywallEyebrow.tsx
|
|
3769
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
3770
|
+
var DEFAULT_EYEBROW_CLASSES = "text-xs uppercase tracking-widest font-semibold opacity-70";
|
|
3771
|
+
function PaywallEyebrow({ text, className }) {
|
|
3772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: [DEFAULT_EYEBROW_CLASSES, className].filter(Boolean).join(" "), children: text });
|
|
3664
3773
|
}
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3774
|
+
|
|
3775
|
+
// src/components/paywall/blocks/PaywallHero.tsx
|
|
3776
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
3777
|
+
var DEFAULT_GRADIENT = "absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent";
|
|
3778
|
+
function PaywallHero({
|
|
3779
|
+
src,
|
|
3780
|
+
alt = "",
|
|
3781
|
+
headline,
|
|
3782
|
+
aspectRatio = "16/9",
|
|
3783
|
+
gradientClassName,
|
|
3784
|
+
className,
|
|
3785
|
+
headlineClassName,
|
|
3786
|
+
imgClassName,
|
|
3787
|
+
render
|
|
3788
|
+
}) {
|
|
3789
|
+
if (render) {
|
|
3790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className, children: render({ src, headline }) });
|
|
3791
|
+
}
|
|
3792
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
3793
|
+
"div",
|
|
3794
|
+
{
|
|
3795
|
+
className: ["relative overflow-hidden", className].filter(Boolean).join(" "),
|
|
3796
|
+
style: { aspectRatio },
|
|
3797
|
+
children: [
|
|
3798
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
3799
|
+
"img",
|
|
3800
|
+
{
|
|
3801
|
+
src,
|
|
3802
|
+
alt,
|
|
3803
|
+
className: ["absolute inset-0 w-full h-full object-cover", imgClassName].filter(Boolean).join(" ")
|
|
3804
|
+
}
|
|
3805
|
+
),
|
|
3806
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: gradientClassName ?? DEFAULT_GRADIENT, "aria-hidden": "true" }),
|
|
3807
|
+
headline ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
3808
|
+
"h1",
|
|
3809
|
+
{
|
|
3810
|
+
className: ["absolute bottom-0 left-0 right-0 p-4 text-white font-bold text-2xl", headlineClassName].filter(Boolean).join(" "),
|
|
3811
|
+
children: headline
|
|
3812
|
+
}
|
|
3813
|
+
) : null
|
|
3814
|
+
]
|
|
3815
|
+
}
|
|
3816
|
+
);
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3819
|
+
// src/components/paywall/blocks/PaywallHeadline.tsx
|
|
3820
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3821
|
+
var DEFAULT_HEADLINE_CLASSES = "text-2xl font-bold leading-tight";
|
|
3822
|
+
function PaywallHeadline({ text, className, as = "h1" }) {
|
|
3823
|
+
const Tag = as;
|
|
3824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Tag, { className: [DEFAULT_HEADLINE_CLASSES, className].filter(Boolean).join(" "), children: text });
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
// src/components/paywall/blocks/PaywallPriceHeadline.tsx
|
|
3828
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3829
|
+
var DEFAULT_CLASS = "text-2xl font-bold leading-tight";
|
|
3830
|
+
var CYCLE_LABEL = {
|
|
3831
|
+
MONTHLY: "mensal",
|
|
3832
|
+
YEARLY: "anual"
|
|
3833
|
+
};
|
|
3834
|
+
function PaywallPriceHeadline({
|
|
3835
|
+
template,
|
|
3836
|
+
className,
|
|
3837
|
+
as = "h1",
|
|
3838
|
+
render
|
|
3839
|
+
}) {
|
|
3840
|
+
const { cycle, currentMonthlyEquivCents, plan } = usePaywallContext();
|
|
3841
|
+
const yearlyCents = plan?.yearlyCents ?? null;
|
|
3842
|
+
const pricePerDay = formatBRL(dailyFromYearly(yearlyCents));
|
|
3843
|
+
const monthlyEquiv = currentMonthlyEquivCents ?? 0;
|
|
3844
|
+
const cycleLabel = CYCLE_LABEL[cycle] ?? cycle.toLowerCase();
|
|
3845
|
+
const rootClasses = [DEFAULT_CLASS, className].filter(Boolean).join(" ");
|
|
3846
|
+
if (render) {
|
|
3847
|
+
const RootTag2 = as;
|
|
3848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RootTag2, { className: [className].filter(Boolean).join(" ") || void 0, children: render({ pricePerDay, currentMonthlyEquivCents: monthlyEquiv, cycle }) });
|
|
3849
|
+
}
|
|
3850
|
+
const text = template.replaceAll("{pricePerDay}", pricePerDay).replaceAll("{currentMonthlyEquiv}", formatBRL(monthlyEquiv)).replaceAll("{cycle}", cycleLabel);
|
|
3851
|
+
const RootTag = as;
|
|
3852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RootTag, { className: rootClasses, children: text });
|
|
3853
|
+
}
|
|
3854
|
+
|
|
3855
|
+
// src/components/paywall/blocks/PaywallCountdown.tsx
|
|
3856
|
+
var import_react30 = require("react");
|
|
3857
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
3858
|
+
var DEFAULT_COUNTDOWN_CLASSES = "font-mono tabular-nums";
|
|
3859
|
+
function resolveDeadlineMs(deadline) {
|
|
3860
|
+
if (deadline instanceof Date) return deadline.getTime();
|
|
3861
|
+
if (typeof deadline === "string") return new Date(deadline).getTime();
|
|
3862
|
+
const { sessionStorageKey, durationMs } = deadline;
|
|
3863
|
+
if (typeof window === "undefined" || typeof window.sessionStorage === "undefined") {
|
|
3864
|
+
return Date.now() + durationMs;
|
|
3865
|
+
}
|
|
3866
|
+
const stored = window.sessionStorage.getItem(sessionStorageKey);
|
|
3867
|
+
const parsed = stored ? Number.parseInt(stored, 10) : NaN;
|
|
3868
|
+
const now = Date.now();
|
|
3869
|
+
if (!Number.isFinite(parsed) || parsed < now) {
|
|
3870
|
+
const target = now + durationMs;
|
|
3871
|
+
window.sessionStorage.setItem(sessionStorageKey, String(target));
|
|
3872
|
+
return target;
|
|
3873
|
+
}
|
|
3874
|
+
return parsed;
|
|
3875
|
+
}
|
|
3876
|
+
function computeRemaining(deadlineMs) {
|
|
3877
|
+
const diff = Math.max(0, deadlineMs - Date.now());
|
|
3878
|
+
const totalSeconds = Math.floor(diff / 1e3);
|
|
3879
|
+
const h = Math.floor(totalSeconds / 3600);
|
|
3880
|
+
const m = Math.floor(totalSeconds % 3600 / 60);
|
|
3881
|
+
const s = totalSeconds % 60;
|
|
3882
|
+
return { h, m, s, expired: diff === 0 };
|
|
3883
|
+
}
|
|
3884
|
+
function pad(n) {
|
|
3885
|
+
return String(n).padStart(2, "0");
|
|
3886
|
+
}
|
|
3887
|
+
function PaywallCountdown({
|
|
3888
|
+
deadline,
|
|
3889
|
+
format = "h:m:s",
|
|
3890
|
+
onExpire,
|
|
3891
|
+
className,
|
|
3892
|
+
render
|
|
3893
|
+
}) {
|
|
3894
|
+
const deadlineMsRef = (0, import_react30.useRef)(null);
|
|
3895
|
+
if (deadlineMsRef.current === null) {
|
|
3896
|
+
deadlineMsRef.current = resolveDeadlineMs(deadline);
|
|
3897
|
+
}
|
|
3898
|
+
const [state, setState] = (0, import_react30.useState)(() => computeRemaining(deadlineMsRef.current));
|
|
3899
|
+
const expiredCalledRef = (0, import_react30.useRef)(false);
|
|
3900
|
+
(0, import_react30.useEffect)(() => {
|
|
3901
|
+
if (state.expired) {
|
|
3902
|
+
if (!expiredCalledRef.current) {
|
|
3903
|
+
expiredCalledRef.current = true;
|
|
3904
|
+
onExpire?.();
|
|
3905
|
+
}
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3908
|
+
const tick = () => {
|
|
3909
|
+
const next = computeRemaining(deadlineMsRef.current);
|
|
3910
|
+
setState(next);
|
|
3911
|
+
if (next.expired && !expiredCalledRef.current) {
|
|
3912
|
+
expiredCalledRef.current = true;
|
|
3913
|
+
onExpire?.();
|
|
3914
|
+
}
|
|
3915
|
+
};
|
|
3916
|
+
const id = setInterval(tick, 1e3);
|
|
3917
|
+
return () => clearInterval(id);
|
|
3918
|
+
}, [state.expired]);
|
|
3919
|
+
if (render) {
|
|
3920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className, children: render(state) });
|
|
3921
|
+
}
|
|
3922
|
+
const formatted = format === "h:m:s" ? `${pad(state.h)}:${pad(state.m)}:${pad(state.s)}` : `${pad(state.h * 60 + state.m)}:${pad(state.s)}`;
|
|
3923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: [DEFAULT_COUNTDOWN_CLASSES, className].filter(Boolean).join(" "), children: formatted });
|
|
3924
|
+
}
|
|
3925
|
+
|
|
3926
|
+
// src/components/paywall/blocks/PaywallFeatures.tsx
|
|
3927
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
3928
|
+
function PaywallFeatures({
|
|
3929
|
+
items,
|
|
3930
|
+
IconComponent,
|
|
3931
|
+
className,
|
|
3932
|
+
itemClassName,
|
|
3933
|
+
iconClassName,
|
|
3934
|
+
render,
|
|
3935
|
+
renderItem
|
|
3936
|
+
}) {
|
|
3937
|
+
if (render) {
|
|
3938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className, children: render({ items }) });
|
|
3939
|
+
}
|
|
3940
|
+
if (renderItem) {
|
|
3941
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className, children: items.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: renderItem(item, idx) }, idx)) });
|
|
3942
|
+
}
|
|
3943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className, children: items.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: itemClassName, children: [
|
|
3944
|
+
IconComponent ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(IconComponent, { className: iconClassName }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: iconClassName, "aria-hidden": "true", children: "\u2713" }),
|
|
3945
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: item })
|
|
3946
|
+
] }, idx)) });
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3949
|
+
// src/components/paywall/blocks/PaywallFeaturesCard.tsx
|
|
3950
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3951
|
+
var DEFAULT_CARD_CLASSES = "rounded-xl border p-4";
|
|
3952
|
+
function PaywallFeaturesCard({
|
|
3953
|
+
title,
|
|
3954
|
+
items,
|
|
3955
|
+
className,
|
|
3956
|
+
cardClassName,
|
|
3957
|
+
titleClassName,
|
|
3958
|
+
itemClassName,
|
|
3959
|
+
renderItem
|
|
3960
|
+
}) {
|
|
3961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: [DEFAULT_CARD_CLASSES, cardClassName].filter(Boolean).join(" "), children: [
|
|
3962
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: ["font-semibold mb-2", titleClassName].filter(Boolean).join(" "), children: title }) : null,
|
|
3963
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { children: items.map(
|
|
3964
|
+
(item, idx) => renderItem ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: renderItem(item, idx) }, idx) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: itemClassName, children: [
|
|
3965
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { "aria-hidden": "true", children: "\u2022" }),
|
|
3966
|
+
" ",
|
|
3967
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: item })
|
|
3968
|
+
] }, idx)
|
|
3969
|
+
) })
|
|
3970
|
+
] }) });
|
|
3971
|
+
}
|
|
3972
|
+
|
|
3973
|
+
// src/components/paywall/blocks/PaywallTrophyBadge.tsx
|
|
3974
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
3975
|
+
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";
|
|
3976
|
+
var FLOATING_CLASSES = "absolute top-2 right-2 z-10 shadow-md";
|
|
3977
|
+
function PaywallTrophyBadge({
|
|
3978
|
+
text,
|
|
3979
|
+
className,
|
|
3980
|
+
iconClassName,
|
|
3981
|
+
floating = false,
|
|
3982
|
+
render
|
|
3983
|
+
}) {
|
|
3984
|
+
if (render) {
|
|
3985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className, children: render({ text }) });
|
|
3986
|
+
}
|
|
3987
|
+
const rootClasses = [
|
|
3988
|
+
DEFAULT_CHIP_CLASSES,
|
|
3989
|
+
floating ? FLOATING_CLASSES : "",
|
|
3990
|
+
className
|
|
3991
|
+
].filter(Boolean).join(" ");
|
|
3992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: rootClasses, children: [
|
|
3993
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: iconClassName, "aria-hidden": "true", children: "\u{1F3C6}" }),
|
|
3994
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { children: text })
|
|
3995
|
+
] });
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3998
|
+
// src/components/paywall/blocks/PaywallAnchorPrice.tsx
|
|
3999
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
4000
|
+
var DEFAULT_CLASS2 = "text-sm opacity-60 line-through";
|
|
4001
|
+
function PaywallAnchorPrice({
|
|
4002
|
+
className,
|
|
4003
|
+
render
|
|
4004
|
+
}) {
|
|
4005
|
+
const { anchorPriceCents, cycle } = usePaywallContext();
|
|
4006
|
+
if (anchorPriceCents === null || anchorPriceCents === void 0 || anchorPriceCents <= 0) {
|
|
4007
|
+
return null;
|
|
4008
|
+
}
|
|
4009
|
+
void cycle;
|
|
4010
|
+
const formatted = formatBRL(anchorPriceCents);
|
|
4011
|
+
const rootClasses = [DEFAULT_CLASS2, className].filter(Boolean).join(" ");
|
|
4012
|
+
if (render) {
|
|
4013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: className || void 0, children: render({ anchorCents: anchorPriceCents, formatted }) });
|
|
4014
|
+
}
|
|
4015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: rootClasses, children: formatted });
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
// src/components/paywall/blocks/PaywallTestimonials.tsx
|
|
4019
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
4020
|
+
var DEFAULT_ROOT = "flex gap-3 overflow-x-auto snap-x snap-mandatory pb-2";
|
|
4021
|
+
var DEFAULT_CARD = "snap-start shrink-0 w-72 rounded-2xl border p-4 flex flex-col gap-2";
|
|
4022
|
+
var DEFAULT_AVATAR = "w-10 h-10 rounded-full object-cover";
|
|
4023
|
+
var DEFAULT_QUOTE = "text-sm leading-snug";
|
|
4024
|
+
var DEFAULT_NAME = "text-xs font-semibold opacity-80";
|
|
4025
|
+
var DEFAULT_STARS = "text-yellow-500 text-sm";
|
|
4026
|
+
function clampStars(n) {
|
|
4027
|
+
return Math.max(0, Math.min(5, Math.round(n)));
|
|
4028
|
+
}
|
|
4029
|
+
function PaywallTestimonials({
|
|
4030
|
+
items,
|
|
4031
|
+
className,
|
|
4032
|
+
cardClassName,
|
|
4033
|
+
avatarClassName,
|
|
4034
|
+
quoteClassName,
|
|
4035
|
+
nameClassName,
|
|
4036
|
+
starsClassName,
|
|
4037
|
+
renderItem
|
|
4038
|
+
}) {
|
|
4039
|
+
const rootClasses = [DEFAULT_ROOT, className].filter(Boolean).join(" ");
|
|
4040
|
+
const cardClasses = [DEFAULT_CARD, cardClassName].filter(Boolean).join(" ");
|
|
4041
|
+
const avatarClasses = [DEFAULT_AVATAR, avatarClassName].filter(Boolean).join(" ");
|
|
4042
|
+
const quoteClasses = [DEFAULT_QUOTE, quoteClassName].filter(Boolean).join(" ");
|
|
4043
|
+
const nameClasses = [DEFAULT_NAME, nameClassName].filter(Boolean).join(" ");
|
|
4044
|
+
const starsClasses = [DEFAULT_STARS, starsClassName].filter(Boolean).join(" ");
|
|
4045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: rootClasses, children: items.map((item, idx) => {
|
|
4046
|
+
if (renderItem) return renderItem(item, idx);
|
|
4047
|
+
const filled = clampStars(item.stars);
|
|
4048
|
+
const empty = 5 - filled;
|
|
4049
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cardClasses, children: [
|
|
4050
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
4051
|
+
item.avatar ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
4052
|
+
"img",
|
|
4053
|
+
{
|
|
4054
|
+
src: item.avatar,
|
|
4055
|
+
alt: "",
|
|
4056
|
+
loading: "lazy",
|
|
4057
|
+
className: avatarClasses,
|
|
4058
|
+
"aria-hidden": "true"
|
|
4059
|
+
}
|
|
4060
|
+
) : null,
|
|
4061
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: nameClasses, children: item.name })
|
|
4062
|
+
] }),
|
|
4063
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: starsClasses, "aria-label": `${filled} de 5 estrelas`, children: [
|
|
4064
|
+
"\u2605".repeat(filled),
|
|
4065
|
+
"\u2606".repeat(empty)
|
|
4066
|
+
] }),
|
|
4067
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: quoteClasses, children: item.quote })
|
|
4068
|
+
] }, idx);
|
|
4069
|
+
}) });
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
// src/components/paywall/blocks/PaywallStatsRow.tsx
|
|
4073
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
4074
|
+
var DEFAULT_ROOT2 = "grid grid-cols-3 gap-4";
|
|
4075
|
+
var DEFAULT_CELL = "flex flex-col items-center text-center";
|
|
4076
|
+
var DEFAULT_VALUE = "text-2xl font-bold";
|
|
4077
|
+
var DEFAULT_LABEL = "text-xs opacity-70";
|
|
4078
|
+
function PaywallStatsRow({
|
|
4079
|
+
stats,
|
|
4080
|
+
className,
|
|
4081
|
+
cellClassName,
|
|
4082
|
+
valueClassName,
|
|
4083
|
+
labelClassName,
|
|
4084
|
+
renderCell
|
|
4085
|
+
}) {
|
|
4086
|
+
const rootClasses = [DEFAULT_ROOT2, className].filter(Boolean).join(" ");
|
|
4087
|
+
const cellClasses = [DEFAULT_CELL, cellClassName].filter(Boolean).join(" ");
|
|
4088
|
+
const valueClasses = [DEFAULT_VALUE, valueClassName].filter(Boolean).join(" ");
|
|
4089
|
+
const labelClasses = [DEFAULT_LABEL, labelClassName].filter(Boolean).join(" ");
|
|
4090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: rootClasses, children: stats.map((stat, idx) => {
|
|
4091
|
+
if (renderCell) return renderCell(stat, idx);
|
|
4092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: cellClasses, children: [
|
|
4093
|
+
stat.icon ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { "aria-hidden": "true", children: stat.icon }) : null,
|
|
4094
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: valueClasses, children: stat.value }),
|
|
4095
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: labelClasses, children: stat.label })
|
|
4096
|
+
] }, idx);
|
|
4097
|
+
}) });
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
// src/components/paywall/blocks/PaywallFinePrint.tsx
|
|
4101
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
4102
|
+
var DEFAULT_CLASS3 = "text-xs opacity-60 leading-snug";
|
|
4103
|
+
var CYCLE_LABEL2 = {
|
|
4104
|
+
MONTHLY: "mensal",
|
|
4105
|
+
YEARLY: "anual"
|
|
4106
|
+
};
|
|
4107
|
+
function PaywallFinePrint({
|
|
4108
|
+
template,
|
|
4109
|
+
className,
|
|
4110
|
+
render
|
|
4111
|
+
}) {
|
|
4112
|
+
const {
|
|
4113
|
+
currentPriceCents,
|
|
4114
|
+
cycle,
|
|
4115
|
+
trialDaysCard,
|
|
4116
|
+
trialDaysPix,
|
|
4117
|
+
selectedMethod
|
|
4118
|
+
} = usePaywallContext();
|
|
4119
|
+
const trialDays = selectedMethod === "card" ? trialDaysCard : trialDaysPix;
|
|
4120
|
+
const cycleLabel = CYCLE_LABEL2[cycle] ?? cycle.toLowerCase();
|
|
4121
|
+
const priceFormatted = formatBRL(currentPriceCents ?? 0);
|
|
4122
|
+
const rootClasses = [DEFAULT_CLASS3, className].filter(Boolean).join(" ");
|
|
4123
|
+
if (render) {
|
|
4124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: className || void 0, children: render({
|
|
4125
|
+
currentPriceCents: currentPriceCents ?? 0,
|
|
4126
|
+
cycle,
|
|
4127
|
+
trialDays: trialDays ?? 0,
|
|
4128
|
+
selectedMethod
|
|
4129
|
+
}) });
|
|
4130
|
+
}
|
|
4131
|
+
const text = template.replaceAll("{price}", priceFormatted).replaceAll("{trialDays}", String(trialDays ?? 0)).replaceAll("{cycle}", cycleLabel);
|
|
4132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: rootClasses, children: text });
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
// src/components/paywall/blocks/PaywallTrustLine.tsx
|
|
4136
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
4137
|
+
var DEFAULT_ROOT3 = "flex items-center gap-3";
|
|
4138
|
+
var DEFAULT_ITEM = "flex items-center gap-1.5 text-xs";
|
|
4139
|
+
function PaywallTrustLine({
|
|
4140
|
+
items,
|
|
4141
|
+
className,
|
|
4142
|
+
itemClassName,
|
|
4143
|
+
renderItem
|
|
4144
|
+
}) {
|
|
4145
|
+
const rootClasses = [DEFAULT_ROOT3, className].filter(Boolean).join(" ");
|
|
4146
|
+
const itemClasses = [DEFAULT_ITEM, itemClassName].filter(Boolean).join(" ");
|
|
4147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: rootClasses, children: items.map((item, idx) => {
|
|
4148
|
+
if (renderItem) return renderItem(item, idx);
|
|
4149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: itemClasses, children: [
|
|
4150
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { "aria-hidden": "true", children: item.icon }),
|
|
4151
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { children: item.text })
|
|
4152
|
+
] }, idx);
|
|
4153
|
+
}) });
|
|
4154
|
+
}
|
|
4155
|
+
|
|
4156
|
+
// src/components/paywall/blocks/PaywallStickyFooter.tsx
|
|
4157
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
4158
|
+
var DEFAULT_CLASSES = "sticky bottom-0 left-0 right-0 bg-background";
|
|
4159
|
+
var SAFE_AREA_CLASS = "pb-[env(safe-area-inset-bottom)]";
|
|
4160
|
+
function PaywallStickyFooter({
|
|
4161
|
+
children,
|
|
4162
|
+
className,
|
|
4163
|
+
safeAreaInsets = true
|
|
4164
|
+
}) {
|
|
4165
|
+
const classes = [DEFAULT_CLASSES, safeAreaInsets ? SAFE_AREA_CLASS : null, className].filter(Boolean).join(" ");
|
|
4166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: classes, children });
|
|
3669
4167
|
}
|
|
3670
4168
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3671
4169
|
0 && (module.exports = {
|
|
@@ -3684,10 +4182,26 @@ function anchorForCycle(s, c) {
|
|
|
3684
4182
|
OnboardingFlow,
|
|
3685
4183
|
PaymentReturnHandler,
|
|
3686
4184
|
Paywall,
|
|
4185
|
+
PaywallAnchorPrice,
|
|
4186
|
+
PaywallContext,
|
|
4187
|
+
PaywallCountdown,
|
|
3687
4188
|
PaywallCta,
|
|
3688
4189
|
PaywallCyclePicker,
|
|
4190
|
+
PaywallEyebrow,
|
|
4191
|
+
PaywallFeatures,
|
|
4192
|
+
PaywallFeaturesCard,
|
|
4193
|
+
PaywallFinePrint,
|
|
4194
|
+
PaywallHeadline,
|
|
4195
|
+
PaywallHero,
|
|
3689
4196
|
PaywallMethodContent,
|
|
3690
4197
|
PaywallMethodTabs,
|
|
4198
|
+
PaywallPriceHeadline,
|
|
4199
|
+
PaywallProvider,
|
|
4200
|
+
PaywallStatsRow,
|
|
4201
|
+
PaywallStickyFooter,
|
|
4202
|
+
PaywallTestimonials,
|
|
4203
|
+
PaywallTrophyBadge,
|
|
4204
|
+
PaywallTrustLine,
|
|
3691
4205
|
PersistenceRegistry,
|
|
3692
4206
|
PreAuthShell,
|
|
3693
4207
|
PushPrompt,
|
|
@@ -3716,6 +4230,7 @@ function anchorForCycle(s, c) {
|
|
|
3716
4230
|
useInstallPrompt,
|
|
3717
4231
|
useLoginForm,
|
|
3718
4232
|
useOnboardingStep,
|
|
4233
|
+
usePaywallContext,
|
|
3719
4234
|
usePaywallState,
|
|
3720
4235
|
usePlan,
|
|
3721
4236
|
usePush,
|