@seatlayer/core 0.26.0 → 0.27.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-73TIXYJH.js → de-UHAOVDS3.js} +3 -2
- package/dist/de-UHAOVDS3.js.map +1 -0
- package/dist/{es-SKAODLTR.js → es-6TJS2L7S.js} +3 -2
- package/dist/es-6TJS2L7S.js.map +1 -0
- package/dist/{fr-J4637T6V.js → fr-MMSY7FPE.js} +3 -2
- package/dist/fr-MMSY7FPE.js.map +1 -0
- package/dist/index.cjs +396 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -2
- package/dist/index.d.ts +48 -2
- package/dist/index.js +393 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/de-73TIXYJH.js.map +0 -1
- package/dist/es-SKAODLTR.js.map +0 -1
- package/dist/fr-J4637T6V.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1547,6 +1547,169 @@ function buyerBackgroundImage(owner) {
|
|
|
1547
1547
|
return background?.url && !background.assetId ? background : void 0;
|
|
1548
1548
|
}
|
|
1549
1549
|
|
|
1550
|
+
// src/core/icons.ts
|
|
1551
|
+
var VENUE_ICON_VIEWBOX = 24;
|
|
1552
|
+
var VENUE_ICON_STROKE = 2;
|
|
1553
|
+
var WHEELCHAIR = "M13 4.6a1.6 1.6 0 1 0-3.2 0 1.6 1.6 0 0 0 3.2 0 M11 6.5V13h5l2.4 6 M15 16.4A5 5 0 1 1 9 11.3";
|
|
1554
|
+
var VENUE_ICONS = [
|
|
1555
|
+
// ---- Facilities --------------------------------------------------------
|
|
1556
|
+
{
|
|
1557
|
+
key: "restroom-men",
|
|
1558
|
+
label: "Men's restroom",
|
|
1559
|
+
group: "facilities",
|
|
1560
|
+
path: "M16 7a4 4 0 1 0-8 0 4 4 0 0 0 8 0 M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
key: "restroom-women",
|
|
1564
|
+
label: "Women's restroom",
|
|
1565
|
+
group: "facilities",
|
|
1566
|
+
path: "M15 5a3 3 0 1 0-6 0 3 3 0 0 0 6 0 M12 8l-4 10h8l-4-10 M10 18v4 M14 18v4"
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
key: "restroom-accessible",
|
|
1570
|
+
label: "Accessible restroom",
|
|
1571
|
+
group: "facilities",
|
|
1572
|
+
path: WHEELCHAIR
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
key: "first-aid",
|
|
1576
|
+
label: "First aid",
|
|
1577
|
+
group: "facilities",
|
|
1578
|
+
path: "M5 4h14a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1Z M12 8v8 M8 12h8"
|
|
1579
|
+
},
|
|
1580
|
+
{
|
|
1581
|
+
key: "coat-check",
|
|
1582
|
+
label: "Coat check",
|
|
1583
|
+
group: "facilities",
|
|
1584
|
+
path: "M12 6a2 2 0 0 1 0-4 2 2 0 0 1 1.6 3.2L21 13H3l8.4-7.8 M3 13h18"
|
|
1585
|
+
},
|
|
1586
|
+
{
|
|
1587
|
+
key: "atm",
|
|
1588
|
+
label: "ATM / cash",
|
|
1589
|
+
group: "facilities",
|
|
1590
|
+
path: "M2 6h20v12H2V6Z M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0 M6 9h.01 M18 15h.01"
|
|
1591
|
+
},
|
|
1592
|
+
{
|
|
1593
|
+
key: "info",
|
|
1594
|
+
label: "Info point",
|
|
1595
|
+
group: "facilities",
|
|
1596
|
+
path: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18 M12 11v5 M12 8h.01"
|
|
1597
|
+
},
|
|
1598
|
+
{
|
|
1599
|
+
key: "lost-found",
|
|
1600
|
+
label: "Lost & found",
|
|
1601
|
+
group: "facilities",
|
|
1602
|
+
path: "M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14 M16 16l5 5 M9 8.5a2 2 0 1 1 3 1.7c-.8.5-1 .8-1 1.8 M11 15h.01"
|
|
1603
|
+
},
|
|
1604
|
+
{
|
|
1605
|
+
key: "charging",
|
|
1606
|
+
label: "Charging point",
|
|
1607
|
+
group: "facilities",
|
|
1608
|
+
path: "M3 8h13v8H3V8Z M16 10h3v4h-3 M9.6 9l-2 3.5h2.5l-1.5 3"
|
|
1609
|
+
},
|
|
1610
|
+
{
|
|
1611
|
+
key: "smoking",
|
|
1612
|
+
label: "Smoking area",
|
|
1613
|
+
group: "facilities",
|
|
1614
|
+
path: "M2 15h13v3H2v-3Z M18 16h2 M19 8c0 1 1 1.5 1 2.5S19 12 19 13"
|
|
1615
|
+
},
|
|
1616
|
+
{
|
|
1617
|
+
key: "no-smoking",
|
|
1618
|
+
label: "No smoking",
|
|
1619
|
+
group: "facilities",
|
|
1620
|
+
path: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18 M5.6 5.6l12.8 12.8 M7 13h6v2H7v-2Z"
|
|
1621
|
+
},
|
|
1622
|
+
// ---- Food & drink ------------------------------------------------------
|
|
1623
|
+
{
|
|
1624
|
+
key: "food",
|
|
1625
|
+
label: "Food",
|
|
1626
|
+
group: "food-drink",
|
|
1627
|
+
path: "M7 3v6a2 2 0 0 0 4 0V3 M9 11v10 M17 3c-1.6 1-2.2 3-2.2 6 0 2 .9 3.2 2.2 3.6V21"
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
key: "bar",
|
|
1631
|
+
label: "Bar",
|
|
1632
|
+
group: "food-drink",
|
|
1633
|
+
path: "M4 5h16l-8 8-8-8Z M12 13v6 M8 20h8"
|
|
1634
|
+
},
|
|
1635
|
+
{
|
|
1636
|
+
key: "coffee",
|
|
1637
|
+
label: "Caf\xE9 / coffee",
|
|
1638
|
+
group: "food-drink",
|
|
1639
|
+
path: "M4 8h13v4a5 5 0 0 1-5 5H9a5 5 0 0 1-5-5V8Z M17 9h2a2 2 0 0 1 0 4h-2 M8 2v2 M11 2v2 M4 21h14"
|
|
1640
|
+
},
|
|
1641
|
+
{
|
|
1642
|
+
key: "water",
|
|
1643
|
+
label: "Water / drinks",
|
|
1644
|
+
group: "food-drink",
|
|
1645
|
+
path: "M12 22a7 7 0 0 1-7-7c0-5 7-12 7-12s7 7 7 12a7 7 0 0 1-7 7Z"
|
|
1646
|
+
},
|
|
1647
|
+
{
|
|
1648
|
+
key: "merch",
|
|
1649
|
+
label: "Merch / shop",
|
|
1650
|
+
group: "food-drink",
|
|
1651
|
+
path: "M6 8h12l-1 12H7L6 8Z M9 8V6a3 3 0 0 1 6 0v2"
|
|
1652
|
+
},
|
|
1653
|
+
// ---- Getting around ----------------------------------------------------
|
|
1654
|
+
{
|
|
1655
|
+
key: "entrance",
|
|
1656
|
+
label: "Entrance",
|
|
1657
|
+
group: "navigation",
|
|
1658
|
+
path: "M14 3h5a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-5 M3 12h11 M10 8l4 4-4 4"
|
|
1659
|
+
},
|
|
1660
|
+
{
|
|
1661
|
+
key: "exit",
|
|
1662
|
+
label: "Exit",
|
|
1663
|
+
group: "navigation",
|
|
1664
|
+
path: "M10 3H5a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h5 M14 12h7 M17 8l4 4-4 4"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
key: "emergency-exit",
|
|
1668
|
+
label: "Emergency exit",
|
|
1669
|
+
group: "navigation",
|
|
1670
|
+
path: "M14 4.6a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0 M12.5 8l-3.5 2 1.6 3.6-2 4.4 M12.5 10l3.5 1.5 M9 10.5l-3.5 1 M15 12h6 M18 9l3 3-3 3"
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
key: "stairs",
|
|
1674
|
+
label: "Stairs",
|
|
1675
|
+
group: "navigation",
|
|
1676
|
+
path: "M3 20v-4h4v-4h4v-4h4V4h5"
|
|
1677
|
+
},
|
|
1678
|
+
{
|
|
1679
|
+
key: "elevator",
|
|
1680
|
+
label: "Elevator",
|
|
1681
|
+
group: "navigation",
|
|
1682
|
+
path: "M5 3h14a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Z M8 11l1.5-2 1.5 2 M8 14l1.5 2 1.5-2 M15 8v8"
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
key: "parking",
|
|
1686
|
+
label: "Parking",
|
|
1687
|
+
group: "navigation",
|
|
1688
|
+
path: "M5 3h14a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Z M9 17V7h4a3 3 0 0 1 0 6H9"
|
|
1689
|
+
},
|
|
1690
|
+
// ---- Accessibility -----------------------------------------------------
|
|
1691
|
+
{
|
|
1692
|
+
key: "wheelchair",
|
|
1693
|
+
label: "Wheelchair access",
|
|
1694
|
+
group: "accessibility",
|
|
1695
|
+
path: WHEELCHAIR
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
key: "hearing",
|
|
1699
|
+
label: "Hearing assistance",
|
|
1700
|
+
group: "accessibility",
|
|
1701
|
+
path: "M8 20a4 4 0 0 1-2-3c0-1 .5-2 .5-3a4.5 4.5 0 1 1 9 0c0 1.4-1 2-2 2.4-1.2.5-1.5 1-1.5 2.2 M17 6a5 5 0 0 1 1 6 M19.5 4a8 8 0 0 1 1.2 9"
|
|
1702
|
+
}
|
|
1703
|
+
];
|
|
1704
|
+
var BY_KEY = new Map(VENUE_ICONS.map((icon) => [icon.key, icon]));
|
|
1705
|
+
function venueIcon(key) {
|
|
1706
|
+
return key ? BY_KEY.get(key) : void 0;
|
|
1707
|
+
}
|
|
1708
|
+
function venueIconPath(key) {
|
|
1709
|
+
return venueIcon(key)?.path;
|
|
1710
|
+
}
|
|
1711
|
+
var VENUE_ICON_KEYS = VENUE_ICONS.map((icon) => icon.key);
|
|
1712
|
+
|
|
1550
1713
|
// src/core/spatialIndex.ts
|
|
1551
1714
|
var DEFAULT_SEAT_RADIUS = 9;
|
|
1552
1715
|
function halfExtents(shape) {
|
|
@@ -1884,6 +2047,7 @@ var en = {
|
|
|
1884
2047
|
// renderer (drawn on the Konva map — shared by the embed SDK)
|
|
1885
2048
|
"map.aria": "Seating map. Use arrow keys to move between seats, Enter to select.",
|
|
1886
2049
|
"map.seatsLeft": "{count} LEFT",
|
|
2050
|
+
"map.soldOut": "SOLD OUT",
|
|
1887
2051
|
"map.fromPrice": "FROM {price}",
|
|
1888
2052
|
"map.statusHeld": "On hold",
|
|
1889
2053
|
"map.statusTaken": "Taken",
|
|
@@ -1891,7 +2055,7 @@ var en = {
|
|
|
1891
2055
|
"picker.floor": "Floor",
|
|
1892
2056
|
"picker.zoomLevel": "Zoom level",
|
|
1893
2057
|
"picker.rungTip.zones": "Venue overview \u2014 groups of sections such as North Stand or VIP",
|
|
1894
|
-
"picker.rungTip.sections": "Section blocks \u2014
|
|
2058
|
+
"picker.rungTip.sections": "Section blocks \u2014 sold-out and nearly-gone sections shade to show availability at a glance",
|
|
1895
2059
|
"picker.rungTip.seats": "Individual seats \u2014 blocks melt into dots",
|
|
1896
2060
|
"picker.rungLabel.zones": "ZONES",
|
|
1897
2061
|
"picker.rungLabel.sections": "SECTIONS",
|
|
@@ -2092,6 +2256,22 @@ function overviewPalette(canvasBackground) {
|
|
|
2092
2256
|
focalStroke: DARK_OVERVIEW_FOCAL_STROKE
|
|
2093
2257
|
};
|
|
2094
2258
|
}
|
|
2259
|
+
var SECTION_NEARLY_GONE_RATIO = 0.1;
|
|
2260
|
+
function overviewStateFill(palette, state) {
|
|
2261
|
+
const base = palette.sectionFill;
|
|
2262
|
+
const soldOut = desaturate(darken(base, 0.2), 0.85);
|
|
2263
|
+
switch (state) {
|
|
2264
|
+
case "closed":
|
|
2265
|
+
return darken(base, 0.12);
|
|
2266
|
+
case "sold-out":
|
|
2267
|
+
return soldOut;
|
|
2268
|
+
case "nearly-gone":
|
|
2269
|
+
return lerpColor(base, soldOut, 0.4);
|
|
2270
|
+
case "normal":
|
|
2271
|
+
default:
|
|
2272
|
+
return base;
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2095
2275
|
var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
2096
2276
|
function seatIdOf(target) {
|
|
2097
2277
|
const n = target;
|
|
@@ -2114,6 +2294,13 @@ function darken(hex, amt) {
|
|
|
2114
2294
|
const mix = (c) => Math.round(c * (1 - amt));
|
|
2115
2295
|
return `#${(1 << 24 | mix(n >> 16 & 255) << 16 | mix(n >> 8 & 255) << 8 | mix(n & 255)).toString(16).slice(1)}`;
|
|
2116
2296
|
}
|
|
2297
|
+
function desaturate(hex, amt) {
|
|
2298
|
+
const rgb2 = hexToRgb(hex);
|
|
2299
|
+
if (!rgb2) return hex;
|
|
2300
|
+
const [r, g, b] = rgb2;
|
|
2301
|
+
const grey = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
2302
|
+
return toHex(r + (grey - r) * amt, g + (grey - g) * amt, b + (grey - b) * amt);
|
|
2303
|
+
}
|
|
2117
2304
|
function polyBounds(pts) {
|
|
2118
2305
|
let minX = Infinity;
|
|
2119
2306
|
let minY = Infinity;
|
|
@@ -2177,18 +2364,36 @@ function polygonLabelCandidates(outer, holes, preferred) {
|
|
|
2177
2364
|
}
|
|
2178
2365
|
return points.sort((left, right) => Math.hypot(left.x - centre.x, left.y - centre.y) - Math.hypot(right.x - centre.x, right.y - centre.y)).filter((point, index, all) => index === all.findIndex((other) => Math.abs(other.x - point.x) < 1e-6 && Math.abs(other.y - point.y) < 1e-6));
|
|
2179
2366
|
}
|
|
2367
|
+
function roundedPolygonSubpath(context, points, radius) {
|
|
2368
|
+
const n = points.length;
|
|
2369
|
+
const start = { x: (points[n - 1].x + points[0].x) / 2, y: (points[n - 1].y + points[0].y) / 2 };
|
|
2370
|
+
context.moveTo(start.x, start.y);
|
|
2371
|
+
for (let i = 0; i < n; i += 1) {
|
|
2372
|
+
const curr = points[i];
|
|
2373
|
+
const next = points[(i + 1) % n];
|
|
2374
|
+
const prev = points[(i - 1 + n) % n];
|
|
2375
|
+
const rMax = Math.min(
|
|
2376
|
+
Math.hypot(curr.x - prev.x, curr.y - prev.y) / 2,
|
|
2377
|
+
Math.hypot(next.x - curr.x, next.y - curr.y) / 2
|
|
2378
|
+
);
|
|
2379
|
+
context.arcTo(curr.x, curr.y, next.x, next.y, Math.max(0, Math.min(radius, rMax)));
|
|
2380
|
+
}
|
|
2381
|
+
context.closePath();
|
|
2382
|
+
}
|
|
2180
2383
|
function polygonWithHolesShape(outer, holes, attrs, outerPath) {
|
|
2181
2384
|
const signedArea = (points) => points.reduce((sum, point, index) => {
|
|
2182
2385
|
const next = points[(index + 1) % points.length];
|
|
2183
2386
|
return sum + point.x * next.y - next.x * point.y;
|
|
2184
2387
|
}, 0);
|
|
2185
2388
|
const outerClockwise = signedArea(outer) > 0;
|
|
2389
|
+
const cornerRadius = attrs.cornerRadius && attrs.cornerRadius > 0 ? attrs.cornerRadius : 0;
|
|
2186
2390
|
return new Shape({
|
|
2187
2391
|
...attrs,
|
|
2188
2392
|
sceneFunc(context, shape) {
|
|
2189
2393
|
context.beginPath();
|
|
2190
2394
|
const polygonPath = (points) => {
|
|
2191
2395
|
if (!points.length) return;
|
|
2396
|
+
if (cornerRadius > 0 && points.length >= 3) return roundedPolygonSubpath(context, points, cornerRadius);
|
|
2192
2397
|
context.moveTo(points[0].x, points[0].y);
|
|
2193
2398
|
for (let index = 1; index < points.length; index += 1) context.lineTo(points[index].x, points[index].y);
|
|
2194
2399
|
context.closePath();
|
|
@@ -2323,6 +2528,8 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2323
2528
|
this.accessGlyphById = /* @__PURE__ */ new Map();
|
|
2324
2529
|
/** Authored free-text nodes obey the same rendered-size visibility floor. */
|
|
2325
2530
|
this.freeTextById = /* @__PURE__ */ new Map();
|
|
2531
|
+
/** Vector venue-icon Path nodes + authored size; obey the free-text size floor. */
|
|
2532
|
+
this.iconNodeById = /* @__PURE__ */ new Map();
|
|
2326
2533
|
/** Stage/rink landmarks retain a readable screen-space caption at overview. */
|
|
2327
2534
|
this.primaryFocalLabels = /* @__PURE__ */ new Map();
|
|
2328
2535
|
/** GA paint and text share price/highlight filter state. */
|
|
@@ -2336,6 +2543,12 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2336
2543
|
this.effSelection = DEF_SELECTION;
|
|
2337
2544
|
/** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
|
|
2338
2545
|
this.colorblind = false;
|
|
2546
|
+
/** Stable per-category-KEY colorblind hue (OV-46) — order-independent. */
|
|
2547
|
+
this.cbHueByKey = /* @__PURE__ */ new Map();
|
|
2548
|
+
/** OV-45(a): authored row-letter labels for the buyer/preview map, resolved in
|
|
2549
|
+
* world space (matching seat labels) and honouring each row's labelPresentation
|
|
2550
|
+
* (position/rotation/visibility/style). Painted at the seats LOD rung. */
|
|
2551
|
+
this.rowLabelPlan = [];
|
|
2339
2552
|
/** Category order from the doc — the stable index into the CB palette. */
|
|
2340
2553
|
this.catOrder = [];
|
|
2341
2554
|
this.selection = /* @__PURE__ */ new Set();
|
|
@@ -2705,6 +2918,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2705
2918
|
this.accessRingById.clear();
|
|
2706
2919
|
this.accessGlyphById.clear();
|
|
2707
2920
|
this.freeTextById.clear();
|
|
2921
|
+
this.iconNodeById.clear();
|
|
2708
2922
|
this.primaryFocalLabels.clear();
|
|
2709
2923
|
this.gaById.clear();
|
|
2710
2924
|
for (const marker of this.selectionMarkers.values()) marker.destroy();
|
|
@@ -2759,13 +2973,22 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2759
2973
|
this.catColor.clear();
|
|
2760
2974
|
this.catPrice.clear();
|
|
2761
2975
|
this.catOrder = doc.categories.map((c) => c.key);
|
|
2976
|
+
this.cbHueByKey.clear();
|
|
2977
|
+
[...this.catOrder].sort().forEach((key, i) => {
|
|
2978
|
+
this.cbHueByKey.set(key, CB_PALETTE[i % CB_PALETTE.length]);
|
|
2979
|
+
});
|
|
2762
2980
|
for (const c of doc.categories) {
|
|
2763
2981
|
this.catColor.set(c.key, c.color);
|
|
2764
2982
|
if (typeof c.price === "number") this.catPrice.set(c.key, c.price);
|
|
2765
2983
|
}
|
|
2766
2984
|
for (const obj of view.objects) {
|
|
2767
2985
|
if (obj.type === "booth") {
|
|
2768
|
-
this.boothDims.set(obj.id, {
|
|
2986
|
+
this.boothDims.set(obj.id, {
|
|
2987
|
+
width: obj.width,
|
|
2988
|
+
height: obj.height,
|
|
2989
|
+
rotation: obj.rotation,
|
|
2990
|
+
...obj.points && obj.points.length >= 3 ? { points: obj.points.map((p) => ({ x: p.x, y: p.y })) } : {}
|
|
2991
|
+
});
|
|
2769
2992
|
}
|
|
2770
2993
|
}
|
|
2771
2994
|
this.seats = expandChart(view, {
|
|
@@ -2785,6 +3008,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2785
3008
|
this.unsectionedSeatGroup = new Group({ listening: true });
|
|
2786
3009
|
this.seatLayer.add(this.unsectionedSeatGroup);
|
|
2787
3010
|
this.renderSeats();
|
|
3011
|
+
this.buildRowLabelPlan(view);
|
|
2788
3012
|
this.overlayLayer.add(this.labelGroup);
|
|
2789
3013
|
this.overlayLayer.add(this.fgDecorGroup);
|
|
2790
3014
|
this.overlayLayer.add(this.hoverRing);
|
|
@@ -4096,25 +4320,42 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4096
4320
|
renderBoothUnit(seat) {
|
|
4097
4321
|
const target = this.seatContainer(seat.id);
|
|
4098
4322
|
const dims = this.boothDims.get(seat.rowId) ?? { width: 40, height: 30, rotation: 0 };
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4323
|
+
let labelX = seat.x;
|
|
4324
|
+
let labelY = seat.y;
|
|
4325
|
+
let node;
|
|
4326
|
+
if (dims.points && dims.points.length >= 3) {
|
|
4327
|
+
node = new Line({
|
|
4328
|
+
x: seat.x,
|
|
4329
|
+
y: seat.y,
|
|
4330
|
+
points: dims.points.flatMap((p) => [p.x, p.y]),
|
|
4331
|
+
closed: true,
|
|
4332
|
+
perfectDrawEnabled: false,
|
|
4333
|
+
shadowForStrokeEnabled: false,
|
|
4334
|
+
hitStrokeWidth: 0
|
|
4335
|
+
});
|
|
4336
|
+
labelX = seat.x + dims.points.reduce((a, p) => a + p.x, 0) / dims.points.length;
|
|
4337
|
+
labelY = seat.y + dims.points.reduce((a, p) => a + p.y, 0) / dims.points.length;
|
|
4338
|
+
} else {
|
|
4339
|
+
node = new Rect({
|
|
4340
|
+
x: seat.x,
|
|
4341
|
+
y: seat.y,
|
|
4342
|
+
width: dims.width,
|
|
4343
|
+
height: dims.height,
|
|
4344
|
+
offsetX: dims.width / 2,
|
|
4345
|
+
offsetY: dims.height / 2,
|
|
4346
|
+
rotation: dims.rotation,
|
|
4347
|
+
cornerRadius: 4,
|
|
4348
|
+
perfectDrawEnabled: false,
|
|
4349
|
+
shadowForStrokeEnabled: false,
|
|
4350
|
+
hitStrokeWidth: 0
|
|
4351
|
+
});
|
|
4352
|
+
}
|
|
4353
|
+
node.setAttr("seatId", seat.id);
|
|
4354
|
+
this.circleById.set(seat.id, node);
|
|
4355
|
+
target.add(node);
|
|
4115
4356
|
const t2 = new Text({
|
|
4116
|
-
x:
|
|
4117
|
-
y:
|
|
4357
|
+
x: labelX,
|
|
4358
|
+
y: labelY,
|
|
4118
4359
|
text: seat.displayLabel ?? seat.label,
|
|
4119
4360
|
fontSize: BOOTH_LABEL_FONT_SIZE,
|
|
4120
4361
|
fontStyle: "600",
|
|
@@ -4129,7 +4370,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4129
4370
|
this.hasBoothText = true;
|
|
4130
4371
|
this.boothLabelById.set(seat.id, t2);
|
|
4131
4372
|
target.add(t2);
|
|
4132
|
-
this.paintSeat(
|
|
4373
|
+
this.paintSeat(node, seat.id);
|
|
4133
4374
|
}
|
|
4134
4375
|
/**
|
|
4135
4376
|
* Build the centred accessibility glyph for a seat. Sized relative to the seat
|
|
@@ -4197,8 +4438,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4197
4438
|
/** The category's display color — Okabe-Ito hue when colorblind-safe is on. */
|
|
4198
4439
|
seatBaseColor(categoryKey) {
|
|
4199
4440
|
if (!this.colorblind) return this.catColor.get(categoryKey) ?? "#6e7bff";
|
|
4200
|
-
|
|
4201
|
-
return CB_PALETTE[(idx >= 0 ? idx : 0) % CB_PALETTE.length];
|
|
4441
|
+
return this.cbHueByKey.get(categoryKey) ?? CB_PALETTE[0];
|
|
4202
4442
|
}
|
|
4203
4443
|
/** Per-seat authored label size relative to the neutral default (1 = default),
|
|
4204
4444
|
* mirroring the section convention (labelStyle.size ?? 18) / 18. Only real
|
|
@@ -4669,6 +4909,28 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4669
4909
|
renderText(obj) {
|
|
4670
4910
|
const background = this.canvasBackground;
|
|
4671
4911
|
const preferredInk = obj.color ?? this.theme.textColor ?? DEF_TEXT;
|
|
4912
|
+
const iconPath = obj.semanticKind === "icon" ? venueIconPath(obj.iconKey) : void 0;
|
|
4913
|
+
if (iconPath) {
|
|
4914
|
+
const scale = obj.fontSize / VENUE_ICON_VIEWBOX;
|
|
4915
|
+
const iconNode = new Path({
|
|
4916
|
+
x: obj.position.x,
|
|
4917
|
+
y: obj.position.y,
|
|
4918
|
+
data: iconPath,
|
|
4919
|
+
rotation: obj.rotation,
|
|
4920
|
+
scaleX: scale,
|
|
4921
|
+
scaleY: scale,
|
|
4922
|
+
stroke: stateAwareBookableLabelInk(background, preferredInk),
|
|
4923
|
+
strokeWidth: VENUE_ICON_STROKE,
|
|
4924
|
+
lineCap: "round",
|
|
4925
|
+
lineJoin: "round",
|
|
4926
|
+
fillEnabled: false,
|
|
4927
|
+
listening: false,
|
|
4928
|
+
perfectDrawEnabled: false
|
|
4929
|
+
});
|
|
4930
|
+
this.iconNodeById.set(obj.id, { node: iconNode, fontSize: obj.fontSize });
|
|
4931
|
+
this.bgLayer.add(iconNode);
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4672
4934
|
const node = new Text({
|
|
4673
4935
|
x: obj.position.x,
|
|
4674
4936
|
y: obj.position.y,
|
|
@@ -4836,7 +5098,8 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4836
5098
|
fill: color,
|
|
4837
5099
|
opacity: GA_FILL_OPACITY,
|
|
4838
5100
|
stroke: color,
|
|
4839
|
-
strokeWidth: 1.5
|
|
5101
|
+
strokeWidth: 1.5,
|
|
5102
|
+
cornerRadius: obj.cornerRadius
|
|
4840
5103
|
});
|
|
4841
5104
|
poly.setAttr("gaId", obj.id);
|
|
4842
5105
|
poly.on("click tap", (e) => {
|
|
@@ -5048,20 +5311,33 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
5048
5311
|
sec.outlinePoly.shadowBlur(4 + raw * 12);
|
|
5049
5312
|
sec.outlinePoly.shadowOpacity(0.25 + raw * 0.45);
|
|
5050
5313
|
}
|
|
5051
|
-
/** Recompute a section's
|
|
5314
|
+
/** Recompute a section's availability shading + retained availability text. */
|
|
5052
5315
|
refreshSectionFill(sec) {
|
|
5053
5316
|
sec.blockPoly.fill(this.sectionBlockFill(sec));
|
|
5054
|
-
sec.subLabel.text(
|
|
5317
|
+
sec.subLabel.text(
|
|
5318
|
+
this.sectionAvailabilityState(sec) === "sold-out" ? t("map.soldOut") : t("map.seatsLeft", { count: sec.free })
|
|
5319
|
+
);
|
|
5055
5320
|
sec.subLabel.offsetX(sec.subLabel.width() / 2);
|
|
5056
5321
|
}
|
|
5057
5322
|
/** True when a section/zone is currently in the `closed` event-state. */
|
|
5058
5323
|
isSectionClosed(sec) {
|
|
5059
5324
|
return this.closedSections.has(sec.id) || this.closedSections.has(sec.logicalId) || sec.zone != null && this.closedSections.has(sec.zone);
|
|
5060
5325
|
}
|
|
5061
|
-
/**
|
|
5326
|
+
/** Resolve the four-bucket overview availability state for a section (OV-69).
|
|
5327
|
+
* `closed` (operator) outranks live availability; the availability buckets
|
|
5328
|
+
* only apply to seated sections (GA-only shells have no seat capacity here). */
|
|
5329
|
+
sectionAvailabilityState(sec) {
|
|
5330
|
+
if (this.isSectionClosed(sec)) return "closed";
|
|
5331
|
+
if (sec.total <= 0) return "normal";
|
|
5332
|
+
if (sec.free <= 0) return "sold-out";
|
|
5333
|
+
if (sec.free <= sec.total * SECTION_NEARLY_GONE_RATIO) return "nearly-gone";
|
|
5334
|
+
return "normal";
|
|
5335
|
+
}
|
|
5336
|
+
/** Overview shells stay neutral except for the bounded availability shading
|
|
5337
|
+
* (nearly-gone / sold-out) and the operator `closed` slab — never category
|
|
5338
|
+
* or price paint, which is deferred to section focus/seat detail. */
|
|
5062
5339
|
sectionBlockFill(sec) {
|
|
5063
|
-
|
|
5064
|
-
return this.isSectionClosed(sec) ? darken(fill, 0.12) : fill;
|
|
5340
|
+
return overviewStateFill(overviewPalette(this.canvasBackground), this.sectionAvailabilityState(sec));
|
|
5065
5341
|
}
|
|
5066
5342
|
/**
|
|
5067
5343
|
* Zone rung: one giant screen-constant label per zone (+ optional "FROM $n"),
|
|
@@ -6067,10 +6343,9 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
6067
6343
|
};
|
|
6068
6344
|
});
|
|
6069
6345
|
const palette = overviewPalette(this.canvasBackground);
|
|
6070
|
-
const neutralSectionFills =
|
|
6071
|
-
palette.
|
|
6072
|
-
|
|
6073
|
-
]);
|
|
6346
|
+
const neutralSectionFills = new Set(
|
|
6347
|
+
["normal", "nearly-gone", "sold-out", "closed"].map((state) => overviewStateFill(palette, state).toLowerCase())
|
|
6348
|
+
);
|
|
6074
6349
|
const visibleSectionShells = this.sections.filter((section) => section.blockPoly.opacity() > 0.05);
|
|
6075
6350
|
return {
|
|
6076
6351
|
viewport,
|
|
@@ -6294,6 +6569,63 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
6294
6569
|
const gaOverviewHidden = objectId != null && (kind === "ga-label" || kind === "ga-capacity") && this.gaById.get(objectId)?.sectionId != null && effectiveScale < CACHE_THRESHOLD;
|
|
6295
6570
|
node.visible(!gaDimmed && !gaOverviewHidden && isBookableLabelLegibleAtScale(node.fontSize(), effectiveScale));
|
|
6296
6571
|
}
|
|
6572
|
+
for (const { node, fontSize } of this.iconNodeById.values()) {
|
|
6573
|
+
node.visible(isBookableLabelLegibleAtScale(fontSize, effectiveScale));
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
/** OV-45(a): resolve authored row-letter labels for the buyer/preview map, in
|
|
6577
|
+
* world space, matching the Designer's placement contract (start/end/both/none
|
|
6578
|
+
* preset, a free-drag `position` that wins over the preset, rotation, and
|
|
6579
|
+
* labelStyle colour/size fed through the same auto-contrast guard). Segmented
|
|
6580
|
+
* rows keep their own logical-label handling and are resolved by their owner. */
|
|
6581
|
+
buildRowLabelPlan(view) {
|
|
6582
|
+
this.rowLabelPlan = [];
|
|
6583
|
+
const background = this.theme.background ?? "#0e1117";
|
|
6584
|
+
const seatsByRow = /* @__PURE__ */ new Map();
|
|
6585
|
+
for (const seat of this.seats) {
|
|
6586
|
+
if (seat.kind === "booth") continue;
|
|
6587
|
+
const key = seat.logicalRowId ?? seat.rowId;
|
|
6588
|
+
(seatsByRow.get(key) ?? seatsByRow.set(key, []).get(key)).push(seat);
|
|
6589
|
+
}
|
|
6590
|
+
const seatOrder = (seat) => seat.logicalSeatIndex ?? Number(seat.id.split(":").pop() ?? 0);
|
|
6591
|
+
for (const obj of view.objects) {
|
|
6592
|
+
if (obj.type !== "row") continue;
|
|
6593
|
+
if (obj.segmentedRow && obj.segmentedRow.componentIndex !== 0) continue;
|
|
6594
|
+
const presentation = obj.segmentedRow?.labelPresentation ?? obj.labelPresentation;
|
|
6595
|
+
if (presentation?.visible === false || presentation?.positionPreset === "none") continue;
|
|
6596
|
+
const key = obj.segmentedRow ? obj.segmentedRow.groupId : obj.id;
|
|
6597
|
+
const seats = (seatsByRow.get(key) ?? []).slice().sort((a, b) => seatOrder(a) - seatOrder(b));
|
|
6598
|
+
if (!seats.length) continue;
|
|
6599
|
+
const first = seats[0];
|
|
6600
|
+
const last = seats[seats.length - 1];
|
|
6601
|
+
const labelStyle = presentation?.labelStyle;
|
|
6602
|
+
const ink = stateAwareBookableLabelInk(
|
|
6603
|
+
background,
|
|
6604
|
+
labelStyle?.color ?? this.theme.rowLabelColor ?? this.theme.textColor ?? "#e6e9f0"
|
|
6605
|
+
);
|
|
6606
|
+
const fontSize = labelStyle?.size ?? 12;
|
|
6607
|
+
const rotation = presentation?.rotation ?? 0;
|
|
6608
|
+
const text = obj.segmentedRow?.displayLabel ?? obj.displayLabel ?? obj.label;
|
|
6609
|
+
const opacity = this.objectFilteredOut(obj) ? 0.15 : 1;
|
|
6610
|
+
const push = (x, y) => this.rowLabelPlan.push({ text, x, y, rotation, fontSize, ink, opacity });
|
|
6611
|
+
if (presentation?.position) {
|
|
6612
|
+
push(presentation.position.x, presentation.position.y);
|
|
6613
|
+
continue;
|
|
6614
|
+
}
|
|
6615
|
+
const radians = obj.rotation * Math.PI / 180;
|
|
6616
|
+
const along = { x: Math.cos(radians), y: Math.sin(radians) };
|
|
6617
|
+
const gap = this.seatR + 12;
|
|
6618
|
+
const preset = presentation?.positionPreset ?? "start";
|
|
6619
|
+
if (preset === "start" || preset === "both") push(first.x - along.x * gap, first.y - along.y * gap);
|
|
6620
|
+
if (preset === "end" || preset === "both") push(last.x + along.x * gap, last.y + along.y * gap);
|
|
6621
|
+
}
|
|
6622
|
+
}
|
|
6623
|
+
/** Row labels never carry status; the buyer just dims them under the same
|
|
6624
|
+
* category/price filters that dim their seats. */
|
|
6625
|
+
objectFilteredOut(obj) {
|
|
6626
|
+
const key = obj.categoryKey;
|
|
6627
|
+
if (!key) return false;
|
|
6628
|
+
return Boolean(this.categoryHighlight && key !== this.categoryHighlight || this.categoryFilter && !this.categoryFilter.has(key));
|
|
6297
6629
|
}
|
|
6298
6630
|
updateLabels() {
|
|
6299
6631
|
const effectiveScale = this.effScale();
|
|
@@ -6387,6 +6719,30 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
6387
6719
|
this.seatLabelById.set(seat.id, t2);
|
|
6388
6720
|
if (++count >= MAX_LABELS) break;
|
|
6389
6721
|
}
|
|
6722
|
+
for (const rl of this.rowLabelPlan) {
|
|
6723
|
+
const screen = this.worldToScreen({ x: rl.x, y: rl.y });
|
|
6724
|
+
if (screen.x < -40 || screen.x > this.stage.width() + 40 || screen.y < -40 || screen.y > this.stage.height() + 40) continue;
|
|
6725
|
+
const t2 = new Text({
|
|
6726
|
+
x: rl.x,
|
|
6727
|
+
y: rl.y,
|
|
6728
|
+
text: rl.text,
|
|
6729
|
+
fontSize: rl.fontSize,
|
|
6730
|
+
fontStyle: "700",
|
|
6731
|
+
fontFamily: this.labelFont(),
|
|
6732
|
+
fill: rl.ink,
|
|
6733
|
+
rotation: rl.rotation,
|
|
6734
|
+
opacity: rl.opacity,
|
|
6735
|
+
shadowColor: "#05070c",
|
|
6736
|
+
shadowBlur: rl.ink.toLowerCase() === "#ffffff" ? 5 : 0,
|
|
6737
|
+
shadowOpacity: rl.ink.toLowerCase() === "#ffffff" ? 0.8 : 0,
|
|
6738
|
+
shadowForStrokeEnabled: false,
|
|
6739
|
+
listening: false,
|
|
6740
|
+
perfectDrawEnabled: false
|
|
6741
|
+
});
|
|
6742
|
+
t2.offsetX(t2.width() / 2);
|
|
6743
|
+
t2.offsetY(t2.height() / 2);
|
|
6744
|
+
this.labelGroup.add(t2);
|
|
6745
|
+
}
|
|
6390
6746
|
if (this.isoT > 0 && this.viewMode !== "perspective") this.applyUprightLabels();
|
|
6391
6747
|
this.overlayLayer.batchDraw();
|
|
6392
6748
|
}
|
|
@@ -7633,7 +7989,7 @@ var PickerController = class {
|
|
|
7633
7989
|
const color = sec.color ?? zone?.color ?? categories[0]?.color ?? "#6e7bff";
|
|
7634
7990
|
return {
|
|
7635
7991
|
id,
|
|
7636
|
-
label: sec.label,
|
|
7992
|
+
label: sec.displayLabel ?? sec.label,
|
|
7637
7993
|
zoneLabel: zone?.label ?? "",
|
|
7638
7994
|
...sec.entrance && sec.entrance.trim() ? { entrance: sec.entrance.trim() } : {},
|
|
7639
7995
|
color,
|
|
@@ -8235,9 +8591,9 @@ function generateSeatThumb(seat, focalPoint, _neighborSeats) {
|
|
|
8235
8591
|
|
|
8236
8592
|
// src/i18n/bundles.ts
|
|
8237
8593
|
var LOADERS = {
|
|
8238
|
-
es: () => import("./es-
|
|
8239
|
-
de: () => import("./de-
|
|
8240
|
-
fr: () => import("./fr-
|
|
8594
|
+
es: () => import("./es-6TJS2L7S.js").then((m) => ({ default: m.es })),
|
|
8595
|
+
de: () => import("./de-UHAOVDS3.js").then((m) => ({ default: m.de })),
|
|
8596
|
+
fr: () => import("./fr-MMSY7FPE.js").then((m) => ({ default: m.fr }))
|
|
8241
8597
|
};
|
|
8242
8598
|
var loaded = /* @__PURE__ */ new Set(["en"]);
|
|
8243
8599
|
async function loadLocale(code) {
|