@hook-sdk/template 0.14.1 → 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 +222 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +105 -54
- 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");
|
|
@@ -248,8 +248,8 @@ function ThemeProvider({ children }) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// src/hooks/usePaywallState.ts
|
|
251
|
-
var
|
|
252
|
-
var
|
|
251
|
+
var import_react6 = require("react");
|
|
252
|
+
var import_sdk3 = require("@hook-sdk/sdk");
|
|
253
253
|
|
|
254
254
|
// src/errors/asaas-pt-br.ts
|
|
255
255
|
var MAP = {
|
|
@@ -270,6 +270,35 @@ function asaasErrorMessage(code) {
|
|
|
270
270
|
return MAP[code] ?? "Ocorreu um erro inesperado. Tente novamente em instantes.";
|
|
271
271
|
}
|
|
272
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
|
+
|
|
273
302
|
// src/hooks/usePaywallState.ts
|
|
274
303
|
function isCheckoutFailure(r) {
|
|
275
304
|
return "ok" in r && r.ok === false;
|
|
@@ -284,11 +313,11 @@ var FALLBACK_PAYWALL = {
|
|
|
284
313
|
};
|
|
285
314
|
var isMethodAvailable = (availability, method) => availability[method] !== false;
|
|
286
315
|
function usePaywallState() {
|
|
287
|
-
const { subscription, plan } = (0,
|
|
288
|
-
const configFromCtx = (0,
|
|
316
|
+
const { subscription, plan } = (0, import_sdk3.useHook)();
|
|
317
|
+
const configFromCtx = (0, import_react6.useContext)(AppConfigContext);
|
|
289
318
|
const paywall = configFromCtx?.paywall ?? FALLBACK_PAYWALL;
|
|
290
319
|
const isFree = paywall.mode === "free";
|
|
291
|
-
const declaredMethods = (0,
|
|
320
|
+
const declaredMethods = (0, import_react6.useMemo)(
|
|
292
321
|
() => isFree ? [] : paywall.checkoutMethods,
|
|
293
322
|
[isFree, paywall]
|
|
294
323
|
);
|
|
@@ -297,33 +326,33 @@ function usePaywallState() {
|
|
|
297
326
|
"pix-auto": null,
|
|
298
327
|
"pix-once": null
|
|
299
328
|
};
|
|
300
|
-
const methods = (0,
|
|
329
|
+
const methods = (0, import_react6.useMemo)(
|
|
301
330
|
() => declaredMethods.filter((m) => isMethodAvailable(availability, m)),
|
|
302
331
|
[declaredMethods, availability]
|
|
303
332
|
);
|
|
304
333
|
const defaultMethod = methods[0] ?? declaredMethods[0] ?? "card";
|
|
305
|
-
const [selectedMethodRaw, setSelectedMethod] = (0,
|
|
334
|
+
const [selectedMethodRaw, setSelectedMethod] = (0, import_react6.useState)(defaultMethod);
|
|
306
335
|
const selectedMethod = methods.includes(selectedMethodRaw) ? selectedMethodRaw : methods[0] ?? selectedMethodRaw;
|
|
307
336
|
const initialCycle = isFree ? "MONTHLY" : paywall.cycles[0] ?? "MONTHLY";
|
|
308
|
-
const [cycle, setCycle] = (0,
|
|
337
|
+
const [cycle, setCycle] = (0, import_react6.useState)(initialCycle);
|
|
309
338
|
const cpfRequired = !isFree && paywall.requiresCpf;
|
|
310
|
-
const [cpf, setCpf] = (0,
|
|
311
|
-
const cpfValid = (0,
|
|
312
|
-
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)({
|
|
313
342
|
number: "",
|
|
314
343
|
cvv: "",
|
|
315
344
|
expiry: "",
|
|
316
345
|
holder: ""
|
|
317
346
|
});
|
|
318
|
-
const setCard = (0,
|
|
347
|
+
const setCard = (0, import_react6.useCallback)((patch) => {
|
|
319
348
|
setCardState((prev) => ({ ...prev, ...patch }));
|
|
320
349
|
}, []);
|
|
321
|
-
const [error, setError] = (0,
|
|
322
|
-
const [submitting, setSubmitting] = (0,
|
|
350
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
351
|
+
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
323
352
|
const status = subscription.status();
|
|
324
353
|
const daysLeftInTrial = subscription.daysLeftInTrial();
|
|
325
354
|
const initialLoadComplete = subscription.initialLoadComplete;
|
|
326
|
-
const pixPending = (0,
|
|
355
|
+
const pixPending = (0, import_react6.useMemo)(() => {
|
|
327
356
|
const sdkPix = subscription.pixPending;
|
|
328
357
|
if (!sdkPix) return null;
|
|
329
358
|
const liveStatus = subscription.current?.status;
|
|
@@ -336,7 +365,7 @@ function usePaywallState() {
|
|
|
336
365
|
paid
|
|
337
366
|
};
|
|
338
367
|
}, [subscription.pixPending, subscription.current]);
|
|
339
|
-
const monthlyEquivalent = (0,
|
|
368
|
+
const monthlyEquivalent = (0, import_react6.useCallback)(
|
|
340
369
|
(c) => {
|
|
341
370
|
const monthlyCents = plan.data?.priceCents ?? (isFree ? 0 : paywall.prices.monthlyCents);
|
|
342
371
|
const yearlyCents = plan.data?.yearlyPriceCents ?? (isFree ? null : paywall.prices.yearlyCents);
|
|
@@ -345,7 +374,7 @@ function usePaywallState() {
|
|
|
345
374
|
},
|
|
346
375
|
[plan, paywall, isFree]
|
|
347
376
|
);
|
|
348
|
-
const planDerived = (0,
|
|
377
|
+
const planDerived = (0, import_react6.useMemo)(() => {
|
|
349
378
|
if (isFree) return null;
|
|
350
379
|
const monthlyCents = paywall.prices.monthlyCents;
|
|
351
380
|
const yearlyCents = paywall.prices.yearlyCents;
|
|
@@ -361,7 +390,7 @@ function usePaywallState() {
|
|
|
361
390
|
};
|
|
362
391
|
}, [paywall, cycle, isFree]);
|
|
363
392
|
const useDefaultMessages = paywall.mode !== "free" && paywall.errorMessages === "default";
|
|
364
|
-
const buildError = (0,
|
|
393
|
+
const buildError = (0, import_react6.useCallback)(
|
|
365
394
|
(code, fallbackMessage) => ({
|
|
366
395
|
code,
|
|
367
396
|
message: fallbackMessage,
|
|
@@ -369,7 +398,7 @@ function usePaywallState() {
|
|
|
369
398
|
}),
|
|
370
399
|
[useDefaultMessages]
|
|
371
400
|
);
|
|
372
|
-
const submit = (0,
|
|
401
|
+
const submit = (0, import_react6.useCallback)(async () => {
|
|
373
402
|
setSubmitting(true);
|
|
374
403
|
setError(null);
|
|
375
404
|
const methodToUse = selectedMethod;
|
|
@@ -431,7 +460,7 @@ function usePaywallState() {
|
|
|
431
460
|
return void 0;
|
|
432
461
|
}
|
|
433
462
|
}, [selectedMethod, availability, subscription, cycle, cpf, card, buildError]);
|
|
434
|
-
const checkout = (0,
|
|
463
|
+
const checkout = (0, import_react6.useCallback)(
|
|
435
464
|
async (args) => {
|
|
436
465
|
setSubmitting(true);
|
|
437
466
|
setError(null);
|
|
@@ -495,7 +524,7 @@ function usePaywallState() {
|
|
|
495
524
|
},
|
|
496
525
|
[subscription, buildError]
|
|
497
526
|
);
|
|
498
|
-
const cancel = (0,
|
|
527
|
+
const cancel = (0, import_react6.useCallback)(async () => {
|
|
499
528
|
try {
|
|
500
529
|
await subscription.cancel();
|
|
501
530
|
await subscription.refresh();
|
|
@@ -505,14 +534,24 @@ function usePaywallState() {
|
|
|
505
534
|
setError(buildError(code, message));
|
|
506
535
|
}
|
|
507
536
|
}, [subscription, buildError]);
|
|
508
|
-
const cardState = (0,
|
|
537
|
+
const cardState = (0, import_react6.useMemo)(
|
|
509
538
|
() => ({ ...card, set: setCard }),
|
|
510
539
|
[card, setCard]
|
|
511
540
|
);
|
|
512
|
-
const cpfState = (0,
|
|
541
|
+
const cpfState = (0, import_react6.useMemo)(
|
|
513
542
|
() => ({ required: cpfRequired, value: cpf, set: setCpf, valid: cpfValid }),
|
|
514
543
|
[cpfRequired, cpf, cpfValid]
|
|
515
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
|
+
});
|
|
516
555
|
return {
|
|
517
556
|
// Subscription status (reactive, proxied from SDK)
|
|
518
557
|
status,
|
|
@@ -567,10 +606,10 @@ function SubscriptionGate({ Paywall, children }) {
|
|
|
567
606
|
}
|
|
568
607
|
|
|
569
608
|
// src/components/InstallGate/InstallGate.tsx
|
|
570
|
-
var
|
|
609
|
+
var import_react9 = require("react");
|
|
571
610
|
|
|
572
611
|
// src/hooks/useInstallPrompt.ts
|
|
573
|
-
var
|
|
612
|
+
var import_react7 = require("react");
|
|
574
613
|
var ANDROID_PROMPT_WAIT_MS = 3e3;
|
|
575
614
|
var IOS_RE = /iPad|iPhone|iPod/;
|
|
576
615
|
var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
|
|
@@ -705,27 +744,27 @@ function useInstallPrompt(slug) {
|
|
|
705
744
|
const iosBrowser = detectIOSBrowser(ua);
|
|
706
745
|
const androidBrowser = detectAndroidBrowser(ua);
|
|
707
746
|
const inAppApp = detectInAppApp(ua);
|
|
708
|
-
const [isInstallable, setIsInstallable] = (0,
|
|
747
|
+
const [isInstallable, setIsInstallable] = (0, import_react7.useState)(() => {
|
|
709
748
|
if (typeof window === "undefined") return false;
|
|
710
749
|
return window.__pwaInstallPrompt != null;
|
|
711
750
|
});
|
|
712
|
-
const [isInstalled, setIsInstalled] = (0,
|
|
751
|
+
const [isInstalled, setIsInstalled] = (0, import_react7.useState)(() => {
|
|
713
752
|
const { installed } = detectStandalone();
|
|
714
753
|
return installed || readInstalledMarker(slug);
|
|
715
754
|
});
|
|
716
|
-
const [isDismissedSession, setIsDismissedSession] = (0,
|
|
717
|
-
const [isDismissedPermanent, setIsDismissedPermanent] = (0,
|
|
718
|
-
const [skipCount, setSkipCount] = (0,
|
|
719
|
-
const [promptWaitElapsed, setPromptWaitElapsed] = (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)(() => {
|
|
720
759
|
if (typeof window === "undefined") return true;
|
|
721
760
|
return window.__pwaInstallPrompt != null;
|
|
722
761
|
});
|
|
723
|
-
(0,
|
|
762
|
+
(0, import_react7.useEffect)(() => {
|
|
724
763
|
if (promptWaitElapsed) return;
|
|
725
764
|
const id = setTimeout(() => setPromptWaitElapsed(true), ANDROID_PROMPT_WAIT_MS);
|
|
726
765
|
return () => clearTimeout(id);
|
|
727
766
|
}, [promptWaitElapsed]);
|
|
728
|
-
(0,
|
|
767
|
+
(0, import_react7.useEffect)(() => {
|
|
729
768
|
if (typeof window === "undefined") return;
|
|
730
769
|
if (window.__pwaInstallPrompt) {
|
|
731
770
|
setIsInstallable(true);
|
|
@@ -749,7 +788,7 @@ function useInstallPrompt(slug) {
|
|
|
749
788
|
window.removeEventListener("appinstalled", onInstalled);
|
|
750
789
|
};
|
|
751
790
|
}, [slug]);
|
|
752
|
-
(0,
|
|
791
|
+
(0, import_react7.useEffect)(() => {
|
|
753
792
|
if (typeof window === "undefined") return;
|
|
754
793
|
const mq = window.matchMedia?.("(display-mode: standalone)");
|
|
755
794
|
if (!mq) return;
|
|
@@ -776,7 +815,7 @@ function useInstallPrompt(slug) {
|
|
|
776
815
|
},
|
|
777
816
|
promptWaitElapsed
|
|
778
817
|
);
|
|
779
|
-
const promptInstall = (0,
|
|
818
|
+
const promptInstall = (0, import_react7.useCallback)(async () => {
|
|
780
819
|
if (typeof window === "undefined") return false;
|
|
781
820
|
const prompt = window.__pwaInstallPrompt;
|
|
782
821
|
if (!prompt) return false;
|
|
@@ -798,7 +837,7 @@ function useInstallPrompt(slug) {
|
|
|
798
837
|
return false;
|
|
799
838
|
}
|
|
800
839
|
}, [slug]);
|
|
801
|
-
const dismissSession = (0,
|
|
840
|
+
const dismissSession = (0, import_react7.useCallback)(() => {
|
|
802
841
|
if (typeof sessionStorage !== "undefined") {
|
|
803
842
|
try {
|
|
804
843
|
sessionStorage.setItem(storageKey.sessionSkip(slug), "true");
|
|
@@ -812,20 +851,20 @@ function useInstallPrompt(slug) {
|
|
|
812
851
|
setIsDismissedSession(true);
|
|
813
852
|
track("pwa_install_session_skip", { slug, platform, skip_count: newCount });
|
|
814
853
|
}, [slug, skipCount, platform]);
|
|
815
|
-
const dismissPermanent = (0,
|
|
854
|
+
const dismissPermanent = (0, import_react7.useCallback)(() => {
|
|
816
855
|
const storage = safeStorage();
|
|
817
856
|
if (storage) storage.setItem(storageKey.dismissedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
818
857
|
setIsDismissedPermanent(true);
|
|
819
858
|
track("pwa_install_permanent_dismiss", { slug, platform, prior_skip_count: skipCount });
|
|
820
859
|
}, [slug, platform, skipCount]);
|
|
821
|
-
const copyLink = (0,
|
|
860
|
+
const copyLink = (0, import_react7.useCallback)(async () => {
|
|
822
861
|
if (typeof navigator === "undefined" || typeof location === "undefined") return;
|
|
823
862
|
try {
|
|
824
863
|
await navigator.clipboard?.writeText?.(location.href);
|
|
825
864
|
} catch {
|
|
826
865
|
}
|
|
827
866
|
}, []);
|
|
828
|
-
const reset = (0,
|
|
867
|
+
const reset = (0, import_react7.useCallback)(() => {
|
|
829
868
|
const storage = safeStorage();
|
|
830
869
|
if (storage) {
|
|
831
870
|
storage.removeItem(storageKey.dismissedAt(slug));
|
|
@@ -1618,7 +1657,7 @@ function IOSOtherVariant({
|
|
|
1618
1657
|
}
|
|
1619
1658
|
|
|
1620
1659
|
// src/components/InstallGate/variants/InAppBrowserVariant.tsx
|
|
1621
|
-
var
|
|
1660
|
+
var import_react8 = require("react");
|
|
1622
1661
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1623
1662
|
function InAppBrowserVariant({
|
|
1624
1663
|
state,
|
|
@@ -1628,7 +1667,7 @@ function InAppBrowserVariant({
|
|
|
1628
1667
|
const appCopy = INSTALL_COPY.inApp[app] ?? INSTALL_COPY.inApp.other;
|
|
1629
1668
|
const copy = INSTALL_COPY.inApp;
|
|
1630
1669
|
const showPermanent = shouldShowPermanentOption(state);
|
|
1631
|
-
const [copied, setCopied] = (0,
|
|
1670
|
+
const [copied, setCopied] = (0, import_react8.useState)(false);
|
|
1632
1671
|
const handleCopy = async () => {
|
|
1633
1672
|
await actions.copyLink();
|
|
1634
1673
|
setCopied(true);
|
|
@@ -1833,8 +1872,8 @@ function InstallGate({ children }) {
|
|
|
1833
1872
|
const enabled = features_enabled.includes("install_prompt");
|
|
1834
1873
|
const installState = useInstallPrompt(slug);
|
|
1835
1874
|
const shouldBlock = enabled && shouldBlockInstall(installState);
|
|
1836
|
-
const trackedRef = (0,
|
|
1837
|
-
(0,
|
|
1875
|
+
const trackedRef = (0, import_react9.useRef)(null);
|
|
1876
|
+
(0, import_react9.useEffect)(() => {
|
|
1838
1877
|
if (!shouldBlock) return;
|
|
1839
1878
|
if (typeof window === "undefined") return;
|
|
1840
1879
|
const variantKey = `${slug}:${installState.variant}`;
|
|
@@ -1883,16 +1922,16 @@ function PushPrompt() {
|
|
|
1883
1922
|
}
|
|
1884
1923
|
|
|
1885
1924
|
// src/internal/SessionExpiredBanner.tsx
|
|
1886
|
-
var
|
|
1887
|
-
var
|
|
1925
|
+
var import_react10 = require("react");
|
|
1926
|
+
var import_sdk4 = require("@hook-sdk/sdk");
|
|
1888
1927
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1889
1928
|
var DISMISS_KEY = "hook:session-expired-dismissed-until";
|
|
1890
1929
|
var DISMISS_TTL_MS = 60 * 60 * 1e3;
|
|
1891
1930
|
function SessionExpiredBanner() {
|
|
1892
|
-
const { authStatus } = (0,
|
|
1893
|
-
const wasAuthRef = (0,
|
|
1894
|
-
const [show, setShow] = (0,
|
|
1895
|
-
(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)(() => {
|
|
1896
1935
|
if (authStatus === "authenticated") {
|
|
1897
1936
|
wasAuthRef.current = true;
|
|
1898
1937
|
setShow(false);
|
|
@@ -1942,9 +1981,9 @@ function SessionExpiredBanner() {
|
|
|
1942
1981
|
}
|
|
1943
1982
|
|
|
1944
1983
|
// src/defaults/ErrorBoundary.tsx
|
|
1945
|
-
var
|
|
1984
|
+
var import_react11 = require("react");
|
|
1946
1985
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1947
|
-
var ErrorBoundary = class extends
|
|
1986
|
+
var ErrorBoundary = class extends import_react11.Component {
|
|
1948
1987
|
state = { error: null };
|
|
1949
1988
|
static getDerivedStateFromError(error) {
|
|
1950
1989
|
return { error };
|
|
@@ -1971,20 +2010,20 @@ var ErrorBoundary = class extends import_react10.Component {
|
|
|
1971
2010
|
};
|
|
1972
2011
|
|
|
1973
2012
|
// src/internal/PaymentReturnHandler.tsx
|
|
1974
|
-
var
|
|
1975
|
-
var
|
|
2013
|
+
var import_react12 = require("react");
|
|
2014
|
+
var import_sdk5 = require("@hook-sdk/sdk");
|
|
1976
2015
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1977
2016
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
1978
2017
|
var MAX_CYCLES = 3;
|
|
1979
2018
|
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
1980
2019
|
function PaymentReturnHandler({ children }) {
|
|
1981
|
-
const { subscription } = (0,
|
|
1982
|
-
const subRef = (0,
|
|
2020
|
+
const { subscription } = (0, import_sdk5.useHook)();
|
|
2021
|
+
const subRef = (0, import_react12.useRef)(subscription);
|
|
1983
2022
|
subRef.current = subscription;
|
|
1984
|
-
const runIdRef = (0,
|
|
1985
|
-
const cyclesRef = (0,
|
|
1986
|
-
const [state, setState] = (0,
|
|
1987
|
-
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)(() => {
|
|
1988
2027
|
const runId = ++runIdRef.current;
|
|
1989
2028
|
cyclesRef.current += 1;
|
|
1990
2029
|
setState("confirming");
|
|
@@ -2019,7 +2058,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2019
2058
|
};
|
|
2020
2059
|
void tick();
|
|
2021
2060
|
}, []);
|
|
2022
|
-
(0,
|
|
2061
|
+
(0, import_react12.useEffect)(() => {
|
|
2023
2062
|
if (typeof window === "undefined") return;
|
|
2024
2063
|
const url = new URL(window.location.href);
|
|
2025
2064
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -2029,7 +2068,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2029
2068
|
runIdRef.current++;
|
|
2030
2069
|
};
|
|
2031
2070
|
}, [runPoll]);
|
|
2032
|
-
const goHome = (0,
|
|
2071
|
+
const goHome = (0, import_react12.useCallback)(() => {
|
|
2033
2072
|
const cleanUrl = new URL(window.location.href);
|
|
2034
2073
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
2035
2074
|
cleanUrl.pathname = "/app/home";
|
|
@@ -2195,7 +2234,7 @@ function AppRoot(props) {
|
|
|
2195
2234
|
"[hook-template] <AppRoot>: PreAuthFlow slot prop is required when config.onboarding.trigger === 'pre_signup_custom'."
|
|
2196
2235
|
);
|
|
2197
2236
|
}
|
|
2198
|
-
const legacyShim = (0,
|
|
2237
|
+
const legacyShim = (0, import_react13.useMemo)(() => buildLegacyConfigShim(config), [config]);
|
|
2199
2238
|
const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
|
|
2200
2239
|
const basename = `/app/${config.slug}`;
|
|
2201
2240
|
const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
|
|
@@ -2232,7 +2271,7 @@ function AuthGated({
|
|
|
2232
2271
|
EmailVerify,
|
|
2233
2272
|
PreAuthFlow
|
|
2234
2273
|
}) {
|
|
2235
|
-
const { authStatus } = (0,
|
|
2274
|
+
const { authStatus } = (0, import_sdk6.useHook)();
|
|
2236
2275
|
if (authStatus === "loading") return null;
|
|
2237
2276
|
if (authStatus !== "authenticated") {
|
|
2238
2277
|
if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
|
|
@@ -2261,8 +2300,8 @@ function FallbackPaywall() {
|
|
|
2261
2300
|
}
|
|
2262
2301
|
|
|
2263
2302
|
// src/hooks/usePush.ts
|
|
2264
|
-
var
|
|
2265
|
-
var
|
|
2303
|
+
var import_react14 = require("react");
|
|
2304
|
+
var import_sdk7 = require("@hook-sdk/sdk");
|
|
2266
2305
|
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2267
2306
|
var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
2268
2307
|
function detectIosNeedsInstall() {
|
|
@@ -2306,12 +2345,12 @@ function deriveState(push) {
|
|
|
2306
2345
|
return { kind: "prompt" };
|
|
2307
2346
|
}
|
|
2308
2347
|
function usePush() {
|
|
2309
|
-
const { push } = (0,
|
|
2310
|
-
const [state, setState] = (0,
|
|
2311
|
-
(0,
|
|
2348
|
+
const { push } = (0, import_sdk7.useHook)();
|
|
2349
|
+
const [state, setState] = (0, import_react14.useState)(() => deriveState(push));
|
|
2350
|
+
(0, import_react14.useEffect)(() => {
|
|
2312
2351
|
setState(deriveState(push));
|
|
2313
2352
|
}, [push]);
|
|
2314
|
-
const subscribe = (0,
|
|
2353
|
+
const subscribe = (0, import_react14.useCallback)(async () => {
|
|
2315
2354
|
try {
|
|
2316
2355
|
await push.subscribe();
|
|
2317
2356
|
setState({ kind: "subscribed" });
|
|
@@ -2323,7 +2362,7 @@ function usePush() {
|
|
|
2323
2362
|
throw e;
|
|
2324
2363
|
}
|
|
2325
2364
|
}, [push]);
|
|
2326
|
-
const unsubscribe = (0,
|
|
2365
|
+
const unsubscribe = (0, import_react14.useCallback)(async () => {
|
|
2327
2366
|
try {
|
|
2328
2367
|
await push.unsubscribe();
|
|
2329
2368
|
setState({ kind: "prompt" });
|
|
@@ -2332,7 +2371,7 @@ function usePush() {
|
|
|
2332
2371
|
throw e;
|
|
2333
2372
|
}
|
|
2334
2373
|
}, [push]);
|
|
2335
|
-
const dismiss = (0,
|
|
2374
|
+
const dismiss = (0, import_react14.useCallback)(() => {
|
|
2336
2375
|
if (typeof localStorage !== "undefined") {
|
|
2337
2376
|
try {
|
|
2338
2377
|
localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS2));
|
|
@@ -2424,20 +2463,20 @@ function EmptyState({ title, description, action }) {
|
|
|
2424
2463
|
}
|
|
2425
2464
|
|
|
2426
2465
|
// src/hooks/useLoginForm.ts
|
|
2427
|
-
var
|
|
2428
|
-
var
|
|
2466
|
+
var import_react15 = require("react");
|
|
2467
|
+
var import_sdk9 = require("@hook-sdk/sdk");
|
|
2429
2468
|
|
|
2430
2469
|
// src/errors.ts
|
|
2431
|
-
var
|
|
2470
|
+
var import_sdk8 = require("@hook-sdk/sdk");
|
|
2432
2471
|
function mapSdkError(err) {
|
|
2433
|
-
if (err instanceof
|
|
2472
|
+
if (err instanceof import_sdk8.SdkRateLimitError) {
|
|
2434
2473
|
return {
|
|
2435
2474
|
code: "rate_limited",
|
|
2436
2475
|
message: `Aguarde ${err.retryAfter}s e tente novamente.`,
|
|
2437
2476
|
retryAfter: err.retryAfter
|
|
2438
2477
|
};
|
|
2439
2478
|
}
|
|
2440
|
-
if (err instanceof
|
|
2479
|
+
if (err instanceof import_sdk8.SdkAuthError) {
|
|
2441
2480
|
const detail = err.detail;
|
|
2442
2481
|
if (detail === "email_unverified") {
|
|
2443
2482
|
return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
|
|
@@ -2447,7 +2486,7 @@ function mapSdkError(err) {
|
|
|
2447
2486
|
}
|
|
2448
2487
|
return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
|
|
2449
2488
|
}
|
|
2450
|
-
if (err instanceof
|
|
2489
|
+
if (err instanceof import_sdk8.SdkError && err.httpStatus === 0) {
|
|
2451
2490
|
return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
|
|
2452
2491
|
}
|
|
2453
2492
|
if (err instanceof TypeError) {
|
|
@@ -2460,20 +2499,20 @@ function mapSdkError(err) {
|
|
|
2460
2499
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2461
2500
|
var MIN_PASSWORD = 8;
|
|
2462
2501
|
function useLoginForm() {
|
|
2463
|
-
const { auth } = (0,
|
|
2464
|
-
const [email, setEmail] = (0,
|
|
2465
|
-
const [password, setPassword] = (0,
|
|
2466
|
-
const [submitting, setSubmitting] = (0,
|
|
2467
|
-
const [error, setError] = (0,
|
|
2468
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2469
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2470
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2471
|
-
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)(() => {
|
|
2472
2511
|
if (email.length === 0) return null;
|
|
2473
2512
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2474
2513
|
return null;
|
|
2475
2514
|
}, [email]);
|
|
2476
|
-
const validatePassword = (0,
|
|
2515
|
+
const validatePassword = (0, import_react15.useMemo)(() => {
|
|
2477
2516
|
if (password.length === 0) return null;
|
|
2478
2517
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2479
2518
|
return null;
|
|
@@ -2481,7 +2520,7 @@ function useLoginForm() {
|
|
|
2481
2520
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2482
2521
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2483
2522
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2484
|
-
const submit = (0,
|
|
2523
|
+
const submit = (0, import_react15.useCallback)(async () => {
|
|
2485
2524
|
setFormSubmitAttempted(true);
|
|
2486
2525
|
if (!canSubmit) return false;
|
|
2487
2526
|
setSubmitting(true);
|
|
@@ -2515,32 +2554,32 @@ function useLoginForm() {
|
|
|
2515
2554
|
}
|
|
2516
2555
|
|
|
2517
2556
|
// src/hooks/useSignupForm.ts
|
|
2518
|
-
var
|
|
2519
|
-
var
|
|
2557
|
+
var import_react16 = require("react");
|
|
2558
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
2520
2559
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2521
2560
|
var MIN_PASSWORD2 = 8;
|
|
2522
2561
|
function useSignupForm() {
|
|
2523
|
-
const { auth } = (0,
|
|
2524
|
-
const [name, setName] = (0,
|
|
2525
|
-
const [email, setEmail] = (0,
|
|
2526
|
-
const [password, setPassword] = (0,
|
|
2527
|
-
const [submitting, setSubmitting] = (0,
|
|
2528
|
-
const [error, setError] = (0,
|
|
2529
|
-
const [touchedName, setTouchedName] = (0,
|
|
2530
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2531
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2532
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2533
|
-
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)(() => {
|
|
2534
2573
|
if (name.length === 0) return null;
|
|
2535
2574
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2536
2575
|
return null;
|
|
2537
2576
|
}, [name]);
|
|
2538
|
-
const validateEmail = (0,
|
|
2577
|
+
const validateEmail = (0, import_react16.useMemo)(() => {
|
|
2539
2578
|
if (email.length === 0) return null;
|
|
2540
2579
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2541
2580
|
return null;
|
|
2542
2581
|
}, [email]);
|
|
2543
|
-
const validatePassword = (0,
|
|
2582
|
+
const validatePassword = (0, import_react16.useMemo)(() => {
|
|
2544
2583
|
if (password.length === 0) return null;
|
|
2545
2584
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2546
2585
|
return null;
|
|
@@ -2549,7 +2588,7 @@ function useSignupForm() {
|
|
|
2549
2588
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2550
2589
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2551
2590
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2552
|
-
const submit = (0,
|
|
2591
|
+
const submit = (0, import_react16.useCallback)(async () => {
|
|
2553
2592
|
setFormSubmitAttempted(true);
|
|
2554
2593
|
if (!canSubmit) return false;
|
|
2555
2594
|
setSubmitting(true);
|
|
@@ -2587,25 +2626,25 @@ function useSignupForm() {
|
|
|
2587
2626
|
}
|
|
2588
2627
|
|
|
2589
2628
|
// src/hooks/useForgotForm.ts
|
|
2590
|
-
var
|
|
2591
|
-
var
|
|
2629
|
+
var import_react17 = require("react");
|
|
2630
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2592
2631
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2593
2632
|
function useForgotForm() {
|
|
2594
|
-
const { auth } = (0,
|
|
2595
|
-
const [email, setEmail] = (0,
|
|
2596
|
-
const [submitting, setSubmitting] = (0,
|
|
2597
|
-
const [sent, setSent] = (0,
|
|
2598
|
-
const [error, setError] = (0,
|
|
2599
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2600
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2601
|
-
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)(() => {
|
|
2602
2641
|
if (email.length === 0) return null;
|
|
2603
2642
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2604
2643
|
return null;
|
|
2605
2644
|
}, [email]);
|
|
2606
2645
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2607
2646
|
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2608
|
-
const submit = (0,
|
|
2647
|
+
const submit = (0, import_react17.useCallback)(async () => {
|
|
2609
2648
|
setFormSubmitAttempted(true);
|
|
2610
2649
|
if (!canSubmit) return false;
|
|
2611
2650
|
setSubmitting(true);
|
|
@@ -2636,32 +2675,32 @@ function useForgotForm() {
|
|
|
2636
2675
|
}
|
|
2637
2676
|
|
|
2638
2677
|
// src/hooks/useResetForm.ts
|
|
2639
|
-
var
|
|
2640
|
-
var
|
|
2678
|
+
var import_react18 = require("react");
|
|
2679
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
2641
2680
|
var MIN_PASSWORD3 = 12;
|
|
2642
2681
|
function useResetForm() {
|
|
2643
|
-
const { auth } = (0,
|
|
2644
|
-
const [token, setToken] = (0,
|
|
2645
|
-
const [password, setPassword] = (0,
|
|
2646
|
-
const [confirm, setConfirm] = (0,
|
|
2647
|
-
const [submitting, setSubmitting] = (0,
|
|
2648
|
-
const [done, setDone] = (0,
|
|
2649
|
-
const [error, setError] = (0,
|
|
2650
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2651
|
-
const [touchedConfirm, setTouchedConfirm] = (0,
|
|
2652
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2653
|
-
(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)(() => {
|
|
2654
2693
|
if (typeof window === "undefined") return;
|
|
2655
2694
|
const params = new URLSearchParams(window.location.search);
|
|
2656
2695
|
const t = params.get("token");
|
|
2657
2696
|
setToken(t && t.length > 0 ? t : null);
|
|
2658
2697
|
}, []);
|
|
2659
|
-
const validatePassword = (0,
|
|
2698
|
+
const validatePassword = (0, import_react18.useMemo)(() => {
|
|
2660
2699
|
if (password.length === 0) return null;
|
|
2661
2700
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
2662
2701
|
return null;
|
|
2663
2702
|
}, [password]);
|
|
2664
|
-
const validateConfirm = (0,
|
|
2703
|
+
const validateConfirm = (0, import_react18.useMemo)(() => {
|
|
2665
2704
|
if (confirm.length === 0) return null;
|
|
2666
2705
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
2667
2706
|
return null;
|
|
@@ -2669,7 +2708,7 @@ function useResetForm() {
|
|
|
2669
2708
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2670
2709
|
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
2671
2710
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
2672
|
-
const submit = (0,
|
|
2711
|
+
const submit = (0, import_react18.useCallback)(async () => {
|
|
2673
2712
|
setFormSubmitAttempted(true);
|
|
2674
2713
|
if (!canSubmit || token === null) return;
|
|
2675
2714
|
setSubmitting(true);
|
|
@@ -2709,9 +2748,9 @@ function useResetForm() {
|
|
|
2709
2748
|
}
|
|
2710
2749
|
|
|
2711
2750
|
// src/hooks/usePlan.ts
|
|
2712
|
-
var
|
|
2751
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
2713
2752
|
function usePlan() {
|
|
2714
|
-
const { plan } = (0,
|
|
2753
|
+
const { plan } = (0, import_sdk13.useHook)();
|
|
2715
2754
|
return plan;
|
|
2716
2755
|
}
|
|
2717
2756
|
|
|
@@ -2744,12 +2783,12 @@ function discountPercent(anchorCents, realCents) {
|
|
|
2744
2783
|
}
|
|
2745
2784
|
|
|
2746
2785
|
// src/hooks/useAuthPrimitives.ts
|
|
2747
|
-
var
|
|
2748
|
-
var
|
|
2786
|
+
var import_react19 = require("react");
|
|
2787
|
+
var import_sdk14 = require("@hook-sdk/sdk");
|
|
2749
2788
|
var warned = false;
|
|
2750
2789
|
function useAuthPrimitives() {
|
|
2751
|
-
const { auth } = (0,
|
|
2752
|
-
(0,
|
|
2790
|
+
const { auth } = (0, import_sdk14.useHook)();
|
|
2791
|
+
(0, import_react19.useEffect)(() => {
|
|
2753
2792
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
2754
2793
|
warned = true;
|
|
2755
2794
|
console.warn(
|
|
@@ -2771,9 +2810,9 @@ function useAuthPrimitives() {
|
|
|
2771
2810
|
}
|
|
2772
2811
|
|
|
2773
2812
|
// src/hooks/useAuth.ts
|
|
2774
|
-
var
|
|
2813
|
+
var import_sdk15 = require("@hook-sdk/sdk");
|
|
2775
2814
|
function useAuth() {
|
|
2776
|
-
const { user, authStatus, auth } = (0,
|
|
2815
|
+
const { user, authStatus, auth } = (0, import_sdk15.useHook)();
|
|
2777
2816
|
return {
|
|
2778
2817
|
user,
|
|
2779
2818
|
authStatus,
|
|
@@ -2782,23 +2821,23 @@ function useAuth() {
|
|
|
2782
2821
|
}
|
|
2783
2822
|
|
|
2784
2823
|
// src/hooks/useSubscription.ts
|
|
2785
|
-
var
|
|
2824
|
+
var import_sdk16 = require("@hook-sdk/sdk");
|
|
2786
2825
|
function useSubscription() {
|
|
2787
|
-
const { subscription } = (0,
|
|
2826
|
+
const { subscription } = (0, import_sdk16.useHook)();
|
|
2788
2827
|
return {
|
|
2789
2828
|
status: subscription.status()
|
|
2790
2829
|
};
|
|
2791
2830
|
}
|
|
2792
2831
|
|
|
2793
2832
|
// src/hooks/useReminders.ts
|
|
2794
|
-
var
|
|
2795
|
-
var
|
|
2833
|
+
var import_react20 = require("react");
|
|
2834
|
+
var import_sdk17 = require("@hook-sdk/sdk");
|
|
2796
2835
|
function useReminders() {
|
|
2797
|
-
const { push } = (0,
|
|
2836
|
+
const { push } = (0, import_sdk17.useHook)();
|
|
2798
2837
|
const r = push.reminders;
|
|
2799
|
-
const [reminders, setReminders] = (0,
|
|
2800
|
-
const [loading, setLoading] = (0,
|
|
2801
|
-
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 () => {
|
|
2802
2841
|
setLoading(true);
|
|
2803
2842
|
try {
|
|
2804
2843
|
const next = await r.list();
|
|
@@ -2807,38 +2846,38 @@ function useReminders() {
|
|
|
2807
2846
|
setLoading(false);
|
|
2808
2847
|
}
|
|
2809
2848
|
}, [r]);
|
|
2810
|
-
(0,
|
|
2849
|
+
(0, import_react20.useEffect)(() => {
|
|
2811
2850
|
void reload();
|
|
2812
2851
|
}, [reload]);
|
|
2813
|
-
const setReminder = (0,
|
|
2852
|
+
const setReminder = (0, import_react20.useCallback)(async (input) => {
|
|
2814
2853
|
await r.set(input);
|
|
2815
2854
|
await reload();
|
|
2816
2855
|
}, [r, reload]);
|
|
2817
|
-
const deleteReminder = (0,
|
|
2856
|
+
const deleteReminder = (0, import_react20.useCallback)(async (slot) => {
|
|
2818
2857
|
await r.delete(slot);
|
|
2819
2858
|
await reload();
|
|
2820
2859
|
}, [r, reload]);
|
|
2821
|
-
const schedule = (0,
|
|
2860
|
+
const schedule = (0, import_react20.useCallback)(async (items) => {
|
|
2822
2861
|
return r.schedule(items);
|
|
2823
2862
|
}, [r]);
|
|
2824
|
-
const setFallbacks = (0,
|
|
2863
|
+
const setFallbacks = (0, import_react20.useCallback)(async (items) => {
|
|
2825
2864
|
return r.setFallbacks(items);
|
|
2826
2865
|
}, [r]);
|
|
2827
2866
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
2828
2867
|
}
|
|
2829
2868
|
|
|
2830
2869
|
// src/hooks/useToast.ts
|
|
2831
|
-
var
|
|
2870
|
+
var import_react21 = require("react");
|
|
2832
2871
|
function useToast() {
|
|
2833
|
-
const [items, setItems] = (0,
|
|
2834
|
-
const show = (0,
|
|
2872
|
+
const [items, setItems] = (0, import_react21.useState)([]);
|
|
2873
|
+
const show = (0, import_react21.useCallback)((message, kind = "info") => {
|
|
2835
2874
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2836
2875
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
2837
2876
|
setTimeout(() => {
|
|
2838
2877
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2839
2878
|
}, 4e3);
|
|
2840
2879
|
}, []);
|
|
2841
|
-
const dismiss = (0,
|
|
2880
|
+
const dismiss = (0, import_react21.useCallback)((id) => {
|
|
2842
2881
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2843
2882
|
}, []);
|
|
2844
2883
|
return { items, show, dismiss };
|
|
@@ -2873,14 +2912,14 @@ function PreAuthShell({
|
|
|
2873
2912
|
}
|
|
2874
2913
|
|
|
2875
2914
|
// src/OnboardingFlow.tsx
|
|
2876
|
-
var
|
|
2877
|
-
var
|
|
2915
|
+
var import_react23 = require("react");
|
|
2916
|
+
var import_sdk18 = require("@hook-sdk/sdk");
|
|
2878
2917
|
|
|
2879
2918
|
// src/hooks/useOnboardingStep.ts
|
|
2880
|
-
var
|
|
2881
|
-
var OnboardingStepContext = (0,
|
|
2919
|
+
var import_react22 = require("react");
|
|
2920
|
+
var OnboardingStepContext = (0, import_react22.createContext)(null);
|
|
2882
2921
|
function useOnboardingStep() {
|
|
2883
|
-
const ctx = (0,
|
|
2922
|
+
const ctx = (0, import_react22.useContext)(OnboardingStepContext);
|
|
2884
2923
|
if (!ctx) {
|
|
2885
2924
|
throw new Error(
|
|
2886
2925
|
"[hook-template] useOnboardingStep must be used inside <OnboardingFlow>. (G75)"
|
|
@@ -2903,12 +2942,12 @@ function OnboardingFlow({
|
|
|
2903
2942
|
onComplete,
|
|
2904
2943
|
persistKey
|
|
2905
2944
|
}) {
|
|
2906
|
-
const [draft, setDraft, status] = (0,
|
|
2907
|
-
const draftRef = (0,
|
|
2945
|
+
const [draft, setDraft, status] = (0, import_sdk18.usePersistedState)(persistKey, {});
|
|
2946
|
+
const draftRef = (0, import_react23.useRef)(draft);
|
|
2908
2947
|
draftRef.current = draft;
|
|
2909
2948
|
const idx = readPersistedStepIdx(draft);
|
|
2910
2949
|
const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
|
|
2911
|
-
const setIdx = (0,
|
|
2950
|
+
const setIdx = (0, import_react23.useCallback)(
|
|
2912
2951
|
(n) => {
|
|
2913
2952
|
setDraft((prev) => {
|
|
2914
2953
|
const prevIdx = readPersistedStepIdx(prev);
|
|
@@ -2918,7 +2957,7 @@ function OnboardingFlow({
|
|
|
2918
2957
|
},
|
|
2919
2958
|
[setDraft]
|
|
2920
2959
|
);
|
|
2921
|
-
const setValue = (0,
|
|
2960
|
+
const setValue = (0, import_react23.useCallback)(
|
|
2922
2961
|
(patch) => {
|
|
2923
2962
|
draftRef.current = { ...draftRef.current, ...patch };
|
|
2924
2963
|
setDraft((prev) => ({ ...prev, ...patch }));
|
|
@@ -2926,11 +2965,23 @@ function OnboardingFlow({
|
|
|
2926
2965
|
[setDraft]
|
|
2927
2966
|
);
|
|
2928
2967
|
const step = steps[clampedIdx];
|
|
2929
|
-
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)(
|
|
2930
2981
|
() => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
|
|
2931
2982
|
[draft, step]
|
|
2932
2983
|
);
|
|
2933
|
-
const next = (0,
|
|
2984
|
+
const next = (0, import_react23.useCallback)(() => {
|
|
2934
2985
|
if (!step) return;
|
|
2935
2986
|
const current = draftRef.current;
|
|
2936
2987
|
const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
|
|
@@ -2941,8 +2992,8 @@ function OnboardingFlow({
|
|
|
2941
2992
|
setIdx(clampedIdx + 1);
|
|
2942
2993
|
}
|
|
2943
2994
|
}, [clampedIdx, onComplete, step, steps.length, setIdx]);
|
|
2944
|
-
const prevStep = (0,
|
|
2945
|
-
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)(
|
|
2946
2997
|
() => ({
|
|
2947
2998
|
stepIndex: clampedIdx,
|
|
2948
2999
|
totalSteps: steps.length,
|