@hook-sdk/template 0.6.0 → 0.7.1
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 +57 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -6
- package/dist/index.d.ts +55 -6
- package/dist/index.js +55 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -267,14 +267,29 @@ interface UseResetFormResult {
|
|
|
267
267
|
declare function useResetForm(): UseResetFormResult;
|
|
268
268
|
|
|
269
269
|
type SubscriptionStatus = 'active' | 'trialing' | 'expired' | 'canceled' | 'past_due' | 'pending' | 'none';
|
|
270
|
+
type PaymentMethod = 'card' | 'pix-auto' | 'pix-once';
|
|
271
|
+
interface PixPending {
|
|
272
|
+
method: 'pix-auto' | 'pix-once';
|
|
273
|
+
qrCodePayload: string | null;
|
|
274
|
+
qrCodeBase64: string | null;
|
|
275
|
+
expiresAt: string | null;
|
|
276
|
+
}
|
|
270
277
|
/**
|
|
271
278
|
* Hook headless pro Paywall. Expõe status atual da subscription + ação
|
|
272
|
-
* `checkout(cpf
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
279
|
+
* `checkout({cpf, cycle, method})` com 3 métodos:
|
|
280
|
+
*
|
|
281
|
+
* - **card** (default): cria subscription Asaas recorrente, redireciona pro
|
|
282
|
+
* invoiceUrl hosted. Após pagar, Asaas redireciona de volta e webhook
|
|
283
|
+
* atualiza DB.
|
|
284
|
+
* - **pix-auto**: Pix Automático Jornada 3 BACEN. User escaneia QR 1x no app
|
|
285
|
+
* do banco, autoriza débito recorrente. Retorna QR via `pixPending`
|
|
286
|
+
* (hook fica populado até user confirmar no banco).
|
|
287
|
+
* - **pix-once**: Pix avulso. User paga QR único, ganha 1 ciclo. Sem
|
|
288
|
+
* recorrência automática — renova voltando no app. Retorna QR via
|
|
289
|
+
* `pixPending`.
|
|
276
290
|
*
|
|
277
|
-
*
|
|
291
|
+
* Subscription real é atualizada via webhook (`PAYMENT_RECEIVED` ou
|
|
292
|
+
* `PIX_AUTOMATIC_RECURRING_AUTHORIZATION_ACTIVATED`).
|
|
278
293
|
*/
|
|
279
294
|
declare function usePaywallState(): {
|
|
280
295
|
status: SubscriptionStatus;
|
|
@@ -283,10 +298,13 @@ declare function usePaywallState(): {
|
|
|
283
298
|
checkout: (args: {
|
|
284
299
|
cpf: string;
|
|
285
300
|
cycle?: "MONTHLY" | "YEARLY";
|
|
301
|
+
method?: PaymentMethod;
|
|
286
302
|
}) => Promise<void>;
|
|
287
303
|
cancel: () => Promise<void>;
|
|
288
304
|
opening: boolean;
|
|
289
305
|
error: Error | null;
|
|
306
|
+
pixPending: PixPending | null;
|
|
307
|
+
dismissPix: () => void;
|
|
290
308
|
};
|
|
291
309
|
|
|
292
310
|
/**
|
|
@@ -348,6 +366,37 @@ declare function monthlyFromYearly(yearlyCents: number | null | undefined): numb
|
|
|
348
366
|
* dailyFromYearly(23988) = 66 → formatBRL = "R$ 0,66"
|
|
349
367
|
*/
|
|
350
368
|
declare function dailyFromYearly(yearlyCents: number | null | undefined): number;
|
|
369
|
+
/**
|
|
370
|
+
* Deriva o preço-ancoragem (valor "cheio" riscado) como múltiplo do preço
|
|
371
|
+
* real. Serve pra ancoragem psicológica em telas de paywall: mostra um valor
|
|
372
|
+
* maior riscado antes do preço real pra o usuário sentir desconto.
|
|
373
|
+
*
|
|
374
|
+
* Com `anchorMultiplier` no `paywall_config`, o creator mantém só o preço
|
|
375
|
+
* real no DB; a ancoragem acompanha automaticamente se o preço muda.
|
|
376
|
+
*
|
|
377
|
+
* Retorna `null` quando o multiplier não é utilizável (falta, ≤ 1, NaN,
|
|
378
|
+
* Infinity). Caller deve cair no fallback (valor absoluto em
|
|
379
|
+
* `paywall_config.anchorPriceCents`) ou pular a renderização da ancoragem.
|
|
380
|
+
*
|
|
381
|
+
* Examples:
|
|
382
|
+
* computeAnchorCents(1999, 2.5) = 4998
|
|
383
|
+
* computeAnchorCents(1999, undefined) = null
|
|
384
|
+
* computeAnchorCents(1999, 1) = null // 1× não ancora nada
|
|
385
|
+
* computeAnchorCents(1999, 0) = null
|
|
386
|
+
* computeAnchorCents(1999, NaN) = null
|
|
387
|
+
*/
|
|
388
|
+
declare function computeAnchorCents(baseCents: number, multiplier: number | null | undefined): number | null;
|
|
389
|
+
/**
|
|
390
|
+
* Percentual de desconto (anchor → real), arredondado pra baixo pra nunca
|
|
391
|
+
* overstate. Retorna 0 quando anchor ≤ real (sem desconto a mostrar).
|
|
392
|
+
*
|
|
393
|
+
* Examples:
|
|
394
|
+
* discountPercent(4998, 1999) = 60 // (4998-1999)/4998 = 0.60...
|
|
395
|
+
* discountPercent(3998, 1999) = 50
|
|
396
|
+
* discountPercent(1000, 2000) = 0 // real > anchor
|
|
397
|
+
* discountPercent(2000, 2000) = 0
|
|
398
|
+
*/
|
|
399
|
+
declare function discountPercent(anchorCents: number, realCents: number): number;
|
|
351
400
|
|
|
352
401
|
/**
|
|
353
402
|
* Escape hatch pra screens FORA do fluxo de auth (ex: settings/trocar-senha).
|
|
@@ -554,4 +603,4 @@ declare function shouldBlockInstall(state: InstallState, now?: number): boolean;
|
|
|
554
603
|
*/
|
|
555
604
|
declare function shouldShowPermanentOption(state: InstallState): boolean;
|
|
556
605
|
|
|
557
|
-
export { type AndroidBrowser, AppRoot, type AppRootProps, type AuthFormError, type AuthFormErrorCode, type AuthScreen, type AuthScreenProps, DefaultForgotScreen, DefaultLoginScreen, DefaultPaywall, DefaultResetScreen, DefaultSignupScreen, EmptyState, ErrorBoundary, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LoadingState, type Platform, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, formatBRL, monthlyFromYearly, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|
|
606
|
+
export { type AndroidBrowser, AppRoot, type AppRootProps, type AuthFormError, type AuthFormErrorCode, type AuthScreen, type AuthScreenProps, DefaultForgotScreen, DefaultLoginScreen, DefaultPaywall, DefaultResetScreen, DefaultSignupScreen, EmptyState, ErrorBoundary, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LoadingState, type PaymentMethod, type PixPending, type Platform, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, computeAnchorCents, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, discountPercent, formatBRL, monthlyFromYearly, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|
package/dist/index.d.ts
CHANGED
|
@@ -267,14 +267,29 @@ interface UseResetFormResult {
|
|
|
267
267
|
declare function useResetForm(): UseResetFormResult;
|
|
268
268
|
|
|
269
269
|
type SubscriptionStatus = 'active' | 'trialing' | 'expired' | 'canceled' | 'past_due' | 'pending' | 'none';
|
|
270
|
+
type PaymentMethod = 'card' | 'pix-auto' | 'pix-once';
|
|
271
|
+
interface PixPending {
|
|
272
|
+
method: 'pix-auto' | 'pix-once';
|
|
273
|
+
qrCodePayload: string | null;
|
|
274
|
+
qrCodeBase64: string | null;
|
|
275
|
+
expiresAt: string | null;
|
|
276
|
+
}
|
|
270
277
|
/**
|
|
271
278
|
* Hook headless pro Paywall. Expõe status atual da subscription + ação
|
|
272
|
-
* `checkout(cpf
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
279
|
+
* `checkout({cpf, cycle, method})` com 3 métodos:
|
|
280
|
+
*
|
|
281
|
+
* - **card** (default): cria subscription Asaas recorrente, redireciona pro
|
|
282
|
+
* invoiceUrl hosted. Após pagar, Asaas redireciona de volta e webhook
|
|
283
|
+
* atualiza DB.
|
|
284
|
+
* - **pix-auto**: Pix Automático Jornada 3 BACEN. User escaneia QR 1x no app
|
|
285
|
+
* do banco, autoriza débito recorrente. Retorna QR via `pixPending`
|
|
286
|
+
* (hook fica populado até user confirmar no banco).
|
|
287
|
+
* - **pix-once**: Pix avulso. User paga QR único, ganha 1 ciclo. Sem
|
|
288
|
+
* recorrência automática — renova voltando no app. Retorna QR via
|
|
289
|
+
* `pixPending`.
|
|
276
290
|
*
|
|
277
|
-
*
|
|
291
|
+
* Subscription real é atualizada via webhook (`PAYMENT_RECEIVED` ou
|
|
292
|
+
* `PIX_AUTOMATIC_RECURRING_AUTHORIZATION_ACTIVATED`).
|
|
278
293
|
*/
|
|
279
294
|
declare function usePaywallState(): {
|
|
280
295
|
status: SubscriptionStatus;
|
|
@@ -283,10 +298,13 @@ declare function usePaywallState(): {
|
|
|
283
298
|
checkout: (args: {
|
|
284
299
|
cpf: string;
|
|
285
300
|
cycle?: "MONTHLY" | "YEARLY";
|
|
301
|
+
method?: PaymentMethod;
|
|
286
302
|
}) => Promise<void>;
|
|
287
303
|
cancel: () => Promise<void>;
|
|
288
304
|
opening: boolean;
|
|
289
305
|
error: Error | null;
|
|
306
|
+
pixPending: PixPending | null;
|
|
307
|
+
dismissPix: () => void;
|
|
290
308
|
};
|
|
291
309
|
|
|
292
310
|
/**
|
|
@@ -348,6 +366,37 @@ declare function monthlyFromYearly(yearlyCents: number | null | undefined): numb
|
|
|
348
366
|
* dailyFromYearly(23988) = 66 → formatBRL = "R$ 0,66"
|
|
349
367
|
*/
|
|
350
368
|
declare function dailyFromYearly(yearlyCents: number | null | undefined): number;
|
|
369
|
+
/**
|
|
370
|
+
* Deriva o preço-ancoragem (valor "cheio" riscado) como múltiplo do preço
|
|
371
|
+
* real. Serve pra ancoragem psicológica em telas de paywall: mostra um valor
|
|
372
|
+
* maior riscado antes do preço real pra o usuário sentir desconto.
|
|
373
|
+
*
|
|
374
|
+
* Com `anchorMultiplier` no `paywall_config`, o creator mantém só o preço
|
|
375
|
+
* real no DB; a ancoragem acompanha automaticamente se o preço muda.
|
|
376
|
+
*
|
|
377
|
+
* Retorna `null` quando o multiplier não é utilizável (falta, ≤ 1, NaN,
|
|
378
|
+
* Infinity). Caller deve cair no fallback (valor absoluto em
|
|
379
|
+
* `paywall_config.anchorPriceCents`) ou pular a renderização da ancoragem.
|
|
380
|
+
*
|
|
381
|
+
* Examples:
|
|
382
|
+
* computeAnchorCents(1999, 2.5) = 4998
|
|
383
|
+
* computeAnchorCents(1999, undefined) = null
|
|
384
|
+
* computeAnchorCents(1999, 1) = null // 1× não ancora nada
|
|
385
|
+
* computeAnchorCents(1999, 0) = null
|
|
386
|
+
* computeAnchorCents(1999, NaN) = null
|
|
387
|
+
*/
|
|
388
|
+
declare function computeAnchorCents(baseCents: number, multiplier: number | null | undefined): number | null;
|
|
389
|
+
/**
|
|
390
|
+
* Percentual de desconto (anchor → real), arredondado pra baixo pra nunca
|
|
391
|
+
* overstate. Retorna 0 quando anchor ≤ real (sem desconto a mostrar).
|
|
392
|
+
*
|
|
393
|
+
* Examples:
|
|
394
|
+
* discountPercent(4998, 1999) = 60 // (4998-1999)/4998 = 0.60...
|
|
395
|
+
* discountPercent(3998, 1999) = 50
|
|
396
|
+
* discountPercent(1000, 2000) = 0 // real > anchor
|
|
397
|
+
* discountPercent(2000, 2000) = 0
|
|
398
|
+
*/
|
|
399
|
+
declare function discountPercent(anchorCents: number, realCents: number): number;
|
|
351
400
|
|
|
352
401
|
/**
|
|
353
402
|
* Escape hatch pra screens FORA do fluxo de auth (ex: settings/trocar-senha).
|
|
@@ -554,4 +603,4 @@ declare function shouldBlockInstall(state: InstallState, now?: number): boolean;
|
|
|
554
603
|
*/
|
|
555
604
|
declare function shouldShowPermanentOption(state: InstallState): boolean;
|
|
556
605
|
|
|
557
|
-
export { type AndroidBrowser, AppRoot, type AppRootProps, type AuthFormError, type AuthFormErrorCode, type AuthScreen, type AuthScreenProps, DefaultForgotScreen, DefaultLoginScreen, DefaultPaywall, DefaultResetScreen, DefaultSignupScreen, EmptyState, ErrorBoundary, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LoadingState, type Platform, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, formatBRL, monthlyFromYearly, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|
|
606
|
+
export { type AndroidBrowser, AppRoot, type AppRootProps, type AuthFormError, type AuthFormErrorCode, type AuthScreen, type AuthScreenProps, DefaultForgotScreen, DefaultLoginScreen, DefaultPaywall, DefaultResetScreen, DefaultSignupScreen, EmptyState, ErrorBoundary, type IOSBrowser, type InAppApp, type InstallActions, InstallGate, InstallSplash, type InstallState, type InstallVariant, LoadingState, type PaymentMethod, type PixPending, type Platform, PushPrompt, type PushPromptProps, type PushPromptTexts, type PushUiState, type SubscriptionStatus, type ToastItem, type UseLoginFormResult, type UseResetFormResult, computeAnchorCents, dailyFromYearly, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, discountPercent, formatBRL, monthlyFromYearly, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, usePlan, usePush, useReminders, useResetForm, useSignupForm, useSubscription, useToast };
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,7 @@ function usePaywallState() {
|
|
|
98
98
|
const { subscription } = useHook2();
|
|
99
99
|
const [opening, setOpening] = useState2(false);
|
|
100
100
|
const [error, setError] = useState2(null);
|
|
101
|
+
const [pixPending, setPixPending] = useState2(null);
|
|
101
102
|
const status = subscription.status();
|
|
102
103
|
const daysLeftInTrial = subscription.daysLeftInTrial();
|
|
103
104
|
const initialLoadComplete = subscription.initialLoadComplete;
|
|
@@ -105,12 +106,37 @@ function usePaywallState() {
|
|
|
105
106
|
async (args) => {
|
|
106
107
|
setOpening(true);
|
|
107
108
|
setError(null);
|
|
109
|
+
setPixPending(null);
|
|
110
|
+
const method = args.method ?? "card";
|
|
111
|
+
const cycle = args.cycle ?? "MONTHLY";
|
|
108
112
|
try {
|
|
109
|
-
|
|
110
|
-
cpf: args.cpf,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
if (method === "card") {
|
|
114
|
+
const result = await subscription.checkoutCard({ cpf: args.cpf, cycle });
|
|
115
|
+
window.location.href = result.invoiceUrl;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (method === "pix-auto") {
|
|
119
|
+
const result = await subscription.checkoutPixAuto({ cpf: args.cpf, cycle });
|
|
120
|
+
setPixPending({
|
|
121
|
+
method: "pix-auto",
|
|
122
|
+
qrCodePayload: result.qrCodePayload,
|
|
123
|
+
qrCodeBase64: result.qrCodeBase64,
|
|
124
|
+
expiresAt: null
|
|
125
|
+
});
|
|
126
|
+
setOpening(false);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (method === "pix-once") {
|
|
130
|
+
const result = await subscription.checkoutPixOnce({ cpf: args.cpf, cycle });
|
|
131
|
+
setPixPending({
|
|
132
|
+
method: "pix-once",
|
|
133
|
+
qrCodePayload: result.qrCodePayload,
|
|
134
|
+
qrCodeBase64: result.qrCodeBase64,
|
|
135
|
+
expiresAt: result.expiresAt
|
|
136
|
+
});
|
|
137
|
+
setOpening(false);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
114
140
|
} catch (err) {
|
|
115
141
|
setError(err);
|
|
116
142
|
setOpening(false);
|
|
@@ -126,7 +152,18 @@ function usePaywallState() {
|
|
|
126
152
|
setError(err);
|
|
127
153
|
}
|
|
128
154
|
}, [subscription]);
|
|
129
|
-
|
|
155
|
+
const dismissPix = useCallback(() => setPixPending(null), []);
|
|
156
|
+
return {
|
|
157
|
+
status,
|
|
158
|
+
daysLeftInTrial,
|
|
159
|
+
initialLoadComplete,
|
|
160
|
+
checkout,
|
|
161
|
+
cancel,
|
|
162
|
+
opening,
|
|
163
|
+
error,
|
|
164
|
+
pixPending,
|
|
165
|
+
dismissPix
|
|
166
|
+
};
|
|
130
167
|
}
|
|
131
168
|
|
|
132
169
|
// src/internal/SubscriptionGate.tsx
|
|
@@ -2351,6 +2388,16 @@ function dailyFromYearly(yearlyCents) {
|
|
|
2351
2388
|
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2352
2389
|
return Math.round(yearlyCents / 365);
|
|
2353
2390
|
}
|
|
2391
|
+
function computeAnchorCents(baseCents, multiplier) {
|
|
2392
|
+
if (multiplier === null || multiplier === void 0) return null;
|
|
2393
|
+
if (!Number.isFinite(multiplier)) return null;
|
|
2394
|
+
if (multiplier <= 1) return null;
|
|
2395
|
+
return Math.round(baseCents * multiplier);
|
|
2396
|
+
}
|
|
2397
|
+
function discountPercent(anchorCents, realCents) {
|
|
2398
|
+
if (anchorCents <= realCents) return 0;
|
|
2399
|
+
return Math.floor((anchorCents - realCents) / anchorCents * 100);
|
|
2400
|
+
}
|
|
2354
2401
|
|
|
2355
2402
|
// src/hooks/useAuthPrimitives.ts
|
|
2356
2403
|
import { useEffect as useEffect9 } from "react";
|
|
@@ -2454,12 +2501,14 @@ export {
|
|
|
2454
2501
|
InstallSplash,
|
|
2455
2502
|
LoadingState,
|
|
2456
2503
|
PushPrompt2 as PushPrompt,
|
|
2504
|
+
computeAnchorCents,
|
|
2457
2505
|
dailyFromYearly,
|
|
2458
2506
|
detectAndroidBrowser,
|
|
2459
2507
|
detectIOSBrowser,
|
|
2460
2508
|
detectInAppApp,
|
|
2461
2509
|
detectPlatform,
|
|
2462
2510
|
detectStandalone,
|
|
2511
|
+
discountPercent,
|
|
2463
2512
|
formatBRL,
|
|
2464
2513
|
monthlyFromYearly,
|
|
2465
2514
|
shouldBlockInstall,
|