@seatlayer/core 0.46.0 → 0.47.1
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/chunk-AZODENEL.js +97 -0
- package/dist/chunk-AZODENEL.js.map +1 -0
- package/dist/chunk-FVCOOLJO.js +335 -0
- package/dist/chunk-FVCOOLJO.js.map +1 -0
- package/dist/{chunk-5MRJCIZP.js → chunk-TCTAS4Z2.js} +88 -14
- package/dist/chunk-TCTAS4Z2.js.map +1 -0
- package/dist/{de-UHAOVDS3.js → de-ST4H423D.js} +6 -3
- package/dist/{de-UHAOVDS3.js.map → de-ST4H423D.js.map} +1 -1
- package/dist/{es-6TJS2L7S.js → es-WEC5NHRT.js} +6 -3
- package/dist/{es-6TJS2L7S.js.map → es-WEC5NHRT.js.map} +1 -1
- package/dist/{fr-MMSY7FPE.js → fr-SGBFNAQV.js} +6 -3
- package/dist/{fr-MMSY7FPE.js.map → fr-SGBFNAQV.js.map} +1 -1
- package/dist/index.cjs +251 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -4
- package/dist/index.d.ts +119 -4
- package/dist/index.js +152 -24
- package/dist/index.js.map +1 -1
- package/dist/{types-DBnRO2hX.d.cts → types-CE63BK0j.d.cts} +88 -10
- package/dist/{types-DBnRO2hX.d.ts → types-CE63BK0j.d.ts} +88 -10
- package/dist/view/panoramaDelivery.cjs +126 -0
- package/dist/view/panoramaDelivery.cjs.map +1 -0
- package/dist/view/panoramaDelivery.d.cts +34 -0
- package/dist/view/panoramaDelivery.d.ts +34 -0
- package/dist/view/panoramaDelivery.js +17 -0
- package/dist/view/panoramaDelivery.js.map +1 -0
- package/dist/view3d/crossfade/panorama.cjs +453 -0
- package/dist/view3d/crossfade/panorama.cjs.map +1 -0
- package/dist/view3d/crossfade/panorama.d.cts +110 -0
- package/dist/view3d/crossfade/panorama.d.ts +110 -0
- package/dist/view3d/crossfade/panorama.js +30 -0
- package/dist/view3d/crossfade/panorama.js.map +1 -0
- package/dist/view3d/index.cjs +1176 -128
- package/dist/view3d/index.cjs.map +1 -1
- package/dist/view3d/index.d.cts +73 -35
- package/dist/view3d/index.d.ts +73 -35
- package/dist/view3d/index.js +960 -300
- package/dist/view3d/index.js.map +1 -1
- package/package.json +28 -1
- package/dist/chunk-5MRJCIZP.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -72,7 +72,7 @@ var init_es = __esm({
|
|
|
72
72
|
"picker.viewFromSeat": "Vista desde el asiento {label}",
|
|
73
73
|
"picker.real360": "REAL 360\xB0",
|
|
74
74
|
"picker.preview": "VISTA PREVIA",
|
|
75
|
-
"picker.sightline": "\u2248 {m} m al escenario
|
|
75
|
+
"picker.sightline": "\u2248 {m} m al escenario",
|
|
76
76
|
"picker.panorama360": "Foto de 360\xB0 del lugar",
|
|
77
77
|
"picker.illustrationCaption": "ilustraci\xF3n \xB7 \u2248 {m} m del escenario",
|
|
78
78
|
"picker.restrictedView": "Visibilidad restringida",
|
|
@@ -80,7 +80,10 @@ var init_es = __esm({
|
|
|
80
80
|
"picker.premiumSeat": "Asiento premium",
|
|
81
81
|
"picker.hideLimitedView": "Ocultar asientos con visibilidad limitada",
|
|
82
82
|
"picker.bestSeatsPremium": "Mejores asientos",
|
|
83
|
-
"picker.premiumFallbackNote": "No hay un bloque premium de {count}: mostrando los mejores disponibles"
|
|
83
|
+
"picker.premiumFallbackNote": "No hay un bloque premium de {count}: mostrando los mejores disponibles",
|
|
84
|
+
"picker.loading3d": "Creando el recinto en 3D\u2026",
|
|
85
|
+
"picker.unavailable3d": "No se pudo iniciar la vista 3D. El mapa de asientos sigue disponible.",
|
|
86
|
+
"picker.jumpToSection": "Ir a una secci\xF3n"
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
});
|
|
@@ -132,7 +135,7 @@ var init_de = __esm({
|
|
|
132
135
|
"picker.viewFromSeat": "Ansicht von Platz {label}",
|
|
133
136
|
"picker.real360": "REAL 360\xB0",
|
|
134
137
|
"picker.preview": "VORSCHAU",
|
|
135
|
-
"picker.sightline": "\u2248 {m} m zur B\xFChne
|
|
138
|
+
"picker.sightline": "\u2248 {m} m zur B\xFChne",
|
|
136
139
|
"picker.panorama360": "360\xB0-Veranstaltungsfotos",
|
|
137
140
|
"picker.illustrationCaption": "Illustration \xB7 \u2248 {m} m von der B\xFChne",
|
|
138
141
|
"picker.restrictedView": "Eingeschr\xE4nkte Sicht",
|
|
@@ -140,7 +143,10 @@ var init_de = __esm({
|
|
|
140
143
|
"picker.premiumSeat": "Premium-Platz",
|
|
141
144
|
"picker.hideLimitedView": "Pl\xE4tze mit eingeschr\xE4nkter Sicht ausblenden",
|
|
142
145
|
"picker.bestSeatsPremium": "Beste Pl\xE4tze",
|
|
143
|
-
"picker.premiumFallbackNote": "Kein Premium-Block mit {count} Pl\xE4tzen \u2014 beste verf\xFCgbare werden angezeigt"
|
|
146
|
+
"picker.premiumFallbackNote": "Kein Premium-Block mit {count} Pl\xE4tzen \u2014 beste verf\xFCgbare werden angezeigt",
|
|
147
|
+
"picker.loading3d": "3D-Veranstaltungsort wird aufgebaut\u2026",
|
|
148
|
+
"picker.unavailable3d": "3D konnte nicht gestartet werden. Der Sitzplan bleibt verf\xFCgbar.",
|
|
149
|
+
"picker.jumpToSection": "Zum Bereich springen"
|
|
144
150
|
};
|
|
145
151
|
}
|
|
146
152
|
});
|
|
@@ -192,7 +198,7 @@ var init_fr = __esm({
|
|
|
192
198
|
"picker.viewFromSeat": "Vue depuis le si\xE8ge {label}",
|
|
193
199
|
"picker.real360": "VRAI 360\xB0",
|
|
194
200
|
"picker.preview": "APER\xC7U",
|
|
195
|
-
"picker.sightline": "\u2248 {m} m de la sc\xE8ne
|
|
201
|
+
"picker.sightline": "\u2248 {m} m de la sc\xE8ne",
|
|
196
202
|
"picker.panorama360": "Photo panoramique 360\xB0 du lieu",
|
|
197
203
|
"picker.illustrationCaption": "illustration \xB7 \u2248 {m} m de la sc\xE8ne",
|
|
198
204
|
"picker.restrictedView": "Visibilit\xE9 r\xE9duite",
|
|
@@ -200,7 +206,10 @@ var init_fr = __esm({
|
|
|
200
206
|
"picker.premiumSeat": "Place premium",
|
|
201
207
|
"picker.hideLimitedView": "Masquer les places \xE0 visibilit\xE9 r\xE9duite",
|
|
202
208
|
"picker.bestSeatsPremium": "Meilleures places",
|
|
203
|
-
"picker.premiumFallbackNote": "Aucun bloc premium de {count} \u2014 affichage des meilleures places disponibles"
|
|
209
|
+
"picker.premiumFallbackNote": "Aucun bloc premium de {count} \u2014 affichage des meilleures places disponibles",
|
|
210
|
+
"picker.loading3d": "Cr\xE9ation de la salle en 3D\u2026",
|
|
211
|
+
"picker.unavailable3d": "La 3D n\u2019a pas pu d\xE9marrer. Le plan des si\xE8ges reste disponible.",
|
|
212
|
+
"picker.jumpToSection": "Acc\xE9der \xE0 une section"
|
|
204
213
|
};
|
|
205
214
|
}
|
|
206
215
|
});
|
|
@@ -211,6 +220,7 @@ __export(index_exports, {
|
|
|
211
220
|
ACCESSIBILITY_RING_COLOR: () => ACCESSIBILITY_RING_COLOR,
|
|
212
221
|
ACCESSIBILITY_TYPES: () => ACCESSIBILITY_TYPES,
|
|
213
222
|
CHART_STORAGE_KEY: () => CHART_STORAGE_KEY,
|
|
223
|
+
CURRENCY_CHOICES: () => CURRENCY_CHOICES,
|
|
214
224
|
DEFAULT_CURRENCY: () => DEFAULT_CURRENCY,
|
|
215
225
|
LABEL_STYLE_MAX_SIZE: () => LABEL_STYLE_MAX_SIZE,
|
|
216
226
|
LABEL_STYLE_MIN_SIZE: () => LABEL_STYLE_MIN_SIZE,
|
|
@@ -331,7 +341,10 @@ var SURROUNDINGS_SHAPE_ROLES = [
|
|
|
331
341
|
"sound",
|
|
332
342
|
"concession",
|
|
333
343
|
"coat",
|
|
334
|
-
"wall"
|
|
344
|
+
"wall",
|
|
345
|
+
"rail",
|
|
346
|
+
"suite",
|
|
347
|
+
"obstruction"
|
|
335
348
|
];
|
|
336
349
|
var SURROUNDINGS_SHAPE_ROLE_SET = new Set(SURROUNDINGS_SHAPE_ROLES);
|
|
337
350
|
function layerOf(obj) {
|
|
@@ -360,6 +373,48 @@ function layerOf(obj) {
|
|
|
360
373
|
}
|
|
361
374
|
var CHART_STORAGE_KEY = "seatmap.chart";
|
|
362
375
|
|
|
376
|
+
// src/core/textLayout.ts
|
|
377
|
+
var glyphAdvance = (text) => Math.max(1, text.fontSize * 0.6 + (text.letterSpacing ?? 0));
|
|
378
|
+
function wrappedLineCount(text, usableWidth) {
|
|
379
|
+
const explicit = text.text.split(/\r?\n/);
|
|
380
|
+
if (!text.width) return Math.max(1, explicit.length);
|
|
381
|
+
const perLine = Math.max(1, Math.floor(usableWidth / glyphAdvance(text)));
|
|
382
|
+
let lines = 0;
|
|
383
|
+
for (const source of explicit) {
|
|
384
|
+
if (!source.length) {
|
|
385
|
+
lines += 1;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
let used = 0;
|
|
389
|
+
for (const word of source.split(/\s+/)) {
|
|
390
|
+
const length = word.length;
|
|
391
|
+
if (!used) {
|
|
392
|
+
lines += Math.max(1, Math.ceil(length / perLine));
|
|
393
|
+
used = length % perLine;
|
|
394
|
+
} else if (used + 1 + length <= perLine) used += 1 + length;
|
|
395
|
+
else {
|
|
396
|
+
lines += Math.max(1, Math.ceil(length / perLine));
|
|
397
|
+
used = length % perLine;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return Math.max(1, lines);
|
|
402
|
+
}
|
|
403
|
+
function textLayoutMetrics(text) {
|
|
404
|
+
const padding = text.background?.padding ?? 0;
|
|
405
|
+
const explicitLines = text.text.split(/\r?\n/);
|
|
406
|
+
const naturalWidth = Math.max(1, ...explicitLines.map((line) => line.length)) * glyphAdvance(text);
|
|
407
|
+
const width = text.width ?? naturalWidth + padding * 2;
|
|
408
|
+
const usableWidth = Math.max(1, width - padding * 2);
|
|
409
|
+
const lineCount = wrappedLineCount(text, usableWidth);
|
|
410
|
+
return {
|
|
411
|
+
width,
|
|
412
|
+
height: lineCount * text.fontSize * (text.lineHeight ?? 1.2) + padding * 2,
|
|
413
|
+
lineCount,
|
|
414
|
+
padding
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
363
418
|
// src/core/complexGeometry.ts
|
|
364
419
|
function cubicPoint(path, t2) {
|
|
365
420
|
const u = 1 - t2;
|
|
@@ -596,7 +651,8 @@ function resolveSegmentedRowGroups(objects) {
|
|
|
596
651
|
displayLabel: first.displayLabel,
|
|
597
652
|
totalSeats,
|
|
598
653
|
canonical: ordered[0],
|
|
599
|
-
viewFromSeatUrl: first.viewFromSeatUrl
|
|
654
|
+
viewFromSeatUrl: first.viewFromSeatUrl,
|
|
655
|
+
viewFromSeatMeta: first.viewFromSeatMeta
|
|
600
656
|
});
|
|
601
657
|
adjacencyOffset += row.seatCount;
|
|
602
658
|
displayOffset += row.seatCount;
|
|
@@ -1179,6 +1235,7 @@ function expandRowSlots(row, placement) {
|
|
|
1179
1235
|
wheelchairSpaceType: o?.wheelchairSpaceType,
|
|
1180
1236
|
commercial: Object.values(commercial).some((value) => value !== void 0 && value !== false && value !== "") ? commercial : void 0,
|
|
1181
1237
|
viewUrl: o?.viewFromSeatUrl ?? row.viewFromSeatUrl,
|
|
1238
|
+
viewMeta: o?.viewFromSeatUrl ? o.viewFromSeatMeta : row.viewFromSeatMeta,
|
|
1182
1239
|
labelStyle: o?.labelStyle
|
|
1183
1240
|
};
|
|
1184
1241
|
});
|
|
@@ -1200,6 +1257,7 @@ function expandRow(row) {
|
|
|
1200
1257
|
wheelchairSpaceType: slot.wheelchairSpaceType,
|
|
1201
1258
|
commercial: slot.commercial,
|
|
1202
1259
|
viewUrl: slot.viewUrl,
|
|
1260
|
+
viewMeta: slot.viewMeta,
|
|
1203
1261
|
labelStyle: slot.labelStyle
|
|
1204
1262
|
});
|
|
1205
1263
|
}
|
|
@@ -1238,6 +1296,7 @@ function expandTableSlots(t2) {
|
|
|
1238
1296
|
wheelchairSpaceType: override?.wheelchairSpaceType,
|
|
1239
1297
|
commercial: override?.commercial,
|
|
1240
1298
|
viewUrl: override?.viewFromSeatUrl,
|
|
1299
|
+
viewMeta: override?.viewFromSeatUrl ? override.viewFromSeatMeta : void 0,
|
|
1241
1300
|
labelStyle: override?.labelStyle,
|
|
1242
1301
|
...side ? { side } : {}
|
|
1243
1302
|
};
|
|
@@ -1309,6 +1368,7 @@ function expandTable(t2) {
|
|
|
1309
1368
|
...slot.wheelchairSpaceType ? { wheelchairSpaceType: slot.wheelchairSpaceType } : {},
|
|
1310
1369
|
...slot.commercial ? { commercial: slot.commercial } : {},
|
|
1311
1370
|
...slot.viewUrl ? { viewUrl: slot.viewUrl } : {},
|
|
1371
|
+
...slot.viewUrl && slot.viewMeta ? { viewMeta: slot.viewMeta } : {},
|
|
1312
1372
|
...slot.labelStyle ? { labelStyle: slot.labelStyle } : {}
|
|
1313
1373
|
}));
|
|
1314
1374
|
}
|
|
@@ -1491,7 +1551,10 @@ function expandFloorObjects(objects, zones, fallbackFocal, viewFallback) {
|
|
|
1491
1551
|
if (!overrides2.get(physicalIndex)?.displayLabel) {
|
|
1492
1552
|
seat.displayLabel = seatDisplayLabel(obj, physicalIndex, logical);
|
|
1493
1553
|
}
|
|
1494
|
-
seat.viewUrl
|
|
1554
|
+
if (!seat.viewUrl && logical.viewFromSeatUrl) {
|
|
1555
|
+
seat.viewUrl = logical.viewFromSeatUrl;
|
|
1556
|
+
seat.viewMeta = logical.viewFromSeatMeta;
|
|
1557
|
+
}
|
|
1495
1558
|
}
|
|
1496
1559
|
}
|
|
1497
1560
|
}
|
|
@@ -1500,8 +1563,14 @@ function expandFloorObjects(objects, zones, fallbackFocal, viewFallback) {
|
|
|
1500
1563
|
const zone = owner?.zone ? zones?.find((candidate) => candidate.id === owner.zone) : void 0;
|
|
1501
1564
|
const resolvedFocal = zone?.focalPoint ?? fallbackFocal;
|
|
1502
1565
|
for (const seat of seats) {
|
|
1503
|
-
if (
|
|
1504
|
-
|
|
1566
|
+
if (!seat.viewUrl && inheritedView) {
|
|
1567
|
+
seat.viewUrl = inheritedView;
|
|
1568
|
+
seat.viewMeta = owner?.viewFromSeatMeta;
|
|
1569
|
+
}
|
|
1570
|
+
if (!seat.viewUrl && viewFallback) {
|
|
1571
|
+
seat.viewUrl = viewFallback.url;
|
|
1572
|
+
seat.viewMeta = viewFallback.meta;
|
|
1573
|
+
}
|
|
1505
1574
|
if (owner) seat.sectionId = owner.logicalSectionId ?? owner.id;
|
|
1506
1575
|
if (owner?.zone) seat.zoneId = owner.zone;
|
|
1507
1576
|
if (resolvedFocal) seat.focalPoint = { ...resolvedFocal };
|
|
@@ -1515,15 +1584,24 @@ function expandChart(doc, options = {}) {
|
|
|
1515
1584
|
const out2 = [];
|
|
1516
1585
|
for (const floor of doc.floors) {
|
|
1517
1586
|
const floorFocal = floor.focalPoint ?? doc.focalPoint;
|
|
1518
|
-
const floorView = floor.viewFromSeatUrl
|
|
1587
|
+
const floorView = floor.viewFromSeatUrl ? { url: floor.viewFromSeatUrl, meta: floor.viewFromSeatMeta } : doc.viewFromSeatUrl ? { url: doc.viewFromSeatUrl, meta: doc.viewFromSeatMeta } : void 0;
|
|
1519
1588
|
const seats = expandFloorObjects(floor.objects, doc.zones, floorFocal, floorView);
|
|
1520
|
-
|
|
1589
|
+
if (options.resolveEyeHeights !== false) {
|
|
1590
|
+
assignEyeHeights(floor.objects, floor.focalPoint ?? doc.focalPoint, floor.baseHeightM ?? 0, seats);
|
|
1591
|
+
}
|
|
1521
1592
|
out2.push(...seats);
|
|
1522
1593
|
}
|
|
1523
1594
|
return out2;
|
|
1524
1595
|
}
|
|
1525
|
-
const out = expandFloorObjects(
|
|
1526
|
-
|
|
1596
|
+
const out = expandFloorObjects(
|
|
1597
|
+
doc.objects,
|
|
1598
|
+
doc.zones,
|
|
1599
|
+
doc.focalPoint,
|
|
1600
|
+
doc.viewFromSeatUrl ? { url: doc.viewFromSeatUrl, meta: doc.viewFromSeatMeta } : void 0
|
|
1601
|
+
);
|
|
1602
|
+
if (options.resolveEyeHeights !== false) {
|
|
1603
|
+
assignEyeHeights(doc.objects, doc.focalPoint, options.floorBaseHeightM ?? 0, out);
|
|
1604
|
+
}
|
|
1527
1605
|
return out;
|
|
1528
1606
|
}
|
|
1529
1607
|
function assignEyeHeights(objects, focal, floorBaseHeightM, seats) {
|
|
@@ -1581,9 +1659,15 @@ function chartBounds(doc) {
|
|
|
1581
1659
|
if (x > maxX) maxX = x;
|
|
1582
1660
|
if (y > maxY) maxY = y;
|
|
1583
1661
|
};
|
|
1584
|
-
for (const s of expandChart(doc)) acc(s.x, s.y);
|
|
1585
1662
|
for (const obj of allObjects(doc)) {
|
|
1586
|
-
if (obj.type === "
|
|
1663
|
+
if (obj.type === "row") {
|
|
1664
|
+
const overrides2 = new Map((obj.overrides ?? []).map((override) => [override.index, override]));
|
|
1665
|
+
rowSeatPositions(obj).forEach((point, index) => {
|
|
1666
|
+
const override = overrides2.get(index);
|
|
1667
|
+
if (override?.skip) return;
|
|
1668
|
+
acc(point.x + (override?.dx ?? 0), point.y + (override?.dy ?? 0));
|
|
1669
|
+
});
|
|
1670
|
+
} else if (obj.type === "gaArea") {
|
|
1587
1671
|
for (const p of obj.points) acc(p.x, p.y);
|
|
1588
1672
|
} else if (obj.type === "section") {
|
|
1589
1673
|
for (const p of obj.outline) acc(p.x, p.y);
|
|
@@ -1607,9 +1691,9 @@ function chartBounds(doc) {
|
|
|
1607
1691
|
acc(obj.center.x - ext, obj.center.y - ext);
|
|
1608
1692
|
acc(obj.center.x + ext, obj.center.y + ext);
|
|
1609
1693
|
} else if (obj.type === "text") {
|
|
1610
|
-
const
|
|
1694
|
+
const box = textLayoutMetrics(obj);
|
|
1611
1695
|
acc(obj.position.x, obj.position.y);
|
|
1612
|
-
acc(obj.position.x +
|
|
1696
|
+
acc(obj.position.x + box.width, obj.position.y + box.height);
|
|
1613
1697
|
}
|
|
1614
1698
|
}
|
|
1615
1699
|
for (const image of [doc.referenceImage, doc.backgroundImage]) {
|
|
@@ -2823,6 +2907,7 @@ function decomposeAffineLinear(affine) {
|
|
|
2823
2907
|
|
|
2824
2908
|
// src/lib/money.ts
|
|
2825
2909
|
var DEFAULT_CURRENCY = "USD";
|
|
2910
|
+
var CURRENCY_CHOICES = ["USD", "EUR", "GBP", "CAD", "AUD", "INR", "AED", "SGD", "JPY", "CHF", "SEK", "NZD", "ZAR", "MXN", "BRL"];
|
|
2826
2911
|
var displayLocale;
|
|
2827
2912
|
function setMoneyLocale(locale) {
|
|
2828
2913
|
displayLocale = locale;
|
|
@@ -2903,7 +2988,7 @@ var en = {
|
|
|
2903
2988
|
"picker.viewFromSeat": "View from seat {label}",
|
|
2904
2989
|
"picker.real360": "REAL 360\xB0",
|
|
2905
2990
|
"picker.preview": "PREVIEW",
|
|
2906
|
-
"picker.sightline": "\u2248 {m} m to stage
|
|
2991
|
+
"picker.sightline": "\u2248 {m} m to stage",
|
|
2907
2992
|
"picker.panorama360": "360\xB0 venue photo",
|
|
2908
2993
|
"picker.illustrationCaption": "illustration \xB7 \u2248 {m} m from stage",
|
|
2909
2994
|
"picker.restrictedView": "Restricted view",
|
|
@@ -2911,7 +2996,10 @@ var en = {
|
|
|
2911
2996
|
"picker.premiumSeat": "Premium seat",
|
|
2912
2997
|
"picker.hideLimitedView": "Hide limited-view seats",
|
|
2913
2998
|
"picker.bestSeatsPremium": "Best seats",
|
|
2914
|
-
"picker.premiumFallbackNote": "No premium block of {count} \u2014 showing best overall"
|
|
2999
|
+
"picker.premiumFallbackNote": "No premium block of {count} \u2014 showing best overall",
|
|
3000
|
+
"picker.loading3d": "Building the 3D venue\u2026",
|
|
3001
|
+
"picker.unavailable3d": "3D could not start. The seat map is still available.",
|
|
3002
|
+
"picker.jumpToSection": "Jump to section"
|
|
2915
3003
|
};
|
|
2916
3004
|
|
|
2917
3005
|
// src/i18n/index.ts
|
|
@@ -5854,7 +5942,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
5854
5942
|
this.freeTextById.set(obj.id, { node: label, background: "#232c40", kind: "table" });
|
|
5855
5943
|
}
|
|
5856
5944
|
renderText(obj) {
|
|
5857
|
-
const background = this.canvasBackground;
|
|
5945
|
+
const background = obj.background?.color ?? this.canvasBackground;
|
|
5858
5946
|
const preferredInk = obj.color ?? this.theme.textColor ?? DEF_TEXT;
|
|
5859
5947
|
const iconPath = obj.semanticKind === "icon" ? venueIconPath(obj.iconKey) : void 0;
|
|
5860
5948
|
if (iconPath) {
|
|
@@ -5878,23 +5966,54 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
5878
5966
|
this.bgLayer.add(iconNode);
|
|
5879
5967
|
return;
|
|
5880
5968
|
}
|
|
5969
|
+
const padding = obj.background?.padding ?? 0;
|
|
5970
|
+
const opacity = obj.opacity ?? 1;
|
|
5881
5971
|
const node = new import_Text.Text({
|
|
5882
5972
|
x: obj.position.x,
|
|
5883
5973
|
y: obj.position.y,
|
|
5884
5974
|
text: obj.text,
|
|
5885
5975
|
fontSize: obj.fontSize,
|
|
5886
5976
|
rotation: obj.rotation,
|
|
5887
|
-
|
|
5977
|
+
// Keep the buyer glyph metrics identical to Designer: wrapping must not
|
|
5978
|
+
// gain or lose a line when the authored chart is published.
|
|
5979
|
+
fontStyle: konvaFontStyle(obj.bold, obj.italic, "600"),
|
|
5888
5980
|
// Authored ink remains preferred, but an embed/theme surface can change
|
|
5889
5981
|
// the actual canvas. Fail over to readable black/white instead of
|
|
5890
5982
|
// painting an otherwise valid caption invisibly on that active surface.
|
|
5891
5983
|
fill: stateAwareBookableLabelInk(background, preferredInk),
|
|
5892
5984
|
fontFamily: obj.fontFamily ?? this.labelFont(),
|
|
5985
|
+
...obj.width != null ? { width: obj.width } : {},
|
|
5986
|
+
align: obj.align ?? "left",
|
|
5987
|
+
lineHeight: obj.lineHeight ?? 1.2,
|
|
5988
|
+
letterSpacing: obj.letterSpacing ?? 0,
|
|
5989
|
+
textDecoration: obj.underline ? "underline" : "",
|
|
5990
|
+
padding,
|
|
5991
|
+
opacity,
|
|
5992
|
+
wrap: "word",
|
|
5893
5993
|
listening: false,
|
|
5894
|
-
perfectDrawEnabled: false
|
|
5994
|
+
perfectDrawEnabled: false,
|
|
5995
|
+
name: "buyer-free-text"
|
|
5895
5996
|
});
|
|
5997
|
+
let backdrop;
|
|
5998
|
+
if (obj.background) {
|
|
5999
|
+
backdrop = new import_Rect.Rect({
|
|
6000
|
+
x: obj.position.x,
|
|
6001
|
+
y: obj.position.y,
|
|
6002
|
+
width: node.width(),
|
|
6003
|
+
height: node.height(),
|
|
6004
|
+
rotation: obj.rotation,
|
|
6005
|
+
fill: obj.background.color,
|
|
6006
|
+
opacity: opacity * (obj.background.opacity ?? 0.9),
|
|
6007
|
+
cornerRadius: obj.background.cornerRadius ?? 4,
|
|
6008
|
+
listening: false,
|
|
6009
|
+
perfectDrawEnabled: false,
|
|
6010
|
+
name: "buyer-text-background"
|
|
6011
|
+
});
|
|
6012
|
+
this.bgLayer.add(backdrop);
|
|
6013
|
+
}
|
|
5896
6014
|
this.freeTextById.set(obj.id, {
|
|
5897
6015
|
node,
|
|
6016
|
+
backdrop,
|
|
5898
6017
|
background,
|
|
5899
6018
|
kind: "free-text"
|
|
5900
6019
|
});
|
|
@@ -7674,10 +7793,12 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
7674
7793
|
}
|
|
7675
7794
|
updateFreeTextVisibility() {
|
|
7676
7795
|
const effectiveScale = this.exportMode ? Math.max(this.effScale(), LABEL_SCALE) : this.effScale();
|
|
7677
|
-
for (const { objectId, node, categoryKey, kind } of this.freeTextById.values()) {
|
|
7796
|
+
for (const { objectId, node, backdrop, categoryKey, kind } of this.freeTextById.values()) {
|
|
7678
7797
|
const gaDimmed = categoryKey != null && (kind === "ga-label" || kind === "ga-capacity") && this.gaCategoryDimmed(categoryKey);
|
|
7679
7798
|
const gaOverviewHidden = objectId != null && (kind === "ga-label" || kind === "ga-capacity") && this.gaById.get(objectId)?.sectionId != null && effectiveScale < CACHE_THRESHOLD;
|
|
7680
|
-
|
|
7799
|
+
const visible = !gaDimmed && !gaOverviewHidden && isBookableLabelLegibleAtScale(node.fontSize(), effectiveScale);
|
|
7800
|
+
node.visible(visible);
|
|
7801
|
+
backdrop?.visible(visible);
|
|
7681
7802
|
}
|
|
7682
7803
|
for (const { node, fontSize } of this.iconNodeById.values()) {
|
|
7683
7804
|
node.visible(isBookableLabelLegibleAtScale(fontSize, effectiveScale));
|
|
@@ -8164,6 +8285,11 @@ function groupedTableInventory(doc, modelVersion) {
|
|
|
8164
8285
|
// src/picker/PickerController.ts
|
|
8165
8286
|
var DEFAULT_MAX_SELECTION = 10;
|
|
8166
8287
|
var MAX_BACKOFF_MS = 15e3;
|
|
8288
|
+
var MAP_THEME_KEYS = ["background", "rowLabelColor", "textColor", "selectionColor"];
|
|
8289
|
+
function sameMapTheme(a, b) {
|
|
8290
|
+
if (!a || !b) return !a && !b;
|
|
8291
|
+
return MAP_THEME_KEYS.every((key) => a[key] === b[key]);
|
|
8292
|
+
}
|
|
8167
8293
|
function errInfo(err) {
|
|
8168
8294
|
const e = err ?? {};
|
|
8169
8295
|
return { status: e.status, conflicts: e.conflicts, reason: e.reason };
|
|
@@ -8179,6 +8305,8 @@ var PickerController = class {
|
|
|
8179
8305
|
this._doc = null;
|
|
8180
8306
|
/** Section/zone ids hidden from buyers this event (3.3) — seats vanish, not grey. */
|
|
8181
8307
|
this.hidden = /* @__PURE__ */ new Set();
|
|
8308
|
+
/** Host overrides folded over the chart's own theme in `visibleDoc()`. */
|
|
8309
|
+
this.mapTheme = null;
|
|
8182
8310
|
/** Section/zone ids in the `closed` event-state (Phase 2) — seats stay, greyed
|
|
8183
8311
|
* + not pickable. Kept separate from `hidden` (which strips them). */
|
|
8184
8312
|
this.closedSections = /* @__PURE__ */ new Set();
|
|
@@ -8214,6 +8342,16 @@ var PickerController = class {
|
|
|
8214
8342
|
// hold state
|
|
8215
8343
|
this.hold_ = null;
|
|
8216
8344
|
this.liveStatuses = /* @__PURE__ */ new Map();
|
|
8345
|
+
/**
|
|
8346
|
+
* What a label absent from `liveStatuses` is.
|
|
8347
|
+
*
|
|
8348
|
+
* `free` while the verbose HTTP map is the source (it names every unit), but a
|
|
8349
|
+
* compact realtime frame names only its exceptions — so on a mostly-sold event
|
|
8350
|
+
* the seats NOT listed are the booked ones. Read through {@link statusOf};
|
|
8351
|
+
* a bare `liveStatuses.get()` silently answers `undefined` for the majority of
|
|
8352
|
+
* a sold-out venue.
|
|
8353
|
+
*/
|
|
8354
|
+
this.liveDefault = "free";
|
|
8217
8355
|
this.currency = "USD";
|
|
8218
8356
|
this.expiryTimer = null;
|
|
8219
8357
|
/** Whether the last emitted hint was non-null (avoids clearing repeatedly). */
|
|
@@ -8222,13 +8360,66 @@ var PickerController = class {
|
|
|
8222
8360
|
this.api = options.transport;
|
|
8223
8361
|
this.key = options.eventKey;
|
|
8224
8362
|
this.maxSelection = options.maxSelection ?? DEFAULT_MAX_SELECTION;
|
|
8363
|
+
this.mapTheme = options.mapTheme ?? null;
|
|
8225
8364
|
}
|
|
8226
8365
|
get doc() {
|
|
8227
8366
|
return this._doc;
|
|
8228
8367
|
}
|
|
8229
|
-
/**
|
|
8368
|
+
/**
|
|
8369
|
+
* The chart with hidden sections' seats removed, and the host's map theme
|
|
8370
|
+
* folded over the chart's own — what buyers actually see.
|
|
8371
|
+
*
|
|
8372
|
+
* THE THEME IS MERGED HERE rather than pushed at the renderer separately
|
|
8373
|
+
* because the renderer reads its theme out of the document it is given. One
|
|
8374
|
+
* merge point means every rebuild — a hidden section arriving mid-sale, a
|
|
8375
|
+
* floor switch, a theme change — repaints from the same resolved theme
|
|
8376
|
+
* instead of from whichever of two sources ran last.
|
|
8377
|
+
*
|
|
8378
|
+
* The chart's theme is the BASE and only named keys are overwritten, so a
|
|
8379
|
+
* host that overrides the ground does not thereby erase the organizer's
|
|
8380
|
+
* `seatScale`, `fontFamily`, logo or badge entitlement.
|
|
8381
|
+
*/
|
|
8230
8382
|
visibleDoc() {
|
|
8231
|
-
|
|
8383
|
+
if (!this._doc) return { objects: [] };
|
|
8384
|
+
const doc = applyHidden(this._doc, this.hidden);
|
|
8385
|
+
if (!this.mapTheme) return doc;
|
|
8386
|
+
const theme = { ...doc.theme ?? {} };
|
|
8387
|
+
for (const key of MAP_THEME_KEYS) {
|
|
8388
|
+
const value = this.mapTheme[key];
|
|
8389
|
+
if (value) theme[key] = value;
|
|
8390
|
+
}
|
|
8391
|
+
return { ...doc, theme };
|
|
8392
|
+
}
|
|
8393
|
+
/**
|
|
8394
|
+
* Re-ink the drawn map, in place, without losing the buyer's place in it.
|
|
8395
|
+
*
|
|
8396
|
+
* WHY THIS IS A SETTER AND NOT A MOUNT OPTION. On a templated event page the
|
|
8397
|
+
* palette is not known when the map mounts: the page config is a separate
|
|
8398
|
+
* cached read and the map is explicitly not allowed to wait for it. The
|
|
8399
|
+
* alternative — remounting the widget once the palette lands — would destroy
|
|
8400
|
+
* a hold the buyer may already be holding.
|
|
8401
|
+
*
|
|
8402
|
+
* The rebuild is the SAME recipe `render()` uses (setChart → colorblind →
|
|
8403
|
+
* closed sections → statuses), because setChart resets all four; the one
|
|
8404
|
+
* addition is restoring the selection, which `render()` has no need to do.
|
|
8405
|
+
* Statuses are repainted from the map already in memory rather than re-read,
|
|
8406
|
+
* so this costs no round trip and cannot flash a stale seat.
|
|
8407
|
+
*
|
|
8408
|
+
* Returns whether anything actually changed, so a caller may call it freely.
|
|
8409
|
+
*/
|
|
8410
|
+
setMapTheme(theme) {
|
|
8411
|
+
if (sameMapTheme(this.mapTheme, theme ?? null)) return false;
|
|
8412
|
+
this.mapTheme = theme ?? null;
|
|
8413
|
+
const r = this.renderer;
|
|
8414
|
+
if (!r) return true;
|
|
8415
|
+
const selected = r.getSelection().map((seat) => seat.id);
|
|
8416
|
+
const floorId = this.getActiveFloorId();
|
|
8417
|
+
r.setChart(this.visibleDoc(), floorId ? { floorId } : void 0);
|
|
8418
|
+
if (this.opts.colorblindSafe) r.setColorblindSafe?.(true);
|
|
8419
|
+
if (this.closedSections.size) r.setClosedSections?.([...this.closedSections]);
|
|
8420
|
+
this.applySeatsMap(Object.fromEntries(this.liveStatuses), this.liveDefault);
|
|
8421
|
+
if (selected.length) r.select?.(selected);
|
|
8422
|
+
return true;
|
|
8232
8423
|
}
|
|
8233
8424
|
/** Adopt a new hidden set; rebuild the visible chart only if it differs. */
|
|
8234
8425
|
syncHidden(ids) {
|
|
@@ -8417,12 +8608,14 @@ var PickerController = class {
|
|
|
8417
8608
|
}
|
|
8418
8609
|
this.renderer = renderer;
|
|
8419
8610
|
let seats = null;
|
|
8611
|
+
let seatsDefault = "free";
|
|
8420
8612
|
let closedIds = [];
|
|
8421
8613
|
try {
|
|
8422
8614
|
const objs = await this.api.objects(this.key);
|
|
8423
8615
|
this.hidden = new Set(objs.hidden ?? []);
|
|
8424
8616
|
closedIds = (objs.closed ?? []).filter((x) => typeof x === "string");
|
|
8425
8617
|
seats = objs.seats;
|
|
8618
|
+
seatsDefault = objs.default ?? "free";
|
|
8426
8619
|
} catch {
|
|
8427
8620
|
}
|
|
8428
8621
|
if (this.closed) {
|
|
@@ -8434,7 +8627,7 @@ var PickerController = class {
|
|
|
8434
8627
|
if (this.opts.colorblindSafe) renderer.setColorblindSafe?.(true);
|
|
8435
8628
|
this.closedSections = new Set(closedIds);
|
|
8436
8629
|
if (closedIds.length) renderer.setClosedSections?.(closedIds);
|
|
8437
|
-
if (seats) this.applySeatsMap(seats);
|
|
8630
|
+
if (seats) this.applySeatsMap(seats, seatsDefault);
|
|
8438
8631
|
this.attachVisibilityListener();
|
|
8439
8632
|
this.connect();
|
|
8440
8633
|
return {
|
|
@@ -8443,6 +8636,7 @@ var PickerController = class {
|
|
|
8443
8636
|
eventName: res.event.name,
|
|
8444
8637
|
venue: res.event.venue,
|
|
8445
8638
|
startsAt: res.event.startsAt,
|
|
8639
|
+
timezone: res.event.timezone ?? null,
|
|
8446
8640
|
currency,
|
|
8447
8641
|
// 'test' ⇒ sandbox event: hosts render a TEST MODE ribbon (Phase 11).
|
|
8448
8642
|
mode: res.event.mode ?? "live"
|
|
@@ -8751,7 +8945,7 @@ var PickerController = class {
|
|
|
8751
8945
|
...area.displayLabel ? { displayLabel: area.displayLabel } : {},
|
|
8752
8946
|
...area.displayType ? { displayType: area.displayType } : {},
|
|
8753
8947
|
capacity: Math.max(0, Math.floor(area.capacity)),
|
|
8754
|
-
available: gaUnitLabels(area).filter((label) =>
|
|
8948
|
+
available: gaUnitLabels(area).filter((label) => this.statusOf(label) === "free").length,
|
|
8755
8949
|
categoryKey: area.categoryKey,
|
|
8756
8950
|
tiers: category?.tiers,
|
|
8757
8951
|
price: category?.tiers?.[0]?.price ?? category?.price ?? 0,
|
|
@@ -8765,7 +8959,7 @@ var PickerController = class {
|
|
|
8765
8959
|
if (!doc || !Number.isFinite(qty) || qty < 1) return null;
|
|
8766
8960
|
const area = gaAreasOf(doc).find((candidate) => candidate.id === areaId);
|
|
8767
8961
|
if (!area) return null;
|
|
8768
|
-
const labels = gaUnitLabels(area).filter((label) => !this.hold_?.labels.includes(label) &&
|
|
8962
|
+
const labels = gaUnitLabels(area).filter((label) => !this.hold_?.labels.includes(label) && this.statusOf(label) === "free").slice(0, Math.floor(qty));
|
|
8769
8963
|
if (labels.length !== Math.floor(qty)) return null;
|
|
8770
8964
|
const selections = /* @__PURE__ */ new Map();
|
|
8771
8965
|
for (const item of this.hold_?.items ?? []) selections.set(item.label, {
|
|
@@ -9460,7 +9654,7 @@ var PickerController = class {
|
|
|
9460
9654
|
try {
|
|
9461
9655
|
const snap = await this.api.objects(this.key);
|
|
9462
9656
|
if (this.hold_?.holdId !== hold.holdId) return;
|
|
9463
|
-
this.applySeatsMap(snap.seats);
|
|
9657
|
+
this.applySeatsMap(snap.seats, snap.default ?? "free");
|
|
9464
9658
|
} catch {
|
|
9465
9659
|
if (this.hold_?.holdId === hold.holdId) {
|
|
9466
9660
|
this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 2e3);
|
|
@@ -9468,18 +9662,30 @@ var PickerController = class {
|
|
|
9468
9662
|
return;
|
|
9469
9663
|
}
|
|
9470
9664
|
if (this.hold_?.holdId !== hold.holdId) return;
|
|
9471
|
-
if (hold.labels.some((label) => this.
|
|
9665
|
+
if (hold.labels.some((label) => this.statusOf(label) === "held")) {
|
|
9472
9666
|
this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 1e3);
|
|
9473
9667
|
return;
|
|
9474
9668
|
}
|
|
9475
9669
|
this.clearHold();
|
|
9476
9670
|
this.opts.onHoldExpired?.();
|
|
9477
9671
|
}
|
|
9478
|
-
|
|
9672
|
+
/**
|
|
9673
|
+
* Repaint from an authoritative map of unit statuses.
|
|
9674
|
+
*
|
|
9675
|
+
* `defaultStatus` is what every unit NOT named in `seats` is. The verbose HTTP
|
|
9676
|
+
* route names every unit and leaves it at `free`; the compact realtime frame
|
|
9677
|
+
* names only the exceptions and states its own default, which on a mostly-sold
|
|
9678
|
+
* event is `booked` rather than `free`. Applying a compact map while assuming
|
|
9679
|
+
* `free` would paint a sold-out stadium as fully available, so the default is
|
|
9680
|
+
* a parameter rather than a constant.
|
|
9681
|
+
*/
|
|
9682
|
+
applySeatsMap(seats, defaultStatus = "free") {
|
|
9479
9683
|
const r = this.renderer;
|
|
9480
9684
|
if (!r) return;
|
|
9481
9685
|
this.liveStatuses = new Map(Object.entries(seats));
|
|
9482
|
-
|
|
9686
|
+
this.liveDefault = defaultStatus;
|
|
9687
|
+
const defaultSeatStatus = mapStatus(defaultStatus);
|
|
9688
|
+
if (this.allIds.length) r.setStatus(this.allIds, defaultSeatStatus);
|
|
9483
9689
|
r.setOwnedHold?.(
|
|
9484
9690
|
this.idsForLabels(this.hold_?.labels ?? [])
|
|
9485
9691
|
);
|
|
@@ -9487,15 +9693,19 @@ var PickerController = class {
|
|
|
9487
9693
|
for (const [label, st] of Object.entries(seats)) {
|
|
9488
9694
|
byStatus[mapStatus(st)].push(...this.idsForLabel(label));
|
|
9489
9695
|
}
|
|
9490
|
-
["held", "booked", "not_for_sale"].forEach((st) => {
|
|
9491
|
-
if (byStatus[st].length) r.setStatus(byStatus[st], st);
|
|
9696
|
+
["free", "held", "booked", "not_for_sale"].forEach((st) => {
|
|
9697
|
+
if (st !== defaultSeatStatus && byStatus[st].length) r.setStatus(byStatus[st], st);
|
|
9492
9698
|
});
|
|
9493
9699
|
this.clearBookedHoldIfSettled();
|
|
9494
9700
|
this.opts.onStatusChange?.();
|
|
9495
9701
|
}
|
|
9702
|
+
/** The live status of one unit, honouring the projection's default. */
|
|
9703
|
+
statusOf(label) {
|
|
9704
|
+
return this.liveStatuses.get(label) ?? this.liveDefault;
|
|
9705
|
+
}
|
|
9496
9706
|
clearBookedHoldIfSettled() {
|
|
9497
9707
|
const hold = this.hold_;
|
|
9498
|
-
if (hold?.labels.every((label) => this.
|
|
9708
|
+
if (hold?.labels.every((label) => this.statusOf(label) === "booked")) {
|
|
9499
9709
|
this.clearHold();
|
|
9500
9710
|
this.resetTableQuantitiesForLabels(hold.labels);
|
|
9501
9711
|
}
|
|
@@ -9503,7 +9713,7 @@ var PickerController = class {
|
|
|
9503
9713
|
async resnapshot() {
|
|
9504
9714
|
try {
|
|
9505
9715
|
const objs = await this.api.objects(this.key);
|
|
9506
|
-
this.applySeatsMap(objs.seats);
|
|
9716
|
+
this.applySeatsMap(objs.seats, objs.default ?? "free");
|
|
9507
9717
|
} catch {
|
|
9508
9718
|
}
|
|
9509
9719
|
}
|
|
@@ -9561,6 +9771,7 @@ var PickerController = class {
|
|
|
9561
9771
|
realtimeSink() {
|
|
9562
9772
|
return {
|
|
9563
9773
|
applyStatuses: (changes) => this.applyStatusChanges(changes),
|
|
9774
|
+
applyProjection: (projection) => this.applySeatsMap(projection.exceptions, projection.default),
|
|
9564
9775
|
resync: () => this.resnapshot(),
|
|
9565
9776
|
onSections: (hidden, closed) => {
|
|
9566
9777
|
const rebuilt = this.syncHidden(hidden);
|
|
@@ -10863,6 +11074,7 @@ async function loadLocale(code) {
|
|
|
10863
11074
|
ACCESSIBILITY_RING_COLOR,
|
|
10864
11075
|
ACCESSIBILITY_TYPES,
|
|
10865
11076
|
CHART_STORAGE_KEY,
|
|
11077
|
+
CURRENCY_CHOICES,
|
|
10866
11078
|
DEFAULT_CURRENCY,
|
|
10867
11079
|
LABEL_STYLE_MAX_SIZE,
|
|
10868
11080
|
LABEL_STYLE_MIN_SIZE,
|