@seatlayer/core 0.1.4 → 0.3.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/{de-A4KJQ374.js → de-YMAVF5S2.js} +2 -1
- package/dist/de-YMAVF5S2.js.map +1 -0
- package/dist/{es-YNYMMP37.js → es-MLM3IFIY.js} +2 -1
- package/dist/es-MLM3IFIY.js.map +1 -0
- package/dist/{fr-DQ4KWKKF.js → fr-N7AAVATM.js} +2 -1
- package/dist/fr-N7AAVATM.js.map +1 -0
- package/dist/index.cjs +143 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -5
- package/dist/index.d.ts +52 -5
- package/dist/index.js +137 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/de-A4KJQ374.js.map +0 -1
- package/dist/es-YNYMMP37.js.map +0 -1
- package/dist/fr-DQ4KWKKF.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -547,6 +547,14 @@ declare function chartBounds(doc: ChartDoc): {
|
|
|
547
547
|
height: number;
|
|
548
548
|
};
|
|
549
549
|
|
|
550
|
+
declare const MAX_GA_CAPACITY = 100000;
|
|
551
|
+
declare const MAX_EVENT_INVENTORY = 100000;
|
|
552
|
+
/** Stable internal inventory label for one unit of a GA area's capacity. */
|
|
553
|
+
declare function gaUnitLabel(areaId: string, index: number): string;
|
|
554
|
+
declare function gaUnitLabels(area: GAAreaObject): string[];
|
|
555
|
+
declare function gaAreasOf(doc: ChartDoc): GAAreaObject[];
|
|
556
|
+
declare function isGaUnitLabel(label: string): boolean;
|
|
557
|
+
|
|
550
558
|
/**
|
|
551
559
|
* Section membership + hide/show resolution (Batch 3.3).
|
|
552
560
|
*
|
|
@@ -947,7 +955,7 @@ interface PickerSeat {
|
|
|
947
955
|
}
|
|
948
956
|
interface HoldConflict {
|
|
949
957
|
label: string;
|
|
950
|
-
|
|
958
|
+
status: string;
|
|
951
959
|
}
|
|
952
960
|
/** An open hold — its id, the labels it covers, and the server's expiry time (ms epoch). */
|
|
953
961
|
interface HoldInfo {
|
|
@@ -956,6 +964,8 @@ interface HoldInfo {
|
|
|
956
964
|
expiresAt: number;
|
|
957
965
|
/** The held seats with their chosen ticket tier — what the host books against. */
|
|
958
966
|
seats: PickerSeat[];
|
|
967
|
+
/** Server-authoritative commercial line items, including GA units and resolved prices. */
|
|
968
|
+
items?: HoldServerItem[];
|
|
959
969
|
}
|
|
960
970
|
/** One category's slice of a section (dot + price + count) for the summary card. */
|
|
961
971
|
interface SectionCategory {
|
|
@@ -987,6 +997,21 @@ interface SectionSummary {
|
|
|
987
997
|
interface HoldResponse {
|
|
988
998
|
holdId: string;
|
|
989
999
|
expiresAt: number;
|
|
1000
|
+
items?: HoldServerItem[];
|
|
1001
|
+
}
|
|
1002
|
+
interface HoldServerItem {
|
|
1003
|
+
label: string;
|
|
1004
|
+
objectId: string;
|
|
1005
|
+
objectType: 'seat' | 'booth' | 'ga';
|
|
1006
|
+
categoryKey: string;
|
|
1007
|
+
tierId: string | null;
|
|
1008
|
+
unitPrice: number;
|
|
1009
|
+
currency: string;
|
|
1010
|
+
quantity?: number;
|
|
1011
|
+
}
|
|
1012
|
+
interface HoldSelectionRequest {
|
|
1013
|
+
label: string;
|
|
1014
|
+
tierId?: string | null;
|
|
990
1015
|
}
|
|
991
1016
|
interface BestAvailableResponse extends HoldResponse {
|
|
992
1017
|
labels: string[];
|
|
@@ -1002,13 +1027,14 @@ interface PickerTransport {
|
|
|
1002
1027
|
venue?: string | null;
|
|
1003
1028
|
startsAt?: number | null;
|
|
1004
1029
|
currency?: string;
|
|
1030
|
+
mode?: string;
|
|
1005
1031
|
};
|
|
1006
1032
|
}>;
|
|
1007
1033
|
objects(key: string): Promise<{
|
|
1008
1034
|
seats: Record<string, string>;
|
|
1009
1035
|
hidden?: string[];
|
|
1010
1036
|
}>;
|
|
1011
|
-
hold(key: string,
|
|
1037
|
+
hold(key: string, selections: HoldSelectionRequest[], ttlMs?: number, replaceHoldId?: string): Promise<HoldResponse>;
|
|
1012
1038
|
bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;
|
|
1013
1039
|
release(key: string, labels: string[], holdId: string): Promise<unknown>;
|
|
1014
1040
|
/** Optional — the SDK omits booking (it hands the holdId to the host page). */
|
|
@@ -1079,6 +1105,8 @@ declare class PickerController {
|
|
|
1079
1105
|
private attempt;
|
|
1080
1106
|
private closed;
|
|
1081
1107
|
private hold_;
|
|
1108
|
+
private liveStatuses;
|
|
1109
|
+
private currency;
|
|
1082
1110
|
private expiryTimer;
|
|
1083
1111
|
constructor(options: PickerOptions);
|
|
1084
1112
|
get doc(): ChartDoc | null;
|
|
@@ -1098,6 +1126,8 @@ declare class PickerController {
|
|
|
1098
1126
|
venue?: string | null;
|
|
1099
1127
|
startsAt?: number | null;
|
|
1100
1128
|
currency?: string;
|
|
1129
|
+
/** 'test' ⇒ sandbox event (hosts show a TEST MODE ribbon). */
|
|
1130
|
+
mode?: string;
|
|
1101
1131
|
} | null>;
|
|
1102
1132
|
getSelection(): PickerSeat[];
|
|
1103
1133
|
clearSelection(): void;
|
|
@@ -1108,7 +1138,23 @@ declare class PickerController {
|
|
|
1108
1138
|
* re-throws so the caller can choose the banner copy. Returns null only when
|
|
1109
1139
|
* there's nothing to hold.
|
|
1110
1140
|
*/
|
|
1111
|
-
hold(labelsArg?: string[]): Promise<HoldInfo | null>;
|
|
1141
|
+
hold(labelsArg?: string[], ttlMs?: number): Promise<HoldInfo | null>;
|
|
1142
|
+
/** Public GA inventory derived from the live synthetic-unit status stream. */
|
|
1143
|
+
getGAAreas(): {
|
|
1144
|
+
id: string;
|
|
1145
|
+
label: string;
|
|
1146
|
+
capacity: number;
|
|
1147
|
+
available: number;
|
|
1148
|
+
categoryKey: string;
|
|
1149
|
+
price: number;
|
|
1150
|
+
currency: string;
|
|
1151
|
+
tiers?: CategoryTier[];
|
|
1152
|
+
}[];
|
|
1153
|
+
/** Select a quantity from one GA area and hold it atomically. */
|
|
1154
|
+
holdGA(areaId: string, qty: number, options?: {
|
|
1155
|
+
tierId?: string | null;
|
|
1156
|
+
ttlMs?: number;
|
|
1157
|
+
}): Promise<HoldInfo | null>;
|
|
1112
1158
|
/** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */
|
|
1113
1159
|
bestAvailable(qty: number, categoryKey?: string): Promise<HoldInfo | null>;
|
|
1114
1160
|
/**
|
|
@@ -1204,8 +1250,9 @@ declare class PickerController {
|
|
|
1204
1250
|
/** Set the open hold + (re)arm the server-authoritative expiry timer. */
|
|
1205
1251
|
private setHold;
|
|
1206
1252
|
private clearHold;
|
|
1207
|
-
private
|
|
1253
|
+
private expireActiveHold;
|
|
1208
1254
|
private applySeatsMap;
|
|
1255
|
+
private clearBookedHoldIfSettled;
|
|
1209
1256
|
private resnapshot;
|
|
1210
1257
|
private connect;
|
|
1211
1258
|
private scheduleReconnect;
|
|
@@ -1283,4 +1330,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
|
|
|
1283
1330
|
/** Bare symbol for input adornments ("€", "$", "₹"). */
|
|
1284
1331
|
declare function currencySymbol(currency?: string): string;
|
|
1285
1332
|
|
|
1286
|
-
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 ISeatmapRenderer, type Locale, type LodRung, 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, getLocale, hiddenObjectIds, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -547,6 +547,14 @@ declare function chartBounds(doc: ChartDoc): {
|
|
|
547
547
|
height: number;
|
|
548
548
|
};
|
|
549
549
|
|
|
550
|
+
declare const MAX_GA_CAPACITY = 100000;
|
|
551
|
+
declare const MAX_EVENT_INVENTORY = 100000;
|
|
552
|
+
/** Stable internal inventory label for one unit of a GA area's capacity. */
|
|
553
|
+
declare function gaUnitLabel(areaId: string, index: number): string;
|
|
554
|
+
declare function gaUnitLabels(area: GAAreaObject): string[];
|
|
555
|
+
declare function gaAreasOf(doc: ChartDoc): GAAreaObject[];
|
|
556
|
+
declare function isGaUnitLabel(label: string): boolean;
|
|
557
|
+
|
|
550
558
|
/**
|
|
551
559
|
* Section membership + hide/show resolution (Batch 3.3).
|
|
552
560
|
*
|
|
@@ -947,7 +955,7 @@ interface PickerSeat {
|
|
|
947
955
|
}
|
|
948
956
|
interface HoldConflict {
|
|
949
957
|
label: string;
|
|
950
|
-
|
|
958
|
+
status: string;
|
|
951
959
|
}
|
|
952
960
|
/** An open hold — its id, the labels it covers, and the server's expiry time (ms epoch). */
|
|
953
961
|
interface HoldInfo {
|
|
@@ -956,6 +964,8 @@ interface HoldInfo {
|
|
|
956
964
|
expiresAt: number;
|
|
957
965
|
/** The held seats with their chosen ticket tier — what the host books against. */
|
|
958
966
|
seats: PickerSeat[];
|
|
967
|
+
/** Server-authoritative commercial line items, including GA units and resolved prices. */
|
|
968
|
+
items?: HoldServerItem[];
|
|
959
969
|
}
|
|
960
970
|
/** One category's slice of a section (dot + price + count) for the summary card. */
|
|
961
971
|
interface SectionCategory {
|
|
@@ -987,6 +997,21 @@ interface SectionSummary {
|
|
|
987
997
|
interface HoldResponse {
|
|
988
998
|
holdId: string;
|
|
989
999
|
expiresAt: number;
|
|
1000
|
+
items?: HoldServerItem[];
|
|
1001
|
+
}
|
|
1002
|
+
interface HoldServerItem {
|
|
1003
|
+
label: string;
|
|
1004
|
+
objectId: string;
|
|
1005
|
+
objectType: 'seat' | 'booth' | 'ga';
|
|
1006
|
+
categoryKey: string;
|
|
1007
|
+
tierId: string | null;
|
|
1008
|
+
unitPrice: number;
|
|
1009
|
+
currency: string;
|
|
1010
|
+
quantity?: number;
|
|
1011
|
+
}
|
|
1012
|
+
interface HoldSelectionRequest {
|
|
1013
|
+
label: string;
|
|
1014
|
+
tierId?: string | null;
|
|
990
1015
|
}
|
|
991
1016
|
interface BestAvailableResponse extends HoldResponse {
|
|
992
1017
|
labels: string[];
|
|
@@ -1002,13 +1027,14 @@ interface PickerTransport {
|
|
|
1002
1027
|
venue?: string | null;
|
|
1003
1028
|
startsAt?: number | null;
|
|
1004
1029
|
currency?: string;
|
|
1030
|
+
mode?: string;
|
|
1005
1031
|
};
|
|
1006
1032
|
}>;
|
|
1007
1033
|
objects(key: string): Promise<{
|
|
1008
1034
|
seats: Record<string, string>;
|
|
1009
1035
|
hidden?: string[];
|
|
1010
1036
|
}>;
|
|
1011
|
-
hold(key: string,
|
|
1037
|
+
hold(key: string, selections: HoldSelectionRequest[], ttlMs?: number, replaceHoldId?: string): Promise<HoldResponse>;
|
|
1012
1038
|
bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;
|
|
1013
1039
|
release(key: string, labels: string[], holdId: string): Promise<unknown>;
|
|
1014
1040
|
/** Optional — the SDK omits booking (it hands the holdId to the host page). */
|
|
@@ -1079,6 +1105,8 @@ declare class PickerController {
|
|
|
1079
1105
|
private attempt;
|
|
1080
1106
|
private closed;
|
|
1081
1107
|
private hold_;
|
|
1108
|
+
private liveStatuses;
|
|
1109
|
+
private currency;
|
|
1082
1110
|
private expiryTimer;
|
|
1083
1111
|
constructor(options: PickerOptions);
|
|
1084
1112
|
get doc(): ChartDoc | null;
|
|
@@ -1098,6 +1126,8 @@ declare class PickerController {
|
|
|
1098
1126
|
venue?: string | null;
|
|
1099
1127
|
startsAt?: number | null;
|
|
1100
1128
|
currency?: string;
|
|
1129
|
+
/** 'test' ⇒ sandbox event (hosts show a TEST MODE ribbon). */
|
|
1130
|
+
mode?: string;
|
|
1101
1131
|
} | null>;
|
|
1102
1132
|
getSelection(): PickerSeat[];
|
|
1103
1133
|
clearSelection(): void;
|
|
@@ -1108,7 +1138,23 @@ declare class PickerController {
|
|
|
1108
1138
|
* re-throws so the caller can choose the banner copy. Returns null only when
|
|
1109
1139
|
* there's nothing to hold.
|
|
1110
1140
|
*/
|
|
1111
|
-
hold(labelsArg?: string[]): Promise<HoldInfo | null>;
|
|
1141
|
+
hold(labelsArg?: string[], ttlMs?: number): Promise<HoldInfo | null>;
|
|
1142
|
+
/** Public GA inventory derived from the live synthetic-unit status stream. */
|
|
1143
|
+
getGAAreas(): {
|
|
1144
|
+
id: string;
|
|
1145
|
+
label: string;
|
|
1146
|
+
capacity: number;
|
|
1147
|
+
available: number;
|
|
1148
|
+
categoryKey: string;
|
|
1149
|
+
price: number;
|
|
1150
|
+
currency: string;
|
|
1151
|
+
tiers?: CategoryTier[];
|
|
1152
|
+
}[];
|
|
1153
|
+
/** Select a quantity from one GA area and hold it atomically. */
|
|
1154
|
+
holdGA(areaId: string, qty: number, options?: {
|
|
1155
|
+
tierId?: string | null;
|
|
1156
|
+
ttlMs?: number;
|
|
1157
|
+
}): Promise<HoldInfo | null>;
|
|
1112
1158
|
/** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */
|
|
1113
1159
|
bestAvailable(qty: number, categoryKey?: string): Promise<HoldInfo | null>;
|
|
1114
1160
|
/**
|
|
@@ -1204,8 +1250,9 @@ declare class PickerController {
|
|
|
1204
1250
|
/** Set the open hold + (re)arm the server-authoritative expiry timer. */
|
|
1205
1251
|
private setHold;
|
|
1206
1252
|
private clearHold;
|
|
1207
|
-
private
|
|
1253
|
+
private expireActiveHold;
|
|
1208
1254
|
private applySeatsMap;
|
|
1255
|
+
private clearBookedHoldIfSettled;
|
|
1209
1256
|
private resnapshot;
|
|
1210
1257
|
private connect;
|
|
1211
1258
|
private scheduleReconnect;
|
|
@@ -1283,4 +1330,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
|
|
|
1283
1330
|
/** Bare symbol for input adornments ("€", "$", "₹"). */
|
|
1284
1331
|
declare function currencySymbol(currency?: string): string;
|
|
1285
1332
|
|
|
1286
|
-
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 ISeatmapRenderer, type Locale, type LodRung, 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, getLocale, hiddenObjectIds, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -364,16 +364,35 @@ function chartBounds(doc) {
|
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
// src/core/ga.ts
|
|
368
|
+
var PREFIX = "__sl_ga__";
|
|
369
|
+
var MAX_GA_CAPACITY = 1e5;
|
|
370
|
+
var MAX_EVENT_INVENTORY = 1e5;
|
|
371
|
+
function gaUnitLabel(areaId, index) {
|
|
372
|
+
return `${PREFIX}${encodeURIComponent(areaId)}__${index + 1}`;
|
|
373
|
+
}
|
|
374
|
+
function gaUnitLabels(area) {
|
|
375
|
+
const capacity = Math.min(MAX_GA_CAPACITY, Math.max(0, Math.floor(area.capacity)));
|
|
376
|
+
return Array.from({ length: capacity }, (_, i) => gaUnitLabel(area.id, i));
|
|
377
|
+
}
|
|
378
|
+
function gaAreasOf(doc) {
|
|
379
|
+
return allObjects(doc).filter((o) => o.type === "gaArea");
|
|
380
|
+
}
|
|
381
|
+
function isGaUnitLabel(label) {
|
|
382
|
+
return label.startsWith(PREFIX);
|
|
383
|
+
}
|
|
384
|
+
|
|
367
385
|
// src/core/sections.ts
|
|
368
386
|
var UNGROUPED_ID = "__ungrouped__";
|
|
369
387
|
function objectSeatLabels(o) {
|
|
370
388
|
if (o.type === "row") return expandRow(o).map((s) => s.label);
|
|
371
389
|
if (o.type === "table") return expandTable(o).map((s) => s.label);
|
|
372
390
|
if (o.type === "booth") return expandBooth(o).map((s) => s.label);
|
|
391
|
+
if (o.type === "gaArea") return gaUnitLabels(o);
|
|
373
392
|
return [];
|
|
374
393
|
}
|
|
375
394
|
function isSeatObject(o) {
|
|
376
|
-
return o.type === "row" || o.type === "table" || o.type === "booth";
|
|
395
|
+
return o.type === "row" || o.type === "table" || o.type === "booth" || o.type === "gaArea";
|
|
377
396
|
}
|
|
378
397
|
function computeSections(doc) {
|
|
379
398
|
const objs = allObjects(doc);
|
|
@@ -501,6 +520,7 @@ var en = {
|
|
|
501
520
|
"picker.holdExpired": "Your hold expired \u2014 the seats were released. Pick again.",
|
|
502
521
|
"picker.seatTaken": "Seat {label} was just taken by another buyer.",
|
|
503
522
|
"picker.poweredBy": "Powered by SeatLayer",
|
|
523
|
+
"picker.testMode": "TEST MODE",
|
|
504
524
|
"picker.colorblind": "Colorblind-friendly colors",
|
|
505
525
|
"picker.orphanHint": "This leaves a single seat stranded \u2014 consider shifting one seat over.",
|
|
506
526
|
"picker.seats.one": "{count} seat",
|
|
@@ -2575,6 +2595,8 @@ var PickerController = class {
|
|
|
2575
2595
|
this.closed = false;
|
|
2576
2596
|
// hold state
|
|
2577
2597
|
this.hold_ = null;
|
|
2598
|
+
this.liveStatuses = /* @__PURE__ */ new Map();
|
|
2599
|
+
this.currency = "USD";
|
|
2578
2600
|
this.expiryTimer = null;
|
|
2579
2601
|
/** Whether the last emitted hint was non-null (avoids clearing repeatedly). */
|
|
2580
2602
|
this.hintShown = false;
|
|
@@ -2634,6 +2656,7 @@ var PickerController = class {
|
|
|
2634
2656
|
this.allIds.push(s.id);
|
|
2635
2657
|
}
|
|
2636
2658
|
const currency = res.event.currency ?? this.opts.currency;
|
|
2659
|
+
this.currency = currency ?? "USD";
|
|
2637
2660
|
const renderer = createRenderer(host, {
|
|
2638
2661
|
maxSelection: this.maxSelection,
|
|
2639
2662
|
confirmSelection: this.opts.confirmSelection,
|
|
@@ -2682,7 +2705,9 @@ var PickerController = class {
|
|
|
2682
2705
|
eventName: res.event.name,
|
|
2683
2706
|
venue: res.event.venue,
|
|
2684
2707
|
startsAt: res.event.startsAt,
|
|
2685
|
-
currency
|
|
2708
|
+
currency,
|
|
2709
|
+
// 'test' ⇒ sandbox event: hosts render a TEST MODE ribbon (Phase 11).
|
|
2710
|
+
mode: res.event.mode ?? "live"
|
|
2686
2711
|
};
|
|
2687
2712
|
}
|
|
2688
2713
|
// ---- selection ------------------------------------------------------------
|
|
@@ -2705,21 +2730,72 @@ var PickerController = class {
|
|
|
2705
2730
|
* re-throws so the caller can choose the banner copy. Returns null only when
|
|
2706
2731
|
* there's nothing to hold.
|
|
2707
2732
|
*/
|
|
2708
|
-
async hold(labelsArg) {
|
|
2733
|
+
async hold(labelsArg, ttlMs) {
|
|
2709
2734
|
const r = this.renderer;
|
|
2710
2735
|
if (!r) return null;
|
|
2711
2736
|
const labels = labelsArg ?? r.getSelection().map((s) => s.label);
|
|
2712
|
-
|
|
2713
|
-
|
|
2737
|
+
const existingGA = (this.hold_?.items ?? []).filter((item) => item.objectType === "ga");
|
|
2738
|
+
const combinedLabels = [.../* @__PURE__ */ new Set([...existingGA.map((item) => item.label), ...labels])];
|
|
2739
|
+
if (!combinedLabels.length) return null;
|
|
2740
|
+
if (this.hold_ && this.holdCovers(combinedLabels)) return this.hold_;
|
|
2714
2741
|
try {
|
|
2715
|
-
const
|
|
2716
|
-
|
|
2742
|
+
const selections = combinedLabels.map((label) => {
|
|
2743
|
+
const ga = existingGA.find((item) => item.label === label);
|
|
2744
|
+
if (ga) return { label, tierId: ga.tierId };
|
|
2745
|
+
const seat = this.labelToSeat.get(label);
|
|
2746
|
+
const resolved = seat ? this.toSeat(seat) : null;
|
|
2747
|
+
return { label, ...resolved?.tierId ? { tierId: resolved.tierId } : {} };
|
|
2748
|
+
});
|
|
2749
|
+
const result = await this.api.hold(this.key, selections, ttlMs, this.hold_?.holdId);
|
|
2750
|
+
this.setHold({ holdId: result.holdId, labels: combinedLabels, expiresAt: result.expiresAt, items: result.items });
|
|
2717
2751
|
return this.hold_;
|
|
2718
2752
|
} catch (err) {
|
|
2719
2753
|
this.handle409Conflicts(err);
|
|
2720
2754
|
throw err;
|
|
2721
2755
|
}
|
|
2722
2756
|
}
|
|
2757
|
+
/** Public GA inventory derived from the live synthetic-unit status stream. */
|
|
2758
|
+
getGAAreas() {
|
|
2759
|
+
const doc = this.visibleDoc();
|
|
2760
|
+
if (!doc) return [];
|
|
2761
|
+
return gaAreasOf(doc).map((area) => {
|
|
2762
|
+
const category = doc.categories.find((candidate) => candidate.key === area.categoryKey);
|
|
2763
|
+
return {
|
|
2764
|
+
id: area.id,
|
|
2765
|
+
label: area.label,
|
|
2766
|
+
capacity: Math.max(0, Math.floor(area.capacity)),
|
|
2767
|
+
available: gaUnitLabels(area).filter((label) => (this.liveStatuses.get(label) ?? "free") === "free").length,
|
|
2768
|
+
categoryKey: area.categoryKey,
|
|
2769
|
+
tiers: category?.tiers,
|
|
2770
|
+
price: category?.tiers?.[0]?.price ?? category?.price ?? 0,
|
|
2771
|
+
currency: this.currency
|
|
2772
|
+
};
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
/** Select a quantity from one GA area and hold it atomically. */
|
|
2776
|
+
async holdGA(areaId, qty, options = {}) {
|
|
2777
|
+
const doc = this.visibleDoc();
|
|
2778
|
+
if (!doc || !Number.isFinite(qty) || qty < 1) return null;
|
|
2779
|
+
const area = gaAreasOf(doc).find((candidate) => candidate.id === areaId);
|
|
2780
|
+
if (!area) return null;
|
|
2781
|
+
const labels = gaUnitLabels(area).filter((label) => !this.hold_?.labels.includes(label) && (this.liveStatuses.get(label) ?? "free") === "free").slice(0, Math.floor(qty));
|
|
2782
|
+
if (labels.length !== Math.floor(qty)) return null;
|
|
2783
|
+
const selections = /* @__PURE__ */ new Map();
|
|
2784
|
+
for (const item of this.hold_?.items ?? []) selections.set(item.label, { label: item.label, tierId: item.tierId });
|
|
2785
|
+
if (this.hold_ && !this.hold_?.items?.length) {
|
|
2786
|
+
for (const seat of this.hold_.seats) selections.set(seat.label, { label: seat.label, ...seat.tierId ? { tierId: seat.tierId } : {} });
|
|
2787
|
+
}
|
|
2788
|
+
for (const seat of this.renderer?.getSelection() ?? []) {
|
|
2789
|
+
const resolved = this.labelToSeat.get(seat.label);
|
|
2790
|
+
const chosen = resolved ? this.toSeat(resolved) : null;
|
|
2791
|
+
selections.set(seat.label, { label: seat.label, ...chosen?.tierId ? { tierId: chosen.tierId } : {} });
|
|
2792
|
+
}
|
|
2793
|
+
for (const label of labels) selections.set(label, { label, ...options.tierId ? { tierId: options.tierId } : {} });
|
|
2794
|
+
const combined = [...selections.values()];
|
|
2795
|
+
const result = await this.api.hold(this.key, combined, options.ttlMs, this.hold_?.holdId);
|
|
2796
|
+
this.setHold({ holdId: result.holdId, labels: combined.map((s) => s.label), expiresAt: result.expiresAt, items: result.items });
|
|
2797
|
+
return this.hold_;
|
|
2798
|
+
}
|
|
2723
2799
|
/** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */
|
|
2724
2800
|
async bestAvailable(qty, categoryKey) {
|
|
2725
2801
|
const r = this.renderer;
|
|
@@ -2730,7 +2806,7 @@ var PickerController = class {
|
|
|
2730
2806
|
r.clearSelection();
|
|
2731
2807
|
const ids = result.labels.map((l) => this.labelToId.get(l)).filter((v) => !!v);
|
|
2732
2808
|
if (ids.length) r.setStatus(ids, "held");
|
|
2733
|
-
this.setHold({ holdId: result.holdId, labels: [...result.labels], expiresAt: result.expiresAt });
|
|
2809
|
+
this.setHold({ holdId: result.holdId, labels: [...result.labels], expiresAt: result.expiresAt, items: result.items });
|
|
2734
2810
|
const seats = result.labels.map((l) => this.labelToSeat.get(l)).filter((s) => !!s).map((s) => this.toSeat(s));
|
|
2735
2811
|
this.opts.onSelectionChange?.(seats);
|
|
2736
2812
|
return this.hold_;
|
|
@@ -2759,9 +2835,19 @@ var PickerController = class {
|
|
|
2759
2835
|
if (this.hold_ && this.holdCovers(labels)) {
|
|
2760
2836
|
holdId = this.hold_.holdId;
|
|
2761
2837
|
} else {
|
|
2762
|
-
const
|
|
2838
|
+
const replaceHoldId = this.hold_?.holdId;
|
|
2839
|
+
const h = await this.api.hold(
|
|
2840
|
+
this.key,
|
|
2841
|
+
labels.map((label) => {
|
|
2842
|
+
const seat = this.labelToSeat.get(label);
|
|
2843
|
+
const resolved = seat ? this.toSeat(seat) : null;
|
|
2844
|
+
return { label, ...resolved?.tierId ? { tierId: resolved.tierId } : {} };
|
|
2845
|
+
}),
|
|
2846
|
+
void 0,
|
|
2847
|
+
replaceHoldId
|
|
2848
|
+
);
|
|
2763
2849
|
holdId = h.holdId;
|
|
2764
|
-
this.setHold({ holdId, labels: [...labels], expiresAt: h.expiresAt });
|
|
2850
|
+
this.setHold({ holdId, labels: [...labels], expiresAt: h.expiresAt, items: h.items });
|
|
2765
2851
|
}
|
|
2766
2852
|
await this.api.book(this.key, labels, holdId, bookingRef);
|
|
2767
2853
|
} catch (err) {
|
|
@@ -3077,7 +3163,13 @@ var PickerController = class {
|
|
|
3077
3163
|
}
|
|
3078
3164
|
holdCovers(labels) {
|
|
3079
3165
|
const h = this.hold_;
|
|
3080
|
-
|
|
3166
|
+
if (!h || h.labels.length !== labels.length || !labels.every((l) => h.labels.includes(l))) return false;
|
|
3167
|
+
const tiers = new Map((h.items ?? []).map((item) => [item.label, item.tierId]));
|
|
3168
|
+
return labels.every((label) => {
|
|
3169
|
+
const seat = this.labelToSeat.get(label);
|
|
3170
|
+
const currentTier = seat ? this.toSeat(seat).tierId ?? null : null;
|
|
3171
|
+
return !tiers.has(label) || tiers.get(label) === currentTier;
|
|
3172
|
+
});
|
|
3081
3173
|
}
|
|
3082
3174
|
handle409Conflicts(err) {
|
|
3083
3175
|
const { status, conflicts } = errInfo(err);
|
|
@@ -3097,7 +3189,7 @@ var PickerController = class {
|
|
|
3097
3189
|
this.hold_ = full;
|
|
3098
3190
|
if (this.expiryTimer) clearTimeout(this.expiryTimer);
|
|
3099
3191
|
const ms = Math.max(0, full.expiresAt - Date.now());
|
|
3100
|
-
this.expiryTimer = setTimeout(() => this.
|
|
3192
|
+
this.expiryTimer = setTimeout(() => void this.expireActiveHold(), ms);
|
|
3101
3193
|
this.opts.onHold?.(full);
|
|
3102
3194
|
}
|
|
3103
3195
|
clearHold() {
|
|
@@ -3107,18 +3199,31 @@ var PickerController = class {
|
|
|
3107
3199
|
this.expiryTimer = null;
|
|
3108
3200
|
}
|
|
3109
3201
|
}
|
|
3110
|
-
|
|
3202
|
+
async expireActiveHold() {
|
|
3111
3203
|
const hold = this.hold_;
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
const
|
|
3115
|
-
if (
|
|
3204
|
+
if (!hold) return;
|
|
3205
|
+
try {
|
|
3206
|
+
const snap = await this.api.objects(this.key);
|
|
3207
|
+
if (this.hold_?.holdId !== hold.holdId) return;
|
|
3208
|
+
this.applySeatsMap(snap.seats);
|
|
3209
|
+
} catch {
|
|
3210
|
+
if (this.hold_?.holdId === hold.holdId) {
|
|
3211
|
+
this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 2e3);
|
|
3212
|
+
}
|
|
3213
|
+
return;
|
|
3214
|
+
}
|
|
3215
|
+
if (this.hold_?.holdId !== hold.holdId) return;
|
|
3216
|
+
if (hold.labels.some((label) => this.liveStatuses.get(label) === "held")) {
|
|
3217
|
+
this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 1e3);
|
|
3218
|
+
return;
|
|
3116
3219
|
}
|
|
3220
|
+
this.clearHold();
|
|
3117
3221
|
this.opts.onHoldExpired?.();
|
|
3118
3222
|
}
|
|
3119
3223
|
applySeatsMap(seats) {
|
|
3120
3224
|
const r = this.renderer;
|
|
3121
3225
|
if (!r) return;
|
|
3226
|
+
this.liveStatuses = new Map(Object.entries(seats));
|
|
3122
3227
|
if (this.allIds.length) r.setStatus(this.allIds, "free");
|
|
3123
3228
|
const byStatus = { free: [], held: [], booked: [], not_for_sale: [] };
|
|
3124
3229
|
for (const [label, st] of Object.entries(seats)) {
|
|
@@ -3129,6 +3234,10 @@ var PickerController = class {
|
|
|
3129
3234
|
if (byStatus[st].length) r.setStatus(byStatus[st], st);
|
|
3130
3235
|
});
|
|
3131
3236
|
this.opts.onStatusChange?.();
|
|
3237
|
+
this.clearBookedHoldIfSettled();
|
|
3238
|
+
}
|
|
3239
|
+
clearBookedHoldIfSettled() {
|
|
3240
|
+
if (this.hold_?.labels.every((label) => this.liveStatuses.get(label) === "booked")) this.clearHold();
|
|
3132
3241
|
}
|
|
3133
3242
|
async resnapshot() {
|
|
3134
3243
|
try {
|
|
@@ -3171,6 +3280,7 @@ var PickerController = class {
|
|
|
3171
3280
|
this.applySeatsMap(m.seats);
|
|
3172
3281
|
} else if (Array.isArray(m.changes)) {
|
|
3173
3282
|
for (const ch of m.changes) {
|
|
3283
|
+
this.liveStatuses.set(ch.label, ch.status);
|
|
3174
3284
|
const id = this.labelToId.get(ch.label);
|
|
3175
3285
|
if (!id) continue;
|
|
3176
3286
|
const next = mapStatus(ch.status);
|
|
@@ -3179,6 +3289,7 @@ var PickerController = class {
|
|
|
3179
3289
|
}
|
|
3180
3290
|
r.setStatus([id], next);
|
|
3181
3291
|
}
|
|
3292
|
+
this.clearBookedHoldIfSettled();
|
|
3182
3293
|
this.opts.onStatusChange?.();
|
|
3183
3294
|
}
|
|
3184
3295
|
};
|
|
@@ -3206,9 +3317,9 @@ var PickerController = class {
|
|
|
3206
3317
|
|
|
3207
3318
|
// src/i18n/bundles.ts
|
|
3208
3319
|
var LOADERS = {
|
|
3209
|
-
es: () => import("./es-
|
|
3210
|
-
de: () => import("./de-
|
|
3211
|
-
fr: () => import("./fr-
|
|
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 }))
|
|
3212
3323
|
};
|
|
3213
3324
|
var loaded = /* @__PURE__ */ new Set(["en"]);
|
|
3214
3325
|
async function loadLocale(code) {
|
|
@@ -3231,6 +3342,8 @@ export {
|
|
|
3231
3342
|
ACCESSIBILITY_TYPES,
|
|
3232
3343
|
CHART_STORAGE_KEY,
|
|
3233
3344
|
DEFAULT_CURRENCY,
|
|
3345
|
+
MAX_EVENT_INVENTORY,
|
|
3346
|
+
MAX_GA_CAPACITY,
|
|
3234
3347
|
PickerController,
|
|
3235
3348
|
SUPPORTED_LOCALES,
|
|
3236
3349
|
SeatmapRenderer,
|
|
@@ -3251,8 +3364,12 @@ export {
|
|
|
3251
3364
|
floorsOf,
|
|
3252
3365
|
formatDate,
|
|
3253
3366
|
formatMoney,
|
|
3367
|
+
gaAreasOf,
|
|
3368
|
+
gaUnitLabel,
|
|
3369
|
+
gaUnitLabels,
|
|
3254
3370
|
getLocale,
|
|
3255
3371
|
hiddenObjectIds,
|
|
3372
|
+
isGaUnitLabel,
|
|
3256
3373
|
isSectionHidden,
|
|
3257
3374
|
layerOf,
|
|
3258
3375
|
loadLocale,
|