@hook-sdk/template 0.14.0 → 0.14.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
@@ -77,7 +77,11 @@ var DeepLinksSchema = z.object({
77
77
  var AppConfigSchema = z.object({
78
78
  slug: z.string().regex(/^[a-z0-9-]+$/),
79
79
  name: z.string().min(1),
80
- branding: z.object({ primaryColor: z.string(), logoUrl: z.string().url() }),
80
+ branding: z.object({
81
+ primaryColor: z.string(),
82
+ logoUrl: z.string().url(),
83
+ iconUrl: z.string().url().optional()
84
+ }),
81
85
  authFlow: AuthFlowSchema,
82
86
  paywall: PaywallSchema,
83
87
  persistedKeys: z.array(PersistedKeySchema),
@@ -497,6 +501,7 @@ import { useEffect as useEffect4, useRef } from "react";
497
501
 
498
502
  // src/hooks/useInstallPrompt.ts
499
503
  import { useCallback as useCallback2, useEffect as useEffect3, useState as useState2 } from "react";
504
+ var ANDROID_PROMPT_WAIT_MS = 3e3;
500
505
  var IOS_RE = /iPad|iPhone|iPod/;
501
506
  var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
502
507
  var ANDROID_RE = /Android/;
@@ -566,11 +571,12 @@ function track(event, props) {
566
571
  if (typeof window === "undefined") return;
567
572
  window.posthog?.capture?.(event, props);
568
573
  }
569
- function pickVariant(state) {
574
+ function pickVariant(state, promptWaitElapsed) {
570
575
  if (state.isInstalled) return "none";
571
576
  switch (state.platform) {
572
577
  case "android":
573
- return state.isInstallable ? "android-native" : "android-manual";
578
+ if (state.isInstallable) return "android-native";
579
+ return promptWaitElapsed ? "android-manual" : "android-pending";
574
580
  case "ios-safari":
575
581
  return "ios-safari";
576
582
  case "ios-other":
@@ -640,6 +646,15 @@ function useInstallPrompt(slug) {
640
646
  const [isDismissedSession, setIsDismissedSession] = useState2(() => readSessionSkip(slug));
641
647
  const [isDismissedPermanent, setIsDismissedPermanent] = useState2(() => readPermanentDismiss(slug).dismissed);
642
648
  const [skipCount, setSkipCount] = useState2(() => readSkipCount(slug));
649
+ const [promptWaitElapsed, setPromptWaitElapsed] = useState2(() => {
650
+ if (typeof window === "undefined") return true;
651
+ return window.__pwaInstallPrompt != null;
652
+ });
653
+ useEffect3(() => {
654
+ if (promptWaitElapsed) return;
655
+ const id = setTimeout(() => setPromptWaitElapsed(true), ANDROID_PROMPT_WAIT_MS);
656
+ return () => clearTimeout(id);
657
+ }, [promptWaitElapsed]);
643
658
  useEffect3(() => {
644
659
  if (typeof window === "undefined") return;
645
660
  if (window.__pwaInstallPrompt) {
@@ -677,17 +692,20 @@ function useInstallPrompt(slug) {
677
692
  mq.addEventListener?.("change", handler);
678
693
  return () => mq.removeEventListener?.("change", handler);
679
694
  }, [slug]);
680
- const variant = pickVariant({
681
- platform,
682
- iosBrowser,
683
- androidBrowser,
684
- inAppApp,
685
- isInstallable,
686
- isInstalled,
687
- isDismissedSession,
688
- isDismissedPermanent,
689
- skipCount
690
- });
695
+ const variant = pickVariant(
696
+ {
697
+ platform,
698
+ iosBrowser,
699
+ androidBrowser,
700
+ inAppApp,
701
+ isInstallable,
702
+ isInstalled,
703
+ isDismissedSession,
704
+ isDismissedPermanent,
705
+ skipCount
706
+ },
707
+ promptWaitElapsed
708
+ );
691
709
  const promptInstall = useCallback2(async () => {
692
710
  if (typeof window === "undefined") return false;
693
711
  const prompt = window.__pwaInstallPrompt;
@@ -1223,8 +1241,44 @@ function Step({ n, icon, children }) {
1223
1241
  );
1224
1242
  }
1225
1243
 
1244
+ // src/components/InstallGate/variants/AndroidPendingVariant.tsx
1245
+ import { jsx as jsx10 } from "react/jsx-runtime";
1246
+ function AndroidPendingVariant() {
1247
+ const copy = INSTALL_COPY.android.native;
1248
+ return /* @__PURE__ */ jsx10(InstallSplash, { title: copy.title, children: /* @__PURE__ */ jsx10(
1249
+ "div",
1250
+ {
1251
+ style: {
1252
+ display: "flex",
1253
+ flexDirection: "column",
1254
+ alignItems: "center",
1255
+ gap: 16,
1256
+ padding: "24px 0"
1257
+ },
1258
+ children: /* @__PURE__ */ jsx10(Spinner, {})
1259
+ }
1260
+ ) });
1261
+ }
1262
+ function Spinner() {
1263
+ return /* @__PURE__ */ jsx10(
1264
+ "div",
1265
+ {
1266
+ "aria-hidden": true,
1267
+ style: {
1268
+ width: 28,
1269
+ height: 28,
1270
+ borderRadius: "50%",
1271
+ border: "3px solid #e5e5e7",
1272
+ borderTopColor: "var(--hook-color-primary)",
1273
+ animation: "hook-install-spin 0.8s linear infinite"
1274
+ },
1275
+ children: /* @__PURE__ */ jsx10("style", { children: `@keyframes hook-install-spin { to { transform: rotate(360deg); } }` })
1276
+ }
1277
+ );
1278
+ }
1279
+
1226
1280
  // src/components/InstallGate/Step.tsx
1227
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1281
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1228
1282
  function Step2({
1229
1283
  n,
1230
1284
  title,
@@ -1242,7 +1296,7 @@ function Step2({
1242
1296
  textAlign: "left"
1243
1297
  },
1244
1298
  children: [
1245
- /* @__PURE__ */ jsx10(
1299
+ /* @__PURE__ */ jsx11(
1246
1300
  "div",
1247
1301
  {
1248
1302
  style: {
@@ -1262,8 +1316,8 @@ function Step2({
1262
1316
  }
1263
1317
  ),
1264
1318
  /* @__PURE__ */ jsxs5("div", { style: { flex: 1 }, children: [
1265
- /* @__PURE__ */ jsx10("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
1266
- subtitle && /* @__PURE__ */ jsx10("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
1319
+ /* @__PURE__ */ jsx11("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
1320
+ subtitle && /* @__PURE__ */ jsx11("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
1267
1321
  visual
1268
1322
  ] })
1269
1323
  ]
@@ -1272,7 +1326,7 @@ function Step2({
1272
1326
  }
1273
1327
 
1274
1328
  // src/components/InstallGate/variants/IOSafariVariant.tsx
1275
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1329
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1276
1330
  function IOSafariVariant({
1277
1331
  state,
1278
1332
  actions
@@ -1280,13 +1334,13 @@ function IOSafariVariant({
1280
1334
  const copy = INSTALL_COPY.iosSafari;
1281
1335
  const showPermanent = shouldShowPermanentOption(state);
1282
1336
  return /* @__PURE__ */ jsxs6(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1283
- /* @__PURE__ */ jsx11(
1337
+ /* @__PURE__ */ jsx12(
1284
1338
  Step2,
1285
1339
  {
1286
1340
  n: 1,
1287
1341
  title: copy.step1.title,
1288
1342
  subtitle: copy.step1.subtitle,
1289
- visual: /* @__PURE__ */ jsx11(
1343
+ visual: /* @__PURE__ */ jsx12(
1290
1344
  "div",
1291
1345
  {
1292
1346
  style: {
@@ -1298,12 +1352,12 @@ function IOSafariVariant({
1298
1352
  padding: "12px 0",
1299
1353
  marginTop: 8
1300
1354
  },
1301
- children: /* @__PURE__ */ jsx11(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1355
+ children: /* @__PURE__ */ jsx12(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1302
1356
  }
1303
1357
  )
1304
1358
  }
1305
1359
  ),
1306
- /* @__PURE__ */ jsx11(
1360
+ /* @__PURE__ */ jsx12(
1307
1361
  Step2,
1308
1362
  {
1309
1363
  n: 2,
@@ -1321,19 +1375,19 @@ function IOSafariVariant({
1321
1375
  marginTop: 8
1322
1376
  },
1323
1377
  children: [
1324
- /* @__PURE__ */ jsx11(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1325
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1378
+ /* @__PURE__ */ jsx12(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1379
+ /* @__PURE__ */ jsx12("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1326
1380
  ]
1327
1381
  }
1328
1382
  )
1329
1383
  }
1330
1384
  ),
1331
- /* @__PURE__ */ jsx11(
1385
+ /* @__PURE__ */ jsx12(
1332
1386
  Step2,
1333
1387
  {
1334
1388
  n: 3,
1335
1389
  title: copy.step3.title,
1336
- visual: /* @__PURE__ */ jsx11(
1390
+ visual: /* @__PURE__ */ jsx12(
1337
1391
  "div",
1338
1392
  {
1339
1393
  style: {
@@ -1344,7 +1398,7 @@ function IOSafariVariant({
1344
1398
  padding: "10px 14px",
1345
1399
  marginTop: 8
1346
1400
  },
1347
- children: /* @__PURE__ */ jsx11(
1401
+ children: /* @__PURE__ */ jsx12(
1348
1402
  "span",
1349
1403
  {
1350
1404
  style: {
@@ -1359,7 +1413,7 @@ function IOSafariVariant({
1359
1413
  )
1360
1414
  }
1361
1415
  ),
1362
- /* @__PURE__ */ jsx11(
1416
+ /* @__PURE__ */ jsx12(
1363
1417
  "button",
1364
1418
  {
1365
1419
  "data-testid": "install-prompt-skip-session",
@@ -1369,7 +1423,7 @@ function IOSafariVariant({
1369
1423
  children: copy.skip
1370
1424
  }
1371
1425
  ),
1372
- showPermanent && /* @__PURE__ */ jsx11(
1426
+ showPermanent && /* @__PURE__ */ jsx12(
1373
1427
  "button",
1374
1428
  {
1375
1429
  "data-testid": "install-prompt-skip-permanent",
@@ -1383,7 +1437,7 @@ function IOSafariVariant({
1383
1437
  }
1384
1438
 
1385
1439
  // src/components/InstallGate/variants/IOSOtherVariant.tsx
1386
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1440
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1387
1441
  function IOSOtherVariant({
1388
1442
  state,
1389
1443
  actions
@@ -1391,13 +1445,13 @@ function IOSOtherVariant({
1391
1445
  const copy = INSTALL_COPY.iosOther;
1392
1446
  const showPermanent = shouldShowPermanentOption(state);
1393
1447
  return /* @__PURE__ */ jsxs7(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1394
- /* @__PURE__ */ jsx12(
1448
+ /* @__PURE__ */ jsx13(
1395
1449
  Step2,
1396
1450
  {
1397
1451
  n: 1,
1398
1452
  title: copy.step1.title,
1399
1453
  subtitle: copy.step1.subtitle,
1400
- visual: /* @__PURE__ */ jsx12(
1454
+ visual: /* @__PURE__ */ jsx13(
1401
1455
  "div",
1402
1456
  {
1403
1457
  style: {
@@ -1409,12 +1463,12 @@ function IOSOtherVariant({
1409
1463
  padding: "12px 0",
1410
1464
  marginTop: 8
1411
1465
  },
1412
- children: /* @__PURE__ */ jsx12(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1466
+ children: /* @__PURE__ */ jsx13(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1413
1467
  }
1414
1468
  )
1415
1469
  }
1416
1470
  ),
1417
- /* @__PURE__ */ jsx12(
1471
+ /* @__PURE__ */ jsx13(
1418
1472
  Step2,
1419
1473
  {
1420
1474
  n: 2,
@@ -1432,19 +1486,19 @@ function IOSOtherVariant({
1432
1486
  marginTop: 8
1433
1487
  },
1434
1488
  children: [
1435
- /* @__PURE__ */ jsx12(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1436
- /* @__PURE__ */ jsx12("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1489
+ /* @__PURE__ */ jsx13(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1490
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1437
1491
  ]
1438
1492
  }
1439
1493
  )
1440
1494
  }
1441
1495
  ),
1442
- /* @__PURE__ */ jsx12(
1496
+ /* @__PURE__ */ jsx13(
1443
1497
  Step2,
1444
1498
  {
1445
1499
  n: 3,
1446
1500
  title: copy.step3.title,
1447
- visual: /* @__PURE__ */ jsx12(
1501
+ visual: /* @__PURE__ */ jsx13(
1448
1502
  "div",
1449
1503
  {
1450
1504
  style: {
@@ -1455,7 +1509,7 @@ function IOSOtherVariant({
1455
1509
  padding: "10px 14px",
1456
1510
  marginTop: 8
1457
1511
  },
1458
- children: /* @__PURE__ */ jsx12(
1512
+ children: /* @__PURE__ */ jsx13(
1459
1513
  "span",
1460
1514
  {
1461
1515
  style: {
@@ -1470,7 +1524,7 @@ function IOSOtherVariant({
1470
1524
  )
1471
1525
  }
1472
1526
  ),
1473
- /* @__PURE__ */ jsx12(
1527
+ /* @__PURE__ */ jsx13(
1474
1528
  "button",
1475
1529
  {
1476
1530
  "data-testid": "install-prompt-skip-session",
@@ -1480,7 +1534,7 @@ function IOSOtherVariant({
1480
1534
  children: copy.skip
1481
1535
  }
1482
1536
  ),
1483
- showPermanent && /* @__PURE__ */ jsx12(
1537
+ showPermanent && /* @__PURE__ */ jsx13(
1484
1538
  "button",
1485
1539
  {
1486
1540
  "data-testid": "install-prompt-skip-permanent",
@@ -1495,7 +1549,7 @@ function IOSOtherVariant({
1495
1549
 
1496
1550
  // src/components/InstallGate/variants/InAppBrowserVariant.tsx
1497
1551
  import { useState as useState3 } from "react";
1498
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1552
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1499
1553
  function InAppBrowserVariant({
1500
1554
  state,
1501
1555
  actions
@@ -1512,9 +1566,9 @@ function InAppBrowserVariant({
1512
1566
  };
1513
1567
  const DotsIcon = app === "facebook" || app === "telegram" ? MenuDotsVerticalIcon : MenuDotsHorizontalIcon;
1514
1568
  return /* @__PURE__ */ jsxs8(InstallSplash, { title: appCopy.title, children: [
1515
- /* @__PURE__ */ jsx13(Step3, { n: 1, icon: /* @__PURE__ */ jsx13(DotsIcon, { size: 20 }), children: appCopy.step1 }),
1516
- /* @__PURE__ */ jsx13(Step3, { n: 2, icon: /* @__PURE__ */ jsx13(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
1517
- /* @__PURE__ */ jsx13(
1569
+ /* @__PURE__ */ jsx14(Step3, { n: 1, icon: /* @__PURE__ */ jsx14(DotsIcon, { size: 20 }), children: appCopy.step1 }),
1570
+ /* @__PURE__ */ jsx14(Step3, { n: 2, icon: /* @__PURE__ */ jsx14(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
1571
+ /* @__PURE__ */ jsx14(
1518
1572
  "button",
1519
1573
  {
1520
1574
  "data-testid": "install-prompt-cta-inapp-copy",
@@ -1524,7 +1578,7 @@ function InAppBrowserVariant({
1524
1578
  children: copied ? copy.copiedToast : copy.copy
1525
1579
  }
1526
1580
  ),
1527
- /* @__PURE__ */ jsx13(
1581
+ /* @__PURE__ */ jsx14(
1528
1582
  "button",
1529
1583
  {
1530
1584
  "data-testid": "install-prompt-skip-session",
@@ -1534,7 +1588,7 @@ function InAppBrowserVariant({
1534
1588
  children: copy.skip
1535
1589
  }
1536
1590
  ),
1537
- showPermanent && /* @__PURE__ */ jsx13(
1591
+ showPermanent && /* @__PURE__ */ jsx14(
1538
1592
  "button",
1539
1593
  {
1540
1594
  "data-testid": "install-prompt-skip-permanent",
@@ -1565,7 +1619,7 @@ function Step3({
1565
1619
  textAlign: "left"
1566
1620
  },
1567
1621
  children: [
1568
- /* @__PURE__ */ jsx13(
1622
+ /* @__PURE__ */ jsx14(
1569
1623
  "div",
1570
1624
  {
1571
1625
  style: {
@@ -1584,15 +1638,15 @@ function Step3({
1584
1638
  children: n
1585
1639
  }
1586
1640
  ),
1587
- /* @__PURE__ */ jsx13("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
1588
- /* @__PURE__ */ jsx13("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
1641
+ /* @__PURE__ */ jsx14("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
1642
+ /* @__PURE__ */ jsx14("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
1589
1643
  ]
1590
1644
  }
1591
1645
  );
1592
1646
  }
1593
1647
 
1594
1648
  // src/components/InstallGate/variants/DesktopVariant.tsx
1595
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1649
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1596
1650
  function DesktopVariant({
1597
1651
  state,
1598
1652
  actions
@@ -1608,14 +1662,14 @@ function DesktopVariant({
1608
1662
  "aria-label": copy.title,
1609
1663
  style: bannerStyle,
1610
1664
  children: [
1611
- iconUrl ? /* @__PURE__ */ jsx14(
1665
+ iconUrl ? /* @__PURE__ */ jsx15(
1612
1666
  "img",
1613
1667
  {
1614
1668
  src: iconUrl,
1615
1669
  alt: "",
1616
1670
  style: { width: 40, height: 40, borderRadius: 10, objectFit: "cover", flexShrink: 0 }
1617
1671
  }
1618
- ) : /* @__PURE__ */ jsx14(
1672
+ ) : /* @__PURE__ */ jsx15(
1619
1673
  "div",
1620
1674
  {
1621
1675
  style: {
@@ -1635,8 +1689,8 @@ function DesktopVariant({
1635
1689
  }
1636
1690
  ),
1637
1691
  /* @__PURE__ */ jsxs9("div", { style: { flex: 1, minWidth: 0 }, children: [
1638
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
1639
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
1692
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
1693
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
1640
1694
  ] }),
1641
1695
  /* @__PURE__ */ jsxs9(
1642
1696
  "button",
@@ -1659,12 +1713,12 @@ function DesktopVariant({
1659
1713
  flexShrink: 0
1660
1714
  },
1661
1715
  children: [
1662
- /* @__PURE__ */ jsx14(DownloadIcon, { size: 14 }),
1716
+ /* @__PURE__ */ jsx15(DownloadIcon, { size: 14 }),
1663
1717
  copy.cta
1664
1718
  ]
1665
1719
  }
1666
1720
  ),
1667
- /* @__PURE__ */ jsx14(
1721
+ /* @__PURE__ */ jsx15(
1668
1722
  "button",
1669
1723
  {
1670
1724
  "data-testid": "install-prompt-desktop-close",
@@ -1679,7 +1733,7 @@ function DesktopVariant({
1679
1733
  padding: 4,
1680
1734
  flexShrink: 0
1681
1735
  },
1682
- children: /* @__PURE__ */ jsx14(XIcon, { size: 16 })
1736
+ children: /* @__PURE__ */ jsx15(XIcon, { size: 16 })
1683
1737
  }
1684
1738
  )
1685
1739
  ]
@@ -1703,7 +1757,7 @@ var bannerStyle = {
1703
1757
  };
1704
1758
 
1705
1759
  // src/components/InstallGate/InstallGate.tsx
1706
- import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1760
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1707
1761
  function InstallGate({ children }) {
1708
1762
  const { slug, features_enabled } = useTemplateConfig();
1709
1763
  const enabled = features_enabled.includes("install_prompt");
@@ -1724,30 +1778,32 @@ function InstallGate({ children }) {
1724
1778
  variant: installState.variant
1725
1779
  });
1726
1780
  }, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
1727
- if (!enabled) return /* @__PURE__ */ jsx15(Fragment3, { children });
1728
- if (installState.isInstalled) return /* @__PURE__ */ jsx15(Fragment3, { children });
1781
+ if (!enabled) return /* @__PURE__ */ jsx16(Fragment3, { children });
1782
+ if (installState.isInstalled) return /* @__PURE__ */ jsx16(Fragment3, { children });
1729
1783
  if (installState.variant === "desktop") {
1730
1784
  const showBanner = !installState.isDismissedSession && !installState.isDismissedPermanent;
1731
1785
  return /* @__PURE__ */ jsxs10(Fragment3, { children: [
1732
1786
  children,
1733
- showBanner && /* @__PURE__ */ jsx15(DesktopVariant, { state: installState, actions: installState })
1787
+ showBanner && /* @__PURE__ */ jsx16(DesktopVariant, { state: installState, actions: installState })
1734
1788
  ] });
1735
1789
  }
1736
- if (!shouldBlock) return /* @__PURE__ */ jsx15(Fragment3, { children });
1790
+ if (!shouldBlock) return /* @__PURE__ */ jsx16(Fragment3, { children });
1737
1791
  switch (installState.variant) {
1738
1792
  case "android-native":
1739
- return /* @__PURE__ */ jsx15(AndroidNativeVariant, { state: installState, actions: installState });
1793
+ return /* @__PURE__ */ jsx16(AndroidNativeVariant, { state: installState, actions: installState });
1740
1794
  case "android-manual":
1741
- return /* @__PURE__ */ jsx15(AndroidManualVariant, { state: installState, actions: installState });
1795
+ return /* @__PURE__ */ jsx16(AndroidManualVariant, { state: installState, actions: installState });
1796
+ case "android-pending":
1797
+ return /* @__PURE__ */ jsx16(AndroidPendingVariant, {});
1742
1798
  case "ios-safari":
1743
- return /* @__PURE__ */ jsx15(IOSafariVariant, { state: installState, actions: installState });
1799
+ return /* @__PURE__ */ jsx16(IOSafariVariant, { state: installState, actions: installState });
1744
1800
  case "ios-other":
1745
- return /* @__PURE__ */ jsx15(IOSOtherVariant, { state: installState, actions: installState });
1801
+ return /* @__PURE__ */ jsx16(IOSOtherVariant, { state: installState, actions: installState });
1746
1802
  case "in-app":
1747
- return /* @__PURE__ */ jsx15(InAppBrowserVariant, { state: installState, actions: installState });
1803
+ return /* @__PURE__ */ jsx16(InAppBrowserVariant, { state: installState, actions: installState });
1748
1804
  case "none":
1749
1805
  default:
1750
- return /* @__PURE__ */ jsx15(Fragment3, { children });
1806
+ return /* @__PURE__ */ jsx16(Fragment3, { children });
1751
1807
  }
1752
1808
  }
1753
1809
 
@@ -1759,7 +1815,7 @@ function PushPrompt() {
1759
1815
  // src/internal/SessionExpiredBanner.tsx
1760
1816
  import { useEffect as useEffect5, useRef as useRef2, useState as useState4 } from "react";
1761
1817
  import { useHook as useHook3 } from "@hook-sdk/sdk";
1762
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1818
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1763
1819
  var DISMISS_KEY = "hook:session-expired-dismissed-until";
1764
1820
  var DISMISS_TTL_MS = 60 * 60 * 1e3;
1765
1821
  function SessionExpiredBanner() {
@@ -1788,11 +1844,11 @@ function SessionExpiredBanner() {
1788
1844
  }
1789
1845
  return /* @__PURE__ */ jsxs11("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: [
1790
1846
  /* @__PURE__ */ jsxs11("span", { children: [
1791
- /* @__PURE__ */ jsx16("strong", { children: "Sua sess\xE3o expirou." }),
1847
+ /* @__PURE__ */ jsx17("strong", { children: "Sua sess\xE3o expirou." }),
1792
1848
  " Fa\xE7a login novamente para continuar."
1793
1849
  ] }),
1794
1850
  /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1795
- /* @__PURE__ */ jsx16(
1851
+ /* @__PURE__ */ jsx17(
1796
1852
  "button",
1797
1853
  {
1798
1854
  type: "button",
@@ -1801,7 +1857,7 @@ function SessionExpiredBanner() {
1801
1857
  children: "Fazer login"
1802
1858
  }
1803
1859
  ),
1804
- /* @__PURE__ */ jsx16(
1860
+ /* @__PURE__ */ jsx17(
1805
1861
  "button",
1806
1862
  {
1807
1863
  type: "button",
@@ -1817,7 +1873,7 @@ function SessionExpiredBanner() {
1817
1873
 
1818
1874
  // src/defaults/ErrorBoundary.tsx
1819
1875
  import { Component } from "react";
1820
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1876
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1821
1877
  var ErrorBoundary = class extends Component {
1822
1878
  state = { error: null };
1823
1879
  static getDerivedStateFromError(error) {
@@ -1836,18 +1892,18 @@ var ErrorBoundary = class extends Component {
1836
1892
  render() {
1837
1893
  if (this.state.error) {
1838
1894
  return this.props.fallback ?? /* @__PURE__ */ jsxs12("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
1839
- /* @__PURE__ */ jsx17("h2", { children: "Algo deu errado" }),
1840
- /* @__PURE__ */ jsx17("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
1895
+ /* @__PURE__ */ jsx18("h2", { children: "Algo deu errado" }),
1896
+ /* @__PURE__ */ jsx18("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
1841
1897
  ] });
1842
1898
  }
1843
- return /* @__PURE__ */ jsx17(Fragment4, { children: this.props.children });
1899
+ return /* @__PURE__ */ jsx18(Fragment4, { children: this.props.children });
1844
1900
  }
1845
1901
  };
1846
1902
 
1847
1903
  // src/internal/PaymentReturnHandler.tsx
1848
1904
  import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef3, useState as useState5 } from "react";
1849
1905
  import { useHook as useHook4 } from "@hook-sdk/sdk";
1850
- import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1906
+ import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1851
1907
  var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
1852
1908
  var MAX_CYCLES = 3;
1853
1909
  var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
@@ -1910,19 +1966,19 @@ function PaymentReturnHandler({ children }) {
1910
1966
  window.location.href = cleanUrl.toString();
1911
1967
  }, []);
1912
1968
  if (state === "confirming") {
1913
- return /* @__PURE__ */ jsx18("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
1969
+ return /* @__PURE__ */ jsx19("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
1914
1970
  }
1915
1971
  if (state === "waiting") {
1916
- return /* @__PURE__ */ jsx18("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
1917
- /* @__PURE__ */ jsx18("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
1918
- /* @__PURE__ */ jsx18("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
1972
+ return /* @__PURE__ */ jsx19("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
1973
+ /* @__PURE__ */ jsx19("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
1974
+ /* @__PURE__ */ jsx19("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
1919
1975
  ] }) });
1920
1976
  }
1921
1977
  if (state === "timeout") {
1922
- return /* @__PURE__ */ jsx18("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
1923
- /* @__PURE__ */ jsx18("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." }),
1978
+ return /* @__PURE__ */ jsx19("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
1979
+ /* @__PURE__ */ jsx19("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." }),
1924
1980
  /* @__PURE__ */ jsxs13("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
1925
- /* @__PURE__ */ jsx18(
1981
+ /* @__PURE__ */ jsx19(
1926
1982
  "button",
1927
1983
  {
1928
1984
  type: "button",
@@ -1935,7 +1991,7 @@ function PaymentReturnHandler({ children }) {
1935
1991
  children: "Tentar de novo"
1936
1992
  }
1937
1993
  ),
1938
- /* @__PURE__ */ jsx18(
1994
+ /* @__PURE__ */ jsx19(
1939
1995
  "button",
1940
1996
  {
1941
1997
  type: "button",
@@ -1945,7 +2001,7 @@ function PaymentReturnHandler({ children }) {
1945
2001
  children: "Voltar pro app"
1946
2002
  }
1947
2003
  ),
1948
- /* @__PURE__ */ jsx18(
2004
+ /* @__PURE__ */ jsx19(
1949
2005
  "a",
1950
2006
  {
1951
2007
  href: SUPPORT_MAILTO,
@@ -1957,7 +2013,7 @@ function PaymentReturnHandler({ children }) {
1957
2013
  ] })
1958
2014
  ] }) });
1959
2015
  }
1960
- return /* @__PURE__ */ jsx18(Fragment5, { children });
2016
+ return /* @__PURE__ */ jsx19(Fragment5, { children });
1961
2017
  }
1962
2018
  var overlayStyle2 = {
1963
2019
  position: "fixed",
@@ -1996,7 +2052,7 @@ var linkStyle = {
1996
2052
  };
1997
2053
 
1998
2054
  // src/AppRoot.tsx
1999
- import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2055
+ import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2000
2056
  function buildLegacyConfigShim(config) {
2001
2057
  const paywall = config.paywall;
2002
2058
  const isFree = paywall.mode === "free";
@@ -2006,7 +2062,16 @@ function buildLegacyConfigShim(config) {
2006
2062
  slug: config.slug,
2007
2063
  name: config.name,
2008
2064
  email_alias: config.slug,
2009
- theme: { primary_color: config.branding.primaryColor },
2065
+ // Map branding into the legacy theme shape so InstallSplash (and
2066
+ // anything else reading theme.icon_url / theme.logo_url) can surface
2067
+ // the app icon instead of the generic "first letter of name" fallback.
2068
+ // Falls back to logoUrl when iconUrl is unset — apps that haven't
2069
+ // adopted iconUrl keep their previous behavior unchanged.
2070
+ theme: {
2071
+ primary_color: config.branding.primaryColor,
2072
+ icon_url: config.branding.iconUrl ?? config.branding.logoUrl,
2073
+ logo_url: config.branding.logoUrl
2074
+ },
2010
2075
  features_enabled: config.features_enabled ?? [],
2011
2076
  dependencies_allowlist: ["react", "react-dom"],
2012
2077
  subscription: {
@@ -2064,10 +2129,10 @@ function AppRoot(props) {
2064
2129
  const Router = testRouter === "memory" ? MemoryRouter : BrowserRouter;
2065
2130
  const basename = `/app/${config.slug}`;
2066
2131
  const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
2067
- return /* @__PURE__ */ jsx19(ErrorBoundary, { children: /* @__PURE__ */ jsx19(AppConfigProvider, { config, children: /* @__PURE__ */ jsx19(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ jsx19(ThemeProvider, { children: /* @__PURE__ */ jsx19(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ jsxs14(Router, { ...routerProps, children: [
2068
- /* @__PURE__ */ jsx19(DeepLinkHandler, { deepLinks: config.deepLinks }),
2069
- /* @__PURE__ */ jsx19(SessionExpiredBanner, {}),
2070
- /* @__PURE__ */ jsx19(InstallGate, { children: /* @__PURE__ */ jsx19(
2132
+ return /* @__PURE__ */ jsx20(ErrorBoundary, { children: /* @__PURE__ */ jsx20(AppConfigProvider, { config, children: /* @__PURE__ */ jsx20(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ jsx20(ThemeProvider, { children: /* @__PURE__ */ jsx20(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ jsxs14(Router, { ...routerProps, children: [
2133
+ /* @__PURE__ */ jsx20(DeepLinkHandler, { deepLinks: config.deepLinks }),
2134
+ /* @__PURE__ */ jsx20(SessionExpiredBanner, {}),
2135
+ /* @__PURE__ */ jsx20(InstallGate, { children: /* @__PURE__ */ jsx20(
2071
2136
  AuthGated,
2072
2137
  {
2073
2138
  config,
@@ -2081,7 +2146,7 @@ function AppRoot(props) {
2081
2146
  PreAuthFlow,
2082
2147
  children: /* @__PURE__ */ jsxs14(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: [
2083
2148
  children,
2084
- /* @__PURE__ */ jsx19(PushPrompt, {})
2149
+ /* @__PURE__ */ jsx20(PushPrompt, {})
2085
2150
  ] })
2086
2151
  }
2087
2152
  ) })
@@ -2102,24 +2167,24 @@ function AuthGated({
2102
2167
  if (authStatus !== "authenticated") {
2103
2168
  if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
2104
2169
  return /* @__PURE__ */ jsxs14(Routes, { children: [
2105
- /* @__PURE__ */ jsx19(Route, { path: "/signin", element: /* @__PURE__ */ jsx19(Login, {}) }),
2106
- /* @__PURE__ */ jsx19(Route, { path: "/signup", element: /* @__PURE__ */ jsx19(Signup, {}) }),
2107
- /* @__PURE__ */ jsx19(Route, { path: "/forgot", element: /* @__PURE__ */ jsx19(Forgot, {}) }),
2108
- /* @__PURE__ */ jsx19(Route, { path: "/reset", element: /* @__PURE__ */ jsx19(Reset, {}) }),
2109
- EmailVerify ? /* @__PURE__ */ jsx19(Route, { path: "/verify", element: /* @__PURE__ */ jsx19(EmailVerify, {}) }) : null,
2110
- /* @__PURE__ */ jsx19(Route, { path: "/*", element: /* @__PURE__ */ jsx19(PreAuthFlow, {}) })
2170
+ /* @__PURE__ */ jsx20(Route, { path: "/signin", element: /* @__PURE__ */ jsx20(Login, {}) }),
2171
+ /* @__PURE__ */ jsx20(Route, { path: "/signup", element: /* @__PURE__ */ jsx20(Signup, {}) }),
2172
+ /* @__PURE__ */ jsx20(Route, { path: "/forgot", element: /* @__PURE__ */ jsx20(Forgot, {}) }),
2173
+ /* @__PURE__ */ jsx20(Route, { path: "/reset", element: /* @__PURE__ */ jsx20(Reset, {}) }),
2174
+ EmailVerify ? /* @__PURE__ */ jsx20(Route, { path: "/verify", element: /* @__PURE__ */ jsx20(EmailVerify, {}) }) : null,
2175
+ /* @__PURE__ */ jsx20(Route, { path: "/*", element: /* @__PURE__ */ jsx20(PreAuthFlow, {}) })
2111
2176
  ] });
2112
2177
  }
2113
2178
  return /* @__PURE__ */ jsxs14(Routes, { children: [
2114
- /* @__PURE__ */ jsx19(Route, { path: "/", element: /* @__PURE__ */ jsx19(Login, {}) }),
2115
- /* @__PURE__ */ jsx19(Route, { path: "/signup", element: /* @__PURE__ */ jsx19(Signup, {}) }),
2116
- /* @__PURE__ */ jsx19(Route, { path: "/forgot", element: /* @__PURE__ */ jsx19(Forgot, {}) }),
2117
- /* @__PURE__ */ jsx19(Route, { path: "/reset", element: /* @__PURE__ */ jsx19(Reset, {}) }),
2118
- EmailVerify ? /* @__PURE__ */ jsx19(Route, { path: "/verify", element: /* @__PURE__ */ jsx19(EmailVerify, {}) }) : null,
2119
- /* @__PURE__ */ jsx19(Route, { path: "*", element: /* @__PURE__ */ jsx19(Navigate, { to: "/", replace: true }) })
2179
+ /* @__PURE__ */ jsx20(Route, { path: "/", element: /* @__PURE__ */ jsx20(Login, {}) }),
2180
+ /* @__PURE__ */ jsx20(Route, { path: "/signup", element: /* @__PURE__ */ jsx20(Signup, {}) }),
2181
+ /* @__PURE__ */ jsx20(Route, { path: "/forgot", element: /* @__PURE__ */ jsx20(Forgot, {}) }),
2182
+ /* @__PURE__ */ jsx20(Route, { path: "/reset", element: /* @__PURE__ */ jsx20(Reset, {}) }),
2183
+ EmailVerify ? /* @__PURE__ */ jsx20(Route, { path: "/verify", element: /* @__PURE__ */ jsx20(EmailVerify, {}) }) : null,
2184
+ /* @__PURE__ */ jsx20(Route, { path: "*", element: /* @__PURE__ */ jsx20(Navigate, { to: "/", replace: true }) })
2120
2185
  ] });
2121
2186
  }
2122
- return /* @__PURE__ */ jsx19(Fragment6, { children });
2187
+ return /* @__PURE__ */ jsx20(Fragment6, { children });
2123
2188
  }
2124
2189
  function FallbackPaywall() {
2125
2190
  return null;
@@ -2210,7 +2275,7 @@ function usePush() {
2210
2275
  }
2211
2276
 
2212
2277
  // src/components/PushPrompt.tsx
2213
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2278
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2214
2279
  function platformRecoveryCopy(texts) {
2215
2280
  if (typeof navigator === "undefined") return null;
2216
2281
  const ua = navigator.userAgent || "";
@@ -2234,27 +2299,27 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
2234
2299
  if (state.kind === "subscribed" || state.kind === "dismissed") return null;
2235
2300
  if (state.kind === "ios_needs_install") {
2236
2301
  return /* @__PURE__ */ jsxs15("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
2237
- /* @__PURE__ */ jsx20("h3", { children: texts.iosInstallTitle }),
2238
- /* @__PURE__ */ jsx20("p", { children: texts.iosInstallBody }),
2239
- onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ jsx20("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2302
+ /* @__PURE__ */ jsx21("h3", { children: texts.iosInstallTitle }),
2303
+ /* @__PURE__ */ jsx21("p", { children: texts.iosInstallBody }),
2304
+ onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ jsx21("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2240
2305
  ] });
2241
2306
  }
2242
2307
  if (state.kind === "denied") {
2243
2308
  const recovery = platformRecoveryCopy(texts);
2244
2309
  return /* @__PURE__ */ jsxs15("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
2245
- /* @__PURE__ */ jsx20("h3", { children: texts.deniedTitle }),
2246
- /* @__PURE__ */ jsx20("p", { children: texts.deniedBody }),
2247
- recovery && /* @__PURE__ */ jsx20("p", { "data-testid": "denied-recovery", children: recovery })
2310
+ /* @__PURE__ */ jsx21("h3", { children: texts.deniedTitle }),
2311
+ /* @__PURE__ */ jsx21("p", { children: texts.deniedBody }),
2312
+ recovery && /* @__PURE__ */ jsx21("p", { "data-testid": "denied-recovery", children: recovery })
2248
2313
  ] });
2249
2314
  }
2250
2315
  if (state.kind === "unsupported") {
2251
- return /* @__PURE__ */ jsx20("div", { className, role: "region", children: /* @__PURE__ */ jsx20("p", { children: texts.unsupportedBody }) });
2316
+ return /* @__PURE__ */ jsx21("div", { className, role: "region", children: /* @__PURE__ */ jsx21("p", { children: texts.unsupportedBody }) });
2252
2317
  }
2253
2318
  if (state.kind === "error") {
2254
- return /* @__PURE__ */ jsx20("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ jsx20("p", { children: state.message }) });
2319
+ return /* @__PURE__ */ jsx21("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ jsx21("p", { children: state.message }) });
2255
2320
  }
2256
2321
  return /* @__PURE__ */ jsxs15("div", { className, role: "region", children: [
2257
- /* @__PURE__ */ jsx20(
2322
+ /* @__PURE__ */ jsx21(
2258
2323
  "button",
2259
2324
  {
2260
2325
  type: "button",
@@ -2268,23 +2333,23 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
2268
2333
  children: texts.cta
2269
2334
  }
2270
2335
  ),
2271
- onDeclined && /* @__PURE__ */ jsx20("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2336
+ onDeclined && /* @__PURE__ */ jsx21("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2272
2337
  ] });
2273
2338
  }
2274
2339
 
2275
2340
  // src/defaults/LoadingState.tsx
2276
- import { jsx as jsx21 } from "react/jsx-runtime";
2341
+ import { jsx as jsx22 } from "react/jsx-runtime";
2277
2342
  function LoadingState({ message }) {
2278
- return /* @__PURE__ */ jsx21("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ jsx21("span", { children: message ?? "Carregando..." }) });
2343
+ return /* @__PURE__ */ jsx22("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ jsx22("span", { children: message ?? "Carregando..." }) });
2279
2344
  }
2280
2345
 
2281
2346
  // src/defaults/EmptyState.tsx
2282
- import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2347
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
2283
2348
  function EmptyState({ title, description, action }) {
2284
2349
  return /* @__PURE__ */ jsxs16("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
2285
- /* @__PURE__ */ jsx22("h2", { style: { marginBottom: 8 }, children: title }),
2286
- description && /* @__PURE__ */ jsx22("p", { style: { opacity: 0.7 }, children: description }),
2287
- action && /* @__PURE__ */ jsx22("div", { style: { marginTop: 16 }, children: action })
2350
+ /* @__PURE__ */ jsx23("h2", { style: { marginBottom: 8 }, children: title }),
2351
+ description && /* @__PURE__ */ jsx23("p", { style: { opacity: 0.7 }, children: description }),
2352
+ action && /* @__PURE__ */ jsx23("div", { style: { marginTop: 16 }, children: action })
2288
2353
  ] });
2289
2354
  }
2290
2355
 
@@ -2711,20 +2776,20 @@ function useToast() {
2711
2776
 
2712
2777
  // src/RouteBoundary.tsx
2713
2778
  import { Routes as Routes2, Route as Route2 } from "react-router-dom";
2714
- import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
2779
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
2715
2780
  function RouteBoundary({ children }) {
2716
2781
  return /* @__PURE__ */ jsxs17(Routes2, { children: [
2717
2782
  children,
2718
- /* @__PURE__ */ jsx23(Route2, { path: "*", element: /* @__PURE__ */ jsx23(DefaultNotFound, {}) })
2783
+ /* @__PURE__ */ jsx24(Route2, { path: "*", element: /* @__PURE__ */ jsx24(DefaultNotFound, {}) })
2719
2784
  ] });
2720
2785
  }
2721
2786
  function DefaultNotFound() {
2722
- return /* @__PURE__ */ jsx23("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
2787
+ return /* @__PURE__ */ jsx24("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
2723
2788
  }
2724
2789
 
2725
2790
  // src/PreAuthShell.tsx
2726
2791
  import { BrowserRouter as BrowserRouter2, MemoryRouter as MemoryRouter2, Routes as Routes3 } from "react-router-dom";
2727
- import { jsx as jsx24 } from "react/jsx-runtime";
2792
+ import { jsx as jsx25 } from "react/jsx-runtime";
2728
2793
  function PreAuthShell({
2729
2794
  basename,
2730
2795
  testRouter,
@@ -2732,9 +2797,9 @@ function PreAuthShell({
2732
2797
  children
2733
2798
  }) {
2734
2799
  if (testRouter === "memory") {
2735
- return /* @__PURE__ */ jsx24(MemoryRouter2, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ jsx24(Routes3, { children }) });
2800
+ return /* @__PURE__ */ jsx25(MemoryRouter2, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ jsx25(Routes3, { children }) });
2736
2801
  }
2737
- return /* @__PURE__ */ jsx24(BrowserRouter2, { basename, children: /* @__PURE__ */ jsx24(Routes3, { children }) });
2802
+ return /* @__PURE__ */ jsx25(BrowserRouter2, { basename, children: /* @__PURE__ */ jsx25(Routes3, { children }) });
2738
2803
  }
2739
2804
 
2740
2805
  // src/OnboardingFlow.tsx
@@ -2755,7 +2820,7 @@ function useOnboardingStep() {
2755
2820
  }
2756
2821
 
2757
2822
  // src/OnboardingFlow.tsx
2758
- import { jsx as jsx25 } from "react/jsx-runtime";
2823
+ import { jsx as jsx26 } from "react/jsx-runtime";
2759
2824
  var isFilled = (v) => v != null && v !== "";
2760
2825
  var CURRENT_STEP_FIELD = "currentStep";
2761
2826
  function readPersistedStepIdx(draft) {
@@ -2833,7 +2898,7 @@ function OnboardingFlow({
2833
2898
  `[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
2834
2899
  );
2835
2900
  }
2836
- return /* @__PURE__ */ jsx25(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx25(Screen, {}) });
2901
+ return /* @__PURE__ */ jsx26(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx26(Screen, {}) });
2837
2902
  }
2838
2903
 
2839
2904
  // src/hooks/useFeature.ts