@seatlayer/js 0.48.0 → 0.48.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -488,7 +488,7 @@ interface OrderStatusResult {
488
488
  }>;
489
489
  /** Hosted ticket page — the durable re-entry point after the modal closes. */
490
490
  ticketUrl?: string;
491
- /** Printable PDF, one page per ticket. */
491
+ /** Printable A4 PDF, up to three ticket cards per page. */
492
492
  pdfUrl?: string;
493
493
  }
494
494
  interface PubApiOptions {
@@ -1342,6 +1342,17 @@ interface SeatPickerOptions {
1342
1342
  * is shown only when BOTH this option and the theme flag are unset/false.
1343
1343
  */
1344
1344
  hideBadge?: boolean;
1345
+ /**
1346
+ * Hide the picker's event identity (logo, event name and venue/date metadata)
1347
+ * when the host surface already presents the same event heading. The hold
1348
+ * timer, sales status and modal close controls remain available. The identity
1349
+ * is restored automatically while the picker is full screen so it never
1350
+ * loses context on a small device or an expanded map. Default false.
1351
+ *
1352
+ * A mounted host can update this through `setEventDetailsHidden()` when its
1353
+ * own event chrome arrives asynchronously.
1354
+ */
1355
+ hideEventDetails?: boolean;
1345
1356
  /** Host theme overrides — see SeatPickerTheme. */
1346
1357
  theme?: SeatPickerTheme;
1347
1358
  /**
@@ -1658,6 +1669,8 @@ declare class SeatPicker {
1658
1669
  private fsFallback;
1659
1670
  private fsChangeHandler;
1660
1671
  private fsEscHandler;
1672
+ /** Host-level event chrome owns the duplicate identity outside full screen. */
1673
+ private eventDetailsHidden;
1661
1674
  /** True once we've asked the host page to pin us fullscreen (framed, no native). */
1662
1675
  private framedFs;
1663
1676
  /** Last height (px) posted to a host frame; dedupes redundant reports. */
@@ -2069,6 +2082,12 @@ declare class SeatPicker {
2069
2082
  * colours have not changed; safe to call on every render.
2070
2083
  */
2071
2084
  setMapTheme(map: PickerMapTheme | null): void;
2085
+ /**
2086
+ * Let a host suppress duplicate event identity after mount without remounting
2087
+ * the live picker (and therefore without disturbing a selection or hold).
2088
+ * Full-screen mode still restores the identity until the buyer exits it.
2089
+ */
2090
+ setEventDetailsHidden(hidden: boolean): void;
2072
2091
  /**
2073
2092
  * Replace the host pricing override AFTER mount, and repaint everything that
2074
2093
  * shows a price.
package/dist/index.d.ts CHANGED
@@ -488,7 +488,7 @@ interface OrderStatusResult {
488
488
  }>;
489
489
  /** Hosted ticket page — the durable re-entry point after the modal closes. */
490
490
  ticketUrl?: string;
491
- /** Printable PDF, one page per ticket. */
491
+ /** Printable A4 PDF, up to three ticket cards per page. */
492
492
  pdfUrl?: string;
493
493
  }
494
494
  interface PubApiOptions {
@@ -1342,6 +1342,17 @@ interface SeatPickerOptions {
1342
1342
  * is shown only when BOTH this option and the theme flag are unset/false.
1343
1343
  */
1344
1344
  hideBadge?: boolean;
1345
+ /**
1346
+ * Hide the picker's event identity (logo, event name and venue/date metadata)
1347
+ * when the host surface already presents the same event heading. The hold
1348
+ * timer, sales status and modal close controls remain available. The identity
1349
+ * is restored automatically while the picker is full screen so it never
1350
+ * loses context on a small device or an expanded map. Default false.
1351
+ *
1352
+ * A mounted host can update this through `setEventDetailsHidden()` when its
1353
+ * own event chrome arrives asynchronously.
1354
+ */
1355
+ hideEventDetails?: boolean;
1345
1356
  /** Host theme overrides — see SeatPickerTheme. */
1346
1357
  theme?: SeatPickerTheme;
1347
1358
  /**
@@ -1658,6 +1669,8 @@ declare class SeatPicker {
1658
1669
  private fsFallback;
1659
1670
  private fsChangeHandler;
1660
1671
  private fsEscHandler;
1672
+ /** Host-level event chrome owns the duplicate identity outside full screen. */
1673
+ private eventDetailsHidden;
1661
1674
  /** True once we've asked the host page to pin us fullscreen (framed, no native). */
1662
1675
  private framedFs;
1663
1676
  /** Last height (px) posted to a host frame; dedupes redundant reports. */
@@ -2069,6 +2082,12 @@ declare class SeatPicker {
2069
2082
  * colours have not changed; safe to call on every render.
2070
2083
  */
2071
2084
  setMapTheme(map: PickerMapTheme | null): void;
2085
+ /**
2086
+ * Let a host suppress duplicate event identity after mount without remounting
2087
+ * the live picker (and therefore without disturbing a selection or hold).
2088
+ * Full-screen mode still restores the identity until the buyer exits it.
2089
+ */
2090
+ setEventDetailsHidden(hidden: boolean): void;
2072
2091
  /**
2073
2092
  * Replace the host pricing override AFTER mount, and repaint everything that
2074
2093
  * shows a price.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SeatManager
3
- } from "./chunk-Q5QT3YLA.js";
3
+ } from "./chunk-SD6GL3DT.js";
4
4
  import {
5
5
  ACCESS_LINK_DEFAULTS,
6
6
  ChannelsMode,
@@ -2328,7 +2328,7 @@ async function loadHostedCheckout() {
2328
2328
  cdnChunkUrl("seatlayer-checkout.mjs")
2329
2329
  );
2330
2330
  }
2331
- return import("./hostedCheckout-SHQCWN5Y.js");
2331
+ return import("./hostedCheckout-F6C6VCCG.js");
2332
2332
  }
2333
2333
  function paymentsOffReason(reason) {
2334
2334
  return reason === "unavailable_for_event" || reason === "payments_off_for_event" ? reason : "not_configured";
@@ -2370,6 +2370,16 @@ var CSS = (
2370
2370
  .sl-close.on{display:inline-flex}
2371
2371
  .sl-close svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round}
2372
2372
 
2373
+ /* A page or popup may already own the event heading. In that case only the
2374
+ duplicate identity disappears; operational header controls stay available.
2375
+ Zero block padding lets an otherwise-empty header collapse completely. */
2376
+ .sl-picker[data-event-details-hidden="true"] .sl-head{padding-block:0;border-bottom-width:0}
2377
+ .sl-picker[data-event-details-hidden="true"] .sl-logo,
2378
+ .sl-picker[data-event-details-hidden="true"] .sl-head-info{display:none!important}
2379
+ .sl-picker[data-event-details-hidden="true"] .sl-hold-pill.on,
2380
+ .sl-picker[data-event-details-hidden="true"] .sl-closed-pill.on,
2381
+ .sl-picker[data-event-details-hidden="true"] .sl-close.on{margin-block:10px}
2382
+
2373
2383
  /* body */
2374
2384
  .sl-body{display:flex;flex:1;min-height:0}
2375
2385
  .sl-map{position:relative;flex:1;min-width:0}
@@ -2387,7 +2397,7 @@ var CSS = (
2387
2397
  .sl-picker[data-layout="narrow"] .sl-side{width:100%;border-left:0;border-top:1px solid var(--sl-line);
2388
2398
  flex:none;height:min(72%,480px);overflow:hidden;transition:height .3s cubic-bezier(.2,.8,.2,1);overscroll-behavior:contain}
2389
2399
  .sl-picker[data-layout="narrow"][data-sheet="open"][data-has-selection="false"] .sl-side{height:min(252px,52%)}
2390
- .sl-picker[data-layout="narrow"][data-sheet="peek"] .sl-side{height:86px;overflow:hidden}
2400
+ .sl-picker[data-layout="narrow"][data-sheet="peek"] .sl-side{height:76px;overflow:hidden}
2391
2401
  .sl-picker[data-layout="narrow"][data-sheet="peek"] .sl-side > :not(.sl-sheet-head){display:none}
2392
2402
  .sl-picker[data-layout="narrow"] .sl-tray{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
2393
2403
  .sl-picker[data-layout="narrow"] .sl-foot{position:static;background:var(--sl-bg)}
@@ -2422,9 +2432,10 @@ var CSS = (
2422
2432
  head is the tap/swipe toggle target (min 44px), so it reads as one control. */
2423
2433
  .sl-sheet-head{display:none;flex-direction:column;justify-content:center;padding:6px 12px 8px;min-height:56px;
2424
2434
  cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none;flex:none}
2425
- .sl-picker[data-layout="narrow"] .sl-sheet-head{display:flex}
2426
- .sl-sheet-grab{width:36px;height:4px;border-radius:999px;background:var(--sl-muted);opacity:.55;margin:2px auto 7px}
2427
- .sl-sheet-bar{display:flex;align-items:center;gap:10px;min-height:26px}
2435
+ .sl-picker[data-layout="narrow"] .sl-sheet-head{display:flex;min-height:64px;padding:4px 10px 6px}
2436
+ .sl-picker[data-layout="narrow"][data-sheet="peek"] .sl-sheet-head{height:100%}
2437
+ .sl-sheet-grab{width:36px;height:4px;border-radius:999px;background:var(--sl-muted);opacity:.55;margin:1px auto 5px}
2438
+ .sl-sheet-bar{display:flex;align-items:center;gap:8px;min-height:44px}
2428
2439
  .sl-sheet-peek{display:flex;align-items:center;gap:7px;flex:1;min-width:0;font-size:13px;font-weight:700;color:var(--sl-text);
2429
2440
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
2430
2441
  .sl-sheet-peek .sub{color:var(--sl-muted);font-weight:600}
@@ -2452,7 +2463,7 @@ var CSS = (
2452
2463
  .sl-picker[data-layout="narrow"][data-has-selection="true"] .sl-filtersec.has,
2453
2464
  .sl-picker[data-layout="narrow"][data-has-selection="true"] .sl-filters.has{display:none}
2454
2465
  /* Accessibility and colour-safety controls must remain reachable on phones.
2455
- Keep them out of the 86px peek, then reveal their consolidated row whenever
2466
+ Keep them out of the collapsed peek, then reveal their consolidated row whenever
2456
2467
  the buyer explicitly opens the ticket panel. */
2457
2468
  .sl-picker[data-layout="narrow"][data-sheet="open"] .sl-filtersec.has{display:block!important}
2458
2469
  .sl-picker[data-layout="narrow"][data-sheet="open"] .sl-filters.has{display:flex!important}
@@ -2595,15 +2606,10 @@ var CSS = (
2595
2606
  .sl-picker .sl-cta:disabled{background:var(--sl-surface);color:var(--sl-muted);opacity:1;
2596
2607
  cursor:not-allowed;filter:none;transform:none}
2597
2608
 
2598
- /* Chrome anchor regions (Feature 6) \u2014 every persistent map overlay is APPENDED
2609
+ /* Chrome anchor regions (Feature 6) \u2014 every interactive map overlay is APPENDED
2599
2610
  INTO one of these positioned flex containers and flows/stacks within it, so no
2600
- two pieces of chrome free-float on top of each other. Regions never overlap:
2601
- the top strip splits into left/center/right; rails + corners own their edge. */
2602
- /* align-items:center, not the flex default of stretch. Without it a short pill
2603
- beside a taller control (TEST MODE next to the Map/3D toggle) is stretched to
2604
- the row's height, so two pills that should read as a matched pair end up
2605
- different shapes on different baselines. Column regions set their own
2606
- cross-axis alignment below and are unaffected. */
2611
+ two controls free-float on top of each other. Regions never overlap: the top
2612
+ strip splits into left/center/right; rails + corners own their edge. */
2607
2613
  .sl-anchor{position:absolute;z-index:5;display:flex;align-items:center;gap:8px;pointer-events:none}
2608
2614
  .sl-anchor > *{pointer-events:auto}
2609
2615
  .sl-anchor[data-region="top-left"]{top:12px;left:12px;flex-wrap:wrap;max-width:38%}
@@ -2619,18 +2625,17 @@ var CSS = (
2619
2625
  .sl-picker[data-layout="narrow"] .sl-anchor[data-region="top-left"]{max-width:30%}
2620
2626
  .sl-picker[data-layout="narrow"] .sl-anchor[data-region="top-center"]{max-width:44%}
2621
2627
 
2622
- /* TEST MODE badge \u2014 a small pill in the top-right region (shrinks on narrow) */
2623
- /* align-self:stretch, not a hardcoded height: the badge sits beside the Map/3D
2624
- toggle, whose height comes from its own border + padding + button metrics.
2625
- Stretching matches that row exactly and keeps matching if the toggle ever
2626
- changes, while the badge's own inline-flex keeps the label centred inside
2627
- whatever height it gets. Alone in the region it simply takes its natural
2628
- size. */
2629
- .sl-testbadge{display:inline-flex;align-items:center;align-self:stretch;padding:0 12px;border-radius:999px;
2630
- font-size:10px;font-weight:800;letter-spacing:.1em;line-height:1;
2631
- text-transform:uppercase;white-space:nowrap;background:var(--sl-accent);color:var(--sl-accent-ink);
2632
- box-shadow:0 2px 8px rgba(0,0,0,.25)}
2633
- .sl-picker[data-layout="narrow"] .sl-testbadge{padding:0 8px;font-size:8.5px;letter-spacing:.06em}
2628
+ /* TEST MODE is environment context, not an action. A clipped corner ribbon
2629
+ keeps it persistent without impersonating a button or competing with Map/3D.
2630
+ The top-left interactive region moves below it only on test events. */
2631
+ .sl-testbadge{position:absolute;top:17px;left:-38px;z-index:6;width:142px;padding:5px 0;
2632
+ transform:rotate(-45deg);text-align:center;pointer-events:none;
2633
+ font-size:9.5px;font-weight:850;letter-spacing:.13em;line-height:1.2;text-transform:uppercase;
2634
+ white-space:nowrap;background:var(--sl-accent);color:var(--sl-accent-ink);
2635
+ box-shadow:0 2px 8px rgba(0,0,0,.28)}
2636
+ .sl-picker[data-event-mode="test"] .sl-anchor[data-region="top-left"]{top:96px}
2637
+ .sl-picker[data-layout="narrow"] .sl-testbadge{top:14px;left:-35px;width:128px;font-size:8.5px}
2638
+ .sl-picker[data-layout="narrow"][data-event-mode="test"] .sl-anchor[data-region="top-left"]{top:88px}
2634
2639
 
2635
2640
  /* zoom column (flows within the bottom-right region) */
2636
2641
  .sl-zoom{display:flex;flex-direction:column;gap:6px}
@@ -2865,10 +2870,15 @@ var CSS = (
2865
2870
  .sl-ba-actions{grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:7px}
2866
2871
  .sl-ba-actions button{min-height:36px;border-radius:9px;border:1px solid var(--sl-line);font-size:11.5px;font-weight:800}
2867
2872
  .sl-ba-actions .replace{border-color:var(--sl-accent);background:var(--sl-accent);color:var(--sl-accent-ink)}
2868
- .sl-picker[data-layout="narrow"] .sl-ba{padding:11px}
2873
+ .sl-picker[data-layout="narrow"] .sl-ba{padding:9px;gap:6px}
2874
+ .sl-picker[data-layout="narrow"] .sl-ba::after{display:none}
2875
+ .sl-picker[data-layout="narrow"] .sl-ba-title{font-size:12.5px}
2876
+ .sl-picker[data-layout="narrow"] .sl-ba-copy{display:none}
2869
2877
  .sl-picker[data-layout="narrow"] .sl-ba-copy .wide{display:none}
2870
2878
  .sl-picker[data-layout="narrow"] .sl-ba-copy .narrow{display:inline}
2871
- .sl-picker[data-layout="narrow"] .sl-ba select{min-height:44px}
2879
+ .sl-picker[data-layout="narrow"] .sl-ba select{min-height:40px}
2880
+ .sl-picker[data-layout="narrow"] .sl-ba-qty button{width:30px;height:30px}
2881
+ .sl-picker[data-layout="narrow"] .sl-ba-go{min-height:40px}
2872
2882
 
2873
2883
  /* screen-reader live region */
2874
2884
  .sl-sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@@ -3311,6 +3321,8 @@ var SeatPicker = class _SeatPicker {
3311
3321
  this.fsFallback = false;
3312
3322
  this.fsChangeHandler = null;
3313
3323
  this.fsEscHandler = null;
3324
+ /** Host-level event chrome owns the duplicate identity outside full screen. */
3325
+ this.eventDetailsHidden = false;
3314
3326
  /** True once we've asked the host page to pin us fullscreen (framed, no native). */
3315
3327
  this.framedFs = false;
3316
3328
  /** Last height (px) posted to a host frame; dedupes redundant reports. */
@@ -3333,6 +3345,7 @@ var SeatPicker = class _SeatPicker {
3333
3345
  if (!options.event || typeof options.event !== "string") throw new Error("seatmap: `event` key is required");
3334
3346
  if (!options.container) throw new Error("seatmap: `container` is required (or use SeatPicker.open())");
3335
3347
  this.opts = { ...options, confirmSelection: options.confirmSelection ?? true };
3348
+ this.eventDetailsHidden = !!options.hideEventDetails;
3336
3349
  this.hostPricing = options.pricing;
3337
3350
  this.apiBase = (options.apiBase ?? DEFAULT_API_BASE2).replace(/\/+$/, "");
3338
3351
  this.access = options.transport ? null : createBuyerAccessContext(options, {
@@ -3617,6 +3630,10 @@ var SeatPicker = class _SeatPicker {
3617
3630
  }
3618
3631
  syncFullscreenButtons() {
3619
3632
  const active = !!document.fullscreenElement || this.fsFallback || this.framedFs;
3633
+ const hideEventDetails = this.eventDetailsHidden && !active;
3634
+ this.root?.setAttribute("data-event-details-hidden", String(hideEventDetails));
3635
+ this.els.logo?.toggleAttribute("hidden", hideEventDetails);
3636
+ this.els.headInfo?.toggleAttribute("hidden", hideEventDetails);
3620
3637
  this.els.zfs?.setAttribute("aria-pressed", String(active));
3621
3638
  this.view3dEl?.querySelector(".sl-view3d-fs")?.setAttribute("aria-pressed", String(active));
3622
3639
  }
@@ -3760,7 +3777,7 @@ var SeatPicker = class _SeatPicker {
3760
3777
  root.innerHTML = `
3761
3778
  <div class="sl-head">
3762
3779
  <div class="sl-logo" data-ref="logo"></div>
3763
- <div class="sl-head-info">
3780
+ <div class="sl-head-info" data-ref="headInfo">
3764
3781
  <div class="sl-head-name" data-ref="name"></div>
3765
3782
  <div class="sl-head-meta" data-ref="meta"></div>
3766
3783
  </div>
@@ -3822,6 +3839,7 @@ var SeatPicker = class _SeatPicker {
3822
3839
  this.els[el.dataset.ref] = el;
3823
3840
  });
3824
3841
  this.mapHost = this.els.map;
3842
+ this.syncFullscreenButtons();
3825
3843
  void this.refreshOfferAvailability(false);
3826
3844
  if (this.api.availability) {
3827
3845
  this.offerVisibilityHandler = () => {
@@ -3934,6 +3952,7 @@ var SeatPicker = class _SeatPicker {
3934
3952
  this.els.boot.remove();
3935
3953
  this.startRealtime();
3936
3954
  this.salesClosed = !!info.salesClosed || !!this.opts.readOnly;
3955
+ root.dataset.eventMode = info.mode === "test" ? "test" : "live";
3937
3956
  this.controller.setViewMode(this.normalizeInitialView(this.opts.initialView));
3938
3957
  this.buildRegions();
3939
3958
  this.regions["bottom-right"].appendChild(this.els.zoom);
@@ -3943,7 +3962,7 @@ var SeatPicker = class _SeatPicker {
3943
3962
  badge.className = "sl-testbadge";
3944
3963
  badge.textContent = t2("picker.testMode");
3945
3964
  badge.setAttribute("aria-label", t2("picker.testMode"));
3946
- this.regions["top-right"].appendChild(badge);
3965
+ this.els.map.appendChild(badge);
3947
3966
  }
3948
3967
  const chartTheme = this.controller.doc?.theme;
3949
3968
  Object.entries(resolveTokens(chartTheme, this.opts.theme)).forEach(([k, v]) => root.style.setProperty(k, v));
@@ -6233,6 +6252,15 @@ var SeatPicker = class _SeatPicker {
6233
6252
  this.opts.theme = { ...this.opts.theme ?? {}, map: map ?? void 0 };
6234
6253
  this.controller.setMapTheme(map);
6235
6254
  }
6255
+ /**
6256
+ * Let a host suppress duplicate event identity after mount without remounting
6257
+ * the live picker (and therefore without disturbing a selection or hold).
6258
+ * Full-screen mode still restores the identity until the buyer exits it.
6259
+ */
6260
+ setEventDetailsHidden(hidden) {
6261
+ this.eventDetailsHidden = hidden;
6262
+ this.syncFullscreenButtons();
6263
+ }
6236
6264
  /**
6237
6265
  * Replace the host pricing override AFTER mount, and repaint everything that
6238
6266
  * shows a price.