@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
@@ -23822,6 +23822,9 @@ function resolveDiscountContext(input) {
23822
23822
  if (!input.eventRequiresPayment) {
23823
23823
  return null;
23824
23824
  }
23825
+ if (input.ticketsCount <= 0) {
23826
+ return null;
23827
+ }
23825
23828
  if (selection?.method && selection.method !== "stripe") {
23826
23829
  return null;
23827
23830
  }
@@ -44790,6 +44793,7 @@ function transformEligibilityResponse(response) {
44790
44793
  requiresPayment: eligibility.requiresPayment,
44791
44794
  pricingMode: eligibility.pricingMode,
44792
44795
  selectedTicketTypeId: eligibility.selectedTicketTypeId ?? null,
44796
+ ticketLines: eligibility.ticketLines ?? [],
44793
44797
  ticketTypes: eligibility.ticketTypes ?? [],
44794
44798
  isFull: eligibility.isFull,
44795
44799
  waitlistEnabled: eligibility.waitlistEnabled,
@@ -44857,6 +44861,77 @@ var init_utils5 = __esm({
44857
44861
  }
44858
44862
  });
44859
44863
 
44864
+ // ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
44865
+ function normalizeTicketSelectionLines(lines) {
44866
+ const quantitiesByTicketType = /* @__PURE__ */ new Map();
44867
+ for (const line of lines) {
44868
+ const quantity = Math.floor(line.quantity);
44869
+ if (quantity <= 0) continue;
44870
+ const key = line.ticketTypeId ?? null;
44871
+ quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
44872
+ }
44873
+ return [...quantitiesByTicketType.entries()].map(([ticketTypeId, quantity]) => ({
44874
+ ticketTypeId,
44875
+ quantity
44876
+ }));
44877
+ }
44878
+ function getTicketSelectionTotal(lines) {
44879
+ return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
44880
+ }
44881
+ function getTicketLineQuantity(lines, ticketTypeId) {
44882
+ return normalizeTicketSelectionLines(lines).find((line) => line.ticketTypeId === ticketTypeId)?.quantity ?? 0;
44883
+ }
44884
+ function getSingleSelectedTicketTypeId(lines) {
44885
+ const normalized = normalizeTicketSelectionLines(lines);
44886
+ return normalized.length === 1 ? normalized[0]?.ticketTypeId ?? null : null;
44887
+ }
44888
+ function setTicketLineQuantity(input) {
44889
+ const nextQuantity = Math.max(0, Math.floor(input.quantity));
44890
+ const normalized = normalizeTicketSelectionLines(input.lines).filter((line) => line.ticketTypeId !== input.ticketTypeId);
44891
+ if (nextQuantity <= 0) {
44892
+ return normalized;
44893
+ }
44894
+ return [
44895
+ ...normalized,
44896
+ {
44897
+ ticketTypeId: input.ticketTypeId,
44898
+ quantity: nextQuantity
44899
+ }
44900
+ ];
44901
+ }
44902
+ function getTicketTypeLineMax(input) {
44903
+ const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
44904
+ const maxByBlock = input.maxTickets - otherSelectedQuantity;
44905
+ const maxByEvent = input.availableSpots == null ? input.maxTickets : input.availableSpots - otherSelectedQuantity;
44906
+ const maxByTicketType = input.ticketTypeRemainingCapacity ?? input.maxTickets;
44907
+ return Math.max(0, Math.min(maxByBlock, maxByEvent, maxByTicketType));
44908
+ }
44909
+ function calculateTicketSelectionSubtotal(input) {
44910
+ return normalizeTicketSelectionLines(input.lines).reduce((subtotal, line) => {
44911
+ const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
44912
+ const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
44913
+ return subtotal + Math.max(0, unitPriceCents) * line.quantity;
44914
+ }, 0);
44915
+ }
44916
+ function buildTicketSelectionSummaryLines(input) {
44917
+ return normalizeTicketSelectionLines(input.lines).map((line) => {
44918
+ const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
44919
+ const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
44920
+ return {
44921
+ ticketTypeId: line.ticketTypeId,
44922
+ label: ticketType?.name ?? input.fallbackLabel,
44923
+ quantity: line.quantity,
44924
+ unitPriceCents,
44925
+ subtotalCents: Math.max(0, unitPriceCents) * line.quantity
44926
+ };
44927
+ });
44928
+ }
44929
+ var init_ticketSelectionLines = __esm({
44930
+ "../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts"() {
44931
+ "use strict";
44932
+ }
44933
+ });
44934
+
44860
44935
  // ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
44861
44936
  function eligibilityLookupReducer(state, action) {
44862
44937
  switch (action.type) {
@@ -44971,6 +45046,7 @@ function usePortalAuth() {
44971
45046
  }
44972
45047
  function useEligibility(params) {
44973
45048
  const api = useBlockApi();
45049
+ const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
44974
45050
  const [state, dispatch] = useReducer8(
44975
45051
  eligibilityLookupReducer,
44976
45052
  initialEligibilityLookupState
@@ -44984,7 +45060,8 @@ function useEligibility(params) {
44984
45060
  dispatch({ type: "reset" });
44985
45061
  return;
44986
45062
  }
44987
- if (!params.occurrenceId || !params.email.trim()) {
45063
+ const ticketSelections = JSON.parse(ticketSelectionsKey);
45064
+ if (!params.occurrenceId || !params.email.trim() || ticketSelections.length === 0) {
44988
45065
  requestIdRef.current += 1;
44989
45066
  dispatch({ type: "reset" });
44990
45067
  return;
@@ -44996,10 +45073,9 @@ function useEligibility(params) {
44996
45073
  const result = await api.checkEligibility({
44997
45074
  occurrenceId: params.occurrenceId,
44998
45075
  attendanceMode: params.attendanceMode ?? void 0,
44999
- ticketTypeId: params.ticketTypeId ?? void 0,
45076
+ ticketSelections,
45000
45077
  selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
45001
- email: params.email.trim().toLowerCase(),
45002
- ticketsCount: params.ticketsCount
45078
+ email: params.email.trim().toLowerCase()
45003
45079
  });
45004
45080
  if (cancelled || requestIdRef.current !== requestId) return;
45005
45081
  dispatch({
@@ -45018,7 +45094,15 @@ function useEligibility(params) {
45018
45094
  return () => {
45019
45095
  cancelled = true;
45020
45096
  };
45021
- }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
45097
+ }, [
45098
+ api,
45099
+ params.enabled,
45100
+ params.occurrenceId,
45101
+ params.attendanceMode,
45102
+ ticketSelectionsKey,
45103
+ params.selectedSlidingAmount,
45104
+ params.email
45105
+ ]);
45022
45106
  return {
45023
45107
  state,
45024
45108
  eligibility: state.eligibility,
@@ -45075,6 +45159,7 @@ var init_hooks = __esm({
45075
45159
  "use strict";
45076
45160
  init_api();
45077
45161
  init_utils5();
45162
+ init_ticketSelectionLines();
45078
45163
  init_hooks_state();
45079
45164
  }
45080
45165
  });
@@ -45100,9 +45185,15 @@ function savePendingRegistration(siteId, occurrenceId, data) {
45100
45185
  }
45101
45186
  try {
45102
45187
  const key = getStorageKey(siteId, occurrenceId);
45188
+ const ticketSelections = normalizeTicketSelectionLines(data.ticketSelections);
45189
+ if (ticketSelections.length === 0) {
45190
+ console.warn("[sessionStorage] No ticket selections to save, skipping registration state");
45191
+ return;
45192
+ }
45103
45193
  const entry = {
45104
45194
  ...data,
45105
- version: 3,
45195
+ ticketSelections,
45196
+ version: 4,
45106
45197
  timestamp: Date.now()
45107
45198
  };
45108
45199
  sessionStorage.setItem(key, JSON.stringify(entry));
@@ -45148,8 +45239,8 @@ function parseAndValidateEntry(stored, key) {
45148
45239
  return null;
45149
45240
  }
45150
45241
  const version = raw.version;
45151
- if (version !== 1 && version !== 2 && version !== 3) {
45152
- console.warn("[sessionStorage] Unknown version, ignoring entry");
45242
+ if (version !== 4) {
45243
+ console.warn("[sessionStorage] Outdated version, ignoring entry");
45153
45244
  sessionStorage.removeItem(key);
45154
45245
  return null;
45155
45246
  }
@@ -45165,34 +45256,12 @@ function parseAndValidateEntry(stored, key) {
45165
45256
  sessionStorage.removeItem(key);
45166
45257
  return null;
45167
45258
  }
45168
- if (entry.version === 1) {
45169
- const legacy = entry;
45170
- return {
45171
- version: 3,
45172
- attendeeId: legacy.attendeeId,
45173
- formData: legacy.formData,
45174
- ticketsCount: legacy.ticketsCount,
45175
- selectedEventId: legacy.selectedEventId,
45176
- selectedAttendanceMode: null,
45177
- selectedTicketTypeId: null,
45178
- paymentSelection: { method: legacy.paymentMethod },
45179
- timestamp: legacy.timestamp
45180
- };
45181
- }
45182
- if (entry.version === 2) {
45183
- return {
45184
- version: 3,
45185
- attendeeId: entry.attendeeId,
45186
- formData: entry.formData,
45187
- ticketsCount: entry.ticketsCount,
45188
- selectedEventId: entry.selectedEventId,
45189
- selectedAttendanceMode: null,
45190
- selectedTicketTypeId: null,
45191
- paymentSelection: entry.paymentSelection,
45192
- timestamp: entry.timestamp
45193
- };
45259
+ const ticketSelections = normalizeTicketSelectionLines(entry.ticketSelections);
45260
+ if (ticketSelections.length === 0 || getTicketSelectionTotal(ticketSelections) <= 0) {
45261
+ sessionStorage.removeItem(key);
45262
+ return null;
45194
45263
  }
45195
- return entry;
45264
+ return { ...entry, ticketSelections };
45196
45265
  } catch {
45197
45266
  console.warn("[sessionStorage] Failed to parse entry, removing");
45198
45267
  sessionStorage.removeItem(key);
@@ -45224,8 +45293,9 @@ function cleanupStaleRegistrations() {
45224
45293
  const stored = sessionStorage.getItem(key);
45225
45294
  if (!stored) continue;
45226
45295
  const entry = JSON.parse(stored);
45227
- const age = Date.now() - entry.timestamp;
45228
- if (age > STALE_THRESHOLD_MS) {
45296
+ const timestamp = typeof entry.timestamp === "number" ? entry.timestamp : NaN;
45297
+ const age = Date.now() - timestamp;
45298
+ if (!Number.isFinite(timestamp) || age > STALE_THRESHOLD_MS) {
45229
45299
  keysToRemove.push(key);
45230
45300
  }
45231
45301
  } catch {
@@ -45246,6 +45316,7 @@ var STORAGE_PREFIX, STALE_THRESHOLD_MS;
45246
45316
  var init_sessionStorage = __esm({
45247
45317
  "../blocks/src/system/runtime/nodes/event-registration/sessionStorage.ts"() {
45248
45318
  "use strict";
45319
+ init_ticketSelectionLines();
45249
45320
  STORAGE_PREFIX = "riverbank:event-registration:";
45250
45321
  STALE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
45251
45322
  }
@@ -45335,14 +45406,16 @@ function getEventAttendanceModeLabel2(mode) {
45335
45406
  }
45336
45407
  }
45337
45408
  function TicketCounter(props2) {
45338
- const { ticketsCount, maxAllowed, onTicketsChange } = props2;
45409
+ const { ticketsCount, maxAllowed, label, onTicketsChange } = props2;
45410
+ const minAllowed = props2.minAllowed ?? 1;
45339
45411
  return /* @__PURE__ */ jsxs66("div", { className: "er-row er-counter", children: [
45340
45412
  /* @__PURE__ */ jsx93(
45341
45413
  "button",
45342
45414
  {
45343
45415
  type: "button",
45344
- onClick: () => onTicketsChange(Math.max(1, ticketsCount - 1)),
45345
- disabled: ticketsCount <= 1,
45416
+ "aria-label": `Decrease ${label}`,
45417
+ onClick: () => onTicketsChange(Math.max(minAllowed, ticketsCount - 1)),
45418
+ disabled: ticketsCount <= minAllowed,
45346
45419
  className: "er-counter-btn",
45347
45420
  children: "-"
45348
45421
  }
@@ -45352,6 +45425,7 @@ function TicketCounter(props2) {
45352
45425
  "button",
45353
45426
  {
45354
45427
  type: "button",
45428
+ "aria-label": `Increase ${label}`,
45355
45429
  onClick: () => onTicketsChange(Math.min(maxAllowed, ticketsCount + 1)),
45356
45430
  disabled: ticketsCount >= maxAllowed,
45357
45431
  className: "er-counter-btn",
@@ -45404,14 +45478,86 @@ function SlidingScaleAmountField(props2) {
45404
45478
  props2.message ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: props2.message }) : null
45405
45479
  ] });
45406
45480
  }
45407
- function getTicketTypeCounterAvailabilityLabel(input) {
45408
- if (input.selectedRemainingCapacity !== null) {
45409
- return `${input.selectedRemainingCapacity} remaining for this ticket type`;
45410
- }
45411
- if (input.eventAvailableSpots != null) {
45412
- return `${input.eventAvailableSpots} spots available`;
45413
- }
45414
- return null;
45481
+ function TicketTypeQuantityRows(props2) {
45482
+ const totalSelectedQuantity = getTicketSelectionTotal(props2.ticketSelections);
45483
+ const selectedTicketTypes = props2.ticketTypes.filter(
45484
+ (ticketType) => getTicketLineQuantity(props2.ticketSelections, ticketType.id) > 0
45485
+ );
45486
+ return /* @__PURE__ */ jsxs66("div", { className: "er-ticket-lines", children: [
45487
+ /* @__PURE__ */ jsx93("div", { className: "er-ticket-line-list", role: "list", "aria-label": "Tickets", children: props2.ticketTypes.map((ticketType) => {
45488
+ const quantity = getTicketLineQuantity(props2.ticketSelections, ticketType.id);
45489
+ const disabled = ticketType.availability.kind === "unavailable";
45490
+ const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
45491
+ const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, props2.currency) : "Free";
45492
+ const maxAllowed = disabled ? 0 : getTicketTypeLineMax({
45493
+ currentQuantity: quantity,
45494
+ totalSelectedQuantity,
45495
+ maxTickets: props2.maxTickets,
45496
+ availableSpots: props2.availableSpots,
45497
+ ticketTypeRemainingCapacity: ticketType.availability.remainingCapacity
45498
+ });
45499
+ return /* @__PURE__ */ jsxs66(
45500
+ "div",
45501
+ {
45502
+ className: `er-ticket-line${disabled ? " er-ticket-line--disabled" : ""}`,
45503
+ role: "listitem",
45504
+ children: [
45505
+ /* @__PURE__ */ jsxs66("div", { className: "er-ticket-line-main", children: [
45506
+ /* @__PURE__ */ jsxs66("div", { className: "er-ticket-line-heading", children: [
45507
+ /* @__PURE__ */ jsx93("span", { className: "er-ticket-line-name", children: ticketType.name }),
45508
+ /* @__PURE__ */ jsx93("span", { className: "er-ticket-line-price", children: priceLabel })
45509
+ ] }),
45510
+ ticketType.description ? /* @__PURE__ */ jsx93("p", { className: "er-ticket-line-detail", children: ticketType.description }) : null,
45511
+ availabilityLabel ? /* @__PURE__ */ jsx93("p", { className: "er-ticket-line-detail", children: availabilityLabel }) : ticketType.availability.remainingCapacity !== null ? /* @__PURE__ */ jsxs66("p", { className: "er-ticket-line-detail", children: [
45512
+ ticketType.availability.remainingCapacity,
45513
+ " remaining for this ticket type"
45514
+ ] }) : null
45515
+ ] }),
45516
+ /* @__PURE__ */ jsx93(
45517
+ TicketCounter,
45518
+ {
45519
+ ticketsCount: quantity,
45520
+ minAllowed: 0,
45521
+ maxAllowed,
45522
+ label: ticketType.name,
45523
+ onTicketsChange: (nextQuantity) => {
45524
+ props2.onTicketSelectionsChange?.(setTicketLineQuantity({
45525
+ lines: props2.ticketSelections,
45526
+ ticketTypeId: ticketType.id,
45527
+ quantity: nextQuantity
45528
+ }));
45529
+ }
45530
+ }
45531
+ )
45532
+ ]
45533
+ },
45534
+ ticketType.id
45535
+ );
45536
+ }) }),
45537
+ /* @__PURE__ */ jsx93(
45538
+ TicketCounterLimit,
45539
+ {
45540
+ maximumLabel: `${props2.maxTickets} tickets maximum`,
45541
+ availabilityLabel: props2.availableSpots != null ? `${props2.availableSpots} spots available` : null
45542
+ }
45543
+ ),
45544
+ selectedTicketTypes.length > 0 ? /* @__PURE__ */ jsxs66("div", { className: "er-ticket-line-summary", "aria-live": "polite", children: [
45545
+ /* @__PURE__ */ jsxs66("div", { className: "er-ticket-line-summary-title", children: [
45546
+ totalSelectedQuantity,
45547
+ " ticket",
45548
+ totalSelectedQuantity === 1 ? "" : "s",
45549
+ " selected"
45550
+ ] }),
45551
+ /* @__PURE__ */ jsx93("ul", { className: "er-ticket-line-summary-list", children: selectedTicketTypes.map((ticketType) => {
45552
+ const quantity = getTicketLineQuantity(props2.ticketSelections, ticketType.id);
45553
+ return /* @__PURE__ */ jsxs66("li", { children: [
45554
+ quantity,
45555
+ " x ",
45556
+ ticketType.name
45557
+ ] }, ticketType.id);
45558
+ }) })
45559
+ ] }) : props2.hasAvailableTicketTypes ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "Choose at least one ticket to continue." }) : /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." })
45560
+ ] });
45415
45561
  }
45416
45562
  function getAttendanceModeDetail(attendanceMode) {
45417
45563
  if (attendanceMode.availableSpots === null) {
@@ -45429,6 +45575,7 @@ function AttendanceModeTiles(props2) {
45429
45575
  "button",
45430
45576
  {
45431
45577
  type: "button",
45578
+ "aria-pressed": isSelected,
45432
45579
  className: `er-payment-tile${isSelected ? " er-payment-tile--selected" : ""}`,
45433
45580
  onClick: () => props2.onAttendanceModeChange?.(attendanceMode.mode),
45434
45581
  children: [
@@ -45466,6 +45613,7 @@ var init_TicketSelectionStep = __esm({
45466
45613
  init_src();
45467
45614
  init_pricing();
45468
45615
  init_utils5();
45616
+ init_ticketSelectionLines();
45469
45617
  TicketSelectionStep = ({
45470
45618
  event,
45471
45619
  occurrenceContext: _occurrenceContext,
@@ -45473,8 +45621,9 @@ var init_TicketSelectionStep = __esm({
45473
45621
  onAttendanceModeChange,
45474
45622
  ticketsCount,
45475
45623
  maxTickets,
45476
- selectedTicketTypeId = null,
45477
- onTicketTypeChange,
45624
+ visibleTicketTypes: visibleTicketTypesOverride,
45625
+ ticketSelections = [],
45626
+ onTicketSelectionsChange,
45478
45627
  slidingScale = null,
45479
45628
  selectedSlidingAmountInput = "",
45480
45629
  slidingScaleSelectionMessage = null,
@@ -45492,28 +45641,22 @@ var init_TicketSelectionStep = __esm({
45492
45641
  const eventPricingMode = eventPricing ? publicEventPricingMode(eventPricing) : void 0;
45493
45642
  const eventPricingCurrency = eventPricing ? publicEventPricingCurrency(eventPricing) : null;
45494
45643
  const usesTicketTypes = eventPricingMode === "ticket_types" && !canJoinWaitlist;
45495
- const visibleTicketTypes = usesTicketTypes ? getVisibleTicketTypes({
45644
+ const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
45496
45645
  event,
45497
45646
  eligibility: null,
45498
45647
  selectedAttendanceMode
45499
45648
  }) : [];
45500
- const selectedTicketType = usesTicketTypes ? visibleTicketTypes.find((ticketType) => ticketType.id === selectedTicketTypeId) ?? null : null;
45501
45649
  const implicitTicketType = usesTicketTypes ? getImplicitSingleAvailableTicketType(visibleTicketTypes) : null;
45502
- const effectiveSelectedTicketType = selectedTicketType ?? implicitTicketType;
45503
- const shouldShowTicketTypeTiles = usesTicketTypes && implicitTicketType === null;
45504
- const selectedRemainingCapacity = effectiveSelectedTicketType?.availability.remainingCapacity ?? null;
45505
- const noSellableTicketTypes = usesTicketTypes && (visibleTicketTypes.length === 0 || visibleTicketTypes.every((ticketType) => ticketType.availability.kind === "unavailable"));
45650
+ const noVisibleTicketTypes = usesTicketTypes && visibleTicketTypes.length === 0;
45651
+ const hasAvailableTicketTypes = usesTicketTypes && visibleTicketTypes.some((ticketType) => ticketType.availability.kind === "available");
45652
+ const aggregateRemainingCapacity = implicitTicketType?.availability.remainingCapacity ?? null;
45506
45653
  const maxAllowed = getMaxAllowedTicketCount({
45507
45654
  canJoinWaitlist,
45508
45655
  usesTicketTypes,
45509
45656
  maxTickets,
45510
45657
  availableSpots,
45511
- selectedTicketTypeRemainingCapacity: selectedRemainingCapacity,
45512
- hasSelectedTicketType: effectiveSelectedTicketType !== null
45513
- });
45514
- const selectedTicketTypeAvailabilityLabel = getTicketTypeCounterAvailabilityLabel({
45515
- selectedRemainingCapacity,
45516
- eventAvailableSpots: event?.availableSpots
45658
+ selectedTicketTypeRemainingCapacity: aggregateRemainingCapacity,
45659
+ hasSelectedTicketType: implicitTicketType !== null
45517
45660
  });
45518
45661
  const eventAvailabilityLabel = !canJoinWaitlist && event?.availableSpots != null ? `${event.availableSpots} spots available` : null;
45519
45662
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) {
@@ -45530,7 +45673,7 @@ var init_TicketSelectionStep = __esm({
45530
45673
  /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "Choose whether you want to attend in person or online." })
45531
45674
  ] });
45532
45675
  }
45533
- if (isSoldOut && !canJoinWaitlist && !usesTicketTypes) {
45676
+ if (isSoldOut && !canJoinWaitlist) {
45534
45677
  return /* @__PURE__ */ jsxs66("div", { className: "er-stack", children: [
45535
45678
  /* @__PURE__ */ jsx93("h3", { className: "er-title", children: "Sold Out" }),
45536
45679
  /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "Sorry you missed out! This event is fully booked." })
@@ -45548,52 +45691,21 @@ var init_TicketSelectionStep = __esm({
45548
45691
  }
45549
45692
  )
45550
45693
  ] }) : null,
45551
- usesTicketTypes ? /* @__PURE__ */ jsxs66(Fragment18, { children: [
45552
- shouldShowTicketTypeTiles ? /* @__PURE__ */ jsxs66(Fragment18, { children: [
45553
- /* @__PURE__ */ jsx93("h3", { className: "er-title", children: "Choose a ticket type" }),
45554
- /* @__PURE__ */ jsx93("div", { className: "er-payment-tiles", role: "list", "aria-label": "Ticket types", children: visibleTicketTypes.map((ticketType) => {
45555
- const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
45556
- const disabled = ticketType.availability.kind === "unavailable";
45557
- const isSelected = selectedTicketTypeId === ticketType.id;
45558
- const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2) : "Free";
45559
- return /* @__PURE__ */ jsx93("div", { role: "listitem", children: /* @__PURE__ */ jsxs66(
45560
- "button",
45561
- {
45562
- type: "button",
45563
- className: `er-payment-tile${isSelected && !disabled ? " er-payment-tile--selected" : ""}${disabled ? " er-payment-tile--disabled" : ""}`,
45564
- disabled,
45565
- onClick: () => onTicketTypeChange?.(ticketType.id),
45566
- children: [
45567
- /* @__PURE__ */ jsx93("div", { className: "er-payment-tile-label", children: ticketType.name }),
45568
- /* @__PURE__ */ jsx93("div", { className: "er-payment-tile-detail", children: priceLabel }),
45569
- ticketType.description ? /* @__PURE__ */ jsx93("div", { className: "er-payment-tile-detail", children: ticketType.description }) : null,
45570
- availabilityLabel ? /* @__PURE__ */ jsx93("div", { className: "er-payment-tile-detail", children: availabilityLabel }) : null
45571
- ]
45572
- }
45573
- ) }, ticketType.id);
45574
- }) })
45575
- ] }) : null,
45576
- noSellableTicketTypes ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : !effectiveSelectedTicketType ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "Select one ticket type to continue." }) : effectiveSelectedTicketType.availability.kind === "unavailable" ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: getTicketTypeAvailabilityLabel(effectiveSelectedTicketType) ?? "This ticket type is unavailable." }) : /* @__PURE__ */ jsxs66(Fragment18, { children: [
45577
- /* @__PURE__ */ jsx93("h3", { className: "er-title", children: "How many tickets?" }),
45578
- /* @__PURE__ */ jsxs66("div", { className: "er-ticket-counter-group", children: [
45579
- /* @__PURE__ */ jsx93(
45580
- TicketCounter,
45581
- {
45582
- ticketsCount,
45583
- maxAllowed,
45584
- onTicketsChange
45585
- }
45586
- ),
45587
- /* @__PURE__ */ jsx93(
45588
- TicketCounterLimit,
45589
- {
45590
- maximumLabel: `${maxAllowed} tickets maximum`,
45591
- availabilityLabel: selectedTicketTypeAvailabilityLabel
45592
- }
45593
- )
45594
- ] })
45595
- ] })
45596
- ] }) : /* @__PURE__ */ jsxs66(Fragment18, { children: [
45694
+ usesTicketTypes ? /* @__PURE__ */ jsx93(Fragment18, { children: noVisibleTicketTypes ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : /* @__PURE__ */ jsxs66(Fragment18, { children: [
45695
+ /* @__PURE__ */ jsx93("h3", { className: "er-title", children: "Choose tickets" }),
45696
+ /* @__PURE__ */ jsx93(
45697
+ TicketTypeQuantityRows,
45698
+ {
45699
+ ticketTypes: visibleTicketTypes,
45700
+ ticketSelections,
45701
+ maxTickets,
45702
+ availableSpots,
45703
+ currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
45704
+ hasAvailableTicketTypes,
45705
+ onTicketSelectionsChange
45706
+ }
45707
+ )
45708
+ ] }) }) : /* @__PURE__ */ jsxs66(Fragment18, { children: [
45597
45709
  slidingScale ? /* @__PURE__ */ jsx93(
45598
45710
  SlidingScaleAmountField,
45599
45711
  {
@@ -45611,6 +45723,7 @@ var init_TicketSelectionStep = __esm({
45611
45723
  {
45612
45724
  ticketsCount,
45613
45725
  maxAllowed,
45726
+ label: canJoinWaitlist ? "waitlist spots" : "tickets",
45614
45727
  onTicketsChange
45615
45728
  }
45616
45729
  ),
@@ -46134,7 +46247,7 @@ var init_PaymentSelectionStep = __esm({
46134
46247
  }) => {
46135
46248
  const occurrenceId = occurrenceContext?.id ?? event?.registrationOccurrenceId;
46136
46249
  const selectedMethod = selectedSelection.method;
46137
- const totalPrice = eligibility?.price ? eligibility.price * ticketsCount : 0;
46250
+ const totalPrice = eligibility?.price ?? 0;
46138
46251
  const canShowDirectPaymentOptions = Boolean(
46139
46252
  eligibility?.eligible && eligibility.canPayDirectly && eligibility.price
46140
46253
  );
@@ -46616,8 +46729,9 @@ function EventRegistrationWizardContent(props2) {
46616
46729
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
46617
46730
  ticketsCount: wizard.ticketsCount,
46618
46731
  maxTickets: wizard.maxTicketsNum,
46619
- selectedTicketTypeId: wizard.selectedTicketTypeId,
46620
- onTicketTypeChange: wizard.setSelectedTicketTypeId,
46732
+ visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
46733
+ ticketSelections: wizard.selectedTicketLines,
46734
+ onTicketSelectionsChange: wizard.setSelectedTicketLines,
46621
46735
  slidingScale: wizard.selectedEventSlidingScale,
46622
46736
  selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
46623
46737
  slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
@@ -46738,9 +46852,9 @@ function EventRegistrationWizardActions(props2) {
46738
46852
  const isWaitingForEligibility = wizard.portalAuthState === "authenticated" && wizard.eligibilityLoading;
46739
46853
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
46740
46854
  const hasExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistration !== null;
46741
- const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidSelectedTicketType;
46855
+ const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
46742
46856
  const isContinueDisabled = isWaitingForEligibility || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
46743
- const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket type" : "Continue";
46857
+ const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket" : "Continue";
46744
46858
  return /* @__PURE__ */ jsxs76("div", { className: "er-actions", children: [
46745
46859
  !wizard.hasPreSelectedContext && /* @__PURE__ */ jsx105("button", { type: "button", onClick: () => wizard.setStep("select-event"), className: "er-back-btn", children: "\u2190 Back" }),
46746
46860
  /* @__PURE__ */ jsx105(
@@ -46838,13 +46952,17 @@ function EventRegistrationSummaryBar(props2) {
46838
46952
  const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
46839
46953
  const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
46840
46954
  const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
46841
- const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
46842
46955
  const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
46843
46956
  const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
46844
- const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
46957
+ const fallbackSubtotalCents = Math.max(
46958
+ 0,
46959
+ ((summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0) * wizard.ticketsCount
46960
+ );
46961
+ const subtotalCents = Math.max(0, wizard.ticketSelectionSubtotalCents ?? fallbackSubtotalCents);
46845
46962
  const autoAppliedDiscount = wizard.discountCode.trim().length > 0 ? null : wizard.autoAppliedDiscount;
46846
46963
  const autoAppliedDiscountCents = Math.max(0, autoAppliedDiscount?.computedAmountCents ?? 0);
46847
46964
  const discountedTotalCents = Math.max(0, subtotalCents - autoAppliedDiscountCents);
46965
+ const selectedLineSummary = (wizard.ticketSelectionSummaryLines ?? []).filter((line) => line.ticketTypeId !== null).map((line) => `${line.quantity} x ${line.label}`).join(", ");
46848
46966
  const selectedDirectPaymentOption = getSelectedDirectPaymentOption({
46849
46967
  wizard,
46850
46968
  totalCents: discountedTotalCents,
@@ -46881,9 +46999,9 @@ function EventRegistrationSummaryBar(props2) {
46881
46999
  /* @__PURE__ */ jsx106("h4", { className: "er-summary-bar-event", children: summaryTitle }),
46882
47000
  /* @__PURE__ */ jsxs77("span", { className: "er-summary-bar-meta", children: [
46883
47001
  summaryDate && formatEventDateTime(summaryDate, { timeZone: summaryTimeZone }),
46884
- wizard.selectedTicketType ? /* @__PURE__ */ jsxs77(Fragment22, { children: [
47002
+ selectedLineSummary ? /* @__PURE__ */ jsxs77(Fragment22, { children: [
46885
47003
  " \xB7 ",
46886
- wizard.selectedTicketType.name
47004
+ selectedLineSummary
46887
47005
  ] }) : null,
46888
47006
  wizard.step !== "select-event" && wizard.step !== "select-tickets" && wizard.ticketsCount > 0 && /* @__PURE__ */ jsxs77(Fragment22, { children: [
46889
47007
  " \xB7 ",
@@ -46897,8 +47015,8 @@ function EventRegistrationSummaryBar(props2) {
46897
47015
  teamMemberNames.join(", ")
46898
47016
  ] })
46899
47017
  ] }),
46900
- summaryPrice > 0 && /* @__PURE__ */ jsx106("div", { className: "er-summary-bar-pricing", children: productMethod ? /* @__PURE__ */ jsxs77(Fragment22, { children: [
46901
- /* @__PURE__ */ jsx106("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(summaryPrice * wizard.ticketsCount, summaryCurrency) }),
47018
+ subtotalCents > 0 && /* @__PURE__ */ jsx106("div", { className: "er-summary-bar-pricing", children: productMethod ? /* @__PURE__ */ jsxs77(Fragment22, { children: [
47019
+ /* @__PURE__ */ jsx106("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(subtotalCents, summaryCurrency) }),
46902
47020
  /* @__PURE__ */ jsx106("div", { className: "er-summary-bar-included", children: wizard.paymentSelection.method === "pass" || wizard.paymentSelection.method === "pass_bundle" ? "1 pass credit" : "Included in membership" })
46903
47021
  ] }) : flexibleBalanceSummary ? /* @__PURE__ */ jsxs77(Fragment22, { children: [
46904
47022
  flexibleBalanceSummary.total ? /* @__PURE__ */ jsxs77("div", { className: "er-summary-bar-product-detail", children: [
@@ -47174,7 +47292,7 @@ function useEventRegistrationStripeReturn(options) {
47174
47292
  setRegistrationResult,
47175
47293
  setSelectedEvent,
47176
47294
  setSelectedAttendanceMode,
47177
- setSelectedTicketTypeId,
47295
+ setTicketSelections,
47178
47296
  setStep,
47179
47297
  setTicketsCount,
47180
47298
  step
@@ -47193,13 +47311,13 @@ function useEventRegistrationStripeReturn(options) {
47193
47311
  const pending = getPendingRegistration(siteId, occurrenceId || void 0);
47194
47312
  if (!pending) return;
47195
47313
  setFormData(pending.formData);
47196
- setTicketsCount(pending.ticketsCount);
47314
+ setTicketSelections(pending.ticketSelections);
47315
+ setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
47197
47316
  if (pending.selectedEventId) {
47198
47317
  const event = events.find((e) => e.publicEventId === pending.selectedEventId) ?? null;
47199
47318
  if (event) setSelectedEvent(event);
47200
47319
  }
47201
47320
  setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
47202
- setSelectedTicketTypeId(pending.selectedTicketTypeId ?? null);
47203
47321
  setPaymentSelection(pending.paymentSelection);
47204
47322
  if (registrationStatus === "cancelled") {
47205
47323
  setStep("select-payment");
@@ -47244,6 +47362,7 @@ var init_useEventRegistrationStripeReturn = __esm({
47244
47362
  init_usePaymentVerification();
47245
47363
  init_shared6();
47246
47364
  init_sessionStorage();
47365
+ init_ticketSelectionLines();
47247
47366
  }
47248
47367
  });
47249
47368
 
@@ -47260,6 +47379,10 @@ function useEventRegistrationSubmit(options) {
47260
47379
  }
47261
47380
  options.setStep("submitting");
47262
47381
  try {
47382
+ const ticketSelections = normalizeTicketSelectionLines(options.ticketSelections);
47383
+ if (ticketSelections.length === 0) {
47384
+ throw new Error("Choose at least one ticket to continue.");
47385
+ }
47263
47386
  const isBundle = method === "pass_bundle" || method === "membership_bundle";
47264
47387
  const bundleProductId = isBundle ? passId || membershipId : void 0;
47265
47388
  const selectionSnapshot = (() => {
@@ -47288,11 +47411,10 @@ function useEventRegistrationSubmit(options) {
47288
47411
  const result = await options.api.registerForEvent({
47289
47412
  occurrenceId: submitOccurrenceId,
47290
47413
  attendanceMode: options.selectedAttendanceMode ?? void 0,
47291
- ticketTypeId: options.selectedTicketTypeId ?? void 0,
47414
+ ticketSelections,
47292
47415
  selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
47293
47416
  email: options.formData.email.trim().toLowerCase(),
47294
47417
  name: options.formData.name.trim(),
47295
- ticketsCount: options.ticketsCount,
47296
47418
  phone: options.formData.phone.trim() || void 0,
47297
47419
  notes: options.formData.notes.trim() || void 0,
47298
47420
  altchaSolution: options.altchaSolution,
@@ -47337,10 +47459,9 @@ function useEventRegistrationSubmit(options) {
47337
47459
  savePendingRegistration(siteId, submitOccurrenceId, {
47338
47460
  attendeeId: result.attendeeId,
47339
47461
  formData: options.formData,
47340
- ticketsCount: options.ticketsCount,
47462
+ ticketSelections,
47341
47463
  selectedEventId: options.registrationTarget?.selectedEventId ?? null,
47342
47464
  selectedAttendanceMode: options.selectedAttendanceMode,
47343
- selectedTicketTypeId: options.selectedTicketTypeId ?? null,
47344
47465
  paymentSelection: selectionSnapshot
47345
47466
  });
47346
47467
  }
@@ -47394,6 +47515,7 @@ var init_useEventRegistrationSubmit = __esm({
47394
47515
  "use strict";
47395
47516
  "use client";
47396
47517
  init_sessionStorage();
47518
+ init_ticketSelectionLines();
47397
47519
  }
47398
47520
  });
47399
47521
 
@@ -47460,7 +47582,6 @@ function useEventRegistrationWizard(options) {
47460
47582
  createInitialRegistrationFlowState
47461
47583
  );
47462
47584
  const step = flowState.step;
47463
- const ticketsCount = flowState.ticketsCount;
47464
47585
  const paymentSelection = flowState.paymentSelection;
47465
47586
  const [selectedEvent, setSelectedEvent] = useState9(preSelectedEvent ?? null);
47466
47587
  const [formData, setFormData] = useState9({ name: "", email: "", phone: "", notes: "" });
@@ -47471,7 +47592,7 @@ function useEventRegistrationWizard(options) {
47471
47592
  const [selectedAttendanceMode, setSelectedAttendanceMode] = useState9(
47472
47593
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
47473
47594
  );
47474
- const [selectedTicketTypeId, setSelectedTicketTypeId] = useState9(null);
47595
+ const [selectedTicketLines, setSelectedTicketLines] = useState9([]);
47475
47596
  const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState9(() => {
47476
47597
  const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
47477
47598
  return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
@@ -47507,14 +47628,51 @@ function useEventRegistrationWizard(options) {
47507
47628
  [options.occurrenceContext, selectedEvent]
47508
47629
  );
47509
47630
  const occurrenceId = registrationTarget?.occurrenceId ?? "";
47631
+ const currentEvent = selectedEvent ?? preSelectedEvent;
47632
+ const currentEventPricing = currentEvent ? resolveRuntimeEventPricing(currentEvent) : null;
47633
+ const currentEventUsesTicketTypes = currentEventPricing !== null && publicEventPricingMode(currentEventPricing) === "ticket_types";
47634
+ const selectedModeAvailability = selectedAttendanceMode ? (currentEvent?.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
47635
+ const currentAvailableSpots = selectedModeAvailability?.availableSpots ?? currentEvent?.availableSpots;
47636
+ const currentWaitlistEnabled = selectedModeAvailability?.waitlistEnabled ?? currentEvent?.waitlistEnabled ?? false;
47637
+ const currentCanJoinWaitlist = currentAvailableSpots === 0 && currentWaitlistEnabled === true;
47638
+ const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
47639
+ const eventTicketTypesForSelection = useMemo12(
47640
+ () => getVisibleTicketTypes({
47641
+ event: currentEvent,
47642
+ eligibility: null,
47643
+ selectedAttendanceMode
47644
+ }),
47645
+ [currentEvent, selectedAttendanceMode]
47646
+ );
47647
+ const normalizedSelectedTicketLines = useMemo12(
47648
+ () => normalizeTicketSelectionLines(selectedTicketLines),
47649
+ [selectedTicketLines]
47650
+ );
47651
+ const ticketTypeSelectionTotal = useMemo12(
47652
+ () => getTicketSelectionTotal(normalizedSelectedTicketLines),
47653
+ [normalizedSelectedTicketLines]
47654
+ );
47655
+ const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
47656
+ const ticketSelections = useMemo12(() => {
47657
+ if (waitlistClaim.claim) {
47658
+ return [{ ticketTypeId: null, quantity: 1 }];
47659
+ }
47660
+ if (usesTicketTypeSelections) {
47661
+ return normalizedSelectedTicketLines;
47662
+ }
47663
+ return [{ ticketTypeId: null, quantity: ticketsCount }];
47664
+ }, [normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, waitlistClaim.claim]);
47665
+ useEffect17(() => {
47666
+ if (flowState.ticketsCount === ticketsCount) return;
47667
+ dispatchFlow({ type: "set-tickets-count", ticketsCount });
47668
+ }, [flowState.ticketsCount, ticketsCount]);
47510
47669
  const eligibilityResult = useEligibility({
47511
47670
  enabled: portalAuthState === "authenticated" || step === "enter-details" || step === "select-payment",
47512
47671
  occurrenceId,
47513
47672
  attendanceMode: selectedAttendanceMode,
47514
- ticketTypeId: selectedTicketTypeId,
47673
+ ticketSelections,
47515
47674
  selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
47516
- email: formData.email,
47517
- ticketsCount
47675
+ email: formData.email
47518
47676
  });
47519
47677
  const existingRegistrationResult = useExistingEventRegistration({
47520
47678
  isAuthenticated: portalAuthState === "authenticated",
@@ -47620,7 +47778,7 @@ function useEventRegistrationWizard(options) {
47620
47778
  setTicketsCount,
47621
47779
  setSelectedEvent,
47622
47780
  setSelectedAttendanceMode,
47623
- setSelectedTicketTypeId,
47781
+ setTicketSelections: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
47624
47782
  setPaymentSelection: (selection) => dispatchFlow({ type: "set-manual-payment-selection", selection }),
47625
47783
  setPendingAttendeeId,
47626
47784
  setStep,
@@ -47633,20 +47791,21 @@ function useEventRegistrationWizard(options) {
47633
47791
  }, [selectedEvent, preSelectedEvent]);
47634
47792
  const visibleTicketTypes = useMemo12(
47635
47793
  () => getVisibleTicketTypes({
47636
- event: selectedEvent ?? preSelectedEvent,
47794
+ event: currentEvent,
47637
47795
  eligibility,
47638
47796
  selectedAttendanceMode
47639
47797
  }),
47640
- [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility]
47798
+ [currentEvent, selectedAttendanceMode, eligibility]
47641
47799
  );
47800
+ const singleSelectedTicketTypeId = getSingleSelectedTicketTypeId(normalizedSelectedTicketLines);
47642
47801
  const selectedTicketType = useMemo12(
47643
47802
  () => findSelectedTicketType({
47644
- event: selectedEvent ?? preSelectedEvent,
47803
+ event: currentEvent,
47645
47804
  eligibility,
47646
- selectedTicketTypeId,
47805
+ selectedTicketTypeId: singleSelectedTicketTypeId,
47647
47806
  selectedAttendanceMode
47648
47807
  }),
47649
- [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
47808
+ [currentEvent, eligibility, selectedAttendanceMode, singleSelectedTicketTypeId]
47650
47809
  );
47651
47810
  const selectedSlidingAmount = useMemo12(
47652
47811
  () => parseCurrencyInputToCents(selectedSlidingAmountInput),
@@ -47661,37 +47820,44 @@ function useEventRegistrationWizard(options) {
47661
47820
  selectedAmount: selectedSlidingAmount
47662
47821
  });
47663
47822
  const ticketTypeSelectionRequired = useMemo12(() => {
47664
- const event = selectedEvent ?? preSelectedEvent;
47823
+ const event = currentEvent;
47665
47824
  if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
47666
47825
  return false;
47667
47826
  }
47668
47827
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) {
47669
47828
  return false;
47670
47829
  }
47671
- const selectedModeAvailability = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
47672
- const canJoinWaitlist = (selectedModeAvailability?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability?.waitlistEnabled ?? event.waitlistEnabled) === true;
47830
+ const selectedModeAvailability2 = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
47831
+ const canJoinWaitlist = (selectedModeAvailability2?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability2?.waitlistEnabled ?? event.waitlistEnabled) === true;
47673
47832
  return !canJoinWaitlist;
47674
- }, [selectedAttendanceMode, selectedEvent, preSelectedEvent]);
47675
- const hasValidSelectedTicketType = !ticketTypeSelectionRequired || Boolean(
47676
- selectedTicketType && selectedTicketType.availability.kind === "available"
47677
- );
47833
+ }, [currentEvent, selectedAttendanceMode]);
47834
+ const hasValidTicketSelection = !ticketTypeSelectionRequired || normalizedSelectedTicketLines.length > 0 && normalizedSelectedTicketLines.every((line) => {
47835
+ if (!line.ticketTypeId) return false;
47836
+ const ticketType = visibleTicketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null;
47837
+ return ticketType?.availability.kind === "available";
47838
+ });
47678
47839
  useEffect17(() => {
47679
- const event = selectedEvent ?? preSelectedEvent;
47680
- if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
47681
- if (selectedTicketTypeId !== null) {
47682
- setSelectedTicketTypeId(null);
47840
+ if (!usesTicketTypeSelections) {
47841
+ if (selectedTicketLines.length > 0) {
47842
+ setSelectedTicketLines([]);
47683
47843
  }
47684
47844
  return;
47685
47845
  }
47686
- const implicitTicketType = getImplicitSingleAvailableTicketType(visibleTicketTypes);
47687
- if (implicitTicketType && selectedTicketTypeId !== implicitTicketType.id) {
47688
- setSelectedTicketTypeId(implicitTicketType.id);
47846
+ const availableTicketTypes = eventTicketTypesForSelection.filter(
47847
+ (ticketType) => ticketType.availability.kind === "available"
47848
+ );
47849
+ const implicitTicketType = getImplicitSingleAvailableTicketType(eventTicketTypesForSelection);
47850
+ if (implicitTicketType && normalizedSelectedTicketLines.length === 0) {
47851
+ setSelectedTicketLines([{ ticketTypeId: implicitTicketType.id, quantity: 1 }]);
47689
47852
  return;
47690
47853
  }
47691
- if (selectedTicketTypeId && !visibleTicketTypes.some((ticketType) => ticketType.id === selectedTicketTypeId)) {
47692
- setSelectedTicketTypeId(null);
47854
+ const filteredLines = normalizedSelectedTicketLines.filter(
47855
+ (line) => line.ticketTypeId && availableTicketTypes.some((ticketType) => ticketType.id === line.ticketTypeId)
47856
+ );
47857
+ if (filteredLines.length !== normalizedSelectedTicketLines.length) {
47858
+ setSelectedTicketLines(filteredLines);
47693
47859
  }
47694
- }, [selectedEvent, preSelectedEvent, selectedTicketTypeId, visibleTicketTypes]);
47860
+ }, [eventTicketTypesForSelection, normalizedSelectedTicketLines, selectedTicketLines.length, usesTicketTypeSelections]);
47695
47861
  useEffect17(() => {
47696
47862
  if (!requireGuestDetails) {
47697
47863
  if (guests.length > 0) setGuests([]);
@@ -47735,21 +47901,20 @@ function useEventRegistrationWizard(options) {
47735
47901
  return resolveEventRequiresPayment({
47736
47902
  eligibility,
47737
47903
  selectedTicketType,
47738
- event: selectedEvent ?? preSelectedEvent
47904
+ event: currentEvent
47739
47905
  });
47740
47906
  },
47741
47907
  [
47742
47908
  eligibility,
47743
47909
  selectedTicketType,
47744
- selectedEvent,
47745
- preSelectedEvent,
47910
+ currentEvent,
47746
47911
  selectedEventSlidingScale,
47747
47912
  selectedSlidingAmount
47748
47913
  ]
47749
47914
  );
47750
47915
  const handleDetailsComplete = async () => {
47751
- if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
47752
- const message = "Select a ticket type to continue.";
47916
+ if (ticketTypeSelectionRequired && !hasValidTicketSelection) {
47917
+ const message = "Choose at least one available ticket to continue.";
47753
47918
  setErrorMessage(message);
47754
47919
  setStep("error");
47755
47920
  return { ok: false, reason: "blocked", message };
@@ -47834,27 +47999,39 @@ function useEventRegistrationWizard(options) {
47834
47999
  const discountContext = useMemo12(
47835
48000
  () => resolveDiscountContext({
47836
48001
  paymentSelection,
47837
- event: selectedEvent ?? preSelectedEvent,
48002
+ event: currentEvent,
47838
48003
  eventRequiresPayment,
47839
48004
  ticketsCount
47840
48005
  }),
47841
- [eventRequiresPayment, paymentSelection, selectedEvent, preSelectedEvent, ticketsCount]
48006
+ [currentEvent, eventRequiresPayment, paymentSelection, ticketsCount]
48007
+ );
48008
+ const fallbackUnitPriceCents = useMemo12(
48009
+ () => currentEvent ? publicEventScalarPrice(resolveRuntimeEventPricing(currentEvent)) ?? 0 : 0,
48010
+ [currentEvent]
48011
+ );
48012
+ const ticketSelectionSubtotalCents = useMemo12(() => {
48013
+ if (!usesTicketTypeSelections) {
48014
+ return Math.max(0, eligibility?.price ?? fallbackUnitPriceCents * ticketsCount);
48015
+ }
48016
+ return calculateTicketSelectionSubtotal({
48017
+ lines: normalizedSelectedTicketLines,
48018
+ ticketTypes: visibleTicketTypes,
48019
+ fallbackUnitPriceCents
48020
+ });
48021
+ }, [eligibility, fallbackUnitPriceCents, normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, visibleTicketTypes]);
48022
+ const ticketSelectionSummaryLines = useMemo12(
48023
+ () => buildTicketSelectionSummaryLines({
48024
+ lines: ticketSelections,
48025
+ ticketTypes: visibleTicketTypes,
48026
+ fallbackLabel: "Ticket",
48027
+ fallbackUnitPriceCents
48028
+ }),
48029
+ [fallbackUnitPriceCents, ticketSelections, visibleTicketTypes]
47842
48030
  );
47843
48031
  const discountSubtotalCents = useMemo12(() => {
47844
48032
  if (discountContext?.type !== "event") return void 0;
47845
- const event = selectedEvent ?? preSelectedEvent;
47846
- const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
47847
- return Math.max(0, eventPriceCents * ticketsCount);
47848
- }, [
47849
- discountContext,
47850
- selectedTicketType,
47851
- eligibility,
47852
- selectedEvent,
47853
- preSelectedEvent,
47854
- selectedEventSlidingScale,
47855
- selectedSlidingAmount,
47856
- ticketsCount
47857
- ]);
48033
+ return ticketSelectionSubtotalCents;
48034
+ }, [discountContext, ticketSelectionSubtotalCents]);
47858
48035
  const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
47859
48036
  const selectionMethod = paymentSelection.method;
47860
48037
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -47862,9 +48039,8 @@ function useEventRegistrationWizard(options) {
47862
48039
  api,
47863
48040
  registrationTarget,
47864
48041
  selectedAttendanceMode,
47865
- selectedTicketTypeId,
48042
+ ticketSelections,
47866
48043
  selectedSlidingAmount,
47867
- ticketsCount,
47868
48044
  formData,
47869
48045
  altchaSolution,
47870
48046
  requireGuestDetails,
@@ -47885,12 +48061,12 @@ function useEventRegistrationWizard(options) {
47885
48061
  setSelectedAttendanceMode(
47886
48062
  (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
47887
48063
  );
47888
- setSelectedTicketTypeId(null);
48064
+ setSelectedTicketLines([]);
47889
48065
  dispatchFlow({ type: "event-changed", hasPreSelectedContext: true });
47890
48066
  };
47891
48067
  const handleRetry = () => {
47892
48068
  dispatchFlow({ type: "reset", hasPreSelectedContext });
47893
- setSelectedTicketTypeId(null);
48069
+ setSelectedTicketLines([]);
47894
48070
  setSelectedSlidingAmountInput("");
47895
48071
  setSelectedAttendanceMode(
47896
48072
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
@@ -47926,17 +48102,20 @@ function useEventRegistrationWizard(options) {
47926
48102
  setTicketsCount,
47927
48103
  selectedAttendanceMode,
47928
48104
  setSelectedAttendanceMode,
47929
- selectedTicketTypeId,
47930
- setSelectedTicketTypeId,
48105
+ ticketSelections,
48106
+ selectedTicketLines: normalizedSelectedTicketLines,
48107
+ setSelectedTicketLines: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
47931
48108
  selectedSlidingAmountInput,
47932
48109
  setSelectedSlidingAmountInput,
47933
48110
  selectedSlidingAmount,
47934
48111
  selectedEventSlidingScale,
47935
48112
  slidingScaleSelectionMessage,
47936
48113
  selectedTicketType,
48114
+ ticketSelectionSummaryLines,
48115
+ ticketSelectionSubtotalCents,
47937
48116
  visibleTicketTypes,
47938
48117
  ticketTypeSelectionRequired,
47939
- hasValidSelectedTicketType,
48118
+ hasValidTicketSelection,
47940
48119
  eventRequiresPayment,
47941
48120
  formData,
47942
48121
  setFormData,
@@ -48006,6 +48185,7 @@ var init_useEventRegistrationWizard = __esm({
48006
48185
  init_useEventRegistrationSubmit();
48007
48186
  init_useDiscountCodeUi();
48008
48187
  init_utils5();
48188
+ init_ticketSelectionLines();
48009
48189
  init_registrationStateMachine();
48010
48190
  init_event_registration_headless_state();
48011
48191
  init_registrationDerivations();
@@ -55724,6 +55904,8 @@ var TAG_TEMPLATES = {
55724
55904
  siteNewsletter: "riverbank:site:{siteId}:newsletter",
55725
55905
  // Pages/routes (routable content)
55726
55906
  siteRoutableContent: "riverbank:site:{siteId}:routable-content",
55907
+ siteRedirects: "riverbank:site:{siteId}:redirects",
55908
+ siteRouteOutcomes: "riverbank:site:{siteId}:route-outcomes",
55727
55909
  routeById: "riverbank:route:{routeId}",
55728
55910
  pageById: "riverbank:page:{pageId}",
55729
55911
  workflowRunById: "riverbank:workflow-run:{runId}",
@@ -59180,6 +59362,18 @@ var ENDPOINT_DEFINITIONS = {
59180
59362
  auth: "public",
59181
59363
  responseKind: "json"
59182
59364
  },
59365
+ resolveRouteOutcome: {
59366
+ path: "/sites/{siteId}/route-outcome",
59367
+ method: "GET",
59368
+ tags: [
59369
+ TAG_TEMPLATES.siteRoutableContent,
59370
+ TAG_TEMPLATES.siteRedirects,
59371
+ TAG_TEMPLATES.siteRouteOutcomes
59372
+ ],
59373
+ auth: "public",
59374
+ responseKind: "json",
59375
+ errors: ["validation:invalid_input", "server:internal_error"]
59376
+ },
59183
59377
  getPageByPath: {
59184
59378
  path: "/sites/{siteId}/pages",
59185
59379
  method: "GET",
@@ -88804,6 +88998,103 @@ var containerResponsiveThemeCss = `/*
88804
88998
  line-height: 1.35;
88805
88999
  }
88806
89000
 
89001
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-lines {
89002
+ display: grid;
89003
+ gap: 0.75rem;
89004
+ }
89005
+
89006
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-list {
89007
+ display: grid;
89008
+ gap: 0.625rem;
89009
+ }
89010
+
89011
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line {
89012
+ display: grid;
89013
+ grid-template-columns: minmax(0, 1fr) auto;
89014
+ align-items: center;
89015
+ gap: 0.875rem;
89016
+ min-height: 4.75rem;
89017
+ padding: 0.875rem;
89018
+ border: 1px solid var(--er-border);
89019
+ border-radius: calc(var(--rb-block-radius) * 0.75);
89020
+ background: var(--er-control-bg);
89021
+ }
89022
+
89023
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line--disabled {
89024
+ color: var(--er-on-surface-disabled);
89025
+ background: var(--er-surface-muted);
89026
+ }
89027
+
89028
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-main {
89029
+ min-width: 0;
89030
+ display: grid;
89031
+ gap: 0.25rem;
89032
+ }
89033
+
89034
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-heading {
89035
+ display: flex;
89036
+ align-items: baseline;
89037
+ justify-content: space-between;
89038
+ gap: 0.75rem;
89039
+ }
89040
+
89041
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-name {
89042
+ min-width: 0;
89043
+ font-size: 0.9375rem;
89044
+ font-weight: 600;
89045
+ line-height: 1.3;
89046
+ overflow-wrap: anywhere;
89047
+ }
89048
+
89049
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-price {
89050
+ flex-shrink: 0;
89051
+ font-size: 0.875rem;
89052
+ font-weight: 600;
89053
+ line-height: 1.3;
89054
+ }
89055
+
89056
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-detail {
89057
+ margin: 0;
89058
+ color: var(--er-on-surface-muted);
89059
+ font-size: 0.8125rem;
89060
+ line-height: 1.35;
89061
+ overflow-wrap: anywhere;
89062
+ }
89063
+
89064
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary {
89065
+ padding: 0.75rem 0.875rem;
89066
+ border: 1px solid var(--er-summary-border);
89067
+ border-radius: calc(var(--rb-block-radius) * 0.75);
89068
+ background: var(--er-surface-muted);
89069
+ }
89070
+
89071
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary-title {
89072
+ font-size: 0.875rem;
89073
+ font-weight: 600;
89074
+ line-height: 1.35;
89075
+ }
89076
+
89077
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line-summary-list {
89078
+ margin: 0.25rem 0 0;
89079
+ padding-left: 1.125rem;
89080
+ color: var(--er-on-surface-muted);
89081
+ font-size: 0.8125rem;
89082
+ line-height: 1.4;
89083
+ }
89084
+
89085
+ @container rb-site (max-width: 639px) {
89086
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
89087
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line {
89088
+ grid-template-columns: minmax(0, 1fr);
89089
+ align-items: stretch;
89090
+ }
89091
+
89092
+ :where(.theme-scope) :where([data-block="event-registration"]) .er-ticket-line .er-counter {
89093
+ justify-content: flex-start;
89094
+ }
89095
+ }
89096
+ }
89097
+
88807
89098
  /* Form inputs */
88808
89099
  :where(.theme-scope) :where([data-block="event-registration"]) .er-input {
88809
89100
  width: 100%;
@@ -99685,7 +99976,7 @@ var SimpleCache = class {
99685
99976
  };
99686
99977
 
99687
99978
  // src/version.ts
99688
- var SDK_VERSION = "0.94.0";
99979
+ var SDK_VERSION = "0.95.0";
99689
99980
 
99690
99981
  // src/client/error.ts
99691
99982
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -99846,6 +100137,7 @@ function attachResilienceStatusToError(error, resilienceStatus) {
99846
100137
  var PUBLIC_ENDPOINT_NAMES2 = [
99847
100138
  "getSite",
99848
100139
  "getContentByPath",
100140
+ "resolveRouteOutcome",
99849
100141
  "listPublishedEntries",
99850
100142
  "getPublishedEntryPreview",
99851
100143
  "getPublicFormById",
@@ -99882,6 +100174,17 @@ var API_ENDPOINTS2 = Object.freeze({
99882
100174
  auth: "public",
99883
100175
  responseKind: "json"
99884
100176
  },
100177
+ resolveRouteOutcome: {
100178
+ path: "/sites/{siteId}/route-outcome",
100179
+ method: "GET",
100180
+ tags: [
100181
+ "riverbank:site:{siteId}:routable-content",
100182
+ "riverbank:site:{siteId}:redirects",
100183
+ "riverbank:site:{siteId}:route-outcomes"
100184
+ ],
100185
+ auth: "public",
100186
+ responseKind: "json"
100187
+ },
99885
100188
  listPublishedEntries: {
99886
100189
  path: "/public/content/{siteId}/{type}/entries",
99887
100190
  method: "GET",
@@ -100045,6 +100348,10 @@ var RUNTIME_CACHE_DURABILITY_OVERRIDES = {
100045
100348
  kind: "durable-public-stale",
100046
100349
  staleTtlSec: DEFAULT_STALE_TTL_SEC
100047
100350
  },
100351
+ resolveRouteOutcome: {
100352
+ kind: "memory-only",
100353
+ reason: "durable_rollout_pending"
100354
+ },
100048
100355
  listPublishedEntries: {
100049
100356
  kind: "memory-only",
100050
100357
  reason: "durable_rollout_pending"
@@ -101746,6 +102053,19 @@ function createRiverbankClient(config) {
101746
102053
  { signal }
101747
102054
  );
101748
102055
  },
102056
+ async resolveRouteOutcome(params) {
102057
+ const { siteId, path, preview = false, signal } = params;
102058
+ if (!siteId || !path) {
102059
+ throw new Error("resolveRouteOutcome() requires siteId and path");
102060
+ }
102061
+ return unwrapResponse(
102062
+ await apiClient({
102063
+ endpoint: "resolveRouteOutcome",
102064
+ params: { siteId, path, preview: String(preview) },
102065
+ options: { signal }
102066
+ })
102067
+ );
102068
+ },
101749
102069
  async getAllPublishedRoutes(params) {
101750
102070
  const { siteId, signal } = params;
101751
102071
  if (!siteId) {