@hook-sdk/template 0.7.3 → 0.8.1

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/AppRoot.tsx
2
- import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef3, useState as useState11 } from "react";
2
+ import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef3, useState as useState12 } from "react";
3
3
  import { useHook as useHook8 } from "@hook-sdk/sdk";
4
4
 
5
5
  // src/internal/TemplateConfigContext.tsx
@@ -213,17 +213,37 @@ function SubscriptionGate({ Paywall, children }) {
213
213
  }
214
214
 
215
215
  // src/internal/PersistedKeysPrefetch.tsx
216
- import { useEffect as useEffect3 } from "react";
216
+ import { useEffect as useEffect3, useState as useState3 } from "react";
217
217
  import { useHook as useHook3 } from "@hook-sdk/sdk";
218
218
  import { Fragment as Fragment3, jsx as jsx6 } from "react/jsx-runtime";
219
+ var SAFETY_TIMEOUT_MS = 3e3;
219
220
  function PersistedKeysPrefetch({ children }) {
220
221
  const { appData } = useHook3();
221
222
  const config = useTemplateConfig();
223
+ const hasKeys = !!config.persistedKeys && config.persistedKeys.length > 0;
224
+ const [ready, setReady] = useState3(!hasKeys);
222
225
  useEffect3(() => {
223
226
  const keys = config.persistedKeys;
224
- if (!keys || keys.length === 0) return;
227
+ if (!keys || keys.length === 0) {
228
+ setReady(true);
229
+ return;
230
+ }
231
+ let cancelled = false;
225
232
  appData.cache.startPrefetch(keys, (ks) => appData.bulkRead(ks));
233
+ void appData.cache.waitForPrimed(SAFETY_TIMEOUT_MS).then((result) => {
234
+ if (cancelled) return;
235
+ if (result === "timeout") {
236
+ console.warn(
237
+ `[@hook-sdk/template] PersistedKeysPrefetch: bulk-read n\xE3o completou em ${SAFETY_TIMEOUT_MS}ms. Liberando render mesmo assim \u2014 usePersistedState pode expor defaultValue at\xE9 o fetch terminar (G77).`
238
+ );
239
+ }
240
+ setReady(true);
241
+ });
242
+ return () => {
243
+ cancelled = true;
244
+ };
226
245
  }, [appData, config.persistedKeys]);
246
+ if (!ready) return null;
227
247
  return /* @__PURE__ */ jsx6(Fragment3, { children });
228
248
  }
229
249
 
@@ -236,7 +256,7 @@ function PushPrompt() {
236
256
  import { useEffect as useEffect5, useRef as useRef2 } from "react";
237
257
 
238
258
  // src/hooks/useInstallPrompt.ts
239
- import { useCallback as useCallback2, useEffect as useEffect4, useState as useState3 } from "react";
259
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState4 } from "react";
240
260
  var IOS_RE = /iPad|iPhone|iPod/;
241
261
  var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
242
262
  var ANDROID_RE = /Android/;
@@ -369,17 +389,17 @@ function useInstallPrompt(slug) {
369
389
  const iosBrowser = detectIOSBrowser(ua);
370
390
  const androidBrowser = detectAndroidBrowser(ua);
371
391
  const inAppApp = detectInAppApp(ua);
372
- const [isInstallable, setIsInstallable] = useState3(() => {
392
+ const [isInstallable, setIsInstallable] = useState4(() => {
373
393
  if (typeof window === "undefined") return false;
374
394
  return window.__pwaInstallPrompt != null;
375
395
  });
376
- const [isInstalled, setIsInstalled] = useState3(() => {
396
+ const [isInstalled, setIsInstalled] = useState4(() => {
377
397
  const { installed } = detectStandalone();
378
398
  return installed || readInstalledMarker(slug);
379
399
  });
380
- const [isDismissedSession, setIsDismissedSession] = useState3(() => readSessionSkip(slug));
381
- const [isDismissedPermanent, setIsDismissedPermanent] = useState3(() => readPermanentDismiss(slug).dismissed);
382
- const [skipCount, setSkipCount] = useState3(() => readSkipCount(slug));
400
+ const [isDismissedSession, setIsDismissedSession] = useState4(() => readSessionSkip(slug));
401
+ const [isDismissedPermanent, setIsDismissedPermanent] = useState4(() => readPermanentDismiss(slug).dismissed);
402
+ const [skipCount, setSkipCount] = useState4(() => readSkipCount(slug));
383
403
  useEffect4(() => {
384
404
  if (typeof window === "undefined") return;
385
405
  if (window.__pwaInstallPrompt) {
@@ -1234,7 +1254,7 @@ function IOSOtherVariant({
1234
1254
  }
1235
1255
 
1236
1256
  // src/components/InstallGate/variants/InAppBrowserVariant.tsx
1237
- import { useState as useState4 } from "react";
1257
+ import { useState as useState5 } from "react";
1238
1258
  import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1239
1259
  function InAppBrowserVariant({
1240
1260
  state,
@@ -1244,7 +1264,7 @@ function InAppBrowserVariant({
1244
1264
  const appCopy = INSTALL_COPY.inApp[app] ?? INSTALL_COPY.inApp.other;
1245
1265
  const copy = INSTALL_COPY.inApp;
1246
1266
  const showPermanent = shouldShowPermanentOption(state);
1247
- const [copied, setCopied] = useState4(false);
1267
+ const [copied, setCopied] = useState5(false);
1248
1268
  const handleCopy = async () => {
1249
1269
  await actions.copyLink();
1250
1270
  setCopied(true);
@@ -1467,9 +1487,10 @@ function InstallGate({ children }) {
1467
1487
  if (!enabled) return /* @__PURE__ */ jsx16(Fragment4, { children });
1468
1488
  if (installState.isInstalled) return /* @__PURE__ */ jsx16(Fragment4, { children });
1469
1489
  if (installState.variant === "desktop") {
1490
+ const showBanner = !installState.isDismissedSession && !installState.isDismissedPermanent;
1470
1491
  return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1471
1492
  children,
1472
- /* @__PURE__ */ jsx16(DesktopVariant, { state: installState, actions: installState })
1493
+ showBanner && /* @__PURE__ */ jsx16(DesktopVariant, { state: installState, actions: installState })
1473
1494
  ] });
1474
1495
  }
1475
1496
  if (!shouldBlock) return /* @__PURE__ */ jsx16(Fragment4, { children });
@@ -1513,7 +1534,7 @@ var ErrorBoundary = class extends Component {
1513
1534
  };
1514
1535
 
1515
1536
  // src/hooks/useLoginForm.ts
1516
- import { useCallback as useCallback3, useMemo as useMemo2, useState as useState5 } from "react";
1537
+ import { useCallback as useCallback3, useMemo as useMemo2, useState as useState6 } from "react";
1517
1538
  import { useHook as useHook4 } from "@hook-sdk/sdk";
1518
1539
 
1519
1540
  // src/errors.ts
@@ -1550,10 +1571,10 @@ var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1550
1571
  var MIN_PASSWORD = 8;
1551
1572
  function useLoginForm() {
1552
1573
  const { auth } = useHook4();
1553
- const [email, setEmail] = useState5("");
1554
- const [password, setPassword] = useState5("");
1555
- const [submitting, setSubmitting] = useState5(false);
1556
- const [error, setError] = useState5(null);
1574
+ const [email, setEmail] = useState6("");
1575
+ const [password, setPassword] = useState6("");
1576
+ const [submitting, setSubmitting] = useState6(false);
1577
+ const [error, setError] = useState6(null);
1557
1578
  const emailError = useMemo2(() => {
1558
1579
  if (email.length === 0) return null;
1559
1580
  if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
@@ -1664,7 +1685,7 @@ function GoogleGlyph() {
1664
1685
  }
1665
1686
 
1666
1687
  // src/internal/OAuthErrorBanner.tsx
1667
- import { useEffect as useEffect6, useState as useState6 } from "react";
1688
+ import { useEffect as useEffect6, useState as useState7 } from "react";
1668
1689
  import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1669
1690
  var ERROR_MESSAGES = {
1670
1691
  invalid_state: "Sess\xE3o expirou, tente de novo.",
@@ -1685,7 +1706,7 @@ function stripErrorFromUrl() {
1685
1706
  window.history.replaceState({}, "", url.toString());
1686
1707
  }
1687
1708
  function OAuthErrorBanner() {
1688
- const [code, setCode] = useState6(() => readErrorCode());
1709
+ const [code, setCode] = useState7(() => readErrorCode());
1689
1710
  useEffect6(() => {
1690
1711
  if (code !== null) stripErrorFromUrl();
1691
1712
  }, [code]);
@@ -1819,17 +1840,17 @@ function DefaultLoginScreen({ onNavigate }) {
1819
1840
  }
1820
1841
 
1821
1842
  // src/hooks/useSignupForm.ts
1822
- import { useCallback as useCallback4, useMemo as useMemo3, useState as useState7 } from "react";
1843
+ import { useCallback as useCallback4, useMemo as useMemo3, useState as useState8 } from "react";
1823
1844
  import { useHook as useHook5 } from "@hook-sdk/sdk";
1824
1845
  var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1825
1846
  var MIN_PASSWORD2 = 8;
1826
1847
  function useSignupForm() {
1827
1848
  const { auth } = useHook5();
1828
- const [name, setName] = useState7("");
1829
- const [email, setEmail] = useState7("");
1830
- const [password, setPassword] = useState7("");
1831
- const [submitting, setSubmitting] = useState7(false);
1832
- const [error, setError] = useState7(null);
1849
+ const [name, setName] = useState8("");
1850
+ const [email, setEmail] = useState8("");
1851
+ const [password, setPassword] = useState8("");
1852
+ const [submitting, setSubmitting] = useState8(false);
1853
+ const [error, setError] = useState8(null);
1833
1854
  const nameError = useMemo3(() => {
1834
1855
  if (name.length === 0) return null;
1835
1856
  if (name.trim().length < 2) return "Nome muito curto.";
@@ -1934,15 +1955,15 @@ function DefaultSignupScreen({ onNavigate }) {
1934
1955
  }
1935
1956
 
1936
1957
  // src/hooks/useForgotForm.ts
1937
- import { useCallback as useCallback5, useMemo as useMemo4, useState as useState8 } from "react";
1958
+ import { useCallback as useCallback5, useMemo as useMemo4, useState as useState9 } from "react";
1938
1959
  import { useHook as useHook6 } from "@hook-sdk/sdk";
1939
1960
  var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1940
1961
  function useForgotForm() {
1941
1962
  const { auth } = useHook6();
1942
- const [email, setEmail] = useState8("");
1943
- const [submitting, setSubmitting] = useState8(false);
1944
- const [sent, setSent] = useState8(false);
1945
- const [error, setError] = useState8(null);
1963
+ const [email, setEmail] = useState9("");
1964
+ const [submitting, setSubmitting] = useState9(false);
1965
+ const [sent, setSent] = useState9(false);
1966
+ const [error, setError] = useState9(null);
1946
1967
  const emailError = useMemo4(() => {
1947
1968
  if (email.length === 0) return null;
1948
1969
  if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
@@ -2008,17 +2029,17 @@ function DefaultForgotScreen({ onNavigate }) {
2008
2029
  }
2009
2030
 
2010
2031
  // src/hooks/useResetForm.ts
2011
- import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo5, useState as useState9 } from "react";
2032
+ import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo5, useState as useState10 } from "react";
2012
2033
  import { useHook as useHook7 } from "@hook-sdk/sdk";
2013
2034
  var MIN_PASSWORD3 = 12;
2014
2035
  function useResetForm() {
2015
2036
  const { auth } = useHook7();
2016
- const [token, setToken] = useState9(null);
2017
- const [password, setPassword] = useState9("");
2018
- const [confirm, setConfirm] = useState9("");
2019
- const [submitting, setSubmitting] = useState9(false);
2020
- const [done, setDone] = useState9(false);
2021
- const [error, setError] = useState9(null);
2037
+ const [token, setToken] = useState10(null);
2038
+ const [password, setPassword] = useState10("");
2039
+ const [confirm, setConfirm] = useState10("");
2040
+ const [submitting, setSubmitting] = useState10(false);
2041
+ const [done, setDone] = useState10(false);
2042
+ const [error, setError] = useState10(null);
2022
2043
  useEffect7(() => {
2023
2044
  if (typeof window === "undefined") return;
2024
2045
  const params = new URLSearchParams(window.location.search);
@@ -2114,13 +2135,13 @@ function DefaultResetScreen({ onNavigate }) {
2114
2135
  }
2115
2136
 
2116
2137
  // src/defaults/DefaultPaywall.tsx
2117
- import { useState as useState10 } from "react";
2138
+ import { useState as useState11 } from "react";
2118
2139
  import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
2119
2140
  function DefaultPaywall() {
2120
2141
  const config = useTemplateConfig();
2121
2142
  const { checkout, opening, error } = usePaywallState();
2122
2143
  const p = config.subscription.paywall_config;
2123
- const [cpf, setCpf] = useState10("");
2144
+ const [cpf, setCpf] = useState11("");
2124
2145
  const cpfDigits = cpf.replace(/\D/g, "");
2125
2146
  const canCheckout = cpfDigits.length === 11 && !opening;
2126
2147
  return /* @__PURE__ */ jsxs18("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
@@ -2180,7 +2201,7 @@ function PaymentReturnHandler({ children }) {
2180
2201
  const subRef = useRef3(subscription);
2181
2202
  subRef.current = subscription;
2182
2203
  const runIdRef = useRef3(0);
2183
- const [state, setState] = useState11("idle");
2204
+ const [state, setState] = useState12("idle");
2184
2205
  const runPoll = useCallback7(() => {
2185
2206
  const runId = ++runIdRef.current;
2186
2207
  setState("confirming");
@@ -2284,7 +2305,7 @@ function AppRoot({
2284
2305
  }
2285
2306
 
2286
2307
  // src/hooks/usePush.ts
2287
- import { useCallback as useCallback8, useEffect as useEffect9, useState as useState12 } from "react";
2308
+ import { useCallback as useCallback8, useEffect as useEffect9, useState as useState13 } from "react";
2288
2309
  import { useHook as useHook9 } from "@hook-sdk/sdk";
2289
2310
  function detectIosNeedsInstall() {
2290
2311
  if (typeof navigator === "undefined" || typeof window === "undefined") return false;
@@ -2312,7 +2333,7 @@ function deriveState(push) {
2312
2333
  }
2313
2334
  function usePush() {
2314
2335
  const { push } = useHook9();
2315
- const [state, setState] = useState12(() => deriveState(push));
2336
+ const [state, setState] = useState13(() => deriveState(push));
2316
2337
  useEffect9(() => {
2317
2338
  setState(deriveState(push));
2318
2339
  }, [push]);
@@ -2465,13 +2486,13 @@ function useSubscription() {
2465
2486
  }
2466
2487
 
2467
2488
  // src/hooks/useReminders.ts
2468
- import { useCallback as useCallback9, useEffect as useEffect11, useState as useState13 } from "react";
2489
+ import { useCallback as useCallback9, useEffect as useEffect11, useState as useState14 } from "react";
2469
2490
  import { useHook as useHook13 } from "@hook-sdk/sdk";
2470
2491
  function useReminders() {
2471
2492
  const { push } = useHook13();
2472
2493
  const r = push.reminders;
2473
- const [reminders, setReminders] = useState13([]);
2474
- const [loading, setLoading] = useState13(true);
2494
+ const [reminders, setReminders] = useState14([]);
2495
+ const [loading, setLoading] = useState14(true);
2475
2496
  const reload = useCallback9(async () => {
2476
2497
  setLoading(true);
2477
2498
  try {
@@ -2502,9 +2523,9 @@ function useReminders() {
2502
2523
  }
2503
2524
 
2504
2525
  // src/hooks/useToast.ts
2505
- import { useCallback as useCallback10, useState as useState14 } from "react";
2526
+ import { useCallback as useCallback10, useState as useState15 } from "react";
2506
2527
  function useToast() {
2507
- const [items, setItems] = useState14([]);
2528
+ const [items, setItems] = useState15([]);
2508
2529
  const show = useCallback10((message, kind = "info") => {
2509
2530
  const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2510
2531
  setItems((prev) => [...prev, { id, message, kind }]);