@hook-sdk/template 0.28.9 → 0.28.11
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 +107 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +107 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -169,6 +169,7 @@ var PaywallNonFreeSchema = import_zod.z.object({
|
|
|
169
169
|
}).optional(),
|
|
170
170
|
checkoutMethods: import_zod.z.array(import_zod.z.enum(["card", "pix-auto", "pix-once"])).min(1),
|
|
171
171
|
requiresCpf: import_zod.z.boolean(),
|
|
172
|
+
collectCep: import_zod.z.boolean().optional(),
|
|
172
173
|
cancelWindowDays: import_zod.z.number().int().nonnegative().optional(),
|
|
173
174
|
errorMessages: import_zod.z.enum(["default", "custom"])
|
|
174
175
|
});
|
|
@@ -2972,15 +2973,17 @@ function mapSdkError(err) {
|
|
|
2972
2973
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2973
2974
|
var PHONE_RE = /^[0-9()+\-\s]{8,20}$/;
|
|
2974
2975
|
var CHECK_DEBOUNCE_MS = 400;
|
|
2975
|
-
function useCheckoutForm(
|
|
2976
|
+
function useCheckoutForm(hookArgs) {
|
|
2976
2977
|
const { auth } = (0, import_sdk13.useHook)();
|
|
2977
2978
|
const [name, setName] = (0, import_react18.useState)("");
|
|
2978
2979
|
const [email, setEmail] = (0, import_react18.useState)("");
|
|
2979
2980
|
const [emailConfirm, setEmailConfirm] = (0, import_react18.useState)("");
|
|
2980
2981
|
const [phone, setPhone] = (0, import_react18.useState)("");
|
|
2981
2982
|
const [cpf, setCpf] = (0, import_react18.useState)("");
|
|
2982
|
-
const [
|
|
2983
|
-
const [
|
|
2983
|
+
const [postalCode, setPostalCode] = (0, import_react18.useState)("");
|
|
2984
|
+
const [addressNumber, setAddressNumber] = (0, import_react18.useState)("");
|
|
2985
|
+
const [method, setMethod] = (0, import_react18.useState)(hookArgs.defaultMethod);
|
|
2986
|
+
const [cycle, setCycle] = (0, import_react18.useState)(hookArgs.defaultCycle);
|
|
2984
2987
|
const [card, setCardState] = (0, import_react18.useState)({
|
|
2985
2988
|
number: "",
|
|
2986
2989
|
expiryMonth: "",
|
|
@@ -2996,6 +2999,8 @@ function useCheckoutForm(args) {
|
|
|
2996
2999
|
const [touchedEmailConfirm, setTouchedEmailConfirm] = (0, import_react18.useState)(false);
|
|
2997
3000
|
const [touchedPhone, setTouchedPhone] = (0, import_react18.useState)(false);
|
|
2998
3001
|
const [touchedCpf, setTouchedCpf] = (0, import_react18.useState)(false);
|
|
3002
|
+
const [touchedPostalCode, setTouchedPostalCode] = (0, import_react18.useState)(false);
|
|
3003
|
+
const [touchedAddressNumber, setTouchedAddressNumber] = (0, import_react18.useState)(false);
|
|
2999
3004
|
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
|
|
3000
3005
|
const [submitting, setSubmitting] = (0, import_react18.useState)(false);
|
|
3001
3006
|
const [error, setError] = (0, import_react18.useState)(null);
|
|
@@ -3049,13 +3054,46 @@ function useCheckoutForm(args) {
|
|
|
3049
3054
|
const ok = mod11(digits, 9) === digits[9] && mod11(digits, 10) === digits[10];
|
|
3050
3055
|
return ok ? null : "CPF inv\xE1lido.";
|
|
3051
3056
|
}, [cpf]);
|
|
3057
|
+
const validatePostalCode = (0, import_react18.useMemo)(() => {
|
|
3058
|
+
if (!hookArgs.collectCep) return null;
|
|
3059
|
+
if (postalCode.length === 0) return null;
|
|
3060
|
+
const digits = postalCode.replace(/\D/g, "");
|
|
3061
|
+
if (digits.length !== 8) return "CEP deve ter 8 d\xEDgitos.";
|
|
3062
|
+
return null;
|
|
3063
|
+
}, [hookArgs.collectCep, postalCode]);
|
|
3064
|
+
const validateAddressNumber = (0, import_react18.useMemo)(() => {
|
|
3065
|
+
if (!hookArgs.collectCep) return null;
|
|
3066
|
+
if (addressNumber.length === 0) return null;
|
|
3067
|
+
if (addressNumber.trim().length === 0) return "N\xFAmero obrigat\xF3rio.";
|
|
3068
|
+
return null;
|
|
3069
|
+
}, [hookArgs.collectCep, addressNumber]);
|
|
3052
3070
|
const nameError = touchedName || formSubmitAttempted ? validateName : null;
|
|
3053
3071
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
3054
3072
|
const emailConfirmError = touchedEmailConfirm || formSubmitAttempted ? validateEmailConfirm : null;
|
|
3055
3073
|
const phoneError = touchedPhone || formSubmitAttempted ? validatePhone : null;
|
|
3056
3074
|
const cpfError = touchedCpf || formSubmitAttempted ? validateCpf : null;
|
|
3075
|
+
const postalCodeError = touchedPostalCode || formSubmitAttempted ? validatePostalCode : null;
|
|
3076
|
+
const addressNumberError = touchedAddressNumber || formSubmitAttempted ? validateAddressNumber : null;
|
|
3077
|
+
const cardExpiryError = (0, import_react18.useMemo)(() => {
|
|
3078
|
+
if (method !== "card") return null;
|
|
3079
|
+
const mm = card.expiryMonth.replace(/\D/g, "");
|
|
3080
|
+
const yy = card.expiryYear.replace(/\D/g, "");
|
|
3081
|
+
if (mm.length < 2 || yy.length < 2) return null;
|
|
3082
|
+
const monthNum = parseInt(mm, 10);
|
|
3083
|
+
if (monthNum < 1 || monthNum > 12) return "M\xEAs inv\xE1lido (use 01-12).";
|
|
3084
|
+
const yearNum = 2e3 + parseInt(yy, 10);
|
|
3085
|
+
const now = /* @__PURE__ */ new Date();
|
|
3086
|
+
const currentMonth = now.getMonth() + 1;
|
|
3087
|
+
const currentYear = now.getFullYear();
|
|
3088
|
+
if (yearNum < currentYear || yearNum === currentYear && monthNum < currentMonth) {
|
|
3089
|
+
return "Cart\xE3o vencido.";
|
|
3090
|
+
}
|
|
3091
|
+
if (yearNum > currentYear + 20) return "Ano muito distante.";
|
|
3092
|
+
return null;
|
|
3093
|
+
}, [method, card.expiryMonth, card.expiryYear]);
|
|
3057
3094
|
const phoneOk = method === "pix-auto" ? phone === "" || PHONE_RE.test(phone) : PHONE_RE.test(phone);
|
|
3058
|
-
const
|
|
3095
|
+
const cepGateOk = !hookArgs.collectCep || method !== "card" || postalCode.replace(/\D/g, "").length === 8 && addressNumber.trim().length > 0;
|
|
3096
|
+
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);
|
|
3059
3097
|
const submit = (0, import_react18.useCallback)(async () => {
|
|
3060
3098
|
setFormSubmitAttempted(true);
|
|
3061
3099
|
setError(null);
|
|
@@ -3064,9 +3102,9 @@ function useCheckoutForm(args) {
|
|
|
3064
3102
|
if (!canSubmit) return null;
|
|
3065
3103
|
setSubmitting(true);
|
|
3066
3104
|
try {
|
|
3067
|
-
let
|
|
3105
|
+
let args;
|
|
3068
3106
|
if (method === "card") {
|
|
3069
|
-
|
|
3107
|
+
args = {
|
|
3070
3108
|
method: "card",
|
|
3071
3109
|
name: name.trim(),
|
|
3072
3110
|
email,
|
|
@@ -3085,21 +3123,17 @@ function useCheckoutForm(args) {
|
|
|
3085
3123
|
name: card.holderName || name.trim(),
|
|
3086
3124
|
email,
|
|
3087
3125
|
cpfCnpj: cpf.replace(/\D/g, ""),
|
|
3088
|
-
//
|
|
3089
|
-
//
|
|
3090
|
-
//
|
|
3091
|
-
//
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
// collect CEP — see personalburn's PaywallStepPagamento for
|
|
3095
|
-
// the pattern.
|
|
3096
|
-
postalCode: "01001000",
|
|
3097
|
-
addressNumber: "100",
|
|
3126
|
+
// collectCep=true → CEP/número reais do form. Senão placeholder
|
|
3127
|
+
// válido (Asaas rejeita all-zeros, então shipping 01001000/100
|
|
3128
|
+
// que são válidos mas anonimizam). Apps com NF-e ou antifraude
|
|
3129
|
+
// refinada devem setar paywall.collectCep no app.config.json.
|
|
3130
|
+
postalCode: hookArgs.collectCep ? postalCode.replace(/\D/g, "") : "01001000",
|
|
3131
|
+
addressNumber: hookArgs.collectCep ? addressNumber.trim() : "100",
|
|
3098
3132
|
phone
|
|
3099
3133
|
}
|
|
3100
3134
|
};
|
|
3101
3135
|
} else {
|
|
3102
|
-
|
|
3136
|
+
args = {
|
|
3103
3137
|
method: "pix-auto",
|
|
3104
3138
|
name: name.trim(),
|
|
3105
3139
|
email,
|
|
@@ -3109,7 +3143,7 @@ function useCheckoutForm(args) {
|
|
|
3109
3143
|
cycle
|
|
3110
3144
|
};
|
|
3111
3145
|
}
|
|
3112
|
-
const result = await auth.subscribeAnonymous(
|
|
3146
|
+
const result = await auth.subscribeAnonymous(args);
|
|
3113
3147
|
return result;
|
|
3114
3148
|
} catch (err) {
|
|
3115
3149
|
if (err instanceof import_sdk13.EmailTakenError) {
|
|
@@ -3135,6 +3169,10 @@ function useCheckoutForm(args) {
|
|
|
3135
3169
|
setPhone,
|
|
3136
3170
|
cpf,
|
|
3137
3171
|
setCpf,
|
|
3172
|
+
postalCode,
|
|
3173
|
+
setPostalCode,
|
|
3174
|
+
addressNumber,
|
|
3175
|
+
setAddressNumber,
|
|
3138
3176
|
method,
|
|
3139
3177
|
setMethod,
|
|
3140
3178
|
cycle,
|
|
@@ -3146,11 +3184,16 @@ function useCheckoutForm(args) {
|
|
|
3146
3184
|
emailConfirmError,
|
|
3147
3185
|
phoneError,
|
|
3148
3186
|
cpfError,
|
|
3187
|
+
postalCodeError,
|
|
3188
|
+
addressNumberError,
|
|
3189
|
+
cardExpiryError,
|
|
3149
3190
|
markNameTouched: () => setTouchedName(true),
|
|
3150
3191
|
markEmailTouched: () => setTouchedEmail(true),
|
|
3151
3192
|
markEmailConfirmTouched: () => setTouchedEmailConfirm(true),
|
|
3152
3193
|
markPhoneTouched: () => setTouchedPhone(true),
|
|
3153
3194
|
markCpfTouched: () => setTouchedCpf(true),
|
|
3195
|
+
markPostalCodeTouched: () => setTouchedPostalCode(true),
|
|
3196
|
+
markAddressNumberTouched: () => setTouchedAddressNumber(true),
|
|
3154
3197
|
emailStatus,
|
|
3155
3198
|
submit,
|
|
3156
3199
|
submitting,
|
|
@@ -3977,10 +4020,12 @@ function detectCardBrand(num) {
|
|
|
3977
4020
|
function CheckoutPageDefault() {
|
|
3978
4021
|
const navigate = (0, import_react_router_dom3.useNavigate)();
|
|
3979
4022
|
const plan = usePlan();
|
|
4023
|
+
const config = useAppConfig();
|
|
3980
4024
|
const intent = (0, import_react23.useMemo)(readIntent, []);
|
|
3981
4025
|
const defaultMethod = intent.method === "pix-auto" ? "pix-auto" : "card";
|
|
3982
4026
|
const defaultCycle = intent.cycle === "MONTHLY" ? "MONTHLY" : "YEARLY";
|
|
3983
|
-
const
|
|
4027
|
+
const collectCep = config.paywall.mode !== "free" && config.paywall.collectCep === true;
|
|
4028
|
+
const form = useCheckoutForm({ defaultMethod, defaultCycle, collectCep });
|
|
3984
4029
|
const [expiryMmAa, setExpiryMmAa] = (0, import_react23.useState)("");
|
|
3985
4030
|
(0, import_react23.useEffect)(() => {
|
|
3986
4031
|
const { month, year } = parseExpiryMmAa(expiryMmAa);
|
|
@@ -4109,11 +4154,11 @@ function CheckoutPageDefault() {
|
|
|
4109
4154
|
value: form.email,
|
|
4110
4155
|
onChange: form.setEmail,
|
|
4111
4156
|
onBlur: form.markEmailTouched,
|
|
4112
|
-
error: form.emailError,
|
|
4157
|
+
error: form.emailError ?? (form.emailStatus === "exists" ? "Este email j\xE1 tem conta. Faz login pra continuar." : null),
|
|
4113
4158
|
valid: form.emailStatus === "available"
|
|
4114
4159
|
}
|
|
4115
4160
|
),
|
|
4116
|
-
!form.emailError && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldHint, { children: form.emailStatus === "checking" ? "Verificando\u2026" : form.emailStatus === "available" ? "\u2713 Dispon\xEDvel" : "Voc\xEA vai usar este email para entrar no app" })
|
|
4161
|
+
!form.emailError && form.emailStatus !== "exists" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldHint, { children: form.emailStatus === "checking" ? "Verificando\u2026" : form.emailStatus === "available" ? "\u2713 Dispon\xEDvel" : "Voc\xEA vai usar este email para entrar no app" })
|
|
4117
4162
|
] }),
|
|
4118
4163
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { children: [
|
|
4119
4164
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { children: "Nome completo" }),
|
|
@@ -4164,6 +4209,45 @@ function CheckoutPageDefault() {
|
|
|
4164
4209
|
}
|
|
4165
4210
|
),
|
|
4166
4211
|
!form.phoneError && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldHint, { children: "Usado pra confirmar pagamento e tratar disputas." })
|
|
4212
|
+
] }) : null,
|
|
4213
|
+
collectCep && form.method === "card" ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
4214
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { children: [
|
|
4215
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { children: "CEP" }),
|
|
4216
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4217
|
+
FieldInput,
|
|
4218
|
+
{
|
|
4219
|
+
type: "text",
|
|
4220
|
+
inputMode: "numeric",
|
|
4221
|
+
autoComplete: "postal-code",
|
|
4222
|
+
placeholder: "00000-000",
|
|
4223
|
+
value: form.postalCode,
|
|
4224
|
+
onChange: (v) => {
|
|
4225
|
+
const digits = v.replace(/\D/g, "").slice(0, 8);
|
|
4226
|
+
const formatted = digits.length > 5 ? `${digits.slice(0, 5)}-${digits.slice(5)}` : digits;
|
|
4227
|
+
form.setPostalCode(formatted);
|
|
4228
|
+
},
|
|
4229
|
+
onBlur: form.markPostalCodeTouched,
|
|
4230
|
+
error: form.postalCodeError,
|
|
4231
|
+
valid: !!form.postalCode && !form.postalCodeError
|
|
4232
|
+
}
|
|
4233
|
+
)
|
|
4234
|
+
] }),
|
|
4235
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { children: [
|
|
4236
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { children: "N\xFAmero" }),
|
|
4237
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4238
|
+
FieldInput,
|
|
4239
|
+
{
|
|
4240
|
+
type: "text",
|
|
4241
|
+
inputMode: "numeric",
|
|
4242
|
+
placeholder: "100",
|
|
4243
|
+
value: form.addressNumber,
|
|
4244
|
+
onChange: form.setAddressNumber,
|
|
4245
|
+
onBlur: form.markAddressNumberTouched,
|
|
4246
|
+
error: form.addressNumberError,
|
|
4247
|
+
valid: !!form.addressNumber && !form.addressNumberError
|
|
4248
|
+
}
|
|
4249
|
+
)
|
|
4250
|
+
] })
|
|
4167
4251
|
] }) : null
|
|
4168
4252
|
] })
|
|
4169
4253
|
] }),
|
|
@@ -4225,7 +4309,8 @@ function CheckoutPageDefault() {
|
|
|
4225
4309
|
autoComplete: "cc-exp",
|
|
4226
4310
|
placeholder: "MM/AA",
|
|
4227
4311
|
value: expiryMmAa,
|
|
4228
|
-
onChange: (v) => setExpiryMmAa(formatExpiryMmAa(v))
|
|
4312
|
+
onChange: (v) => setExpiryMmAa(formatExpiryMmAa(v)),
|
|
4313
|
+
error: form.cardExpiryError
|
|
4229
4314
|
}
|
|
4230
4315
|
)
|
|
4231
4316
|
] }),
|