@hook-sdk/template 0.8.0 → 0.9.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 +540 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -17
- package/dist/index.d.ts +30 -17
- package/dist/index.js +557 -97
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -62,7 +62,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
62
62
|
|
|
63
63
|
// src/AppRoot.tsx
|
|
64
64
|
var import_react15 = require("react");
|
|
65
|
-
var
|
|
65
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
66
66
|
|
|
67
67
|
// src/internal/TemplateConfigContext.tsx
|
|
68
68
|
var import_react = require("react");
|
|
@@ -157,50 +157,66 @@ function AuthGate({ Login, Signup, Forgot, Reset, children }) {
|
|
|
157
157
|
var import_react3 = require("react");
|
|
158
158
|
var import_sdk2 = require("@hook-sdk/sdk");
|
|
159
159
|
function usePaywallState() {
|
|
160
|
-
const { subscription } = (0, import_sdk2.useHook)();
|
|
160
|
+
const { subscription, plan } = (0, import_sdk2.useHook)();
|
|
161
161
|
const [opening, setOpening] = (0, import_react3.useState)(false);
|
|
162
162
|
const [error, setError] = (0, import_react3.useState)(null);
|
|
163
163
|
const [pixPending, setPixPending] = (0, import_react3.useState)(null);
|
|
164
164
|
const status = subscription.status();
|
|
165
165
|
const daysLeftInTrial = subscription.daysLeftInTrial();
|
|
166
166
|
const initialLoadComplete = subscription.initialLoadComplete;
|
|
167
|
+
const availableMethods = (0, import_react3.useMemo)(
|
|
168
|
+
() => ["card", "pix-auto"],
|
|
169
|
+
[]
|
|
170
|
+
);
|
|
171
|
+
const priceCents = plan.data?.priceCents ?? 0;
|
|
172
|
+
const yearlyPriceCents = plan.data?.yearlyPriceCents ?? null;
|
|
173
|
+
const monthlyEquivalent = (0, import_react3.useCallback)(
|
|
174
|
+
(cycle) => {
|
|
175
|
+
if (cycle === "YEARLY" && yearlyPriceCents) {
|
|
176
|
+
return Math.round(yearlyPriceCents / 12);
|
|
177
|
+
}
|
|
178
|
+
return priceCents;
|
|
179
|
+
},
|
|
180
|
+
[priceCents, yearlyPriceCents]
|
|
181
|
+
);
|
|
167
182
|
const checkout = (0, import_react3.useCallback)(
|
|
168
183
|
async (args) => {
|
|
169
184
|
setOpening(true);
|
|
170
185
|
setError(null);
|
|
171
186
|
setPixPending(null);
|
|
172
|
-
const method = args.method ?? "card";
|
|
173
|
-
const cycle = args.cycle ?? "MONTHLY";
|
|
174
187
|
try {
|
|
175
|
-
if (method === "card") {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
expiresAt: null,
|
|
187
|
-
paid: false
|
|
188
|
+
if (args.method === "card") {
|
|
189
|
+
if (!args.card || !args.holderInfo) {
|
|
190
|
+
throw new Error('card and holderInfo are required when method is "card"');
|
|
191
|
+
}
|
|
192
|
+
await subscription.checkout({
|
|
193
|
+
method: "card",
|
|
194
|
+
cycle: args.cycle,
|
|
195
|
+
cpf: args.cpf,
|
|
196
|
+
card: args.card,
|
|
197
|
+
holderInfo: args.holderInfo,
|
|
198
|
+
...args.remoteIp ? { remoteIp: args.remoteIp } : {}
|
|
188
199
|
});
|
|
200
|
+
await subscription.refresh();
|
|
189
201
|
setOpening(false);
|
|
190
202
|
return;
|
|
191
203
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
paid: false
|
|
200
|
-
});
|
|
201
|
-
setOpening(false);
|
|
202
|
-
return;
|
|
204
|
+
const result = await subscription.checkout({
|
|
205
|
+
method: "pix-auto",
|
|
206
|
+
cycle: args.cycle,
|
|
207
|
+
cpf: args.cpf
|
|
208
|
+
});
|
|
209
|
+
if (result.method !== "pix-auto") {
|
|
210
|
+
throw new Error(`unexpected checkout result method: ${result.method}`);
|
|
203
211
|
}
|
|
212
|
+
setPixPending({
|
|
213
|
+
method: "pix-auto",
|
|
214
|
+
qrCodePayload: result.qrCodePayload,
|
|
215
|
+
qrCodeBase64: result.qrCodeBase64,
|
|
216
|
+
expiresAt: null,
|
|
217
|
+
paid: false
|
|
218
|
+
});
|
|
219
|
+
setOpening(false);
|
|
204
220
|
} catch (err) {
|
|
205
221
|
setError(err);
|
|
206
222
|
setOpening(false);
|
|
@@ -253,7 +269,9 @@ function usePaywallState() {
|
|
|
253
269
|
opening,
|
|
254
270
|
error,
|
|
255
271
|
pixPending,
|
|
256
|
-
dismissPix
|
|
272
|
+
dismissPix,
|
|
273
|
+
availableMethods,
|
|
274
|
+
monthlyEquivalent
|
|
257
275
|
};
|
|
258
276
|
}
|
|
259
277
|
|
|
@@ -1549,9 +1567,10 @@ function InstallGate({ children }) {
|
|
|
1549
1567
|
if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1550
1568
|
if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1551
1569
|
if (installState.variant === "desktop") {
|
|
1570
|
+
const showBanner = !installState.isDismissedSession && !installState.isDismissedPermanent;
|
|
1552
1571
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1553
1572
|
children,
|
|
1554
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DesktopVariant, { state: installState, actions: installState })
|
|
1573
|
+
showBanner && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DesktopVariant, { state: installState, actions: installState })
|
|
1555
1574
|
] });
|
|
1556
1575
|
}
|
|
1557
1576
|
if (!shouldBlock) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
@@ -2197,33 +2216,429 @@ function DefaultResetScreen({ onNavigate }) {
|
|
|
2197
2216
|
|
|
2198
2217
|
// src/defaults/DefaultPaywall.tsx
|
|
2199
2218
|
var import_react14 = require("react");
|
|
2219
|
+
|
|
2220
|
+
// src/hooks/usePlan.ts
|
|
2221
|
+
var import_sdk9 = require("@hook-sdk/sdk");
|
|
2222
|
+
function usePlan() {
|
|
2223
|
+
const { plan } = (0, import_sdk9.useHook)();
|
|
2224
|
+
return plan;
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
// src/utils/price.ts
|
|
2228
|
+
function formatBRL(cents) {
|
|
2229
|
+
if (cents === null || cents === void 0) return "";
|
|
2230
|
+
const reais = cents / 100;
|
|
2231
|
+
return new Intl.NumberFormat("pt-BR", {
|
|
2232
|
+
style: "currency",
|
|
2233
|
+
currency: "BRL"
|
|
2234
|
+
}).format(reais);
|
|
2235
|
+
}
|
|
2236
|
+
function monthlyFromYearly(yearlyCents) {
|
|
2237
|
+
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2238
|
+
return Math.round(yearlyCents / 12);
|
|
2239
|
+
}
|
|
2240
|
+
function dailyFromYearly(yearlyCents) {
|
|
2241
|
+
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2242
|
+
return Math.round(yearlyCents / 365);
|
|
2243
|
+
}
|
|
2244
|
+
function computeAnchorCents(baseCents, multiplier) {
|
|
2245
|
+
if (multiplier === null || multiplier === void 0) return null;
|
|
2246
|
+
if (!Number.isFinite(multiplier)) return null;
|
|
2247
|
+
if (multiplier <= 1) return null;
|
|
2248
|
+
return Math.round(baseCents * multiplier);
|
|
2249
|
+
}
|
|
2250
|
+
function discountPercent(anchorCents, realCents) {
|
|
2251
|
+
if (anchorCents <= realCents) return 0;
|
|
2252
|
+
return Math.floor((anchorCents - realCents) / anchorCents * 100);
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
// src/defaults/DefaultPaywall.tsx
|
|
2200
2256
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2201
2257
|
function DefaultPaywall() {
|
|
2202
2258
|
const config = useTemplateConfig();
|
|
2203
|
-
const
|
|
2259
|
+
const plan = usePlan();
|
|
2260
|
+
const {
|
|
2261
|
+
checkout,
|
|
2262
|
+
opening,
|
|
2263
|
+
error,
|
|
2264
|
+
availableMethods,
|
|
2265
|
+
monthlyEquivalent,
|
|
2266
|
+
pixPending,
|
|
2267
|
+
dismissPix
|
|
2268
|
+
} = usePaywallState();
|
|
2204
2269
|
const p = config.subscription.paywall_config;
|
|
2270
|
+
const paywallCfg = plan.data?.paywallConfig ?? {};
|
|
2271
|
+
const anchorMultiplier = paywallCfg.anchorMultiplier ?? p.anchorMultiplier;
|
|
2272
|
+
const anchorPriceCents = paywallCfg.anchorPriceCents ?? p.anchorPriceCents;
|
|
2273
|
+
const [cycle, setCycle] = (0, import_react14.useState)("MONTHLY");
|
|
2274
|
+
const [method, setMethod] = (0, import_react14.useState)("card");
|
|
2205
2275
|
const [cpf, setCpf] = (0, import_react14.useState)("");
|
|
2276
|
+
const [cardNumber, setCardNumber] = (0, import_react14.useState)("");
|
|
2277
|
+
const [cardHolderName, setCardHolderName] = (0, import_react14.useState)("");
|
|
2278
|
+
const [cardExpiryMonth, setCardExpiryMonth] = (0, import_react14.useState)("");
|
|
2279
|
+
const [cardExpiryYear, setCardExpiryYear] = (0, import_react14.useState)("");
|
|
2280
|
+
const [cardCcv, setCardCcv] = (0, import_react14.useState)("");
|
|
2281
|
+
const [holderName, setHolderName] = (0, import_react14.useState)("");
|
|
2282
|
+
const [holderEmail, setHolderEmail] = (0, import_react14.useState)("");
|
|
2283
|
+
const [holderPostalCode, setHolderPostalCode] = (0, import_react14.useState)("");
|
|
2284
|
+
const [holderAddressNumber, setHolderAddressNumber] = (0, import_react14.useState)("");
|
|
2285
|
+
const [holderPhone, setHolderPhone] = (0, import_react14.useState)("");
|
|
2286
|
+
const trialDays = plan.data?.trialDays ?? 0;
|
|
2287
|
+
const monthlyCents = plan.data?.priceCents ?? 0;
|
|
2288
|
+
const yearlyCents = plan.data?.yearlyPriceCents ?? null;
|
|
2289
|
+
const activeCents = cycle === "YEARLY" && yearlyCents ? monthlyEquivalent("YEARLY") : monthlyCents;
|
|
2290
|
+
const pct = (0, import_react14.useMemo)(() => {
|
|
2291
|
+
if (!yearlyCents || !monthlyCents) return 0;
|
|
2292
|
+
const derived = Math.round((1 - yearlyCents / 12 / monthlyCents) * 100);
|
|
2293
|
+
return Math.max(0, derived);
|
|
2294
|
+
}, [monthlyCents, yearlyCents]);
|
|
2295
|
+
const anchorBaseCents = cycle === "YEARLY" && yearlyCents ? monthlyFromYearly(yearlyCents) : monthlyCents;
|
|
2296
|
+
const anchorCents = computeAnchorCents(anchorBaseCents, anchorMultiplier) ?? (anchorPriceCents && anchorPriceCents > anchorBaseCents ? anchorPriceCents : null);
|
|
2297
|
+
const anchorDiscount = anchorCents ? discountPercent(anchorCents, activeCents) : 0;
|
|
2206
2298
|
const cpfDigits = cpf.replace(/\D/g, "");
|
|
2207
|
-
const
|
|
2208
|
-
|
|
2299
|
+
const cardFieldsFilled = cardNumber.replace(/\s/g, "").length >= 13 && cardHolderName.trim().length > 0 && cardExpiryMonth.length === 2 && cardExpiryYear.length >= 2 && cardCcv.length >= 3 && holderName.trim().length > 0 && /.+@.+\..+/.test(holderEmail) && holderPostalCode.replace(/\D/g, "").length === 8 && holderAddressNumber.trim().length > 0;
|
|
2300
|
+
const canCheckout = cpfDigits.length === 11 && !opening && (method === "pix-auto" || cardFieldsFilled);
|
|
2301
|
+
const ctaLabel = (0, import_react14.useMemo)(() => {
|
|
2302
|
+
if (opening) return "Abrindo\u2026";
|
|
2303
|
+
if (trialDays > 0) return `Comece trial de ${trialDays} dias gr\xE1tis`;
|
|
2304
|
+
return p.cta ?? "Assinar agora";
|
|
2305
|
+
}, [opening, trialDays, p.cta]);
|
|
2306
|
+
const footer = (0, import_react14.useMemo)(() => {
|
|
2307
|
+
if (trialDays > 0) {
|
|
2308
|
+
return `Sem cobran\xE7a agora. Cobran\xE7a autom\xE1tica em ${trialDays} dias. Cancele quando quiser.`;
|
|
2309
|
+
}
|
|
2310
|
+
return "Cobran\xE7a imediata. Cancele quando quiser.";
|
|
2311
|
+
}, [trialDays]);
|
|
2312
|
+
const yearSuffix = cardExpiryYear.length === 2 ? `20${cardExpiryYear}` : cardExpiryYear;
|
|
2313
|
+
const phoneDigits = holderPhone.replace(/\D/g, "");
|
|
2314
|
+
const postalDigits = holderPostalCode.replace(/\D/g, "");
|
|
2315
|
+
const submit = () => {
|
|
2316
|
+
if (method === "card") {
|
|
2317
|
+
void checkout({
|
|
2318
|
+
cpf: cpfDigits,
|
|
2319
|
+
cycle,
|
|
2320
|
+
method: "card",
|
|
2321
|
+
card: {
|
|
2322
|
+
number: cardNumber.replace(/\s/g, ""),
|
|
2323
|
+
holderName: cardHolderName.trim(),
|
|
2324
|
+
expiryMonth: cardExpiryMonth,
|
|
2325
|
+
expiryYear: yearSuffix,
|
|
2326
|
+
ccv: cardCcv
|
|
2327
|
+
},
|
|
2328
|
+
holderInfo: {
|
|
2329
|
+
name: holderName.trim(),
|
|
2330
|
+
email: holderEmail.trim(),
|
|
2331
|
+
cpfCnpj: cpfDigits,
|
|
2332
|
+
postalCode: postalDigits,
|
|
2333
|
+
addressNumber: holderAddressNumber.trim(),
|
|
2334
|
+
...phoneDigits ? { phone: phoneDigits } : {}
|
|
2335
|
+
}
|
|
2336
|
+
});
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
void checkout({ cpf: cpfDigits, cycle, method: "pix-auto" });
|
|
2340
|
+
};
|
|
2341
|
+
const inputStyle = {
|
|
2342
|
+
width: "100%",
|
|
2343
|
+
padding: 10,
|
|
2344
|
+
fontSize: 14,
|
|
2345
|
+
borderRadius: 8,
|
|
2346
|
+
border: "1px solid #ccc",
|
|
2347
|
+
boxSizing: "border-box"
|
|
2348
|
+
};
|
|
2349
|
+
const labelStyle = { display: "block", fontSize: 13, opacity: 0.75, marginBottom: 4 };
|
|
2350
|
+
const fieldGroup = { marginBottom: 10, textAlign: "left" };
|
|
2351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("main", { style: { padding: 24, maxWidth: 480, margin: "0 auto", textAlign: "center" }, children: [
|
|
2209
2352
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
|
|
2210
2353
|
p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
|
|
2211
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2355
|
+
"div",
|
|
2356
|
+
{
|
|
2357
|
+
role: "group",
|
|
2358
|
+
"aria-label": "Per\xEDodo de cobran\xE7a",
|
|
2359
|
+
style: { display: "flex", gap: 8, marginBottom: 16 },
|
|
2360
|
+
children: [
|
|
2361
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2362
|
+
"button",
|
|
2363
|
+
{
|
|
2364
|
+
type: "button",
|
|
2365
|
+
"aria-pressed": cycle === "MONTHLY",
|
|
2366
|
+
onClick: () => setCycle("MONTHLY"),
|
|
2367
|
+
style: {
|
|
2368
|
+
flex: 1,
|
|
2369
|
+
padding: 12,
|
|
2370
|
+
borderRadius: 8,
|
|
2371
|
+
border: cycle === "MONTHLY" ? "2px solid var(--hook-color-primary)" : "1px solid #ccc",
|
|
2372
|
+
background: cycle === "MONTHLY" ? "var(--hook-color-primary-soft, #eef)" : "white",
|
|
2373
|
+
cursor: "pointer"
|
|
2374
|
+
},
|
|
2375
|
+
children: "Mensal"
|
|
2376
|
+
}
|
|
2377
|
+
),
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2379
|
+
"button",
|
|
2380
|
+
{
|
|
2381
|
+
type: "button",
|
|
2382
|
+
"aria-pressed": cycle === "YEARLY",
|
|
2383
|
+
onClick: () => setCycle("YEARLY"),
|
|
2384
|
+
disabled: !yearlyCents,
|
|
2385
|
+
style: {
|
|
2386
|
+
flex: 1,
|
|
2387
|
+
padding: 12,
|
|
2388
|
+
borderRadius: 8,
|
|
2389
|
+
border: cycle === "YEARLY" ? "2px solid var(--hook-color-primary)" : "1px solid #ccc",
|
|
2390
|
+
background: cycle === "YEARLY" ? "var(--hook-color-primary-soft, #eef)" : "white",
|
|
2391
|
+
cursor: yearlyCents ? "pointer" : "not-allowed",
|
|
2392
|
+
opacity: yearlyCents ? 1 : 0.5
|
|
2393
|
+
},
|
|
2394
|
+
children: [
|
|
2395
|
+
"Anual",
|
|
2396
|
+
pct > 0 ? ` \u2212${pct}%` : ""
|
|
2397
|
+
]
|
|
2398
|
+
}
|
|
2399
|
+
)
|
|
2400
|
+
]
|
|
2401
|
+
}
|
|
2402
|
+
),
|
|
2403
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { marginBottom: 8 }, children: [
|
|
2404
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 32, fontWeight: 700, lineHeight: 1 }, children: [
|
|
2405
|
+
formatBRL(activeCents),
|
|
2406
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 16, fontWeight: 400, opacity: 0.7 }, children: "/m\xEAs" })
|
|
2407
|
+
] }),
|
|
2408
|
+
anchorCents && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 14, opacity: 0.6, marginTop: 4 }, children: [
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { textDecoration: "line-through" }, children: formatBRL(anchorCents) }),
|
|
2410
|
+
anchorDiscount > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { marginLeft: 6 }, children: [
|
|
2411
|
+
"\u2212",
|
|
2412
|
+
anchorDiscount,
|
|
2413
|
+
"%"
|
|
2414
|
+
] })
|
|
2415
|
+
] }),
|
|
2416
|
+
cycle === "YEARLY" && yearlyCents && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 12, opacity: 0.6, marginTop: 4 }, children: [
|
|
2417
|
+
"Cobrado ",
|
|
2418
|
+
formatBRL(yearlyCents),
|
|
2419
|
+
" por ano"
|
|
2420
|
+
] })
|
|
2421
|
+
] }),
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", margin: "24px 0" }, children: p.benefits.map((b) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
|
|
2212
2423
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
|
|
2213
2424
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: b })
|
|
2214
2425
|
] }, b)) }),
|
|
2215
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.
|
|
2216
|
-
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "tablist", "aria-label": "M\xE9todo de pagamento", style: { display: "flex", gap: 8, marginBottom: 16 }, children: availableMethods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2427
|
+
"button",
|
|
2428
|
+
{
|
|
2429
|
+
type: "button",
|
|
2430
|
+
role: "tab",
|
|
2431
|
+
"aria-selected": method === m,
|
|
2432
|
+
onClick: () => setMethod(m),
|
|
2433
|
+
style: {
|
|
2434
|
+
flex: 1,
|
|
2435
|
+
padding: 10,
|
|
2436
|
+
borderRadius: 8,
|
|
2437
|
+
border: method === m ? "2px solid var(--hook-color-primary)" : "1px solid #ccc",
|
|
2438
|
+
background: method === m ? "var(--hook-color-primary-soft, #eef)" : "white",
|
|
2439
|
+
cursor: "pointer"
|
|
2440
|
+
},
|
|
2441
|
+
children: m === "card" ? "\u{1F4B3} Cart\xE3o" : "\u{1F4F1} Pix Autom\xE1tico"
|
|
2442
|
+
},
|
|
2443
|
+
m
|
|
2444
|
+
)) }),
|
|
2445
|
+
method === "card" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2446
|
+
"fieldset",
|
|
2447
|
+
{
|
|
2448
|
+
"data-testid": "paywall-card-form",
|
|
2449
|
+
style: { border: "none", padding: 0, marginBottom: 16 },
|
|
2450
|
+
children: [
|
|
2451
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("legend", { style: { fontSize: 13, opacity: 0.75, marginBottom: 8 }, children: "Dados do cart\xE3o" }),
|
|
2452
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-card-number", style: labelStyle, children: "N\xFAmero do cart\xE3o" }),
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2455
|
+
"input",
|
|
2456
|
+
{
|
|
2457
|
+
id: "pw-card-number",
|
|
2458
|
+
"data-testid": "pw-card-number",
|
|
2459
|
+
type: "text",
|
|
2460
|
+
inputMode: "numeric",
|
|
2461
|
+
autoComplete: "cc-number",
|
|
2462
|
+
placeholder: "0000 0000 0000 0000",
|
|
2463
|
+
value: cardNumber,
|
|
2464
|
+
onChange: (e) => setCardNumber(e.target.value),
|
|
2465
|
+
style: inputStyle
|
|
2466
|
+
}
|
|
2467
|
+
)
|
|
2468
|
+
] }),
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-card-holder", style: labelStyle, children: "Nome impresso no cart\xE3o" }),
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2472
|
+
"input",
|
|
2473
|
+
{
|
|
2474
|
+
id: "pw-card-holder",
|
|
2475
|
+
"data-testid": "pw-card-holder",
|
|
2476
|
+
type: "text",
|
|
2477
|
+
autoComplete: "cc-name",
|
|
2478
|
+
placeholder: "NOME SOBRENOME",
|
|
2479
|
+
value: cardHolderName,
|
|
2480
|
+
onChange: (e) => setCardHolderName(e.target.value),
|
|
2481
|
+
style: inputStyle
|
|
2482
|
+
}
|
|
2483
|
+
)
|
|
2484
|
+
] }),
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 8, marginBottom: 10 }, children: [
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, textAlign: "left" }, children: [
|
|
2487
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-card-exp-m", style: labelStyle, children: "M\xEAs" }),
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2489
|
+
"input",
|
|
2490
|
+
{
|
|
2491
|
+
id: "pw-card-exp-m",
|
|
2492
|
+
"data-testid": "pw-card-exp-m",
|
|
2493
|
+
type: "text",
|
|
2494
|
+
inputMode: "numeric",
|
|
2495
|
+
autoComplete: "cc-exp-month",
|
|
2496
|
+
placeholder: "MM",
|
|
2497
|
+
maxLength: 2,
|
|
2498
|
+
value: cardExpiryMonth,
|
|
2499
|
+
onChange: (e) => setCardExpiryMonth(e.target.value.replace(/\D/g, "")),
|
|
2500
|
+
style: inputStyle
|
|
2501
|
+
}
|
|
2502
|
+
)
|
|
2503
|
+
] }),
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, textAlign: "left" }, children: [
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-card-exp-y", style: labelStyle, children: "Ano" }),
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2507
|
+
"input",
|
|
2508
|
+
{
|
|
2509
|
+
id: "pw-card-exp-y",
|
|
2510
|
+
"data-testid": "pw-card-exp-y",
|
|
2511
|
+
type: "text",
|
|
2512
|
+
inputMode: "numeric",
|
|
2513
|
+
autoComplete: "cc-exp-year",
|
|
2514
|
+
placeholder: "AA",
|
|
2515
|
+
maxLength: 4,
|
|
2516
|
+
value: cardExpiryYear,
|
|
2517
|
+
onChange: (e) => setCardExpiryYear(e.target.value.replace(/\D/g, "")),
|
|
2518
|
+
style: inputStyle
|
|
2519
|
+
}
|
|
2520
|
+
)
|
|
2521
|
+
] }),
|
|
2522
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, textAlign: "left" }, children: [
|
|
2523
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-card-cvv", style: labelStyle, children: "CVV" }),
|
|
2524
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2525
|
+
"input",
|
|
2526
|
+
{
|
|
2527
|
+
id: "pw-card-cvv",
|
|
2528
|
+
"data-testid": "pw-card-cvv",
|
|
2529
|
+
type: "text",
|
|
2530
|
+
inputMode: "numeric",
|
|
2531
|
+
autoComplete: "cc-csc",
|
|
2532
|
+
placeholder: "123",
|
|
2533
|
+
maxLength: 4,
|
|
2534
|
+
value: cardCcv,
|
|
2535
|
+
onChange: (e) => setCardCcv(e.target.value.replace(/\D/g, "")),
|
|
2536
|
+
style: inputStyle
|
|
2537
|
+
}
|
|
2538
|
+
)
|
|
2539
|
+
] })
|
|
2540
|
+
] }),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("legend", { style: { fontSize: 13, opacity: 0.75, marginBottom: 8, marginTop: 8 }, children: "Dados do titular" }),
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2543
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-holder-name", style: labelStyle, children: "Nome completo" }),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2545
|
+
"input",
|
|
2546
|
+
{
|
|
2547
|
+
id: "pw-holder-name",
|
|
2548
|
+
"data-testid": "pw-holder-name",
|
|
2549
|
+
type: "text",
|
|
2550
|
+
autoComplete: "name",
|
|
2551
|
+
placeholder: "Nome Sobrenome",
|
|
2552
|
+
value: holderName,
|
|
2553
|
+
onChange: (e) => setHolderName(e.target.value),
|
|
2554
|
+
style: inputStyle
|
|
2555
|
+
}
|
|
2556
|
+
)
|
|
2557
|
+
] }),
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-holder-email", style: labelStyle, children: "E-mail" }),
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2561
|
+
"input",
|
|
2562
|
+
{
|
|
2563
|
+
id: "pw-holder-email",
|
|
2564
|
+
"data-testid": "pw-holder-email",
|
|
2565
|
+
type: "email",
|
|
2566
|
+
autoComplete: "email",
|
|
2567
|
+
placeholder: "voce@email.com",
|
|
2568
|
+
value: holderEmail,
|
|
2569
|
+
onChange: (e) => setHolderEmail(e.target.value),
|
|
2570
|
+
style: inputStyle
|
|
2571
|
+
}
|
|
2572
|
+
)
|
|
2573
|
+
] }),
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 8, marginBottom: 10 }, children: [
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, textAlign: "left" }, children: [
|
|
2576
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-holder-cep", style: labelStyle, children: "CEP" }),
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2578
|
+
"input",
|
|
2579
|
+
{
|
|
2580
|
+
id: "pw-holder-cep",
|
|
2581
|
+
"data-testid": "pw-holder-cep",
|
|
2582
|
+
type: "text",
|
|
2583
|
+
inputMode: "numeric",
|
|
2584
|
+
autoComplete: "postal-code",
|
|
2585
|
+
placeholder: "00000-000",
|
|
2586
|
+
value: holderPostalCode,
|
|
2587
|
+
onChange: (e) => setHolderPostalCode(e.target.value),
|
|
2588
|
+
style: inputStyle
|
|
2589
|
+
}
|
|
2590
|
+
)
|
|
2591
|
+
] }),
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, textAlign: "left" }, children: [
|
|
2593
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-holder-addr-n", style: labelStyle, children: "N\xFAmero" }),
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2595
|
+
"input",
|
|
2596
|
+
{
|
|
2597
|
+
id: "pw-holder-addr-n",
|
|
2598
|
+
"data-testid": "pw-holder-addr-n",
|
|
2599
|
+
type: "text",
|
|
2600
|
+
inputMode: "numeric",
|
|
2601
|
+
placeholder: "123",
|
|
2602
|
+
value: holderAddressNumber,
|
|
2603
|
+
onChange: (e) => setHolderAddressNumber(e.target.value),
|
|
2604
|
+
style: inputStyle
|
|
2605
|
+
}
|
|
2606
|
+
)
|
|
2607
|
+
] })
|
|
2608
|
+
] }),
|
|
2609
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-holder-phone", style: labelStyle, children: "Telefone (opcional)" }),
|
|
2611
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2612
|
+
"input",
|
|
2613
|
+
{
|
|
2614
|
+
id: "pw-holder-phone",
|
|
2615
|
+
"data-testid": "pw-holder-phone",
|
|
2616
|
+
type: "tel",
|
|
2617
|
+
inputMode: "tel",
|
|
2618
|
+
autoComplete: "tel",
|
|
2619
|
+
placeholder: "(11) 99999-9999",
|
|
2620
|
+
value: holderPhone,
|
|
2621
|
+
onChange: (e) => setHolderPhone(e.target.value),
|
|
2622
|
+
style: inputStyle
|
|
2623
|
+
}
|
|
2624
|
+
)
|
|
2625
|
+
] })
|
|
2626
|
+
]
|
|
2627
|
+
}
|
|
2628
|
+
),
|
|
2629
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: fieldGroup, children: [
|
|
2630
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "pw-cpf", style: labelStyle, children: "Seu CPF" }),
|
|
2217
2631
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2218
2632
|
"input",
|
|
2219
2633
|
{
|
|
2634
|
+
id: "pw-cpf",
|
|
2220
2635
|
"data-testid": "paywall-cpf",
|
|
2221
2636
|
type: "text",
|
|
2222
2637
|
inputMode: "numeric",
|
|
2223
2638
|
placeholder: "000.000.000-00",
|
|
2224
2639
|
value: cpf,
|
|
2225
2640
|
onChange: (e) => setCpf(e.target.value),
|
|
2226
|
-
style:
|
|
2641
|
+
style: inputStyle
|
|
2227
2642
|
}
|
|
2228
2643
|
)
|
|
2229
2644
|
] }),
|
|
@@ -2233,7 +2648,7 @@ function DefaultPaywall() {
|
|
|
2233
2648
|
{
|
|
2234
2649
|
"data-testid": "paywall-cta",
|
|
2235
2650
|
type: "button",
|
|
2236
|
-
onClick:
|
|
2651
|
+
onClick: submit,
|
|
2237
2652
|
disabled: !canCheckout,
|
|
2238
2653
|
style: {
|
|
2239
2654
|
width: "100%",
|
|
@@ -2244,13 +2659,93 @@ function DefaultPaywall() {
|
|
|
2244
2659
|
borderRadius: 8,
|
|
2245
2660
|
opacity: canCheckout ? 1 : 0.5,
|
|
2246
2661
|
fontSize: 16,
|
|
2247
|
-
fontWeight: 600
|
|
2662
|
+
fontWeight: 600,
|
|
2663
|
+
cursor: canCheckout ? "pointer" : "not-allowed"
|
|
2248
2664
|
},
|
|
2249
|
-
children:
|
|
2665
|
+
children: ctaLabel
|
|
2250
2666
|
}
|
|
2251
2667
|
),
|
|
2252
|
-
|
|
2253
|
-
p.
|
|
2668
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.55, marginTop: 16, fontSize: 12 }, children: footer }),
|
|
2669
|
+
p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.6, marginTop: 8, fontSize: 12 }, children: p.priceHint }),
|
|
2670
|
+
p.footerNote && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.5, marginTop: 8, fontSize: 12 }, children: p.footerNote }),
|
|
2671
|
+
pixPending && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2672
|
+
"div",
|
|
2673
|
+
{
|
|
2674
|
+
"data-testid": "paywall-pix-modal",
|
|
2675
|
+
role: "dialog",
|
|
2676
|
+
"aria-label": "Pagamento Pix pendente",
|
|
2677
|
+
style: {
|
|
2678
|
+
position: "fixed",
|
|
2679
|
+
inset: 0,
|
|
2680
|
+
background: "rgba(0,0,0,0.6)",
|
|
2681
|
+
display: "flex",
|
|
2682
|
+
alignItems: "center",
|
|
2683
|
+
justifyContent: "center",
|
|
2684
|
+
padding: 24,
|
|
2685
|
+
zIndex: 1e3
|
|
2686
|
+
},
|
|
2687
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: {
|
|
2688
|
+
background: "#fff",
|
|
2689
|
+
borderRadius: 12,
|
|
2690
|
+
padding: 24,
|
|
2691
|
+
maxWidth: 360,
|
|
2692
|
+
width: "100%",
|
|
2693
|
+
textAlign: "center"
|
|
2694
|
+
}, children: [
|
|
2695
|
+
pixPending.paid ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { style: { marginTop: 0 }, children: "Pagamento confirmado!" }),
|
|
2697
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.7 }, children: "Liberando acesso\u2026" })
|
|
2698
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
2699
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { style: { marginTop: 0, fontSize: 18 }, children: "Pague com Pix Autom\xE1tico" }),
|
|
2700
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { fontSize: 13, opacity: 0.75 }, children: "Escaneie o QR Code no app do seu banco pra autorizar o d\xE9bito recorrente." }),
|
|
2701
|
+
pixPending.qrCodeBase64 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2702
|
+
"img",
|
|
2703
|
+
{
|
|
2704
|
+
"data-testid": "pix-qr-image",
|
|
2705
|
+
alt: "QR Code Pix",
|
|
2706
|
+
src: `data:image/png;base64,${pixPending.qrCodeBase64}`,
|
|
2707
|
+
style: { width: "100%", maxWidth: 240, margin: "12px auto", display: "block" }
|
|
2708
|
+
}
|
|
2709
|
+
),
|
|
2710
|
+
pixPending.qrCodePayload && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2711
|
+
"textarea",
|
|
2712
|
+
{
|
|
2713
|
+
"data-testid": "pix-qr-payload",
|
|
2714
|
+
readOnly: true,
|
|
2715
|
+
value: pixPending.qrCodePayload,
|
|
2716
|
+
style: {
|
|
2717
|
+
width: "100%",
|
|
2718
|
+
minHeight: 72,
|
|
2719
|
+
padding: 8,
|
|
2720
|
+
fontSize: 11,
|
|
2721
|
+
fontFamily: "monospace",
|
|
2722
|
+
borderRadius: 6,
|
|
2723
|
+
border: "1px solid #ccc",
|
|
2724
|
+
resize: "none"
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
),
|
|
2728
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { fontSize: 11, opacity: 0.55, marginTop: 12 }, children: "Aguardando confirma\xE7\xE3o do banco\u2026 Pode levar alguns segundos." })
|
|
2729
|
+
] }),
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2731
|
+
"button",
|
|
2732
|
+
{
|
|
2733
|
+
type: "button",
|
|
2734
|
+
onClick: dismissPix,
|
|
2735
|
+
style: {
|
|
2736
|
+
marginTop: 16,
|
|
2737
|
+
padding: "8px 16px",
|
|
2738
|
+
border: "1px solid #ccc",
|
|
2739
|
+
borderRadius: 6,
|
|
2740
|
+
background: "white",
|
|
2741
|
+
cursor: "pointer"
|
|
2742
|
+
},
|
|
2743
|
+
children: "Fechar"
|
|
2744
|
+
}
|
|
2745
|
+
)
|
|
2746
|
+
] })
|
|
2747
|
+
}
|
|
2748
|
+
)
|
|
2254
2749
|
] });
|
|
2255
2750
|
}
|
|
2256
2751
|
|
|
@@ -2258,7 +2753,7 @@ function DefaultPaywall() {
|
|
|
2258
2753
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2259
2754
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
2260
2755
|
function PaymentReturnHandler({ children }) {
|
|
2261
|
-
const { subscription } = (0,
|
|
2756
|
+
const { subscription } = (0, import_sdk10.useHook)();
|
|
2262
2757
|
const subRef = (0, import_react15.useRef)(subscription);
|
|
2263
2758
|
subRef.current = subscription;
|
|
2264
2759
|
const runIdRef = (0, import_react15.useRef)(0);
|
|
@@ -2367,7 +2862,7 @@ function AppRoot({
|
|
|
2367
2862
|
|
|
2368
2863
|
// src/hooks/usePush.ts
|
|
2369
2864
|
var import_react16 = require("react");
|
|
2370
|
-
var
|
|
2865
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2371
2866
|
function detectIosNeedsInstall() {
|
|
2372
2867
|
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
2373
2868
|
const ua = navigator.userAgent || "";
|
|
@@ -2393,7 +2888,7 @@ function deriveState(push) {
|
|
|
2393
2888
|
return { kind: "prompt" };
|
|
2394
2889
|
}
|
|
2395
2890
|
function usePush() {
|
|
2396
|
-
const { push } = (0,
|
|
2891
|
+
const { push } = (0, import_sdk11.useHook)();
|
|
2397
2892
|
const [state, setState] = (0, import_react16.useState)(() => deriveState(push));
|
|
2398
2893
|
(0, import_react16.useEffect)(() => {
|
|
2399
2894
|
setState(deriveState(push));
|
|
@@ -2475,41 +2970,6 @@ function EmptyState({ title, description, action }) {
|
|
|
2475
2970
|
] });
|
|
2476
2971
|
}
|
|
2477
2972
|
|
|
2478
|
-
// src/hooks/usePlan.ts
|
|
2479
|
-
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2480
|
-
function usePlan() {
|
|
2481
|
-
const { plan } = (0, import_sdk11.useHook)();
|
|
2482
|
-
return plan;
|
|
2483
|
-
}
|
|
2484
|
-
|
|
2485
|
-
// src/utils/price.ts
|
|
2486
|
-
function formatBRL(cents) {
|
|
2487
|
-
if (cents === null || cents === void 0) return "";
|
|
2488
|
-
const reais = cents / 100;
|
|
2489
|
-
return new Intl.NumberFormat("pt-BR", {
|
|
2490
|
-
style: "currency",
|
|
2491
|
-
currency: "BRL"
|
|
2492
|
-
}).format(reais);
|
|
2493
|
-
}
|
|
2494
|
-
function monthlyFromYearly(yearlyCents) {
|
|
2495
|
-
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2496
|
-
return Math.round(yearlyCents / 12);
|
|
2497
|
-
}
|
|
2498
|
-
function dailyFromYearly(yearlyCents) {
|
|
2499
|
-
if (yearlyCents === null || yearlyCents === void 0) return 0;
|
|
2500
|
-
return Math.round(yearlyCents / 365);
|
|
2501
|
-
}
|
|
2502
|
-
function computeAnchorCents(baseCents, multiplier) {
|
|
2503
|
-
if (multiplier === null || multiplier === void 0) return null;
|
|
2504
|
-
if (!Number.isFinite(multiplier)) return null;
|
|
2505
|
-
if (multiplier <= 1) return null;
|
|
2506
|
-
return Math.round(baseCents * multiplier);
|
|
2507
|
-
}
|
|
2508
|
-
function discountPercent(anchorCents, realCents) {
|
|
2509
|
-
if (anchorCents <= realCents) return 0;
|
|
2510
|
-
return Math.floor((anchorCents - realCents) / anchorCents * 100);
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
2973
|
// src/hooks/useAuthPrimitives.ts
|
|
2514
2974
|
var import_react17 = require("react");
|
|
2515
2975
|
var import_sdk12 = require("@hook-sdk/sdk");
|