@odla-ai/chapter 0.55.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -294,7 +294,7 @@ function CheckoutSeatChoice(props) {
294
294
  try {
295
295
  await props.onChange(selected ? { recipientName: name, recipientEmail: email } : null);
296
296
  } catch (error2) {
297
- setError(error2 instanceof Error ? error2.message : "Could not update your total. Try again.");
297
+ setError(error2 instanceof Error ? error2.message : "Could not save your selection. Try again.");
298
298
  } finally {
299
299
  setSaving(false);
300
300
  }
@@ -311,7 +311,7 @@ function CheckoutSeatChoice(props) {
311
311
  ] }),
312
312
  selected ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
313
313
  /* @__PURE__ */ jsxs3("label", { children: [
314
- "Recipient name",
314
+ "Full name",
315
315
  /* @__PURE__ */ jsx3(
316
316
  "input",
317
317
  {
@@ -327,7 +327,7 @@ function CheckoutSeatChoice(props) {
327
327
  )
328
328
  ] }),
329
329
  /* @__PURE__ */ jsxs3("label", { children: [
330
- "Recipient email",
330
+ "Email",
331
331
  /* @__PURE__ */ jsx3(
332
332
  "input",
333
333
  {
@@ -342,9 +342,9 @@ function CheckoutSeatChoice(props) {
342
342
  }
343
343
  )
344
344
  ] }),
345
- /* @__PURE__ */ jsx3("p", { children: "This seat belongs to one named person and cannot be reassigned. They must accept and complete their own application and any required interview. It renews and ends with your membership. Contact the chapter if you need a refund." })
345
+ /* @__PURE__ */ jsx3("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
346
346
  ] }) : /* @__PURE__ */ jsx3("p", { children: "You can add someone from your member page after paying." }),
347
- dirty ? /* @__PURE__ */ jsx3("button", { type: "submit", disabled: saving, children: saving ? "Updating total\u2026" : "Update total" }) : null
347
+ dirty ? /* @__PURE__ */ jsx3("button", { type: "submit", disabled: saving, children: saving ? "Saving\u2026" : amount === 0 ? "Save member details" : "Update total" }) : null
348
348
  ] }),
349
349
  error ? /* @__PURE__ */ jsx3("p", { role: "alert", children: error }) : null
350
350
  ] }) });
@@ -357,7 +357,7 @@ function MembershipPaymentStep(props) {
357
357
  const copy = props.copy ?? inherited.join.payment;
358
358
  const [quote, setQuote] = useState4(null);
359
359
  const [locked, setLocked] = useState4(false), [editing, setEditing] = useState4(Boolean(props.initialNamedSeat));
360
- const [seatTerms, setSeatTerms] = useState4(false), [prefillConsumed, setPrefillConsumed] = useState4(false);
360
+ const [prefillConsumed, setPrefillConsumed] = useState4(false);
361
361
  const [error, setError] = useState4(false);
362
362
  const [revision, setRevision] = useState4(0);
363
363
  useEffect(() => {
@@ -372,7 +372,6 @@ function MembershipPaymentStep(props) {
372
372
  if (live) {
373
373
  setQuote(value);
374
374
  setLocked(Boolean(value.checkoutStarted));
375
- setSeatTerms(Boolean(value.checkoutStarted));
376
375
  setEditing(Boolean(props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer));
377
376
  }
378
377
  }).catch(() => {
@@ -419,13 +418,12 @@ function MembershipPaymentStep(props) {
419
418
  });
420
419
  if (!response.ok) {
421
420
  if (response.status === 409) refresh();
422
- throw new Error(response.status === 400 ? "Enter a different recipient's name and valid email." : "Could not update your total. Reload payment terms and try again.");
421
+ throw new Error(response.status === 400 ? "Enter a different recipient's name and valid email." : "Could not save your selection. Reload payment terms and try again.");
423
422
  }
424
423
  const value = await response.json();
425
424
  if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest)) throw new Error(copy.setupFailed);
426
425
  setQuote(value);
427
426
  setEditing(false);
428
- setSeatTerms(false);
429
427
  setPrefillConsumed(true);
430
428
  };
431
429
  return /* @__PURE__ */ jsxs4(Fragment3, { children: [
@@ -509,29 +507,18 @@ function MembershipPaymentStep(props) {
509
507
  ] }) : null,
510
508
  quote.trustCopy ? /* @__PURE__ */ jsx4("p", { className: "pay-trust", children: quote.trustCopy }) : null
511
509
  ] }),
512
- quote.namedSeat && !editing ? /* @__PURE__ */ jsxs4("label", { className: "journey-consent", children: [
513
- /* @__PURE__ */ jsx4(
514
- "input",
515
- {
516
- type: "checkbox",
517
- checked: seatTerms,
518
- disabled: locked,
519
- onChange: (event) => setSeatTerms(event.currentTarget.checked)
520
- }
521
- ),
522
- "I agree to the additional-member terms and renewal with my membership."
523
- ] }) : null,
524
- !editing && (!quote.namedSeat || seatTerms) ? /* @__PURE__ */ jsx4(
510
+ !editing ? /* @__PURE__ */ jsx4(
525
511
  PaymentStep,
526
512
  {
527
513
  ...props,
528
514
  refundPolicyText: quote.refundPolicyText,
529
515
  merchantDisclosureText: quote.merchantDisclosureText,
516
+ copy: { ...copy, consent: quote.namedSeat ? "I agree to the refund policy, renewal terms, and additional-member terms above." : "I agree to the refund policy and renewal terms above." },
530
517
  renderPriceLines: void 0,
531
518
  startCheckout
532
519
  },
533
520
  quote.digest
534
- ) : editing ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Update the total to continue to payment." }) : null
521
+ ) : /* @__PURE__ */ jsx4("p", { role: "status", children: "Save your member selection to continue to payment." })
535
522
  ] });
536
523
  }
537
524
 
@@ -1179,7 +1166,7 @@ function MembersArea(props) {
1179
1166
  }
1180
1167
 
1181
1168
  // src/ui/join.tsx
1182
- import { useEffect as useEffect10, useRef as useRef3, useState as useState17 } from "preact/hooks";
1169
+ import { useEffect as useEffect11, useRef as useRef3, useState as useState18 } from "preact/hooks";
1183
1170
 
1184
1171
  // src/ui/join-booking.tsx
1185
1172
  import { useEffect as useEffect7, useState as useState11 } from "preact/hooks";
@@ -1318,7 +1305,7 @@ function useTierSelection(tiers, initialTierId) {
1318
1305
  return tiers.length === 1 ? tiers[0].id : null;
1319
1306
  });
1320
1307
  return {
1321
- tiers,
1308
+ tiers: [...tiers].sort((a, b) => Number(b.id === selectedTierId) - Number(a.id === selectedTierId)),
1322
1309
  selected: tiers.find((tier) => tier.id === selectedTierId) ?? null,
1323
1310
  selectedTierId,
1324
1311
  selectTier: (tierId) => {
@@ -1622,10 +1609,93 @@ function useJoinPending(state, loadResume, setState) {
1622
1609
  }, [state, loadResume]);
1623
1610
  }
1624
1611
 
1625
- // src/ui/join.tsx
1612
+ // src/ui/payment-receipt.tsx
1613
+ import { useEffect as useEffect10, useState as useState17 } from "preact/hooks";
1626
1614
  import { Fragment as Fragment10, jsx as jsx22, jsxs as jsxs22 } from "preact/jsx-runtime";
1615
+ function PaymentReceiptCard({ applicationId }) {
1616
+ const [receipt, setReceipt] = useState17(null);
1617
+ const [error, setError] = useState17("");
1618
+ const [revision, setRevision] = useState17(0);
1619
+ const [emailState, setEmailState] = useState17("idle");
1620
+ const [previewEmail, setPreviewEmail] = useState17(false);
1621
+ const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
1622
+ useEffect10(() => {
1623
+ let live = true, timer;
1624
+ setReceipt(null);
1625
+ setError("");
1626
+ setEmailState("idle");
1627
+ const read = async () => {
1628
+ try {
1629
+ const response = await fetch(endpoint, { cache: "no-store" });
1630
+ if (!live || response.status === 404) return;
1631
+ if (response.status === 202) {
1632
+ timer = setTimeout(() => void read(), 2e3);
1633
+ return;
1634
+ }
1635
+ if (!response.ok) throw new Error();
1636
+ const data = await response.json();
1637
+ if (live) setReceipt(data.receipt);
1638
+ } catch {
1639
+ if (live) setError("Your receipt is temporarily unavailable.");
1640
+ }
1641
+ };
1642
+ void read();
1643
+ return () => {
1644
+ live = false;
1645
+ if (timer) clearTimeout(timer);
1646
+ };
1647
+ }, [endpoint, revision]);
1648
+ if (!receipt) return error ? /* @__PURE__ */ jsxs22("section", { "aria-label": "Payment receipt", children: [
1649
+ /* @__PURE__ */ jsx22("p", { role: "status", children: error }),
1650
+ /* @__PURE__ */ jsx22("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
1651
+ ] }) : null;
1652
+ const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
1653
+ const email = async () => {
1654
+ setEmailState("sending");
1655
+ setError("");
1656
+ try {
1657
+ const response = await fetch(endpoint, { method: "POST" });
1658
+ if (!response.ok) throw new Error();
1659
+ const result = await response.json();
1660
+ setPreviewEmail(result.preview === true);
1661
+ setEmailState("sent");
1662
+ } catch {
1663
+ setEmailState("idle");
1664
+ setError("We could not confirm email delivery. You can print or save your receipt.");
1665
+ }
1666
+ };
1667
+ return /* @__PURE__ */ jsxs22("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
1668
+ /* @__PURE__ */ jsx22("h2", { children: "Payment received" }),
1669
+ /* @__PURE__ */ jsx22("p", { children: receipt.tierName }),
1670
+ /* @__PURE__ */ jsxs22("dl", { className: "journey-summary", children: [
1671
+ /* @__PURE__ */ jsx22("dt", { children: "Membership" }),
1672
+ /* @__PURE__ */ jsx22("dd", { children: money(receipt.membershipCents) }),
1673
+ receipt.namedSeat ? /* @__PURE__ */ jsxs22(Fragment10, { children: [
1674
+ /* @__PURE__ */ jsxs22("dt", { children: [
1675
+ "Additional member \u2014 ",
1676
+ receipt.namedSeat.recipientName
1677
+ ] }),
1678
+ /* @__PURE__ */ jsxs22("dd", { children: [
1679
+ receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
1680
+ money(receipt.namedSeat.amountCents)
1681
+ ] })
1682
+ ] }) : null,
1683
+ /* @__PURE__ */ jsx22("dt", { children: "Total paid" }),
1684
+ /* @__PURE__ */ jsx22("dd", { children: money(receipt.totalCents) })
1685
+ ] }),
1686
+ /* @__PURE__ */ jsxs22("div", { className: "journey-actions", children: [
1687
+ /* @__PURE__ */ jsx22("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
1688
+ /* @__PURE__ */ jsx22("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
1689
+ ] }),
1690
+ emailState === "sent" ? /* @__PURE__ */ jsx22("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
1691
+ error ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error }) : null
1692
+ ] });
1693
+ }
1694
+
1695
+ // src/ui/join.tsx
1696
+ import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
1627
1697
  function JoinIsland(props) {
1628
- return /* @__PURE__ */ jsx22(JourneyFrame, { children: /* @__PURE__ */ jsx22(JoinFlow, { ...props }) });
1698
+ return /* @__PURE__ */ jsx23(JourneyFrame, { children: /* @__PURE__ */ jsx23(JoinFlow, { ...props }) });
1629
1699
  }
1630
1700
  function JoinFlow(props) {
1631
1701
  const inheritedCopy = useChapterCopy();
@@ -1646,10 +1716,10 @@ function JoinFlow(props) {
1646
1716
  const invitation = invitationState.invitation;
1647
1717
  const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
1648
1718
  const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
1649
- const [state, setState] = useState17(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1650
- const [error, setError] = useState17(null);
1651
- const [submitting, setSubmitting] = useState17(false);
1652
- const [giftOfferId, setGiftOfferId] = useState17(props.initialGiftOfferId ?? null);
1719
+ const [state, setState] = useState18(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1720
+ const [error, setError] = useState18(null);
1721
+ const [submitting, setSubmitting] = useState18(false);
1722
+ const [giftOfferId, setGiftOfferId] = useState18(props.initialGiftOfferId ?? null);
1653
1723
  const simulatedPayment = props.simulation ? props.simulation.payment ?? {
1654
1724
  lineItems: {
1655
1725
  standardCents: selectedTier?.priceCents ?? 0,
@@ -1659,7 +1729,7 @@ function JoinFlow(props) {
1659
1729
  } : void 0;
1660
1730
  const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
1661
1731
  const submissionId = useRef3(null);
1662
- useEffect10(() => {
1732
+ useEffect11(() => {
1663
1733
  if (props.simulation) return;
1664
1734
  const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
1665
1735
  if (typeof window === "undefined") return Promise.resolve(null);
@@ -1728,13 +1798,13 @@ function JoinFlow(props) {
1728
1798
  setSubmitting(false);
1729
1799
  }
1730
1800
  };
1731
- if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs22("section", { className: "card", "aria-live": "polite", children: [
1732
- /* @__PURE__ */ jsx22("h2", { children: seatCopy.title }),
1733
- /* @__PURE__ */ jsx22("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
1734
- invitationState.error ? /* @__PURE__ */ jsx22("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1801
+ if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs23("section", { className: "card", "aria-live": "polite", children: [
1802
+ /* @__PURE__ */ jsx23("h2", { children: seatCopy.title }),
1803
+ /* @__PURE__ */ jsx23("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
1804
+ invitationState.error ? /* @__PURE__ */ jsx23("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1735
1805
  ] });
1736
- const header = /* @__PURE__ */ jsxs22(Fragment10, { children: [
1737
- invitation ? /* @__PURE__ */ jsx22(
1806
+ const header = /* @__PURE__ */ jsxs23(Fragment11, { children: [
1807
+ invitation ? /* @__PURE__ */ jsx23(
1738
1808
  JoinInvitationNotice,
1739
1809
  {
1740
1810
  invitation,
@@ -1746,48 +1816,49 @@ function JoinFlow(props) {
1746
1816
  state,
1747
1817
  ...invitation ? { invitation } : {},
1748
1818
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
1749
- })
1819
+ }),
1820
+ !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx23(PaymentReceiptCard, { applicationId: state.applicationId }) : null
1750
1821
  ] });
1751
1822
  if (state.step === "closed") {
1752
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1823
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1753
1824
  header,
1754
- /* @__PURE__ */ jsxs22("section", { className: "card", "aria-label": "Application closed", children: [
1755
- /* @__PURE__ */ jsx22("h2", { children: "This application is closed" }),
1756
- /* @__PURE__ */ jsx22("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
1757
- /* @__PURE__ */ jsx22("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1825
+ /* @__PURE__ */ jsxs23("section", { className: "card", "aria-label": "Application closed", children: [
1826
+ /* @__PURE__ */ jsx23("h2", { children: "This application is closed" }),
1827
+ /* @__PURE__ */ jsx23("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
1828
+ /* @__PURE__ */ jsx23("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1758
1829
  ] })
1759
1830
  ] });
1760
1831
  }
1761
1832
  if (state.step === "done") {
1762
- const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs22("div", { className: "join-done card", children: [
1763
- /* @__PURE__ */ jsx22("div", { className: "card-label", children: copy.done.label }),
1764
- /* @__PURE__ */ jsx22("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1765
- /* @__PURE__ */ jsx22("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1766
- /* @__PURE__ */ jsx22("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1833
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs23("div", { className: "join-done card", children: [
1834
+ /* @__PURE__ */ jsx23("div", { className: "card-label", children: copy.done.label }),
1835
+ /* @__PURE__ */ jsx23("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1836
+ /* @__PURE__ */ jsx23("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1837
+ /* @__PURE__ */ jsx23("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1767
1838
  ] });
1768
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1839
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1769
1840
  header,
1770
1841
  body
1771
1842
  ] });
1772
1843
  }
1773
1844
  if (state.step === "accepted") {
1774
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx22(JoinAccepted, { copy, membersHref });
1775
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1845
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx23(JoinAccepted, { copy, membersHref });
1846
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1776
1847
  header,
1777
1848
  body
1778
1849
  ] });
1779
1850
  }
1780
1851
  if (state.step === "gift") {
1781
- const body = renderGift?.(state) ?? /* @__PURE__ */ jsx22(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1782
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1852
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx23(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1853
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1783
1854
  header,
1784
1855
  body
1785
1856
  ] });
1786
1857
  }
1787
1858
  if (state.step === "booking") {
1788
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1859
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1789
1860
  header,
1790
- /* @__PURE__ */ jsx22(
1861
+ /* @__PURE__ */ jsx23(
1791
1862
  JoinBooking,
1792
1863
  {
1793
1864
  applicationId: state.applicationId,
@@ -1802,9 +1873,9 @@ function JoinFlow(props) {
1802
1873
  }
1803
1874
  if (state.step === "payment") {
1804
1875
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
1805
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1876
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1806
1877
  header,
1807
- /* @__PURE__ */ jsx22(
1878
+ /* @__PURE__ */ jsx23(
1808
1879
  JoinNamedSeat,
1809
1880
  {
1810
1881
  api: props.namedSeatClaimApi,
@@ -1817,9 +1888,9 @@ function JoinFlow(props) {
1817
1888
  ] });
1818
1889
  }
1819
1890
  const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
1820
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1891
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1821
1892
  header,
1822
- props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx22(
1893
+ props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx23(
1823
1894
  JoinGiftClaim,
1824
1895
  {
1825
1896
  api: props.giftClaimApi,
@@ -1830,7 +1901,7 @@ function JoinFlow(props) {
1830
1901
  onError: () => setError(copy.form.unexpectedFailure)
1831
1902
  }
1832
1903
  ) : null,
1833
- /* @__PURE__ */ jsx22(
1904
+ /* @__PURE__ */ jsx23(
1834
1905
  Payment,
1835
1906
  {
1836
1907
  applicationId: state.applicationId,
@@ -1860,9 +1931,9 @@ function JoinFlow(props) {
1860
1931
  }
1861
1932
  if (state.step === "paymentPending") {
1862
1933
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
1863
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1934
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1864
1935
  header,
1865
- /* @__PURE__ */ jsx22(
1936
+ /* @__PURE__ */ jsx23(
1866
1937
  JoinNamedSeat,
1867
1938
  {
1868
1939
  api: props.namedSeatClaimApi,
@@ -1874,14 +1945,14 @@ function JoinFlow(props) {
1874
1945
  )
1875
1946
  ] });
1876
1947
  }
1877
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1948
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1878
1949
  header,
1879
- /* @__PURE__ */ jsx22("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1950
+ /* @__PURE__ */ jsx23("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1880
1951
  ] });
1881
1952
  }
1882
- return /* @__PURE__ */ jsxs22(Fragment10, { children: [
1953
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1883
1954
  header,
1884
- /* @__PURE__ */ jsx22(
1955
+ /* @__PURE__ */ jsx23(
1885
1956
  JoinApplicationForm,
1886
1957
  {
1887
1958
  props,
@@ -2071,7 +2142,7 @@ function membershipPageDocument(input, options = {}) {
2071
2142
  }
2072
2143
 
2073
2144
  // src/ui/membership-cards.tsx
2074
- import { jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
2145
+ import { jsx as jsx24, jsxs as jsxs24 } from "preact/jsx-runtime";
2075
2146
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
2076
2147
  "--ui-membership-grid-gap": "1.4rem",
2077
2148
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -2140,67 +2211,67 @@ function membershipApplicationHref(applicationPath, tierId) {
2140
2211
  }
2141
2212
  function TierAction(props) {
2142
2213
  if (props.mode === "select") {
2143
- return /* @__PURE__ */ jsxs23("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2214
+ return /* @__PURE__ */ jsxs24("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2144
2215
  props.label,
2145
- /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", children: "\u2192" })
2216
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2146
2217
  ] });
2147
2218
  }
2148
2219
  if (props.mode === "preview") {
2149
- return /* @__PURE__ */ jsxs23("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2220
+ return /* @__PURE__ */ jsxs24("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2150
2221
  props.label,
2151
- /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", children: "\u2192" })
2222
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2152
2223
  ] });
2153
2224
  }
2154
- return /* @__PURE__ */ jsxs23("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2225
+ return /* @__PURE__ */ jsxs24("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2155
2226
  props.label,
2156
- /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", children: "\u2192" })
2227
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2157
2228
  ] });
2158
2229
  }
2159
2230
  function TierCard(props) {
2160
2231
  const { tier, presentation } = props;
2161
2232
  const summary = presentation.summaryMarkdown ?? tier.blurb;
2162
2233
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
2163
- return /* @__PURE__ */ jsxs23("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2164
- presentation.badge ? /* @__PURE__ */ jsx23("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2165
- /* @__PURE__ */ jsx23("h3", { className: "chapter-membership-name", children: tier.name }),
2166
- /* @__PURE__ */ jsxs23("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2167
- presentation.capacity ? /* @__PURE__ */ jsxs23("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2168
- /* @__PURE__ */ jsx23("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2169
- /* @__PURE__ */ jsx23("small", { children: presentation.capacity.label ?? "available" })
2234
+ return /* @__PURE__ */ jsxs24("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2235
+ presentation.badge ? /* @__PURE__ */ jsx24("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2236
+ /* @__PURE__ */ jsx24("h3", { className: "chapter-membership-name", children: tier.name }),
2237
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2238
+ presentation.capacity ? /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2239
+ /* @__PURE__ */ jsx24("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2240
+ /* @__PURE__ */ jsx24("small", { children: presentation.capacity.label ?? "available" })
2170
2241
  ] }) : null,
2171
- /* @__PURE__ */ jsxs23("div", { className: "chapter-membership-price-stack", children: [
2172
- presentation.priceEyebrow ? /* @__PURE__ */ jsx23("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx23("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2173
- /* @__PURE__ */ jsxs23("div", { className: "chapter-membership-price-row", children: [
2174
- tier.founding ? /* @__PURE__ */ jsx23("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx23("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2175
- /* @__PURE__ */ jsx23("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2176
- !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx23("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2242
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-price-stack", children: [
2243
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2244
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-price-row", children: [
2245
+ tier.founding ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2246
+ /* @__PURE__ */ jsx24("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2247
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2177
2248
  ] })
2178
2249
  ] })
2179
2250
  ] }),
2180
- presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx23(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2181
- summary ? /* @__PURE__ */ jsx23(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2182
- presentation.benefits?.length ? /* @__PURE__ */ jsx23("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs23("li", { children: [
2183
- /* @__PURE__ */ jsx23("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2184
- /* @__PURE__ */ jsx23(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2251
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2252
+ summary ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2253
+ presentation.benefits?.length ? /* @__PURE__ */ jsx24("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs24("li", { children: [
2254
+ /* @__PURE__ */ jsx24("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2255
+ /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2185
2256
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
2186
- presentation.callout ? /* @__PURE__ */ jsxs23("aside", { className: "chapter-membership-callout", children: [
2187
- presentation.callout.label ? /* @__PURE__ */ jsx23("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2188
- /* @__PURE__ */ jsx23(Markdown2, { source: presentation.callout.bodyMarkdown })
2257
+ presentation.callout ? /* @__PURE__ */ jsxs24("aside", { className: "chapter-membership-callout", children: [
2258
+ presentation.callout.label ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2259
+ /* @__PURE__ */ jsx24(Markdown2, { source: presentation.callout.bodyMarkdown })
2189
2260
  ] }) : null,
2190
- /* @__PURE__ */ jsx23(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2261
+ /* @__PURE__ */ jsx24(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2191
2262
  ] });
2192
2263
  }
2193
2264
  function MembershipCards(props) {
2194
2265
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
2195
2266
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
2196
2267
  const mode = props.mode ?? "link";
2197
- return /* @__PURE__ */ jsxs23("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2198
- /* @__PURE__ */ jsx23("style", { children: MEMBERSHIP_CARDS_CSS }),
2199
- /* @__PURE__ */ jsx23("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2268
+ return /* @__PURE__ */ jsxs24("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2269
+ /* @__PURE__ */ jsx24("style", { children: MEMBERSHIP_CARDS_CSS }),
2270
+ /* @__PURE__ */ jsx24("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2200
2271
  const tier = byId.get(presentation.tierId);
2201
- return /* @__PURE__ */ jsx23(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2272
+ return /* @__PURE__ */ jsx24(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2202
2273
  }) }),
2203
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx23(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2274
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2204
2275
  ] });
2205
2276
  }
2206
2277
 
@@ -2236,4 +2307,4 @@ export {
2236
2307
  membershipApplicationHref,
2237
2308
  MembershipCards
2238
2309
  };
2239
- //# sourceMappingURL=chunk-VEOGTSVX.js.map
2310
+ //# sourceMappingURL=chunk-IQZWCG42.js.map