@hook-sdk/template 0.20.0 → 0.22.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 +714 -202
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +242 -2
- package/dist/index.d.ts +242 -2
- package/dist/index.js +666 -163
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, ComponentType, Component } from 'react';
|
|
4
4
|
import * as _hook_sdk_sdk from '@hook-sdk/sdk';
|
|
5
|
-
import { CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { HookContextValue, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
6
|
export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
|
|
@@ -19,7 +19,27 @@ type PaywallConfig = {
|
|
|
19
19
|
mode: 'free';
|
|
20
20
|
} | {
|
|
21
21
|
mode: 'trial' | 'pay_first';
|
|
22
|
+
/**
|
|
23
|
+
* Legacy flat trial — fallback when per-method fields aren't set.
|
|
24
|
+
* Read via `trialDaysForMethod(method)` helper on `usePaywallState`.
|
|
25
|
+
*/
|
|
22
26
|
trialDays?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Per-method trial overrides (ADR-022 Amendment 2026-05-12 + G154).
|
|
29
|
+
* - `trialDaysCard` — days of free trial on the card method.
|
|
30
|
+
* Default 7 in the backend, but apps can opt down to 0 if they want
|
|
31
|
+
* PIX-style "pay now" semantics on cards too.
|
|
32
|
+
* - `trialDaysPix` — days of free trial on PIX Auto. Default 0 because
|
|
33
|
+
* Asaas does not implement BCB Jornada 2 (consent-only authorization).
|
|
34
|
+
* Any value > 0 forces the R$ 0,01 capture workaround — see G123-G127.
|
|
35
|
+
*/
|
|
36
|
+
trialDaysCard?: number;
|
|
37
|
+
trialDaysPix?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Which method the paywall preselects. Reflects creator audience,
|
|
40
|
+
* not Hook bias. `null`/`undefined` = no preselection — user picks.
|
|
41
|
+
*/
|
|
42
|
+
defaultMethod?: CheckoutMethod | null;
|
|
23
43
|
cycles: Cycle[];
|
|
24
44
|
prices: {
|
|
25
45
|
monthlyCents: number;
|
|
@@ -120,6 +140,33 @@ interface AuthScreenProps {
|
|
|
120
140
|
onNavigate?: (target: 'login' | 'signup' | 'forgot' | 'reset') => void;
|
|
121
141
|
}
|
|
122
142
|
|
|
143
|
+
interface SkipDefaults {
|
|
144
|
+
/**
|
|
145
|
+
* Final flag the host app's ProtectedRoute reads. If unset here, the helper
|
|
146
|
+
* forces it to `true` after merging defaults.
|
|
147
|
+
*/
|
|
148
|
+
onboarding_completed?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Free-form per-app fields (userName, mainGoal, faixa, kids[], etc.). The
|
|
151
|
+
* helper merges this object verbatim into `appData.set('onboarding_data', …)`.
|
|
152
|
+
*/
|
|
153
|
+
[field: string]: unknown;
|
|
154
|
+
/**
|
|
155
|
+
* Optional per-app seed callback. Use to insert anything that lives outside
|
|
156
|
+
* `onboarding_data` (e.g. seed first workout in `hook.db.collection('workouts')`).
|
|
157
|
+
* Awaited after `appData.set` and before the hard reload.
|
|
158
|
+
*/
|
|
159
|
+
__seed?: (hook: HookContextValue) => Promise<void>;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Programmatic skip helper. Exposed for advanced consumers / tests; the FAB
|
|
163
|
+
* just calls this on confirm.
|
|
164
|
+
*/
|
|
165
|
+
declare function skipOnboarding(hook: HookContextValue, defaults: SkipDefaults, appSlug: string): Promise<void>;
|
|
166
|
+
declare function DevSkipOnboardingFab({ defaults }: {
|
|
167
|
+
defaults: SkipDefaults;
|
|
168
|
+
}): react_jsx_runtime.JSX.Element;
|
|
169
|
+
|
|
123
170
|
declare function PaymentReturnHandler({ children }: {
|
|
124
171
|
children: ReactNode;
|
|
125
172
|
}): react_jsx_runtime.JSX.Element;
|
|
@@ -145,10 +192,37 @@ type AppRootProps = AppRootSlots & {
|
|
|
145
192
|
testRouter?: 'memory';
|
|
146
193
|
/** Test-only: initial entries for MemoryRouter. */
|
|
147
194
|
testInitialEntries?: string[];
|
|
195
|
+
/**
|
|
196
|
+
* Staging-only dev tools. When this prop is set AND
|
|
197
|
+
* `VITE_HOOK_DEV_TOOLS=1` AND the hostname is staging/localhost, AppRoot
|
|
198
|
+
* mounts a floating "skip onboarding" button that pre-fills
|
|
199
|
+
* `appData.onboarding_data` with the supplied defaults and lands the user
|
|
200
|
+
* on `/app/<slug>/`. Tree-shaken from prod builds via the build-time env
|
|
201
|
+
* replacement (see `dev/env.ts`).
|
|
202
|
+
*/
|
|
203
|
+
devSkipOnboarding?: {
|
|
204
|
+
defaults: SkipDefaults;
|
|
205
|
+
};
|
|
148
206
|
};
|
|
149
207
|
|
|
150
208
|
declare function AppRoot(props: AppRootProps): react_jsx_runtime.JSX.Element;
|
|
151
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Build-time + runtime gate for dev-only tools (e.g. <DevSkipOnboardingFab>).
|
|
212
|
+
*
|
|
213
|
+
* Two independent signals must agree:
|
|
214
|
+
*
|
|
215
|
+
* 1. Build-time: `import.meta.env.VITE_HOOK_DEV_TOOLS === '1'`. Vite folds
|
|
216
|
+
* this constant at build time — when unset, the entire dev tree is
|
|
217
|
+
* tree-shaken from the prod bundle (sideEffects:false in package.json
|
|
218
|
+
* makes that effective). Set `VITE_HOOK_DEV_TOOLS=1` only in
|
|
219
|
+
* `.env.staging` builds.
|
|
220
|
+
*
|
|
221
|
+
* 2. Runtime: hostname must be staging-ish. Belt-and-suspenders against
|
|
222
|
+
* a misconfigured build that somehow ships the FAB to prod.
|
|
223
|
+
*/
|
|
224
|
+
declare function isDevToolsEnabled(): boolean;
|
|
225
|
+
|
|
152
226
|
interface PushPromptTexts {
|
|
153
227
|
cta: string;
|
|
154
228
|
declineCta: string;
|
|
@@ -464,6 +538,16 @@ declare function usePaywallState(): {
|
|
|
464
538
|
methods: readonly CheckoutMethod$1[];
|
|
465
539
|
selectedMethod: CheckoutMethod$1;
|
|
466
540
|
setSelectedMethod: react.Dispatch<react.SetStateAction<CheckoutMethod$1>>;
|
|
541
|
+
hasConsumedTrial: boolean;
|
|
542
|
+
currentPriceCents: number;
|
|
543
|
+
currentMonthlyEquivCents: number;
|
|
544
|
+
anchorPriceCents: number | null;
|
|
545
|
+
selectMethod: (next: CheckoutMethod$1) => void;
|
|
546
|
+
selectCycle: (next: CheckoutCycle) => void;
|
|
547
|
+
isFree: boolean;
|
|
548
|
+
trialDaysForMethod: (method: CheckoutMethod$1) => number;
|
|
549
|
+
trialDaysCard: number;
|
|
550
|
+
trialDaysPix: number;
|
|
467
551
|
cpfState: CpfState;
|
|
468
552
|
cardState: CardFormStateWithSetter;
|
|
469
553
|
submit: () => Promise<CheckoutResult | undefined>;
|
|
@@ -882,6 +966,13 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
882
966
|
pay_first: "pay_first";
|
|
883
967
|
}>;
|
|
884
968
|
trialDays: z.ZodOptional<z.ZodNumber>;
|
|
969
|
+
trialDaysCard: z.ZodOptional<z.ZodNumber>;
|
|
970
|
+
trialDaysPix: z.ZodOptional<z.ZodNumber>;
|
|
971
|
+
defaultMethod: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
972
|
+
card: "card";
|
|
973
|
+
"pix-auto": "pix-auto";
|
|
974
|
+
"pix-once": "pix-once";
|
|
975
|
+
}>>>;
|
|
885
976
|
cycles: z.ZodArray<z.ZodEnum<{
|
|
886
977
|
MONTHLY: "MONTHLY";
|
|
887
978
|
YEARLY: "YEARLY";
|
|
@@ -950,4 +1041,153 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
950
1041
|
}, z.core.$strict>;
|
|
951
1042
|
declare function parseAppConfig(input: unknown): AppConfig;
|
|
952
1043
|
|
|
953
|
-
|
|
1044
|
+
type PaywallMethodCopy = {
|
|
1045
|
+
/** Tab label, e.g. "⚡ PIX" or "💳 Cartão" */
|
|
1046
|
+
tabLabel: string;
|
|
1047
|
+
/** 3 body rows under the active tab. Use literal strings; price/days come from the hook. */
|
|
1048
|
+
bodyRows: [string, string, string];
|
|
1049
|
+
/** CTA label template. `{price}` and `{days}` placeholders are interpolated. */
|
|
1050
|
+
ctaTemplate: string;
|
|
1051
|
+
/** Switch-hint copy shown under the CTA when the OTHER tab is available. */
|
|
1052
|
+
switchHint: string;
|
|
1053
|
+
};
|
|
1054
|
+
type PaywallCopy = {
|
|
1055
|
+
headline: string;
|
|
1056
|
+
features: readonly string[];
|
|
1057
|
+
socialProof?: string;
|
|
1058
|
+
/** Trust line above sticky CTA. Shared across methods. */
|
|
1059
|
+
trustLine: string;
|
|
1060
|
+
pix: PaywallMethodCopy;
|
|
1061
|
+
card: PaywallMethodCopy;
|
|
1062
|
+
/** Used when `usePaywallState().hasConsumedTrial === true`. Card tab body + CTA shift. */
|
|
1063
|
+
cardConsumedTrial: Omit<PaywallMethodCopy, 'tabLabel' | 'switchHint'>;
|
|
1064
|
+
cycle: {
|
|
1065
|
+
annualLabel: string;
|
|
1066
|
+
monthlyLabel: string;
|
|
1067
|
+
/** Append after price on annual card, e.g. "/mês · anual" */
|
|
1068
|
+
annualSuffix: string;
|
|
1069
|
+
/** Append after price on monthly card, e.g. "/mês" */
|
|
1070
|
+
monthlySuffix: string;
|
|
1071
|
+
};
|
|
1072
|
+
/** Optional override for the "free" CTA when `paywall.mode === 'free'`. */
|
|
1073
|
+
freeCta?: string;
|
|
1074
|
+
};
|
|
1075
|
+
type PaywallThemeClasses = {
|
|
1076
|
+
/** Container wrapper. Default: empty. */
|
|
1077
|
+
container?: string;
|
|
1078
|
+
/** Headline `<h1>`. */
|
|
1079
|
+
headline?: string;
|
|
1080
|
+
/** Feature row `<li>`. */
|
|
1081
|
+
feature?: string;
|
|
1082
|
+
/** Cycle picker card. */
|
|
1083
|
+
cycleCard?: string;
|
|
1084
|
+
/** Cycle picker card when selected. */
|
|
1085
|
+
cycleCardSelected?: string;
|
|
1086
|
+
/** Method tabs wrapper (pill background). */
|
|
1087
|
+
tabs?: string;
|
|
1088
|
+
/** Individual tab. */
|
|
1089
|
+
tab?: string;
|
|
1090
|
+
/** Individual tab when active. */
|
|
1091
|
+
tabActive?: string;
|
|
1092
|
+
/** Tab body card. */
|
|
1093
|
+
tabContent?: string;
|
|
1094
|
+
/** Tab body row (one row per icon+text). */
|
|
1095
|
+
tabContentRow?: string;
|
|
1096
|
+
/** CTA button — applied when method=pix-auto. */
|
|
1097
|
+
ctaPix?: string;
|
|
1098
|
+
/** CTA button — applied when method=card. */
|
|
1099
|
+
ctaCard?: string;
|
|
1100
|
+
/** Switch-hint line under CTA. */
|
|
1101
|
+
switchHint?: string;
|
|
1102
|
+
/** Trust line under switch hint. */
|
|
1103
|
+
trustLine?: string;
|
|
1104
|
+
/** Social proof badge. */
|
|
1105
|
+
socialProof?: string;
|
|
1106
|
+
/** Anchor strikethrough price. */
|
|
1107
|
+
anchorPrice?: string;
|
|
1108
|
+
};
|
|
1109
|
+
type PaywallSlots = {
|
|
1110
|
+
/** Above headline (hero image, brand visual). */
|
|
1111
|
+
heroSlot?: ReactNode;
|
|
1112
|
+
/** Below tab content, above CTA (e.g. testimonials). */
|
|
1113
|
+
beforeCtaSlot?: ReactNode;
|
|
1114
|
+
/** Replace the cycle picker entirely. */
|
|
1115
|
+
cyclePickerSlot?: ReactNode;
|
|
1116
|
+
};
|
|
1117
|
+
type PaywallProps = {
|
|
1118
|
+
copy: PaywallCopy;
|
|
1119
|
+
themeClasses?: PaywallThemeClasses;
|
|
1120
|
+
slots?: PaywallSlots;
|
|
1121
|
+
/** Called immediately before checkout dispatches. Use for opening CPF modal etc. */
|
|
1122
|
+
onBeforeCheckout?: (method: CheckoutMethod, cycle: Cycle) => void | Promise<void>;
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Composed top-level paywall component. Apps wrap it in their `PaywallOffer.tsx`
|
|
1127
|
+
* (or `Offer.tsx`) and pass copy + themeClasses + slots. Logic + telemetry live
|
|
1128
|
+
* here. To customize layout entirely, drop down to the primitives.
|
|
1129
|
+
*/
|
|
1130
|
+
declare function Paywall({ copy, themeClasses, slots, onBeforeCheckout, }: PaywallProps): react_jsx_runtime.JSX.Element;
|
|
1131
|
+
|
|
1132
|
+
type PaywallMethodTabsProps = {
|
|
1133
|
+
methods: readonly CheckoutMethod[];
|
|
1134
|
+
selected: CheckoutMethod;
|
|
1135
|
+
onSelect: (m: CheckoutMethod) => void;
|
|
1136
|
+
labels: Partial<Record<CheckoutMethod, string>>;
|
|
1137
|
+
className?: string;
|
|
1138
|
+
tabClassName?: string;
|
|
1139
|
+
tabActiveClassName?: string;
|
|
1140
|
+
};
|
|
1141
|
+
declare function PaywallMethodTabs({ methods, selected, onSelect, labels, className, tabClassName, tabActiveClassName, }: PaywallMethodTabsProps): react_jsx_runtime.JSX.Element | null;
|
|
1142
|
+
|
|
1143
|
+
type PaywallMethodContentProps = {
|
|
1144
|
+
method: CheckoutMethod;
|
|
1145
|
+
copy: Pick<PaywallCopy, 'pix' | 'card'> & {
|
|
1146
|
+
cardConsumedTrial?: PaywallCopy['cardConsumedTrial'];
|
|
1147
|
+
};
|
|
1148
|
+
hasConsumedTrial?: boolean;
|
|
1149
|
+
className?: string;
|
|
1150
|
+
rowClassName?: string;
|
|
1151
|
+
};
|
|
1152
|
+
declare function PaywallMethodContent({ method, copy, hasConsumedTrial, className, rowClassName, }: PaywallMethodContentProps): react_jsx_runtime.JSX.Element;
|
|
1153
|
+
|
|
1154
|
+
type CycleLabels = {
|
|
1155
|
+
annualLabel: string;
|
|
1156
|
+
monthlyLabel: string;
|
|
1157
|
+
annualSuffix: string;
|
|
1158
|
+
monthlySuffix: string;
|
|
1159
|
+
};
|
|
1160
|
+
type PaywallCyclePickerProps = {
|
|
1161
|
+
cycles: readonly Cycle[];
|
|
1162
|
+
selected: Cycle;
|
|
1163
|
+
onSelect: (c: Cycle) => void;
|
|
1164
|
+
/** Raw price for the cycle (used to show full annual/monthly). */
|
|
1165
|
+
priceCentsByCycle: Record<Cycle, number>;
|
|
1166
|
+
/** Anchor strikethrough price, null when not set. */
|
|
1167
|
+
anchorCentsByCycle: Record<Cycle, number | null>;
|
|
1168
|
+
/** Monthly-equiv for YEARLY (priceCents / 12). Same as priceCentsByCycle for MONTHLY. */
|
|
1169
|
+
monthlyEquivByCycle: Record<Cycle, number>;
|
|
1170
|
+
labels: CycleLabels;
|
|
1171
|
+
className?: string;
|
|
1172
|
+
cardClassName?: string;
|
|
1173
|
+
cardSelectedClassName?: string;
|
|
1174
|
+
anchorClassName?: string;
|
|
1175
|
+
};
|
|
1176
|
+
declare function PaywallCyclePicker({ cycles, selected, onSelect, priceCentsByCycle, anchorCentsByCycle, monthlyEquivByCycle, labels, className, cardClassName, cardSelectedClassName, anchorClassName, }: PaywallCyclePickerProps): react_jsx_runtime.JSX.Element | null;
|
|
1177
|
+
|
|
1178
|
+
type PaywallCtaProps = {
|
|
1179
|
+
ctaLabel: string;
|
|
1180
|
+
loadingLabel?: string;
|
|
1181
|
+
switchHint?: string;
|
|
1182
|
+
trustLine: string;
|
|
1183
|
+
onClick: () => void;
|
|
1184
|
+
disabled?: boolean;
|
|
1185
|
+
loading?: boolean;
|
|
1186
|
+
className?: string;
|
|
1187
|
+
buttonClassName?: string;
|
|
1188
|
+
switchHintClassName?: string;
|
|
1189
|
+
trustClassName?: string;
|
|
1190
|
+
};
|
|
1191
|
+
declare function PaywallCta({ ctaLabel, loadingLabel, switchHint, trustLine, onClick, disabled, loading, className, buttonClassName, switchHintClassName, trustClassName, }: PaywallCtaProps): react_jsx_runtime.JSX.Element;
|
|
1192
|
+
|
|
1193
|
+
export { type AndroidBrowser, type AppConfig, AppConfigProvider, AppConfigSchema, AppRoot, type AppRootProps, type AppRootSlots, type AuthFlowConfig, type AuthFormError, type AuthFormErrorCode, type AuthScreenProps, type CheckoutMethod, type Cycle, type CycleLabels, DeepLinkHandler, type DeepLinks, DevSkipOnboardingFab, EmptyState, ErrorBoundary, type I18nConfig, I18nProvider, type I18nProviderProps, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LanguageSwitcher, type LanguageSwitcherProps, LoadingState, type OnboardingConfig, OnboardingFlow, type OnboardingFlowProps, type OnboardingStep, type OnboardingStepCtx, type OnboardingStepDef, type PaymentMethod, PaymentReturnHandler, Paywall, type PaywallConfig, type PaywallCopy, PaywallCta, type PaywallCtaProps, PaywallCyclePicker, type PaywallCyclePickerProps, PaywallMethodContent, type PaywallMethodContentProps, type PaywallMethodCopy, PaywallMethodTabs, type PaywallMethodTabsProps, type PaywallProps, type PaywallSlots, type PaywallThemeClasses, type PersistedKey, PersistenceRegistry, type PersistenceRegistryProps, type PixPending, type Platform, PreAuthShell, type PreAuthShellProps, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, RouteBoundary, type RouteBoundaryProps, type SkipDefaults, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, asaasErrorMessage, computeAnchorCents, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, discountPercent, formatBRL, isDevToolsEnabled, monthlyFromYearly, parseAppConfig, shouldBlockInstall, shouldShowPermanentOption, skipOnboarding, useAppConfig, useAuth, useAuthPrimitives, useFeature, useForgotForm, useInstallPrompt, useLoginForm, useOnboardingStep, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, ComponentType, Component } from 'react';
|
|
4
4
|
import * as _hook_sdk_sdk from '@hook-sdk/sdk';
|
|
5
|
-
import { CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { HookContextValue, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
6
|
export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
|
|
@@ -19,7 +19,27 @@ type PaywallConfig = {
|
|
|
19
19
|
mode: 'free';
|
|
20
20
|
} | {
|
|
21
21
|
mode: 'trial' | 'pay_first';
|
|
22
|
+
/**
|
|
23
|
+
* Legacy flat trial — fallback when per-method fields aren't set.
|
|
24
|
+
* Read via `trialDaysForMethod(method)` helper on `usePaywallState`.
|
|
25
|
+
*/
|
|
22
26
|
trialDays?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Per-method trial overrides (ADR-022 Amendment 2026-05-12 + G154).
|
|
29
|
+
* - `trialDaysCard` — days of free trial on the card method.
|
|
30
|
+
* Default 7 in the backend, but apps can opt down to 0 if they want
|
|
31
|
+
* PIX-style "pay now" semantics on cards too.
|
|
32
|
+
* - `trialDaysPix` — days of free trial on PIX Auto. Default 0 because
|
|
33
|
+
* Asaas does not implement BCB Jornada 2 (consent-only authorization).
|
|
34
|
+
* Any value > 0 forces the R$ 0,01 capture workaround — see G123-G127.
|
|
35
|
+
*/
|
|
36
|
+
trialDaysCard?: number;
|
|
37
|
+
trialDaysPix?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Which method the paywall preselects. Reflects creator audience,
|
|
40
|
+
* not Hook bias. `null`/`undefined` = no preselection — user picks.
|
|
41
|
+
*/
|
|
42
|
+
defaultMethod?: CheckoutMethod | null;
|
|
23
43
|
cycles: Cycle[];
|
|
24
44
|
prices: {
|
|
25
45
|
monthlyCents: number;
|
|
@@ -120,6 +140,33 @@ interface AuthScreenProps {
|
|
|
120
140
|
onNavigate?: (target: 'login' | 'signup' | 'forgot' | 'reset') => void;
|
|
121
141
|
}
|
|
122
142
|
|
|
143
|
+
interface SkipDefaults {
|
|
144
|
+
/**
|
|
145
|
+
* Final flag the host app's ProtectedRoute reads. If unset here, the helper
|
|
146
|
+
* forces it to `true` after merging defaults.
|
|
147
|
+
*/
|
|
148
|
+
onboarding_completed?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Free-form per-app fields (userName, mainGoal, faixa, kids[], etc.). The
|
|
151
|
+
* helper merges this object verbatim into `appData.set('onboarding_data', …)`.
|
|
152
|
+
*/
|
|
153
|
+
[field: string]: unknown;
|
|
154
|
+
/**
|
|
155
|
+
* Optional per-app seed callback. Use to insert anything that lives outside
|
|
156
|
+
* `onboarding_data` (e.g. seed first workout in `hook.db.collection('workouts')`).
|
|
157
|
+
* Awaited after `appData.set` and before the hard reload.
|
|
158
|
+
*/
|
|
159
|
+
__seed?: (hook: HookContextValue) => Promise<void>;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Programmatic skip helper. Exposed for advanced consumers / tests; the FAB
|
|
163
|
+
* just calls this on confirm.
|
|
164
|
+
*/
|
|
165
|
+
declare function skipOnboarding(hook: HookContextValue, defaults: SkipDefaults, appSlug: string): Promise<void>;
|
|
166
|
+
declare function DevSkipOnboardingFab({ defaults }: {
|
|
167
|
+
defaults: SkipDefaults;
|
|
168
|
+
}): react_jsx_runtime.JSX.Element;
|
|
169
|
+
|
|
123
170
|
declare function PaymentReturnHandler({ children }: {
|
|
124
171
|
children: ReactNode;
|
|
125
172
|
}): react_jsx_runtime.JSX.Element;
|
|
@@ -145,10 +192,37 @@ type AppRootProps = AppRootSlots & {
|
|
|
145
192
|
testRouter?: 'memory';
|
|
146
193
|
/** Test-only: initial entries for MemoryRouter. */
|
|
147
194
|
testInitialEntries?: string[];
|
|
195
|
+
/**
|
|
196
|
+
* Staging-only dev tools. When this prop is set AND
|
|
197
|
+
* `VITE_HOOK_DEV_TOOLS=1` AND the hostname is staging/localhost, AppRoot
|
|
198
|
+
* mounts a floating "skip onboarding" button that pre-fills
|
|
199
|
+
* `appData.onboarding_data` with the supplied defaults and lands the user
|
|
200
|
+
* on `/app/<slug>/`. Tree-shaken from prod builds via the build-time env
|
|
201
|
+
* replacement (see `dev/env.ts`).
|
|
202
|
+
*/
|
|
203
|
+
devSkipOnboarding?: {
|
|
204
|
+
defaults: SkipDefaults;
|
|
205
|
+
};
|
|
148
206
|
};
|
|
149
207
|
|
|
150
208
|
declare function AppRoot(props: AppRootProps): react_jsx_runtime.JSX.Element;
|
|
151
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Build-time + runtime gate for dev-only tools (e.g. <DevSkipOnboardingFab>).
|
|
212
|
+
*
|
|
213
|
+
* Two independent signals must agree:
|
|
214
|
+
*
|
|
215
|
+
* 1. Build-time: `import.meta.env.VITE_HOOK_DEV_TOOLS === '1'`. Vite folds
|
|
216
|
+
* this constant at build time — when unset, the entire dev tree is
|
|
217
|
+
* tree-shaken from the prod bundle (sideEffects:false in package.json
|
|
218
|
+
* makes that effective). Set `VITE_HOOK_DEV_TOOLS=1` only in
|
|
219
|
+
* `.env.staging` builds.
|
|
220
|
+
*
|
|
221
|
+
* 2. Runtime: hostname must be staging-ish. Belt-and-suspenders against
|
|
222
|
+
* a misconfigured build that somehow ships the FAB to prod.
|
|
223
|
+
*/
|
|
224
|
+
declare function isDevToolsEnabled(): boolean;
|
|
225
|
+
|
|
152
226
|
interface PushPromptTexts {
|
|
153
227
|
cta: string;
|
|
154
228
|
declineCta: string;
|
|
@@ -464,6 +538,16 @@ declare function usePaywallState(): {
|
|
|
464
538
|
methods: readonly CheckoutMethod$1[];
|
|
465
539
|
selectedMethod: CheckoutMethod$1;
|
|
466
540
|
setSelectedMethod: react.Dispatch<react.SetStateAction<CheckoutMethod$1>>;
|
|
541
|
+
hasConsumedTrial: boolean;
|
|
542
|
+
currentPriceCents: number;
|
|
543
|
+
currentMonthlyEquivCents: number;
|
|
544
|
+
anchorPriceCents: number | null;
|
|
545
|
+
selectMethod: (next: CheckoutMethod$1) => void;
|
|
546
|
+
selectCycle: (next: CheckoutCycle) => void;
|
|
547
|
+
isFree: boolean;
|
|
548
|
+
trialDaysForMethod: (method: CheckoutMethod$1) => number;
|
|
549
|
+
trialDaysCard: number;
|
|
550
|
+
trialDaysPix: number;
|
|
467
551
|
cpfState: CpfState;
|
|
468
552
|
cardState: CardFormStateWithSetter;
|
|
469
553
|
submit: () => Promise<CheckoutResult | undefined>;
|
|
@@ -882,6 +966,13 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
882
966
|
pay_first: "pay_first";
|
|
883
967
|
}>;
|
|
884
968
|
trialDays: z.ZodOptional<z.ZodNumber>;
|
|
969
|
+
trialDaysCard: z.ZodOptional<z.ZodNumber>;
|
|
970
|
+
trialDaysPix: z.ZodOptional<z.ZodNumber>;
|
|
971
|
+
defaultMethod: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
972
|
+
card: "card";
|
|
973
|
+
"pix-auto": "pix-auto";
|
|
974
|
+
"pix-once": "pix-once";
|
|
975
|
+
}>>>;
|
|
885
976
|
cycles: z.ZodArray<z.ZodEnum<{
|
|
886
977
|
MONTHLY: "MONTHLY";
|
|
887
978
|
YEARLY: "YEARLY";
|
|
@@ -950,4 +1041,153 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
950
1041
|
}, z.core.$strict>;
|
|
951
1042
|
declare function parseAppConfig(input: unknown): AppConfig;
|
|
952
1043
|
|
|
953
|
-
|
|
1044
|
+
type PaywallMethodCopy = {
|
|
1045
|
+
/** Tab label, e.g. "⚡ PIX" or "💳 Cartão" */
|
|
1046
|
+
tabLabel: string;
|
|
1047
|
+
/** 3 body rows under the active tab. Use literal strings; price/days come from the hook. */
|
|
1048
|
+
bodyRows: [string, string, string];
|
|
1049
|
+
/** CTA label template. `{price}` and `{days}` placeholders are interpolated. */
|
|
1050
|
+
ctaTemplate: string;
|
|
1051
|
+
/** Switch-hint copy shown under the CTA when the OTHER tab is available. */
|
|
1052
|
+
switchHint: string;
|
|
1053
|
+
};
|
|
1054
|
+
type PaywallCopy = {
|
|
1055
|
+
headline: string;
|
|
1056
|
+
features: readonly string[];
|
|
1057
|
+
socialProof?: string;
|
|
1058
|
+
/** Trust line above sticky CTA. Shared across methods. */
|
|
1059
|
+
trustLine: string;
|
|
1060
|
+
pix: PaywallMethodCopy;
|
|
1061
|
+
card: PaywallMethodCopy;
|
|
1062
|
+
/** Used when `usePaywallState().hasConsumedTrial === true`. Card tab body + CTA shift. */
|
|
1063
|
+
cardConsumedTrial: Omit<PaywallMethodCopy, 'tabLabel' | 'switchHint'>;
|
|
1064
|
+
cycle: {
|
|
1065
|
+
annualLabel: string;
|
|
1066
|
+
monthlyLabel: string;
|
|
1067
|
+
/** Append after price on annual card, e.g. "/mês · anual" */
|
|
1068
|
+
annualSuffix: string;
|
|
1069
|
+
/** Append after price on monthly card, e.g. "/mês" */
|
|
1070
|
+
monthlySuffix: string;
|
|
1071
|
+
};
|
|
1072
|
+
/** Optional override for the "free" CTA when `paywall.mode === 'free'`. */
|
|
1073
|
+
freeCta?: string;
|
|
1074
|
+
};
|
|
1075
|
+
type PaywallThemeClasses = {
|
|
1076
|
+
/** Container wrapper. Default: empty. */
|
|
1077
|
+
container?: string;
|
|
1078
|
+
/** Headline `<h1>`. */
|
|
1079
|
+
headline?: string;
|
|
1080
|
+
/** Feature row `<li>`. */
|
|
1081
|
+
feature?: string;
|
|
1082
|
+
/** Cycle picker card. */
|
|
1083
|
+
cycleCard?: string;
|
|
1084
|
+
/** Cycle picker card when selected. */
|
|
1085
|
+
cycleCardSelected?: string;
|
|
1086
|
+
/** Method tabs wrapper (pill background). */
|
|
1087
|
+
tabs?: string;
|
|
1088
|
+
/** Individual tab. */
|
|
1089
|
+
tab?: string;
|
|
1090
|
+
/** Individual tab when active. */
|
|
1091
|
+
tabActive?: string;
|
|
1092
|
+
/** Tab body card. */
|
|
1093
|
+
tabContent?: string;
|
|
1094
|
+
/** Tab body row (one row per icon+text). */
|
|
1095
|
+
tabContentRow?: string;
|
|
1096
|
+
/** CTA button — applied when method=pix-auto. */
|
|
1097
|
+
ctaPix?: string;
|
|
1098
|
+
/** CTA button — applied when method=card. */
|
|
1099
|
+
ctaCard?: string;
|
|
1100
|
+
/** Switch-hint line under CTA. */
|
|
1101
|
+
switchHint?: string;
|
|
1102
|
+
/** Trust line under switch hint. */
|
|
1103
|
+
trustLine?: string;
|
|
1104
|
+
/** Social proof badge. */
|
|
1105
|
+
socialProof?: string;
|
|
1106
|
+
/** Anchor strikethrough price. */
|
|
1107
|
+
anchorPrice?: string;
|
|
1108
|
+
};
|
|
1109
|
+
type PaywallSlots = {
|
|
1110
|
+
/** Above headline (hero image, brand visual). */
|
|
1111
|
+
heroSlot?: ReactNode;
|
|
1112
|
+
/** Below tab content, above CTA (e.g. testimonials). */
|
|
1113
|
+
beforeCtaSlot?: ReactNode;
|
|
1114
|
+
/** Replace the cycle picker entirely. */
|
|
1115
|
+
cyclePickerSlot?: ReactNode;
|
|
1116
|
+
};
|
|
1117
|
+
type PaywallProps = {
|
|
1118
|
+
copy: PaywallCopy;
|
|
1119
|
+
themeClasses?: PaywallThemeClasses;
|
|
1120
|
+
slots?: PaywallSlots;
|
|
1121
|
+
/** Called immediately before checkout dispatches. Use for opening CPF modal etc. */
|
|
1122
|
+
onBeforeCheckout?: (method: CheckoutMethod, cycle: Cycle) => void | Promise<void>;
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Composed top-level paywall component. Apps wrap it in their `PaywallOffer.tsx`
|
|
1127
|
+
* (or `Offer.tsx`) and pass copy + themeClasses + slots. Logic + telemetry live
|
|
1128
|
+
* here. To customize layout entirely, drop down to the primitives.
|
|
1129
|
+
*/
|
|
1130
|
+
declare function Paywall({ copy, themeClasses, slots, onBeforeCheckout, }: PaywallProps): react_jsx_runtime.JSX.Element;
|
|
1131
|
+
|
|
1132
|
+
type PaywallMethodTabsProps = {
|
|
1133
|
+
methods: readonly CheckoutMethod[];
|
|
1134
|
+
selected: CheckoutMethod;
|
|
1135
|
+
onSelect: (m: CheckoutMethod) => void;
|
|
1136
|
+
labels: Partial<Record<CheckoutMethod, string>>;
|
|
1137
|
+
className?: string;
|
|
1138
|
+
tabClassName?: string;
|
|
1139
|
+
tabActiveClassName?: string;
|
|
1140
|
+
};
|
|
1141
|
+
declare function PaywallMethodTabs({ methods, selected, onSelect, labels, className, tabClassName, tabActiveClassName, }: PaywallMethodTabsProps): react_jsx_runtime.JSX.Element | null;
|
|
1142
|
+
|
|
1143
|
+
type PaywallMethodContentProps = {
|
|
1144
|
+
method: CheckoutMethod;
|
|
1145
|
+
copy: Pick<PaywallCopy, 'pix' | 'card'> & {
|
|
1146
|
+
cardConsumedTrial?: PaywallCopy['cardConsumedTrial'];
|
|
1147
|
+
};
|
|
1148
|
+
hasConsumedTrial?: boolean;
|
|
1149
|
+
className?: string;
|
|
1150
|
+
rowClassName?: string;
|
|
1151
|
+
};
|
|
1152
|
+
declare function PaywallMethodContent({ method, copy, hasConsumedTrial, className, rowClassName, }: PaywallMethodContentProps): react_jsx_runtime.JSX.Element;
|
|
1153
|
+
|
|
1154
|
+
type CycleLabels = {
|
|
1155
|
+
annualLabel: string;
|
|
1156
|
+
monthlyLabel: string;
|
|
1157
|
+
annualSuffix: string;
|
|
1158
|
+
monthlySuffix: string;
|
|
1159
|
+
};
|
|
1160
|
+
type PaywallCyclePickerProps = {
|
|
1161
|
+
cycles: readonly Cycle[];
|
|
1162
|
+
selected: Cycle;
|
|
1163
|
+
onSelect: (c: Cycle) => void;
|
|
1164
|
+
/** Raw price for the cycle (used to show full annual/monthly). */
|
|
1165
|
+
priceCentsByCycle: Record<Cycle, number>;
|
|
1166
|
+
/** Anchor strikethrough price, null when not set. */
|
|
1167
|
+
anchorCentsByCycle: Record<Cycle, number | null>;
|
|
1168
|
+
/** Monthly-equiv for YEARLY (priceCents / 12). Same as priceCentsByCycle for MONTHLY. */
|
|
1169
|
+
monthlyEquivByCycle: Record<Cycle, number>;
|
|
1170
|
+
labels: CycleLabels;
|
|
1171
|
+
className?: string;
|
|
1172
|
+
cardClassName?: string;
|
|
1173
|
+
cardSelectedClassName?: string;
|
|
1174
|
+
anchorClassName?: string;
|
|
1175
|
+
};
|
|
1176
|
+
declare function PaywallCyclePicker({ cycles, selected, onSelect, priceCentsByCycle, anchorCentsByCycle, monthlyEquivByCycle, labels, className, cardClassName, cardSelectedClassName, anchorClassName, }: PaywallCyclePickerProps): react_jsx_runtime.JSX.Element | null;
|
|
1177
|
+
|
|
1178
|
+
type PaywallCtaProps = {
|
|
1179
|
+
ctaLabel: string;
|
|
1180
|
+
loadingLabel?: string;
|
|
1181
|
+
switchHint?: string;
|
|
1182
|
+
trustLine: string;
|
|
1183
|
+
onClick: () => void;
|
|
1184
|
+
disabled?: boolean;
|
|
1185
|
+
loading?: boolean;
|
|
1186
|
+
className?: string;
|
|
1187
|
+
buttonClassName?: string;
|
|
1188
|
+
switchHintClassName?: string;
|
|
1189
|
+
trustClassName?: string;
|
|
1190
|
+
};
|
|
1191
|
+
declare function PaywallCta({ ctaLabel, loadingLabel, switchHint, trustLine, onClick, disabled, loading, className, buttonClassName, switchHintClassName, trustClassName, }: PaywallCtaProps): react_jsx_runtime.JSX.Element;
|
|
1192
|
+
|
|
1193
|
+
export { type AndroidBrowser, type AppConfig, AppConfigProvider, AppConfigSchema, AppRoot, type AppRootProps, type AppRootSlots, type AuthFlowConfig, type AuthFormError, type AuthFormErrorCode, type AuthScreenProps, type CheckoutMethod, type Cycle, type CycleLabels, DeepLinkHandler, type DeepLinks, DevSkipOnboardingFab, EmptyState, ErrorBoundary, type I18nConfig, I18nProvider, type I18nProviderProps, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LanguageSwitcher, type LanguageSwitcherProps, LoadingState, type OnboardingConfig, OnboardingFlow, type OnboardingFlowProps, type OnboardingStep, type OnboardingStepCtx, type OnboardingStepDef, type PaymentMethod, PaymentReturnHandler, Paywall, type PaywallConfig, type PaywallCopy, PaywallCta, type PaywallCtaProps, PaywallCyclePicker, type PaywallCyclePickerProps, PaywallMethodContent, type PaywallMethodContentProps, type PaywallMethodCopy, PaywallMethodTabs, type PaywallMethodTabsProps, type PaywallProps, type PaywallSlots, type PaywallThemeClasses, type PersistedKey, PersistenceRegistry, type PersistenceRegistryProps, type PixPending, type Platform, PreAuthShell, type PreAuthShellProps, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, RouteBoundary, type RouteBoundaryProps, type SkipDefaults, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, asaasErrorMessage, computeAnchorCents, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, discountPercent, formatBRL, isDevToolsEnabled, monthlyFromYearly, parseAppConfig, shouldBlockInstall, shouldShowPermanentOption, skipOnboarding, useAppConfig, useAuth, useAuthPrimitives, useFeature, useForgotForm, useInstallPrompt, useLoginForm, useOnboardingStep, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|