@hook-sdk/template 0.14.0 → 0.15.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 +444 -328
- 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 +303 -187
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -69,9 +69,9 @@ __export(index_exports, {
|
|
|
69
69
|
module.exports = __toCommonJS(index_exports);
|
|
70
70
|
|
|
71
71
|
// src/AppRoot.tsx
|
|
72
|
-
var
|
|
72
|
+
var import_react13 = require("react");
|
|
73
73
|
var import_react_router_dom2 = require("react-router-dom");
|
|
74
|
-
var
|
|
74
|
+
var import_sdk6 = require("@hook-sdk/sdk");
|
|
75
75
|
|
|
76
76
|
// src/config/AppConfigContext.tsx
|
|
77
77
|
var import_react = require("react");
|
|
@@ -147,7 +147,11 @@ var DeepLinksSchema = import_zod.z.object({
|
|
|
147
147
|
var AppConfigSchema = import_zod.z.object({
|
|
148
148
|
slug: import_zod.z.string().regex(/^[a-z0-9-]+$/),
|
|
149
149
|
name: import_zod.z.string().min(1),
|
|
150
|
-
branding: import_zod.z.object({
|
|
150
|
+
branding: import_zod.z.object({
|
|
151
|
+
primaryColor: import_zod.z.string(),
|
|
152
|
+
logoUrl: import_zod.z.string().url(),
|
|
153
|
+
iconUrl: import_zod.z.string().url().optional()
|
|
154
|
+
}),
|
|
151
155
|
authFlow: AuthFlowSchema,
|
|
152
156
|
paywall: PaywallSchema,
|
|
153
157
|
persistedKeys: import_zod.z.array(PersistedKeySchema),
|
|
@@ -244,8 +248,8 @@ function ThemeProvider({ children }) {
|
|
|
244
248
|
}
|
|
245
249
|
|
|
246
250
|
// src/hooks/usePaywallState.ts
|
|
247
|
-
var
|
|
248
|
-
var
|
|
251
|
+
var import_react6 = require("react");
|
|
252
|
+
var import_sdk3 = require("@hook-sdk/sdk");
|
|
249
253
|
|
|
250
254
|
// src/errors/asaas-pt-br.ts
|
|
251
255
|
var MAP = {
|
|
@@ -266,6 +270,35 @@ function asaasErrorMessage(code) {
|
|
|
266
270
|
return MAP[code] ?? "Ocorreu um erro inesperado. Tente novamente em instantes.";
|
|
267
271
|
}
|
|
268
272
|
|
|
273
|
+
// src/hooks/usePaywallTracker.ts
|
|
274
|
+
var import_react5 = require("react");
|
|
275
|
+
var import_sdk2 = require("@hook-sdk/sdk");
|
|
276
|
+
function deriveStep(s) {
|
|
277
|
+
if (s.pixPaid) return "success";
|
|
278
|
+
if (s.hasError) return "error";
|
|
279
|
+
if (s.pixPendingShown) return "pix_qr_shown";
|
|
280
|
+
if (s.selectedMethod === "card" && s.cpfValid) return "card_form";
|
|
281
|
+
if (s.cpfRequired && !s.cpfValid) return "cpf_input";
|
|
282
|
+
if (s.selectedMethod) return "method_select";
|
|
283
|
+
return "plan_select";
|
|
284
|
+
}
|
|
285
|
+
function usePaywallTracker(snapshot) {
|
|
286
|
+
const ctx = (0, import_sdk2.useHook)();
|
|
287
|
+
const track2 = typeof ctx.track === "function" ? ctx.track : void 0;
|
|
288
|
+
const lastStepRef = (0, import_react5.useRef)(null);
|
|
289
|
+
const step = deriveStep(snapshot);
|
|
290
|
+
(0, import_react5.useEffect)(() => {
|
|
291
|
+
if (lastStepRef.current === step) return;
|
|
292
|
+
lastStepRef.current = step;
|
|
293
|
+
if (!track2) return;
|
|
294
|
+
track2("paywall_step_viewed", {
|
|
295
|
+
step,
|
|
296
|
+
method: snapshot.selectedMethod,
|
|
297
|
+
cycle: snapshot.cycle
|
|
298
|
+
});
|
|
299
|
+
}, [step]);
|
|
300
|
+
}
|
|
301
|
+
|
|
269
302
|
// src/hooks/usePaywallState.ts
|
|
270
303
|
function isCheckoutFailure(r) {
|
|
271
304
|
return "ok" in r && r.ok === false;
|
|
@@ -280,11 +313,11 @@ var FALLBACK_PAYWALL = {
|
|
|
280
313
|
};
|
|
281
314
|
var isMethodAvailable = (availability, method) => availability[method] !== false;
|
|
282
315
|
function usePaywallState() {
|
|
283
|
-
const { subscription, plan } = (0,
|
|
284
|
-
const configFromCtx = (0,
|
|
316
|
+
const { subscription, plan } = (0, import_sdk3.useHook)();
|
|
317
|
+
const configFromCtx = (0, import_react6.useContext)(AppConfigContext);
|
|
285
318
|
const paywall = configFromCtx?.paywall ?? FALLBACK_PAYWALL;
|
|
286
319
|
const isFree = paywall.mode === "free";
|
|
287
|
-
const declaredMethods = (0,
|
|
320
|
+
const declaredMethods = (0, import_react6.useMemo)(
|
|
288
321
|
() => isFree ? [] : paywall.checkoutMethods,
|
|
289
322
|
[isFree, paywall]
|
|
290
323
|
);
|
|
@@ -293,33 +326,33 @@ function usePaywallState() {
|
|
|
293
326
|
"pix-auto": null,
|
|
294
327
|
"pix-once": null
|
|
295
328
|
};
|
|
296
|
-
const methods = (0,
|
|
329
|
+
const methods = (0, import_react6.useMemo)(
|
|
297
330
|
() => declaredMethods.filter((m) => isMethodAvailable(availability, m)),
|
|
298
331
|
[declaredMethods, availability]
|
|
299
332
|
);
|
|
300
333
|
const defaultMethod = methods[0] ?? declaredMethods[0] ?? "card";
|
|
301
|
-
const [selectedMethodRaw, setSelectedMethod] = (0,
|
|
334
|
+
const [selectedMethodRaw, setSelectedMethod] = (0, import_react6.useState)(defaultMethod);
|
|
302
335
|
const selectedMethod = methods.includes(selectedMethodRaw) ? selectedMethodRaw : methods[0] ?? selectedMethodRaw;
|
|
303
336
|
const initialCycle = isFree ? "MONTHLY" : paywall.cycles[0] ?? "MONTHLY";
|
|
304
|
-
const [cycle, setCycle] = (0,
|
|
337
|
+
const [cycle, setCycle] = (0, import_react6.useState)(initialCycle);
|
|
305
338
|
const cpfRequired = !isFree && paywall.requiresCpf;
|
|
306
|
-
const [cpf, setCpf] = (0,
|
|
307
|
-
const cpfValid = (0,
|
|
308
|
-
const [card, setCardState] = (0,
|
|
339
|
+
const [cpf, setCpf] = (0, import_react6.useState)("");
|
|
340
|
+
const cpfValid = (0, import_react6.useMemo)(() => /^[0-9]{11}$/.test(cpf), [cpf]);
|
|
341
|
+
const [card, setCardState] = (0, import_react6.useState)({
|
|
309
342
|
number: "",
|
|
310
343
|
cvv: "",
|
|
311
344
|
expiry: "",
|
|
312
345
|
holder: ""
|
|
313
346
|
});
|
|
314
|
-
const setCard = (0,
|
|
347
|
+
const setCard = (0, import_react6.useCallback)((patch) => {
|
|
315
348
|
setCardState((prev) => ({ ...prev, ...patch }));
|
|
316
349
|
}, []);
|
|
317
|
-
const [error, setError] = (0,
|
|
318
|
-
const [submitting, setSubmitting] = (0,
|
|
350
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
351
|
+
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
319
352
|
const status = subscription.status();
|
|
320
353
|
const daysLeftInTrial = subscription.daysLeftInTrial();
|
|
321
354
|
const initialLoadComplete = subscription.initialLoadComplete;
|
|
322
|
-
const pixPending = (0,
|
|
355
|
+
const pixPending = (0, import_react6.useMemo)(() => {
|
|
323
356
|
const sdkPix = subscription.pixPending;
|
|
324
357
|
if (!sdkPix) return null;
|
|
325
358
|
const liveStatus = subscription.current?.status;
|
|
@@ -332,7 +365,7 @@ function usePaywallState() {
|
|
|
332
365
|
paid
|
|
333
366
|
};
|
|
334
367
|
}, [subscription.pixPending, subscription.current]);
|
|
335
|
-
const monthlyEquivalent = (0,
|
|
368
|
+
const monthlyEquivalent = (0, import_react6.useCallback)(
|
|
336
369
|
(c) => {
|
|
337
370
|
const monthlyCents = plan.data?.priceCents ?? (isFree ? 0 : paywall.prices.monthlyCents);
|
|
338
371
|
const yearlyCents = plan.data?.yearlyPriceCents ?? (isFree ? null : paywall.prices.yearlyCents);
|
|
@@ -341,7 +374,7 @@ function usePaywallState() {
|
|
|
341
374
|
},
|
|
342
375
|
[plan, paywall, isFree]
|
|
343
376
|
);
|
|
344
|
-
const planDerived = (0,
|
|
377
|
+
const planDerived = (0, import_react6.useMemo)(() => {
|
|
345
378
|
if (isFree) return null;
|
|
346
379
|
const monthlyCents = paywall.prices.monthlyCents;
|
|
347
380
|
const yearlyCents = paywall.prices.yearlyCents;
|
|
@@ -357,7 +390,7 @@ function usePaywallState() {
|
|
|
357
390
|
};
|
|
358
391
|
}, [paywall, cycle, isFree]);
|
|
359
392
|
const useDefaultMessages = paywall.mode !== "free" && paywall.errorMessages === "default";
|
|
360
|
-
const buildError = (0,
|
|
393
|
+
const buildError = (0, import_react6.useCallback)(
|
|
361
394
|
(code, fallbackMessage) => ({
|
|
362
395
|
code,
|
|
363
396
|
message: fallbackMessage,
|
|
@@ -365,7 +398,7 @@ function usePaywallState() {
|
|
|
365
398
|
}),
|
|
366
399
|
[useDefaultMessages]
|
|
367
400
|
);
|
|
368
|
-
const submit = (0,
|
|
401
|
+
const submit = (0, import_react6.useCallback)(async () => {
|
|
369
402
|
setSubmitting(true);
|
|
370
403
|
setError(null);
|
|
371
404
|
const methodToUse = selectedMethod;
|
|
@@ -427,7 +460,7 @@ function usePaywallState() {
|
|
|
427
460
|
return void 0;
|
|
428
461
|
}
|
|
429
462
|
}, [selectedMethod, availability, subscription, cycle, cpf, card, buildError]);
|
|
430
|
-
const checkout = (0,
|
|
463
|
+
const checkout = (0, import_react6.useCallback)(
|
|
431
464
|
async (args) => {
|
|
432
465
|
setSubmitting(true);
|
|
433
466
|
setError(null);
|
|
@@ -491,7 +524,7 @@ function usePaywallState() {
|
|
|
491
524
|
},
|
|
492
525
|
[subscription, buildError]
|
|
493
526
|
);
|
|
494
|
-
const cancel = (0,
|
|
527
|
+
const cancel = (0, import_react6.useCallback)(async () => {
|
|
495
528
|
try {
|
|
496
529
|
await subscription.cancel();
|
|
497
530
|
await subscription.refresh();
|
|
@@ -501,14 +534,24 @@ function usePaywallState() {
|
|
|
501
534
|
setError(buildError(code, message));
|
|
502
535
|
}
|
|
503
536
|
}, [subscription, buildError]);
|
|
504
|
-
const cardState = (0,
|
|
537
|
+
const cardState = (0, import_react6.useMemo)(
|
|
505
538
|
() => ({ ...card, set: setCard }),
|
|
506
539
|
[card, setCard]
|
|
507
540
|
);
|
|
508
|
-
const cpfState = (0,
|
|
541
|
+
const cpfState = (0, import_react6.useMemo)(
|
|
509
542
|
() => ({ required: cpfRequired, value: cpf, set: setCpf, valid: cpfValid }),
|
|
510
543
|
[cpfRequired, cpf, cpfValid]
|
|
511
544
|
);
|
|
545
|
+
usePaywallTracker({
|
|
546
|
+
selectedMethod,
|
|
547
|
+
cycle,
|
|
548
|
+
cpfRequired,
|
|
549
|
+
cpfValid,
|
|
550
|
+
pixPendingShown: pixPending !== null,
|
|
551
|
+
pixPaid: pixPending?.paid === true,
|
|
552
|
+
hasError: error !== null,
|
|
553
|
+
submitting
|
|
554
|
+
});
|
|
512
555
|
return {
|
|
513
556
|
// Subscription status (reactive, proxied from SDK)
|
|
514
557
|
status,
|
|
@@ -563,10 +606,11 @@ function SubscriptionGate({ Paywall, children }) {
|
|
|
563
606
|
}
|
|
564
607
|
|
|
565
608
|
// src/components/InstallGate/InstallGate.tsx
|
|
566
|
-
var
|
|
609
|
+
var import_react9 = require("react");
|
|
567
610
|
|
|
568
611
|
// src/hooks/useInstallPrompt.ts
|
|
569
|
-
var
|
|
612
|
+
var import_react7 = require("react");
|
|
613
|
+
var ANDROID_PROMPT_WAIT_MS = 3e3;
|
|
570
614
|
var IOS_RE = /iPad|iPhone|iPod/;
|
|
571
615
|
var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
|
|
572
616
|
var ANDROID_RE = /Android/;
|
|
@@ -636,11 +680,12 @@ function track(event, props) {
|
|
|
636
680
|
if (typeof window === "undefined") return;
|
|
637
681
|
window.posthog?.capture?.(event, props);
|
|
638
682
|
}
|
|
639
|
-
function pickVariant(state) {
|
|
683
|
+
function pickVariant(state, promptWaitElapsed) {
|
|
640
684
|
if (state.isInstalled) return "none";
|
|
641
685
|
switch (state.platform) {
|
|
642
686
|
case "android":
|
|
643
|
-
|
|
687
|
+
if (state.isInstallable) return "android-native";
|
|
688
|
+
return promptWaitElapsed ? "android-manual" : "android-pending";
|
|
644
689
|
case "ios-safari":
|
|
645
690
|
return "ios-safari";
|
|
646
691
|
case "ios-other":
|
|
@@ -699,18 +744,27 @@ function useInstallPrompt(slug) {
|
|
|
699
744
|
const iosBrowser = detectIOSBrowser(ua);
|
|
700
745
|
const androidBrowser = detectAndroidBrowser(ua);
|
|
701
746
|
const inAppApp = detectInAppApp(ua);
|
|
702
|
-
const [isInstallable, setIsInstallable] = (0,
|
|
747
|
+
const [isInstallable, setIsInstallable] = (0, import_react7.useState)(() => {
|
|
703
748
|
if (typeof window === "undefined") return false;
|
|
704
749
|
return window.__pwaInstallPrompt != null;
|
|
705
750
|
});
|
|
706
|
-
const [isInstalled, setIsInstalled] = (0,
|
|
751
|
+
const [isInstalled, setIsInstalled] = (0, import_react7.useState)(() => {
|
|
707
752
|
const { installed } = detectStandalone();
|
|
708
753
|
return installed || readInstalledMarker(slug);
|
|
709
754
|
});
|
|
710
|
-
const [isDismissedSession, setIsDismissedSession] = (0,
|
|
711
|
-
const [isDismissedPermanent, setIsDismissedPermanent] = (0,
|
|
712
|
-
const [skipCount, setSkipCount] = (0,
|
|
713
|
-
(0,
|
|
755
|
+
const [isDismissedSession, setIsDismissedSession] = (0, import_react7.useState)(() => readSessionSkip(slug));
|
|
756
|
+
const [isDismissedPermanent, setIsDismissedPermanent] = (0, import_react7.useState)(() => readPermanentDismiss(slug).dismissed);
|
|
757
|
+
const [skipCount, setSkipCount] = (0, import_react7.useState)(() => readSkipCount(slug));
|
|
758
|
+
const [promptWaitElapsed, setPromptWaitElapsed] = (0, import_react7.useState)(() => {
|
|
759
|
+
if (typeof window === "undefined") return true;
|
|
760
|
+
return window.__pwaInstallPrompt != null;
|
|
761
|
+
});
|
|
762
|
+
(0, import_react7.useEffect)(() => {
|
|
763
|
+
if (promptWaitElapsed) return;
|
|
764
|
+
const id = setTimeout(() => setPromptWaitElapsed(true), ANDROID_PROMPT_WAIT_MS);
|
|
765
|
+
return () => clearTimeout(id);
|
|
766
|
+
}, [promptWaitElapsed]);
|
|
767
|
+
(0, import_react7.useEffect)(() => {
|
|
714
768
|
if (typeof window === "undefined") return;
|
|
715
769
|
if (window.__pwaInstallPrompt) {
|
|
716
770
|
setIsInstallable(true);
|
|
@@ -734,7 +788,7 @@ function useInstallPrompt(slug) {
|
|
|
734
788
|
window.removeEventListener("appinstalled", onInstalled);
|
|
735
789
|
};
|
|
736
790
|
}, [slug]);
|
|
737
|
-
(0,
|
|
791
|
+
(0, import_react7.useEffect)(() => {
|
|
738
792
|
if (typeof window === "undefined") return;
|
|
739
793
|
const mq = window.matchMedia?.("(display-mode: standalone)");
|
|
740
794
|
if (!mq) return;
|
|
@@ -747,18 +801,21 @@ function useInstallPrompt(slug) {
|
|
|
747
801
|
mq.addEventListener?.("change", handler);
|
|
748
802
|
return () => mq.removeEventListener?.("change", handler);
|
|
749
803
|
}, [slug]);
|
|
750
|
-
const variant = pickVariant(
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
804
|
+
const variant = pickVariant(
|
|
805
|
+
{
|
|
806
|
+
platform,
|
|
807
|
+
iosBrowser,
|
|
808
|
+
androidBrowser,
|
|
809
|
+
inAppApp,
|
|
810
|
+
isInstallable,
|
|
811
|
+
isInstalled,
|
|
812
|
+
isDismissedSession,
|
|
813
|
+
isDismissedPermanent,
|
|
814
|
+
skipCount
|
|
815
|
+
},
|
|
816
|
+
promptWaitElapsed
|
|
817
|
+
);
|
|
818
|
+
const promptInstall = (0, import_react7.useCallback)(async () => {
|
|
762
819
|
if (typeof window === "undefined") return false;
|
|
763
820
|
const prompt = window.__pwaInstallPrompt;
|
|
764
821
|
if (!prompt) return false;
|
|
@@ -780,7 +837,7 @@ function useInstallPrompt(slug) {
|
|
|
780
837
|
return false;
|
|
781
838
|
}
|
|
782
839
|
}, [slug]);
|
|
783
|
-
const dismissSession = (0,
|
|
840
|
+
const dismissSession = (0, import_react7.useCallback)(() => {
|
|
784
841
|
if (typeof sessionStorage !== "undefined") {
|
|
785
842
|
try {
|
|
786
843
|
sessionStorage.setItem(storageKey.sessionSkip(slug), "true");
|
|
@@ -794,20 +851,20 @@ function useInstallPrompt(slug) {
|
|
|
794
851
|
setIsDismissedSession(true);
|
|
795
852
|
track("pwa_install_session_skip", { slug, platform, skip_count: newCount });
|
|
796
853
|
}, [slug, skipCount, platform]);
|
|
797
|
-
const dismissPermanent = (0,
|
|
854
|
+
const dismissPermanent = (0, import_react7.useCallback)(() => {
|
|
798
855
|
const storage = safeStorage();
|
|
799
856
|
if (storage) storage.setItem(storageKey.dismissedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
800
857
|
setIsDismissedPermanent(true);
|
|
801
858
|
track("pwa_install_permanent_dismiss", { slug, platform, prior_skip_count: skipCount });
|
|
802
859
|
}, [slug, platform, skipCount]);
|
|
803
|
-
const copyLink = (0,
|
|
860
|
+
const copyLink = (0, import_react7.useCallback)(async () => {
|
|
804
861
|
if (typeof navigator === "undefined" || typeof location === "undefined") return;
|
|
805
862
|
try {
|
|
806
863
|
await navigator.clipboard?.writeText?.(location.href);
|
|
807
864
|
} catch {
|
|
808
865
|
}
|
|
809
866
|
}, []);
|
|
810
|
-
const reset = (0,
|
|
867
|
+
const reset = (0, import_react7.useCallback)(() => {
|
|
811
868
|
const storage = safeStorage();
|
|
812
869
|
if (storage) {
|
|
813
870
|
storage.removeItem(storageKey.dismissedAt(slug));
|
|
@@ -1293,15 +1350,51 @@ function Step({ n, icon, children }) {
|
|
|
1293
1350
|
);
|
|
1294
1351
|
}
|
|
1295
1352
|
|
|
1296
|
-
// src/components/InstallGate/
|
|
1353
|
+
// src/components/InstallGate/variants/AndroidPendingVariant.tsx
|
|
1297
1354
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1355
|
+
function AndroidPendingVariant() {
|
|
1356
|
+
const copy = INSTALL_COPY.android.native;
|
|
1357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(InstallSplash, { title: copy.title, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1358
|
+
"div",
|
|
1359
|
+
{
|
|
1360
|
+
style: {
|
|
1361
|
+
display: "flex",
|
|
1362
|
+
flexDirection: "column",
|
|
1363
|
+
alignItems: "center",
|
|
1364
|
+
gap: 16,
|
|
1365
|
+
padding: "24px 0"
|
|
1366
|
+
},
|
|
1367
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Spinner, {})
|
|
1368
|
+
}
|
|
1369
|
+
) });
|
|
1370
|
+
}
|
|
1371
|
+
function Spinner() {
|
|
1372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1373
|
+
"div",
|
|
1374
|
+
{
|
|
1375
|
+
"aria-hidden": true,
|
|
1376
|
+
style: {
|
|
1377
|
+
width: 28,
|
|
1378
|
+
height: 28,
|
|
1379
|
+
borderRadius: "50%",
|
|
1380
|
+
border: "3px solid #e5e5e7",
|
|
1381
|
+
borderTopColor: "var(--hook-color-primary)",
|
|
1382
|
+
animation: "hook-install-spin 0.8s linear infinite"
|
|
1383
|
+
},
|
|
1384
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: `@keyframes hook-install-spin { to { transform: rotate(360deg); } }` })
|
|
1385
|
+
}
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
// src/components/InstallGate/Step.tsx
|
|
1390
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1298
1391
|
function Step2({
|
|
1299
1392
|
n,
|
|
1300
1393
|
title,
|
|
1301
1394
|
subtitle,
|
|
1302
1395
|
visual
|
|
1303
1396
|
}) {
|
|
1304
|
-
return /* @__PURE__ */ (0,
|
|
1397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1305
1398
|
"div",
|
|
1306
1399
|
{
|
|
1307
1400
|
style: {
|
|
@@ -1312,7 +1405,7 @@ function Step2({
|
|
|
1312
1405
|
textAlign: "left"
|
|
1313
1406
|
},
|
|
1314
1407
|
children: [
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1316
1409
|
"div",
|
|
1317
1410
|
{
|
|
1318
1411
|
style: {
|
|
@@ -1331,9 +1424,9 @@ function Step2({
|
|
|
1331
1424
|
children: n
|
|
1332
1425
|
}
|
|
1333
1426
|
),
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1335
|
-
/* @__PURE__ */ (0,
|
|
1336
|
-
subtitle && /* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1 }, children: [
|
|
1428
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
|
|
1429
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
|
|
1337
1430
|
visual
|
|
1338
1431
|
] })
|
|
1339
1432
|
]
|
|
@@ -1342,21 +1435,21 @@ function Step2({
|
|
|
1342
1435
|
}
|
|
1343
1436
|
|
|
1344
1437
|
// src/components/InstallGate/variants/IOSafariVariant.tsx
|
|
1345
|
-
var
|
|
1438
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1346
1439
|
function IOSafariVariant({
|
|
1347
1440
|
state,
|
|
1348
1441
|
actions
|
|
1349
1442
|
}) {
|
|
1350
1443
|
const copy = INSTALL_COPY.iosSafari;
|
|
1351
1444
|
const showPermanent = shouldShowPermanentOption(state);
|
|
1352
|
-
return /* @__PURE__ */ (0,
|
|
1353
|
-
/* @__PURE__ */ (0,
|
|
1445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1354
1447
|
Step2,
|
|
1355
1448
|
{
|
|
1356
1449
|
n: 1,
|
|
1357
1450
|
title: copy.step1.title,
|
|
1358
1451
|
subtitle: copy.step1.subtitle,
|
|
1359
|
-
visual: /* @__PURE__ */ (0,
|
|
1452
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1360
1453
|
"div",
|
|
1361
1454
|
{
|
|
1362
1455
|
style: {
|
|
@@ -1368,17 +1461,17 @@ function IOSafariVariant({
|
|
|
1368
1461
|
padding: "12px 0",
|
|
1369
1462
|
marginTop: 8
|
|
1370
1463
|
},
|
|
1371
|
-
children: /* @__PURE__ */ (0,
|
|
1464
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
|
|
1372
1465
|
}
|
|
1373
1466
|
)
|
|
1374
1467
|
}
|
|
1375
1468
|
),
|
|
1376
|
-
/* @__PURE__ */ (0,
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1377
1470
|
Step2,
|
|
1378
1471
|
{
|
|
1379
1472
|
n: 2,
|
|
1380
1473
|
title: copy.step2.title,
|
|
1381
|
-
visual: /* @__PURE__ */ (0,
|
|
1474
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1382
1475
|
"div",
|
|
1383
1476
|
{
|
|
1384
1477
|
style: {
|
|
@@ -1391,19 +1484,19 @@ function IOSafariVariant({
|
|
|
1391
1484
|
marginTop: 8
|
|
1392
1485
|
},
|
|
1393
1486
|
children: [
|
|
1394
|
-
/* @__PURE__ */ (0,
|
|
1395
|
-
/* @__PURE__ */ (0,
|
|
1487
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
|
|
1396
1489
|
]
|
|
1397
1490
|
}
|
|
1398
1491
|
)
|
|
1399
1492
|
}
|
|
1400
1493
|
),
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1402
1495
|
Step2,
|
|
1403
1496
|
{
|
|
1404
1497
|
n: 3,
|
|
1405
1498
|
title: copy.step3.title,
|
|
1406
|
-
visual: /* @__PURE__ */ (0,
|
|
1499
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1407
1500
|
"div",
|
|
1408
1501
|
{
|
|
1409
1502
|
style: {
|
|
@@ -1414,7 +1507,7 @@ function IOSafariVariant({
|
|
|
1414
1507
|
padding: "10px 14px",
|
|
1415
1508
|
marginTop: 8
|
|
1416
1509
|
},
|
|
1417
|
-
children: /* @__PURE__ */ (0,
|
|
1510
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1418
1511
|
"span",
|
|
1419
1512
|
{
|
|
1420
1513
|
style: {
|
|
@@ -1429,7 +1522,7 @@ function IOSafariVariant({
|
|
|
1429
1522
|
)
|
|
1430
1523
|
}
|
|
1431
1524
|
),
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1525
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1433
1526
|
"button",
|
|
1434
1527
|
{
|
|
1435
1528
|
"data-testid": "install-prompt-skip-session",
|
|
@@ -1439,7 +1532,7 @@ function IOSafariVariant({
|
|
|
1439
1532
|
children: copy.skip
|
|
1440
1533
|
}
|
|
1441
1534
|
),
|
|
1442
|
-
showPermanent && /* @__PURE__ */ (0,
|
|
1535
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1443
1536
|
"button",
|
|
1444
1537
|
{
|
|
1445
1538
|
"data-testid": "install-prompt-skip-permanent",
|
|
@@ -1453,21 +1546,21 @@ function IOSafariVariant({
|
|
|
1453
1546
|
}
|
|
1454
1547
|
|
|
1455
1548
|
// src/components/InstallGate/variants/IOSOtherVariant.tsx
|
|
1456
|
-
var
|
|
1549
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1457
1550
|
function IOSOtherVariant({
|
|
1458
1551
|
state,
|
|
1459
1552
|
actions
|
|
1460
1553
|
}) {
|
|
1461
1554
|
const copy = INSTALL_COPY.iosOther;
|
|
1462
1555
|
const showPermanent = shouldShowPermanentOption(state);
|
|
1463
|
-
return /* @__PURE__ */ (0,
|
|
1464
|
-
/* @__PURE__ */ (0,
|
|
1556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
1557
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1465
1558
|
Step2,
|
|
1466
1559
|
{
|
|
1467
1560
|
n: 1,
|
|
1468
1561
|
title: copy.step1.title,
|
|
1469
1562
|
subtitle: copy.step1.subtitle,
|
|
1470
|
-
visual: /* @__PURE__ */ (0,
|
|
1563
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1471
1564
|
"div",
|
|
1472
1565
|
{
|
|
1473
1566
|
style: {
|
|
@@ -1479,17 +1572,17 @@ function IOSOtherVariant({
|
|
|
1479
1572
|
padding: "12px 0",
|
|
1480
1573
|
marginTop: 8
|
|
1481
1574
|
},
|
|
1482
|
-
children: /* @__PURE__ */ (0,
|
|
1575
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
|
|
1483
1576
|
}
|
|
1484
1577
|
)
|
|
1485
1578
|
}
|
|
1486
1579
|
),
|
|
1487
|
-
/* @__PURE__ */ (0,
|
|
1580
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1488
1581
|
Step2,
|
|
1489
1582
|
{
|
|
1490
1583
|
n: 2,
|
|
1491
1584
|
title: copy.step2.title,
|
|
1492
|
-
visual: /* @__PURE__ */ (0,
|
|
1585
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1493
1586
|
"div",
|
|
1494
1587
|
{
|
|
1495
1588
|
style: {
|
|
@@ -1502,19 +1595,19 @@ function IOSOtherVariant({
|
|
|
1502
1595
|
marginTop: 8
|
|
1503
1596
|
},
|
|
1504
1597
|
children: [
|
|
1505
|
-
/* @__PURE__ */ (0,
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1598
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
|
|
1507
1600
|
]
|
|
1508
1601
|
}
|
|
1509
1602
|
)
|
|
1510
1603
|
}
|
|
1511
1604
|
),
|
|
1512
|
-
/* @__PURE__ */ (0,
|
|
1605
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1513
1606
|
Step2,
|
|
1514
1607
|
{
|
|
1515
1608
|
n: 3,
|
|
1516
1609
|
title: copy.step3.title,
|
|
1517
|
-
visual: /* @__PURE__ */ (0,
|
|
1610
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1518
1611
|
"div",
|
|
1519
1612
|
{
|
|
1520
1613
|
style: {
|
|
@@ -1525,7 +1618,7 @@ function IOSOtherVariant({
|
|
|
1525
1618
|
padding: "10px 14px",
|
|
1526
1619
|
marginTop: 8
|
|
1527
1620
|
},
|
|
1528
|
-
children: /* @__PURE__ */ (0,
|
|
1621
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1529
1622
|
"span",
|
|
1530
1623
|
{
|
|
1531
1624
|
style: {
|
|
@@ -1540,7 +1633,7 @@ function IOSOtherVariant({
|
|
|
1540
1633
|
)
|
|
1541
1634
|
}
|
|
1542
1635
|
),
|
|
1543
|
-
/* @__PURE__ */ (0,
|
|
1636
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1544
1637
|
"button",
|
|
1545
1638
|
{
|
|
1546
1639
|
"data-testid": "install-prompt-skip-session",
|
|
@@ -1550,7 +1643,7 @@ function IOSOtherVariant({
|
|
|
1550
1643
|
children: copy.skip
|
|
1551
1644
|
}
|
|
1552
1645
|
),
|
|
1553
|
-
showPermanent && /* @__PURE__ */ (0,
|
|
1646
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1554
1647
|
"button",
|
|
1555
1648
|
{
|
|
1556
1649
|
"data-testid": "install-prompt-skip-permanent",
|
|
@@ -1564,8 +1657,8 @@ function IOSOtherVariant({
|
|
|
1564
1657
|
}
|
|
1565
1658
|
|
|
1566
1659
|
// src/components/InstallGate/variants/InAppBrowserVariant.tsx
|
|
1567
|
-
var
|
|
1568
|
-
var
|
|
1660
|
+
var import_react8 = require("react");
|
|
1661
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1569
1662
|
function InAppBrowserVariant({
|
|
1570
1663
|
state,
|
|
1571
1664
|
actions
|
|
@@ -1574,17 +1667,17 @@ function InAppBrowserVariant({
|
|
|
1574
1667
|
const appCopy = INSTALL_COPY.inApp[app] ?? INSTALL_COPY.inApp.other;
|
|
1575
1668
|
const copy = INSTALL_COPY.inApp;
|
|
1576
1669
|
const showPermanent = shouldShowPermanentOption(state);
|
|
1577
|
-
const [copied, setCopied] = (0,
|
|
1670
|
+
const [copied, setCopied] = (0, import_react8.useState)(false);
|
|
1578
1671
|
const handleCopy = async () => {
|
|
1579
1672
|
await actions.copyLink();
|
|
1580
1673
|
setCopied(true);
|
|
1581
1674
|
setTimeout(() => setCopied(false), 2e3);
|
|
1582
1675
|
};
|
|
1583
1676
|
const DotsIcon = app === "facebook" || app === "telegram" ? MenuDotsVerticalIcon : MenuDotsHorizontalIcon;
|
|
1584
|
-
return /* @__PURE__ */ (0,
|
|
1585
|
-
/* @__PURE__ */ (0,
|
|
1586
|
-
/* @__PURE__ */ (0,
|
|
1587
|
-
/* @__PURE__ */ (0,
|
|
1677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(InstallSplash, { title: appCopy.title, children: [
|
|
1678
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 1, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DotsIcon, { size: 20 }), children: appCopy.step1 }),
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 2, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1588
1681
|
"button",
|
|
1589
1682
|
{
|
|
1590
1683
|
"data-testid": "install-prompt-cta-inapp-copy",
|
|
@@ -1594,7 +1687,7 @@ function InAppBrowserVariant({
|
|
|
1594
1687
|
children: copied ? copy.copiedToast : copy.copy
|
|
1595
1688
|
}
|
|
1596
1689
|
),
|
|
1597
|
-
/* @__PURE__ */ (0,
|
|
1690
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1598
1691
|
"button",
|
|
1599
1692
|
{
|
|
1600
1693
|
"data-testid": "install-prompt-skip-session",
|
|
@@ -1604,7 +1697,7 @@ function InAppBrowserVariant({
|
|
|
1604
1697
|
children: copy.skip
|
|
1605
1698
|
}
|
|
1606
1699
|
),
|
|
1607
|
-
showPermanent && /* @__PURE__ */ (0,
|
|
1700
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1608
1701
|
"button",
|
|
1609
1702
|
{
|
|
1610
1703
|
"data-testid": "install-prompt-skip-permanent",
|
|
@@ -1621,7 +1714,7 @@ function Step3({
|
|
|
1621
1714
|
icon,
|
|
1622
1715
|
children
|
|
1623
1716
|
}) {
|
|
1624
|
-
return /* @__PURE__ */ (0,
|
|
1717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1625
1718
|
"div",
|
|
1626
1719
|
{
|
|
1627
1720
|
style: {
|
|
@@ -1635,7 +1728,7 @@ function Step3({
|
|
|
1635
1728
|
textAlign: "left"
|
|
1636
1729
|
},
|
|
1637
1730
|
children: [
|
|
1638
|
-
/* @__PURE__ */ (0,
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1639
1732
|
"div",
|
|
1640
1733
|
{
|
|
1641
1734
|
style: {
|
|
@@ -1654,15 +1747,15 @@ function Step3({
|
|
|
1654
1747
|
children: n
|
|
1655
1748
|
}
|
|
1656
1749
|
),
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
|
|
1659
1752
|
]
|
|
1660
1753
|
}
|
|
1661
1754
|
);
|
|
1662
1755
|
}
|
|
1663
1756
|
|
|
1664
1757
|
// src/components/InstallGate/variants/DesktopVariant.tsx
|
|
1665
|
-
var
|
|
1758
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1666
1759
|
function DesktopVariant({
|
|
1667
1760
|
state,
|
|
1668
1761
|
actions
|
|
@@ -1671,21 +1764,21 @@ function DesktopVariant({
|
|
|
1671
1764
|
const copy = INSTALL_COPY.desktop;
|
|
1672
1765
|
const iconUrl = theme.icon_url || theme.logo_url || null;
|
|
1673
1766
|
if (!state.isInstallable) return null;
|
|
1674
|
-
return /* @__PURE__ */ (0,
|
|
1767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1675
1768
|
"div",
|
|
1676
1769
|
{
|
|
1677
1770
|
role: "complementary",
|
|
1678
1771
|
"aria-label": copy.title,
|
|
1679
1772
|
style: bannerStyle,
|
|
1680
1773
|
children: [
|
|
1681
|
-
iconUrl ? /* @__PURE__ */ (0,
|
|
1774
|
+
iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1682
1775
|
"img",
|
|
1683
1776
|
{
|
|
1684
1777
|
src: iconUrl,
|
|
1685
1778
|
alt: "",
|
|
1686
1779
|
style: { width: 40, height: 40, borderRadius: 10, objectFit: "cover", flexShrink: 0 }
|
|
1687
1780
|
}
|
|
1688
|
-
) : /* @__PURE__ */ (0,
|
|
1781
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1689
1782
|
"div",
|
|
1690
1783
|
{
|
|
1691
1784
|
style: {
|
|
@@ -1704,11 +1797,11 @@ function DesktopVariant({
|
|
|
1704
1797
|
children: name.charAt(0).toUpperCase()
|
|
1705
1798
|
}
|
|
1706
1799
|
),
|
|
1707
|
-
/* @__PURE__ */ (0,
|
|
1708
|
-
/* @__PURE__ */ (0,
|
|
1709
|
-
/* @__PURE__ */ (0,
|
|
1800
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1801
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
|
|
1710
1803
|
] }),
|
|
1711
|
-
/* @__PURE__ */ (0,
|
|
1804
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1712
1805
|
"button",
|
|
1713
1806
|
{
|
|
1714
1807
|
"data-testid": "install-prompt-cta-desktop",
|
|
@@ -1729,12 +1822,12 @@ function DesktopVariant({
|
|
|
1729
1822
|
flexShrink: 0
|
|
1730
1823
|
},
|
|
1731
1824
|
children: [
|
|
1732
|
-
/* @__PURE__ */ (0,
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DownloadIcon, { size: 14 }),
|
|
1733
1826
|
copy.cta
|
|
1734
1827
|
]
|
|
1735
1828
|
}
|
|
1736
1829
|
),
|
|
1737
|
-
/* @__PURE__ */ (0,
|
|
1830
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1738
1831
|
"button",
|
|
1739
1832
|
{
|
|
1740
1833
|
"data-testid": "install-prompt-desktop-close",
|
|
@@ -1749,7 +1842,7 @@ function DesktopVariant({
|
|
|
1749
1842
|
padding: 4,
|
|
1750
1843
|
flexShrink: 0
|
|
1751
1844
|
},
|
|
1752
|
-
children: /* @__PURE__ */ (0,
|
|
1845
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(XIcon, { size: 16 })
|
|
1753
1846
|
}
|
|
1754
1847
|
)
|
|
1755
1848
|
]
|
|
@@ -1773,14 +1866,14 @@ var bannerStyle = {
|
|
|
1773
1866
|
};
|
|
1774
1867
|
|
|
1775
1868
|
// src/components/InstallGate/InstallGate.tsx
|
|
1776
|
-
var
|
|
1869
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1777
1870
|
function InstallGate({ children }) {
|
|
1778
1871
|
const { slug, features_enabled } = useTemplateConfig();
|
|
1779
1872
|
const enabled = features_enabled.includes("install_prompt");
|
|
1780
1873
|
const installState = useInstallPrompt(slug);
|
|
1781
1874
|
const shouldBlock = enabled && shouldBlockInstall(installState);
|
|
1782
|
-
const trackedRef = (0,
|
|
1783
|
-
(0,
|
|
1875
|
+
const trackedRef = (0, import_react9.useRef)(null);
|
|
1876
|
+
(0, import_react9.useEffect)(() => {
|
|
1784
1877
|
if (!shouldBlock) return;
|
|
1785
1878
|
if (typeof window === "undefined") return;
|
|
1786
1879
|
const variantKey = `${slug}:${installState.variant}`;
|
|
@@ -1794,30 +1887,32 @@ function InstallGate({ children }) {
|
|
|
1794
1887
|
variant: installState.variant
|
|
1795
1888
|
});
|
|
1796
1889
|
}, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
|
|
1797
|
-
if (!enabled) return /* @__PURE__ */ (0,
|
|
1798
|
-
if (installState.isInstalled) return /* @__PURE__ */ (0,
|
|
1890
|
+
if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1891
|
+
if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1799
1892
|
if (installState.variant === "desktop") {
|
|
1800
1893
|
const showBanner = !installState.isDismissedSession && !installState.isDismissedPermanent;
|
|
1801
|
-
return /* @__PURE__ */ (0,
|
|
1894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1802
1895
|
children,
|
|
1803
|
-
showBanner && /* @__PURE__ */ (0,
|
|
1896
|
+
showBanner && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DesktopVariant, { state: installState, actions: installState })
|
|
1804
1897
|
] });
|
|
1805
1898
|
}
|
|
1806
|
-
if (!shouldBlock) return /* @__PURE__ */ (0,
|
|
1899
|
+
if (!shouldBlock) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1807
1900
|
switch (installState.variant) {
|
|
1808
1901
|
case "android-native":
|
|
1809
|
-
return /* @__PURE__ */ (0,
|
|
1902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidNativeVariant, { state: installState, actions: installState });
|
|
1810
1903
|
case "android-manual":
|
|
1811
|
-
return /* @__PURE__ */ (0,
|
|
1904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidManualVariant, { state: installState, actions: installState });
|
|
1905
|
+
case "android-pending":
|
|
1906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidPendingVariant, {});
|
|
1812
1907
|
case "ios-safari":
|
|
1813
|
-
return /* @__PURE__ */ (0,
|
|
1908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSafariVariant, { state: installState, actions: installState });
|
|
1814
1909
|
case "ios-other":
|
|
1815
|
-
return /* @__PURE__ */ (0,
|
|
1910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSOtherVariant, { state: installState, actions: installState });
|
|
1816
1911
|
case "in-app":
|
|
1817
|
-
return /* @__PURE__ */ (0,
|
|
1912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(InAppBrowserVariant, { state: installState, actions: installState });
|
|
1818
1913
|
case "none":
|
|
1819
1914
|
default:
|
|
1820
|
-
return /* @__PURE__ */ (0,
|
|
1915
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1821
1916
|
}
|
|
1822
1917
|
}
|
|
1823
1918
|
|
|
@@ -1827,16 +1922,16 @@ function PushPrompt() {
|
|
|
1827
1922
|
}
|
|
1828
1923
|
|
|
1829
1924
|
// src/internal/SessionExpiredBanner.tsx
|
|
1830
|
-
var
|
|
1831
|
-
var
|
|
1832
|
-
var
|
|
1925
|
+
var import_react10 = require("react");
|
|
1926
|
+
var import_sdk4 = require("@hook-sdk/sdk");
|
|
1927
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1833
1928
|
var DISMISS_KEY = "hook:session-expired-dismissed-until";
|
|
1834
1929
|
var DISMISS_TTL_MS = 60 * 60 * 1e3;
|
|
1835
1930
|
function SessionExpiredBanner() {
|
|
1836
|
-
const { authStatus } = (0,
|
|
1837
|
-
const wasAuthRef = (0,
|
|
1838
|
-
const [show, setShow] = (0,
|
|
1839
|
-
(0,
|
|
1931
|
+
const { authStatus } = (0, import_sdk4.useHook)();
|
|
1932
|
+
const wasAuthRef = (0, import_react10.useRef)(false);
|
|
1933
|
+
const [show, setShow] = (0, import_react10.useState)(false);
|
|
1934
|
+
(0, import_react10.useEffect)(() => {
|
|
1840
1935
|
if (authStatus === "authenticated") {
|
|
1841
1936
|
wasAuthRef.current = true;
|
|
1842
1937
|
setShow(false);
|
|
@@ -1856,13 +1951,13 @@ function SessionExpiredBanner() {
|
|
|
1856
1951
|
localStorage.setItem(DISMISS_KEY, String(Date.now() + DISMISS_TTL_MS));
|
|
1857
1952
|
setShow(false);
|
|
1858
1953
|
}
|
|
1859
|
-
return /* @__PURE__ */ (0,
|
|
1860
|
-
/* @__PURE__ */ (0,
|
|
1861
|
-
/* @__PURE__ */ (0,
|
|
1954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { role: "alert", className: "fixed top-0 inset-x-0 bg-red-600 text-white px-4 py-2 flex items-center justify-between gap-3 text-sm shadow", style: { zIndex: 10001 }, children: [
|
|
1955
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
1956
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "Sua sess\xE3o expirou." }),
|
|
1862
1957
|
" Fa\xE7a login novamente para continuar."
|
|
1863
1958
|
] }),
|
|
1864
|
-
/* @__PURE__ */ (0,
|
|
1865
|
-
/* @__PURE__ */ (0,
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1960
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1866
1961
|
"button",
|
|
1867
1962
|
{
|
|
1868
1963
|
type: "button",
|
|
@@ -1871,7 +1966,7 @@ function SessionExpiredBanner() {
|
|
|
1871
1966
|
children: "Fazer login"
|
|
1872
1967
|
}
|
|
1873
1968
|
),
|
|
1874
|
-
/* @__PURE__ */ (0,
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1875
1970
|
"button",
|
|
1876
1971
|
{
|
|
1877
1972
|
type: "button",
|
|
@@ -1886,9 +1981,9 @@ function SessionExpiredBanner() {
|
|
|
1886
1981
|
}
|
|
1887
1982
|
|
|
1888
1983
|
// src/defaults/ErrorBoundary.tsx
|
|
1889
|
-
var
|
|
1890
|
-
var
|
|
1891
|
-
var ErrorBoundary = class extends
|
|
1984
|
+
var import_react11 = require("react");
|
|
1985
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1986
|
+
var ErrorBoundary = class extends import_react11.Component {
|
|
1892
1987
|
state = { error: null };
|
|
1893
1988
|
static getDerivedStateFromError(error) {
|
|
1894
1989
|
return { error };
|
|
@@ -1905,30 +2000,30 @@ var ErrorBoundary = class extends import_react10.Component {
|
|
|
1905
2000
|
}
|
|
1906
2001
|
render() {
|
|
1907
2002
|
if (this.state.error) {
|
|
1908
|
-
return this.props.fallback ?? /* @__PURE__ */ (0,
|
|
1909
|
-
/* @__PURE__ */ (0,
|
|
1910
|
-
/* @__PURE__ */ (0,
|
|
2003
|
+
return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
2004
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h2", { children: "Algo deu errado" }),
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
1911
2006
|
] });
|
|
1912
2007
|
}
|
|
1913
|
-
return /* @__PURE__ */ (0,
|
|
2008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: this.props.children });
|
|
1914
2009
|
}
|
|
1915
2010
|
};
|
|
1916
2011
|
|
|
1917
2012
|
// src/internal/PaymentReturnHandler.tsx
|
|
1918
|
-
var
|
|
1919
|
-
var
|
|
1920
|
-
var
|
|
2013
|
+
var import_react12 = require("react");
|
|
2014
|
+
var import_sdk5 = require("@hook-sdk/sdk");
|
|
2015
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1921
2016
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
1922
2017
|
var MAX_CYCLES = 3;
|
|
1923
2018
|
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
1924
2019
|
function PaymentReturnHandler({ children }) {
|
|
1925
|
-
const { subscription } = (0,
|
|
1926
|
-
const subRef = (0,
|
|
2020
|
+
const { subscription } = (0, import_sdk5.useHook)();
|
|
2021
|
+
const subRef = (0, import_react12.useRef)(subscription);
|
|
1927
2022
|
subRef.current = subscription;
|
|
1928
|
-
const runIdRef = (0,
|
|
1929
|
-
const cyclesRef = (0,
|
|
1930
|
-
const [state, setState] = (0,
|
|
1931
|
-
const runPoll = (0,
|
|
2023
|
+
const runIdRef = (0, import_react12.useRef)(0);
|
|
2024
|
+
const cyclesRef = (0, import_react12.useRef)(0);
|
|
2025
|
+
const [state, setState] = (0, import_react12.useState)("idle");
|
|
2026
|
+
const runPoll = (0, import_react12.useCallback)(() => {
|
|
1932
2027
|
const runId = ++runIdRef.current;
|
|
1933
2028
|
cyclesRef.current += 1;
|
|
1934
2029
|
setState("confirming");
|
|
@@ -1963,7 +2058,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
1963
2058
|
};
|
|
1964
2059
|
void tick();
|
|
1965
2060
|
}, []);
|
|
1966
|
-
(0,
|
|
2061
|
+
(0, import_react12.useEffect)(() => {
|
|
1967
2062
|
if (typeof window === "undefined") return;
|
|
1968
2063
|
const url = new URL(window.location.href);
|
|
1969
2064
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -1973,26 +2068,26 @@ function PaymentReturnHandler({ children }) {
|
|
|
1973
2068
|
runIdRef.current++;
|
|
1974
2069
|
};
|
|
1975
2070
|
}, [runPoll]);
|
|
1976
|
-
const goHome = (0,
|
|
2071
|
+
const goHome = (0, import_react12.useCallback)(() => {
|
|
1977
2072
|
const cleanUrl = new URL(window.location.href);
|
|
1978
2073
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
1979
2074
|
cleanUrl.pathname = "/app/home";
|
|
1980
2075
|
window.location.href = cleanUrl.toString();
|
|
1981
2076
|
}, []);
|
|
1982
2077
|
if (state === "confirming") {
|
|
1983
|
-
return /* @__PURE__ */ (0,
|
|
2078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
|
|
1984
2079
|
}
|
|
1985
2080
|
if (state === "waiting") {
|
|
1986
|
-
return /* @__PURE__ */ (0,
|
|
1987
|
-
/* @__PURE__ */ (0,
|
|
1988
|
-
/* @__PURE__ */ (0,
|
|
2081
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2083
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
|
|
1989
2084
|
] }) });
|
|
1990
2085
|
}
|
|
1991
2086
|
if (state === "timeout") {
|
|
1992
|
-
return /* @__PURE__ */ (0,
|
|
1993
|
-
/* @__PURE__ */ (0,
|
|
1994
|
-
/* @__PURE__ */ (0,
|
|
1995
|
-
/* @__PURE__ */ (0,
|
|
2087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2088
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
|
|
2089
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1996
2091
|
"button",
|
|
1997
2092
|
{
|
|
1998
2093
|
type: "button",
|
|
@@ -2005,7 +2100,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2005
2100
|
children: "Tentar de novo"
|
|
2006
2101
|
}
|
|
2007
2102
|
),
|
|
2008
|
-
/* @__PURE__ */ (0,
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2009
2104
|
"button",
|
|
2010
2105
|
{
|
|
2011
2106
|
type: "button",
|
|
@@ -2015,7 +2110,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2015
2110
|
children: "Voltar pro app"
|
|
2016
2111
|
}
|
|
2017
2112
|
),
|
|
2018
|
-
/* @__PURE__ */ (0,
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2019
2114
|
"a",
|
|
2020
2115
|
{
|
|
2021
2116
|
href: SUPPORT_MAILTO,
|
|
@@ -2027,7 +2122,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2027
2122
|
] })
|
|
2028
2123
|
] }) });
|
|
2029
2124
|
}
|
|
2030
|
-
return /* @__PURE__ */ (0,
|
|
2125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children });
|
|
2031
2126
|
}
|
|
2032
2127
|
var overlayStyle2 = {
|
|
2033
2128
|
position: "fixed",
|
|
@@ -2066,7 +2161,7 @@ var linkStyle = {
|
|
|
2066
2161
|
};
|
|
2067
2162
|
|
|
2068
2163
|
// src/AppRoot.tsx
|
|
2069
|
-
var
|
|
2164
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2070
2165
|
function buildLegacyConfigShim(config) {
|
|
2071
2166
|
const paywall = config.paywall;
|
|
2072
2167
|
const isFree = paywall.mode === "free";
|
|
@@ -2076,7 +2171,16 @@ function buildLegacyConfigShim(config) {
|
|
|
2076
2171
|
slug: config.slug,
|
|
2077
2172
|
name: config.name,
|
|
2078
2173
|
email_alias: config.slug,
|
|
2079
|
-
theme
|
|
2174
|
+
// Map branding into the legacy theme shape so InstallSplash (and
|
|
2175
|
+
// anything else reading theme.icon_url / theme.logo_url) can surface
|
|
2176
|
+
// the app icon instead of the generic "first letter of name" fallback.
|
|
2177
|
+
// Falls back to logoUrl when iconUrl is unset — apps that haven't
|
|
2178
|
+
// adopted iconUrl keep their previous behavior unchanged.
|
|
2179
|
+
theme: {
|
|
2180
|
+
primary_color: config.branding.primaryColor,
|
|
2181
|
+
icon_url: config.branding.iconUrl ?? config.branding.logoUrl,
|
|
2182
|
+
logo_url: config.branding.logoUrl
|
|
2183
|
+
},
|
|
2080
2184
|
features_enabled: config.features_enabled ?? [],
|
|
2081
2185
|
dependencies_allowlist: ["react", "react-dom"],
|
|
2082
2186
|
subscription: {
|
|
@@ -2130,14 +2234,14 @@ function AppRoot(props) {
|
|
|
2130
2234
|
"[hook-template] <AppRoot>: PreAuthFlow slot prop is required when config.onboarding.trigger === 'pre_signup_custom'."
|
|
2131
2235
|
);
|
|
2132
2236
|
}
|
|
2133
|
-
const legacyShim = (0,
|
|
2237
|
+
const legacyShim = (0, import_react13.useMemo)(() => buildLegacyConfigShim(config), [config]);
|
|
2134
2238
|
const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
|
|
2135
2239
|
const basename = `/app/${config.slug}`;
|
|
2136
2240
|
const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
|
|
2137
|
-
return /* @__PURE__ */ (0,
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2139
|
-
/* @__PURE__ */ (0,
|
|
2140
|
-
/* @__PURE__ */ (0,
|
|
2241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Router, { ...routerProps, children: [
|
|
2242
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SessionExpiredBanner, {}),
|
|
2244
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(InstallGate, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2141
2245
|
AuthGated,
|
|
2142
2246
|
{
|
|
2143
2247
|
config,
|
|
@@ -2149,9 +2253,9 @@ function AppRoot(props) {
|
|
|
2149
2253
|
Paywall,
|
|
2150
2254
|
Onboarding,
|
|
2151
2255
|
PreAuthFlow,
|
|
2152
|
-
children: /* @__PURE__ */ (0,
|
|
2256
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: [
|
|
2153
2257
|
children,
|
|
2154
|
-
/* @__PURE__ */ (0,
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PushPrompt, {})
|
|
2155
2259
|
] })
|
|
2156
2260
|
}
|
|
2157
2261
|
) })
|
|
@@ -2167,37 +2271,37 @@ function AuthGated({
|
|
|
2167
2271
|
EmailVerify,
|
|
2168
2272
|
PreAuthFlow
|
|
2169
2273
|
}) {
|
|
2170
|
-
const { authStatus } = (0,
|
|
2274
|
+
const { authStatus } = (0, import_sdk6.useHook)();
|
|
2171
2275
|
if (authStatus === "loading") return null;
|
|
2172
2276
|
if (authStatus !== "authenticated") {
|
|
2173
2277
|
if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
|
|
2174
|
-
return /* @__PURE__ */ (0,
|
|
2175
|
-
/* @__PURE__ */ (0,
|
|
2176
|
-
/* @__PURE__ */ (0,
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2178
|
-
/* @__PURE__ */ (0,
|
|
2179
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2180
|
-
/* @__PURE__ */ (0,
|
|
2278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2279
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Login, {}) }),
|
|
2280
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Signup, {}) }),
|
|
2281
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Forgot, {}) }),
|
|
2282
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Reset, {}) }),
|
|
2283
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EmailVerify, {}) }) : null,
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PreAuthFlow, {}) })
|
|
2181
2285
|
] });
|
|
2182
2286
|
}
|
|
2183
|
-
return /* @__PURE__ */ (0,
|
|
2184
|
-
/* @__PURE__ */ (0,
|
|
2185
|
-
/* @__PURE__ */ (0,
|
|
2186
|
-
/* @__PURE__ */ (0,
|
|
2187
|
-
/* @__PURE__ */ (0,
|
|
2188
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2189
|
-
/* @__PURE__ */ (0,
|
|
2287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Login, {}) }),
|
|
2289
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Signup, {}) }),
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Forgot, {}) }),
|
|
2291
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Reset, {}) }),
|
|
2292
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EmailVerify, {}) }) : null,
|
|
2293
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
|
|
2190
2294
|
] });
|
|
2191
2295
|
}
|
|
2192
|
-
return /* @__PURE__ */ (0,
|
|
2296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, { children });
|
|
2193
2297
|
}
|
|
2194
2298
|
function FallbackPaywall() {
|
|
2195
2299
|
return null;
|
|
2196
2300
|
}
|
|
2197
2301
|
|
|
2198
2302
|
// src/hooks/usePush.ts
|
|
2199
|
-
var
|
|
2200
|
-
var
|
|
2303
|
+
var import_react14 = require("react");
|
|
2304
|
+
var import_sdk7 = require("@hook-sdk/sdk");
|
|
2201
2305
|
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2202
2306
|
var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
2203
2307
|
function detectIosNeedsInstall() {
|
|
@@ -2241,12 +2345,12 @@ function deriveState(push) {
|
|
|
2241
2345
|
return { kind: "prompt" };
|
|
2242
2346
|
}
|
|
2243
2347
|
function usePush() {
|
|
2244
|
-
const { push } = (0,
|
|
2245
|
-
const [state, setState] = (0,
|
|
2246
|
-
(0,
|
|
2348
|
+
const { push } = (0, import_sdk7.useHook)();
|
|
2349
|
+
const [state, setState] = (0, import_react14.useState)(() => deriveState(push));
|
|
2350
|
+
(0, import_react14.useEffect)(() => {
|
|
2247
2351
|
setState(deriveState(push));
|
|
2248
2352
|
}, [push]);
|
|
2249
|
-
const subscribe = (0,
|
|
2353
|
+
const subscribe = (0, import_react14.useCallback)(async () => {
|
|
2250
2354
|
try {
|
|
2251
2355
|
await push.subscribe();
|
|
2252
2356
|
setState({ kind: "subscribed" });
|
|
@@ -2258,7 +2362,7 @@ function usePush() {
|
|
|
2258
2362
|
throw e;
|
|
2259
2363
|
}
|
|
2260
2364
|
}, [push]);
|
|
2261
|
-
const unsubscribe = (0,
|
|
2365
|
+
const unsubscribe = (0, import_react14.useCallback)(async () => {
|
|
2262
2366
|
try {
|
|
2263
2367
|
await push.unsubscribe();
|
|
2264
2368
|
setState({ kind: "prompt" });
|
|
@@ -2267,7 +2371,7 @@ function usePush() {
|
|
|
2267
2371
|
throw e;
|
|
2268
2372
|
}
|
|
2269
2373
|
}, [push]);
|
|
2270
|
-
const dismiss = (0,
|
|
2374
|
+
const dismiss = (0, import_react14.useCallback)(() => {
|
|
2271
2375
|
if (typeof localStorage !== "undefined") {
|
|
2272
2376
|
try {
|
|
2273
2377
|
localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS2));
|
|
@@ -2280,7 +2384,7 @@ function usePush() {
|
|
|
2280
2384
|
}
|
|
2281
2385
|
|
|
2282
2386
|
// src/components/PushPrompt.tsx
|
|
2283
|
-
var
|
|
2387
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2284
2388
|
function platformRecoveryCopy(texts) {
|
|
2285
2389
|
if (typeof navigator === "undefined") return null;
|
|
2286
2390
|
const ua = navigator.userAgent || "";
|
|
@@ -2303,28 +2407,28 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2303
2407
|
const { state, subscribe } = usePush();
|
|
2304
2408
|
if (state.kind === "subscribed" || state.kind === "dismissed") return null;
|
|
2305
2409
|
if (state.kind === "ios_needs_install") {
|
|
2306
|
-
return /* @__PURE__ */ (0,
|
|
2307
|
-
/* @__PURE__ */ (0,
|
|
2308
|
-
/* @__PURE__ */ (0,
|
|
2309
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0,
|
|
2410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2411
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
2412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.iosInstallBody }),
|
|
2413
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
2310
2414
|
] });
|
|
2311
2415
|
}
|
|
2312
2416
|
if (state.kind === "denied") {
|
|
2313
2417
|
const recovery = platformRecoveryCopy(texts);
|
|
2314
|
-
return /* @__PURE__ */ (0,
|
|
2315
|
-
/* @__PURE__ */ (0,
|
|
2316
|
-
/* @__PURE__ */ (0,
|
|
2317
|
-
recovery && /* @__PURE__ */ (0,
|
|
2418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
2419
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { children: texts.deniedTitle }),
|
|
2420
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.deniedBody }),
|
|
2421
|
+
recovery && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { "data-testid": "denied-recovery", children: recovery })
|
|
2318
2422
|
] });
|
|
2319
2423
|
}
|
|
2320
2424
|
if (state.kind === "unsupported") {
|
|
2321
|
-
return /* @__PURE__ */ (0,
|
|
2425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.unsupportedBody }) });
|
|
2322
2426
|
}
|
|
2323
2427
|
if (state.kind === "error") {
|
|
2324
|
-
return /* @__PURE__ */ (0,
|
|
2428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: state.message }) });
|
|
2325
2429
|
}
|
|
2326
|
-
return /* @__PURE__ */ (0,
|
|
2327
|
-
/* @__PURE__ */ (0,
|
|
2430
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", children: [
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2328
2432
|
"button",
|
|
2329
2433
|
{
|
|
2330
2434
|
type: "button",
|
|
@@ -2338,41 +2442,41 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2338
2442
|
children: texts.cta
|
|
2339
2443
|
}
|
|
2340
2444
|
),
|
|
2341
|
-
onDeclined && /* @__PURE__ */ (0,
|
|
2445
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
2342
2446
|
] });
|
|
2343
2447
|
}
|
|
2344
2448
|
|
|
2345
2449
|
// src/defaults/LoadingState.tsx
|
|
2346
|
-
var
|
|
2450
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2347
2451
|
function LoadingState({ message }) {
|
|
2348
|
-
return /* @__PURE__ */ (0,
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: message ?? "Carregando..." }) });
|
|
2349
2453
|
}
|
|
2350
2454
|
|
|
2351
2455
|
// src/defaults/EmptyState.tsx
|
|
2352
|
-
var
|
|
2456
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2353
2457
|
function EmptyState({ title, description, action }) {
|
|
2354
|
-
return /* @__PURE__ */ (0,
|
|
2355
|
-
/* @__PURE__ */ (0,
|
|
2356
|
-
description && /* @__PURE__ */ (0,
|
|
2357
|
-
action && /* @__PURE__ */ (0,
|
|
2458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2459
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2460
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
2461
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
2358
2462
|
] });
|
|
2359
2463
|
}
|
|
2360
2464
|
|
|
2361
2465
|
// src/hooks/useLoginForm.ts
|
|
2362
|
-
var
|
|
2363
|
-
var
|
|
2466
|
+
var import_react15 = require("react");
|
|
2467
|
+
var import_sdk9 = require("@hook-sdk/sdk");
|
|
2364
2468
|
|
|
2365
2469
|
// src/errors.ts
|
|
2366
|
-
var
|
|
2470
|
+
var import_sdk8 = require("@hook-sdk/sdk");
|
|
2367
2471
|
function mapSdkError(err) {
|
|
2368
|
-
if (err instanceof
|
|
2472
|
+
if (err instanceof import_sdk8.SdkRateLimitError) {
|
|
2369
2473
|
return {
|
|
2370
2474
|
code: "rate_limited",
|
|
2371
2475
|
message: `Aguarde ${err.retryAfter}s e tente novamente.`,
|
|
2372
2476
|
retryAfter: err.retryAfter
|
|
2373
2477
|
};
|
|
2374
2478
|
}
|
|
2375
|
-
if (err instanceof
|
|
2479
|
+
if (err instanceof import_sdk8.SdkAuthError) {
|
|
2376
2480
|
const detail = err.detail;
|
|
2377
2481
|
if (detail === "email_unverified") {
|
|
2378
2482
|
return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
|
|
@@ -2382,7 +2486,7 @@ function mapSdkError(err) {
|
|
|
2382
2486
|
}
|
|
2383
2487
|
return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
|
|
2384
2488
|
}
|
|
2385
|
-
if (err instanceof
|
|
2489
|
+
if (err instanceof import_sdk8.SdkError && err.httpStatus === 0) {
|
|
2386
2490
|
return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
|
|
2387
2491
|
}
|
|
2388
2492
|
if (err instanceof TypeError) {
|
|
@@ -2395,20 +2499,20 @@ function mapSdkError(err) {
|
|
|
2395
2499
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2396
2500
|
var MIN_PASSWORD = 8;
|
|
2397
2501
|
function useLoginForm() {
|
|
2398
|
-
const { auth } = (0,
|
|
2399
|
-
const [email, setEmail] = (0,
|
|
2400
|
-
const [password, setPassword] = (0,
|
|
2401
|
-
const [submitting, setSubmitting] = (0,
|
|
2402
|
-
const [error, setError] = (0,
|
|
2403
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2404
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2405
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2406
|
-
const validateEmail = (0,
|
|
2502
|
+
const { auth } = (0, import_sdk9.useHook)();
|
|
2503
|
+
const [email, setEmail] = (0, import_react15.useState)("");
|
|
2504
|
+
const [password, setPassword] = (0, import_react15.useState)("");
|
|
2505
|
+
const [submitting, setSubmitting] = (0, import_react15.useState)(false);
|
|
2506
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
2507
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react15.useState)(false);
|
|
2508
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react15.useState)(false);
|
|
2509
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react15.useState)(false);
|
|
2510
|
+
const validateEmail = (0, import_react15.useMemo)(() => {
|
|
2407
2511
|
if (email.length === 0) return null;
|
|
2408
2512
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2409
2513
|
return null;
|
|
2410
2514
|
}, [email]);
|
|
2411
|
-
const validatePassword = (0,
|
|
2515
|
+
const validatePassword = (0, import_react15.useMemo)(() => {
|
|
2412
2516
|
if (password.length === 0) return null;
|
|
2413
2517
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2414
2518
|
return null;
|
|
@@ -2416,7 +2520,7 @@ function useLoginForm() {
|
|
|
2416
2520
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2417
2521
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2418
2522
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2419
|
-
const submit = (0,
|
|
2523
|
+
const submit = (0, import_react15.useCallback)(async () => {
|
|
2420
2524
|
setFormSubmitAttempted(true);
|
|
2421
2525
|
if (!canSubmit) return false;
|
|
2422
2526
|
setSubmitting(true);
|
|
@@ -2450,32 +2554,32 @@ function useLoginForm() {
|
|
|
2450
2554
|
}
|
|
2451
2555
|
|
|
2452
2556
|
// src/hooks/useSignupForm.ts
|
|
2453
|
-
var
|
|
2454
|
-
var
|
|
2557
|
+
var import_react16 = require("react");
|
|
2558
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
2455
2559
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2456
2560
|
var MIN_PASSWORD2 = 8;
|
|
2457
2561
|
function useSignupForm() {
|
|
2458
|
-
const { auth } = (0,
|
|
2459
|
-
const [name, setName] = (0,
|
|
2460
|
-
const [email, setEmail] = (0,
|
|
2461
|
-
const [password, setPassword] = (0,
|
|
2462
|
-
const [submitting, setSubmitting] = (0,
|
|
2463
|
-
const [error, setError] = (0,
|
|
2464
|
-
const [touchedName, setTouchedName] = (0,
|
|
2465
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2466
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2467
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2468
|
-
const validateName = (0,
|
|
2562
|
+
const { auth } = (0, import_sdk10.useHook)();
|
|
2563
|
+
const [name, setName] = (0, import_react16.useState)("");
|
|
2564
|
+
const [email, setEmail] = (0, import_react16.useState)("");
|
|
2565
|
+
const [password, setPassword] = (0, import_react16.useState)("");
|
|
2566
|
+
const [submitting, setSubmitting] = (0, import_react16.useState)(false);
|
|
2567
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
2568
|
+
const [touchedName, setTouchedName] = (0, import_react16.useState)(false);
|
|
2569
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react16.useState)(false);
|
|
2570
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react16.useState)(false);
|
|
2571
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react16.useState)(false);
|
|
2572
|
+
const validateName = (0, import_react16.useMemo)(() => {
|
|
2469
2573
|
if (name.length === 0) return null;
|
|
2470
2574
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2471
2575
|
return null;
|
|
2472
2576
|
}, [name]);
|
|
2473
|
-
const validateEmail = (0,
|
|
2577
|
+
const validateEmail = (0, import_react16.useMemo)(() => {
|
|
2474
2578
|
if (email.length === 0) return null;
|
|
2475
2579
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2476
2580
|
return null;
|
|
2477
2581
|
}, [email]);
|
|
2478
|
-
const validatePassword = (0,
|
|
2582
|
+
const validatePassword = (0, import_react16.useMemo)(() => {
|
|
2479
2583
|
if (password.length === 0) return null;
|
|
2480
2584
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2481
2585
|
return null;
|
|
@@ -2484,7 +2588,7 @@ function useSignupForm() {
|
|
|
2484
2588
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2485
2589
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2486
2590
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2487
|
-
const submit = (0,
|
|
2591
|
+
const submit = (0, import_react16.useCallback)(async () => {
|
|
2488
2592
|
setFormSubmitAttempted(true);
|
|
2489
2593
|
if (!canSubmit) return false;
|
|
2490
2594
|
setSubmitting(true);
|
|
@@ -2522,25 +2626,25 @@ function useSignupForm() {
|
|
|
2522
2626
|
}
|
|
2523
2627
|
|
|
2524
2628
|
// src/hooks/useForgotForm.ts
|
|
2525
|
-
var
|
|
2526
|
-
var
|
|
2629
|
+
var import_react17 = require("react");
|
|
2630
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2527
2631
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2528
2632
|
function useForgotForm() {
|
|
2529
|
-
const { auth } = (0,
|
|
2530
|
-
const [email, setEmail] = (0,
|
|
2531
|
-
const [submitting, setSubmitting] = (0,
|
|
2532
|
-
const [sent, setSent] = (0,
|
|
2533
|
-
const [error, setError] = (0,
|
|
2534
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2535
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2536
|
-
const validateEmail = (0,
|
|
2633
|
+
const { auth } = (0, import_sdk11.useHook)();
|
|
2634
|
+
const [email, setEmail] = (0, import_react17.useState)("");
|
|
2635
|
+
const [submitting, setSubmitting] = (0, import_react17.useState)(false);
|
|
2636
|
+
const [sent, setSent] = (0, import_react17.useState)(false);
|
|
2637
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
2638
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react17.useState)(false);
|
|
2639
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react17.useState)(false);
|
|
2640
|
+
const validateEmail = (0, import_react17.useMemo)(() => {
|
|
2537
2641
|
if (email.length === 0) return null;
|
|
2538
2642
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2539
2643
|
return null;
|
|
2540
2644
|
}, [email]);
|
|
2541
2645
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2542
2646
|
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2543
|
-
const submit = (0,
|
|
2647
|
+
const submit = (0, import_react17.useCallback)(async () => {
|
|
2544
2648
|
setFormSubmitAttempted(true);
|
|
2545
2649
|
if (!canSubmit) return false;
|
|
2546
2650
|
setSubmitting(true);
|
|
@@ -2571,32 +2675,32 @@ function useForgotForm() {
|
|
|
2571
2675
|
}
|
|
2572
2676
|
|
|
2573
2677
|
// src/hooks/useResetForm.ts
|
|
2574
|
-
var
|
|
2575
|
-
var
|
|
2678
|
+
var import_react18 = require("react");
|
|
2679
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
2576
2680
|
var MIN_PASSWORD3 = 12;
|
|
2577
2681
|
function useResetForm() {
|
|
2578
|
-
const { auth } = (0,
|
|
2579
|
-
const [token, setToken] = (0,
|
|
2580
|
-
const [password, setPassword] = (0,
|
|
2581
|
-
const [confirm, setConfirm] = (0,
|
|
2582
|
-
const [submitting, setSubmitting] = (0,
|
|
2583
|
-
const [done, setDone] = (0,
|
|
2584
|
-
const [error, setError] = (0,
|
|
2585
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2586
|
-
const [touchedConfirm, setTouchedConfirm] = (0,
|
|
2587
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2588
|
-
(0,
|
|
2682
|
+
const { auth } = (0, import_sdk12.useHook)();
|
|
2683
|
+
const [token, setToken] = (0, import_react18.useState)(null);
|
|
2684
|
+
const [password, setPassword] = (0, import_react18.useState)("");
|
|
2685
|
+
const [confirm, setConfirm] = (0, import_react18.useState)("");
|
|
2686
|
+
const [submitting, setSubmitting] = (0, import_react18.useState)(false);
|
|
2687
|
+
const [done, setDone] = (0, import_react18.useState)(false);
|
|
2688
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
2689
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react18.useState)(false);
|
|
2690
|
+
const [touchedConfirm, setTouchedConfirm] = (0, import_react18.useState)(false);
|
|
2691
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
|
|
2692
|
+
(0, import_react18.useEffect)(() => {
|
|
2589
2693
|
if (typeof window === "undefined") return;
|
|
2590
2694
|
const params = new URLSearchParams(window.location.search);
|
|
2591
2695
|
const t = params.get("token");
|
|
2592
2696
|
setToken(t && t.length > 0 ? t : null);
|
|
2593
2697
|
}, []);
|
|
2594
|
-
const validatePassword = (0,
|
|
2698
|
+
const validatePassword = (0, import_react18.useMemo)(() => {
|
|
2595
2699
|
if (password.length === 0) return null;
|
|
2596
2700
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
2597
2701
|
return null;
|
|
2598
2702
|
}, [password]);
|
|
2599
|
-
const validateConfirm = (0,
|
|
2703
|
+
const validateConfirm = (0, import_react18.useMemo)(() => {
|
|
2600
2704
|
if (confirm.length === 0) return null;
|
|
2601
2705
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
2602
2706
|
return null;
|
|
@@ -2604,7 +2708,7 @@ function useResetForm() {
|
|
|
2604
2708
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2605
2709
|
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
2606
2710
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
2607
|
-
const submit = (0,
|
|
2711
|
+
const submit = (0, import_react18.useCallback)(async () => {
|
|
2608
2712
|
setFormSubmitAttempted(true);
|
|
2609
2713
|
if (!canSubmit || token === null) return;
|
|
2610
2714
|
setSubmitting(true);
|
|
@@ -2644,9 +2748,9 @@ function useResetForm() {
|
|
|
2644
2748
|
}
|
|
2645
2749
|
|
|
2646
2750
|
// src/hooks/usePlan.ts
|
|
2647
|
-
var
|
|
2751
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
2648
2752
|
function usePlan() {
|
|
2649
|
-
const { plan } = (0,
|
|
2753
|
+
const { plan } = (0, import_sdk13.useHook)();
|
|
2650
2754
|
return plan;
|
|
2651
2755
|
}
|
|
2652
2756
|
|
|
@@ -2679,12 +2783,12 @@ function discountPercent(anchorCents, realCents) {
|
|
|
2679
2783
|
}
|
|
2680
2784
|
|
|
2681
2785
|
// src/hooks/useAuthPrimitives.ts
|
|
2682
|
-
var
|
|
2683
|
-
var
|
|
2786
|
+
var import_react19 = require("react");
|
|
2787
|
+
var import_sdk14 = require("@hook-sdk/sdk");
|
|
2684
2788
|
var warned = false;
|
|
2685
2789
|
function useAuthPrimitives() {
|
|
2686
|
-
const { auth } = (0,
|
|
2687
|
-
(0,
|
|
2790
|
+
const { auth } = (0, import_sdk14.useHook)();
|
|
2791
|
+
(0, import_react19.useEffect)(() => {
|
|
2688
2792
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
2689
2793
|
warned = true;
|
|
2690
2794
|
console.warn(
|
|
@@ -2706,9 +2810,9 @@ function useAuthPrimitives() {
|
|
|
2706
2810
|
}
|
|
2707
2811
|
|
|
2708
2812
|
// src/hooks/useAuth.ts
|
|
2709
|
-
var
|
|
2813
|
+
var import_sdk15 = require("@hook-sdk/sdk");
|
|
2710
2814
|
function useAuth() {
|
|
2711
|
-
const { user, authStatus, auth } = (0,
|
|
2815
|
+
const { user, authStatus, auth } = (0, import_sdk15.useHook)();
|
|
2712
2816
|
return {
|
|
2713
2817
|
user,
|
|
2714
2818
|
authStatus,
|
|
@@ -2717,23 +2821,23 @@ function useAuth() {
|
|
|
2717
2821
|
}
|
|
2718
2822
|
|
|
2719
2823
|
// src/hooks/useSubscription.ts
|
|
2720
|
-
var
|
|
2824
|
+
var import_sdk16 = require("@hook-sdk/sdk");
|
|
2721
2825
|
function useSubscription() {
|
|
2722
|
-
const { subscription } = (0,
|
|
2826
|
+
const { subscription } = (0, import_sdk16.useHook)();
|
|
2723
2827
|
return {
|
|
2724
2828
|
status: subscription.status()
|
|
2725
2829
|
};
|
|
2726
2830
|
}
|
|
2727
2831
|
|
|
2728
2832
|
// src/hooks/useReminders.ts
|
|
2729
|
-
var
|
|
2730
|
-
var
|
|
2833
|
+
var import_react20 = require("react");
|
|
2834
|
+
var import_sdk17 = require("@hook-sdk/sdk");
|
|
2731
2835
|
function useReminders() {
|
|
2732
|
-
const { push } = (0,
|
|
2836
|
+
const { push } = (0, import_sdk17.useHook)();
|
|
2733
2837
|
const r = push.reminders;
|
|
2734
|
-
const [reminders, setReminders] = (0,
|
|
2735
|
-
const [loading, setLoading] = (0,
|
|
2736
|
-
const reload = (0,
|
|
2838
|
+
const [reminders, setReminders] = (0, import_react20.useState)([]);
|
|
2839
|
+
const [loading, setLoading] = (0, import_react20.useState)(true);
|
|
2840
|
+
const reload = (0, import_react20.useCallback)(async () => {
|
|
2737
2841
|
setLoading(true);
|
|
2738
2842
|
try {
|
|
2739
2843
|
const next = await r.list();
|
|
@@ -2742,38 +2846,38 @@ function useReminders() {
|
|
|
2742
2846
|
setLoading(false);
|
|
2743
2847
|
}
|
|
2744
2848
|
}, [r]);
|
|
2745
|
-
(0,
|
|
2849
|
+
(0, import_react20.useEffect)(() => {
|
|
2746
2850
|
void reload();
|
|
2747
2851
|
}, [reload]);
|
|
2748
|
-
const setReminder = (0,
|
|
2852
|
+
const setReminder = (0, import_react20.useCallback)(async (input) => {
|
|
2749
2853
|
await r.set(input);
|
|
2750
2854
|
await reload();
|
|
2751
2855
|
}, [r, reload]);
|
|
2752
|
-
const deleteReminder = (0,
|
|
2856
|
+
const deleteReminder = (0, import_react20.useCallback)(async (slot) => {
|
|
2753
2857
|
await r.delete(slot);
|
|
2754
2858
|
await reload();
|
|
2755
2859
|
}, [r, reload]);
|
|
2756
|
-
const schedule = (0,
|
|
2860
|
+
const schedule = (0, import_react20.useCallback)(async (items) => {
|
|
2757
2861
|
return r.schedule(items);
|
|
2758
2862
|
}, [r]);
|
|
2759
|
-
const setFallbacks = (0,
|
|
2863
|
+
const setFallbacks = (0, import_react20.useCallback)(async (items) => {
|
|
2760
2864
|
return r.setFallbacks(items);
|
|
2761
2865
|
}, [r]);
|
|
2762
2866
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
2763
2867
|
}
|
|
2764
2868
|
|
|
2765
2869
|
// src/hooks/useToast.ts
|
|
2766
|
-
var
|
|
2870
|
+
var import_react21 = require("react");
|
|
2767
2871
|
function useToast() {
|
|
2768
|
-
const [items, setItems] = (0,
|
|
2769
|
-
const show = (0,
|
|
2872
|
+
const [items, setItems] = (0, import_react21.useState)([]);
|
|
2873
|
+
const show = (0, import_react21.useCallback)((message, kind = "info") => {
|
|
2770
2874
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2771
2875
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
2772
2876
|
setTimeout(() => {
|
|
2773
2877
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2774
2878
|
}, 4e3);
|
|
2775
2879
|
}, []);
|
|
2776
|
-
const dismiss = (0,
|
|
2880
|
+
const dismiss = (0, import_react21.useCallback)((id) => {
|
|
2777
2881
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2778
2882
|
}, []);
|
|
2779
2883
|
return { items, show, dismiss };
|
|
@@ -2781,20 +2885,20 @@ function useToast() {
|
|
|
2781
2885
|
|
|
2782
2886
|
// src/RouteBoundary.tsx
|
|
2783
2887
|
var import_react_router_dom3 = require("react-router-dom");
|
|
2784
|
-
var
|
|
2888
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2785
2889
|
function RouteBoundary({ children }) {
|
|
2786
|
-
return /* @__PURE__ */ (0,
|
|
2890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_router_dom3.Routes, { children: [
|
|
2787
2891
|
children,
|
|
2788
|
-
/* @__PURE__ */ (0,
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DefaultNotFound, {}) })
|
|
2789
2893
|
] });
|
|
2790
2894
|
}
|
|
2791
2895
|
function DefaultNotFound() {
|
|
2792
|
-
return /* @__PURE__ */ (0,
|
|
2896
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
|
|
2793
2897
|
}
|
|
2794
2898
|
|
|
2795
2899
|
// src/PreAuthShell.tsx
|
|
2796
2900
|
var import_react_router_dom4 = require("react-router-dom");
|
|
2797
|
-
var
|
|
2901
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2798
2902
|
function PreAuthShell({
|
|
2799
2903
|
basename,
|
|
2800
2904
|
testRouter,
|
|
@@ -2802,20 +2906,20 @@ function PreAuthShell({
|
|
|
2802
2906
|
children
|
|
2803
2907
|
}) {
|
|
2804
2908
|
if (testRouter === "memory") {
|
|
2805
|
-
return /* @__PURE__ */ (0,
|
|
2909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
2806
2910
|
}
|
|
2807
|
-
return /* @__PURE__ */ (0,
|
|
2911
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
2808
2912
|
}
|
|
2809
2913
|
|
|
2810
2914
|
// src/OnboardingFlow.tsx
|
|
2811
|
-
var
|
|
2812
|
-
var
|
|
2915
|
+
var import_react23 = require("react");
|
|
2916
|
+
var import_sdk18 = require("@hook-sdk/sdk");
|
|
2813
2917
|
|
|
2814
2918
|
// src/hooks/useOnboardingStep.ts
|
|
2815
|
-
var
|
|
2816
|
-
var OnboardingStepContext = (0,
|
|
2919
|
+
var import_react22 = require("react");
|
|
2920
|
+
var OnboardingStepContext = (0, import_react22.createContext)(null);
|
|
2817
2921
|
function useOnboardingStep() {
|
|
2818
|
-
const ctx = (0,
|
|
2922
|
+
const ctx = (0, import_react22.useContext)(OnboardingStepContext);
|
|
2819
2923
|
if (!ctx) {
|
|
2820
2924
|
throw new Error(
|
|
2821
2925
|
"[hook-template] useOnboardingStep must be used inside <OnboardingFlow>. (G75)"
|
|
@@ -2825,7 +2929,7 @@ function useOnboardingStep() {
|
|
|
2825
2929
|
}
|
|
2826
2930
|
|
|
2827
2931
|
// src/OnboardingFlow.tsx
|
|
2828
|
-
var
|
|
2932
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2829
2933
|
var isFilled = (v) => v != null && v !== "";
|
|
2830
2934
|
var CURRENT_STEP_FIELD = "currentStep";
|
|
2831
2935
|
function readPersistedStepIdx(draft) {
|
|
@@ -2838,12 +2942,12 @@ function OnboardingFlow({
|
|
|
2838
2942
|
onComplete,
|
|
2839
2943
|
persistKey
|
|
2840
2944
|
}) {
|
|
2841
|
-
const [draft, setDraft, status] = (0,
|
|
2842
|
-
const draftRef = (0,
|
|
2945
|
+
const [draft, setDraft, status] = (0, import_sdk18.usePersistedState)(persistKey, {});
|
|
2946
|
+
const draftRef = (0, import_react23.useRef)(draft);
|
|
2843
2947
|
draftRef.current = draft;
|
|
2844
2948
|
const idx = readPersistedStepIdx(draft);
|
|
2845
2949
|
const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
|
|
2846
|
-
const setIdx = (0,
|
|
2950
|
+
const setIdx = (0, import_react23.useCallback)(
|
|
2847
2951
|
(n) => {
|
|
2848
2952
|
setDraft((prev) => {
|
|
2849
2953
|
const prevIdx = readPersistedStepIdx(prev);
|
|
@@ -2853,7 +2957,7 @@ function OnboardingFlow({
|
|
|
2853
2957
|
},
|
|
2854
2958
|
[setDraft]
|
|
2855
2959
|
);
|
|
2856
|
-
const setValue = (0,
|
|
2960
|
+
const setValue = (0, import_react23.useCallback)(
|
|
2857
2961
|
(patch) => {
|
|
2858
2962
|
draftRef.current = { ...draftRef.current, ...patch };
|
|
2859
2963
|
setDraft((prev) => ({ ...prev, ...patch }));
|
|
@@ -2861,11 +2965,23 @@ function OnboardingFlow({
|
|
|
2861
2965
|
[setDraft]
|
|
2862
2966
|
);
|
|
2863
2967
|
const step = steps[clampedIdx];
|
|
2864
|
-
const
|
|
2968
|
+
const hookCtx = (0, import_sdk18.useHook)();
|
|
2969
|
+
const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
|
|
2970
|
+
(0, import_react23.useEffect)(() => {
|
|
2971
|
+
if (status.loading) return;
|
|
2972
|
+
if (!step) return;
|
|
2973
|
+
if (!track2) return;
|
|
2974
|
+
track2("onboarding_step_viewed", {
|
|
2975
|
+
step: step.id,
|
|
2976
|
+
step_index: clampedIdx,
|
|
2977
|
+
total_steps: steps.length
|
|
2978
|
+
});
|
|
2979
|
+
}, [step?.id, clampedIdx, steps.length, status.loading, track2]);
|
|
2980
|
+
const valid = (0, import_react23.useMemo)(
|
|
2865
2981
|
() => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
|
|
2866
2982
|
[draft, step]
|
|
2867
2983
|
);
|
|
2868
|
-
const next = (0,
|
|
2984
|
+
const next = (0, import_react23.useCallback)(() => {
|
|
2869
2985
|
if (!step) return;
|
|
2870
2986
|
const current = draftRef.current;
|
|
2871
2987
|
const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
|
|
@@ -2876,8 +2992,8 @@ function OnboardingFlow({
|
|
|
2876
2992
|
setIdx(clampedIdx + 1);
|
|
2877
2993
|
}
|
|
2878
2994
|
}, [clampedIdx, onComplete, step, steps.length, setIdx]);
|
|
2879
|
-
const prevStep = (0,
|
|
2880
|
-
const ctx = (0,
|
|
2995
|
+
const prevStep = (0, import_react23.useCallback)(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
|
|
2996
|
+
const ctx = (0, import_react23.useMemo)(
|
|
2881
2997
|
() => ({
|
|
2882
2998
|
stepIndex: clampedIdx,
|
|
2883
2999
|
totalSteps: steps.length,
|
|
@@ -2903,7 +3019,7 @@ function OnboardingFlow({
|
|
|
2903
3019
|
`[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
|
|
2904
3020
|
);
|
|
2905
3021
|
}
|
|
2906
|
-
return /* @__PURE__ */ (0,
|
|
3022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Screen, {}) });
|
|
2907
3023
|
}
|
|
2908
3024
|
|
|
2909
3025
|
// src/hooks/useFeature.ts
|