@hook-sdk/template 0.19.0 → 0.21.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 CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  AppConfigSchema: () => AppConfigSchema,
35
35
  AppRoot: () => AppRoot,
36
36
  DeepLinkHandler: () => DeepLinkHandler,
37
+ DevSkipOnboardingFab: () => DevSkipOnboardingFab,
37
38
  EmptyState: () => EmptyState,
38
39
  ErrorBoundary: () => ErrorBoundary,
39
40
  I18nProvider: () => I18nProvider,
@@ -43,6 +44,11 @@ __export(index_exports, {
43
44
  LoadingState: () => LoadingState,
44
45
  OnboardingFlow: () => OnboardingFlow,
45
46
  PaymentReturnHandler: () => PaymentReturnHandler,
47
+ Paywall: () => Paywall,
48
+ PaywallCta: () => PaywallCta,
49
+ PaywallCyclePicker: () => PaywallCyclePicker,
50
+ PaywallMethodContent: () => PaywallMethodContent,
51
+ PaywallMethodTabs: () => PaywallMethodTabs,
46
52
  PersistenceRegistry: () => PersistenceRegistry,
47
53
  PreAuthShell: () => PreAuthShell,
48
54
  PushPrompt: () => PushPrompt2,
@@ -57,10 +63,12 @@ __export(index_exports, {
57
63
  detectStandalone: () => detectStandalone,
58
64
  discountPercent: () => discountPercent,
59
65
  formatBRL: () => formatBRL,
66
+ isDevToolsEnabled: () => isDevToolsEnabled,
60
67
  monthlyFromYearly: () => monthlyFromYearly,
61
68
  parseAppConfig: () => parseAppConfig,
62
69
  shouldBlockInstall: () => shouldBlockInstall,
63
70
  shouldShowPermanentOption: () => shouldShowPermanentOption,
71
+ skipOnboarding: () => skipOnboarding,
64
72
  useAppConfig: () => useAppConfig,
65
73
  useAuth: () => useAuth,
66
74
  useAuthPrimitives: () => useAuthPrimitives,
@@ -77,14 +85,14 @@ __export(index_exports, {
77
85
  useSignupForm: () => useSignupForm,
78
86
  useSubscription: () => useSubscription,
79
87
  useToast: () => useToast,
80
- useTrackOnboardingStep: () => import_sdk21.useTrackOnboardingStep
88
+ useTrackOnboardingStep: () => import_sdk23.useTrackOnboardingStep
81
89
  });
82
90
  module.exports = __toCommonJS(index_exports);
83
91
 
84
92
  // src/AppRoot.tsx
85
- var import_react14 = require("react");
93
+ var import_react15 = require("react");
86
94
  var import_react_router_dom2 = require("react-router-dom");
87
- var import_sdk7 = require("@hook-sdk/sdk");
95
+ var import_sdk8 = require("@hook-sdk/sdk");
88
96
 
89
97
  // src/config/AppConfigContext.tsx
90
98
  var import_react = require("react");
@@ -118,7 +126,16 @@ var AuthFlowSchema = import_zod.z.object({
118
126
  });
119
127
  var PaywallNonFreeSchema = import_zod.z.object({
120
128
  mode: import_zod.z.enum(["trial", "pay_first"]),
129
+ // Legacy flat trial — fallback when per-method fields aren't set.
121
130
  trialDays: import_zod.z.number().int().nonnegative().optional(),
131
+ // Per-method trial (ADR-022 Amendment 2026-05-12 + G154). PIX Auto can't
132
+ // offer trial on Asaas today (Jornada 2 unavailable), so apps that mix
133
+ // methods must split the value to avoid bait-and-switch on PIX shoppers.
134
+ trialDaysCard: import_zod.z.number().int().nonnegative().optional(),
135
+ trialDaysPix: import_zod.z.number().int().nonnegative().optional(),
136
+ // Which method the paywall preselects. null/undefined = no preselection
137
+ // (user picks). Per-app override reflects audience, not Hook bias.
138
+ defaultMethod: import_zod.z.enum(["card", "pix-auto", "pix-once"]).nullable().optional(),
122
139
  cycles: import_zod.z.array(import_zod.z.enum(["MONTHLY", "YEARLY"])).min(1),
123
140
  prices: import_zod.z.object({
124
141
  monthlyCents: import_zod.z.number().int().nonnegative(),
@@ -352,7 +369,7 @@ var FALLBACK_PAYWALL = {
352
369
  };
353
370
  var isMethodAvailable = (availability, method) => availability[method] !== false;
354
371
  function usePaywallState() {
355
- const { subscription, plan } = (0, import_sdk3.useHook)();
372
+ const { subscription, plan, authStatus, track: track2 } = (0, import_sdk3.useHook)();
356
373
  const configFromCtx = (0, import_react6.useContext)(AppConfigContext);
357
374
  const paywall = configFromCtx?.paywall ?? FALLBACK_PAYWALL;
358
375
  const isFree = paywall.mode === "free";
@@ -369,7 +386,8 @@ function usePaywallState() {
369
386
  () => declaredMethods.filter((m) => isMethodAvailable(availability, m)),
370
387
  [declaredMethods, availability]
371
388
  );
372
- const defaultMethod = methods[0] ?? declaredMethods[0] ?? "card";
389
+ const configDefault = !isFree && "defaultMethod" in paywall ? paywall.defaultMethod ?? null : null;
390
+ const defaultMethod = (configDefault && methods.includes(configDefault) ? configDefault : null) ?? methods[0] ?? declaredMethods[0] ?? "card";
373
391
  const [selectedMethodRaw, setSelectedMethod] = (0, import_react6.useState)(defaultMethod);
374
392
  const selectedMethod = methods.includes(selectedMethodRaw) ? selectedMethodRaw : methods[0] ?? selectedMethodRaw;
375
393
  const initialCycle = isFree ? "MONTHLY" : paywall.cycles[0] ?? "MONTHLY";
@@ -390,6 +408,22 @@ function usePaywallState() {
390
408
  const [submitting, setSubmitting] = (0, import_react6.useState)(false);
391
409
  const status = subscription.status();
392
410
  const daysLeftInTrial = subscription.daysLeftInTrial();
411
+ const trialDaysForMethod = (0, import_react6.useCallback)(
412
+ (method) => {
413
+ if (isFree) return 0;
414
+ if (method === "card") {
415
+ if (typeof paywall.trialDaysCard === "number") return paywall.trialDaysCard;
416
+ if (typeof paywall.trialDays === "number") return paywall.trialDays;
417
+ return 7;
418
+ }
419
+ if (typeof paywall.trialDaysPix === "number") return paywall.trialDaysPix;
420
+ if (typeof paywall.trialDays === "number") return paywall.trialDays;
421
+ return 0;
422
+ },
423
+ [isFree, paywall]
424
+ );
425
+ const trialDaysCard = trialDaysForMethod("card");
426
+ const trialDaysPix = trialDaysForMethod("pix-auto");
393
427
  const initialLoadComplete = subscription.initialLoadComplete;
394
428
  const hasAccess = subscription.hasAccess;
395
429
  const pixPending = (0, import_react6.useMemo)(() => {
@@ -429,6 +463,40 @@ function usePaywallState() {
429
463
  discountPercent: discount
430
464
  };
431
465
  }, [paywall, cycle, isFree]);
466
+ const hasConsumedTrial = (0, import_react6.useMemo)(() => {
467
+ return ["active", "trialing", "past_due", "canceled", "expired"].includes(status);
468
+ }, [status]);
469
+ const currentPriceCents = (0, import_react6.useMemo)(() => {
470
+ if (isFree) return 0;
471
+ return cycle === "YEARLY" ? paywall.prices.yearlyCents : paywall.prices.monthlyCents;
472
+ }, [paywall, cycle, isFree]);
473
+ const currentMonthlyEquivCents = (0, import_react6.useMemo)(() => {
474
+ if (isFree) return 0;
475
+ if (cycle === "YEARLY") return Math.round(paywall.prices.yearlyCents / 12);
476
+ return paywall.prices.monthlyCents;
477
+ }, [paywall, cycle, isFree]);
478
+ const anchorPriceCents = (0, import_react6.useMemo)(() => {
479
+ if (isFree) return null;
480
+ const a = paywall.anchorPrices;
481
+ if (!a) return null;
482
+ return cycle === "YEARLY" ? a.yearlyCents : a.monthlyCents;
483
+ }, [paywall, cycle, isFree]);
484
+ const selectMethod = (0, import_react6.useCallback)(
485
+ (next) => {
486
+ if (next === selectedMethod) return;
487
+ track2("paywall_method_tab_clicked", { method: next, from_method: selectedMethod });
488
+ setSelectedMethod(next);
489
+ },
490
+ [selectedMethod, track2]
491
+ );
492
+ const selectCycle = (0, import_react6.useCallback)(
493
+ (next) => {
494
+ if (next === cycle) return;
495
+ track2("paywall_cycle_clicked", { cycle: next, from_cycle: cycle });
496
+ setCycle(next);
497
+ },
498
+ [cycle, track2]
499
+ );
432
500
  const useDefaultMessages = paywall.mode !== "free" && paywall.errorMessages === "default";
433
501
  const buildError = (0, import_react6.useCallback)(
434
502
  (code, fallbackMessage) => ({
@@ -441,6 +509,21 @@ function usePaywallState() {
441
509
  [useDefaultMessages]
442
510
  );
443
511
  const submit = (0, import_react6.useCallback)(async () => {
512
+ if (authStatus === "loading") return void 0;
513
+ if (authStatus !== "authenticated") {
514
+ track2("unauthenticated_submit_attempted", {
515
+ method: selectedMethod,
516
+ cycle,
517
+ cpf_valid: cpfValid
518
+ });
519
+ return void 0;
520
+ }
521
+ track2("payment_attempted", {
522
+ method: selectedMethod,
523
+ cycle,
524
+ cpf_valid: cpfValid,
525
+ selected_amount_cents: cycle === "YEARLY" ? plan.data?.yearlyPriceCents ?? (isFree ? 0 : paywall.prices.yearlyCents) : plan.data?.priceCents ?? (isFree ? 0 : paywall.prices.monthlyCents)
526
+ });
444
527
  setSubmitting(true);
445
528
  setError(null);
446
529
  const methodToUse = selectedMethod;
@@ -501,7 +584,7 @@ function usePaywallState() {
501
584
  setSubmitting(false);
502
585
  return void 0;
503
586
  }
504
- }, [selectedMethod, availability, subscription, cycle, cpf, card, buildError]);
587
+ }, [authStatus, track2, selectedMethod, availability, subscription, cycle, cpf, cpfValid, card, buildError, plan, paywall]);
505
588
  const checkout = (0, import_react6.useCallback)(
506
589
  async (args) => {
507
590
  setSubmitting(true);
@@ -608,6 +691,20 @@ function usePaywallState() {
608
691
  methods,
609
692
  selectedMethod,
610
693
  setSelectedMethod,
694
+ // Conversion-max derivations (template 0.21)
695
+ hasConsumedTrial,
696
+ currentPriceCents,
697
+ currentMonthlyEquivCents,
698
+ anchorPriceCents,
699
+ selectMethod,
700
+ selectCycle,
701
+ isFree,
702
+ // Per-method trial (ADR-022 Amendment 2026-05-12). Use these to render
703
+ // asymmetric copy per method card on the paywall — never a global
704
+ // "free trial!" headline when both methods are visible.
705
+ trialDaysForMethod,
706
+ trialDaysCard,
707
+ trialDaysPix,
611
708
  // Form state
612
709
  cpfState,
613
710
  cardState,
@@ -639,13 +736,13 @@ var BLOCKING = /* @__PURE__ */ new Set([
639
736
  "canceled",
640
737
  "none"
641
738
  ]);
642
- function SubscriptionGate({ Paywall, children }) {
739
+ function SubscriptionGate({ Paywall: Paywall2, children }) {
643
740
  const { mode } = useTemplateConfig();
644
741
  const { status, hasAccess, initialLoadComplete } = usePaywallState();
645
742
  if (mode === "free") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
646
743
  if (!initialLoadComplete && status === "none") return null;
647
744
  if (hasAccess === true && status !== "none") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
648
- if (BLOCKING.has(status)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Paywall, {});
745
+ if (BLOCKING.has(status)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Paywall2, {});
649
746
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
650
747
  }
651
748
 
@@ -2091,23 +2188,163 @@ function I18nProvider({
2091
2188
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_i18next.I18nextProvider, { i18n: import_i18next.default, children });
2092
2189
  }
2093
2190
 
2094
- // src/internal/PaymentReturnHandler.tsx
2191
+ // src/dev/env.ts
2192
+ var import_meta = {};
2193
+ function isDevToolsEnabled() {
2194
+ const meta = import_meta;
2195
+ if (meta.env?.VITE_HOOK_DEV_TOOLS !== "1") return false;
2196
+ if (typeof window === "undefined") return false;
2197
+ const host = window.location.hostname;
2198
+ return host.includes(".staging.") || host === "localhost" || host === "127.0.0.1";
2199
+ }
2200
+
2201
+ // src/dev/DevSkipOnboardingFab.tsx
2095
2202
  var import_react13 = require("react");
2096
2203
  var import_sdk6 = require("@hook-sdk/sdk");
2097
2204
  var import_jsx_runtime20 = require("react/jsx-runtime");
2205
+ var STORAGE_KEY = "hook_dev_skip_email";
2206
+ var TEST_EMAIL_DOMAIN = "@hook.test";
2207
+ var TEST_PASSWORD = "SkipTest!2026";
2208
+ function makeEmail() {
2209
+ return `ryan+skip-${Date.now()}${TEST_EMAIL_DOMAIN}`;
2210
+ }
2211
+ async function ensureSignedIn(hook, maxAttempts = 3) {
2212
+ if (hook.authStatus === "authenticated") return null;
2213
+ let lastErr;
2214
+ for (let i = 0; i < maxAttempts; i += 1) {
2215
+ const email = makeEmail();
2216
+ try {
2217
+ await hook.auth.signup({ email, password: TEST_PASSWORD, name: "Ryan Test" });
2218
+ try {
2219
+ window.sessionStorage.setItem(STORAGE_KEY, email);
2220
+ } catch {
2221
+ }
2222
+ return email;
2223
+ } catch (err) {
2224
+ lastErr = err;
2225
+ await new Promise((r) => setTimeout(r, 30));
2226
+ }
2227
+ }
2228
+ throw lastErr ?? new Error("signup failed after retries");
2229
+ }
2230
+ async function skipOnboarding(hook, defaults, appSlug) {
2231
+ const { __seed, ...rest } = defaults;
2232
+ await ensureSignedIn(hook);
2233
+ await hook.appData.set("onboarding_data", {
2234
+ ...rest,
2235
+ onboarding_completed: true
2236
+ });
2237
+ if (__seed) {
2238
+ await __seed(hook);
2239
+ }
2240
+ console.info("[hook-template] dev_skip_onboarding fired", {
2241
+ app_slug: appSlug,
2242
+ hostname: window.location.hostname
2243
+ });
2244
+ window.location.assign(`/app/${appSlug}/`);
2245
+ }
2246
+ var STYLES = {
2247
+ base: {
2248
+ position: "fixed",
2249
+ bottom: "16px",
2250
+ right: "16px",
2251
+ zIndex: 2147483647,
2252
+ padding: "10px 14px",
2253
+ borderRadius: "999px",
2254
+ border: "none",
2255
+ background: "#F59E0B",
2256
+ color: "#111827",
2257
+ fontWeight: 600,
2258
+ fontSize: "13px",
2259
+ fontFamily: "system-ui, -apple-system, sans-serif",
2260
+ boxShadow: "0 4px 14px rgba(0, 0, 0, 0.25)",
2261
+ cursor: "pointer",
2262
+ display: "flex",
2263
+ alignItems: "center",
2264
+ gap: "6px"
2265
+ },
2266
+ confirm: { background: "#DC2626", color: "#FFFFFF" },
2267
+ busy: { opacity: 0.6, cursor: "wait" }
2268
+ };
2269
+ var CONFIRM_TIMEOUT_MS = 3e3;
2270
+ function DevSkipOnboardingFab({ defaults }) {
2271
+ const hook = (0, import_sdk6.useHook)();
2272
+ const { slug } = useAppConfig();
2273
+ const [state, setState] = (0, import_react13.useState)("idle");
2274
+ const [errorMsg, setErrorMsg] = (0, import_react13.useState)(null);
2275
+ const timerRef = (0, import_react13.useRef)(null);
2276
+ const clearTimer = (0, import_react13.useCallback)(() => {
2277
+ if (timerRef.current) {
2278
+ clearTimeout(timerRef.current);
2279
+ timerRef.current = null;
2280
+ }
2281
+ }, []);
2282
+ const onClick = (0, import_react13.useCallback)(async () => {
2283
+ if (state === "busy") return;
2284
+ if (state === "idle" || state === "error") {
2285
+ setState("confirm");
2286
+ setErrorMsg(null);
2287
+ clearTimer();
2288
+ timerRef.current = setTimeout(() => setState("idle"), CONFIRM_TIMEOUT_MS);
2289
+ return;
2290
+ }
2291
+ clearTimer();
2292
+ setState("busy");
2293
+ try {
2294
+ await skipOnboarding(hook, defaults, slug);
2295
+ } catch (err) {
2296
+ setState("error");
2297
+ setErrorMsg(err instanceof Error ? err.message : String(err));
2298
+ }
2299
+ }, [state, hook, defaults, slug, clearTimer]);
2300
+ const label = (() => {
2301
+ if (state === "busy") return "skipping\u2026";
2302
+ if (state === "confirm") return "tap again to confirm";
2303
+ if (state === "error") return `failed \u2014 tap to retry`;
2304
+ return hook.authStatus === "authenticated" ? "\u26A1 skip onboarding" : "\u26A1 skip + signup";
2305
+ })();
2306
+ const style = {
2307
+ ...STYLES.base,
2308
+ ...state === "confirm" || state === "error" ? STYLES.confirm : {},
2309
+ ...state === "busy" ? STYLES.busy : {}
2310
+ };
2311
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2312
+ "button",
2313
+ {
2314
+ type: "button",
2315
+ "data-testid": "dev-skip-onboarding-fab",
2316
+ "aria-label": "Skip onboarding (staging dev only)",
2317
+ style,
2318
+ onClick,
2319
+ title: errorMsg ?? void 0,
2320
+ children: label
2321
+ }
2322
+ );
2323
+ }
2324
+
2325
+ // src/internal/PaymentReturnHandler.tsx
2326
+ var import_react14 = require("react");
2327
+ var import_sdk7 = require("@hook-sdk/sdk");
2328
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2098
2329
  var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
2099
2330
  var MAX_CYCLES = 3;
2100
2331
  var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
2101
2332
  function PaymentReturnHandler({ children }) {
2102
- const { subscription } = (0, import_sdk6.useHook)();
2103
- const subRef = (0, import_react13.useRef)(subscription);
2333
+ const { subscription, track: track2 } = (0, import_sdk7.useHook)();
2334
+ const subRef = (0, import_react14.useRef)(subscription);
2104
2335
  subRef.current = subscription;
2105
- const runIdRef = (0, import_react13.useRef)(0);
2106
- const cyclesRef = (0, import_react13.useRef)(0);
2107
- const [state, setState] = (0, import_react13.useState)("idle");
2108
- const runPoll = (0, import_react13.useCallback)(() => {
2336
+ const runIdRef = (0, import_react14.useRef)(0);
2337
+ const cyclesRef = (0, import_react14.useRef)(0);
2338
+ const startMsRef = (0, import_react14.useRef)(0);
2339
+ const [state, setState] = (0, import_react14.useState)("idle");
2340
+ const runPoll = (0, import_react14.useCallback)(() => {
2109
2341
  const runId = ++runIdRef.current;
2342
+ const isFirstRun = cyclesRef.current === 0;
2110
2343
  cyclesRef.current += 1;
2344
+ if (isFirstRun) {
2345
+ startMsRef.current = Date.now();
2346
+ track2("payment_confirmation_started", {});
2347
+ }
2111
2348
  setState("confirming");
2112
2349
  let attempts = 0;
2113
2350
  const tick = async () => {
@@ -2120,6 +2357,11 @@ function PaymentReturnHandler({ children }) {
2120
2357
  if (runIdRef.current !== runId) return;
2121
2358
  const status = subRef.current.status();
2122
2359
  if (status === "active" || status === "trialing") {
2360
+ track2("payment_confirmation_succeeded", {
2361
+ cycle_count: cyclesRef.current,
2362
+ attempt_count: attempts,
2363
+ duration_ms: Date.now() - startMsRef.current
2364
+ });
2123
2365
  const cleanUrl = new URL(window.location.href);
2124
2366
  cleanUrl.searchParams.delete("paymentReturn");
2125
2367
  window.history.replaceState({}, "", cleanUrl.toString());
@@ -2130,6 +2372,9 @@ function PaymentReturnHandler({ children }) {
2130
2372
  const delay = BACKOFF_MS[attempts - 1];
2131
2373
  if (delay === void 0) {
2132
2374
  if (cyclesRef.current >= MAX_CYCLES) {
2375
+ track2("payment_confirmation_timed_out", {
2376
+ total_duration_ms: Date.now() - startMsRef.current
2377
+ });
2133
2378
  setState("timeout");
2134
2379
  } else {
2135
2380
  setState("waiting");
@@ -2139,8 +2384,8 @@ function PaymentReturnHandler({ children }) {
2139
2384
  setTimeout(tick, delay);
2140
2385
  };
2141
2386
  void tick();
2142
- }, []);
2143
- (0, import_react13.useEffect)(() => {
2387
+ }, [track2]);
2388
+ (0, import_react14.useEffect)(() => {
2144
2389
  if (typeof window === "undefined") return;
2145
2390
  const url = new URL(window.location.href);
2146
2391
  if (url.searchParams.get("paymentReturn") !== "1") return;
@@ -2150,26 +2395,26 @@ function PaymentReturnHandler({ children }) {
2150
2395
  runIdRef.current++;
2151
2396
  };
2152
2397
  }, [runPoll]);
2153
- const goHome = (0, import_react13.useCallback)(() => {
2398
+ const goHome = (0, import_react14.useCallback)(() => {
2154
2399
  const cleanUrl = new URL(window.location.href);
2155
2400
  cleanUrl.searchParams.delete("paymentReturn");
2156
2401
  cleanUrl.pathname = "/app/home";
2157
2402
  window.location.href = cleanUrl.toString();
2158
2403
  }, []);
2159
2404
  if (state === "confirming") {
2160
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
2405
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
2161
2406
  }
2162
2407
  if (state === "waiting") {
2163
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
2164
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
2165
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
2408
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
2409
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
2410
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
2166
2411
  ] }) });
2167
2412
  }
2168
2413
  if (state === "timeout") {
2169
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
2170
- /* @__PURE__ */ (0, import_jsx_runtime20.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." }),
2171
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
2172
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2414
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
2415
+ /* @__PURE__ */ (0, import_jsx_runtime21.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." }),
2416
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
2417
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2173
2418
  "button",
2174
2419
  {
2175
2420
  type: "button",
@@ -2182,7 +2427,7 @@ function PaymentReturnHandler({ children }) {
2182
2427
  children: "Tentar de novo"
2183
2428
  }
2184
2429
  ),
2185
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2430
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2186
2431
  "button",
2187
2432
  {
2188
2433
  type: "button",
@@ -2192,7 +2437,7 @@ function PaymentReturnHandler({ children }) {
2192
2437
  children: "Voltar pro app"
2193
2438
  }
2194
2439
  ),
2195
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2440
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2196
2441
  "a",
2197
2442
  {
2198
2443
  href: SUPPORT_MAILTO,
@@ -2204,7 +2449,7 @@ function PaymentReturnHandler({ children }) {
2204
2449
  ] })
2205
2450
  ] }) });
2206
2451
  }
2207
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, { children });
2452
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_jsx_runtime21.Fragment, { children });
2208
2453
  }
2209
2454
  var overlayStyle2 = {
2210
2455
  position: "fixed",
@@ -2243,7 +2488,7 @@ var linkStyle = {
2243
2488
  };
2244
2489
 
2245
2490
  // src/AppRoot.tsx
2246
- var import_jsx_runtime21 = require("react/jsx-runtime");
2491
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2247
2492
  function buildLegacyConfigShim(config) {
2248
2493
  const paywall = config.paywall;
2249
2494
  const isFree = paywall.mode === "free";
@@ -2291,9 +2536,10 @@ function AppRoot(props) {
2291
2536
  Forgot,
2292
2537
  Reset,
2293
2538
  EmailVerify,
2294
- Paywall,
2539
+ Paywall: Paywall2,
2295
2540
  Onboarding,
2296
- PreAuthFlow
2541
+ PreAuthFlow,
2542
+ devSkipOnboarding
2297
2543
  } = props;
2298
2544
  if (!Login || !Signup || !Forgot || !Reset) {
2299
2545
  throw new Error(
@@ -2301,7 +2547,7 @@ function AppRoot(props) {
2301
2547
  );
2302
2548
  }
2303
2549
  const config = parseAppConfig(rawConfig);
2304
- if (config.paywall.mode !== "free" && !Paywall) {
2550
+ if (config.paywall.mode !== "free" && !Paywall2) {
2305
2551
  throw new Error(
2306
2552
  "[hook-template] <AppRoot>: Paywall slot prop is required when config.paywall.mode != 'free'."
2307
2553
  );
@@ -2316,19 +2562,19 @@ function AppRoot(props) {
2316
2562
  "[hook-template] <AppRoot>: PreAuthFlow slot prop is required when config.onboarding.trigger === 'pre_signup_custom'."
2317
2563
  );
2318
2564
  }
2319
- const legacyShim = (0, import_react14.useMemo)(() => buildLegacyConfigShim(config), [config]);
2565
+ const legacyShim = (0, import_react15.useMemo)(() => buildLegacyConfigShim(config), [config]);
2320
2566
  const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
2321
2567
  const basename = `/app/${config.slug}`;
2322
2568
  const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
2323
2569
  const position = config.install_prompt?.position ?? "post-paywall";
2324
- const subscriptionGated = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: position === "post-paywall" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(InstallGate, { position: "post-paywall", children: [
2570
+ const subscriptionGated = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SubscriptionGate, { Paywall: Paywall2 ?? FallbackPaywall, children: position === "post-paywall" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(InstallGate, { position: "post-paywall", children: [
2325
2571
  children,
2326
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PushPrompt, {})
2327
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
2572
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PushPrompt, {})
2573
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
2328
2574
  children,
2329
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PushPrompt, {})
2575
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PushPrompt, {})
2330
2576
  ] }) });
2331
- const authGated = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2577
+ const authGated = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2332
2578
  AuthGated,
2333
2579
  {
2334
2580
  config,
@@ -2337,18 +2583,19 @@ function AppRoot(props) {
2337
2583
  Forgot,
2338
2584
  Reset,
2339
2585
  EmailVerify,
2340
- Paywall,
2586
+ Paywall: Paywall2,
2341
2587
  Onboarding,
2342
2588
  PreAuthFlow,
2343
2589
  children: subscriptionGated
2344
2590
  }
2345
2591
  );
2346
- const routedTree = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Router, { ...routerProps, children: [
2347
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
2348
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SessionExpiredBanner, {}),
2349
- position === "pre-auth" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InstallGate, { position: "pre-auth", children: authGated }) : authGated
2592
+ const routedTree = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Router, { ...routerProps, children: [
2593
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
2594
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SessionExpiredBanner, {}),
2595
+ position === "pre-auth" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InstallGate, { position: "pre-auth", children: authGated }) : authGated,
2596
+ isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DevSkipOnboardingFab, { defaults: devSkipOnboarding.defaults }) : null
2350
2597
  ] });
2351
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2598
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2352
2599
  I18nProvider,
2353
2600
  {
2354
2601
  defaultLocale: config.i18n.defaultLocale,
@@ -2368,37 +2615,37 @@ function AuthGated({
2368
2615
  EmailVerify,
2369
2616
  PreAuthFlow
2370
2617
  }) {
2371
- const { authStatus } = (0, import_sdk7.useHook)();
2618
+ const { authStatus } = (0, import_sdk8.useHook)();
2372
2619
  if (authStatus === "loading") return null;
2373
2620
  if (authStatus !== "authenticated") {
2374
2621
  if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
2375
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_router_dom2.Routes, { children: [
2376
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Login, {}) }),
2377
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Signup, {}) }),
2378
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Forgot, {}) }),
2379
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Reset, {}) }),
2380
- EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmailVerify, {}) }) : null,
2381
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PreAuthFlow, {}) })
2622
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_router_dom2.Routes, { children: [
2623
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Login, {}) }),
2624
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Signup, {}) }),
2625
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Forgot, {}) }),
2626
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Reset, {}) }),
2627
+ EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmailVerify, {}) }) : null,
2628
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PreAuthFlow, {}) })
2382
2629
  ] });
2383
2630
  }
2384
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_router_dom2.Routes, { children: [
2385
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Login, {}) }),
2386
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Signup, {}) }),
2387
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Forgot, {}) }),
2388
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Reset, {}) }),
2389
- EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmailVerify, {}) }) : null,
2390
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
2631
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_router_dom2.Routes, { children: [
2632
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Login, {}) }),
2633
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Signup, {}) }),
2634
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Forgot, {}) }),
2635
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Reset, {}) }),
2636
+ EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmailVerify, {}) }) : null,
2637
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
2391
2638
  ] });
2392
2639
  }
2393
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_jsx_runtime21.Fragment, { children });
2640
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, { children });
2394
2641
  }
2395
2642
  function FallbackPaywall() {
2396
2643
  return null;
2397
2644
  }
2398
2645
 
2399
2646
  // src/hooks/usePush.ts
2400
- var import_react15 = require("react");
2401
- var import_sdk8 = require("@hook-sdk/sdk");
2647
+ var import_react16 = require("react");
2648
+ var import_sdk9 = require("@hook-sdk/sdk");
2402
2649
  var DISMISS_STORAGE_KEY = "push:dismissed-until";
2403
2650
  var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
2404
2651
  function detectIosNeedsInstall() {
@@ -2442,12 +2689,12 @@ function deriveState(push) {
2442
2689
  return { kind: "prompt" };
2443
2690
  }
2444
2691
  function usePush() {
2445
- const { push } = (0, import_sdk8.useHook)();
2446
- const [state, setState] = (0, import_react15.useState)(() => deriveState(push));
2447
- (0, import_react15.useEffect)(() => {
2692
+ const { push } = (0, import_sdk9.useHook)();
2693
+ const [state, setState] = (0, import_react16.useState)(() => deriveState(push));
2694
+ (0, import_react16.useEffect)(() => {
2448
2695
  setState(deriveState(push));
2449
2696
  }, [push]);
2450
- const subscribe = (0, import_react15.useCallback)(async () => {
2697
+ const subscribe = (0, import_react16.useCallback)(async () => {
2451
2698
  try {
2452
2699
  await push.subscribe();
2453
2700
  setState({ kind: "subscribed" });
@@ -2459,7 +2706,7 @@ function usePush() {
2459
2706
  throw e;
2460
2707
  }
2461
2708
  }, [push]);
2462
- const unsubscribe = (0, import_react15.useCallback)(async () => {
2709
+ const unsubscribe = (0, import_react16.useCallback)(async () => {
2463
2710
  try {
2464
2711
  await push.unsubscribe();
2465
2712
  setState({ kind: "prompt" });
@@ -2468,7 +2715,7 @@ function usePush() {
2468
2715
  throw e;
2469
2716
  }
2470
2717
  }, [push]);
2471
- const dismiss = (0, import_react15.useCallback)(() => {
2718
+ const dismiss = (0, import_react16.useCallback)(() => {
2472
2719
  if (typeof localStorage !== "undefined") {
2473
2720
  try {
2474
2721
  localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS2));
@@ -2481,51 +2728,27 @@ function usePush() {
2481
2728
  }
2482
2729
 
2483
2730
  // src/components/PushPrompt.tsx
2484
- var import_jsx_runtime22 = require("react/jsx-runtime");
2485
- function platformRecoveryCopy(texts) {
2486
- if (typeof navigator === "undefined") return null;
2487
- const ua = navigator.userAgent || "";
2488
- const platform = detectPlatform(ua);
2489
- switch (platform) {
2490
- case "ios-safari":
2491
- case "ios-other":
2492
- return texts.deniedRecoveryIos ?? null;
2493
- case "android":
2494
- return texts.deniedRecoveryAndroid ?? null;
2495
- case "desktop":
2496
- return texts.deniedRecoveryDesktop ?? null;
2497
- case "in-app":
2498
- return texts.deniedRecoveryInApp ?? null;
2499
- default:
2500
- return null;
2501
- }
2502
- }
2731
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2503
2732
  function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
2504
2733
  const { state, subscribe } = usePush();
2505
- if (state.kind === "subscribed" || state.kind === "dismissed") return null;
2506
- if (state.kind === "ios_needs_install") {
2507
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
2508
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { children: texts.iosInstallTitle }),
2509
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: texts.iosInstallBody }),
2510
- onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2511
- ] });
2734
+ if (state.kind === "denied" || state.kind === "dismissed" || state.kind === "subscribed") {
2735
+ return null;
2512
2736
  }
2513
- if (state.kind === "denied") {
2514
- const recovery = platformRecoveryCopy(texts);
2515
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
2516
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { children: texts.deniedTitle }),
2517
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: texts.deniedBody }),
2518
- recovery && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { "data-testid": "denied-recovery", children: recovery })
2737
+ if (state.kind === "ios_needs_install") {
2738
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
2739
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { children: texts.iosInstallTitle }),
2740
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { children: texts.iosInstallBody }),
2741
+ onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2519
2742
  ] });
2520
2743
  }
2521
2744
  if (state.kind === "unsupported") {
2522
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: texts.unsupportedBody }) });
2745
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { children: texts.unsupportedBody }) });
2523
2746
  }
2524
2747
  if (state.kind === "error") {
2525
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: state.message }) });
2748
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { children: state.message }) });
2526
2749
  }
2527
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, role: "region", children: [
2528
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2750
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className, role: "region", children: [
2751
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2529
2752
  "button",
2530
2753
  {
2531
2754
  type: "button",
@@ -2539,67 +2762,67 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
2539
2762
  children: texts.cta
2540
2763
  }
2541
2764
  ),
2542
- onDeclined && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2765
+ onDeclined && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2543
2766
  ] });
2544
2767
  }
2545
2768
 
2546
2769
  // src/components/LanguageSwitcher.tsx
2547
- var import_sdk9 = require("@hook-sdk/sdk");
2548
- var import_jsx_runtime23 = require("react/jsx-runtime");
2770
+ var import_sdk10 = require("@hook-sdk/sdk");
2771
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2549
2772
  function LanguageSwitcher({ id, className, label = "Language" }) {
2550
2773
  const config = useAppConfig();
2551
2774
  const i18nConfig = config.i18n;
2552
- const [userLocale, setUserLocale] = (0, import_sdk9.usePersistedState)(
2775
+ const [userLocale, setUserLocale] = (0, import_sdk10.usePersistedState)(
2553
2776
  "user-locale",
2554
2777
  i18nConfig?.defaultLocale ?? "en-US"
2555
2778
  );
2556
2779
  if (!i18nConfig) return null;
2557
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className, children: [
2558
- label ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: label }) : null,
2559
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2780
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className, children: [
2781
+ label ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label }) : null,
2782
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2560
2783
  "select",
2561
2784
  {
2562
2785
  id,
2563
2786
  value: userLocale,
2564
2787
  onChange: (e) => setUserLocale(e.target.value),
2565
2788
  "data-testid": "language-switcher",
2566
- children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: loc, children: loc }, loc))
2789
+ children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: loc, children: loc }, loc))
2567
2790
  }
2568
2791
  )
2569
2792
  ] });
2570
2793
  }
2571
2794
 
2572
2795
  // src/defaults/LoadingState.tsx
2573
- var import_jsx_runtime24 = require("react/jsx-runtime");
2796
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2574
2797
  function LoadingState({ message }) {
2575
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: message ?? "Carregando..." }) });
2798
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: message ?? "Carregando..." }) });
2576
2799
  }
2577
2800
 
2578
2801
  // src/defaults/EmptyState.tsx
2579
- var import_jsx_runtime25 = require("react/jsx-runtime");
2802
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2580
2803
  function EmptyState({ title, description, action }) {
2581
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
2582
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
2583
- description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { style: { opacity: 0.7 }, children: description }),
2584
- action && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { marginTop: 16 }, children: action })
2804
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
2805
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
2806
+ description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { style: { opacity: 0.7 }, children: description }),
2807
+ action && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { marginTop: 16 }, children: action })
2585
2808
  ] });
2586
2809
  }
2587
2810
 
2588
2811
  // src/hooks/useLoginForm.ts
2589
- var import_react16 = require("react");
2590
- var import_sdk11 = require("@hook-sdk/sdk");
2812
+ var import_react17 = require("react");
2813
+ var import_sdk12 = require("@hook-sdk/sdk");
2591
2814
 
2592
2815
  // src/errors.ts
2593
- var import_sdk10 = require("@hook-sdk/sdk");
2816
+ var import_sdk11 = require("@hook-sdk/sdk");
2594
2817
  function mapSdkError(err) {
2595
- if (err instanceof import_sdk10.SdkRateLimitError) {
2818
+ if (err instanceof import_sdk11.SdkRateLimitError) {
2596
2819
  return {
2597
2820
  code: "rate_limited",
2598
2821
  message: `Aguarde ${err.retryAfter}s e tente novamente.`,
2599
2822
  retryAfter: err.retryAfter
2600
2823
  };
2601
2824
  }
2602
- if (err instanceof import_sdk10.SdkAuthError) {
2825
+ if (err instanceof import_sdk11.SdkAuthError) {
2603
2826
  const detail = err.detail;
2604
2827
  if (detail === "email_unverified") {
2605
2828
  return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
@@ -2609,7 +2832,7 @@ function mapSdkError(err) {
2609
2832
  }
2610
2833
  return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
2611
2834
  }
2612
- if (err instanceof import_sdk10.SdkError && err.httpStatus === 0) {
2835
+ if (err instanceof import_sdk11.SdkError && err.httpStatus === 0) {
2613
2836
  return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
2614
2837
  }
2615
2838
  if (err instanceof TypeError) {
@@ -2622,20 +2845,20 @@ function mapSdkError(err) {
2622
2845
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2623
2846
  var MIN_PASSWORD = 8;
2624
2847
  function useLoginForm() {
2625
- const { auth } = (0, import_sdk11.useHook)();
2626
- const [email, setEmail] = (0, import_react16.useState)("");
2627
- const [password, setPassword] = (0, import_react16.useState)("");
2628
- const [submitting, setSubmitting] = (0, import_react16.useState)(false);
2629
- const [error, setError] = (0, import_react16.useState)(null);
2630
- const [touchedEmail, setTouchedEmail] = (0, import_react16.useState)(false);
2631
- const [touchedPassword, setTouchedPassword] = (0, import_react16.useState)(false);
2632
- const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react16.useState)(false);
2633
- const validateEmail = (0, import_react16.useMemo)(() => {
2848
+ const { auth } = (0, import_sdk12.useHook)();
2849
+ const [email, setEmail] = (0, import_react17.useState)("");
2850
+ const [password, setPassword] = (0, import_react17.useState)("");
2851
+ const [submitting, setSubmitting] = (0, import_react17.useState)(false);
2852
+ const [error, setError] = (0, import_react17.useState)(null);
2853
+ const [touchedEmail, setTouchedEmail] = (0, import_react17.useState)(false);
2854
+ const [touchedPassword, setTouchedPassword] = (0, import_react17.useState)(false);
2855
+ const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react17.useState)(false);
2856
+ const validateEmail = (0, import_react17.useMemo)(() => {
2634
2857
  if (email.length === 0) return null;
2635
2858
  if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
2636
2859
  return null;
2637
2860
  }, [email]);
2638
- const validatePassword = (0, import_react16.useMemo)(() => {
2861
+ const validatePassword = (0, import_react17.useMemo)(() => {
2639
2862
  if (password.length === 0) return null;
2640
2863
  if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
2641
2864
  return null;
@@ -2643,7 +2866,7 @@ function useLoginForm() {
2643
2866
  const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
2644
2867
  const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
2645
2868
  const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
2646
- const submit = (0, import_react16.useCallback)(async () => {
2869
+ const submit = (0, import_react17.useCallback)(async () => {
2647
2870
  setFormSubmitAttempted(true);
2648
2871
  if (!canSubmit) return false;
2649
2872
  setSubmitting(true);
@@ -2677,32 +2900,32 @@ function useLoginForm() {
2677
2900
  }
2678
2901
 
2679
2902
  // src/hooks/useSignupForm.ts
2680
- var import_react17 = require("react");
2681
- var import_sdk12 = require("@hook-sdk/sdk");
2903
+ var import_react18 = require("react");
2904
+ var import_sdk13 = require("@hook-sdk/sdk");
2682
2905
  var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2683
2906
  var MIN_PASSWORD2 = 8;
2684
2907
  function useSignupForm() {
2685
- const { auth } = (0, import_sdk12.useHook)();
2686
- const [name, setName] = (0, import_react17.useState)("");
2687
- const [email, setEmail] = (0, import_react17.useState)("");
2688
- const [password, setPassword] = (0, import_react17.useState)("");
2689
- const [submitting, setSubmitting] = (0, import_react17.useState)(false);
2690
- const [error, setError] = (0, import_react17.useState)(null);
2691
- const [touchedName, setTouchedName] = (0, import_react17.useState)(false);
2692
- const [touchedEmail, setTouchedEmail] = (0, import_react17.useState)(false);
2693
- const [touchedPassword, setTouchedPassword] = (0, import_react17.useState)(false);
2694
- const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react17.useState)(false);
2695
- const validateName = (0, import_react17.useMemo)(() => {
2908
+ const { auth } = (0, import_sdk13.useHook)();
2909
+ const [name, setName] = (0, import_react18.useState)("");
2910
+ const [email, setEmail] = (0, import_react18.useState)("");
2911
+ const [password, setPassword] = (0, import_react18.useState)("");
2912
+ const [submitting, setSubmitting] = (0, import_react18.useState)(false);
2913
+ const [error, setError] = (0, import_react18.useState)(null);
2914
+ const [touchedName, setTouchedName] = (0, import_react18.useState)(false);
2915
+ const [touchedEmail, setTouchedEmail] = (0, import_react18.useState)(false);
2916
+ const [touchedPassword, setTouchedPassword] = (0, import_react18.useState)(false);
2917
+ const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
2918
+ const validateName = (0, import_react18.useMemo)(() => {
2696
2919
  if (name.length === 0) return null;
2697
2920
  if (name.trim().length < 2) return "Nome muito curto.";
2698
2921
  return null;
2699
2922
  }, [name]);
2700
- const validateEmail = (0, import_react17.useMemo)(() => {
2923
+ const validateEmail = (0, import_react18.useMemo)(() => {
2701
2924
  if (email.length === 0) return null;
2702
2925
  if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
2703
2926
  return null;
2704
2927
  }, [email]);
2705
- const validatePassword = (0, import_react17.useMemo)(() => {
2928
+ const validatePassword = (0, import_react18.useMemo)(() => {
2706
2929
  if (password.length === 0) return null;
2707
2930
  if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
2708
2931
  return null;
@@ -2711,7 +2934,7 @@ function useSignupForm() {
2711
2934
  const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
2712
2935
  const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
2713
2936
  const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
2714
- const submit = (0, import_react17.useCallback)(async () => {
2937
+ const submit = (0, import_react18.useCallback)(async () => {
2715
2938
  setFormSubmitAttempted(true);
2716
2939
  if (!canSubmit) return false;
2717
2940
  setSubmitting(true);
@@ -2749,25 +2972,25 @@ function useSignupForm() {
2749
2972
  }
2750
2973
 
2751
2974
  // src/hooks/useForgotForm.ts
2752
- var import_react18 = require("react");
2753
- var import_sdk13 = require("@hook-sdk/sdk");
2975
+ var import_react19 = require("react");
2976
+ var import_sdk14 = require("@hook-sdk/sdk");
2754
2977
  var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2755
2978
  function useForgotForm() {
2756
- const { auth } = (0, import_sdk13.useHook)();
2757
- const [email, setEmail] = (0, import_react18.useState)("");
2758
- const [submitting, setSubmitting] = (0, import_react18.useState)(false);
2759
- const [sent, setSent] = (0, import_react18.useState)(false);
2760
- const [error, setError] = (0, import_react18.useState)(null);
2761
- const [touchedEmail, setTouchedEmail] = (0, import_react18.useState)(false);
2762
- const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
2763
- const validateEmail = (0, import_react18.useMemo)(() => {
2979
+ const { auth } = (0, import_sdk14.useHook)();
2980
+ const [email, setEmail] = (0, import_react19.useState)("");
2981
+ const [submitting, setSubmitting] = (0, import_react19.useState)(false);
2982
+ const [sent, setSent] = (0, import_react19.useState)(false);
2983
+ const [error, setError] = (0, import_react19.useState)(null);
2984
+ const [touchedEmail, setTouchedEmail] = (0, import_react19.useState)(false);
2985
+ const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react19.useState)(false);
2986
+ const validateEmail = (0, import_react19.useMemo)(() => {
2764
2987
  if (email.length === 0) return null;
2765
2988
  if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
2766
2989
  return null;
2767
2990
  }, [email]);
2768
2991
  const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
2769
2992
  const canSubmit = email.length > 0 && validateEmail === null && !submitting;
2770
- const submit = (0, import_react18.useCallback)(async () => {
2993
+ const submit = (0, import_react19.useCallback)(async () => {
2771
2994
  setFormSubmitAttempted(true);
2772
2995
  if (!canSubmit) return false;
2773
2996
  setSubmitting(true);
@@ -2798,32 +3021,32 @@ function useForgotForm() {
2798
3021
  }
2799
3022
 
2800
3023
  // src/hooks/useResetForm.ts
2801
- var import_react19 = require("react");
2802
- var import_sdk14 = require("@hook-sdk/sdk");
3024
+ var import_react20 = require("react");
3025
+ var import_sdk15 = require("@hook-sdk/sdk");
2803
3026
  var MIN_PASSWORD3 = 12;
2804
3027
  function useResetForm() {
2805
- const { auth } = (0, import_sdk14.useHook)();
2806
- const [token, setToken] = (0, import_react19.useState)(null);
2807
- const [password, setPassword] = (0, import_react19.useState)("");
2808
- const [confirm, setConfirm] = (0, import_react19.useState)("");
2809
- const [submitting, setSubmitting] = (0, import_react19.useState)(false);
2810
- const [done, setDone] = (0, import_react19.useState)(false);
2811
- const [error, setError] = (0, import_react19.useState)(null);
2812
- const [touchedPassword, setTouchedPassword] = (0, import_react19.useState)(false);
2813
- const [touchedConfirm, setTouchedConfirm] = (0, import_react19.useState)(false);
2814
- const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react19.useState)(false);
2815
- (0, import_react19.useEffect)(() => {
3028
+ const { auth } = (0, import_sdk15.useHook)();
3029
+ const [token, setToken] = (0, import_react20.useState)(null);
3030
+ const [password, setPassword] = (0, import_react20.useState)("");
3031
+ const [confirm, setConfirm] = (0, import_react20.useState)("");
3032
+ const [submitting, setSubmitting] = (0, import_react20.useState)(false);
3033
+ const [done, setDone] = (0, import_react20.useState)(false);
3034
+ const [error, setError] = (0, import_react20.useState)(null);
3035
+ const [touchedPassword, setTouchedPassword] = (0, import_react20.useState)(false);
3036
+ const [touchedConfirm, setTouchedConfirm] = (0, import_react20.useState)(false);
3037
+ const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react20.useState)(false);
3038
+ (0, import_react20.useEffect)(() => {
2816
3039
  if (typeof window === "undefined") return;
2817
3040
  const params = new URLSearchParams(window.location.search);
2818
3041
  const t = params.get("token");
2819
3042
  setToken(t && t.length > 0 ? t : null);
2820
3043
  }, []);
2821
- const validatePassword = (0, import_react19.useMemo)(() => {
3044
+ const validatePassword = (0, import_react20.useMemo)(() => {
2822
3045
  if (password.length === 0) return null;
2823
3046
  if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
2824
3047
  return null;
2825
3048
  }, [password]);
2826
- const validateConfirm = (0, import_react19.useMemo)(() => {
3049
+ const validateConfirm = (0, import_react20.useMemo)(() => {
2827
3050
  if (confirm.length === 0) return null;
2828
3051
  if (confirm !== password) return "Senhas n\xE3o coincidem.";
2829
3052
  return null;
@@ -2831,7 +3054,7 @@ function useResetForm() {
2831
3054
  const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
2832
3055
  const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
2833
3056
  const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
2834
- const submit = (0, import_react19.useCallback)(async () => {
3057
+ const submit = (0, import_react20.useCallback)(async () => {
2835
3058
  setFormSubmitAttempted(true);
2836
3059
  if (!canSubmit || token === null) return;
2837
3060
  setSubmitting(true);
@@ -2871,9 +3094,9 @@ function useResetForm() {
2871
3094
  }
2872
3095
 
2873
3096
  // src/hooks/usePlan.ts
2874
- var import_sdk15 = require("@hook-sdk/sdk");
3097
+ var import_sdk16 = require("@hook-sdk/sdk");
2875
3098
  function usePlan() {
2876
- const { plan } = (0, import_sdk15.useHook)();
3099
+ const { plan } = (0, import_sdk16.useHook)();
2877
3100
  return plan;
2878
3101
  }
2879
3102
 
@@ -2906,12 +3129,12 @@ function discountPercent(anchorCents, realCents) {
2906
3129
  }
2907
3130
 
2908
3131
  // src/hooks/useAuthPrimitives.ts
2909
- var import_react20 = require("react");
2910
- var import_sdk16 = require("@hook-sdk/sdk");
3132
+ var import_react21 = require("react");
3133
+ var import_sdk17 = require("@hook-sdk/sdk");
2911
3134
  var warned = false;
2912
3135
  function useAuthPrimitives() {
2913
- const { auth } = (0, import_sdk16.useHook)();
2914
- (0, import_react20.useEffect)(() => {
3136
+ const { auth } = (0, import_sdk17.useHook)();
3137
+ (0, import_react21.useEffect)(() => {
2915
3138
  if (!warned && process.env.NODE_ENV !== "production") {
2916
3139
  warned = true;
2917
3140
  console.warn(
@@ -2933,9 +3156,9 @@ function useAuthPrimitives() {
2933
3156
  }
2934
3157
 
2935
3158
  // src/hooks/useAuth.ts
2936
- var import_sdk17 = require("@hook-sdk/sdk");
3159
+ var import_sdk18 = require("@hook-sdk/sdk");
2937
3160
  function useAuth() {
2938
- const { user, authStatus, auth } = (0, import_sdk17.useHook)();
3161
+ const { user, authStatus, auth } = (0, import_sdk18.useHook)();
2939
3162
  return {
2940
3163
  user,
2941
3164
  authStatus,
@@ -2944,26 +3167,26 @@ function useAuth() {
2944
3167
  }
2945
3168
 
2946
3169
  // src/index.ts
2947
- var import_sdk21 = require("@hook-sdk/sdk");
3170
+ var import_sdk23 = require("@hook-sdk/sdk");
2948
3171
 
2949
3172
  // src/hooks/useSubscription.ts
2950
- var import_sdk18 = require("@hook-sdk/sdk");
3173
+ var import_sdk19 = require("@hook-sdk/sdk");
2951
3174
  function useSubscription() {
2952
- const { subscription } = (0, import_sdk18.useHook)();
3175
+ const { subscription } = (0, import_sdk19.useHook)();
2953
3176
  return {
2954
3177
  status: subscription.status()
2955
3178
  };
2956
3179
  }
2957
3180
 
2958
3181
  // src/hooks/useReminders.ts
2959
- var import_react21 = require("react");
2960
- var import_sdk19 = require("@hook-sdk/sdk");
3182
+ var import_react22 = require("react");
3183
+ var import_sdk20 = require("@hook-sdk/sdk");
2961
3184
  function useReminders() {
2962
- const { push } = (0, import_sdk19.useHook)();
3185
+ const { push } = (0, import_sdk20.useHook)();
2963
3186
  const r = push.reminders;
2964
- const [reminders, setReminders] = (0, import_react21.useState)([]);
2965
- const [loading, setLoading] = (0, import_react21.useState)(true);
2966
- const reload = (0, import_react21.useCallback)(async () => {
3187
+ const [reminders, setReminders] = (0, import_react22.useState)([]);
3188
+ const [loading, setLoading] = (0, import_react22.useState)(true);
3189
+ const reload = (0, import_react22.useCallback)(async () => {
2967
3190
  setLoading(true);
2968
3191
  try {
2969
3192
  const next = await r.list();
@@ -2972,38 +3195,38 @@ function useReminders() {
2972
3195
  setLoading(false);
2973
3196
  }
2974
3197
  }, [r]);
2975
- (0, import_react21.useEffect)(() => {
3198
+ (0, import_react22.useEffect)(() => {
2976
3199
  void reload();
2977
3200
  }, [reload]);
2978
- const setReminder = (0, import_react21.useCallback)(async (input) => {
3201
+ const setReminder = (0, import_react22.useCallback)(async (input) => {
2979
3202
  await r.set(input);
2980
3203
  await reload();
2981
3204
  }, [r, reload]);
2982
- const deleteReminder = (0, import_react21.useCallback)(async (slot) => {
3205
+ const deleteReminder = (0, import_react22.useCallback)(async (slot) => {
2983
3206
  await r.delete(slot);
2984
3207
  await reload();
2985
3208
  }, [r, reload]);
2986
- const schedule = (0, import_react21.useCallback)(async (items) => {
3209
+ const schedule = (0, import_react22.useCallback)(async (items) => {
2987
3210
  return r.schedule(items);
2988
3211
  }, [r]);
2989
- const setFallbacks = (0, import_react21.useCallback)(async (items) => {
3212
+ const setFallbacks = (0, import_react22.useCallback)(async (items) => {
2990
3213
  return r.setFallbacks(items);
2991
3214
  }, [r]);
2992
3215
  return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
2993
3216
  }
2994
3217
 
2995
3218
  // src/hooks/useToast.ts
2996
- var import_react22 = require("react");
3219
+ var import_react23 = require("react");
2997
3220
  function useToast() {
2998
- const [items, setItems] = (0, import_react22.useState)([]);
2999
- const show = (0, import_react22.useCallback)((message, kind = "info") => {
3221
+ const [items, setItems] = (0, import_react23.useState)([]);
3222
+ const show = (0, import_react23.useCallback)((message, kind = "info") => {
3000
3223
  const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
3001
3224
  setItems((prev) => [...prev, { id, message, kind }]);
3002
3225
  setTimeout(() => {
3003
3226
  setItems((prev) => prev.filter((t) => t.id !== id));
3004
3227
  }, 4e3);
3005
3228
  }, []);
3006
- const dismiss = (0, import_react22.useCallback)((id) => {
3229
+ const dismiss = (0, import_react23.useCallback)((id) => {
3007
3230
  setItems((prev) => prev.filter((t) => t.id !== id));
3008
3231
  }, []);
3009
3232
  return { items, show, dismiss };
@@ -3011,20 +3234,20 @@ function useToast() {
3011
3234
 
3012
3235
  // src/RouteBoundary.tsx
3013
3236
  var import_react_router_dom3 = require("react-router-dom");
3014
- var import_jsx_runtime26 = require("react/jsx-runtime");
3237
+ var import_jsx_runtime27 = require("react/jsx-runtime");
3015
3238
  function RouteBoundary({ children }) {
3016
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react_router_dom3.Routes, { children: [
3239
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_router_dom3.Routes, { children: [
3017
3240
  children,
3018
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DefaultNotFound, {}) })
3241
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DefaultNotFound, {}) })
3019
3242
  ] });
3020
3243
  }
3021
3244
  function DefaultNotFound() {
3022
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
3245
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
3023
3246
  }
3024
3247
 
3025
3248
  // src/PreAuthShell.tsx
3026
3249
  var import_react_router_dom4 = require("react-router-dom");
3027
- var import_jsx_runtime27 = require("react/jsx-runtime");
3250
+ var import_jsx_runtime28 = require("react/jsx-runtime");
3028
3251
  function PreAuthShell({
3029
3252
  basename,
3030
3253
  testRouter,
@@ -3032,20 +3255,20 @@ function PreAuthShell({
3032
3255
  children
3033
3256
  }) {
3034
3257
  if (testRouter === "memory") {
3035
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.Routes, { children }) });
3258
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_router_dom4.Routes, { children }) });
3036
3259
  }
3037
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.Routes, { children }) });
3260
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_router_dom4.Routes, { children }) });
3038
3261
  }
3039
3262
 
3040
3263
  // src/OnboardingFlow.tsx
3041
- var import_react24 = require("react");
3042
- var import_sdk20 = require("@hook-sdk/sdk");
3264
+ var import_react25 = require("react");
3265
+ var import_sdk21 = require("@hook-sdk/sdk");
3043
3266
 
3044
3267
  // src/hooks/useOnboardingStep.ts
3045
- var import_react23 = require("react");
3046
- var OnboardingStepContext = (0, import_react23.createContext)(null);
3268
+ var import_react24 = require("react");
3269
+ var OnboardingStepContext = (0, import_react24.createContext)(null);
3047
3270
  function useOnboardingStep() {
3048
- const ctx = (0, import_react23.useContext)(OnboardingStepContext);
3271
+ const ctx = (0, import_react24.useContext)(OnboardingStepContext);
3049
3272
  if (!ctx) {
3050
3273
  throw new Error(
3051
3274
  "[hook-template] useOnboardingStep must be used inside <OnboardingFlow>. (G75)"
@@ -3055,7 +3278,7 @@ function useOnboardingStep() {
3055
3278
  }
3056
3279
 
3057
3280
  // src/OnboardingFlow.tsx
3058
- var import_jsx_runtime28 = require("react/jsx-runtime");
3281
+ var import_jsx_runtime29 = require("react/jsx-runtime");
3059
3282
  var isFilled = (v) => v != null && v !== "";
3060
3283
  var CURRENT_STEP_FIELD = "currentStep";
3061
3284
  function readPersistedStepIdx(draft) {
@@ -3068,12 +3291,12 @@ function OnboardingFlow({
3068
3291
  onComplete,
3069
3292
  persistKey
3070
3293
  }) {
3071
- const [draft, setDraft, status] = (0, import_sdk20.usePersistedState)(persistKey, {});
3072
- const draftRef = (0, import_react24.useRef)(draft);
3294
+ const [draft, setDraft, status] = (0, import_sdk21.usePersistedState)(persistKey, {});
3295
+ const draftRef = (0, import_react25.useRef)(draft);
3073
3296
  draftRef.current = draft;
3074
3297
  const idx = readPersistedStepIdx(draft);
3075
3298
  const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
3076
- const setIdx = (0, import_react24.useCallback)(
3299
+ const setIdx = (0, import_react25.useCallback)(
3077
3300
  (n) => {
3078
3301
  setDraft((prev) => {
3079
3302
  const prevIdx = readPersistedStepIdx(prev);
@@ -3083,7 +3306,7 @@ function OnboardingFlow({
3083
3306
  },
3084
3307
  [setDraft]
3085
3308
  );
3086
- const setValue = (0, import_react24.useCallback)(
3309
+ const setValue = (0, import_react25.useCallback)(
3087
3310
  (patch) => {
3088
3311
  draftRef.current = { ...draftRef.current, ...patch };
3089
3312
  setDraft((prev) => ({ ...prev, ...patch }));
@@ -3091,9 +3314,9 @@ function OnboardingFlow({
3091
3314
  [setDraft]
3092
3315
  );
3093
3316
  const step = steps[clampedIdx];
3094
- const hookCtx = (0, import_sdk20.useHook)();
3317
+ const hookCtx = (0, import_sdk21.useHook)();
3095
3318
  const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
3096
- (0, import_react24.useEffect)(() => {
3319
+ (0, import_react25.useEffect)(() => {
3097
3320
  if (status.loading) return;
3098
3321
  if (!step) return;
3099
3322
  if (!track2) return;
@@ -3103,11 +3326,11 @@ function OnboardingFlow({
3103
3326
  total_steps: steps.length
3104
3327
  });
3105
3328
  }, [step?.id, clampedIdx, steps.length, status.loading, track2]);
3106
- const valid = (0, import_react24.useMemo)(
3329
+ const valid = (0, import_react25.useMemo)(
3107
3330
  () => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
3108
3331
  [draft, step]
3109
3332
  );
3110
- const next = (0, import_react24.useCallback)(() => {
3333
+ const next = (0, import_react25.useCallback)(() => {
3111
3334
  if (!step) return;
3112
3335
  const current = draftRef.current;
3113
3336
  const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
@@ -3118,8 +3341,8 @@ function OnboardingFlow({
3118
3341
  setIdx(clampedIdx + 1);
3119
3342
  }
3120
3343
  }, [clampedIdx, onComplete, step, steps.length, setIdx]);
3121
- const prevStep = (0, import_react24.useCallback)(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
3122
- const ctx = (0, import_react24.useMemo)(
3344
+ const prevStep = (0, import_react25.useCallback)(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
3345
+ const ctx = (0, import_react25.useMemo)(
3123
3346
  () => ({
3124
3347
  stepIndex: clampedIdx,
3125
3348
  totalSteps: steps.length,
@@ -3145,7 +3368,7 @@ function OnboardingFlow({
3145
3368
  `[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
3146
3369
  );
3147
3370
  }
3148
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Screen, {}) });
3371
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Screen, {}) });
3149
3372
  }
3150
3373
 
3151
3374
  // src/hooks/useFeature.ts
@@ -3153,12 +3376,299 @@ function useFeature(name) {
3153
3376
  const config = useAppConfig();
3154
3377
  return Array.isArray(config.features_enabled) && config.features_enabled.includes(name);
3155
3378
  }
3379
+
3380
+ // src/components/paywall/Paywall.tsx
3381
+ var import_react26 = require("react");
3382
+ var import_sdk22 = require("@hook-sdk/sdk");
3383
+
3384
+ // src/components/paywall/PaywallMethodTabs.tsx
3385
+ var import_jsx_runtime30 = require("react/jsx-runtime");
3386
+ function PaywallMethodTabs({
3387
+ methods,
3388
+ selected,
3389
+ onSelect,
3390
+ labels,
3391
+ className,
3392
+ tabClassName,
3393
+ tabActiveClassName
3394
+ }) {
3395
+ if (methods.length < 2) return null;
3396
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { role: "tablist", "aria-label": "M\xE9todo de pagamento", className, children: methods.map((m) => {
3397
+ const active = m === selected;
3398
+ const label = labels[m] ?? m;
3399
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
3400
+ "button",
3401
+ {
3402
+ type: "button",
3403
+ role: "tab",
3404
+ "aria-selected": active,
3405
+ "aria-controls": `paywall-tab-${m}`,
3406
+ tabIndex: active ? 0 : -1,
3407
+ onClick: () => onSelect(m),
3408
+ className: [tabClassName, active ? tabActiveClassName : ""].filter(Boolean).join(" "),
3409
+ children: label
3410
+ },
3411
+ m
3412
+ );
3413
+ }) });
3414
+ }
3415
+
3416
+ // src/components/paywall/PaywallMethodContent.tsx
3417
+ var import_jsx_runtime31 = require("react/jsx-runtime");
3418
+ function PaywallMethodContent({
3419
+ method,
3420
+ copy,
3421
+ hasConsumedTrial = false,
3422
+ className,
3423
+ rowClassName
3424
+ }) {
3425
+ const useCardConsumed = method === "card" && hasConsumedTrial && copy.cardConsumedTrial;
3426
+ const rows = useCardConsumed ? copy.cardConsumedTrial.bodyRows : method === "pix-auto" || method === "pix-once" ? copy.pix.bodyRows : copy.card.bodyRows;
3427
+ 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)) });
3428
+ }
3429
+
3430
+ // src/components/paywall/PaywallCyclePicker.tsx
3431
+ var import_jsx_runtime32 = require("react/jsx-runtime");
3432
+ function PaywallCyclePicker({
3433
+ cycles,
3434
+ selected,
3435
+ onSelect,
3436
+ priceCentsByCycle,
3437
+ anchorCentsByCycle,
3438
+ monthlyEquivByCycle,
3439
+ labels,
3440
+ className,
3441
+ cardClassName,
3442
+ cardSelectedClassName,
3443
+ anchorClassName
3444
+ }) {
3445
+ if (cycles.length < 2) return null;
3446
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "radiogroup", "aria-label": "Ciclo de cobran\xE7a", className, children: cycles.map((c) => {
3447
+ const active = c === selected;
3448
+ const label = c === "YEARLY" ? labels.annualLabel : labels.monthlyLabel;
3449
+ const suffix = c === "YEARLY" ? labels.annualSuffix : labels.monthlySuffix;
3450
+ const mainCents = c === "YEARLY" ? monthlyEquivByCycle[c] : priceCentsByCycle[c];
3451
+ const anchorCents = anchorCentsByCycle[c];
3452
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
3453
+ "button",
3454
+ {
3455
+ type: "button",
3456
+ role: "radio",
3457
+ "aria-checked": active,
3458
+ onClick: () => onSelect(c),
3459
+ className: [cardClassName, active ? cardSelectedClassName : ""].filter(Boolean).join(" "),
3460
+ children: [
3461
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("strong", { children: formatBRL(mainCents) }),
3462
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: suffix }),
3463
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: label }),
3464
+ anchorCents != null && anchorCents > mainCents ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: anchorClassName, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("s", { children: formatBRL(anchorCents) }) }) : null
3465
+ ]
3466
+ },
3467
+ c
3468
+ );
3469
+ }) });
3470
+ }
3471
+
3472
+ // src/components/paywall/PaywallCta.tsx
3473
+ var import_jsx_runtime33 = require("react/jsx-runtime");
3474
+ function PaywallCta({
3475
+ ctaLabel,
3476
+ loadingLabel,
3477
+ switchHint,
3478
+ trustLine,
3479
+ onClick,
3480
+ disabled = false,
3481
+ loading = false,
3482
+ className,
3483
+ buttonClassName,
3484
+ switchHintClassName,
3485
+ trustClassName
3486
+ }) {
3487
+ const label = loading && loadingLabel ? loadingLabel : ctaLabel;
3488
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className, children: [
3489
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3490
+ "button",
3491
+ {
3492
+ type: "button",
3493
+ onClick,
3494
+ disabled: disabled || loading,
3495
+ className: buttonClassName,
3496
+ children: label
3497
+ }
3498
+ ),
3499
+ switchHint ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: switchHintClassName, children: switchHint }) : null,
3500
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: trustClassName, children: trustLine })
3501
+ ] });
3502
+ }
3503
+
3504
+ // src/components/paywall/Paywall.tsx
3505
+ var import_jsx_runtime34 = require("react/jsx-runtime");
3506
+ var NBSP = "\xA0";
3507
+ function Paywall({
3508
+ copy,
3509
+ themeClasses = {},
3510
+ slots = {},
3511
+ onBeforeCheckout
3512
+ }) {
3513
+ const { track: track2 } = (0, import_sdk22.useHook)();
3514
+ const s = usePaywallState();
3515
+ const priceLabel = formatBRL(s.currentPriceCents).replace(new RegExp(NBSP, "g"), " ");
3516
+ const monthlyEquivLabel = formatBRL(s.currentMonthlyEquivCents).replace(new RegExp(NBSP, "g"), " ");
3517
+ const trialDaysCardLabel = String(s.trialDaysCard);
3518
+ const ctaLabel = (0, import_react26.useMemo)(() => {
3519
+ if (s.isFree) return copy.freeCta ?? "Come\xE7ar agora";
3520
+ if (s.selectedMethod === "card") {
3521
+ if (s.hasConsumedTrial && copy.cardConsumedTrial) {
3522
+ return interp(copy.cardConsumedTrial.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel });
3523
+ }
3524
+ if (s.trialDaysCard > 0) {
3525
+ return interp(copy.card.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel });
3526
+ }
3527
+ return copy.cardConsumedTrial ? interp(copy.cardConsumedTrial.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel }) : `Assinar por ${priceLabel}`;
3528
+ }
3529
+ return interp(copy.pix.ctaTemplate, { price: priceLabel, days: trialDaysCardLabel });
3530
+ }, [
3531
+ s.isFree,
3532
+ s.selectedMethod,
3533
+ s.hasConsumedTrial,
3534
+ s.trialDaysCard,
3535
+ copy,
3536
+ priceLabel,
3537
+ trialDaysCardLabel
3538
+ ]);
3539
+ const switchHint = (0, import_react26.useMemo)(() => {
3540
+ if (s.methods.length < 2) return void 0;
3541
+ return s.selectedMethod === "card" ? copy.card.switchHint : copy.pix.switchHint;
3542
+ }, [s.methods.length, s.selectedMethod, copy]);
3543
+ (0, import_react26.useEffect)(() => {
3544
+ if (!s.initialLoadComplete) return;
3545
+ track2("paywall_view", {
3546
+ default_method: s.selectedMethod,
3547
+ default_cycle: s.cycle,
3548
+ available_methods: s.methods
3549
+ });
3550
+ }, [s.initialLoadComplete]);
3551
+ const handleCta = async () => {
3552
+ track2("paywall_cta_clicked", {
3553
+ method: s.selectedMethod,
3554
+ cycle: s.cycle,
3555
+ price_cents: s.currentPriceCents,
3556
+ had_consumed_trial: s.hasConsumedTrial
3557
+ });
3558
+ if (onBeforeCheckout) {
3559
+ await onBeforeCheckout(s.selectedMethod, s.cycle);
3560
+ return;
3561
+ }
3562
+ await s.submit();
3563
+ };
3564
+ const ctaTheme = s.selectedMethod === "card" ? themeClasses.ctaCard : themeClasses.ctaPix;
3565
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: themeClasses.container, children: [
3566
+ slots.heroSlot,
3567
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h1", { className: themeClasses.headline, children: copy.headline }),
3568
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { children: copy.features.map((f) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: themeClasses.feature, children: [
3569
+ "\u2713 ",
3570
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: f })
3571
+ ] }, f)) }),
3572
+ copy.socialProof ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: themeClasses.socialProof, children: copy.socialProof }) : null,
3573
+ slots.cyclePickerSlot ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3574
+ PaywallCyclePicker,
3575
+ {
3576
+ cycles: ["MONTHLY", "YEARLY"],
3577
+ selected: s.cycle,
3578
+ onSelect: s.selectCycle,
3579
+ priceCentsByCycle: {
3580
+ MONTHLY: priceCentsForCycle(s, "MONTHLY"),
3581
+ YEARLY: priceCentsForCycle(s, "YEARLY")
3582
+ },
3583
+ anchorCentsByCycle: {
3584
+ MONTHLY: anchorForCycle(s, "MONTHLY"),
3585
+ YEARLY: anchorForCycle(s, "YEARLY")
3586
+ },
3587
+ monthlyEquivByCycle: {
3588
+ MONTHLY: priceCentsForCycle(s, "MONTHLY"),
3589
+ YEARLY: Math.round(priceCentsForCycle(s, "YEARLY") / 12)
3590
+ },
3591
+ labels: copy.cycle,
3592
+ cardClassName: themeClasses.cycleCard,
3593
+ cardSelectedClassName: themeClasses.cycleCardSelected,
3594
+ anchorClassName: themeClasses.anchorPrice
3595
+ }
3596
+ ),
3597
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3598
+ PaywallMethodTabs,
3599
+ {
3600
+ methods: s.methods,
3601
+ selected: s.selectedMethod,
3602
+ onSelect: s.selectMethod,
3603
+ labels: { "pix-auto": copy.pix.tabLabel, card: copy.card.tabLabel },
3604
+ className: themeClasses.tabs,
3605
+ tabClassName: themeClasses.tab,
3606
+ tabActiveClassName: themeClasses.tabActive
3607
+ }
3608
+ ),
3609
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3610
+ PaywallMethodContent,
3611
+ {
3612
+ method: s.selectedMethod,
3613
+ copy: {
3614
+ pix: interpolateCopy(copy.pix, priceLabel, trialDaysCardLabel),
3615
+ card: interpolateCopy(copy.card, priceLabel, trialDaysCardLabel),
3616
+ cardConsumedTrial: copy.cardConsumedTrial ? {
3617
+ bodyRows: copy.cardConsumedTrial.bodyRows.map(
3618
+ (r) => interp(r, { price: priceLabel, days: trialDaysCardLabel })
3619
+ ),
3620
+ ctaTemplate: copy.cardConsumedTrial.ctaTemplate
3621
+ } : void 0
3622
+ },
3623
+ hasConsumedTrial: s.hasConsumedTrial,
3624
+ className: themeClasses.tabContent,
3625
+ rowClassName: themeClasses.tabContentRow
3626
+ }
3627
+ ),
3628
+ slots.beforeCtaSlot,
3629
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3630
+ PaywallCta,
3631
+ {
3632
+ ctaLabel,
3633
+ loadingLabel: "Abrindo checkout\u2026",
3634
+ switchHint,
3635
+ trustLine: copy.trustLine,
3636
+ onClick: handleCta,
3637
+ disabled: !s.initialLoadComplete,
3638
+ loading: s.submitting,
3639
+ buttonClassName: ctaTheme,
3640
+ switchHintClassName: themeClasses.switchHint,
3641
+ trustClassName: themeClasses.trustLine
3642
+ }
3643
+ )
3644
+ ] });
3645
+ }
3646
+ function interp(tpl, vars) {
3647
+ return tpl.replace(/\{(\w+)\}/g, (_m, k) => vars[k] ?? "");
3648
+ }
3649
+ function interpolateCopy(m, price, days) {
3650
+ return {
3651
+ tabLabel: m.tabLabel,
3652
+ bodyRows: m.bodyRows.map((r) => interp(r, { price, days })),
3653
+ ctaTemplate: m.ctaTemplate,
3654
+ switchHint: m.switchHint
3655
+ };
3656
+ }
3657
+ function priceCentsForCycle(s, c) {
3658
+ return s.plan ? c === "YEARLY" ? s.plan.yearlyCents ?? 0 : s.plan.monthlyCents : 0;
3659
+ }
3660
+ function anchorForCycle(s, c) {
3661
+ if (!s.plan) return null;
3662
+ if (c === "YEARLY") return s.plan.anchorYearlyCents ?? null;
3663
+ return s.plan.anchorMonthlyCents ?? null;
3664
+ }
3156
3665
  // Annotate the CommonJS export names for ESM import in node:
3157
3666
  0 && (module.exports = {
3158
3667
  AppConfigProvider,
3159
3668
  AppConfigSchema,
3160
3669
  AppRoot,
3161
3670
  DeepLinkHandler,
3671
+ DevSkipOnboardingFab,
3162
3672
  EmptyState,
3163
3673
  ErrorBoundary,
3164
3674
  I18nProvider,
@@ -3168,6 +3678,11 @@ function useFeature(name) {
3168
3678
  LoadingState,
3169
3679
  OnboardingFlow,
3170
3680
  PaymentReturnHandler,
3681
+ Paywall,
3682
+ PaywallCta,
3683
+ PaywallCyclePicker,
3684
+ PaywallMethodContent,
3685
+ PaywallMethodTabs,
3171
3686
  PersistenceRegistry,
3172
3687
  PreAuthShell,
3173
3688
  PushPrompt,
@@ -3182,10 +3697,12 @@ function useFeature(name) {
3182
3697
  detectStandalone,
3183
3698
  discountPercent,
3184
3699
  formatBRL,
3700
+ isDevToolsEnabled,
3185
3701
  monthlyFromYearly,
3186
3702
  parseAppConfig,
3187
3703
  shouldBlockInstall,
3188
3704
  shouldShowPermanentOption,
3705
+ skipOnboarding,
3189
3706
  useAppConfig,
3190
3707
  useAuth,
3191
3708
  useAuthPrimitives,