@hook-sdk/template 0.28.10 → 0.29.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 +26 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +27 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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 { HookContextValue, SubscribeAnonymousResult, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutCardData, CheckoutHolderInfo, CheckoutResult, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { HookContextValue, VideoConfig, SubscribeAnonymousResult, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutCardData, CheckoutHolderInfo, CheckoutResult, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
6
|
export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
|
|
@@ -205,6 +205,14 @@ type AppRootSlots = {
|
|
|
205
205
|
type AppRootProps = AppRootSlots & {
|
|
206
206
|
config: AppConfig;
|
|
207
207
|
children?: ReactNode;
|
|
208
|
+
/**
|
|
209
|
+
* P-Video — per-videoId config map. Bundles that use <HookVideo> pass
|
|
210
|
+
* `videos.videos` from `import videos from './videos.json'` (file is
|
|
211
|
+
* synced from `hook/creators/<slug>/videos.json` by the build step).
|
|
212
|
+
* Omit when the app has no VSL screens — empty map is fine.
|
|
213
|
+
* Spec: docs/superpowers/specs/2026-05-16-hook-video-player-design.md
|
|
214
|
+
*/
|
|
215
|
+
videos?: Record<string, VideoConfig>;
|
|
208
216
|
/** Test-only: skip BrowserRouter (which fights jsdom's document.location). */
|
|
209
217
|
testRouter?: 'memory';
|
|
210
218
|
/** Test-only: initial entries for MemoryRouter. */
|
|
@@ -524,6 +532,7 @@ interface UseCheckoutFormResult {
|
|
|
524
532
|
cpfError: string | null;
|
|
525
533
|
postalCodeError: string | null;
|
|
526
534
|
addressNumberError: string | null;
|
|
535
|
+
cardExpiryError: string | null;
|
|
527
536
|
markNameTouched: () => void;
|
|
528
537
|
markEmailTouched: () => void;
|
|
529
538
|
markEmailConfirmTouched: () => void;
|
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 { HookContextValue, SubscribeAnonymousResult, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutCardData, CheckoutHolderInfo, CheckoutResult, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
5
|
+
import { HookContextValue, VideoConfig, SubscribeAnonymousResult, CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutCardData, CheckoutHolderInfo, CheckoutResult, PlanState, ReminderSlot } from '@hook-sdk/sdk';
|
|
6
6
|
export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
|
|
@@ -205,6 +205,14 @@ type AppRootSlots = {
|
|
|
205
205
|
type AppRootProps = AppRootSlots & {
|
|
206
206
|
config: AppConfig;
|
|
207
207
|
children?: ReactNode;
|
|
208
|
+
/**
|
|
209
|
+
* P-Video — per-videoId config map. Bundles that use <HookVideo> pass
|
|
210
|
+
* `videos.videos` from `import videos from './videos.json'` (file is
|
|
211
|
+
* synced from `hook/creators/<slug>/videos.json` by the build step).
|
|
212
|
+
* Omit when the app has no VSL screens — empty map is fine.
|
|
213
|
+
* Spec: docs/superpowers/specs/2026-05-16-hook-video-player-design.md
|
|
214
|
+
*/
|
|
215
|
+
videos?: Record<string, VideoConfig>;
|
|
208
216
|
/** Test-only: skip BrowserRouter (which fights jsdom's document.location). */
|
|
209
217
|
testRouter?: 'memory';
|
|
210
218
|
/** Test-only: initial entries for MemoryRouter. */
|
|
@@ -524,6 +532,7 @@ interface UseCheckoutFormResult {
|
|
|
524
532
|
cpfError: string | null;
|
|
525
533
|
postalCodeError: string | null;
|
|
526
534
|
addressNumberError: string | null;
|
|
535
|
+
cardExpiryError: string | null;
|
|
527
536
|
markNameTouched: () => void;
|
|
528
537
|
markEmailTouched: () => void;
|
|
529
538
|
markEmailConfirmTouched: () => void;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/AppRoot.tsx
|
|
2
2
|
import { useMemo as useMemo3 } from "react";
|
|
3
3
|
import { BrowserRouter, MemoryRouter, Navigate, Route, Routes } from "react-router-dom";
|
|
4
|
-
import { useHook as useHook8 } from "@hook-sdk/sdk";
|
|
4
|
+
import { useHook as useHook8, VideoProvider } from "@hook-sdk/sdk";
|
|
5
5
|
|
|
6
6
|
// src/config/AppConfigContext.tsx
|
|
7
7
|
import { createContext, useContext } from "react";
|
|
@@ -2504,6 +2504,7 @@ function AppRoot(props) {
|
|
|
2504
2504
|
const {
|
|
2505
2505
|
config: rawConfig,
|
|
2506
2506
|
children,
|
|
2507
|
+
videos,
|
|
2507
2508
|
testRouter,
|
|
2508
2509
|
testInitialEntries,
|
|
2509
2510
|
Login,
|
|
@@ -2573,7 +2574,7 @@ function AppRoot(props) {
|
|
|
2573
2574
|
position === "pre-auth" ? /* @__PURE__ */ jsx23(InstallGate, { position: "pre-auth", children: authGated }) : authGated,
|
|
2574
2575
|
isDevToolsEnabled() && devSkipOnboarding ? /* @__PURE__ */ jsx23(DevSkipOnboardingFab, { defaults: devSkipOnboarding.defaults }) : null
|
|
2575
2576
|
] });
|
|
2576
|
-
return /* @__PURE__ */ jsx23(ErrorBoundary, { children: /* @__PURE__ */ jsx23(AppConfigProvider, { config, children: /* @__PURE__ */ jsx23(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ jsx23(ThemeProvider, { children: /* @__PURE__ */ jsx23(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ jsx23(
|
|
2577
|
+
return /* @__PURE__ */ jsx23(ErrorBoundary, { children: /* @__PURE__ */ jsx23(AppConfigProvider, { config, children: /* @__PURE__ */ jsx23(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ jsx23(ThemeProvider, { children: /* @__PURE__ */ jsx23(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ jsx23(VideoProvider, { videos: videos ?? {}, children: config.i18n ? /* @__PURE__ */ jsx23(
|
|
2577
2578
|
I18nProvider,
|
|
2578
2579
|
{
|
|
2579
2580
|
defaultLocale: config.i18n.defaultLocale,
|
|
@@ -2581,7 +2582,7 @@ function AppRoot(props) {
|
|
|
2581
2582
|
resources: config.i18n.resources,
|
|
2582
2583
|
children: routedTree
|
|
2583
2584
|
}
|
|
2584
|
-
) : routedTree }) }) }) }) });
|
|
2585
|
+
) : routedTree }) }) }) }) }) });
|
|
2585
2586
|
}
|
|
2586
2587
|
function AuthGated({
|
|
2587
2588
|
children,
|
|
@@ -2966,9 +2967,26 @@ function useCheckoutForm(hookArgs) {
|
|
|
2966
2967
|
const cpfError = touchedCpf || formSubmitAttempted ? validateCpf : null;
|
|
2967
2968
|
const postalCodeError = touchedPostalCode || formSubmitAttempted ? validatePostalCode : null;
|
|
2968
2969
|
const addressNumberError = touchedAddressNumber || formSubmitAttempted ? validateAddressNumber : null;
|
|
2970
|
+
const cardExpiryError = useMemo4(() => {
|
|
2971
|
+
if (method !== "card") return null;
|
|
2972
|
+
const mm = card.expiryMonth.replace(/\D/g, "");
|
|
2973
|
+
const yy = card.expiryYear.replace(/\D/g, "");
|
|
2974
|
+
if (mm.length < 2 || yy.length < 2) return null;
|
|
2975
|
+
const monthNum = parseInt(mm, 10);
|
|
2976
|
+
if (monthNum < 1 || monthNum > 12) return "M\xEAs inv\xE1lido (use 01-12).";
|
|
2977
|
+
const yearNum = 2e3 + parseInt(yy, 10);
|
|
2978
|
+
const now = /* @__PURE__ */ new Date();
|
|
2979
|
+
const currentMonth = now.getMonth() + 1;
|
|
2980
|
+
const currentYear = now.getFullYear();
|
|
2981
|
+
if (yearNum < currentYear || yearNum === currentYear && monthNum < currentMonth) {
|
|
2982
|
+
return "Cart\xE3o vencido.";
|
|
2983
|
+
}
|
|
2984
|
+
if (yearNum > currentYear + 20) return "Ano muito distante.";
|
|
2985
|
+
return null;
|
|
2986
|
+
}, [method, card.expiryMonth, card.expiryYear]);
|
|
2969
2987
|
const phoneOk = method === "pix-auto" ? phone === "" || PHONE_RE.test(phone) : PHONE_RE.test(phone);
|
|
2970
2988
|
const cepGateOk = !hookArgs.collectCep || method !== "card" || postalCode.replace(/\D/g, "").length === 8 && addressNumber.trim().length > 0;
|
|
2971
|
-
const canSubmit = name.trim().length >= 2 && EMAIL_RE.test(email) && (emailConfirm === "" || emailConfirm === email) && phoneOk && validateCpf === null && cpf.replace(/\D/g, "").length === 11 && emailStatus !== "exists" && !submitting && cepGateOk && (method !== "card" || card.number.length >= 12 && card.ccv.length >= 3 && card.expiryMonth.length >= 1 && card.expiryYear.length >= 2 && card.holderName.length >= 1);
|
|
2989
|
+
const canSubmit = name.trim().length >= 2 && EMAIL_RE.test(email) && (emailConfirm === "" || emailConfirm === email) && phoneOk && validateCpf === null && cpf.replace(/\D/g, "").length === 11 && emailStatus !== "exists" && !submitting && cepGateOk && (method !== "card" || card.number.length >= 12 && card.ccv.length >= 3 && card.expiryMonth.length >= 1 && card.expiryYear.length >= 2 && card.holderName.length >= 1 && cardExpiryError === null);
|
|
2972
2990
|
const submit = useCallback6(async () => {
|
|
2973
2991
|
setFormSubmitAttempted(true);
|
|
2974
2992
|
setError(null);
|
|
@@ -3061,6 +3079,7 @@ function useCheckoutForm(hookArgs) {
|
|
|
3061
3079
|
cpfError,
|
|
3062
3080
|
postalCodeError,
|
|
3063
3081
|
addressNumberError,
|
|
3082
|
+
cardExpiryError,
|
|
3064
3083
|
markNameTouched: () => setTouchedName(true),
|
|
3065
3084
|
markEmailTouched: () => setTouchedEmail(true),
|
|
3066
3085
|
markEmailConfirmTouched: () => setTouchedEmailConfirm(true),
|
|
@@ -4028,11 +4047,11 @@ function CheckoutPageDefault() {
|
|
|
4028
4047
|
value: form.email,
|
|
4029
4048
|
onChange: form.setEmail,
|
|
4030
4049
|
onBlur: form.markEmailTouched,
|
|
4031
|
-
error: form.emailError,
|
|
4050
|
+
error: form.emailError ?? (form.emailStatus === "exists" ? "Este email j\xE1 tem conta. Faz login pra continuar." : null),
|
|
4032
4051
|
valid: form.emailStatus === "available"
|
|
4033
4052
|
}
|
|
4034
4053
|
),
|
|
4035
|
-
!form.emailError && /* @__PURE__ */ jsx48(FieldHint, { children: form.emailStatus === "checking" ? "Verificando\u2026" : form.emailStatus === "available" ? "\u2713 Dispon\xEDvel" : "Voc\xEA vai usar este email para entrar no app" })
|
|
4054
|
+
!form.emailError && form.emailStatus !== "exists" && /* @__PURE__ */ jsx48(FieldHint, { children: form.emailStatus === "checking" ? "Verificando\u2026" : form.emailStatus === "available" ? "\u2713 Dispon\xEDvel" : "Voc\xEA vai usar este email para entrar no app" })
|
|
4036
4055
|
] }),
|
|
4037
4056
|
/* @__PURE__ */ jsxs29("div", { children: [
|
|
4038
4057
|
/* @__PURE__ */ jsx48(FieldLabel, { children: "Nome completo" }),
|
|
@@ -4183,7 +4202,8 @@ function CheckoutPageDefault() {
|
|
|
4183
4202
|
autoComplete: "cc-exp",
|
|
4184
4203
|
placeholder: "MM/AA",
|
|
4185
4204
|
value: expiryMmAa,
|
|
4186
|
-
onChange: (v) => setExpiryMmAa(formatExpiryMmAa(v))
|
|
4205
|
+
onChange: (v) => setExpiryMmAa(formatExpiryMmAa(v)),
|
|
4206
|
+
error: form.cardExpiryError
|
|
4187
4207
|
}
|
|
4188
4208
|
)
|
|
4189
4209
|
] }),
|