@openreceive/react 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  // src/checkout.ts
2
2
  import {
3
+ checkoutLabels as checkoutLabels6,
3
4
  createLightningInvoiceDecodeUrl as createLightningInvoiceDecodeUrl2,
4
5
  enterCheckoutResumePath,
5
6
  mergeAttemptIntoCheckout,
6
7
  mergeAttemptIntoSnapshot,
7
8
  OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES as OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES3,
8
9
  OPENRECEIVE_DEFAULT_PREFIX,
9
- checkoutLabels as checkoutLabels6,
10
10
  orClasses as orClasses7,
11
11
  prepareCheckout,
12
12
  requestCheckout,
13
+ resumeSwapAttempt,
13
14
  validateCheckoutProps
14
15
  } from "@openreceive/browser/headless";
15
16
  import * as React10 from "react";
@@ -429,106 +430,17 @@ function SatsDetail(props) {
429
430
  );
430
431
  }
431
432
 
432
- // src/transaction-details.ts
433
- import {
434
- checkoutLabels as checkoutLabels2,
435
- orClasses as orClasses2,
436
- resolveTransactionDetailRows
437
- } from "@openreceive/browser/headless";
438
- import * as React4 from "react";
439
- function TransactionDetails(props) {
440
- const rows = resolveTransactionDetailRows(props.state);
441
- if (rows.length === 0) return null;
442
- return React4.createElement(
443
- "details",
444
- {
445
- className: joinClassNames(orClasses2.transactionDetails, props.className),
446
- open: props.open === true ? true : void 0
447
- },
448
- React4.createElement(
449
- "summary",
450
- { className: orClasses2.transactionDetailsTitle },
451
- checkoutLabels2.transactionDetails
452
- ),
453
- React4.createElement(
454
- "div",
455
- { className: orClasses2.transactionDetailsContent },
456
- React4.createElement(
457
- "dl",
458
- { className: orClasses2.swapDetails },
459
- rows.flatMap(
460
- (row) => renderTransactionDetailRow(row, {
461
- clipboard: props.clipboard,
462
- onError: props.onError
463
- })
464
- )
465
- )
466
- )
467
- );
468
- }
469
- function renderTransactionDetailRow(row, options) {
470
- const copyValue = row.copyValue ?? row.value;
471
- return [
472
- React4.createElement(
473
- "dt",
474
- { key: `${row.label}-label`, className: orClasses2.swapDetailsDt },
475
- row.label
476
- ),
477
- React4.createElement(
478
- "dd",
479
- { key: `${row.label}-value`, className: orClasses2.swapDetailsDd },
480
- React4.createElement("code", { className: orClasses2.swapDetailsCode }, row.value),
481
- React4.createElement(
482
- "div",
483
- { className: orClasses2.swapDetailsActions },
484
- React4.createElement(TransactionDetailCopyButton, {
485
- value: copyValue,
486
- clipboard: options.clipboard,
487
- onError: options.onError
488
- }),
489
- row.href === void 0 ? null : React4.createElement(
490
- "a",
491
- {
492
- className: orClasses2.swapDetailsLink,
493
- href: row.href,
494
- rel: "noreferrer",
495
- target: "_blank"
496
- },
497
- row.hrefLabel ?? checkoutLabels2.viewOnExplorer
498
- )
499
- )
500
- )
501
- ];
502
- }
503
- function TransactionDetailCopyButton(props) {
504
- const [copied, setCopied] = useTransientValue(false);
505
- const label = copied ? checkoutLabels2.copied : "Copy";
506
- return React4.createElement(
507
- "button",
508
- {
509
- className: orClasses2.detailCopy,
510
- type: "button",
511
- "aria-label": label,
512
- title: label,
513
- onClick: () => {
514
- void copyText(props.value, props.clipboard).then(() => setCopied(true)).catch((error) => props.onError?.(error));
515
- }
516
- },
517
- React4.createElement(ClipboardIcon)
518
- );
519
- }
520
-
521
433
  // src/theme.ts
522
- import * as React5 from "react";
434
+ import * as React4 from "react";
523
435
  import {
524
436
  OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES as OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES2,
525
437
  OPENRECEIVE_THEME_STORAGE_KEY,
526
438
  createThemeModel,
527
- orClasses as orClasses3,
439
+ orClasses as orClasses2,
528
440
  readThemePreference,
529
441
  writeThemePreference
530
442
  } from "@openreceive/browser/headless";
531
- var ThemeContext = React5.createContext(null);
443
+ var ThemeContext = React4.createContext(null);
532
444
  var storedThemeListeners = /* @__PURE__ */ new Set();
533
445
  var lastSetTheme = /* @__PURE__ */ new Map();
534
446
  function notifyStoredThemeChange() {
@@ -557,9 +469,9 @@ function useLocalTheme(options = {}) {
557
469
  const storageKey = options.storageKey ?? OPENRECEIVE_THEME_STORAGE_KEY;
558
470
  const storage = options.storage;
559
471
  const defaultTheme = options.defaultTheme;
560
- const theme = React5.useSyncExternalStore(
472
+ const theme = React4.useSyncExternalStore(
561
473
  subscribeStoredTheme,
562
- React5.useCallback(
474
+ React4.useCallback(
563
475
  () => readThemePreference({
564
476
  storage,
565
477
  storageKey,
@@ -567,7 +479,7 @@ function useLocalTheme(options = {}) {
567
479
  }),
568
480
  [storage, storageKey, defaultTheme]
569
481
  ),
570
- React5.useCallback(
482
+ React4.useCallback(
571
483
  () => (
572
484
  // A host-supplied storage is readable on the server (that is how SSR theming is
573
485
  // wired); the implicit browser localStorage is not, so fall back to the default.
@@ -576,13 +488,13 @@ function useLocalTheme(options = {}) {
576
488
  [storage, storageKey, defaultTheme]
577
489
  )
578
490
  );
579
- const systemDark = React5.useSyncExternalStore(
491
+ const systemDark = React4.useSyncExternalStore(
580
492
  subscribeSystemDark,
581
493
  getSystemDark,
582
494
  getServerSystemDark
583
495
  );
584
496
  const themeModel = createThemeModel(theme, { systemDark });
585
- const setTheme = React5.useCallback(
497
+ const setTheme = React4.useCallback(
586
498
  (nextTheme) => {
587
499
  lastSetTheme.set(storageKey, nextTheme);
588
500
  writeThemePreference(nextTheme, {
@@ -593,7 +505,7 @@ function useLocalTheme(options = {}) {
593
505
  },
594
506
  [storage, storageKey]
595
507
  );
596
- const toggleTheme = React5.useCallback(() => {
508
+ const toggleTheme = React4.useCallback(() => {
597
509
  setTheme(themeModel.nextTheme);
598
510
  }, [setTheme, themeModel.nextTheme]);
599
511
  return {
@@ -610,7 +522,7 @@ function useLocalTheme(options = {}) {
610
522
  };
611
523
  }
612
524
  function useTheme(options = {}) {
613
- const scoped = React5.useContext(ThemeContext);
525
+ const scoped = React4.useContext(ThemeContext);
614
526
  const local = useLocalTheme(options);
615
527
  const storageKey = options.storageKey ?? OPENRECEIVE_THEME_STORAGE_KEY;
616
528
  if (scoped !== null && options.storage === void 0 && (options.storageKey === void 0 || options.storageKey === storageKey) && options.defaultTheme === void 0) {
@@ -637,7 +549,7 @@ function ThemeToggle(props) {
637
549
  const componentProps = {
638
550
  ...buttonProps,
639
551
  "aria-label": themeModel.toggleLabel,
640
- className: joinClassNames(orClasses3.themeToggle, buttonProps.className),
552
+ className: joinClassNames(orClasses2.themeToggle, buttonProps.className),
641
553
  title: themeModel.toggleLabel,
642
554
  type,
643
555
  [OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES2.themeToggle]: "",
@@ -648,7 +560,7 @@ function ThemeToggle(props) {
648
560
  if (onThemeChange === void 0) fallback.setTheme(themeModel.nextTheme);
649
561
  }
650
562
  };
651
- return React5.createElement(ButtonComponent, componentProps, children ?? themeModel.toggleLabel);
563
+ return React4.createElement(ButtonComponent, componentProps, children ?? themeModel.toggleLabel);
652
564
  }
653
565
  function ThemeScope(props) {
654
566
  const {
@@ -669,22 +581,22 @@ function ThemeScope(props) {
669
581
  storage
670
582
  });
671
583
  const scopedChildren = typeof children === "function" ? children(theme) : children;
672
- return React5.createElement(
584
+ return React4.createElement(
673
585
  ThemeContext.Provider,
674
586
  { value: theme },
675
587
  // Variadic children, not an array: an array child needs a key on every entry.
676
- React5.createElement(
588
+ React4.createElement(
677
589
  Element,
678
590
  {
679
591
  ...elementProps,
680
592
  ...theme.attributes
681
593
  },
682
- themeToggle ? React5.createElement(
594
+ themeToggle ? React4.createElement(
683
595
  "div",
684
596
  {
685
597
  className: topbarClassName
686
598
  },
687
- React5.createElement(ThemeToggle, {
599
+ React4.createElement(ThemeToggle, {
688
600
  className: themeToggleClassName,
689
601
  theme: theme.theme,
690
602
  resolvedTheme: theme.resolvedTheme,
@@ -697,6 +609,95 @@ function ThemeScope(props) {
697
609
  );
698
610
  }
699
611
 
612
+ // src/transaction-details.ts
613
+ import {
614
+ checkoutLabels as checkoutLabels2,
615
+ orClasses as orClasses3,
616
+ resolveTransactionDetailRows
617
+ } from "@openreceive/browser/headless";
618
+ import * as React5 from "react";
619
+ function TransactionDetails(props) {
620
+ const rows = resolveTransactionDetailRows(props.state);
621
+ if (rows.length === 0) return null;
622
+ return React5.createElement(
623
+ "details",
624
+ {
625
+ className: joinClassNames(orClasses3.transactionDetails, props.className),
626
+ open: props.open === true ? true : void 0
627
+ },
628
+ React5.createElement(
629
+ "summary",
630
+ { className: orClasses3.transactionDetailsTitle },
631
+ checkoutLabels2.transactionDetails
632
+ ),
633
+ React5.createElement(
634
+ "div",
635
+ { className: orClasses3.transactionDetailsContent },
636
+ React5.createElement(
637
+ "dl",
638
+ { className: orClasses3.swapDetails },
639
+ rows.flatMap(
640
+ (row) => renderTransactionDetailRow(row, {
641
+ clipboard: props.clipboard,
642
+ onError: props.onError
643
+ })
644
+ )
645
+ )
646
+ )
647
+ );
648
+ }
649
+ function renderTransactionDetailRow(row, options) {
650
+ const copyValue = row.copyValue ?? row.value;
651
+ return [
652
+ React5.createElement(
653
+ "dt",
654
+ { key: `${row.label}-label`, className: orClasses3.swapDetailsDt },
655
+ row.label
656
+ ),
657
+ React5.createElement(
658
+ "dd",
659
+ { key: `${row.label}-value`, className: orClasses3.swapDetailsDd },
660
+ React5.createElement("code", { className: orClasses3.swapDetailsCode }, row.value),
661
+ React5.createElement(
662
+ "div",
663
+ { className: orClasses3.swapDetailsActions },
664
+ React5.createElement(TransactionDetailCopyButton, {
665
+ value: copyValue,
666
+ clipboard: options.clipboard,
667
+ onError: options.onError
668
+ }),
669
+ row.href === void 0 ? null : React5.createElement(
670
+ "a",
671
+ {
672
+ className: orClasses3.swapDetailsLink,
673
+ href: row.href,
674
+ rel: "noreferrer",
675
+ target: "_blank"
676
+ },
677
+ row.hrefLabel ?? checkoutLabels2.viewOnExplorer
678
+ )
679
+ )
680
+ )
681
+ ];
682
+ }
683
+ function TransactionDetailCopyButton(props) {
684
+ const [copied, setCopied] = useTransientValue(false);
685
+ const label = copied ? checkoutLabels2.copied : "Copy";
686
+ return React5.createElement(
687
+ "button",
688
+ {
689
+ className: orClasses3.detailCopy,
690
+ type: "button",
691
+ "aria-label": label,
692
+ title: label,
693
+ onClick: () => {
694
+ void copyText(props.value, props.clipboard).then(() => setCopied(true)).catch((error) => props.onError?.(error));
695
+ }
696
+ },
697
+ React5.createElement(ClipboardIcon)
698
+ );
699
+ }
700
+
700
701
  // src/use-checkout.ts
701
702
  import * as React6 from "react";
702
703
  import {
@@ -935,8 +936,10 @@ import {
935
936
  createMethodGridDisplay,
936
937
  createPaymentWizardController,
937
938
  createPaymentWizardModel,
939
+ createSwapDisplayModel as createSwapDisplayModel2,
938
940
  createWizardRouteAssetDisplays,
939
941
  createWizardRouteDisplays,
942
+ formatMethodNetworkDetail,
940
943
  formatNetworkSummary,
941
944
  getNetworkIcon,
942
945
  getPaymentMethodIcon,
@@ -1199,16 +1202,17 @@ function ProviderTutorialModal(options) {
1199
1202
 
1200
1203
  // src/swap.ts
1201
1204
  import {
1205
+ checkoutLabels as checkoutLabels4,
1202
1206
  createDetailExternalLink,
1207
+ createQrSvgController as createQrSvgController2,
1203
1208
  createSwapDisplayModel,
1209
+ createSwapUnavailableModel,
1204
1210
  createTransactionDetails,
1205
- createQrSvgController as createQrSvgController2,
1211
+ currentCheckoutUrl,
1206
1212
  getSwapRefundFormError,
1207
- checkoutLabels as checkoutLabels4,
1208
- createSwapUnavailableModel,
1209
- swapOptionLimitMessage,
1210
1213
  orClasses as orClasses5,
1211
- selectCheckoutDisplayInvoice
1214
+ selectCheckoutDisplayInvoice,
1215
+ swapOptionLimitMessage
1212
1216
  } from "@openreceive/browser/headless";
1213
1217
  import * as React8 from "react";
1214
1218
  function renderSwapActions(options) {
@@ -1339,6 +1343,25 @@ function renderSwapDepositPanel(options) {
1339
1343
  display.providerStateDetail
1340
1344
  )
1341
1345
  );
1346
+ const refundHeading = React8.createElement(
1347
+ "div",
1348
+ { className: orClasses5.swapRefundHeading, role: "alert" },
1349
+ renderAlertIcon("warning"),
1350
+ React8.createElement(
1351
+ "div",
1352
+ { className: orClasses5.swapNetworkWarningContent },
1353
+ React8.createElement(
1354
+ "strong",
1355
+ { className: orClasses5.swapHeadingTitle },
1356
+ display.providerStateLabel
1357
+ ),
1358
+ React8.createElement(
1359
+ "span",
1360
+ { className: orClasses5.swapHeadingDetail },
1361
+ display.providerStateDetail
1362
+ )
1363
+ )
1364
+ );
1342
1365
  const waitingCard = (countdownLabel) => React8.createElement(WaitingState, {
1343
1366
  waiting: true,
1344
1367
  statusTitle: display.providerStateLabel,
@@ -1443,26 +1466,20 @@ function renderSwapDepositPanel(options) {
1443
1466
  {
1444
1467
  className: orClasses5.swapPanel
1445
1468
  },
1446
- heading,
1447
- renderSwapRefundFacts(display, options),
1448
- React8.createElement(
1449
- "p",
1450
- {
1451
- className: orClasses5.swapWarning
1452
- },
1453
- `Use a ${display.networkLabel} address you control. Do not paste the deposit address.`
1454
- ),
1469
+ refundHeading,
1470
+ renderSwapRefundReturnWarning(display, options),
1471
+ renderSwapAmountFacts(display),
1455
1472
  React8.createElement(SwapRefundForm, {
1456
1473
  attemptId: display.attemptId,
1457
1474
  payInAsset: display.payInAsset,
1458
1475
  networkLabel: display.networkLabel,
1476
+ ...display.refundReason === void 0 ? {} : { refundReason: display.refundReason },
1459
1477
  submittedRefundAddress: display.refundAddress,
1460
1478
  refundAllowed: display.refundAllowed,
1461
1479
  onRefund: options.onRefund,
1462
1480
  onError: options.onError
1463
1481
  }),
1464
- renderSwapSupportDetails(display, options),
1465
- renderSwapRefundReturnWarning(display)
1482
+ renderSwapSupportDetails(display, options)
1466
1483
  );
1467
1484
  }
1468
1485
  if (display.state === "refund_pending" || display.state === "refunded") {
@@ -1471,8 +1488,9 @@ function renderSwapDepositPanel(options) {
1471
1488
  {
1472
1489
  className: orClasses5.swapPanel
1473
1490
  },
1474
- heading,
1475
- renderSwapRefundFacts(display, options),
1491
+ refundHeading,
1492
+ renderSwapRefundReturnWarning(display, options),
1493
+ renderSwapAmountFacts(display),
1476
1494
  React8.createElement(
1477
1495
  "dl",
1478
1496
  {
@@ -1489,8 +1507,7 @@ function renderSwapDepositPanel(options) {
1489
1507
  payInAsset: display.payInAsset
1490
1508
  })
1491
1509
  ),
1492
- renderSwapSupportDetails(display, options),
1493
- renderSwapRefundReturnWarning(display)
1510
+ renderSwapSupportDetails(display, options)
1494
1511
  );
1495
1512
  }
1496
1513
  if (display.state === "deposit") {
@@ -1514,11 +1531,15 @@ function renderSwapDepositPanel(options) {
1514
1531
  {
1515
1532
  className: orClasses5.swapDepositLayout
1516
1533
  },
1517
- React8.createElement(SwapPayloadQRCode, {
1518
- payload: display.qrPayload,
1519
- encoder: options.encoder,
1520
- onError: options.onError
1521
- }),
1534
+ React8.createElement(
1535
+ "div",
1536
+ { className: orClasses5.swapQrFrame },
1537
+ React8.createElement(SwapPayloadQRCode, {
1538
+ payload: display.qrPayload,
1539
+ encoder: options.encoder,
1540
+ onError: options.onError
1541
+ })
1542
+ ),
1522
1543
  React8.createElement(
1523
1544
  "div",
1524
1545
  {
@@ -1554,9 +1575,10 @@ function renderSwapDepositPanel(options) {
1554
1575
  React8.createElement(
1555
1576
  "p",
1556
1577
  { className: orClasses5.swapWarning },
1557
- checkoutLabels4.supportReviewNeeded
1578
+ checkoutLabels4.supportReviewFacts
1558
1579
  ),
1559
- renderSwapSupportDetails(display, options),
1580
+ renderSwapAmountFacts(display),
1581
+ renderSwapSupportDetails(display, options, { open: true }),
1560
1582
  backButton
1561
1583
  );
1562
1584
  }
@@ -1610,26 +1632,45 @@ function renderSwapNetworkWarning(display) {
1610
1632
  )
1611
1633
  );
1612
1634
  }
1613
- function renderSwapRefundFacts(display, options) {
1635
+ function renderSwapAmountFacts(display) {
1614
1636
  const rows = [
1615
- ...display.depositReceivedAmount === void 0 ? [] : renderSwapCopyRow(
1616
- "Amount received",
1617
- `${display.depositReceivedAmount} ${display.assetLabel}`,
1618
- options
1619
- ),
1620
- ...display.depositReceivedAmount === void 0 ? [] : renderSwapCopyRow(
1621
- "Amount required",
1622
- `${display.depositAmount} ${display.assetLabel}`,
1623
- options
1624
- ),
1625
- ...display.refundAmount === void 0 ? [] : renderSwapCopyRow(
1626
- "Estimated refund",
1627
- `${display.refundAmount} ${display.assetLabel}`,
1628
- options
1629
- )
1637
+ ...display.depositReceivedAmount === void 0 ? [] : [
1638
+ ["Amount received", `${display.depositReceivedAmount} ${display.assetLabel}`],
1639
+ ["Amount required", `${display.depositAmount} ${display.assetLabel}`]
1640
+ ],
1641
+ ...display.refundAmount === void 0 ? [] : [["Estimated refund", `${display.refundAmount} ${display.assetLabel}`]]
1630
1642
  ];
1631
1643
  if (rows.length === 0) return null;
1632
- return React8.createElement("dl", { className: orClasses5.swapDetails }, rows);
1644
+ return React8.createElement(
1645
+ "dl",
1646
+ { className: orClasses5.swapFacts },
1647
+ rows.map(
1648
+ ([label, value]) => React8.createElement(
1649
+ "div",
1650
+ { key: label, className: orClasses5.swapFactsRow },
1651
+ React8.createElement("dt", { className: orClasses5.swapFactsLabel }, label),
1652
+ React8.createElement("dd", { className: orClasses5.swapFactsValue }, value)
1653
+ )
1654
+ )
1655
+ );
1656
+ }
1657
+ function renderAlertIcon(kind) {
1658
+ return React8.createElement(
1659
+ "svg",
1660
+ {
1661
+ xmlns: "http://www.w3.org/2000/svg",
1662
+ fill: "none",
1663
+ viewBox: "0 0 24 24",
1664
+ className: orClasses5.swapNetworkWarningIcon,
1665
+ "aria-hidden": "true"
1666
+ },
1667
+ React8.createElement("path", {
1668
+ strokeLinecap: "round",
1669
+ strokeLinejoin: "round",
1670
+ strokeWidth: 2,
1671
+ d: kind === "warning" ? "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" : "M17 3H7a2 2 0 00-2 2v16l7-3.5L19 21V5a2 2 0 00-2-2z"
1672
+ })
1673
+ );
1633
1674
  }
1634
1675
  function renderSwapFeeBreakdown(breakdown) {
1635
1676
  if (breakdown === void 0) return null;
@@ -1728,7 +1769,7 @@ function SwapCopyButton(props) {
1728
1769
  React8.createElement(ClipboardIcon)
1729
1770
  );
1730
1771
  }
1731
- function renderSwapSupportDetails(display, options) {
1772
+ function renderSwapSupportDetails(display, options, view = {}) {
1732
1773
  const rowOptions = { ...options, payInAsset: display.payInAsset };
1733
1774
  const rows = [
1734
1775
  ...display.depositTxId === void 0 ? [] : renderSwapCopyRow("Deposit transaction", display.depositTxId, rowOptions),
@@ -1740,7 +1781,8 @@ function renderSwapSupportDetails(display, options) {
1740
1781
  return React8.createElement(
1741
1782
  "details",
1742
1783
  {
1743
- className: orClasses5.swapSupport
1784
+ className: orClasses5.swapSupport,
1785
+ ...view.open === true ? { open: true } : {}
1744
1786
  },
1745
1787
  React8.createElement("summary", { className: orClasses5.swapSupportTitle }, "Payment details"),
1746
1788
  React8.createElement(
@@ -1750,13 +1792,57 @@ function renderSwapSupportDetails(display, options) {
1750
1792
  )
1751
1793
  );
1752
1794
  }
1753
- function renderSwapRefundReturnWarning(display) {
1795
+ function renderSwapRefundReturnWarning(display, options) {
1796
+ const url = display.resumable ? currentCheckoutUrl() : void 0;
1754
1797
  return React8.createElement(
1755
- "p",
1756
- {
1757
- className: orClasses5.swapWarning
1758
- },
1759
- display.refundReturnLabel
1798
+ "div",
1799
+ { className: orClasses5.swapRefundReturn },
1800
+ renderAlertIcon("bookmark"),
1801
+ React8.createElement(
1802
+ "div",
1803
+ { className: orClasses5.swapNetworkWarningContent },
1804
+ React8.createElement(
1805
+ "p",
1806
+ { className: orClasses5.swapRefundReturnTitle },
1807
+ checkoutLabels4.refundReturnTitle
1808
+ ),
1809
+ React8.createElement(
1810
+ "p",
1811
+ { className: orClasses5.swapRefundReturnBody },
1812
+ display.refundReturnLabel
1813
+ ),
1814
+ url === void 0 ? null : React8.createElement(
1815
+ "dl",
1816
+ { className: orClasses5.swapDetails },
1817
+ ...renderSwapCopyRow(checkoutLabels4.refundReturnUrlLabel, url, {
1818
+ ...options,
1819
+ selectable: true
1820
+ })
1821
+ )
1822
+ )
1823
+ );
1824
+ }
1825
+ function renderKeepOrderNote(options) {
1826
+ if (options.resumable !== true) return null;
1827
+ const reference = options.reference ?? "";
1828
+ const url = currentCheckoutUrl();
1829
+ if (reference.length === 0 && url === void 0) return null;
1830
+ const rowOptions = { ...options, selectable: true };
1831
+ return React8.createElement(
1832
+ "div",
1833
+ { className: orClasses5.keepOrder },
1834
+ React8.createElement(
1835
+ "p",
1836
+ { className: orClasses5.swapSectionTitle },
1837
+ checkoutLabels4.keepOrderTitle
1838
+ ),
1839
+ React8.createElement("p", { className: orClasses5.keepOrderBody }, checkoutLabels4.keepOrderBody),
1840
+ React8.createElement(
1841
+ "dl",
1842
+ { className: orClasses5.swapDetails },
1843
+ ...reference.length === 0 ? [] : renderSwapCopyRow(checkoutLabels4.keepOrderIdLabel, reference, rowOptions),
1844
+ ...url === void 0 ? [] : renderSwapCopyRow(checkoutLabels4.keepOrderUrlLabel, url, rowOptions)
1845
+ )
1760
1846
  );
1761
1847
  }
1762
1848
  var REFUND_ADDRESS_DRAFT_LIMIT = 8;
@@ -1799,10 +1885,30 @@ function SwapRefundForm(props) {
1799
1885
  void props.onRefund(props.attemptId, address, confirm).catch(props.onError).finally(() => setSubmitting(false));
1800
1886
  }
1801
1887
  },
1888
+ // The form says what it is and why it is here before it asks for anything:
1889
+ // a bare input under a red banner is a payer guessing what to type.
1890
+ React8.createElement(
1891
+ "p",
1892
+ { className: orClasses5.swapSectionTitle },
1893
+ checkoutLabels4.refundSectionTitle
1894
+ ),
1895
+ props.refundReason === void 0 ? null : React8.createElement(
1896
+ "p",
1897
+ { className: orClasses5.swapRefundReason },
1898
+ checkoutLabels4.refundReasonLabel.replace(
1899
+ "{reason}",
1900
+ props.refundReason.replace(/_/g, " ")
1901
+ )
1902
+ ),
1903
+ React8.createElement(
1904
+ "p",
1905
+ { className: orClasses5.swapRefundInstruction },
1906
+ checkoutLabels4.refundAddressOwnership.replace("{network}", props.networkLabel)
1907
+ ),
1802
1908
  props.submittedRefundAddress === void 0 ? null : React8.createElement(
1803
1909
  "p",
1804
1910
  {
1805
- className: orClasses5.swapWarning
1911
+ className: orClasses5.swapRefundInstruction
1806
1912
  },
1807
1913
  checkoutLabels4.confirmRefundTo.replace("{address}", props.submittedRefundAddress)
1808
1914
  ),
@@ -2007,6 +2113,18 @@ function PaymentWizard(props) {
2007
2113
  stickySwapInvoiceRef.current = void 0;
2008
2114
  }
2009
2115
  const activeSwapForAsset = selectedSwapAsset === null ? void 0 : currentSwapInvoice !== void 0 && currentSwapInvoice.swap?.pay_in_asset === selectedSwapAsset ? currentSwapInvoice : stickySwapInvoiceRef.current?.swap?.pay_in_asset === selectedSwapAsset ? stickySwapInvoiceRef.current : void 0;
2116
+ const resumeAdoptedRef = React9.useRef(false);
2117
+ React9.useEffect(() => {
2118
+ if (resumeAdoptedRef.current) return;
2119
+ if (selectedSwapAsset !== null) {
2120
+ resumeAdoptedRef.current = true;
2121
+ return;
2122
+ }
2123
+ const payInAsset = currentSwapInvoice?.swap?.pay_in_asset;
2124
+ if (payInAsset === void 0) return;
2125
+ resumeAdoptedRef.current = true;
2126
+ setSelectedSwapAsset(payInAsset);
2127
+ }, [currentSwapInvoice, selectedSwapAsset]);
2010
2128
  React9.useEffect(() => {
2011
2129
  if (selectedSwapAsset === null) return;
2012
2130
  if (props.prefix === void 0) return;
@@ -2018,6 +2136,18 @@ function PaymentWizard(props) {
2018
2136
  const selectedSwapOption = selectedSwapAsset === null ? void 0 : swapAssetOptions.find((option) => option.pay_in_asset === selectedSwapAsset) ?? session.swapQuotes[selectedSwapAsset];
2019
2137
  const selectedSwapQuote = selectedSwapAsset === null ? void 0 : session.swapQuotes[selectedSwapAsset];
2020
2138
  const selectedSwapLabel = selectedSwapOption?.label ?? "this coin";
2139
+ const activeSwapState = activeSwapForAsset === void 0 ? void 0 : createSwapDisplayModel2(activeSwapForAsset, {
2140
+ ...now === void 0 ? {} : { now },
2141
+ ...props.resumable === void 0 ? {} : { resumable: props.resumable }
2142
+ })?.state;
2143
+ const refundOwed = activeSwapState === "refund_required";
2144
+ const refundStage = activeSwapState?.startsWith("refund") ?? false;
2145
+ const keepOrderNote = renderKeepOrderNote({
2146
+ ...checkout?.reference === void 0 ? {} : { reference: checkout.reference },
2147
+ ...props.resumable === void 0 ? {} : { resumable: props.resumable },
2148
+ ...props.clipboard === void 0 ? {} : { clipboard: props.clipboard },
2149
+ ...props.onError === void 0 ? {} : { onError: props.onError }
2150
+ });
2021
2151
  if (selectedSwapAsset !== null) {
2022
2152
  return React9.createElement(
2023
2153
  "div",
@@ -2027,7 +2157,7 @@ function PaymentWizard(props) {
2027
2157
  React9.createElement(
2028
2158
  "div",
2029
2159
  { className: orClasses6.wizardBody },
2030
- renderWizardBackBreadcrumb(
2160
+ refundOwed ? null : renderWizardBackBreadcrumb(
2031
2161
  selectedSwapOption === void 0 ? selectedSwapLabel : `${selectedSwapOption.label} \xB7 ${selectedSwapOption.network_label}`,
2032
2162
  clearSwapFocus
2033
2163
  ),
@@ -2055,7 +2185,8 @@ function PaymentWizard(props) {
2055
2185
  void props.onRequestLightning?.();
2056
2186
  }
2057
2187
  }) : selectedSwapQuote !== void 0 && !selectedSwapQuote.available ? renderSwapUnavailable(selectedSwapQuote, checkout) : renderSwapPreparing(selectedSwapLabel)
2058
- )
2188
+ ),
2189
+ refundStage ? null : keepOrderNote
2059
2190
  )
2060
2191
  );
2061
2192
  }
@@ -2118,6 +2249,13 @@ function PaymentWizard(props) {
2118
2249
  onContinueSwap: selectSwapAsset,
2119
2250
  ...resolveAssetUrl === void 0 ? {} : { resolveAssetUrl }
2120
2251
  }) : null,
2252
+ // On the grid the note is a section of its own, under the tiles: there is no
2253
+ // body to put it in until a method is chosen.
2254
+ selection.selectedMethod === null && keepOrderNote !== null ? React9.createElement(
2255
+ "div",
2256
+ { key: "keep-order", className: orClasses6.wizardBody },
2257
+ keepOrderNote
2258
+ ) : null,
2121
2259
  selection.selectedMethod === null ? null : React9.createElement(
2122
2260
  "div",
2123
2261
  { className: orClasses6.wizardBody },
@@ -2246,7 +2384,8 @@ function PaymentWizard(props) {
2246
2384
  ) : null
2247
2385
  );
2248
2386
  })
2249
- )
2387
+ ),
2388
+ keepOrderNote
2250
2389
  ),
2251
2390
  activeTutorialProvider === void 0 || activeTutorial === null ? null : React9.createElement(ProviderTutorialModal, {
2252
2391
  key: "provider-tutorial",
@@ -2482,7 +2621,15 @@ function renderCompactPaymentMethodSelector(options) {
2482
2621
  React9.createElement(
2483
2622
  "span",
2484
2623
  { className: orClasses6.methodTitleWrap },
2485
- React9.createElement("span", { className: orClasses6.methodTitle }, method.title)
2624
+ React9.createElement("span", { className: orClasses6.methodTitle }, method.title),
2625
+ // The tile's own description. A grid of five names is a grid of
2626
+ // five questions; `paymentMethods` has carried the answer all
2627
+ // along and only the mobile layout was printing it.
2628
+ React9.createElement(
2629
+ "span",
2630
+ { className: orClasses6.methodTileDetail },
2631
+ method.detail
2632
+ )
2486
2633
  )
2487
2634
  );
2488
2635
  }
@@ -2492,7 +2639,6 @@ function renderCompactPaymentMethodSelector(options) {
2492
2639
  selected,
2493
2640
  multiNetwork,
2494
2641
  displayOption,
2495
- selectedOption,
2496
2642
  starting,
2497
2643
  disabled,
2498
2644
  accent,
@@ -2542,11 +2688,11 @@ function renderCompactPaymentMethodSelector(options) {
2542
2688
  "span",
2543
2689
  { className: orClasses6.methodTitleWrap },
2544
2690
  React9.createElement("span", { className: orClasses6.methodTitle }, group.label),
2545
- !disabled && multiNetwork ? React9.createElement(
2691
+ React9.createElement(
2546
2692
  "span",
2547
- { className: orClasses6.methodDetailMobile },
2548
- selected && selectedOption !== void 0 ? `${selectedOption.network_label} network` : checkoutLabels5.selectNetwork
2549
- ) : null
2693
+ { className: orClasses6.methodTileDetail },
2694
+ formatMethodNetworkDetail(group.options)
2695
+ )
2550
2696
  )
2551
2697
  ),
2552
2698
  disabled && limitMessage !== void 0 ? React9.createElement("span", { className: orClasses6.methodLimitHint }, limitMessage) : null,
@@ -2726,7 +2872,8 @@ function Checkout(props) {
2726
2872
  metadata: props.metadata,
2727
2873
  syncUrl: props.syncUrl,
2728
2874
  resumePathPrefix: props.resumePathPrefix,
2729
- routeReference: props.routeReference
2875
+ routeReference: props.routeReference,
2876
+ resumePaymentHash: props.resumePaymentHash
2730
2877
  });
2731
2878
  const { checkout } = props;
2732
2879
  if (checkout !== void 0) {
@@ -2769,7 +2916,8 @@ function CheckoutCreate(props) {
2769
2916
  classNames,
2770
2917
  syncUrl = false,
2771
2918
  resumePathPrefix = "/checkout",
2772
- routeReference
2919
+ routeReference,
2920
+ resumePaymentHash
2773
2921
  } = props;
2774
2922
  const [created, setCreated] = React10.useState({ status: "pending" });
2775
2923
  const [attempt, setAttempt] = React10.useState(0);
@@ -2810,7 +2958,15 @@ function CheckoutCreate(props) {
2810
2958
  prefix: resolvedPrefix,
2811
2959
  reference,
2812
2960
  ...createFetchRef.current === void 0 ? {} : { fetch: createFetchRef.current }
2813
- }).then((checkout) => {
2961
+ }).then(
2962
+ (checkout) => resumePaymentHash === void 0 ? checkout : resumeSwapAttempt({
2963
+ fetch: createFetchRef.current ?? globalThis.fetch,
2964
+ prefix: resolvedPrefix,
2965
+ reference,
2966
+ paymentHash: resumePaymentHash,
2967
+ snapshot: checkout
2968
+ })
2969
+ ).then((checkout) => {
2814
2970
  if (!cancelled) setCreated({ status: "ready", checkout });
2815
2971
  }).catch((error) => {
2816
2972
  if (cancelled) return;
@@ -2823,7 +2979,7 @@ function CheckoutCreate(props) {
2823
2979
  return () => {
2824
2980
  cancelled = true;
2825
2981
  };
2826
- }, [reference, resolvedPrefix, attempt]);
2982
+ }, [reference, resolvedPrefix, resumePaymentHash, attempt]);
2827
2983
  const onSwapStarted = React10.useCallback(
2828
2984
  (invoice) => {
2829
2985
  setCreated((current) => {
@@ -2908,6 +3064,9 @@ function CheckoutView(props) {
2908
3064
  syncUrl,
2909
3065
  resumePathPrefix: _resumePathPrefix,
2910
3066
  routeReference,
3067
+ // Consumed by CheckoutCreate before the view exists; destructured out here
3068
+ // so it never reaches the rendered <section> as an attribute.
3069
+ resumePaymentHash: _resumePaymentHash,
2911
3070
  resumable,
2912
3071
  onRequestLightning,
2913
3072
  onSwapStarted,