@hook-sdk/template 0.28.8 → 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 +126 -46
- 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 +126 -46
- 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
|
});
|
|
@@ -2115,33 +2116,47 @@ function SessionExpiredBanner() {
|
|
|
2115
2116
|
localStorage.setItem(DISMISS_KEY, String(Date.now() + DISMISS_TTL_MS));
|
|
2116
2117
|
setShow(false);
|
|
2117
2118
|
}
|
|
2118
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
"
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
children: "
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2120
|
+
"div",
|
|
2121
|
+
{
|
|
2122
|
+
role: "alert",
|
|
2123
|
+
className: "fixed top-0 inset-x-0 px-4 py-3 flex items-center justify-between gap-3 text-sm font-medium shadow-lg",
|
|
2124
|
+
style: {
|
|
2125
|
+
zIndex: 10001,
|
|
2126
|
+
backgroundColor: "#991b1b",
|
|
2127
|
+
color: "#ffffff"
|
|
2128
|
+
},
|
|
2129
|
+
children: [
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { className: "font-bold", children: "Sua sess\xE3o expirou." }),
|
|
2132
|
+
" Fa\xE7a login novamente para continuar."
|
|
2133
|
+
] }),
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2135
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2136
|
+
"button",
|
|
2137
|
+
{
|
|
2138
|
+
type: "button",
|
|
2139
|
+
onClick: dismiss,
|
|
2140
|
+
className: "px-3 py-1.5 rounded text-xs font-semibold",
|
|
2141
|
+
style: { backgroundColor: "#ffffff", color: "#991b1b" },
|
|
2142
|
+
children: "Fazer login"
|
|
2143
|
+
}
|
|
2144
|
+
),
|
|
2145
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2146
|
+
"button",
|
|
2147
|
+
{
|
|
2148
|
+
type: "button",
|
|
2149
|
+
onClick: dismiss,
|
|
2150
|
+
"aria-label": "Fechar",
|
|
2151
|
+
className: "px-2 py-1 text-xs",
|
|
2152
|
+
style: { color: "#ffffff" },
|
|
2153
|
+
children: "Fechar"
|
|
2154
|
+
}
|
|
2155
|
+
)
|
|
2156
|
+
] })
|
|
2157
|
+
]
|
|
2158
|
+
}
|
|
2159
|
+
);
|
|
2145
2160
|
}
|
|
2146
2161
|
|
|
2147
2162
|
// src/internal/EmailVerifyBanner.tsx
|
|
@@ -2958,15 +2973,17 @@ function mapSdkError(err) {
|
|
|
2958
2973
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2959
2974
|
var PHONE_RE = /^[0-9()+\-\s]{8,20}$/;
|
|
2960
2975
|
var CHECK_DEBOUNCE_MS = 400;
|
|
2961
|
-
function useCheckoutForm(
|
|
2976
|
+
function useCheckoutForm(hookArgs) {
|
|
2962
2977
|
const { auth } = (0, import_sdk13.useHook)();
|
|
2963
2978
|
const [name, setName] = (0, import_react18.useState)("");
|
|
2964
2979
|
const [email, setEmail] = (0, import_react18.useState)("");
|
|
2965
2980
|
const [emailConfirm, setEmailConfirm] = (0, import_react18.useState)("");
|
|
2966
2981
|
const [phone, setPhone] = (0, import_react18.useState)("");
|
|
2967
2982
|
const [cpf, setCpf] = (0, import_react18.useState)("");
|
|
2968
|
-
const [
|
|
2969
|
-
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);
|
|
2970
2987
|
const [card, setCardState] = (0, import_react18.useState)({
|
|
2971
2988
|
number: "",
|
|
2972
2989
|
expiryMonth: "",
|
|
@@ -2982,6 +2999,8 @@ function useCheckoutForm(args) {
|
|
|
2982
2999
|
const [touchedEmailConfirm, setTouchedEmailConfirm] = (0, import_react18.useState)(false);
|
|
2983
3000
|
const [touchedPhone, setTouchedPhone] = (0, import_react18.useState)(false);
|
|
2984
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);
|
|
2985
3004
|
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
|
|
2986
3005
|
const [submitting, setSubmitting] = (0, import_react18.useState)(false);
|
|
2987
3006
|
const [error, setError] = (0, import_react18.useState)(null);
|
|
@@ -3035,13 +3054,29 @@ function useCheckoutForm(args) {
|
|
|
3035
3054
|
const ok = mod11(digits, 9) === digits[9] && mod11(digits, 10) === digits[10];
|
|
3036
3055
|
return ok ? null : "CPF inv\xE1lido.";
|
|
3037
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]);
|
|
3038
3070
|
const nameError = touchedName || formSubmitAttempted ? validateName : null;
|
|
3039
3071
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
3040
3072
|
const emailConfirmError = touchedEmailConfirm || formSubmitAttempted ? validateEmailConfirm : null;
|
|
3041
3073
|
const phoneError = touchedPhone || formSubmitAttempted ? validatePhone : null;
|
|
3042
3074
|
const cpfError = touchedCpf || formSubmitAttempted ? validateCpf : null;
|
|
3075
|
+
const postalCodeError = touchedPostalCode || formSubmitAttempted ? validatePostalCode : null;
|
|
3076
|
+
const addressNumberError = touchedAddressNumber || formSubmitAttempted ? validateAddressNumber : null;
|
|
3043
3077
|
const phoneOk = method === "pix-auto" ? phone === "" || PHONE_RE.test(phone) : PHONE_RE.test(phone);
|
|
3044
|
-
const
|
|
3078
|
+
const cepGateOk = !hookArgs.collectCep || method !== "card" || postalCode.replace(/\D/g, "").length === 8 && addressNumber.trim().length > 0;
|
|
3079
|
+
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);
|
|
3045
3080
|
const submit = (0, import_react18.useCallback)(async () => {
|
|
3046
3081
|
setFormSubmitAttempted(true);
|
|
3047
3082
|
setError(null);
|
|
@@ -3050,9 +3085,9 @@ function useCheckoutForm(args) {
|
|
|
3050
3085
|
if (!canSubmit) return null;
|
|
3051
3086
|
setSubmitting(true);
|
|
3052
3087
|
try {
|
|
3053
|
-
let
|
|
3088
|
+
let args;
|
|
3054
3089
|
if (method === "card") {
|
|
3055
|
-
|
|
3090
|
+
args = {
|
|
3056
3091
|
method: "card",
|
|
3057
3092
|
name: name.trim(),
|
|
3058
3093
|
email,
|
|
@@ -3071,21 +3106,17 @@ function useCheckoutForm(args) {
|
|
|
3071
3106
|
name: card.holderName || name.trim(),
|
|
3072
3107
|
email,
|
|
3073
3108
|
cpfCnpj: cpf.replace(/\D/g, ""),
|
|
3074
|
-
//
|
|
3075
|
-
//
|
|
3076
|
-
//
|
|
3077
|
-
//
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
// collect CEP — see personalburn's PaywallStepPagamento for
|
|
3081
|
-
// the pattern.
|
|
3082
|
-
postalCode: "01001000",
|
|
3083
|
-
addressNumber: "100",
|
|
3109
|
+
// collectCep=true → CEP/número reais do form. Senão placeholder
|
|
3110
|
+
// válido (Asaas rejeita all-zeros, então shipping 01001000/100
|
|
3111
|
+
// que são válidos mas anonimizam). Apps com NF-e ou antifraude
|
|
3112
|
+
// refinada devem setar paywall.collectCep no app.config.json.
|
|
3113
|
+
postalCode: hookArgs.collectCep ? postalCode.replace(/\D/g, "") : "01001000",
|
|
3114
|
+
addressNumber: hookArgs.collectCep ? addressNumber.trim() : "100",
|
|
3084
3115
|
phone
|
|
3085
3116
|
}
|
|
3086
3117
|
};
|
|
3087
3118
|
} else {
|
|
3088
|
-
|
|
3119
|
+
args = {
|
|
3089
3120
|
method: "pix-auto",
|
|
3090
3121
|
name: name.trim(),
|
|
3091
3122
|
email,
|
|
@@ -3095,7 +3126,7 @@ function useCheckoutForm(args) {
|
|
|
3095
3126
|
cycle
|
|
3096
3127
|
};
|
|
3097
3128
|
}
|
|
3098
|
-
const result = await auth.subscribeAnonymous(
|
|
3129
|
+
const result = await auth.subscribeAnonymous(args);
|
|
3099
3130
|
return result;
|
|
3100
3131
|
} catch (err) {
|
|
3101
3132
|
if (err instanceof import_sdk13.EmailTakenError) {
|
|
@@ -3121,6 +3152,10 @@ function useCheckoutForm(args) {
|
|
|
3121
3152
|
setPhone,
|
|
3122
3153
|
cpf,
|
|
3123
3154
|
setCpf,
|
|
3155
|
+
postalCode,
|
|
3156
|
+
setPostalCode,
|
|
3157
|
+
addressNumber,
|
|
3158
|
+
setAddressNumber,
|
|
3124
3159
|
method,
|
|
3125
3160
|
setMethod,
|
|
3126
3161
|
cycle,
|
|
@@ -3132,11 +3167,15 @@ function useCheckoutForm(args) {
|
|
|
3132
3167
|
emailConfirmError,
|
|
3133
3168
|
phoneError,
|
|
3134
3169
|
cpfError,
|
|
3170
|
+
postalCodeError,
|
|
3171
|
+
addressNumberError,
|
|
3135
3172
|
markNameTouched: () => setTouchedName(true),
|
|
3136
3173
|
markEmailTouched: () => setTouchedEmail(true),
|
|
3137
3174
|
markEmailConfirmTouched: () => setTouchedEmailConfirm(true),
|
|
3138
3175
|
markPhoneTouched: () => setTouchedPhone(true),
|
|
3139
3176
|
markCpfTouched: () => setTouchedCpf(true),
|
|
3177
|
+
markPostalCodeTouched: () => setTouchedPostalCode(true),
|
|
3178
|
+
markAddressNumberTouched: () => setTouchedAddressNumber(true),
|
|
3140
3179
|
emailStatus,
|
|
3141
3180
|
submit,
|
|
3142
3181
|
submitting,
|
|
@@ -3963,10 +4002,12 @@ function detectCardBrand(num) {
|
|
|
3963
4002
|
function CheckoutPageDefault() {
|
|
3964
4003
|
const navigate = (0, import_react_router_dom3.useNavigate)();
|
|
3965
4004
|
const plan = usePlan();
|
|
4005
|
+
const config = useAppConfig();
|
|
3966
4006
|
const intent = (0, import_react23.useMemo)(readIntent, []);
|
|
3967
4007
|
const defaultMethod = intent.method === "pix-auto" ? "pix-auto" : "card";
|
|
3968
4008
|
const defaultCycle = intent.cycle === "MONTHLY" ? "MONTHLY" : "YEARLY";
|
|
3969
|
-
const
|
|
4009
|
+
const collectCep = config.paywall.mode !== "free" && config.paywall.collectCep === true;
|
|
4010
|
+
const form = useCheckoutForm({ defaultMethod, defaultCycle, collectCep });
|
|
3970
4011
|
const [expiryMmAa, setExpiryMmAa] = (0, import_react23.useState)("");
|
|
3971
4012
|
(0, import_react23.useEffect)(() => {
|
|
3972
4013
|
const { month, year } = parseExpiryMmAa(expiryMmAa);
|
|
@@ -4150,6 +4191,45 @@ function CheckoutPageDefault() {
|
|
|
4150
4191
|
}
|
|
4151
4192
|
),
|
|
4152
4193
|
!form.phoneError && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldHint, { children: "Usado pra confirmar pagamento e tratar disputas." })
|
|
4194
|
+
] }) : null,
|
|
4195
|
+
collectCep && form.method === "card" ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
4196
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { children: [
|
|
4197
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { children: "CEP" }),
|
|
4198
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4199
|
+
FieldInput,
|
|
4200
|
+
{
|
|
4201
|
+
type: "text",
|
|
4202
|
+
inputMode: "numeric",
|
|
4203
|
+
autoComplete: "postal-code",
|
|
4204
|
+
placeholder: "00000-000",
|
|
4205
|
+
value: form.postalCode,
|
|
4206
|
+
onChange: (v) => {
|
|
4207
|
+
const digits = v.replace(/\D/g, "").slice(0, 8);
|
|
4208
|
+
const formatted = digits.length > 5 ? `${digits.slice(0, 5)}-${digits.slice(5)}` : digits;
|
|
4209
|
+
form.setPostalCode(formatted);
|
|
4210
|
+
},
|
|
4211
|
+
onBlur: form.markPostalCodeTouched,
|
|
4212
|
+
error: form.postalCodeError,
|
|
4213
|
+
valid: !!form.postalCode && !form.postalCodeError
|
|
4214
|
+
}
|
|
4215
|
+
)
|
|
4216
|
+
] }),
|
|
4217
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { children: [
|
|
4218
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { children: "N\xFAmero" }),
|
|
4219
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4220
|
+
FieldInput,
|
|
4221
|
+
{
|
|
4222
|
+
type: "text",
|
|
4223
|
+
inputMode: "numeric",
|
|
4224
|
+
placeholder: "100",
|
|
4225
|
+
value: form.addressNumber,
|
|
4226
|
+
onChange: form.setAddressNumber,
|
|
4227
|
+
onBlur: form.markAddressNumberTouched,
|
|
4228
|
+
error: form.addressNumberError,
|
|
4229
|
+
valid: !!form.addressNumber && !form.addressNumberError
|
|
4230
|
+
}
|
|
4231
|
+
)
|
|
4232
|
+
] })
|
|
4153
4233
|
] }) : null
|
|
4154
4234
|
] })
|
|
4155
4235
|
] }),
|