@hook-sdk/template 0.5.0 → 0.7.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 +96 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -7
- package/dist/index.d.ts +117 -7
- package/dist/index.js +90 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { ReactNode, ComponentType, Component } from 'react';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import * as _hook_sdk_sdk from '@hook-sdk/sdk';
|
|
5
|
-
import { ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
|
+
export { PlanInfo, PlanState } from '@hook-sdk/sdk';
|
|
6
7
|
|
|
7
8
|
declare const AppConfigSchema: z.ZodObject<{
|
|
8
9
|
$schema: z.ZodOptional<z.ZodString>;
|
|
@@ -266,14 +267,29 @@ interface UseResetFormResult {
|
|
|
266
267
|
declare function useResetForm(): UseResetFormResult;
|
|
267
268
|
|
|
268
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
|
+
}
|
|
269
277
|
/**
|
|
270
278
|
* Hook headless pro Paywall. Expõe status atual da subscription + ação
|
|
271
|
-
* `checkout(cpf
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
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`.
|
|
275
290
|
*
|
|
276
|
-
*
|
|
291
|
+
* Subscription real é atualizada via webhook (`PAYMENT_RECEIVED` ou
|
|
292
|
+
* `PIX_AUTOMATIC_RECURRING_AUTHORIZATION_ACTIVATED`).
|
|
277
293
|
*/
|
|
278
294
|
declare function usePaywallState(): {
|
|
279
295
|
status: SubscriptionStatus;
|
|
@@ -282,12 +298,106 @@ declare function usePaywallState(): {
|
|
|
282
298
|
checkout: (args: {
|
|
283
299
|
cpf: string;
|
|
284
300
|
cycle?: "MONTHLY" | "YEARLY";
|
|
301
|
+
method?: PaymentMethod;
|
|
285
302
|
}) => Promise<void>;
|
|
286
303
|
cancel: () => Promise<void>;
|
|
287
304
|
opening: boolean;
|
|
288
305
|
error: Error | null;
|
|
306
|
+
pixPending: PixPending | null;
|
|
307
|
+
dismissPix: () => void;
|
|
289
308
|
};
|
|
290
309
|
|
|
310
|
+
/**
|
|
311
|
+
* Thin wrapper sobre `useHook().plan`. Existe pra apps importarem "tudo
|
|
312
|
+
* que precisam" via `@hook-sdk/template` sem mudar de package pra cada
|
|
313
|
+
* primitive, e pra manter espaço pra evoluir a API (ex: expor campos
|
|
314
|
+
* derivados como `monthlyEquivalent()`) sem mexer no SDK.
|
|
315
|
+
*
|
|
316
|
+
* Retorna o PlanState bruto. Use junto com helpers de `@hook-sdk/template`:
|
|
317
|
+
*
|
|
318
|
+
* const { data, initialLoadComplete } = usePlan();
|
|
319
|
+
* if (!initialLoadComplete) return <Skeleton />;
|
|
320
|
+
* if (!data) return null;
|
|
321
|
+
* return <span>{formatBRL(data.priceCents)}</span>;
|
|
322
|
+
*/
|
|
323
|
+
declare function usePlan(): PlanState;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Helpers de formatação de preço pro Hook.
|
|
327
|
+
*
|
|
328
|
+
* Preço vive no banco em CENTAVOS (int), sempre. Apps que renderizam preço
|
|
329
|
+
* leem do hook `usePlan()` e passam por `formatBRL(cents)` — nunca formatam
|
|
330
|
+
* inline. Isso evita os dois patterns errados que já vimos em conversões
|
|
331
|
+
* Lovable→Hook: (a) strings hardcoded "R$ 19,90" no JSX, (b) divisões ad-hoc
|
|
332
|
+
* por 100 + `toFixed(2)` que ignoram locale.
|
|
333
|
+
*
|
|
334
|
+
* Ver G72 em .claude/skills/lovable-to-hook/catalog/known-gotchas.md.
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* Formata centavos como BRL no locale pt-BR. Aceita null pra conveniência
|
|
338
|
+
* (callers que lidam com `yearlyPriceCents: number | null`).
|
|
339
|
+
*
|
|
340
|
+
* Examples:
|
|
341
|
+
* formatBRL(1990) → "R$ 19,90"
|
|
342
|
+
* formatBRL(4999) → "R$ 49,99"
|
|
343
|
+
* formatBRL(23988) → "R$ 239,88"
|
|
344
|
+
* formatBRL(0) → "R$ 0,00"
|
|
345
|
+
* formatBRL(null) → ""
|
|
346
|
+
*/
|
|
347
|
+
declare function formatBRL(cents: number | null | undefined): string;
|
|
348
|
+
/**
|
|
349
|
+
* Deriva "preço mensal" a partir do preço anual (em centavos). Round half-up
|
|
350
|
+
* pra evitar R$ 19,899... → R$ 19,89 quando o usuário esperava R$ 19,90.
|
|
351
|
+
*
|
|
352
|
+
* Não assume que o creator configurou yearlyPriceCents "redondo": se ele
|
|
353
|
+
* setou 23988 (= R$ 239,88), 23988/12 = 1999 (= R$ 19,99). Se setou 23880
|
|
354
|
+
* (= R$ 238,80), 23880/12 = 1990 (= R$ 19,90).
|
|
355
|
+
*
|
|
356
|
+
* Example (papomaterno):
|
|
357
|
+
* monthlyFromYearly(23988) = 1999 → formatBRL = "R$ 19,99"
|
|
358
|
+
* monthlyFromYearly(23880) = 1990 → formatBRL = "R$ 19,90"
|
|
359
|
+
*/
|
|
360
|
+
declare function monthlyFromYearly(yearlyCents: number | null | undefined): number;
|
|
361
|
+
/**
|
|
362
|
+
* Deriva "preço por dia" (365 dias) a partir do anual, em centavos. Útil
|
|
363
|
+
* pra copy tipo "apenas R$ 0,66 por dia, menos que um café".
|
|
364
|
+
*
|
|
365
|
+
* Example:
|
|
366
|
+
* dailyFromYearly(23988) = 66 → formatBRL = "R$ 0,66"
|
|
367
|
+
*/
|
|
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;
|
|
400
|
+
|
|
291
401
|
/**
|
|
292
402
|
* Escape hatch pra screens FORA do fluxo de auth (ex: settings/trocar-senha).
|
|
293
403
|
* Pra LoginScreen/SignupScreen/ForgotScreen custom, use useLoginForm/useSignupForm/useForgotForm.
|
|
@@ -493,4 +603,4 @@ declare function shouldBlockInstall(state: InstallState, now?: number): boolean;
|
|
|
493
603
|
*/
|
|
494
604
|
declare function shouldShowPermanentOption(state: InstallState): boolean;
|
|
495
605
|
|
|
496
|
-
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, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, 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 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
|
@@ -2,7 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { ReactNode, ComponentType, Component } from 'react';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import * as _hook_sdk_sdk from '@hook-sdk/sdk';
|
|
5
|
-
import { ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
|
+
export { PlanInfo, PlanState } from '@hook-sdk/sdk';
|
|
6
7
|
|
|
7
8
|
declare const AppConfigSchema: z.ZodObject<{
|
|
8
9
|
$schema: z.ZodOptional<z.ZodString>;
|
|
@@ -266,14 +267,29 @@ interface UseResetFormResult {
|
|
|
266
267
|
declare function useResetForm(): UseResetFormResult;
|
|
267
268
|
|
|
268
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
|
+
}
|
|
269
277
|
/**
|
|
270
278
|
* Hook headless pro Paywall. Expõe status atual da subscription + ação
|
|
271
|
-
* `checkout(cpf
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
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`.
|
|
275
290
|
*
|
|
276
|
-
*
|
|
291
|
+
* Subscription real é atualizada via webhook (`PAYMENT_RECEIVED` ou
|
|
292
|
+
* `PIX_AUTOMATIC_RECURRING_AUTHORIZATION_ACTIVATED`).
|
|
277
293
|
*/
|
|
278
294
|
declare function usePaywallState(): {
|
|
279
295
|
status: SubscriptionStatus;
|
|
@@ -282,12 +298,106 @@ declare function usePaywallState(): {
|
|
|
282
298
|
checkout: (args: {
|
|
283
299
|
cpf: string;
|
|
284
300
|
cycle?: "MONTHLY" | "YEARLY";
|
|
301
|
+
method?: PaymentMethod;
|
|
285
302
|
}) => Promise<void>;
|
|
286
303
|
cancel: () => Promise<void>;
|
|
287
304
|
opening: boolean;
|
|
288
305
|
error: Error | null;
|
|
306
|
+
pixPending: PixPending | null;
|
|
307
|
+
dismissPix: () => void;
|
|
289
308
|
};
|
|
290
309
|
|
|
310
|
+
/**
|
|
311
|
+
* Thin wrapper sobre `useHook().plan`. Existe pra apps importarem "tudo
|
|
312
|
+
* que precisam" via `@hook-sdk/template` sem mudar de package pra cada
|
|
313
|
+
* primitive, e pra manter espaço pra evoluir a API (ex: expor campos
|
|
314
|
+
* derivados como `monthlyEquivalent()`) sem mexer no SDK.
|
|
315
|
+
*
|
|
316
|
+
* Retorna o PlanState bruto. Use junto com helpers de `@hook-sdk/template`:
|
|
317
|
+
*
|
|
318
|
+
* const { data, initialLoadComplete } = usePlan();
|
|
319
|
+
* if (!initialLoadComplete) return <Skeleton />;
|
|
320
|
+
* if (!data) return null;
|
|
321
|
+
* return <span>{formatBRL(data.priceCents)}</span>;
|
|
322
|
+
*/
|
|
323
|
+
declare function usePlan(): PlanState;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Helpers de formatação de preço pro Hook.
|
|
327
|
+
*
|
|
328
|
+
* Preço vive no banco em CENTAVOS (int), sempre. Apps que renderizam preço
|
|
329
|
+
* leem do hook `usePlan()` e passam por `formatBRL(cents)` — nunca formatam
|
|
330
|
+
* inline. Isso evita os dois patterns errados que já vimos em conversões
|
|
331
|
+
* Lovable→Hook: (a) strings hardcoded "R$ 19,90" no JSX, (b) divisões ad-hoc
|
|
332
|
+
* por 100 + `toFixed(2)` que ignoram locale.
|
|
333
|
+
*
|
|
334
|
+
* Ver G72 em .claude/skills/lovable-to-hook/catalog/known-gotchas.md.
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* Formata centavos como BRL no locale pt-BR. Aceita null pra conveniência
|
|
338
|
+
* (callers que lidam com `yearlyPriceCents: number | null`).
|
|
339
|
+
*
|
|
340
|
+
* Examples:
|
|
341
|
+
* formatBRL(1990) → "R$ 19,90"
|
|
342
|
+
* formatBRL(4999) → "R$ 49,99"
|
|
343
|
+
* formatBRL(23988) → "R$ 239,88"
|
|
344
|
+
* formatBRL(0) → "R$ 0,00"
|
|
345
|
+
* formatBRL(null) → ""
|
|
346
|
+
*/
|
|
347
|
+
declare function formatBRL(cents: number | null | undefined): string;
|
|
348
|
+
/**
|
|
349
|
+
* Deriva "preço mensal" a partir do preço anual (em centavos). Round half-up
|
|
350
|
+
* pra evitar R$ 19,899... → R$ 19,89 quando o usuário esperava R$ 19,90.
|
|
351
|
+
*
|
|
352
|
+
* Não assume que o creator configurou yearlyPriceCents "redondo": se ele
|
|
353
|
+
* setou 23988 (= R$ 239,88), 23988/12 = 1999 (= R$ 19,99). Se setou 23880
|
|
354
|
+
* (= R$ 238,80), 23880/12 = 1990 (= R$ 19,90).
|
|
355
|
+
*
|
|
356
|
+
* Example (papomaterno):
|
|
357
|
+
* monthlyFromYearly(23988) = 1999 → formatBRL = "R$ 19,99"
|
|
358
|
+
* monthlyFromYearly(23880) = 1990 → formatBRL = "R$ 19,90"
|
|
359
|
+
*/
|
|
360
|
+
declare function monthlyFromYearly(yearlyCents: number | null | undefined): number;
|
|
361
|
+
/**
|
|
362
|
+
* Deriva "preço por dia" (365 dias) a partir do anual, em centavos. Útil
|
|
363
|
+
* pra copy tipo "apenas R$ 0,66 por dia, menos que um café".
|
|
364
|
+
*
|
|
365
|
+
* Example:
|
|
366
|
+
* dailyFromYearly(23988) = 66 → formatBRL = "R$ 0,66"
|
|
367
|
+
*/
|
|
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;
|
|
400
|
+
|
|
291
401
|
/**
|
|
292
402
|
* Escape hatch pra screens FORA do fluxo de auth (ex: settings/trocar-senha).
|
|
293
403
|
* Pra LoginScreen/SignupScreen/ForgotScreen custom, use useLoginForm/useSignupForm/useForgotForm.
|
|
@@ -493,4 +603,4 @@ declare function shouldBlockInstall(state: InstallState, now?: number): boolean;
|
|
|
493
603
|
*/
|
|
494
604
|
declare function shouldShowPermanentOption(state: InstallState): boolean;
|
|
495
605
|
|
|
496
|
-
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, detectAndroidBrowser, detectIOSBrowser, detectInAppApp, detectPlatform, detectStandalone, shouldBlockInstall, shouldShowPermanentOption, useAuth, useAuthPrimitives, useForgotForm, useInstallPrompt, useLoginForm, usePaywallState, 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 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
|
|
@@ -2327,12 +2364,47 @@ function EmptyState({ title, description, action }) {
|
|
|
2327
2364
|
] });
|
|
2328
2365
|
}
|
|
2329
2366
|
|
|
2367
|
+
// src/hooks/usePlan.ts
|
|
2368
|
+
import { useHook as useHook10 } from "@hook-sdk/sdk";
|
|
2369
|
+
function usePlan() {
|
|
2370
|
+
const { plan } = useHook10();
|
|
2371
|
+
return plan;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
// src/utils/price.ts
|
|
2375
|
+
function formatBRL(cents) {
|
|
2376
|
+
if (cents === null || cents === void 0) return "";
|
|
2377
|
+
const reais = cents / 100;
|
|
2378
|
+
return new Intl.NumberFormat("pt-BR", {
|
|
2379
|
+
style: "currency",
|
|
2380
|
+
currency: "BRL"
|
|
2381
|
+
}).format(reais);
|
|
2382
|
+
}
|
|
2383
|
+
function monthlyFromYearly(yearlyCents) {
|
|
2384
|
+
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2385
|
+
return Math.round(yearlyCents / 12);
|
|
2386
|
+
}
|
|
2387
|
+
function dailyFromYearly(yearlyCents) {
|
|
2388
|
+
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2389
|
+
return Math.round(yearlyCents / 365);
|
|
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
|
+
}
|
|
2401
|
+
|
|
2330
2402
|
// src/hooks/useAuthPrimitives.ts
|
|
2331
2403
|
import { useEffect as useEffect9 } from "react";
|
|
2332
|
-
import { useHook as
|
|
2404
|
+
import { useHook as useHook11 } from "@hook-sdk/sdk";
|
|
2333
2405
|
var warned = false;
|
|
2334
2406
|
function useAuthPrimitives() {
|
|
2335
|
-
const { auth } =
|
|
2407
|
+
const { auth } = useHook11();
|
|
2336
2408
|
useEffect9(() => {
|
|
2337
2409
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
2338
2410
|
warned = true;
|
|
@@ -2355,9 +2427,9 @@ function useAuthPrimitives() {
|
|
|
2355
2427
|
}
|
|
2356
2428
|
|
|
2357
2429
|
// src/hooks/useSubscription.ts
|
|
2358
|
-
import { useHook as
|
|
2430
|
+
import { useHook as useHook12 } from "@hook-sdk/sdk";
|
|
2359
2431
|
function useSubscription() {
|
|
2360
|
-
const { subscription } =
|
|
2432
|
+
const { subscription } = useHook12();
|
|
2361
2433
|
return {
|
|
2362
2434
|
status: subscription.status()
|
|
2363
2435
|
};
|
|
@@ -2365,9 +2437,9 @@ function useSubscription() {
|
|
|
2365
2437
|
|
|
2366
2438
|
// src/hooks/useReminders.ts
|
|
2367
2439
|
import { useCallback as useCallback9, useEffect as useEffect10, useState as useState13 } from "react";
|
|
2368
|
-
import { useHook as
|
|
2440
|
+
import { useHook as useHook13 } from "@hook-sdk/sdk";
|
|
2369
2441
|
function useReminders() {
|
|
2370
|
-
const { push } =
|
|
2442
|
+
const { push } = useHook13();
|
|
2371
2443
|
const r = push.reminders;
|
|
2372
2444
|
const [reminders, setReminders] = useState13([]);
|
|
2373
2445
|
const [loading, setLoading] = useState13(true);
|
|
@@ -2429,11 +2501,16 @@ export {
|
|
|
2429
2501
|
InstallSplash,
|
|
2430
2502
|
LoadingState,
|
|
2431
2503
|
PushPrompt2 as PushPrompt,
|
|
2504
|
+
computeAnchorCents,
|
|
2505
|
+
dailyFromYearly,
|
|
2432
2506
|
detectAndroidBrowser,
|
|
2433
2507
|
detectIOSBrowser,
|
|
2434
2508
|
detectInAppApp,
|
|
2435
2509
|
detectPlatform,
|
|
2436
2510
|
detectStandalone,
|
|
2511
|
+
discountPercent,
|
|
2512
|
+
formatBRL,
|
|
2513
|
+
monthlyFromYearly,
|
|
2437
2514
|
shouldBlockInstall,
|
|
2438
2515
|
shouldShowPermanentOption,
|
|
2439
2516
|
useAuth,
|
|
@@ -2442,6 +2519,7 @@ export {
|
|
|
2442
2519
|
useInstallPrompt,
|
|
2443
2520
|
useLoginForm,
|
|
2444
2521
|
usePaywallState,
|
|
2522
|
+
usePlan,
|
|
2445
2523
|
usePush,
|
|
2446
2524
|
useReminders,
|
|
2447
2525
|
useResetForm,
|