@riverbankcms/sdk 0.94.0 → 0.95.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.
Files changed (99) hide show
  1. package/README.md +3 -0
  2. package/dist/{PreviewEditorSidebar-D3PAF7NW.mjs → PreviewEditorSidebar-6FQYKOSB.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-G5JVJEIJ.mjs → PreviewEditorUI-NPO2XMFB.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-PBEFH5AL.mjs +8 -0
  5. package/dist/_dts/api/src/bookingOperations.d.ts +7 -0
  6. package/dist/_dts/api/src/bookingRecords.d.ts +3 -0
  7. package/dist/_dts/api/src/cache-tags.d.ts +4 -0
  8. package/dist/_dts/api/src/contentRuntime.d.ts +14 -0
  9. package/dist/_dts/api/src/endpoints.d.ts +8 -0
  10. package/dist/_dts/api/src/event-presentation.d.ts +15 -0
  11. package/dist/_dts/api/src/index.d.ts +1 -1
  12. package/dist/_dts/api/src/public/endpoints.d.ts +1 -1
  13. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +17 -4
  14. package/dist/_dts/api/src/shared-contracts.d.ts +19 -9
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
  16. package/dist/_dts/blocks/src/portal/types.d.ts +7 -0
  17. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  18. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +21 -6
  19. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +5 -3
  20. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +5 -1
  21. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +2 -2
  22. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +9 -6
  23. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.d.ts +36 -0
  24. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +7 -1
  25. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +2 -2
  26. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -3
  27. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +19 -4
  28. package/dist/_dts/content-model/src/entry-slots/types.d.ts +6 -0
  29. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +163 -2
  30. package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +7 -0
  31. package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +29 -1
  32. package/dist/_dts/sdk/src/client/types.d.ts +7 -2
  33. package/dist/_dts/sdk/src/next/middleware.d.ts +1 -0
  34. package/dist/_dts/sdk/src/next/redirect-destination.d.ts +3 -0
  35. package/dist/_dts/sdk/src/next/route-outcome-proxy.d.ts +22 -0
  36. package/dist/_dts/sdk/src/public-api/contracts.d.ts +20 -1
  37. package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
  38. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +9 -1
  39. package/dist/_dts/sdk/src/version.d.ts +1 -1
  40. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  41. package/dist/{chunk-XIK2HYI3.mjs → chunk-4A6NWO3X.mjs} +7 -7
  42. package/dist/{chunk-NT76QGIJ.mjs → chunk-7ED5UNHL.mjs} +14 -0
  43. package/dist/{chunk-AQ6RT6LZ.mjs → chunk-K2SJTZMX.mjs} +2 -2
  44. package/dist/{chunk-A63UXN3P.mjs → chunk-PJPFTVZG.mjs} +2 -2
  45. package/dist/{chunk-AJZGT6YG.mjs → chunk-VTPPVAOL.mjs} +1 -1
  46. package/dist/{chunk-PCNCETBI.mjs → chunk-VZBSD4AJ.mjs} +449 -183
  47. package/dist/cli/index.mjs +176 -73
  48. package/dist/client/{accordion-RNQIPG55.mjs → accordion-LGO4IO5U.mjs} +1 -1
  49. package/dist/client/{bookingForm-HYEEVRLP.mjs → bookingForm-MWLS4LGU.mjs} +3 -3
  50. package/dist/client/bookings.mjs +211 -105
  51. package/dist/client/{carousel-W7DQ3YPU.mjs → carousel-6AHNP5HA.mjs} +1 -1
  52. package/dist/client/{cart-PXJ3SXXO.mjs → cart-CIXGYAZB.mjs} +4 -4
  53. package/dist/client/{checkout-X3JYSOXI.mjs → checkout-OTX6O3DN.mjs} +4 -4
  54. package/dist/client/{chunk-Q47XGAGS.mjs → chunk-AVBQSUIS.mjs} +1 -1
  55. package/dist/client/{chunk-WERRJXNJ.mjs → chunk-HOP7MKAZ.mjs} +1 -1
  56. package/dist/client/{chunk-IXDSXF2D.mjs → chunk-INRIT6DP.mjs} +353 -187
  57. package/dist/client/{chunk-DUOHLWLF.mjs → chunk-MYCXAKWP.mjs} +2 -2
  58. package/dist/client/{chunk-J6TMMMXW.mjs → chunk-R3NQTBWE.mjs} +1 -1
  59. package/dist/client/{chunk-YYVGSYBO.mjs → chunk-TREIML53.mjs} +3 -3
  60. package/dist/client/{chunk-6SYGVVWA.mjs → chunk-V67AT7ZW.mjs} +3 -0
  61. package/dist/client/{chunk-PICR3NTQ.mjs → chunk-Y2PMKCXO.mjs} +1 -1
  62. package/dist/client/client.mjs +503 -183
  63. package/dist/client/{courseRegistration-QZ67PVHO.mjs → courseRegistration-2LU6C3JL.mjs} +3 -3
  64. package/dist/client/{eventCalendar-V3BDHQNT.mjs → eventCalendar-OKUSISBZ.mjs} +6 -6
  65. package/dist/client/{eventCombined-XYFRN2RG.mjs → eventCombined-CMF6CD4S.mjs} +6 -6
  66. package/dist/client/{eventDetails-TFE5TWKV.mjs → eventDetails-XYWH7WXI.mjs} +6 -6
  67. package/dist/client/{eventListing-IQ6AGWZ6.mjs → eventListing-EK5DJTAH.mjs} +6 -6
  68. package/dist/client/{eventRegistration-WGJVFKQJ.mjs → eventRegistration-XDOSICV6.mjs} +6 -6
  69. package/dist/client/{form-6UZY6RUA.mjs → form-J6GOHKYG.mjs} +1 -1
  70. package/dist/client/{headerSection-RSFXY6V3.mjs → headerSection-C5SYJTRW.mjs} +2 -2
  71. package/dist/client/hooks.mjs +14 -0
  72. package/dist/client/{locationMap-24FH67I4.mjs → locationMap-QSQIFVVT.mjs} +2 -2
  73. package/dist/client/{newsletterForm-QVL3MLTN.mjs → newsletterForm-47VXJRWK.mjs} +1 -1
  74. package/dist/client/{productDetail-ZDYN3G4T.mjs → productDetail-5U6ISCC2.mjs} +4 -4
  75. package/dist/client/{productList-4BMJLQHZ.mjs → productList-XDZUMR3P.mjs} +4 -4
  76. package/dist/client/rendering/client.mjs +362 -182
  77. package/dist/client/rendering/islands.mjs +18 -18
  78. package/dist/client/rendering.mjs +489 -182
  79. package/dist/client/{shop-U5C634FF.mjs → shop-ZSZKIY3R.mjs} +4 -4
  80. package/dist/preview-next/before-render.mjs +14 -0
  81. package/dist/preview-next/client/runtime.mjs +5 -5
  82. package/dist/preview-next/middleware.mjs +14 -0
  83. package/dist/{sdk-runtime-VGV46WVB.mjs → sdk-runtime-PHNM7MRD.mjs} +6 -6
  84. package/dist/server/components.mjs +111 -0
  85. package/dist/server/config-validation.mjs +14 -0
  86. package/dist/server/config.mjs +14 -0
  87. package/dist/server/data.mjs +14 -0
  88. package/dist/server/index.mjs +44 -1
  89. package/dist/server/next/middleware.mjs +120 -0
  90. package/dist/server/next.mjs +225 -2
  91. package/dist/server/prebuild.mjs +1 -1
  92. package/dist/server/rendering/server.mjs +111 -0
  93. package/dist/server/rendering.mjs +127 -0
  94. package/dist/server/routing.mjs +14 -0
  95. package/dist/server/server.mjs +60 -1
  96. package/dist/server/theme-bridge.mjs +97 -0
  97. package/dist/styles/index.css +95 -0
  98. package/package.json +5 -1
  99. package/dist/SdkPreviewModeRuntime-NHTLRNQD.mjs +0 -8
@@ -28155,6 +28155,9 @@ function resolveDiscountContext(input) {
28155
28155
  if (!input.eventRequiresPayment) {
28156
28156
  return null;
28157
28157
  }
28158
+ if (input.ticketsCount <= 0) {
28159
+ return null;
28160
+ }
28158
28161
  if (selection?.method && selection.method !== "stripe") {
28159
28162
  return null;
28160
28163
  }
@@ -43490,6 +43493,7 @@ function transformEligibilityResponse(response) {
43490
43493
  requiresPayment: eligibility.requiresPayment,
43491
43494
  pricingMode: eligibility.pricingMode,
43492
43495
  selectedTicketTypeId: eligibility.selectedTicketTypeId ?? null,
43496
+ ticketLines: eligibility.ticketLines ?? [],
43493
43497
  ticketTypes: eligibility.ticketTypes ?? [],
43494
43498
  isFull: eligibility.isFull,
43495
43499
  waitlistEnabled: eligibility.waitlistEnabled,
@@ -43557,6 +43561,77 @@ var init_utils5 = __esm({
43557
43561
  }
43558
43562
  });
43559
43563
 
43564
+ // ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
43565
+ function normalizeTicketSelectionLines(lines) {
43566
+ const quantitiesByTicketType = /* @__PURE__ */ new Map();
43567
+ for (const line of lines) {
43568
+ const quantity = Math.floor(line.quantity);
43569
+ if (quantity <= 0) continue;
43570
+ const key = line.ticketTypeId ?? null;
43571
+ quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
43572
+ }
43573
+ return [...quantitiesByTicketType.entries()].map(([ticketTypeId, quantity]) => ({
43574
+ ticketTypeId,
43575
+ quantity
43576
+ }));
43577
+ }
43578
+ function getTicketSelectionTotal(lines) {
43579
+ return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
43580
+ }
43581
+ function getTicketLineQuantity(lines, ticketTypeId) {
43582
+ return normalizeTicketSelectionLines(lines).find((line) => line.ticketTypeId === ticketTypeId)?.quantity ?? 0;
43583
+ }
43584
+ function getSingleSelectedTicketTypeId(lines) {
43585
+ const normalized = normalizeTicketSelectionLines(lines);
43586
+ return normalized.length === 1 ? normalized[0]?.ticketTypeId ?? null : null;
43587
+ }
43588
+ function setTicketLineQuantity(input) {
43589
+ const nextQuantity = Math.max(0, Math.floor(input.quantity));
43590
+ const normalized = normalizeTicketSelectionLines(input.lines).filter((line) => line.ticketTypeId !== input.ticketTypeId);
43591
+ if (nextQuantity <= 0) {
43592
+ return normalized;
43593
+ }
43594
+ return [
43595
+ ...normalized,
43596
+ {
43597
+ ticketTypeId: input.ticketTypeId,
43598
+ quantity: nextQuantity
43599
+ }
43600
+ ];
43601
+ }
43602
+ function getTicketTypeLineMax(input) {
43603
+ const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
43604
+ const maxByBlock = input.maxTickets - otherSelectedQuantity;
43605
+ const maxByEvent = input.availableSpots == null ? input.maxTickets : input.availableSpots - otherSelectedQuantity;
43606
+ const maxByTicketType = input.ticketTypeRemainingCapacity ?? input.maxTickets;
43607
+ return Math.max(0, Math.min(maxByBlock, maxByEvent, maxByTicketType));
43608
+ }
43609
+ function calculateTicketSelectionSubtotal(input) {
43610
+ return normalizeTicketSelectionLines(input.lines).reduce((subtotal, line) => {
43611
+ const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
43612
+ const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
43613
+ return subtotal + Math.max(0, unitPriceCents) * line.quantity;
43614
+ }, 0);
43615
+ }
43616
+ function buildTicketSelectionSummaryLines(input) {
43617
+ return normalizeTicketSelectionLines(input.lines).map((line) => {
43618
+ const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
43619
+ const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
43620
+ return {
43621
+ ticketTypeId: line.ticketTypeId,
43622
+ label: ticketType?.name ?? input.fallbackLabel,
43623
+ quantity: line.quantity,
43624
+ unitPriceCents,
43625
+ subtotalCents: Math.max(0, unitPriceCents) * line.quantity
43626
+ };
43627
+ });
43628
+ }
43629
+ var init_ticketSelectionLines = __esm({
43630
+ "../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts"() {
43631
+ "use strict";
43632
+ }
43633
+ });
43634
+
43560
43635
  // ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
43561
43636
  function eligibilityLookupReducer(state, action) {
43562
43637
  switch (action.type) {
@@ -43671,6 +43746,7 @@ function usePortalAuth() {
43671
43746
  }
43672
43747
  function useEligibility(params) {
43673
43748
  const api = useBlockApi();
43749
+ const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
43674
43750
  const [state, dispatch] = useReducer8(
43675
43751
  eligibilityLookupReducer,
43676
43752
  initialEligibilityLookupState
@@ -43684,7 +43760,8 @@ function useEligibility(params) {
43684
43760
  dispatch({ type: "reset" });
43685
43761
  return;
43686
43762
  }
43687
- if (!params.occurrenceId || !params.email.trim()) {
43763
+ const ticketSelections = JSON.parse(ticketSelectionsKey);
43764
+ if (!params.occurrenceId || !params.email.trim() || ticketSelections.length === 0) {
43688
43765
  requestIdRef.current += 1;
43689
43766
  dispatch({ type: "reset" });
43690
43767
  return;
@@ -43696,10 +43773,9 @@ function useEligibility(params) {
43696
43773
  const result = await api.checkEligibility({
43697
43774
  occurrenceId: params.occurrenceId,
43698
43775
  attendanceMode: params.attendanceMode ?? void 0,
43699
- ticketTypeId: params.ticketTypeId ?? void 0,
43776
+ ticketSelections,
43700
43777
  selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
43701
- email: params.email.trim().toLowerCase(),
43702
- ticketsCount: params.ticketsCount
43778
+ email: params.email.trim().toLowerCase()
43703
43779
  });
43704
43780
  if (cancelled || requestIdRef.current !== requestId) return;
43705
43781
  dispatch({
@@ -43718,7 +43794,15 @@ function useEligibility(params) {
43718
43794
  return () => {
43719
43795
  cancelled = true;
43720
43796
  };
43721
- }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
43797
+ }, [
43798
+ api,
43799
+ params.enabled,
43800
+ params.occurrenceId,
43801
+ params.attendanceMode,
43802
+ ticketSelectionsKey,
43803
+ params.selectedSlidingAmount,
43804
+ params.email
43805
+ ]);
43722
43806
  return {
43723
43807
  state,
43724
43808
  eligibility: state.eligibility,
@@ -43775,6 +43859,7 @@ var init_hooks = __esm({
43775
43859
  "use strict";
43776
43860
  init_api();
43777
43861
  init_utils5();
43862
+ init_ticketSelectionLines();
43778
43863
  init_hooks_state();
43779
43864
  }
43780
43865
  });
@@ -43800,9 +43885,15 @@ function savePendingRegistration(siteId, occurrenceId, data) {
43800
43885
  }
43801
43886
  try {
43802
43887
  const key = getStorageKey(siteId, occurrenceId);
43888
+ const ticketSelections = normalizeTicketSelectionLines(data.ticketSelections);
43889
+ if (ticketSelections.length === 0) {
43890
+ console.warn("[sessionStorage] No ticket selections to save, skipping registration state");
43891
+ return;
43892
+ }
43803
43893
  const entry = {
43804
43894
  ...data,
43805
- version: 3,
43895
+ ticketSelections,
43896
+ version: 4,
43806
43897
  timestamp: Date.now()
43807
43898
  };
43808
43899
  sessionStorage.setItem(key, JSON.stringify(entry));
@@ -43848,8 +43939,8 @@ function parseAndValidateEntry(stored, key) {
43848
43939
  return null;
43849
43940
  }
43850
43941
  const version = raw.version;
43851
- if (version !== 1 && version !== 2 && version !== 3) {
43852
- console.warn("[sessionStorage] Unknown version, ignoring entry");
43942
+ if (version !== 4) {
43943
+ console.warn("[sessionStorage] Outdated version, ignoring entry");
43853
43944
  sessionStorage.removeItem(key);
43854
43945
  return null;
43855
43946
  }
@@ -43865,34 +43956,12 @@ function parseAndValidateEntry(stored, key) {
43865
43956
  sessionStorage.removeItem(key);
43866
43957
  return null;
43867
43958
  }
43868
- if (entry.version === 1) {
43869
- const legacy = entry;
43870
- return {
43871
- version: 3,
43872
- attendeeId: legacy.attendeeId,
43873
- formData: legacy.formData,
43874
- ticketsCount: legacy.ticketsCount,
43875
- selectedEventId: legacy.selectedEventId,
43876
- selectedAttendanceMode: null,
43877
- selectedTicketTypeId: null,
43878
- paymentSelection: { method: legacy.paymentMethod },
43879
- timestamp: legacy.timestamp
43880
- };
43881
- }
43882
- if (entry.version === 2) {
43883
- return {
43884
- version: 3,
43885
- attendeeId: entry.attendeeId,
43886
- formData: entry.formData,
43887
- ticketsCount: entry.ticketsCount,
43888
- selectedEventId: entry.selectedEventId,
43889
- selectedAttendanceMode: null,
43890
- selectedTicketTypeId: null,
43891
- paymentSelection: entry.paymentSelection,
43892
- timestamp: entry.timestamp
43893
- };
43959
+ const ticketSelections = normalizeTicketSelectionLines(entry.ticketSelections);
43960
+ if (ticketSelections.length === 0 || getTicketSelectionTotal(ticketSelections) <= 0) {
43961
+ sessionStorage.removeItem(key);
43962
+ return null;
43894
43963
  }
43895
- return entry;
43964
+ return { ...entry, ticketSelections };
43896
43965
  } catch {
43897
43966
  console.warn("[sessionStorage] Failed to parse entry, removing");
43898
43967
  sessionStorage.removeItem(key);
@@ -43924,8 +43993,9 @@ function cleanupStaleRegistrations() {
43924
43993
  const stored = sessionStorage.getItem(key);
43925
43994
  if (!stored) continue;
43926
43995
  const entry = JSON.parse(stored);
43927
- const age = Date.now() - entry.timestamp;
43928
- if (age > STALE_THRESHOLD_MS) {
43996
+ const timestamp = typeof entry.timestamp === "number" ? entry.timestamp : NaN;
43997
+ const age = Date.now() - timestamp;
43998
+ if (!Number.isFinite(timestamp) || age > STALE_THRESHOLD_MS) {
43929
43999
  keysToRemove.push(key);
43930
44000
  }
43931
44001
  } catch {
@@ -43946,6 +44016,7 @@ var STORAGE_PREFIX, STALE_THRESHOLD_MS;
43946
44016
  var init_sessionStorage = __esm({
43947
44017
  "../blocks/src/system/runtime/nodes/event-registration/sessionStorage.ts"() {
43948
44018
  "use strict";
44019
+ init_ticketSelectionLines();
43949
44020
  STORAGE_PREFIX = "riverbank:event-registration:";
43950
44021
  STALE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
43951
44022
  }
@@ -44035,14 +44106,16 @@ function getEventAttendanceModeLabel(mode) {
44035
44106
  }
44036
44107
  }
44037
44108
  function TicketCounter(props2) {
44038
- const { ticketsCount, maxAllowed, onTicketsChange } = props2;
44109
+ const { ticketsCount, maxAllowed, label, onTicketsChange } = props2;
44110
+ const minAllowed = props2.minAllowed ?? 1;
44039
44111
  return /* @__PURE__ */ jsxs28("div", { className: "er-row er-counter", children: [
44040
44112
  /* @__PURE__ */ jsx42(
44041
44113
  "button",
44042
44114
  {
44043
44115
  type: "button",
44044
- onClick: () => onTicketsChange(Math.max(1, ticketsCount - 1)),
44045
- disabled: ticketsCount <= 1,
44116
+ "aria-label": `Decrease ${label}`,
44117
+ onClick: () => onTicketsChange(Math.max(minAllowed, ticketsCount - 1)),
44118
+ disabled: ticketsCount <= minAllowed,
44046
44119
  className: "er-counter-btn",
44047
44120
  children: "-"
44048
44121
  }
@@ -44052,6 +44125,7 @@ function TicketCounter(props2) {
44052
44125
  "button",
44053
44126
  {
44054
44127
  type: "button",
44128
+ "aria-label": `Increase ${label}`,
44055
44129
  onClick: () => onTicketsChange(Math.min(maxAllowed, ticketsCount + 1)),
44056
44130
  disabled: ticketsCount >= maxAllowed,
44057
44131
  className: "er-counter-btn",
@@ -44104,14 +44178,86 @@ function SlidingScaleAmountField(props2) {
44104
44178
  props2.message ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: props2.message }) : null
44105
44179
  ] });
44106
44180
  }
44107
- function getTicketTypeCounterAvailabilityLabel(input) {
44108
- if (input.selectedRemainingCapacity !== null) {
44109
- return `${input.selectedRemainingCapacity} remaining for this ticket type`;
44110
- }
44111
- if (input.eventAvailableSpots != null) {
44112
- return `${input.eventAvailableSpots} spots available`;
44113
- }
44114
- return null;
44181
+ function TicketTypeQuantityRows(props2) {
44182
+ const totalSelectedQuantity = getTicketSelectionTotal(props2.ticketSelections);
44183
+ const selectedTicketTypes = props2.ticketTypes.filter(
44184
+ (ticketType) => getTicketLineQuantity(props2.ticketSelections, ticketType.id) > 0
44185
+ );
44186
+ return /* @__PURE__ */ jsxs28("div", { className: "er-ticket-lines", children: [
44187
+ /* @__PURE__ */ jsx42("div", { className: "er-ticket-line-list", role: "list", "aria-label": "Tickets", children: props2.ticketTypes.map((ticketType) => {
44188
+ const quantity = getTicketLineQuantity(props2.ticketSelections, ticketType.id);
44189
+ const disabled = ticketType.availability.kind === "unavailable";
44190
+ const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
44191
+ const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, props2.currency) : "Free";
44192
+ const maxAllowed = disabled ? 0 : getTicketTypeLineMax({
44193
+ currentQuantity: quantity,
44194
+ totalSelectedQuantity,
44195
+ maxTickets: props2.maxTickets,
44196
+ availableSpots: props2.availableSpots,
44197
+ ticketTypeRemainingCapacity: ticketType.availability.remainingCapacity
44198
+ });
44199
+ return /* @__PURE__ */ jsxs28(
44200
+ "div",
44201
+ {
44202
+ className: `er-ticket-line${disabled ? " er-ticket-line--disabled" : ""}`,
44203
+ role: "listitem",
44204
+ children: [
44205
+ /* @__PURE__ */ jsxs28("div", { className: "er-ticket-line-main", children: [
44206
+ /* @__PURE__ */ jsxs28("div", { className: "er-ticket-line-heading", children: [
44207
+ /* @__PURE__ */ jsx42("span", { className: "er-ticket-line-name", children: ticketType.name }),
44208
+ /* @__PURE__ */ jsx42("span", { className: "er-ticket-line-price", children: priceLabel })
44209
+ ] }),
44210
+ ticketType.description ? /* @__PURE__ */ jsx42("p", { className: "er-ticket-line-detail", children: ticketType.description }) : null,
44211
+ availabilityLabel ? /* @__PURE__ */ jsx42("p", { className: "er-ticket-line-detail", children: availabilityLabel }) : ticketType.availability.remainingCapacity !== null ? /* @__PURE__ */ jsxs28("p", { className: "er-ticket-line-detail", children: [
44212
+ ticketType.availability.remainingCapacity,
44213
+ " remaining for this ticket type"
44214
+ ] }) : null
44215
+ ] }),
44216
+ /* @__PURE__ */ jsx42(
44217
+ TicketCounter,
44218
+ {
44219
+ ticketsCount: quantity,
44220
+ minAllowed: 0,
44221
+ maxAllowed,
44222
+ label: ticketType.name,
44223
+ onTicketsChange: (nextQuantity) => {
44224
+ props2.onTicketSelectionsChange?.(setTicketLineQuantity({
44225
+ lines: props2.ticketSelections,
44226
+ ticketTypeId: ticketType.id,
44227
+ quantity: nextQuantity
44228
+ }));
44229
+ }
44230
+ }
44231
+ )
44232
+ ]
44233
+ },
44234
+ ticketType.id
44235
+ );
44236
+ }) }),
44237
+ /* @__PURE__ */ jsx42(
44238
+ TicketCounterLimit,
44239
+ {
44240
+ maximumLabel: `${props2.maxTickets} tickets maximum`,
44241
+ availabilityLabel: props2.availableSpots != null ? `${props2.availableSpots} spots available` : null
44242
+ }
44243
+ ),
44244
+ selectedTicketTypes.length > 0 ? /* @__PURE__ */ jsxs28("div", { className: "er-ticket-line-summary", "aria-live": "polite", children: [
44245
+ /* @__PURE__ */ jsxs28("div", { className: "er-ticket-line-summary-title", children: [
44246
+ totalSelectedQuantity,
44247
+ " ticket",
44248
+ totalSelectedQuantity === 1 ? "" : "s",
44249
+ " selected"
44250
+ ] }),
44251
+ /* @__PURE__ */ jsx42("ul", { className: "er-ticket-line-summary-list", children: selectedTicketTypes.map((ticketType) => {
44252
+ const quantity = getTicketLineQuantity(props2.ticketSelections, ticketType.id);
44253
+ return /* @__PURE__ */ jsxs28("li", { children: [
44254
+ quantity,
44255
+ " x ",
44256
+ ticketType.name
44257
+ ] }, ticketType.id);
44258
+ }) })
44259
+ ] }) : props2.hasAvailableTicketTypes ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "Choose at least one ticket to continue." }) : /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." })
44260
+ ] });
44115
44261
  }
44116
44262
  function getAttendanceModeDetail(attendanceMode) {
44117
44263
  if (attendanceMode.availableSpots === null) {
@@ -44129,6 +44275,7 @@ function AttendanceModeTiles(props2) {
44129
44275
  "button",
44130
44276
  {
44131
44277
  type: "button",
44278
+ "aria-pressed": isSelected,
44132
44279
  className: `er-payment-tile${isSelected ? " er-payment-tile--selected" : ""}`,
44133
44280
  onClick: () => props2.onAttendanceModeChange?.(attendanceMode.mode),
44134
44281
  children: [
@@ -44166,6 +44313,7 @@ var init_TicketSelectionStep = __esm({
44166
44313
  init_src();
44167
44314
  init_pricing();
44168
44315
  init_utils5();
44316
+ init_ticketSelectionLines();
44169
44317
  TicketSelectionStep = ({
44170
44318
  event,
44171
44319
  occurrenceContext: _occurrenceContext,
@@ -44173,8 +44321,9 @@ var init_TicketSelectionStep = __esm({
44173
44321
  onAttendanceModeChange,
44174
44322
  ticketsCount,
44175
44323
  maxTickets,
44176
- selectedTicketTypeId = null,
44177
- onTicketTypeChange,
44324
+ visibleTicketTypes: visibleTicketTypesOverride,
44325
+ ticketSelections = [],
44326
+ onTicketSelectionsChange,
44178
44327
  slidingScale = null,
44179
44328
  selectedSlidingAmountInput = "",
44180
44329
  slidingScaleSelectionMessage = null,
@@ -44192,28 +44341,22 @@ var init_TicketSelectionStep = __esm({
44192
44341
  const eventPricingMode = eventPricing ? publicEventPricingMode(eventPricing) : void 0;
44193
44342
  const eventPricingCurrency = eventPricing ? publicEventPricingCurrency(eventPricing) : null;
44194
44343
  const usesTicketTypes = eventPricingMode === "ticket_types" && !canJoinWaitlist;
44195
- const visibleTicketTypes = usesTicketTypes ? getVisibleTicketTypes({
44344
+ const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
44196
44345
  event,
44197
44346
  eligibility: null,
44198
44347
  selectedAttendanceMode
44199
44348
  }) : [];
44200
- const selectedTicketType = usesTicketTypes ? visibleTicketTypes.find((ticketType) => ticketType.id === selectedTicketTypeId) ?? null : null;
44201
44349
  const implicitTicketType = usesTicketTypes ? getImplicitSingleAvailableTicketType(visibleTicketTypes) : null;
44202
- const effectiveSelectedTicketType = selectedTicketType ?? implicitTicketType;
44203
- const shouldShowTicketTypeTiles = usesTicketTypes && implicitTicketType === null;
44204
- const selectedRemainingCapacity = effectiveSelectedTicketType?.availability.remainingCapacity ?? null;
44205
- const noSellableTicketTypes = usesTicketTypes && (visibleTicketTypes.length === 0 || visibleTicketTypes.every((ticketType) => ticketType.availability.kind === "unavailable"));
44350
+ const noVisibleTicketTypes = usesTicketTypes && visibleTicketTypes.length === 0;
44351
+ const hasAvailableTicketTypes = usesTicketTypes && visibleTicketTypes.some((ticketType) => ticketType.availability.kind === "available");
44352
+ const aggregateRemainingCapacity = implicitTicketType?.availability.remainingCapacity ?? null;
44206
44353
  const maxAllowed = getMaxAllowedTicketCount({
44207
44354
  canJoinWaitlist,
44208
44355
  usesTicketTypes,
44209
44356
  maxTickets,
44210
44357
  availableSpots,
44211
- selectedTicketTypeRemainingCapacity: selectedRemainingCapacity,
44212
- hasSelectedTicketType: effectiveSelectedTicketType !== null
44213
- });
44214
- const selectedTicketTypeAvailabilityLabel = getTicketTypeCounterAvailabilityLabel({
44215
- selectedRemainingCapacity,
44216
- eventAvailableSpots: event?.availableSpots
44358
+ selectedTicketTypeRemainingCapacity: aggregateRemainingCapacity,
44359
+ hasSelectedTicketType: implicitTicketType !== null
44217
44360
  });
44218
44361
  const eventAvailabilityLabel = !canJoinWaitlist && event?.availableSpots != null ? `${event.availableSpots} spots available` : null;
44219
44362
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) {
@@ -44230,7 +44373,7 @@ var init_TicketSelectionStep = __esm({
44230
44373
  /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "Choose whether you want to attend in person or online." })
44231
44374
  ] });
44232
44375
  }
44233
- if (isSoldOut && !canJoinWaitlist && !usesTicketTypes) {
44376
+ if (isSoldOut && !canJoinWaitlist) {
44234
44377
  return /* @__PURE__ */ jsxs28("div", { className: "er-stack", children: [
44235
44378
  /* @__PURE__ */ jsx42("h3", { className: "er-title", children: "Sold Out" }),
44236
44379
  /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "Sorry you missed out! This event is fully booked." })
@@ -44248,52 +44391,21 @@ var init_TicketSelectionStep = __esm({
44248
44391
  }
44249
44392
  )
44250
44393
  ] }) : null,
44251
- usesTicketTypes ? /* @__PURE__ */ jsxs28(Fragment8, { children: [
44252
- shouldShowTicketTypeTiles ? /* @__PURE__ */ jsxs28(Fragment8, { children: [
44253
- /* @__PURE__ */ jsx42("h3", { className: "er-title", children: "Choose a ticket type" }),
44254
- /* @__PURE__ */ jsx42("div", { className: "er-payment-tiles", role: "list", "aria-label": "Ticket types", children: visibleTicketTypes.map((ticketType) => {
44255
- const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
44256
- const disabled = ticketType.availability.kind === "unavailable";
44257
- const isSelected = selectedTicketTypeId === ticketType.id;
44258
- const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2) : "Free";
44259
- return /* @__PURE__ */ jsx42("div", { role: "listitem", children: /* @__PURE__ */ jsxs28(
44260
- "button",
44261
- {
44262
- type: "button",
44263
- className: `er-payment-tile${isSelected && !disabled ? " er-payment-tile--selected" : ""}${disabled ? " er-payment-tile--disabled" : ""}`,
44264
- disabled,
44265
- onClick: () => onTicketTypeChange?.(ticketType.id),
44266
- children: [
44267
- /* @__PURE__ */ jsx42("div", { className: "er-payment-tile-label", children: ticketType.name }),
44268
- /* @__PURE__ */ jsx42("div", { className: "er-payment-tile-detail", children: priceLabel }),
44269
- ticketType.description ? /* @__PURE__ */ jsx42("div", { className: "er-payment-tile-detail", children: ticketType.description }) : null,
44270
- availabilityLabel ? /* @__PURE__ */ jsx42("div", { className: "er-payment-tile-detail", children: availabilityLabel }) : null
44271
- ]
44272
- }
44273
- ) }, ticketType.id);
44274
- }) })
44275
- ] }) : null,
44276
- noSellableTicketTypes ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : !effectiveSelectedTicketType ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "Select one ticket type to continue." }) : effectiveSelectedTicketType.availability.kind === "unavailable" ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: getTicketTypeAvailabilityLabel(effectiveSelectedTicketType) ?? "This ticket type is unavailable." }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
44277
- /* @__PURE__ */ jsx42("h3", { className: "er-title", children: "How many tickets?" }),
44278
- /* @__PURE__ */ jsxs28("div", { className: "er-ticket-counter-group", children: [
44279
- /* @__PURE__ */ jsx42(
44280
- TicketCounter,
44281
- {
44282
- ticketsCount,
44283
- maxAllowed,
44284
- onTicketsChange
44285
- }
44286
- ),
44287
- /* @__PURE__ */ jsx42(
44288
- TicketCounterLimit,
44289
- {
44290
- maximumLabel: `${maxAllowed} tickets maximum`,
44291
- availabilityLabel: selectedTicketTypeAvailabilityLabel
44292
- }
44293
- )
44294
- ] })
44295
- ] })
44296
- ] }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
44394
+ usesTicketTypes ? /* @__PURE__ */ jsx42(Fragment8, { children: noVisibleTicketTypes ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
44395
+ /* @__PURE__ */ jsx42("h3", { className: "er-title", children: "Choose tickets" }),
44396
+ /* @__PURE__ */ jsx42(
44397
+ TicketTypeQuantityRows,
44398
+ {
44399
+ ticketTypes: visibleTicketTypes,
44400
+ ticketSelections,
44401
+ maxTickets,
44402
+ availableSpots,
44403
+ currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
44404
+ hasAvailableTicketTypes,
44405
+ onTicketSelectionsChange
44406
+ }
44407
+ )
44408
+ ] }) }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
44297
44409
  slidingScale ? /* @__PURE__ */ jsx42(
44298
44410
  SlidingScaleAmountField,
44299
44411
  {
@@ -44311,6 +44423,7 @@ var init_TicketSelectionStep = __esm({
44311
44423
  {
44312
44424
  ticketsCount,
44313
44425
  maxAllowed,
44426
+ label: canJoinWaitlist ? "waitlist spots" : "tickets",
44314
44427
  onTicketsChange
44315
44428
  }
44316
44429
  ),
@@ -44834,7 +44947,7 @@ var init_PaymentSelectionStep = __esm({
44834
44947
  }) => {
44835
44948
  const occurrenceId = occurrenceContext?.id ?? event?.registrationOccurrenceId;
44836
44949
  const selectedMethod = selectedSelection.method;
44837
- const totalPrice = eligibility?.price ? eligibility.price * ticketsCount : 0;
44950
+ const totalPrice = eligibility?.price ?? 0;
44838
44951
  const canShowDirectPaymentOptions = Boolean(
44839
44952
  eligibility?.eligible && eligibility.canPayDirectly && eligibility.price
44840
44953
  );
@@ -45316,8 +45429,9 @@ function EventRegistrationWizardContent(props2) {
45316
45429
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
45317
45430
  ticketsCount: wizard.ticketsCount,
45318
45431
  maxTickets: wizard.maxTicketsNum,
45319
- selectedTicketTypeId: wizard.selectedTicketTypeId,
45320
- onTicketTypeChange: wizard.setSelectedTicketTypeId,
45432
+ visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
45433
+ ticketSelections: wizard.selectedTicketLines,
45434
+ onTicketSelectionsChange: wizard.setSelectedTicketLines,
45321
45435
  slidingScale: wizard.selectedEventSlidingScale,
45322
45436
  selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
45323
45437
  slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
@@ -45438,9 +45552,9 @@ function EventRegistrationWizardActions(props2) {
45438
45552
  const isWaitingForEligibility = wizard.portalAuthState === "authenticated" && wizard.eligibilityLoading;
45439
45553
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
45440
45554
  const hasExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistration !== null;
45441
- const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidSelectedTicketType;
45555
+ const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
45442
45556
  const isContinueDisabled = isWaitingForEligibility || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
45443
- const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket type" : "Continue";
45557
+ const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket" : "Continue";
45444
45558
  return /* @__PURE__ */ jsxs38("div", { className: "er-actions", children: [
45445
45559
  !wizard.hasPreSelectedContext && /* @__PURE__ */ jsx54("button", { type: "button", onClick: () => wizard.setStep("select-event"), className: "er-back-btn", children: "\u2190 Back" }),
45446
45560
  /* @__PURE__ */ jsx54(
@@ -45538,13 +45652,17 @@ function EventRegistrationSummaryBar(props2) {
45538
45652
  const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
45539
45653
  const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
45540
45654
  const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
45541
- const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
45542
45655
  const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
45543
45656
  const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
45544
- const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
45657
+ const fallbackSubtotalCents = Math.max(
45658
+ 0,
45659
+ ((summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0) * wizard.ticketsCount
45660
+ );
45661
+ const subtotalCents = Math.max(0, wizard.ticketSelectionSubtotalCents ?? fallbackSubtotalCents);
45545
45662
  const autoAppliedDiscount = wizard.discountCode.trim().length > 0 ? null : wizard.autoAppliedDiscount;
45546
45663
  const autoAppliedDiscountCents = Math.max(0, autoAppliedDiscount?.computedAmountCents ?? 0);
45547
45664
  const discountedTotalCents = Math.max(0, subtotalCents - autoAppliedDiscountCents);
45665
+ const selectedLineSummary = (wizard.ticketSelectionSummaryLines ?? []).filter((line) => line.ticketTypeId !== null).map((line) => `${line.quantity} x ${line.label}`).join(", ");
45548
45666
  const selectedDirectPaymentOption = getSelectedDirectPaymentOption({
45549
45667
  wizard,
45550
45668
  totalCents: discountedTotalCents,
@@ -45581,9 +45699,9 @@ function EventRegistrationSummaryBar(props2) {
45581
45699
  /* @__PURE__ */ jsx55("h4", { className: "er-summary-bar-event", children: summaryTitle }),
45582
45700
  /* @__PURE__ */ jsxs39("span", { className: "er-summary-bar-meta", children: [
45583
45701
  summaryDate && formatEventDateTime(summaryDate, { timeZone: summaryTimeZone }),
45584
- wizard.selectedTicketType ? /* @__PURE__ */ jsxs39(Fragment12, { children: [
45702
+ selectedLineSummary ? /* @__PURE__ */ jsxs39(Fragment12, { children: [
45585
45703
  " \xB7 ",
45586
- wizard.selectedTicketType.name
45704
+ selectedLineSummary
45587
45705
  ] }) : null,
45588
45706
  wizard.step !== "select-event" && wizard.step !== "select-tickets" && wizard.ticketsCount > 0 && /* @__PURE__ */ jsxs39(Fragment12, { children: [
45589
45707
  " \xB7 ",
@@ -45597,8 +45715,8 @@ function EventRegistrationSummaryBar(props2) {
45597
45715
  teamMemberNames.join(", ")
45598
45716
  ] })
45599
45717
  ] }),
45600
- summaryPrice > 0 && /* @__PURE__ */ jsx55("div", { className: "er-summary-bar-pricing", children: productMethod ? /* @__PURE__ */ jsxs39(Fragment12, { children: [
45601
- /* @__PURE__ */ jsx55("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(summaryPrice * wizard.ticketsCount, summaryCurrency) }),
45718
+ subtotalCents > 0 && /* @__PURE__ */ jsx55("div", { className: "er-summary-bar-pricing", children: productMethod ? /* @__PURE__ */ jsxs39(Fragment12, { children: [
45719
+ /* @__PURE__ */ jsx55("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(subtotalCents, summaryCurrency) }),
45602
45720
  /* @__PURE__ */ jsx55("div", { className: "er-summary-bar-included", children: wizard.paymentSelection.method === "pass" || wizard.paymentSelection.method === "pass_bundle" ? "1 pass credit" : "Included in membership" })
45603
45721
  ] }) : flexibleBalanceSummary ? /* @__PURE__ */ jsxs39(Fragment12, { children: [
45604
45722
  flexibleBalanceSummary.total ? /* @__PURE__ */ jsxs39("div", { className: "er-summary-bar-product-detail", children: [
@@ -45874,7 +45992,7 @@ function useEventRegistrationStripeReturn(options) {
45874
45992
  setRegistrationResult,
45875
45993
  setSelectedEvent,
45876
45994
  setSelectedAttendanceMode,
45877
- setSelectedTicketTypeId,
45995
+ setTicketSelections,
45878
45996
  setStep,
45879
45997
  setTicketsCount,
45880
45998
  step
@@ -45893,13 +46011,13 @@ function useEventRegistrationStripeReturn(options) {
45893
46011
  const pending = getPendingRegistration(siteId, occurrenceId || void 0);
45894
46012
  if (!pending) return;
45895
46013
  setFormData(pending.formData);
45896
- setTicketsCount(pending.ticketsCount);
46014
+ setTicketSelections(pending.ticketSelections);
46015
+ setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
45897
46016
  if (pending.selectedEventId) {
45898
46017
  const event = events.find((e) => e.publicEventId === pending.selectedEventId) ?? null;
45899
46018
  if (event) setSelectedEvent(event);
45900
46019
  }
45901
46020
  setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
45902
- setSelectedTicketTypeId(pending.selectedTicketTypeId ?? null);
45903
46021
  setPaymentSelection(pending.paymentSelection);
45904
46022
  if (registrationStatus === "cancelled") {
45905
46023
  setStep("select-payment");
@@ -45944,6 +46062,7 @@ var init_useEventRegistrationStripeReturn = __esm({
45944
46062
  init_usePaymentVerification();
45945
46063
  init_shared5();
45946
46064
  init_sessionStorage();
46065
+ init_ticketSelectionLines();
45947
46066
  }
45948
46067
  });
45949
46068
 
@@ -45960,6 +46079,10 @@ function useEventRegistrationSubmit(options) {
45960
46079
  }
45961
46080
  options.setStep("submitting");
45962
46081
  try {
46082
+ const ticketSelections = normalizeTicketSelectionLines(options.ticketSelections);
46083
+ if (ticketSelections.length === 0) {
46084
+ throw new Error("Choose at least one ticket to continue.");
46085
+ }
45963
46086
  const isBundle = method === "pass_bundle" || method === "membership_bundle";
45964
46087
  const bundleProductId = isBundle ? passId || membershipId : void 0;
45965
46088
  const selectionSnapshot = (() => {
@@ -45988,11 +46111,10 @@ function useEventRegistrationSubmit(options) {
45988
46111
  const result = await options.api.registerForEvent({
45989
46112
  occurrenceId: submitOccurrenceId,
45990
46113
  attendanceMode: options.selectedAttendanceMode ?? void 0,
45991
- ticketTypeId: options.selectedTicketTypeId ?? void 0,
46114
+ ticketSelections,
45992
46115
  selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
45993
46116
  email: options.formData.email.trim().toLowerCase(),
45994
46117
  name: options.formData.name.trim(),
45995
- ticketsCount: options.ticketsCount,
45996
46118
  phone: options.formData.phone.trim() || void 0,
45997
46119
  notes: options.formData.notes.trim() || void 0,
45998
46120
  altchaSolution: options.altchaSolution,
@@ -46037,10 +46159,9 @@ function useEventRegistrationSubmit(options) {
46037
46159
  savePendingRegistration(siteId, submitOccurrenceId, {
46038
46160
  attendeeId: result.attendeeId,
46039
46161
  formData: options.formData,
46040
- ticketsCount: options.ticketsCount,
46162
+ ticketSelections,
46041
46163
  selectedEventId: options.registrationTarget?.selectedEventId ?? null,
46042
46164
  selectedAttendanceMode: options.selectedAttendanceMode,
46043
- selectedTicketTypeId: options.selectedTicketTypeId ?? null,
46044
46165
  paymentSelection: selectionSnapshot
46045
46166
  });
46046
46167
  }
@@ -46094,6 +46215,7 @@ var init_useEventRegistrationSubmit = __esm({
46094
46215
  "use strict";
46095
46216
  "use client";
46096
46217
  init_sessionStorage();
46218
+ init_ticketSelectionLines();
46097
46219
  }
46098
46220
  });
46099
46221
 
@@ -46160,7 +46282,6 @@ function useEventRegistrationWizard(options) {
46160
46282
  createInitialRegistrationFlowState
46161
46283
  );
46162
46284
  const step = flowState.step;
46163
- const ticketsCount = flowState.ticketsCount;
46164
46285
  const paymentSelection = flowState.paymentSelection;
46165
46286
  const [selectedEvent, setSelectedEvent] = useState7(preSelectedEvent ?? null);
46166
46287
  const [formData, setFormData] = useState7({ name: "", email: "", phone: "", notes: "" });
@@ -46171,7 +46292,7 @@ function useEventRegistrationWizard(options) {
46171
46292
  const [selectedAttendanceMode, setSelectedAttendanceMode] = useState7(
46172
46293
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
46173
46294
  );
46174
- const [selectedTicketTypeId, setSelectedTicketTypeId] = useState7(null);
46295
+ const [selectedTicketLines, setSelectedTicketLines] = useState7([]);
46175
46296
  const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState7(() => {
46176
46297
  const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
46177
46298
  return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
@@ -46207,14 +46328,51 @@ function useEventRegistrationWizard(options) {
46207
46328
  [options.occurrenceContext, selectedEvent]
46208
46329
  );
46209
46330
  const occurrenceId = registrationTarget?.occurrenceId ?? "";
46331
+ const currentEvent = selectedEvent ?? preSelectedEvent;
46332
+ const currentEventPricing = currentEvent ? resolveRuntimeEventPricing(currentEvent) : null;
46333
+ const currentEventUsesTicketTypes = currentEventPricing !== null && publicEventPricingMode(currentEventPricing) === "ticket_types";
46334
+ const selectedModeAvailability = selectedAttendanceMode ? (currentEvent?.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
46335
+ const currentAvailableSpots = selectedModeAvailability?.availableSpots ?? currentEvent?.availableSpots;
46336
+ const currentWaitlistEnabled = selectedModeAvailability?.waitlistEnabled ?? currentEvent?.waitlistEnabled ?? false;
46337
+ const currentCanJoinWaitlist = currentAvailableSpots === 0 && currentWaitlistEnabled === true;
46338
+ const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
46339
+ const eventTicketTypesForSelection = useMemo10(
46340
+ () => getVisibleTicketTypes({
46341
+ event: currentEvent,
46342
+ eligibility: null,
46343
+ selectedAttendanceMode
46344
+ }),
46345
+ [currentEvent, selectedAttendanceMode]
46346
+ );
46347
+ const normalizedSelectedTicketLines = useMemo10(
46348
+ () => normalizeTicketSelectionLines(selectedTicketLines),
46349
+ [selectedTicketLines]
46350
+ );
46351
+ const ticketTypeSelectionTotal = useMemo10(
46352
+ () => getTicketSelectionTotal(normalizedSelectedTicketLines),
46353
+ [normalizedSelectedTicketLines]
46354
+ );
46355
+ const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
46356
+ const ticketSelections = useMemo10(() => {
46357
+ if (waitlistClaim.claim) {
46358
+ return [{ ticketTypeId: null, quantity: 1 }];
46359
+ }
46360
+ if (usesTicketTypeSelections) {
46361
+ return normalizedSelectedTicketLines;
46362
+ }
46363
+ return [{ ticketTypeId: null, quantity: ticketsCount }];
46364
+ }, [normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, waitlistClaim.claim]);
46365
+ useEffect15(() => {
46366
+ if (flowState.ticketsCount === ticketsCount) return;
46367
+ dispatchFlow({ type: "set-tickets-count", ticketsCount });
46368
+ }, [flowState.ticketsCount, ticketsCount]);
46210
46369
  const eligibilityResult = useEligibility({
46211
46370
  enabled: portalAuthState === "authenticated" || step === "enter-details" || step === "select-payment",
46212
46371
  occurrenceId,
46213
46372
  attendanceMode: selectedAttendanceMode,
46214
- ticketTypeId: selectedTicketTypeId,
46373
+ ticketSelections,
46215
46374
  selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
46216
- email: formData.email,
46217
- ticketsCount
46375
+ email: formData.email
46218
46376
  });
46219
46377
  const existingRegistrationResult = useExistingEventRegistration({
46220
46378
  isAuthenticated: portalAuthState === "authenticated",
@@ -46320,7 +46478,7 @@ function useEventRegistrationWizard(options) {
46320
46478
  setTicketsCount,
46321
46479
  setSelectedEvent,
46322
46480
  setSelectedAttendanceMode,
46323
- setSelectedTicketTypeId,
46481
+ setTicketSelections: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
46324
46482
  setPaymentSelection: (selection) => dispatchFlow({ type: "set-manual-payment-selection", selection }),
46325
46483
  setPendingAttendeeId,
46326
46484
  setStep,
@@ -46333,20 +46491,21 @@ function useEventRegistrationWizard(options) {
46333
46491
  }, [selectedEvent, preSelectedEvent]);
46334
46492
  const visibleTicketTypes = useMemo10(
46335
46493
  () => getVisibleTicketTypes({
46336
- event: selectedEvent ?? preSelectedEvent,
46494
+ event: currentEvent,
46337
46495
  eligibility,
46338
46496
  selectedAttendanceMode
46339
46497
  }),
46340
- [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility]
46498
+ [currentEvent, selectedAttendanceMode, eligibility]
46341
46499
  );
46500
+ const singleSelectedTicketTypeId = getSingleSelectedTicketTypeId(normalizedSelectedTicketLines);
46342
46501
  const selectedTicketType = useMemo10(
46343
46502
  () => findSelectedTicketType({
46344
- event: selectedEvent ?? preSelectedEvent,
46503
+ event: currentEvent,
46345
46504
  eligibility,
46346
- selectedTicketTypeId,
46505
+ selectedTicketTypeId: singleSelectedTicketTypeId,
46347
46506
  selectedAttendanceMode
46348
46507
  }),
46349
- [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
46508
+ [currentEvent, eligibility, selectedAttendanceMode, singleSelectedTicketTypeId]
46350
46509
  );
46351
46510
  const selectedSlidingAmount = useMemo10(
46352
46511
  () => parseCurrencyInputToCents(selectedSlidingAmountInput),
@@ -46361,37 +46520,44 @@ function useEventRegistrationWizard(options) {
46361
46520
  selectedAmount: selectedSlidingAmount
46362
46521
  });
46363
46522
  const ticketTypeSelectionRequired = useMemo10(() => {
46364
- const event = selectedEvent ?? preSelectedEvent;
46523
+ const event = currentEvent;
46365
46524
  if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
46366
46525
  return false;
46367
46526
  }
46368
46527
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) {
46369
46528
  return false;
46370
46529
  }
46371
- const selectedModeAvailability = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
46372
- const canJoinWaitlist = (selectedModeAvailability?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability?.waitlistEnabled ?? event.waitlistEnabled) === true;
46530
+ const selectedModeAvailability2 = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
46531
+ const canJoinWaitlist = (selectedModeAvailability2?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability2?.waitlistEnabled ?? event.waitlistEnabled) === true;
46373
46532
  return !canJoinWaitlist;
46374
- }, [selectedAttendanceMode, selectedEvent, preSelectedEvent]);
46375
- const hasValidSelectedTicketType = !ticketTypeSelectionRequired || Boolean(
46376
- selectedTicketType && selectedTicketType.availability.kind === "available"
46377
- );
46533
+ }, [currentEvent, selectedAttendanceMode]);
46534
+ const hasValidTicketSelection = !ticketTypeSelectionRequired || normalizedSelectedTicketLines.length > 0 && normalizedSelectedTicketLines.every((line) => {
46535
+ if (!line.ticketTypeId) return false;
46536
+ const ticketType = visibleTicketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null;
46537
+ return ticketType?.availability.kind === "available";
46538
+ });
46378
46539
  useEffect15(() => {
46379
- const event = selectedEvent ?? preSelectedEvent;
46380
- if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
46381
- if (selectedTicketTypeId !== null) {
46382
- setSelectedTicketTypeId(null);
46540
+ if (!usesTicketTypeSelections) {
46541
+ if (selectedTicketLines.length > 0) {
46542
+ setSelectedTicketLines([]);
46383
46543
  }
46384
46544
  return;
46385
46545
  }
46386
- const implicitTicketType = getImplicitSingleAvailableTicketType(visibleTicketTypes);
46387
- if (implicitTicketType && selectedTicketTypeId !== implicitTicketType.id) {
46388
- setSelectedTicketTypeId(implicitTicketType.id);
46546
+ const availableTicketTypes = eventTicketTypesForSelection.filter(
46547
+ (ticketType) => ticketType.availability.kind === "available"
46548
+ );
46549
+ const implicitTicketType = getImplicitSingleAvailableTicketType(eventTicketTypesForSelection);
46550
+ if (implicitTicketType && normalizedSelectedTicketLines.length === 0) {
46551
+ setSelectedTicketLines([{ ticketTypeId: implicitTicketType.id, quantity: 1 }]);
46389
46552
  return;
46390
46553
  }
46391
- if (selectedTicketTypeId && !visibleTicketTypes.some((ticketType) => ticketType.id === selectedTicketTypeId)) {
46392
- setSelectedTicketTypeId(null);
46554
+ const filteredLines = normalizedSelectedTicketLines.filter(
46555
+ (line) => line.ticketTypeId && availableTicketTypes.some((ticketType) => ticketType.id === line.ticketTypeId)
46556
+ );
46557
+ if (filteredLines.length !== normalizedSelectedTicketLines.length) {
46558
+ setSelectedTicketLines(filteredLines);
46393
46559
  }
46394
- }, [selectedEvent, preSelectedEvent, selectedTicketTypeId, visibleTicketTypes]);
46560
+ }, [eventTicketTypesForSelection, normalizedSelectedTicketLines, selectedTicketLines.length, usesTicketTypeSelections]);
46395
46561
  useEffect15(() => {
46396
46562
  if (!requireGuestDetails) {
46397
46563
  if (guests.length > 0) setGuests([]);
@@ -46435,21 +46601,20 @@ function useEventRegistrationWizard(options) {
46435
46601
  return resolveEventRequiresPayment({
46436
46602
  eligibility,
46437
46603
  selectedTicketType,
46438
- event: selectedEvent ?? preSelectedEvent
46604
+ event: currentEvent
46439
46605
  });
46440
46606
  },
46441
46607
  [
46442
46608
  eligibility,
46443
46609
  selectedTicketType,
46444
- selectedEvent,
46445
- preSelectedEvent,
46610
+ currentEvent,
46446
46611
  selectedEventSlidingScale,
46447
46612
  selectedSlidingAmount
46448
46613
  ]
46449
46614
  );
46450
46615
  const handleDetailsComplete = async () => {
46451
- if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
46452
- const message = "Select a ticket type to continue.";
46616
+ if (ticketTypeSelectionRequired && !hasValidTicketSelection) {
46617
+ const message = "Choose at least one available ticket to continue.";
46453
46618
  setErrorMessage(message);
46454
46619
  setStep("error");
46455
46620
  return { ok: false, reason: "blocked", message };
@@ -46534,27 +46699,39 @@ function useEventRegistrationWizard(options) {
46534
46699
  const discountContext = useMemo10(
46535
46700
  () => resolveDiscountContext({
46536
46701
  paymentSelection,
46537
- event: selectedEvent ?? preSelectedEvent,
46702
+ event: currentEvent,
46538
46703
  eventRequiresPayment,
46539
46704
  ticketsCount
46540
46705
  }),
46541
- [eventRequiresPayment, paymentSelection, selectedEvent, preSelectedEvent, ticketsCount]
46706
+ [currentEvent, eventRequiresPayment, paymentSelection, ticketsCount]
46707
+ );
46708
+ const fallbackUnitPriceCents = useMemo10(
46709
+ () => currentEvent ? publicEventScalarPrice(resolveRuntimeEventPricing(currentEvent)) ?? 0 : 0,
46710
+ [currentEvent]
46711
+ );
46712
+ const ticketSelectionSubtotalCents = useMemo10(() => {
46713
+ if (!usesTicketTypeSelections) {
46714
+ return Math.max(0, eligibility?.price ?? fallbackUnitPriceCents * ticketsCount);
46715
+ }
46716
+ return calculateTicketSelectionSubtotal({
46717
+ lines: normalizedSelectedTicketLines,
46718
+ ticketTypes: visibleTicketTypes,
46719
+ fallbackUnitPriceCents
46720
+ });
46721
+ }, [eligibility, fallbackUnitPriceCents, normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, visibleTicketTypes]);
46722
+ const ticketSelectionSummaryLines = useMemo10(
46723
+ () => buildTicketSelectionSummaryLines({
46724
+ lines: ticketSelections,
46725
+ ticketTypes: visibleTicketTypes,
46726
+ fallbackLabel: "Ticket",
46727
+ fallbackUnitPriceCents
46728
+ }),
46729
+ [fallbackUnitPriceCents, ticketSelections, visibleTicketTypes]
46542
46730
  );
46543
46731
  const discountSubtotalCents = useMemo10(() => {
46544
46732
  if (discountContext?.type !== "event") return void 0;
46545
- const event = selectedEvent ?? preSelectedEvent;
46546
- const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
46547
- return Math.max(0, eventPriceCents * ticketsCount);
46548
- }, [
46549
- discountContext,
46550
- selectedTicketType,
46551
- eligibility,
46552
- selectedEvent,
46553
- preSelectedEvent,
46554
- selectedEventSlidingScale,
46555
- selectedSlidingAmount,
46556
- ticketsCount
46557
- ]);
46733
+ return ticketSelectionSubtotalCents;
46734
+ }, [discountContext, ticketSelectionSubtotalCents]);
46558
46735
  const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
46559
46736
  const selectionMethod = paymentSelection.method;
46560
46737
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -46562,9 +46739,8 @@ function useEventRegistrationWizard(options) {
46562
46739
  api,
46563
46740
  registrationTarget,
46564
46741
  selectedAttendanceMode,
46565
- selectedTicketTypeId,
46742
+ ticketSelections,
46566
46743
  selectedSlidingAmount,
46567
- ticketsCount,
46568
46744
  formData,
46569
46745
  altchaSolution,
46570
46746
  requireGuestDetails,
@@ -46585,12 +46761,12 @@ function useEventRegistrationWizard(options) {
46585
46761
  setSelectedAttendanceMode(
46586
46762
  (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
46587
46763
  );
46588
- setSelectedTicketTypeId(null);
46764
+ setSelectedTicketLines([]);
46589
46765
  dispatchFlow({ type: "event-changed", hasPreSelectedContext: true });
46590
46766
  };
46591
46767
  const handleRetry = () => {
46592
46768
  dispatchFlow({ type: "reset", hasPreSelectedContext });
46593
- setSelectedTicketTypeId(null);
46769
+ setSelectedTicketLines([]);
46594
46770
  setSelectedSlidingAmountInput("");
46595
46771
  setSelectedAttendanceMode(
46596
46772
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
@@ -46626,17 +46802,20 @@ function useEventRegistrationWizard(options) {
46626
46802
  setTicketsCount,
46627
46803
  selectedAttendanceMode,
46628
46804
  setSelectedAttendanceMode,
46629
- selectedTicketTypeId,
46630
- setSelectedTicketTypeId,
46805
+ ticketSelections,
46806
+ selectedTicketLines: normalizedSelectedTicketLines,
46807
+ setSelectedTicketLines: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
46631
46808
  selectedSlidingAmountInput,
46632
46809
  setSelectedSlidingAmountInput,
46633
46810
  selectedSlidingAmount,
46634
46811
  selectedEventSlidingScale,
46635
46812
  slidingScaleSelectionMessage,
46636
46813
  selectedTicketType,
46814
+ ticketSelectionSummaryLines,
46815
+ ticketSelectionSubtotalCents,
46637
46816
  visibleTicketTypes,
46638
46817
  ticketTypeSelectionRequired,
46639
- hasValidSelectedTicketType,
46818
+ hasValidTicketSelection,
46640
46819
  eventRequiresPayment,
46641
46820
  formData,
46642
46821
  setFormData,
@@ -46706,6 +46885,7 @@ var init_useEventRegistrationWizard = __esm({
46706
46885
  init_useEventRegistrationSubmit();
46707
46886
  init_useDiscountCodeUi();
46708
46887
  init_utils5();
46888
+ init_ticketSelectionLines();
46709
46889
  init_registrationStateMachine();
46710
46890
  init_event_registration_headless_state();
46711
46891
  init_registrationDerivations();
@@ -82628,6 +82808,103 @@ var containerResponsiveThemeCss = `/*
82628
82808
  line-height: 1.35;
82629
82809
  }
82630
82810
 
82811
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-lines {
82812
+ display: grid;
82813
+ gap: 0.75rem;
82814
+ }
82815
+
82816
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-list {
82817
+ display: grid;
82818
+ gap: 0.625rem;
82819
+ }
82820
+
82821
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line {
82822
+ display: grid;
82823
+ grid-template-columns: minmax(0, 1fr) auto;
82824
+ align-items: center;
82825
+ gap: 0.875rem;
82826
+ min-height: 4.75rem;
82827
+ padding: 0.875rem;
82828
+ border: 1px solid var(--er-border);
82829
+ border-radius: calc(var(--rb-block-radius) * 0.75);
82830
+ background: var(--er-control-bg);
82831
+ }
82832
+
82833
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line--disabled {
82834
+ color: var(--er-on-surface-disabled);
82835
+ background: var(--er-surface-muted);
82836
+ }
82837
+
82838
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-main {
82839
+ min-width: 0;
82840
+ display: grid;
82841
+ gap: 0.25rem;
82842
+ }
82843
+
82844
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-heading {
82845
+ display: flex;
82846
+ align-items: baseline;
82847
+ justify-content: space-between;
82848
+ gap: 0.75rem;
82849
+ }
82850
+
82851
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-name {
82852
+ min-width: 0;
82853
+ font-size: 0.9375rem;
82854
+ font-weight: 600;
82855
+ line-height: 1.3;
82856
+ overflow-wrap: anywhere;
82857
+ }
82858
+
82859
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-price {
82860
+ flex-shrink: 0;
82861
+ font-size: 0.875rem;
82862
+ font-weight: 600;
82863
+ line-height: 1.3;
82864
+ }
82865
+
82866
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-detail {
82867
+ margin: 0;
82868
+ color: var(--er-on-surface-muted);
82869
+ font-size: 0.8125rem;
82870
+ line-height: 1.35;
82871
+ overflow-wrap: anywhere;
82872
+ }
82873
+
82874
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary {
82875
+ padding: 0.75rem 0.875rem;
82876
+ border: 1px solid var(--er-summary-border);
82877
+ border-radius: calc(var(--rb-block-radius) * 0.75);
82878
+ background: var(--er-surface-muted);
82879
+ }
82880
+
82881
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary-title {
82882
+ font-size: 0.875rem;
82883
+ font-weight: 600;
82884
+ line-height: 1.35;
82885
+ }
82886
+
82887
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary-list {
82888
+ margin: 0.25rem 0 0;
82889
+ padding-left: 1.125rem;
82890
+ color: var(--er-on-surface-muted);
82891
+ font-size: 0.8125rem;
82892
+ line-height: 1.4;
82893
+ }
82894
+
82895
+ @container rb-site (max-width: 639px) {
82896
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
82897
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line {
82898
+ grid-template-columns: minmax(0, 1fr);
82899
+ align-items: stretch;
82900
+ }
82901
+
82902
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line .er-counter {
82903
+ justify-content: flex-start;
82904
+ }
82905
+ }
82906
+ }
82907
+
82631
82908
  /* Form inputs */
82632
82909
  :where(.theme-scope) :where([data-block="event-registration"]) .er-input {
82633
82910
  width: 100%;
@@ -91525,6 +91802,8 @@ var TAG_TEMPLATES = {
91525
91802
  siteNewsletter: "riverbank:site:{siteId}:newsletter",
91526
91803
  // Pages/routes (routable content)
91527
91804
  siteRoutableContent: "riverbank:site:{siteId}:routable-content",
91805
+ siteRedirects: "riverbank:site:{siteId}:redirects",
91806
+ siteRouteOutcomes: "riverbank:site:{siteId}:route-outcomes",
91528
91807
  routeById: "riverbank:route:{routeId}",
91529
91808
  pageById: "riverbank:page:{pageId}",
91530
91809
  workflowRunById: "riverbank:workflow-run:{runId}",
@@ -94981,6 +95260,18 @@ var ENDPOINT_DEFINITIONS = {
94981
95260
  auth: "public",
94982
95261
  responseKind: "json"
94983
95262
  },
95263
+ resolveRouteOutcome: {
95264
+ path: "/sites/{siteId}/route-outcome",
95265
+ method: "GET",
95266
+ tags: [
95267
+ TAG_TEMPLATES.siteRoutableContent,
95268
+ TAG_TEMPLATES.siteRedirects,
95269
+ TAG_TEMPLATES.siteRouteOutcomes
95270
+ ],
95271
+ auth: "public",
95272
+ responseKind: "json",
95273
+ errors: ["validation:invalid_input", "server:internal_error"]
95274
+ },
94984
95275
  getPageByPath: {
94985
95276
  path: "/sites/{siteId}/pages",
94986
95277
  method: "GET",
@@ -100136,6 +100427,22 @@ async function loadContent(params) {
100136
100427
  }
100137
100428
  const site = siteResult.value;
100138
100429
  const contentResponse = contentResult.value;
100430
+ return loadContentFromContentResponse({
100431
+ client,
100432
+ siteId,
100433
+ site,
100434
+ contentResponse,
100435
+ preview
100436
+ });
100437
+ }
100438
+ async function loadContentFromContentResponse(params) {
100439
+ const {
100440
+ client,
100441
+ siteId,
100442
+ site,
100443
+ contentResponse,
100444
+ preview = false
100445
+ } = params;
100139
100446
  const support = buildSiteRenderSupport(
100140
100447
  site,
100141
100448
  collectMediaAssetSidecar(contentResponse.mediaAssets)