@hook-sdk/template 0.28.9 → 0.28.10
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 +85 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +85 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -61,6 +61,13 @@ type PaywallConfig = {
|
|
|
61
61
|
};
|
|
62
62
|
checkoutMethods: CheckoutMethod[];
|
|
63
63
|
requiresCpf: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* When true, CheckoutPageDefault coleta CEP + número do endereço (card-path)
|
|
66
|
+
* e envia ambos como `cardHolderInfo.postalCode`/`addressNumber`.
|
|
67
|
+
* Default false → ship placeholder `01001000`/`100` (legacy behavior).
|
|
68
|
+
* Apps que precisam de NF-e ou antifraude refinada devem ativar.
|
|
69
|
+
*/
|
|
70
|
+
collectCep?: boolean;
|
|
64
71
|
cancelWindowDays?: number;
|
|
65
72
|
errorMessages: 'default' | 'custom';
|
|
66
73
|
};
|
|
@@ -500,6 +507,10 @@ interface UseCheckoutFormResult {
|
|
|
500
507
|
setPhone: (v: string) => void;
|
|
501
508
|
cpf: string;
|
|
502
509
|
setCpf: (v: string) => void;
|
|
510
|
+
postalCode: string;
|
|
511
|
+
setPostalCode: (v: string) => void;
|
|
512
|
+
addressNumber: string;
|
|
513
|
+
setAddressNumber: (v: string) => void;
|
|
503
514
|
method: CheckoutFormMethod;
|
|
504
515
|
setMethod: (m: CheckoutFormMethod) => void;
|
|
505
516
|
cycle: CheckoutFormCycle;
|
|
@@ -511,11 +522,15 @@ interface UseCheckoutFormResult {
|
|
|
511
522
|
emailConfirmError: string | null;
|
|
512
523
|
phoneError: string | null;
|
|
513
524
|
cpfError: string | null;
|
|
525
|
+
postalCodeError: string | null;
|
|
526
|
+
addressNumberError: string | null;
|
|
514
527
|
markNameTouched: () => void;
|
|
515
528
|
markEmailTouched: () => void;
|
|
516
529
|
markEmailConfirmTouched: () => void;
|
|
517
530
|
markPhoneTouched: () => void;
|
|
518
531
|
markCpfTouched: () => void;
|
|
532
|
+
markPostalCodeTouched: () => void;
|
|
533
|
+
markAddressNumberTouched: () => void;
|
|
519
534
|
/**
|
|
520
535
|
* Result of the debounced server-side email-exists check, used to swap
|
|
521
536
|
* the CTA into "Email já cadastrado · Entrar" on the checkout form.
|
|
@@ -539,8 +554,15 @@ interface UseCheckoutFormResult {
|
|
|
539
554
|
interface UseCheckoutFormArgs {
|
|
540
555
|
defaultMethod: CheckoutFormMethod;
|
|
541
556
|
defaultCycle: CheckoutFormCycle;
|
|
557
|
+
/**
|
|
558
|
+
* Quando true, o submit envia postalCode + addressNumber reais coletados
|
|
559
|
+
* via setPostalCode/setAddressNumber. Quando false (default), envia
|
|
560
|
+
* placeholder `01001000`/`100`. CheckoutPageDefault liga via config
|
|
561
|
+
* `paywall.collectCep`.
|
|
562
|
+
*/
|
|
563
|
+
collectCep?: boolean;
|
|
542
564
|
}
|
|
543
|
-
declare function useCheckoutForm(
|
|
565
|
+
declare function useCheckoutForm(hookArgs: UseCheckoutFormArgs): UseCheckoutFormResult;
|
|
544
566
|
|
|
545
567
|
type SubscriptionStatus = 'active' | 'trialing' | 'expired' | 'canceled' | 'past_due' | 'pending' | 'none';
|
|
546
568
|
type PaymentMethod = CheckoutMethod$1;
|
|
@@ -1082,6 +1104,7 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
1082
1104
|
"pix-once": "pix-once";
|
|
1083
1105
|
}>>;
|
|
1084
1106
|
requiresCpf: z.ZodBoolean;
|
|
1107
|
+
collectCep: z.ZodOptional<z.ZodBoolean>;
|
|
1085
1108
|
cancelWindowDays: z.ZodOptional<z.ZodNumber>;
|
|
1086
1109
|
errorMessages: z.ZodEnum<{
|
|
1087
1110
|
default: "default";
|
package/dist/index.d.ts
CHANGED
|
@@ -61,6 +61,13 @@ type PaywallConfig = {
|
|
|
61
61
|
};
|
|
62
62
|
checkoutMethods: CheckoutMethod[];
|
|
63
63
|
requiresCpf: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* When true, CheckoutPageDefault coleta CEP + número do endereço (card-path)
|
|
66
|
+
* e envia ambos como `cardHolderInfo.postalCode`/`addressNumber`.
|
|
67
|
+
* Default false → ship placeholder `01001000`/`100` (legacy behavior).
|
|
68
|
+
* Apps que precisam de NF-e ou antifraude refinada devem ativar.
|
|
69
|
+
*/
|
|
70
|
+
collectCep?: boolean;
|
|
64
71
|
cancelWindowDays?: number;
|
|
65
72
|
errorMessages: 'default' | 'custom';
|
|
66
73
|
};
|
|
@@ -500,6 +507,10 @@ interface UseCheckoutFormResult {
|
|
|
500
507
|
setPhone: (v: string) => void;
|
|
501
508
|
cpf: string;
|
|
502
509
|
setCpf: (v: string) => void;
|
|
510
|
+
postalCode: string;
|
|
511
|
+
setPostalCode: (v: string) => void;
|
|
512
|
+
addressNumber: string;
|
|
513
|
+
setAddressNumber: (v: string) => void;
|
|
503
514
|
method: CheckoutFormMethod;
|
|
504
515
|
setMethod: (m: CheckoutFormMethod) => void;
|
|
505
516
|
cycle: CheckoutFormCycle;
|
|
@@ -511,11 +522,15 @@ interface UseCheckoutFormResult {
|
|
|
511
522
|
emailConfirmError: string | null;
|
|
512
523
|
phoneError: string | null;
|
|
513
524
|
cpfError: string | null;
|
|
525
|
+
postalCodeError: string | null;
|
|
526
|
+
addressNumberError: string | null;
|
|
514
527
|
markNameTouched: () => void;
|
|
515
528
|
markEmailTouched: () => void;
|
|
516
529
|
markEmailConfirmTouched: () => void;
|
|
517
530
|
markPhoneTouched: () => void;
|
|
518
531
|
markCpfTouched: () => void;
|
|
532
|
+
markPostalCodeTouched: () => void;
|
|
533
|
+
markAddressNumberTouched: () => void;
|
|
519
534
|
/**
|
|
520
535
|
* Result of the debounced server-side email-exists check, used to swap
|
|
521
536
|
* the CTA into "Email já cadastrado · Entrar" on the checkout form.
|
|
@@ -539,8 +554,15 @@ interface UseCheckoutFormResult {
|
|
|
539
554
|
interface UseCheckoutFormArgs {
|
|
540
555
|
defaultMethod: CheckoutFormMethod;
|
|
541
556
|
defaultCycle: CheckoutFormCycle;
|
|
557
|
+
/**
|
|
558
|
+
* Quando true, o submit envia postalCode + addressNumber reais coletados
|
|
559
|
+
* via setPostalCode/setAddressNumber. Quando false (default), envia
|
|
560
|
+
* placeholder `01001000`/`100`. CheckoutPageDefault liga via config
|
|
561
|
+
* `paywall.collectCep`.
|
|
562
|
+
*/
|
|
563
|
+
collectCep?: boolean;
|
|
542
564
|
}
|
|
543
|
-
declare function useCheckoutForm(
|
|
565
|
+
declare function useCheckoutForm(hookArgs: UseCheckoutFormArgs): UseCheckoutFormResult;
|
|
544
566
|
|
|
545
567
|
type SubscriptionStatus = 'active' | 'trialing' | 'expired' | 'canceled' | 'past_due' | 'pending' | 'none';
|
|
546
568
|
type PaymentMethod = CheckoutMethod$1;
|
|
@@ -1082,6 +1104,7 @@ declare const AppConfigSchema: z.ZodObject<{
|
|
|
1082
1104
|
"pix-once": "pix-once";
|
|
1083
1105
|
}>>;
|
|
1084
1106
|
requiresCpf: z.ZodBoolean;
|
|
1107
|
+
collectCep: z.ZodOptional<z.ZodBoolean>;
|
|
1085
1108
|
cancelWindowDays: z.ZodOptional<z.ZodNumber>;
|
|
1086
1109
|
errorMessages: z.ZodEnum<{
|
|
1087
1110
|
default: "default";
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,7 @@ var PaywallNonFreeSchema = z.object({
|
|
|
58
58
|
}).optional(),
|
|
59
59
|
checkoutMethods: z.array(z.enum(["card", "pix-auto", "pix-once"])).min(1),
|
|
60
60
|
requiresCpf: z.boolean(),
|
|
61
|
+
collectCep: z.boolean().optional(),
|
|
61
62
|
cancelWindowDays: z.number().int().nonnegative().optional(),
|
|
62
63
|
errorMessages: z.enum(["default", "custom"])
|
|
63
64
|
});
|
|
@@ -2864,15 +2865,17 @@ function mapSdkError(err) {
|
|
|
2864
2865
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2865
2866
|
var PHONE_RE = /^[0-9()+\-\s]{8,20}$/;
|
|
2866
2867
|
var CHECK_DEBOUNCE_MS = 400;
|
|
2867
|
-
function useCheckoutForm(
|
|
2868
|
+
function useCheckoutForm(hookArgs) {
|
|
2868
2869
|
const { auth } = useHook10();
|
|
2869
2870
|
const [name, setName] = useState9("");
|
|
2870
2871
|
const [email, setEmail] = useState9("");
|
|
2871
2872
|
const [emailConfirm, setEmailConfirm] = useState9("");
|
|
2872
2873
|
const [phone, setPhone] = useState9("");
|
|
2873
2874
|
const [cpf, setCpf] = useState9("");
|
|
2874
|
-
const [
|
|
2875
|
-
const [
|
|
2875
|
+
const [postalCode, setPostalCode] = useState9("");
|
|
2876
|
+
const [addressNumber, setAddressNumber] = useState9("");
|
|
2877
|
+
const [method, setMethod] = useState9(hookArgs.defaultMethod);
|
|
2878
|
+
const [cycle, setCycle] = useState9(hookArgs.defaultCycle);
|
|
2876
2879
|
const [card, setCardState] = useState9({
|
|
2877
2880
|
number: "",
|
|
2878
2881
|
expiryMonth: "",
|
|
@@ -2888,6 +2891,8 @@ function useCheckoutForm(args) {
|
|
|
2888
2891
|
const [touchedEmailConfirm, setTouchedEmailConfirm] = useState9(false);
|
|
2889
2892
|
const [touchedPhone, setTouchedPhone] = useState9(false);
|
|
2890
2893
|
const [touchedCpf, setTouchedCpf] = useState9(false);
|
|
2894
|
+
const [touchedPostalCode, setTouchedPostalCode] = useState9(false);
|
|
2895
|
+
const [touchedAddressNumber, setTouchedAddressNumber] = useState9(false);
|
|
2891
2896
|
const [formSubmitAttempted, setFormSubmitAttempted] = useState9(false);
|
|
2892
2897
|
const [submitting, setSubmitting] = useState9(false);
|
|
2893
2898
|
const [error, setError] = useState9(null);
|
|
@@ -2941,13 +2946,29 @@ function useCheckoutForm(args) {
|
|
|
2941
2946
|
const ok = mod11(digits, 9) === digits[9] && mod11(digits, 10) === digits[10];
|
|
2942
2947
|
return ok ? null : "CPF inv\xE1lido.";
|
|
2943
2948
|
}, [cpf]);
|
|
2949
|
+
const validatePostalCode = useMemo4(() => {
|
|
2950
|
+
if (!hookArgs.collectCep) return null;
|
|
2951
|
+
if (postalCode.length === 0) return null;
|
|
2952
|
+
const digits = postalCode.replace(/\D/g, "");
|
|
2953
|
+
if (digits.length !== 8) return "CEP deve ter 8 d\xEDgitos.";
|
|
2954
|
+
return null;
|
|
2955
|
+
}, [hookArgs.collectCep, postalCode]);
|
|
2956
|
+
const validateAddressNumber = useMemo4(() => {
|
|
2957
|
+
if (!hookArgs.collectCep) return null;
|
|
2958
|
+
if (addressNumber.length === 0) return null;
|
|
2959
|
+
if (addressNumber.trim().length === 0) return "N\xFAmero obrigat\xF3rio.";
|
|
2960
|
+
return null;
|
|
2961
|
+
}, [hookArgs.collectCep, addressNumber]);
|
|
2944
2962
|
const nameError = touchedName || formSubmitAttempted ? validateName : null;
|
|
2945
2963
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2946
2964
|
const emailConfirmError = touchedEmailConfirm || formSubmitAttempted ? validateEmailConfirm : null;
|
|
2947
2965
|
const phoneError = touchedPhone || formSubmitAttempted ? validatePhone : null;
|
|
2948
2966
|
const cpfError = touchedCpf || formSubmitAttempted ? validateCpf : null;
|
|
2967
|
+
const postalCodeError = touchedPostalCode || formSubmitAttempted ? validatePostalCode : null;
|
|
2968
|
+
const addressNumberError = touchedAddressNumber || formSubmitAttempted ? validateAddressNumber : null;
|
|
2949
2969
|
const phoneOk = method === "pix-auto" ? phone === "" || PHONE_RE.test(phone) : PHONE_RE.test(phone);
|
|
2950
|
-
const
|
|
2970
|
+
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);
|
|
2951
2972
|
const submit = useCallback6(async () => {
|
|
2952
2973
|
setFormSubmitAttempted(true);
|
|
2953
2974
|
setError(null);
|
|
@@ -2956,9 +2977,9 @@ function useCheckoutForm(args) {
|
|
|
2956
2977
|
if (!canSubmit) return null;
|
|
2957
2978
|
setSubmitting(true);
|
|
2958
2979
|
try {
|
|
2959
|
-
let
|
|
2980
|
+
let args;
|
|
2960
2981
|
if (method === "card") {
|
|
2961
|
-
|
|
2982
|
+
args = {
|
|
2962
2983
|
method: "card",
|
|
2963
2984
|
name: name.trim(),
|
|
2964
2985
|
email,
|
|
@@ -2977,21 +2998,17 @@ function useCheckoutForm(args) {
|
|
|
2977
2998
|
name: card.holderName || name.trim(),
|
|
2978
2999
|
email,
|
|
2979
3000
|
cpfCnpj: cpf.replace(/\D/g, ""),
|
|
2980
|
-
//
|
|
2981
|
-
//
|
|
2982
|
-
//
|
|
2983
|
-
//
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
// collect CEP — see personalburn's PaywallStepPagamento for
|
|
2987
|
-
// the pattern.
|
|
2988
|
-
postalCode: "01001000",
|
|
2989
|
-
addressNumber: "100",
|
|
3001
|
+
// collectCep=true → CEP/número reais do form. Senão placeholder
|
|
3002
|
+
// válido (Asaas rejeita all-zeros, então shipping 01001000/100
|
|
3003
|
+
// que são válidos mas anonimizam). Apps com NF-e ou antifraude
|
|
3004
|
+
// refinada devem setar paywall.collectCep no app.config.json.
|
|
3005
|
+
postalCode: hookArgs.collectCep ? postalCode.replace(/\D/g, "") : "01001000",
|
|
3006
|
+
addressNumber: hookArgs.collectCep ? addressNumber.trim() : "100",
|
|
2990
3007
|
phone
|
|
2991
3008
|
}
|
|
2992
3009
|
};
|
|
2993
3010
|
} else {
|
|
2994
|
-
|
|
3011
|
+
args = {
|
|
2995
3012
|
method: "pix-auto",
|
|
2996
3013
|
name: name.trim(),
|
|
2997
3014
|
email,
|
|
@@ -3001,7 +3018,7 @@ function useCheckoutForm(args) {
|
|
|
3001
3018
|
cycle
|
|
3002
3019
|
};
|
|
3003
3020
|
}
|
|
3004
|
-
const result = await auth.subscribeAnonymous(
|
|
3021
|
+
const result = await auth.subscribeAnonymous(args);
|
|
3005
3022
|
return result;
|
|
3006
3023
|
} catch (err) {
|
|
3007
3024
|
if (err instanceof EmailTakenError) {
|
|
@@ -3027,6 +3044,10 @@ function useCheckoutForm(args) {
|
|
|
3027
3044
|
setPhone,
|
|
3028
3045
|
cpf,
|
|
3029
3046
|
setCpf,
|
|
3047
|
+
postalCode,
|
|
3048
|
+
setPostalCode,
|
|
3049
|
+
addressNumber,
|
|
3050
|
+
setAddressNumber,
|
|
3030
3051
|
method,
|
|
3031
3052
|
setMethod,
|
|
3032
3053
|
cycle,
|
|
@@ -3038,11 +3059,15 @@ function useCheckoutForm(args) {
|
|
|
3038
3059
|
emailConfirmError,
|
|
3039
3060
|
phoneError,
|
|
3040
3061
|
cpfError,
|
|
3062
|
+
postalCodeError,
|
|
3063
|
+
addressNumberError,
|
|
3041
3064
|
markNameTouched: () => setTouchedName(true),
|
|
3042
3065
|
markEmailTouched: () => setTouchedEmail(true),
|
|
3043
3066
|
markEmailConfirmTouched: () => setTouchedEmailConfirm(true),
|
|
3044
3067
|
markPhoneTouched: () => setTouchedPhone(true),
|
|
3045
3068
|
markCpfTouched: () => setTouchedCpf(true),
|
|
3069
|
+
markPostalCodeTouched: () => setTouchedPostalCode(true),
|
|
3070
|
+
markAddressNumberTouched: () => setTouchedAddressNumber(true),
|
|
3046
3071
|
emailStatus,
|
|
3047
3072
|
submit,
|
|
3048
3073
|
submitting,
|
|
@@ -3869,10 +3894,12 @@ function detectCardBrand(num) {
|
|
|
3869
3894
|
function CheckoutPageDefault() {
|
|
3870
3895
|
const navigate = useNavigate2();
|
|
3871
3896
|
const plan = usePlan();
|
|
3897
|
+
const config = useAppConfig();
|
|
3872
3898
|
const intent = useMemo6(readIntent, []);
|
|
3873
3899
|
const defaultMethod = intent.method === "pix-auto" ? "pix-auto" : "card";
|
|
3874
3900
|
const defaultCycle = intent.cycle === "MONTHLY" ? "MONTHLY" : "YEARLY";
|
|
3875
|
-
const
|
|
3901
|
+
const collectCep = config.paywall.mode !== "free" && config.paywall.collectCep === true;
|
|
3902
|
+
const form = useCheckoutForm({ defaultMethod, defaultCycle, collectCep });
|
|
3876
3903
|
const [expiryMmAa, setExpiryMmAa] = useState11("");
|
|
3877
3904
|
useEffect13(() => {
|
|
3878
3905
|
const { month, year } = parseExpiryMmAa(expiryMmAa);
|
|
@@ -4056,6 +4083,45 @@ function CheckoutPageDefault() {
|
|
|
4056
4083
|
}
|
|
4057
4084
|
),
|
|
4058
4085
|
!form.phoneError && /* @__PURE__ */ jsx48(FieldHint, { children: "Usado pra confirmar pagamento e tratar disputas." })
|
|
4086
|
+
] }) : null,
|
|
4087
|
+
collectCep && form.method === "card" ? /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
4088
|
+
/* @__PURE__ */ jsxs29("div", { children: [
|
|
4089
|
+
/* @__PURE__ */ jsx48(FieldLabel, { children: "CEP" }),
|
|
4090
|
+
/* @__PURE__ */ jsx48(
|
|
4091
|
+
FieldInput,
|
|
4092
|
+
{
|
|
4093
|
+
type: "text",
|
|
4094
|
+
inputMode: "numeric",
|
|
4095
|
+
autoComplete: "postal-code",
|
|
4096
|
+
placeholder: "00000-000",
|
|
4097
|
+
value: form.postalCode,
|
|
4098
|
+
onChange: (v) => {
|
|
4099
|
+
const digits = v.replace(/\D/g, "").slice(0, 8);
|
|
4100
|
+
const formatted = digits.length > 5 ? `${digits.slice(0, 5)}-${digits.slice(5)}` : digits;
|
|
4101
|
+
form.setPostalCode(formatted);
|
|
4102
|
+
},
|
|
4103
|
+
onBlur: form.markPostalCodeTouched,
|
|
4104
|
+
error: form.postalCodeError,
|
|
4105
|
+
valid: !!form.postalCode && !form.postalCodeError
|
|
4106
|
+
}
|
|
4107
|
+
)
|
|
4108
|
+
] }),
|
|
4109
|
+
/* @__PURE__ */ jsxs29("div", { children: [
|
|
4110
|
+
/* @__PURE__ */ jsx48(FieldLabel, { children: "N\xFAmero" }),
|
|
4111
|
+
/* @__PURE__ */ jsx48(
|
|
4112
|
+
FieldInput,
|
|
4113
|
+
{
|
|
4114
|
+
type: "text",
|
|
4115
|
+
inputMode: "numeric",
|
|
4116
|
+
placeholder: "100",
|
|
4117
|
+
value: form.addressNumber,
|
|
4118
|
+
onChange: form.setAddressNumber,
|
|
4119
|
+
onBlur: form.markAddressNumberTouched,
|
|
4120
|
+
error: form.addressNumberError,
|
|
4121
|
+
valid: !!form.addressNumber && !form.addressNumberError
|
|
4122
|
+
}
|
|
4123
|
+
)
|
|
4124
|
+
] })
|
|
4059
4125
|
] }) : null
|
|
4060
4126
|
] })
|
|
4061
4127
|
] }),
|