@hook-sdk/template 0.14.1 → 0.16.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.d.cts CHANGED
@@ -3,7 +3,7 @@ import * as react from 'react';
3
3
  import { ReactNode, ComponentType, Component } from 'react';
4
4
  import * as _hook_sdk_sdk from '@hook-sdk/sdk';
5
5
  import { CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
6
- export { PlanInfo, PlanState } from '@hook-sdk/sdk';
6
+ export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
7
7
  import { z } from 'zod';
8
8
 
9
9
  type Cycle = 'MONTHLY' | 'YEARLY';
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as react from 'react';
3
3
  import { ReactNode, ComponentType, Component } from 'react';
4
4
  import * as _hook_sdk_sdk from '@hook-sdk/sdk';
5
5
  import { CheckoutMethod as CheckoutMethod$1, CheckoutCycle, CheckoutResult, CheckoutCardData, CheckoutHolderInfo, PlanState, ReminderSlot } from '@hook-sdk/sdk';
6
- export { PlanInfo, PlanState } from '@hook-sdk/sdk';
6
+ export { PlanInfo, PlanState, useTrackOnboardingStep } from '@hook-sdk/sdk';
7
7
  import { z } from 'zod';
8
8
 
9
9
  type Cycle = 'MONTHLY' | 'YEARLY';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/AppRoot.tsx
2
2
  import { useMemo as useMemo3 } from "react";
3
3
  import { BrowserRouter, MemoryRouter, Navigate, Route, Routes } from "react-router-dom";
4
- import { useHook as useHook5 } from "@hook-sdk/sdk";
4
+ import { useHook as useHook6 } from "@hook-sdk/sdk";
5
5
 
6
6
  // src/config/AppConfigContext.tsx
7
7
  import { createContext, useContext } from "react";
@@ -179,7 +179,7 @@ function ThemeProvider({ children }) {
179
179
 
180
180
  // src/hooks/usePaywallState.ts
181
181
  import { useCallback, useContext as useContext3, useMemo as useMemo2, useState } from "react";
182
- import { useHook as useHook2 } from "@hook-sdk/sdk";
182
+ import { useHook as useHook3 } from "@hook-sdk/sdk";
183
183
 
184
184
  // src/errors/asaas-pt-br.ts
185
185
  var MAP = {
@@ -200,6 +200,35 @@ function asaasErrorMessage(code) {
200
200
  return MAP[code] ?? "Ocorreu um erro inesperado. Tente novamente em instantes.";
201
201
  }
202
202
 
203
+ // src/hooks/usePaywallTracker.ts
204
+ import { useEffect as useEffect3, useRef } from "react";
205
+ import { useHook as useHook2 } from "@hook-sdk/sdk";
206
+ function deriveStep(s) {
207
+ if (s.pixPaid) return "success";
208
+ if (s.hasError) return "error";
209
+ if (s.pixPendingShown) return "pix_qr_shown";
210
+ if (s.selectedMethod === "card" && s.cpfValid) return "card_form";
211
+ if (s.cpfRequired && !s.cpfValid) return "cpf_input";
212
+ if (s.selectedMethod) return "method_select";
213
+ return "plan_select";
214
+ }
215
+ function usePaywallTracker(snapshot) {
216
+ const ctx = useHook2();
217
+ const track2 = typeof ctx.track === "function" ? ctx.track : void 0;
218
+ const lastStepRef = useRef(null);
219
+ const step = deriveStep(snapshot);
220
+ useEffect3(() => {
221
+ if (lastStepRef.current === step) return;
222
+ lastStepRef.current = step;
223
+ if (!track2) return;
224
+ track2("paywall_step_viewed", {
225
+ step,
226
+ method: snapshot.selectedMethod,
227
+ cycle: snapshot.cycle
228
+ });
229
+ }, [step]);
230
+ }
231
+
203
232
  // src/hooks/usePaywallState.ts
204
233
  function isCheckoutFailure(r) {
205
234
  return "ok" in r && r.ok === false;
@@ -214,7 +243,7 @@ var FALLBACK_PAYWALL = {
214
243
  };
215
244
  var isMethodAvailable = (availability, method) => availability[method] !== false;
216
245
  function usePaywallState() {
217
- const { subscription, plan } = useHook2();
246
+ const { subscription, plan } = useHook3();
218
247
  const configFromCtx = useContext3(AppConfigContext);
219
248
  const paywall = configFromCtx?.paywall ?? FALLBACK_PAYWALL;
220
249
  const isFree = paywall.mode === "free";
@@ -443,6 +472,16 @@ function usePaywallState() {
443
472
  () => ({ required: cpfRequired, value: cpf, set: setCpf, valid: cpfValid }),
444
473
  [cpfRequired, cpf, cpfValid]
445
474
  );
475
+ usePaywallTracker({
476
+ selectedMethod,
477
+ cycle,
478
+ cpfRequired,
479
+ cpfValid,
480
+ pixPendingShown: pixPending !== null,
481
+ pixPaid: pixPending?.paid === true,
482
+ hasError: error !== null,
483
+ submitting
484
+ });
446
485
  return {
447
486
  // Subscription status (reactive, proxied from SDK)
448
487
  status,
@@ -497,10 +536,10 @@ function SubscriptionGate({ Paywall, children }) {
497
536
  }
498
537
 
499
538
  // src/components/InstallGate/InstallGate.tsx
500
- import { useEffect as useEffect4, useRef } from "react";
539
+ import { useEffect as useEffect5, useRef as useRef2 } from "react";
501
540
 
502
541
  // src/hooks/useInstallPrompt.ts
503
- import { useCallback as useCallback2, useEffect as useEffect3, useState as useState2 } from "react";
542
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
504
543
  var ANDROID_PROMPT_WAIT_MS = 3e3;
505
544
  var IOS_RE = /iPad|iPhone|iPod/;
506
545
  var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
@@ -650,12 +689,12 @@ function useInstallPrompt(slug) {
650
689
  if (typeof window === "undefined") return true;
651
690
  return window.__pwaInstallPrompt != null;
652
691
  });
653
- useEffect3(() => {
692
+ useEffect4(() => {
654
693
  if (promptWaitElapsed) return;
655
694
  const id = setTimeout(() => setPromptWaitElapsed(true), ANDROID_PROMPT_WAIT_MS);
656
695
  return () => clearTimeout(id);
657
696
  }, [promptWaitElapsed]);
658
- useEffect3(() => {
697
+ useEffect4(() => {
659
698
  if (typeof window === "undefined") return;
660
699
  if (window.__pwaInstallPrompt) {
661
700
  setIsInstallable(true);
@@ -679,7 +718,7 @@ function useInstallPrompt(slug) {
679
718
  window.removeEventListener("appinstalled", onInstalled);
680
719
  };
681
720
  }, [slug]);
682
- useEffect3(() => {
721
+ useEffect4(() => {
683
722
  if (typeof window === "undefined") return;
684
723
  const mq = window.matchMedia?.("(display-mode: standalone)");
685
724
  if (!mq) return;
@@ -1763,8 +1802,8 @@ function InstallGate({ children }) {
1763
1802
  const enabled = features_enabled.includes("install_prompt");
1764
1803
  const installState = useInstallPrompt(slug);
1765
1804
  const shouldBlock = enabled && shouldBlockInstall(installState);
1766
- const trackedRef = useRef(null);
1767
- useEffect4(() => {
1805
+ const trackedRef = useRef2(null);
1806
+ useEffect5(() => {
1768
1807
  if (!shouldBlock) return;
1769
1808
  if (typeof window === "undefined") return;
1770
1809
  const variantKey = `${slug}:${installState.variant}`;
@@ -1813,16 +1852,16 @@ function PushPrompt() {
1813
1852
  }
1814
1853
 
1815
1854
  // src/internal/SessionExpiredBanner.tsx
1816
- import { useEffect as useEffect5, useRef as useRef2, useState as useState4 } from "react";
1817
- import { useHook as useHook3 } from "@hook-sdk/sdk";
1855
+ import { useEffect as useEffect6, useRef as useRef3, useState as useState4 } from "react";
1856
+ import { useHook as useHook4 } from "@hook-sdk/sdk";
1818
1857
  import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1819
1858
  var DISMISS_KEY = "hook:session-expired-dismissed-until";
1820
1859
  var DISMISS_TTL_MS = 60 * 60 * 1e3;
1821
1860
  function SessionExpiredBanner() {
1822
- const { authStatus } = useHook3();
1823
- const wasAuthRef = useRef2(false);
1861
+ const { authStatus } = useHook4();
1862
+ const wasAuthRef = useRef3(false);
1824
1863
  const [show, setShow] = useState4(false);
1825
- useEffect5(() => {
1864
+ useEffect6(() => {
1826
1865
  if (authStatus === "authenticated") {
1827
1866
  wasAuthRef.current = true;
1828
1867
  setShow(false);
@@ -1901,18 +1940,18 @@ var ErrorBoundary = class extends Component {
1901
1940
  };
1902
1941
 
1903
1942
  // src/internal/PaymentReturnHandler.tsx
1904
- import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef3, useState as useState5 } from "react";
1905
- import { useHook as useHook4 } from "@hook-sdk/sdk";
1943
+ import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef4, useState as useState5 } from "react";
1944
+ import { useHook as useHook5 } from "@hook-sdk/sdk";
1906
1945
  import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1907
1946
  var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
1908
1947
  var MAX_CYCLES = 3;
1909
1948
  var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
1910
1949
  function PaymentReturnHandler({ children }) {
1911
- const { subscription } = useHook4();
1912
- const subRef = useRef3(subscription);
1950
+ const { subscription } = useHook5();
1951
+ const subRef = useRef4(subscription);
1913
1952
  subRef.current = subscription;
1914
- const runIdRef = useRef3(0);
1915
- const cyclesRef = useRef3(0);
1953
+ const runIdRef = useRef4(0);
1954
+ const cyclesRef = useRef4(0);
1916
1955
  const [state, setState] = useState5("idle");
1917
1956
  const runPoll = useCallback3(() => {
1918
1957
  const runId = ++runIdRef.current;
@@ -1949,7 +1988,7 @@ function PaymentReturnHandler({ children }) {
1949
1988
  };
1950
1989
  void tick();
1951
1990
  }, []);
1952
- useEffect6(() => {
1991
+ useEffect7(() => {
1953
1992
  if (typeof window === "undefined") return;
1954
1993
  const url = new URL(window.location.href);
1955
1994
  if (url.searchParams.get("paymentReturn") !== "1") return;
@@ -2162,7 +2201,7 @@ function AuthGated({
2162
2201
  EmailVerify,
2163
2202
  PreAuthFlow
2164
2203
  }) {
2165
- const { authStatus } = useHook5();
2204
+ const { authStatus } = useHook6();
2166
2205
  if (authStatus === "loading") return null;
2167
2206
  if (authStatus !== "authenticated") {
2168
2207
  if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
@@ -2191,8 +2230,8 @@ function FallbackPaywall() {
2191
2230
  }
2192
2231
 
2193
2232
  // src/hooks/usePush.ts
2194
- import { useCallback as useCallback4, useEffect as useEffect7, useState as useState6 } from "react";
2195
- import { useHook as useHook6 } from "@hook-sdk/sdk";
2233
+ import { useCallback as useCallback4, useEffect as useEffect8, useState as useState6 } from "react";
2234
+ import { useHook as useHook7 } from "@hook-sdk/sdk";
2196
2235
  var DISMISS_STORAGE_KEY = "push:dismissed-until";
2197
2236
  var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
2198
2237
  function detectIosNeedsInstall() {
@@ -2236,9 +2275,9 @@ function deriveState(push) {
2236
2275
  return { kind: "prompt" };
2237
2276
  }
2238
2277
  function usePush() {
2239
- const { push } = useHook6();
2278
+ const { push } = useHook7();
2240
2279
  const [state, setState] = useState6(() => deriveState(push));
2241
- useEffect7(() => {
2280
+ useEffect8(() => {
2242
2281
  setState(deriveState(push));
2243
2282
  }, [push]);
2244
2283
  const subscribe = useCallback4(async () => {
@@ -2355,7 +2394,7 @@ function EmptyState({ title, description, action }) {
2355
2394
 
2356
2395
  // src/hooks/useLoginForm.ts
2357
2396
  import { useCallback as useCallback5, useMemo as useMemo4, useState as useState7 } from "react";
2358
- import { useHook as useHook7 } from "@hook-sdk/sdk";
2397
+ import { useHook as useHook8 } from "@hook-sdk/sdk";
2359
2398
 
2360
2399
  // src/errors.ts
2361
2400
  import { SdkError, SdkAuthError, SdkRateLimitError } from "@hook-sdk/sdk";
@@ -2390,7 +2429,7 @@ function mapSdkError(err) {
2390
2429
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2391
2430
  var MIN_PASSWORD = 8;
2392
2431
  function useLoginForm() {
2393
- const { auth } = useHook7();
2432
+ const { auth } = useHook8();
2394
2433
  const [email, setEmail] = useState7("");
2395
2434
  const [password, setPassword] = useState7("");
2396
2435
  const [submitting, setSubmitting] = useState7(false);
@@ -2446,11 +2485,11 @@ function useLoginForm() {
2446
2485
 
2447
2486
  // src/hooks/useSignupForm.ts
2448
2487
  import { useCallback as useCallback6, useMemo as useMemo5, useState as useState8 } from "react";
2449
- import { useHook as useHook8 } from "@hook-sdk/sdk";
2488
+ import { useHook as useHook9 } from "@hook-sdk/sdk";
2450
2489
  var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2451
2490
  var MIN_PASSWORD2 = 8;
2452
2491
  function useSignupForm() {
2453
- const { auth } = useHook8();
2492
+ const { auth } = useHook9();
2454
2493
  const [name, setName] = useState8("");
2455
2494
  const [email, setEmail] = useState8("");
2456
2495
  const [password, setPassword] = useState8("");
@@ -2518,10 +2557,10 @@ function useSignupForm() {
2518
2557
 
2519
2558
  // src/hooks/useForgotForm.ts
2520
2559
  import { useCallback as useCallback7, useMemo as useMemo6, useState as useState9 } from "react";
2521
- import { useHook as useHook9 } from "@hook-sdk/sdk";
2560
+ import { useHook as useHook10 } from "@hook-sdk/sdk";
2522
2561
  var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2523
2562
  function useForgotForm() {
2524
- const { auth } = useHook9();
2563
+ const { auth } = useHook10();
2525
2564
  const [email, setEmail] = useState9("");
2526
2565
  const [submitting, setSubmitting] = useState9(false);
2527
2566
  const [sent, setSent] = useState9(false);
@@ -2566,11 +2605,11 @@ function useForgotForm() {
2566
2605
  }
2567
2606
 
2568
2607
  // src/hooks/useResetForm.ts
2569
- import { useCallback as useCallback8, useEffect as useEffect8, useMemo as useMemo7, useState as useState10 } from "react";
2570
- import { useHook as useHook10 } from "@hook-sdk/sdk";
2608
+ import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo7, useState as useState10 } from "react";
2609
+ import { useHook as useHook11 } from "@hook-sdk/sdk";
2571
2610
  var MIN_PASSWORD3 = 12;
2572
2611
  function useResetForm() {
2573
- const { auth } = useHook10();
2612
+ const { auth } = useHook11();
2574
2613
  const [token, setToken] = useState10(null);
2575
2614
  const [password, setPassword] = useState10("");
2576
2615
  const [confirm, setConfirm] = useState10("");
@@ -2580,7 +2619,7 @@ function useResetForm() {
2580
2619
  const [touchedPassword, setTouchedPassword] = useState10(false);
2581
2620
  const [touchedConfirm, setTouchedConfirm] = useState10(false);
2582
2621
  const [formSubmitAttempted, setFormSubmitAttempted] = useState10(false);
2583
- useEffect8(() => {
2622
+ useEffect9(() => {
2584
2623
  if (typeof window === "undefined") return;
2585
2624
  const params = new URLSearchParams(window.location.search);
2586
2625
  const t = params.get("token");
@@ -2639,9 +2678,9 @@ function useResetForm() {
2639
2678
  }
2640
2679
 
2641
2680
  // src/hooks/usePlan.ts
2642
- import { useHook as useHook11 } from "@hook-sdk/sdk";
2681
+ import { useHook as useHook12 } from "@hook-sdk/sdk";
2643
2682
  function usePlan() {
2644
- const { plan } = useHook11();
2683
+ const { plan } = useHook12();
2645
2684
  return plan;
2646
2685
  }
2647
2686
 
@@ -2674,12 +2713,12 @@ function discountPercent(anchorCents, realCents) {
2674
2713
  }
2675
2714
 
2676
2715
  // src/hooks/useAuthPrimitives.ts
2677
- import { useEffect as useEffect9 } from "react";
2678
- import { useHook as useHook12 } from "@hook-sdk/sdk";
2716
+ import { useEffect as useEffect10 } from "react";
2717
+ import { useHook as useHook13 } from "@hook-sdk/sdk";
2679
2718
  var warned = false;
2680
2719
  function useAuthPrimitives() {
2681
- const { auth } = useHook12();
2682
- useEffect9(() => {
2720
+ const { auth } = useHook13();
2721
+ useEffect10(() => {
2683
2722
  if (!warned && process.env.NODE_ENV !== "production") {
2684
2723
  warned = true;
2685
2724
  console.warn(
@@ -2701,9 +2740,9 @@ function useAuthPrimitives() {
2701
2740
  }
2702
2741
 
2703
2742
  // src/hooks/useAuth.ts
2704
- import { useHook as useHook13 } from "@hook-sdk/sdk";
2743
+ import { useHook as useHook14 } from "@hook-sdk/sdk";
2705
2744
  function useAuth() {
2706
- const { user, authStatus, auth } = useHook13();
2745
+ const { user, authStatus, auth } = useHook14();
2707
2746
  return {
2708
2747
  user,
2709
2748
  authStatus,
@@ -2711,20 +2750,23 @@ function useAuth() {
2711
2750
  };
2712
2751
  }
2713
2752
 
2753
+ // src/index.ts
2754
+ import { useTrackOnboardingStep } from "@hook-sdk/sdk";
2755
+
2714
2756
  // src/hooks/useSubscription.ts
2715
- import { useHook as useHook14 } from "@hook-sdk/sdk";
2757
+ import { useHook as useHook15 } from "@hook-sdk/sdk";
2716
2758
  function useSubscription() {
2717
- const { subscription } = useHook14();
2759
+ const { subscription } = useHook15();
2718
2760
  return {
2719
2761
  status: subscription.status()
2720
2762
  };
2721
2763
  }
2722
2764
 
2723
2765
  // src/hooks/useReminders.ts
2724
- import { useCallback as useCallback9, useEffect as useEffect10, useState as useState11 } from "react";
2725
- import { useHook as useHook15 } from "@hook-sdk/sdk";
2766
+ import { useCallback as useCallback9, useEffect as useEffect11, useState as useState11 } from "react";
2767
+ import { useHook as useHook16 } from "@hook-sdk/sdk";
2726
2768
  function useReminders() {
2727
- const { push } = useHook15();
2769
+ const { push } = useHook16();
2728
2770
  const r = push.reminders;
2729
2771
  const [reminders, setReminders] = useState11([]);
2730
2772
  const [loading, setLoading] = useState11(true);
@@ -2737,7 +2779,7 @@ function useReminders() {
2737
2779
  setLoading(false);
2738
2780
  }
2739
2781
  }, [r]);
2740
- useEffect10(() => {
2782
+ useEffect11(() => {
2741
2783
  void reload();
2742
2784
  }, [reload]);
2743
2785
  const setReminder = useCallback9(async (input) => {
@@ -2803,8 +2845,8 @@ function PreAuthShell({
2803
2845
  }
2804
2846
 
2805
2847
  // src/OnboardingFlow.tsx
2806
- import { useCallback as useCallback11, useMemo as useMemo8, useRef as useRef4 } from "react";
2807
- import { usePersistedState } from "@hook-sdk/sdk";
2848
+ import { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef5 } from "react";
2849
+ import { usePersistedState, useHook as useHook17 } from "@hook-sdk/sdk";
2808
2850
 
2809
2851
  // src/hooks/useOnboardingStep.ts
2810
2852
  import { createContext as createContext3, useContext as useContext4 } from "react";
@@ -2834,7 +2876,7 @@ function OnboardingFlow({
2834
2876
  persistKey
2835
2877
  }) {
2836
2878
  const [draft, setDraft, status] = usePersistedState(persistKey, {});
2837
- const draftRef = useRef4(draft);
2879
+ const draftRef = useRef5(draft);
2838
2880
  draftRef.current = draft;
2839
2881
  const idx = readPersistedStepIdx(draft);
2840
2882
  const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
@@ -2856,6 +2898,18 @@ function OnboardingFlow({
2856
2898
  [setDraft]
2857
2899
  );
2858
2900
  const step = steps[clampedIdx];
2901
+ const hookCtx = useHook17();
2902
+ const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
2903
+ useEffect12(() => {
2904
+ if (status.loading) return;
2905
+ if (!step) return;
2906
+ if (!track2) return;
2907
+ track2("onboarding_step_viewed", {
2908
+ step: step.id,
2909
+ step_index: clampedIdx,
2910
+ total_steps: steps.length
2911
+ });
2912
+ }, [step?.id, clampedIdx, steps.length, status.loading, track2]);
2859
2913
  const valid = useMemo8(
2860
2914
  () => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
2861
2915
  [draft, step]
@@ -2951,6 +3005,7 @@ export {
2951
3005
  useResetForm,
2952
3006
  useSignupForm,
2953
3007
  useSubscription,
2954
- useToast
3008
+ useToast,
3009
+ useTrackOnboardingStep
2955
3010
  };
2956
3011
  //# sourceMappingURL=index.js.map