@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.cjs CHANGED
@@ -147,7 +147,11 @@ var DeepLinksSchema = import_zod.z.object({
147
147
  var AppConfigSchema = import_zod.z.object({
148
148
  slug: import_zod.z.string().regex(/^[a-z0-9-]+$/),
149
149
  name: import_zod.z.string().min(1),
150
- branding: import_zod.z.object({ primaryColor: import_zod.z.string(), logoUrl: import_zod.z.string().url() }),
150
+ branding: import_zod.z.object({
151
+ primaryColor: import_zod.z.string(),
152
+ logoUrl: import_zod.z.string().url(),
153
+ iconUrl: import_zod.z.string().url().optional()
154
+ }),
151
155
  authFlow: AuthFlowSchema,
152
156
  paywall: PaywallSchema,
153
157
  persistedKeys: import_zod.z.array(PersistedKeySchema),
@@ -567,6 +571,7 @@ var import_react8 = require("react");
567
571
 
568
572
  // src/hooks/useInstallPrompt.ts
569
573
  var import_react6 = require("react");
574
+ var ANDROID_PROMPT_WAIT_MS = 3e3;
570
575
  var IOS_RE = /iPad|iPhone|iPod/;
571
576
  var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
572
577
  var ANDROID_RE = /Android/;
@@ -636,11 +641,12 @@ function track(event, props) {
636
641
  if (typeof window === "undefined") return;
637
642
  window.posthog?.capture?.(event, props);
638
643
  }
639
- function pickVariant(state) {
644
+ function pickVariant(state, promptWaitElapsed) {
640
645
  if (state.isInstalled) return "none";
641
646
  switch (state.platform) {
642
647
  case "android":
643
- return state.isInstallable ? "android-native" : "android-manual";
648
+ if (state.isInstallable) return "android-native";
649
+ return promptWaitElapsed ? "android-manual" : "android-pending";
644
650
  case "ios-safari":
645
651
  return "ios-safari";
646
652
  case "ios-other":
@@ -710,6 +716,15 @@ function useInstallPrompt(slug) {
710
716
  const [isDismissedSession, setIsDismissedSession] = (0, import_react6.useState)(() => readSessionSkip(slug));
711
717
  const [isDismissedPermanent, setIsDismissedPermanent] = (0, import_react6.useState)(() => readPermanentDismiss(slug).dismissed);
712
718
  const [skipCount, setSkipCount] = (0, import_react6.useState)(() => readSkipCount(slug));
719
+ const [promptWaitElapsed, setPromptWaitElapsed] = (0, import_react6.useState)(() => {
720
+ if (typeof window === "undefined") return true;
721
+ return window.__pwaInstallPrompt != null;
722
+ });
723
+ (0, import_react6.useEffect)(() => {
724
+ if (promptWaitElapsed) return;
725
+ const id = setTimeout(() => setPromptWaitElapsed(true), ANDROID_PROMPT_WAIT_MS);
726
+ return () => clearTimeout(id);
727
+ }, [promptWaitElapsed]);
713
728
  (0, import_react6.useEffect)(() => {
714
729
  if (typeof window === "undefined") return;
715
730
  if (window.__pwaInstallPrompt) {
@@ -747,17 +762,20 @@ function useInstallPrompt(slug) {
747
762
  mq.addEventListener?.("change", handler);
748
763
  return () => mq.removeEventListener?.("change", handler);
749
764
  }, [slug]);
750
- const variant = pickVariant({
751
- platform,
752
- iosBrowser,
753
- androidBrowser,
754
- inAppApp,
755
- isInstallable,
756
- isInstalled,
757
- isDismissedSession,
758
- isDismissedPermanent,
759
- skipCount
760
- });
765
+ const variant = pickVariant(
766
+ {
767
+ platform,
768
+ iosBrowser,
769
+ androidBrowser,
770
+ inAppApp,
771
+ isInstallable,
772
+ isInstalled,
773
+ isDismissedSession,
774
+ isDismissedPermanent,
775
+ skipCount
776
+ },
777
+ promptWaitElapsed
778
+ );
761
779
  const promptInstall = (0, import_react6.useCallback)(async () => {
762
780
  if (typeof window === "undefined") return false;
763
781
  const prompt = window.__pwaInstallPrompt;
@@ -1293,15 +1311,51 @@ function Step({ n, icon, children }) {
1293
1311
  );
1294
1312
  }
1295
1313
 
1296
- // src/components/InstallGate/Step.tsx
1314
+ // src/components/InstallGate/variants/AndroidPendingVariant.tsx
1297
1315
  var import_jsx_runtime10 = require("react/jsx-runtime");
1316
+ function AndroidPendingVariant() {
1317
+ const copy = INSTALL_COPY.android.native;
1318
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(InstallSplash, { title: copy.title, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1319
+ "div",
1320
+ {
1321
+ style: {
1322
+ display: "flex",
1323
+ flexDirection: "column",
1324
+ alignItems: "center",
1325
+ gap: 16,
1326
+ padding: "24px 0"
1327
+ },
1328
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Spinner, {})
1329
+ }
1330
+ ) });
1331
+ }
1332
+ function Spinner() {
1333
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1334
+ "div",
1335
+ {
1336
+ "aria-hidden": true,
1337
+ style: {
1338
+ width: 28,
1339
+ height: 28,
1340
+ borderRadius: "50%",
1341
+ border: "3px solid #e5e5e7",
1342
+ borderTopColor: "var(--hook-color-primary)",
1343
+ animation: "hook-install-spin 0.8s linear infinite"
1344
+ },
1345
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: `@keyframes hook-install-spin { to { transform: rotate(360deg); } }` })
1346
+ }
1347
+ );
1348
+ }
1349
+
1350
+ // src/components/InstallGate/Step.tsx
1351
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1298
1352
  function Step2({
1299
1353
  n,
1300
1354
  title,
1301
1355
  subtitle,
1302
1356
  visual
1303
1357
  }) {
1304
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1358
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1305
1359
  "div",
1306
1360
  {
1307
1361
  style: {
@@ -1312,7 +1366,7 @@ function Step2({
1312
1366
  textAlign: "left"
1313
1367
  },
1314
1368
  children: [
1315
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1369
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1316
1370
  "div",
1317
1371
  {
1318
1372
  style: {
@@ -1331,9 +1385,9 @@ function Step2({
1331
1385
  children: n
1332
1386
  }
1333
1387
  ),
1334
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1 }, children: [
1335
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
1336
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1 }, children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
1390
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
1337
1391
  visual
1338
1392
  ] })
1339
1393
  ]
@@ -1342,21 +1396,21 @@ function Step2({
1342
1396
  }
1343
1397
 
1344
1398
  // src/components/InstallGate/variants/IOSafariVariant.tsx
1345
- var import_jsx_runtime11 = require("react/jsx-runtime");
1399
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1346
1400
  function IOSafariVariant({
1347
1401
  state,
1348
1402
  actions
1349
1403
  }) {
1350
1404
  const copy = INSTALL_COPY.iosSafari;
1351
1405
  const showPermanent = shouldShowPermanentOption(state);
1352
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1353
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1406
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1407
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1354
1408
  Step2,
1355
1409
  {
1356
1410
  n: 1,
1357
1411
  title: copy.step1.title,
1358
1412
  subtitle: copy.step1.subtitle,
1359
- visual: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1413
+ visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1360
1414
  "div",
1361
1415
  {
1362
1416
  style: {
@@ -1368,17 +1422,17 @@ function IOSafariVariant({
1368
1422
  padding: "12px 0",
1369
1423
  marginTop: 8
1370
1424
  },
1371
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1425
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1372
1426
  }
1373
1427
  )
1374
1428
  }
1375
1429
  ),
1376
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1430
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1377
1431
  Step2,
1378
1432
  {
1379
1433
  n: 2,
1380
1434
  title: copy.step2.title,
1381
- visual: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1435
+ visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1382
1436
  "div",
1383
1437
  {
1384
1438
  style: {
@@ -1391,19 +1445,19 @@ function IOSafariVariant({
1391
1445
  marginTop: 8
1392
1446
  },
1393
1447
  children: [
1394
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1395
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1448
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1449
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1396
1450
  ]
1397
1451
  }
1398
1452
  )
1399
1453
  }
1400
1454
  ),
1401
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1455
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1402
1456
  Step2,
1403
1457
  {
1404
1458
  n: 3,
1405
1459
  title: copy.step3.title,
1406
- visual: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1460
+ visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1407
1461
  "div",
1408
1462
  {
1409
1463
  style: {
@@ -1414,7 +1468,7 @@ function IOSafariVariant({
1414
1468
  padding: "10px 14px",
1415
1469
  marginTop: 8
1416
1470
  },
1417
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1471
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1418
1472
  "span",
1419
1473
  {
1420
1474
  style: {
@@ -1429,7 +1483,7 @@ function IOSafariVariant({
1429
1483
  )
1430
1484
  }
1431
1485
  ),
1432
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1486
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1433
1487
  "button",
1434
1488
  {
1435
1489
  "data-testid": "install-prompt-skip-session",
@@ -1439,7 +1493,7 @@ function IOSafariVariant({
1439
1493
  children: copy.skip
1440
1494
  }
1441
1495
  ),
1442
- showPermanent && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1496
+ showPermanent && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1443
1497
  "button",
1444
1498
  {
1445
1499
  "data-testid": "install-prompt-skip-permanent",
@@ -1453,21 +1507,21 @@ function IOSafariVariant({
1453
1507
  }
1454
1508
 
1455
1509
  // src/components/InstallGate/variants/IOSOtherVariant.tsx
1456
- var import_jsx_runtime12 = require("react/jsx-runtime");
1510
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1457
1511
  function IOSOtherVariant({
1458
1512
  state,
1459
1513
  actions
1460
1514
  }) {
1461
1515
  const copy = INSTALL_COPY.iosOther;
1462
1516
  const showPermanent = shouldShowPermanentOption(state);
1463
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1464
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1517
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
1518
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1465
1519
  Step2,
1466
1520
  {
1467
1521
  n: 1,
1468
1522
  title: copy.step1.title,
1469
1523
  subtitle: copy.step1.subtitle,
1470
- visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1524
+ visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1471
1525
  "div",
1472
1526
  {
1473
1527
  style: {
@@ -1479,17 +1533,17 @@ function IOSOtherVariant({
1479
1533
  padding: "12px 0",
1480
1534
  marginTop: 8
1481
1535
  },
1482
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1536
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
1483
1537
  }
1484
1538
  )
1485
1539
  }
1486
1540
  ),
1487
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1541
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1488
1542
  Step2,
1489
1543
  {
1490
1544
  n: 2,
1491
1545
  title: copy.step2.title,
1492
- visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1546
+ visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1493
1547
  "div",
1494
1548
  {
1495
1549
  style: {
@@ -1502,19 +1556,19 @@ function IOSOtherVariant({
1502
1556
  marginTop: 8
1503
1557
  },
1504
1558
  children: [
1505
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1506
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1559
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
1560
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
1507
1561
  ]
1508
1562
  }
1509
1563
  )
1510
1564
  }
1511
1565
  ),
1512
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1566
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1513
1567
  Step2,
1514
1568
  {
1515
1569
  n: 3,
1516
1570
  title: copy.step3.title,
1517
- visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1571
+ visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1518
1572
  "div",
1519
1573
  {
1520
1574
  style: {
@@ -1525,7 +1579,7 @@ function IOSOtherVariant({
1525
1579
  padding: "10px 14px",
1526
1580
  marginTop: 8
1527
1581
  },
1528
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1582
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1529
1583
  "span",
1530
1584
  {
1531
1585
  style: {
@@ -1540,7 +1594,7 @@ function IOSOtherVariant({
1540
1594
  )
1541
1595
  }
1542
1596
  ),
1543
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1597
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1544
1598
  "button",
1545
1599
  {
1546
1600
  "data-testid": "install-prompt-skip-session",
@@ -1550,7 +1604,7 @@ function IOSOtherVariant({
1550
1604
  children: copy.skip
1551
1605
  }
1552
1606
  ),
1553
- showPermanent && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1607
+ showPermanent && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1554
1608
  "button",
1555
1609
  {
1556
1610
  "data-testid": "install-prompt-skip-permanent",
@@ -1565,7 +1619,7 @@ function IOSOtherVariant({
1565
1619
 
1566
1620
  // src/components/InstallGate/variants/InAppBrowserVariant.tsx
1567
1621
  var import_react7 = require("react");
1568
- var import_jsx_runtime13 = require("react/jsx-runtime");
1622
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1569
1623
  function InAppBrowserVariant({
1570
1624
  state,
1571
1625
  actions
@@ -1581,10 +1635,10 @@ function InAppBrowserVariant({
1581
1635
  setTimeout(() => setCopied(false), 2e3);
1582
1636
  };
1583
1637
  const DotsIcon = app === "facebook" || app === "telegram" ? MenuDotsVerticalIcon : MenuDotsHorizontalIcon;
1584
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(InstallSplash, { title: appCopy.title, children: [
1585
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Step3, { n: 1, icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DotsIcon, { size: 20 }), children: appCopy.step1 }),
1586
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Step3, { n: 2, icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
1587
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1638
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(InstallSplash, { title: appCopy.title, children: [
1639
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 1, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DotsIcon, { size: 20 }), children: appCopy.step1 }),
1640
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 2, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
1641
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1588
1642
  "button",
1589
1643
  {
1590
1644
  "data-testid": "install-prompt-cta-inapp-copy",
@@ -1594,7 +1648,7 @@ function InAppBrowserVariant({
1594
1648
  children: copied ? copy.copiedToast : copy.copy
1595
1649
  }
1596
1650
  ),
1597
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1651
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1598
1652
  "button",
1599
1653
  {
1600
1654
  "data-testid": "install-prompt-skip-session",
@@ -1604,7 +1658,7 @@ function InAppBrowserVariant({
1604
1658
  children: copy.skip
1605
1659
  }
1606
1660
  ),
1607
- showPermanent && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1661
+ showPermanent && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1608
1662
  "button",
1609
1663
  {
1610
1664
  "data-testid": "install-prompt-skip-permanent",
@@ -1621,7 +1675,7 @@ function Step3({
1621
1675
  icon,
1622
1676
  children
1623
1677
  }) {
1624
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1678
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1625
1679
  "div",
1626
1680
  {
1627
1681
  style: {
@@ -1635,7 +1689,7 @@ function Step3({
1635
1689
  textAlign: "left"
1636
1690
  },
1637
1691
  children: [
1638
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1692
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1639
1693
  "div",
1640
1694
  {
1641
1695
  style: {
@@ -1654,15 +1708,15 @@ function Step3({
1654
1708
  children: n
1655
1709
  }
1656
1710
  ),
1657
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
1711
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
1712
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
1659
1713
  ]
1660
1714
  }
1661
1715
  );
1662
1716
  }
1663
1717
 
1664
1718
  // src/components/InstallGate/variants/DesktopVariant.tsx
1665
- var import_jsx_runtime14 = require("react/jsx-runtime");
1719
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1666
1720
  function DesktopVariant({
1667
1721
  state,
1668
1722
  actions
@@ -1671,21 +1725,21 @@ function DesktopVariant({
1671
1725
  const copy = INSTALL_COPY.desktop;
1672
1726
  const iconUrl = theme.icon_url || theme.logo_url || null;
1673
1727
  if (!state.isInstallable) return null;
1674
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1728
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1675
1729
  "div",
1676
1730
  {
1677
1731
  role: "complementary",
1678
1732
  "aria-label": copy.title,
1679
1733
  style: bannerStyle,
1680
1734
  children: [
1681
- iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1735
+ iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1682
1736
  "img",
1683
1737
  {
1684
1738
  src: iconUrl,
1685
1739
  alt: "",
1686
1740
  style: { width: 40, height: 40, borderRadius: 10, objectFit: "cover", flexShrink: 0 }
1687
1741
  }
1688
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1742
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1689
1743
  "div",
1690
1744
  {
1691
1745
  style: {
@@ -1704,11 +1758,11 @@ function DesktopVariant({
1704
1758
  children: name.charAt(0).toUpperCase()
1705
1759
  }
1706
1760
  ),
1707
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
1708
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
1709
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
1761
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
1763
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
1710
1764
  ] }),
1711
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1765
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1712
1766
  "button",
1713
1767
  {
1714
1768
  "data-testid": "install-prompt-cta-desktop",
@@ -1729,12 +1783,12 @@ function DesktopVariant({
1729
1783
  flexShrink: 0
1730
1784
  },
1731
1785
  children: [
1732
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DownloadIcon, { size: 14 }),
1786
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DownloadIcon, { size: 14 }),
1733
1787
  copy.cta
1734
1788
  ]
1735
1789
  }
1736
1790
  ),
1737
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1791
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1738
1792
  "button",
1739
1793
  {
1740
1794
  "data-testid": "install-prompt-desktop-close",
@@ -1749,7 +1803,7 @@ function DesktopVariant({
1749
1803
  padding: 4,
1750
1804
  flexShrink: 0
1751
1805
  },
1752
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(XIcon, { size: 16 })
1806
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(XIcon, { size: 16 })
1753
1807
  }
1754
1808
  )
1755
1809
  ]
@@ -1773,7 +1827,7 @@ var bannerStyle = {
1773
1827
  };
1774
1828
 
1775
1829
  // src/components/InstallGate/InstallGate.tsx
1776
- var import_jsx_runtime15 = require("react/jsx-runtime");
1830
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1777
1831
  function InstallGate({ children }) {
1778
1832
  const { slug, features_enabled } = useTemplateConfig();
1779
1833
  const enabled = features_enabled.includes("install_prompt");
@@ -1794,30 +1848,32 @@ function InstallGate({ children }) {
1794
1848
  variant: installState.variant
1795
1849
  });
1796
1850
  }, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
1797
- if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
1798
- if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
1851
+ if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
1852
+ if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
1799
1853
  if (installState.variant === "desktop") {
1800
1854
  const showBanner = !installState.isDismissedSession && !installState.isDismissedPermanent;
1801
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
1855
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
1802
1856
  children,
1803
- showBanner && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DesktopVariant, { state: installState, actions: installState })
1857
+ showBanner && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DesktopVariant, { state: installState, actions: installState })
1804
1858
  ] });
1805
1859
  }
1806
- if (!shouldBlock) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
1860
+ if (!shouldBlock) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
1807
1861
  switch (installState.variant) {
1808
1862
  case "android-native":
1809
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AndroidNativeVariant, { state: installState, actions: installState });
1863
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidNativeVariant, { state: installState, actions: installState });
1810
1864
  case "android-manual":
1811
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AndroidManualVariant, { state: installState, actions: installState });
1865
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidManualVariant, { state: installState, actions: installState });
1866
+ case "android-pending":
1867
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidPendingVariant, {});
1812
1868
  case "ios-safari":
1813
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IOSafariVariant, { state: installState, actions: installState });
1869
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSafariVariant, { state: installState, actions: installState });
1814
1870
  case "ios-other":
1815
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IOSOtherVariant, { state: installState, actions: installState });
1871
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSOtherVariant, { state: installState, actions: installState });
1816
1872
  case "in-app":
1817
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(InAppBrowserVariant, { state: installState, actions: installState });
1873
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(InAppBrowserVariant, { state: installState, actions: installState });
1818
1874
  case "none":
1819
1875
  default:
1820
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
1876
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
1821
1877
  }
1822
1878
  }
1823
1879
 
@@ -1829,7 +1885,7 @@ function PushPrompt() {
1829
1885
  // src/internal/SessionExpiredBanner.tsx
1830
1886
  var import_react9 = require("react");
1831
1887
  var import_sdk3 = require("@hook-sdk/sdk");
1832
- var import_jsx_runtime16 = require("react/jsx-runtime");
1888
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1833
1889
  var DISMISS_KEY = "hook:session-expired-dismissed-until";
1834
1890
  var DISMISS_TTL_MS = 60 * 60 * 1e3;
1835
1891
  function SessionExpiredBanner() {
@@ -1856,13 +1912,13 @@ function SessionExpiredBanner() {
1856
1912
  localStorage.setItem(DISMISS_KEY, String(Date.now() + DISMISS_TTL_MS));
1857
1913
  setShow(false);
1858
1914
  }
1859
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { role: "alert", className: "fixed top-0 inset-x-0 bg-red-600 text-white px-4 py-2 flex items-center justify-between gap-3 text-sm shadow", style: { zIndex: 10001 }, children: [
1860
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { children: [
1861
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "Sua sess\xE3o expirou." }),
1915
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { role: "alert", className: "fixed top-0 inset-x-0 bg-red-600 text-white px-4 py-2 flex items-center justify-between gap-3 text-sm shadow", style: { zIndex: 10001 }, children: [
1916
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
1917
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "Sua sess\xE3o expirou." }),
1862
1918
  " Fa\xE7a login novamente para continuar."
1863
1919
  ] }),
1864
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2", children: [
1865
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1920
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
1921
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1866
1922
  "button",
1867
1923
  {
1868
1924
  type: "button",
@@ -1871,7 +1927,7 @@ function SessionExpiredBanner() {
1871
1927
  children: "Fazer login"
1872
1928
  }
1873
1929
  ),
1874
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1930
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1875
1931
  "button",
1876
1932
  {
1877
1933
  type: "button",
@@ -1887,7 +1943,7 @@ function SessionExpiredBanner() {
1887
1943
 
1888
1944
  // src/defaults/ErrorBoundary.tsx
1889
1945
  var import_react10 = require("react");
1890
- var import_jsx_runtime17 = require("react/jsx-runtime");
1946
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1891
1947
  var ErrorBoundary = class extends import_react10.Component {
1892
1948
  state = { error: null };
1893
1949
  static getDerivedStateFromError(error) {
@@ -1905,19 +1961,19 @@ var ErrorBoundary = class extends import_react10.Component {
1905
1961
  }
1906
1962
  render() {
1907
1963
  if (this.state.error) {
1908
- return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
1909
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { children: "Algo deu errado" }),
1910
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
1964
+ return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
1965
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h2", { children: "Algo deu errado" }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
1911
1967
  ] });
1912
1968
  }
1913
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: this.props.children });
1969
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: this.props.children });
1914
1970
  }
1915
1971
  };
1916
1972
 
1917
1973
  // src/internal/PaymentReturnHandler.tsx
1918
1974
  var import_react11 = require("react");
1919
1975
  var import_sdk4 = require("@hook-sdk/sdk");
1920
- var import_jsx_runtime18 = require("react/jsx-runtime");
1976
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1921
1977
  var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
1922
1978
  var MAX_CYCLES = 3;
1923
1979
  var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
@@ -1980,19 +2036,19 @@ function PaymentReturnHandler({ children }) {
1980
2036
  window.location.href = cleanUrl.toString();
1981
2037
  }, []);
1982
2038
  if (state === "confirming") {
1983
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
2039
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
1984
2040
  }
1985
2041
  if (state === "waiting") {
1986
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
1987
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
1988
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
2042
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
2043
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
1989
2045
  ] }) });
1990
2046
  }
1991
2047
  if (state === "timeout") {
1992
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
1993
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
1994
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
1995
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2048
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
2049
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
2050
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
2051
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1996
2052
  "button",
1997
2053
  {
1998
2054
  type: "button",
@@ -2005,7 +2061,7 @@ function PaymentReturnHandler({ children }) {
2005
2061
  children: "Tentar de novo"
2006
2062
  }
2007
2063
  ),
2008
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2064
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2009
2065
  "button",
2010
2066
  {
2011
2067
  type: "button",
@@ -2015,7 +2071,7 @@ function PaymentReturnHandler({ children }) {
2015
2071
  children: "Voltar pro app"
2016
2072
  }
2017
2073
  ),
2018
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2074
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2019
2075
  "a",
2020
2076
  {
2021
2077
  href: SUPPORT_MAILTO,
@@ -2027,7 +2083,7 @@ function PaymentReturnHandler({ children }) {
2027
2083
  ] })
2028
2084
  ] }) });
2029
2085
  }
2030
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children });
2086
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children });
2031
2087
  }
2032
2088
  var overlayStyle2 = {
2033
2089
  position: "fixed",
@@ -2066,7 +2122,7 @@ var linkStyle = {
2066
2122
  };
2067
2123
 
2068
2124
  // src/AppRoot.tsx
2069
- var import_jsx_runtime19 = require("react/jsx-runtime");
2125
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2070
2126
  function buildLegacyConfigShim(config) {
2071
2127
  const paywall = config.paywall;
2072
2128
  const isFree = paywall.mode === "free";
@@ -2076,7 +2132,16 @@ function buildLegacyConfigShim(config) {
2076
2132
  slug: config.slug,
2077
2133
  name: config.name,
2078
2134
  email_alias: config.slug,
2079
- theme: { primary_color: config.branding.primaryColor },
2135
+ // Map branding into the legacy theme shape so InstallSplash (and
2136
+ // anything else reading theme.icon_url / theme.logo_url) can surface
2137
+ // the app icon instead of the generic "first letter of name" fallback.
2138
+ // Falls back to logoUrl when iconUrl is unset — apps that haven't
2139
+ // adopted iconUrl keep their previous behavior unchanged.
2140
+ theme: {
2141
+ primary_color: config.branding.primaryColor,
2142
+ icon_url: config.branding.iconUrl ?? config.branding.logoUrl,
2143
+ logo_url: config.branding.logoUrl
2144
+ },
2080
2145
  features_enabled: config.features_enabled ?? [],
2081
2146
  dependencies_allowlist: ["react", "react-dom"],
2082
2147
  subscription: {
@@ -2134,10 +2199,10 @@ function AppRoot(props) {
2134
2199
  const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
2135
2200
  const basename = `/app/${config.slug}`;
2136
2201
  const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
2137
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Router, { ...routerProps, children: [
2138
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
2139
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SessionExpiredBanner, {}),
2140
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InstallGate, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2202
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Router, { ...routerProps, children: [
2203
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
2204
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SessionExpiredBanner, {}),
2205
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(InstallGate, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2141
2206
  AuthGated,
2142
2207
  {
2143
2208
  config,
@@ -2149,9 +2214,9 @@ function AppRoot(props) {
2149
2214
  Paywall,
2150
2215
  Onboarding,
2151
2216
  PreAuthFlow,
2152
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: [
2217
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: [
2153
2218
  children,
2154
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PushPrompt, {})
2219
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PushPrompt, {})
2155
2220
  ] })
2156
2221
  }
2157
2222
  ) })
@@ -2171,25 +2236,25 @@ function AuthGated({
2171
2236
  if (authStatus === "loading") return null;
2172
2237
  if (authStatus !== "authenticated") {
2173
2238
  if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
2174
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_router_dom2.Routes, { children: [
2175
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Login, {}) }),
2176
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Signup, {}) }),
2177
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Forgot, {}) }),
2178
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Reset, {}) }),
2179
- EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(EmailVerify, {}) }) : null,
2180
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PreAuthFlow, {}) })
2239
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_router_dom2.Routes, { children: [
2240
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Login, {}) }),
2241
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Signup, {}) }),
2242
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Forgot, {}) }),
2243
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Reset, {}) }),
2244
+ EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EmailVerify, {}) }) : null,
2245
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PreAuthFlow, {}) })
2181
2246
  ] });
2182
2247
  }
2183
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_router_dom2.Routes, { children: [
2184
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Login, {}) }),
2185
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Signup, {}) }),
2186
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Forgot, {}) }),
2187
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Reset, {}) }),
2188
- EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(EmailVerify, {}) }) : null,
2189
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
2248
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_router_dom2.Routes, { children: [
2249
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Login, {}) }),
2250
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Signup, {}) }),
2251
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Forgot, {}) }),
2252
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Reset, {}) }),
2253
+ EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EmailVerify, {}) }) : null,
2254
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
2190
2255
  ] });
2191
2256
  }
2192
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children });
2257
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, { children });
2193
2258
  }
2194
2259
  function FallbackPaywall() {
2195
2260
  return null;
@@ -2280,7 +2345,7 @@ function usePush() {
2280
2345
  }
2281
2346
 
2282
2347
  // src/components/PushPrompt.tsx
2283
- var import_jsx_runtime20 = require("react/jsx-runtime");
2348
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2284
2349
  function platformRecoveryCopy(texts) {
2285
2350
  if (typeof navigator === "undefined") return null;
2286
2351
  const ua = navigator.userAgent || "";
@@ -2303,28 +2368,28 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
2303
2368
  const { state, subscribe } = usePush();
2304
2369
  if (state.kind === "subscribed" || state.kind === "dismissed") return null;
2305
2370
  if (state.kind === "ios_needs_install") {
2306
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
2307
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { children: texts.iosInstallTitle }),
2308
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: texts.iosInstallBody }),
2309
- onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2371
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
2372
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { children: texts.iosInstallTitle }),
2373
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.iosInstallBody }),
2374
+ onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
2310
2375
  ] });
2311
2376
  }
2312
2377
  if (state.kind === "denied") {
2313
2378
  const recovery = platformRecoveryCopy(texts);
2314
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
2315
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { children: texts.deniedTitle }),
2316
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: texts.deniedBody }),
2317
- recovery && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { "data-testid": "denied-recovery", children: recovery })
2379
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
2380
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { children: texts.deniedTitle }),
2381
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.deniedBody }),
2382
+ recovery && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { "data-testid": "denied-recovery", children: recovery })
2318
2383
  ] });
2319
2384
  }
2320
2385
  if (state.kind === "unsupported") {
2321
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: texts.unsupportedBody }) });
2386
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.unsupportedBody }) });
2322
2387
  }
2323
2388
  if (state.kind === "error") {
2324
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: state.message }) });
2389
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: state.message }) });
2325
2390
  }
2326
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className, role: "region", children: [
2327
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2391
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", children: [
2392
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2328
2393
  "button",
2329
2394
  {
2330
2395
  type: "button",
@@ -2338,23 +2403,23 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
2338
2403
  children: texts.cta
2339
2404
  }
2340
2405
  ),
2341
- onDeclined && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2406
+ onDeclined && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
2342
2407
  ] });
2343
2408
  }
2344
2409
 
2345
2410
  // src/defaults/LoadingState.tsx
2346
- var import_jsx_runtime21 = require("react/jsx-runtime");
2411
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2347
2412
  function LoadingState({ message }) {
2348
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: message ?? "Carregando..." }) });
2413
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: message ?? "Carregando..." }) });
2349
2414
  }
2350
2415
 
2351
2416
  // src/defaults/EmptyState.tsx
2352
- var import_jsx_runtime22 = require("react/jsx-runtime");
2417
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2353
2418
  function EmptyState({ title, description, action }) {
2354
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
2355
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
2356
- description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { style: { opacity: 0.7 }, children: description }),
2357
- action && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginTop: 16 }, children: action })
2419
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
2420
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
2421
+ description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { opacity: 0.7 }, children: description }),
2422
+ action && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { marginTop: 16 }, children: action })
2358
2423
  ] });
2359
2424
  }
2360
2425
 
@@ -2781,20 +2846,20 @@ function useToast() {
2781
2846
 
2782
2847
  // src/RouteBoundary.tsx
2783
2848
  var import_react_router_dom3 = require("react-router-dom");
2784
- var import_jsx_runtime23 = require("react/jsx-runtime");
2849
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2785
2850
  function RouteBoundary({ children }) {
2786
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_router_dom3.Routes, { children: [
2851
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_router_dom3.Routes, { children: [
2787
2852
  children,
2788
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DefaultNotFound, {}) })
2853
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DefaultNotFound, {}) })
2789
2854
  ] });
2790
2855
  }
2791
2856
  function DefaultNotFound() {
2792
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
2857
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
2793
2858
  }
2794
2859
 
2795
2860
  // src/PreAuthShell.tsx
2796
2861
  var import_react_router_dom4 = require("react-router-dom");
2797
- var import_jsx_runtime24 = require("react/jsx-runtime");
2862
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2798
2863
  function PreAuthShell({
2799
2864
  basename,
2800
2865
  testRouter,
@@ -2802,9 +2867,9 @@ function PreAuthShell({
2802
2867
  children
2803
2868
  }) {
2804
2869
  if (testRouter === "memory") {
2805
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom4.Routes, { children }) });
2870
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.Routes, { children }) });
2806
2871
  }
2807
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_router_dom4.Routes, { children }) });
2872
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_router_dom4.Routes, { children }) });
2808
2873
  }
2809
2874
 
2810
2875
  // src/OnboardingFlow.tsx
@@ -2825,7 +2890,7 @@ function useOnboardingStep() {
2825
2890
  }
2826
2891
 
2827
2892
  // src/OnboardingFlow.tsx
2828
- var import_jsx_runtime25 = require("react/jsx-runtime");
2893
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2829
2894
  var isFilled = (v) => v != null && v !== "";
2830
2895
  var CURRENT_STEP_FIELD = "currentStep";
2831
2896
  function readPersistedStepIdx(draft) {
@@ -2903,7 +2968,7 @@ function OnboardingFlow({
2903
2968
  `[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
2904
2969
  );
2905
2970
  }
2906
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Screen, {}) });
2971
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Screen, {}) });
2907
2972
  }
2908
2973
 
2909
2974
  // src/hooks/useFeature.ts