@seatlayer/core 0.2.0 → 0.4.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.
package/dist/index.d.cts CHANGED
@@ -659,6 +659,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
659
659
  private statusById;
660
660
  private catColor;
661
661
  private theme;
662
+ /** Effective selection/hover ring color — resolved per chart in setChart(). */
663
+ private effSelection;
662
664
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
663
665
  private colorblind;
664
666
  /** Category order from the doc — the stable index into the CB palette. */
@@ -886,6 +888,16 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
886
888
  private addCentredLabel;
887
889
  private isSelectable;
888
890
  private toggleSeat;
891
+ /**
892
+ * Selection/hover ring color. An explicit theme.selectionColor always wins;
893
+ * otherwise auto-contrast against the effective canvas background — the
894
+ * designer renders on dark (white ring reads), but light-themed hosts (e.g.
895
+ * the DesiPass buyer picker on cream) made the white ring invisible and
896
+ * selected seats looked *disabled*. theme.background is checked first, then
897
+ * the container's computed CSS background (walking up past transparent
898
+ * ancestors). Unknown/unparseable backgrounds keep the dark default.
899
+ */
900
+ private resolveSelectionColor;
889
901
  private setSelected;
890
902
  private wireInteraction;
891
903
  /**
@@ -953,6 +965,17 @@ interface PickerSeat {
953
965
  /** The chosen tier's id — defaults to the first tier; absent when no tiers. */
954
966
  tierId?: string;
955
967
  }
968
+ /**
969
+ * Rich hover payload for seat tooltips — the PickerSeat plus everything a
970
+ * buyer-facing popover needs: category label + swatch color, live status and
971
+ * the chart currency. Emitted by `onSeatHover` (null on hover-out).
972
+ */
973
+ interface SeatHoverDetails extends PickerSeat {
974
+ categoryLabel: string;
975
+ categoryColor: string;
976
+ status: SeatStatus;
977
+ currency: string;
978
+ }
956
979
  interface HoldConflict {
957
980
  label: string;
958
981
  status: string;
@@ -1052,6 +1075,12 @@ interface PickerCallbacks extends RendererCallbacks {
1052
1075
  onBook?: (bookingRef: string) => void;
1053
1076
  /** Any live seat-status change arrived (delta or snapshot) — e.g. to recount "N left". */
1054
1077
  onStatusChange?: () => void;
1078
+ /**
1079
+ * Mouse hover moved onto a seat (null on hover-out) — the seat enriched with
1080
+ * category label/color, resolved price and live status, ready for a tooltip.
1081
+ * Fires alongside the raw renderer-level `onHover`.
1082
+ */
1083
+ onSeatHover?: (details: SeatHoverDetails | null) => void;
1055
1084
  /** The server declared the event closed (a 409 event_closed). */
1056
1085
  onSalesClosed?: () => void;
1057
1086
  /**
@@ -1221,6 +1250,8 @@ declare class PickerController {
1221
1250
  private sectionSummary;
1222
1251
  destroy(): void;
1223
1252
  private toSeat;
1253
+ /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */
1254
+ private describeSeat;
1224
1255
  private priceFor;
1225
1256
  private tiersFor;
1226
1257
  /**
@@ -1330,4 +1361,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
1330
1361
  /** Bare symbol for input adornments ("€", "$", "₹"). */
1331
1362
  declare function currencySymbol(currency?: string): string;
1332
1363
 
1333
- export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
1364
+ export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
package/dist/index.d.ts CHANGED
@@ -659,6 +659,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
659
659
  private statusById;
660
660
  private catColor;
661
661
  private theme;
662
+ /** Effective selection/hover ring color — resolved per chart in setChart(). */
663
+ private effSelection;
662
664
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
663
665
  private colorblind;
664
666
  /** Category order from the doc — the stable index into the CB palette. */
@@ -886,6 +888,16 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
886
888
  private addCentredLabel;
887
889
  private isSelectable;
888
890
  private toggleSeat;
891
+ /**
892
+ * Selection/hover ring color. An explicit theme.selectionColor always wins;
893
+ * otherwise auto-contrast against the effective canvas background — the
894
+ * designer renders on dark (white ring reads), but light-themed hosts (e.g.
895
+ * the DesiPass buyer picker on cream) made the white ring invisible and
896
+ * selected seats looked *disabled*. theme.background is checked first, then
897
+ * the container's computed CSS background (walking up past transparent
898
+ * ancestors). Unknown/unparseable backgrounds keep the dark default.
899
+ */
900
+ private resolveSelectionColor;
889
901
  private setSelected;
890
902
  private wireInteraction;
891
903
  /**
@@ -953,6 +965,17 @@ interface PickerSeat {
953
965
  /** The chosen tier's id — defaults to the first tier; absent when no tiers. */
954
966
  tierId?: string;
955
967
  }
968
+ /**
969
+ * Rich hover payload for seat tooltips — the PickerSeat plus everything a
970
+ * buyer-facing popover needs: category label + swatch color, live status and
971
+ * the chart currency. Emitted by `onSeatHover` (null on hover-out).
972
+ */
973
+ interface SeatHoverDetails extends PickerSeat {
974
+ categoryLabel: string;
975
+ categoryColor: string;
976
+ status: SeatStatus;
977
+ currency: string;
978
+ }
956
979
  interface HoldConflict {
957
980
  label: string;
958
981
  status: string;
@@ -1052,6 +1075,12 @@ interface PickerCallbacks extends RendererCallbacks {
1052
1075
  onBook?: (bookingRef: string) => void;
1053
1076
  /** Any live seat-status change arrived (delta or snapshot) — e.g. to recount "N left". */
1054
1077
  onStatusChange?: () => void;
1078
+ /**
1079
+ * Mouse hover moved onto a seat (null on hover-out) — the seat enriched with
1080
+ * category label/color, resolved price and live status, ready for a tooltip.
1081
+ * Fires alongside the raw renderer-level `onHover`.
1082
+ */
1083
+ onSeatHover?: (details: SeatHoverDetails | null) => void;
1055
1084
  /** The server declared the event closed (a 409 event_closed). */
1056
1085
  onSalesClosed?: () => void;
1057
1086
  /**
@@ -1221,6 +1250,8 @@ declare class PickerController {
1221
1250
  private sectionSummary;
1222
1251
  destroy(): void;
1223
1252
  private toSeat;
1253
+ /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */
1254
+ private describeSeat;
1224
1255
  private priceFor;
1225
1256
  private tiersFor;
1226
1257
  /**
@@ -1330,4 +1361,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
1330
1361
  /** Bare symbol for input adornments ("€", "$", "₹"). */
1331
1362
  declare function currencySymbol(currency?: string): string;
1332
1363
 
1333
- export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
1364
+ export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
package/dist/index.js CHANGED
@@ -529,6 +529,8 @@ var en = {
529
529
  "map.aria": "Seating map. Use arrow keys to move between seats, Enter to select.",
530
530
  "map.seatsLeft": "{count} LEFT",
531
531
  "map.fromPrice": "FROM {price}",
532
+ "map.statusHeld": "On hold",
533
+ "map.statusTaken": "Taken",
532
534
  // buyer picker page (src/pages/PickerPage.tsx)
533
535
  "picker.language": "Language",
534
536
  "picker.zoomToFit": "Zoom to fit",
@@ -655,8 +657,35 @@ function seatMatchesAccess(seat, filter) {
655
657
  }
656
658
  var DEF_SEAT_LABEL = "#0b1220";
657
659
  var DEF_SELECTION = "#ffffff";
660
+ var DEF_SELECTION_ON_LIGHT = "#0b1220";
658
661
  var DEF_DECOR_FILL = "#232c40";
659
662
  var DEF_TEXT = "#8b93a7";
663
+ function colorLuminance(color) {
664
+ const s = color.trim();
665
+ let r = NaN;
666
+ let g = NaN;
667
+ let b = NaN;
668
+ const hex = /^#([\da-f]{3}|[\da-f]{6})$/i.exec(s);
669
+ if (hex) {
670
+ const h = hex[1].length === 3 ? hex[1].split("").map((c) => c + c).join("") : hex[1];
671
+ r = parseInt(h.slice(0, 2), 16);
672
+ g = parseInt(h.slice(2, 4), 16);
673
+ b = parseInt(h.slice(4, 6), 16);
674
+ } else {
675
+ const rgb = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(s);
676
+ if (rgb) {
677
+ r = +rgb[1];
678
+ g = +rgb[2];
679
+ b = +rgb[3];
680
+ }
681
+ }
682
+ if (Number.isNaN(r)) return NaN;
683
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
684
+ }
685
+ function isLightColor(color) {
686
+ const lum = colorLuminance(color);
687
+ return !Number.isNaN(lum) && lum > 0.6;
688
+ }
660
689
  var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
661
690
  function seatIdOf(target) {
662
691
  const n = target;
@@ -742,6 +771,8 @@ var _SeatmapRenderer = class _SeatmapRenderer {
742
771
  this.statusById = /* @__PURE__ */ new Map();
743
772
  this.catColor = /* @__PURE__ */ new Map();
744
773
  this.theme = {};
774
+ /** Effective selection/hover ring color — resolved per chart in setChart(). */
775
+ this.effSelection = DEF_SELECTION;
745
776
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
746
777
  this.colorblind = false;
747
778
  /** Category order from the doc — the stable index into the CB palette. */
@@ -992,7 +1023,8 @@ var _SeatmapRenderer = class _SeatmapRenderer {
992
1023
  this.theme = doc.theme ?? {};
993
1024
  this.seatR = clamp(this.theme.seatScale ?? 1, 0.7, 1.6) * SEAT_RADIUS;
994
1025
  this.container.style.background = this.theme.background ?? "";
995
- this.hoverRing.stroke(this.theme.selectionColor ?? DEF_SELECTION);
1026
+ this.effSelection = this.resolveSelectionColor();
1027
+ this.hoverRing.stroke(this.effSelection);
996
1028
  this.hoverRing.radius(this.seatR + 2);
997
1029
  this.catColor.clear();
998
1030
  this.catPrice.clear();
@@ -1538,7 +1570,9 @@ var _SeatmapRenderer = class _SeatmapRenderer {
1538
1570
  c.opacity(1);
1539
1571
  switch (status) {
1540
1572
  case "free":
1541
- c.fill(selected ? lighten(base, 0.28) : base);
1573
+ c.fill(
1574
+ selected && this.effSelection === DEF_SELECTION ? lighten(base, 0.28) : base
1575
+ );
1542
1576
  break;
1543
1577
  case "held":
1544
1578
  c.fill(HELD_FILL);
@@ -2180,6 +2214,31 @@ var _SeatmapRenderer = class _SeatmapRenderer {
2180
2214
  }
2181
2215
  this.overlayLayer.batchDraw();
2182
2216
  }
2217
+ /**
2218
+ * Selection/hover ring color. An explicit theme.selectionColor always wins;
2219
+ * otherwise auto-contrast against the effective canvas background — the
2220
+ * designer renders on dark (white ring reads), but light-themed hosts (e.g.
2221
+ * the DesiPass buyer picker on cream) made the white ring invisible and
2222
+ * selected seats looked *disabled*. theme.background is checked first, then
2223
+ * the container's computed CSS background (walking up past transparent
2224
+ * ancestors). Unknown/unparseable backgrounds keep the dark default.
2225
+ */
2226
+ resolveSelectionColor() {
2227
+ if (this.theme.selectionColor) return this.theme.selectionColor;
2228
+ let bg = this.theme.background ?? "";
2229
+ if (!bg && typeof getComputedStyle === "function") {
2230
+ let el = this.container;
2231
+ while (el) {
2232
+ const c = getComputedStyle(el).backgroundColor;
2233
+ if (c && c !== "transparent" && !/^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*0\s*\)$/.test(c)) {
2234
+ bg = c;
2235
+ break;
2236
+ }
2237
+ el = el.parentElement;
2238
+ }
2239
+ }
2240
+ return isLightColor(bg) ? DEF_SELECTION_ON_LIGHT : DEF_SELECTION;
2241
+ }
2183
2242
  setSelected(id, on, silent = false) {
2184
2243
  const c = this.circleById.get(id);
2185
2244
  if (on) {
@@ -2189,7 +2248,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
2189
2248
  x: seat.x,
2190
2249
  y: seat.y,
2191
2250
  radius: this.seatR,
2192
- stroke: this.theme.selectionColor ?? DEF_SELECTION,
2251
+ stroke: this.effSelection,
2193
2252
  strokeWidth: 3,
2194
2253
  listening: false,
2195
2254
  perfectDrawEnabled: false,
@@ -2669,7 +2728,10 @@ var PickerController = class {
2669
2728
  this.opts.onDeselect?.(seat);
2670
2729
  this.emitSelectionChange();
2671
2730
  },
2672
- onHover: this.opts.onHover,
2731
+ onHover: (seat) => {
2732
+ this.opts.onHover?.(seat);
2733
+ if (this.opts.onSeatHover) this.opts.onSeatHover(seat ? this.describeSeat(seat) : null);
2734
+ },
2673
2735
  onFocusSeat: this.opts.onFocusSeat,
2674
2736
  onViewChange: this.opts.onViewChange,
2675
2737
  onGAClick: this.opts.onGAClick,
@@ -3096,6 +3158,17 @@ var PickerController = class {
3096
3158
  tierId: chosen.id
3097
3159
  };
3098
3160
  }
3161
+ /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */
3162
+ describeSeat(s) {
3163
+ const cat = this._doc?.categories.find((c) => c.key === s.categoryKey);
3164
+ return {
3165
+ ...this.toSeat(s),
3166
+ categoryLabel: cat?.label ?? s.categoryKey,
3167
+ categoryColor: cat?.color ?? "#6e7bff",
3168
+ status: this.renderer?.getStatus(s.id) ?? "free",
3169
+ currency: this.currency
3170
+ };
3171
+ }
3099
3172
  priceFor(categoryKey) {
3100
3173
  return this._doc?.categories.find((c) => c.key === categoryKey)?.price ?? 0;
3101
3174
  }
@@ -3317,9 +3390,9 @@ var PickerController = class {
3317
3390
 
3318
3391
  // src/i18n/bundles.ts
3319
3392
  var LOADERS = {
3320
- es: () => import("./es-MLM3IFIY.js").then((m) => ({ default: m.es })),
3321
- de: () => import("./de-YMAVF5S2.js").then((m) => ({ default: m.de })),
3322
- fr: () => import("./fr-N7AAVATM.js").then((m) => ({ default: m.fr }))
3393
+ es: () => import("./es-SKJTYKLL.js").then((m) => ({ default: m.es })),
3394
+ de: () => import("./de-DDXO5ERX.js").then((m) => ({ default: m.de })),
3395
+ fr: () => import("./fr-NPIGOYCU.js").then((m) => ({ default: m.fr }))
3323
3396
  };
3324
3397
  var loaded = /* @__PURE__ */ new Set(["en"]);
3325
3398
  async function loadLocale(code) {