@seatlayer/core 0.10.0 → 0.10.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/index.cjs +81 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +81 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1035,6 +1035,32 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1035
1035
|
*/
|
|
1036
1036
|
private resolveSelectionColor;
|
|
1037
1037
|
private setSelected;
|
|
1038
|
+
/**
|
|
1039
|
+
* The stage scale `focusRegion(id)` would settle at — i.e. the zoom that
|
|
1040
|
+
* frames this section in the current viewport. Used to decide whether
|
|
1041
|
+
* redirecting a seat tap to section-focus would actually zoom in FURTHER, or
|
|
1042
|
+
* whether the section already fills the viewport (small container) so the tap
|
|
1043
|
+
* must fall through and pick.
|
|
1044
|
+
*/
|
|
1045
|
+
private sectionFrameScale;
|
|
1046
|
+
/**
|
|
1047
|
+
* Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
|
|
1048
|
+
* then toggle. The gate (§4) redirects small on-screen seats to section-focus
|
|
1049
|
+
* to avoid blind mis-picks at overview scales — but ONLY when focusing would
|
|
1050
|
+
* zoom the seat up to a safe size. If we're already focused on the section, or
|
|
1051
|
+
* the section already fills the viewport (a narrow — OR even a wide — container
|
|
1052
|
+
* frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would
|
|
1053
|
+
* leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we
|
|
1054
|
+
* fall through and PICK. This is the invariant: seats are never unpickable.
|
|
1055
|
+
*/
|
|
1056
|
+
private handleSeatTap;
|
|
1057
|
+
/**
|
|
1058
|
+
* Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a
|
|
1059
|
+
* seat circle edge, or null. Enlarges the effective tap target for small seats
|
|
1060
|
+
* so a near-miss on mobile still lands on the intended seat, without ever
|
|
1061
|
+
* hijacking a clean tap on empty space beyond the slop.
|
|
1062
|
+
*/
|
|
1063
|
+
private nearestSeatToScreen;
|
|
1038
1064
|
private wireInteraction;
|
|
1039
1065
|
/**
|
|
1040
1066
|
* Which deck (floor) a screen tap landed on in the 3D stacked overview. The
|
package/dist/index.d.ts
CHANGED
|
@@ -1035,6 +1035,32 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1035
1035
|
*/
|
|
1036
1036
|
private resolveSelectionColor;
|
|
1037
1037
|
private setSelected;
|
|
1038
|
+
/**
|
|
1039
|
+
* The stage scale `focusRegion(id)` would settle at — i.e. the zoom that
|
|
1040
|
+
* frames this section in the current viewport. Used to decide whether
|
|
1041
|
+
* redirecting a seat tap to section-focus would actually zoom in FURTHER, or
|
|
1042
|
+
* whether the section already fills the viewport (small container) so the tap
|
|
1043
|
+
* must fall through and pick.
|
|
1044
|
+
*/
|
|
1045
|
+
private sectionFrameScale;
|
|
1046
|
+
/**
|
|
1047
|
+
* Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
|
|
1048
|
+
* then toggle. The gate (§4) redirects small on-screen seats to section-focus
|
|
1049
|
+
* to avoid blind mis-picks at overview scales — but ONLY when focusing would
|
|
1050
|
+
* zoom the seat up to a safe size. If we're already focused on the section, or
|
|
1051
|
+
* the section already fills the viewport (a narrow — OR even a wide — container
|
|
1052
|
+
* frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would
|
|
1053
|
+
* leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we
|
|
1054
|
+
* fall through and PICK. This is the invariant: seats are never unpickable.
|
|
1055
|
+
*/
|
|
1056
|
+
private handleSeatTap;
|
|
1057
|
+
/**
|
|
1058
|
+
* Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a
|
|
1059
|
+
* seat circle edge, or null. Enlarges the effective tap target for small seats
|
|
1060
|
+
* so a near-miss on mobile still lands on the intended seat, without ever
|
|
1061
|
+
* hijacking a clean tap on empty space beyond the slop.
|
|
1062
|
+
*/
|
|
1063
|
+
private nearestSeatToScreen;
|
|
1038
1064
|
private wireInteraction;
|
|
1039
1065
|
/**
|
|
1040
1066
|
* Which deck (floor) a screen tap landed on in the 3D stacked overview. The
|
package/dist/index.js
CHANGED
|
@@ -632,6 +632,7 @@ var SEAT_RADIUS = 9;
|
|
|
632
632
|
var SEAT_LEGIBLE_SCALE = 0.9;
|
|
633
633
|
var CACHE_THRESHOLD = 0.55 * SEAT_LEGIBLE_SCALE;
|
|
634
634
|
var LABEL_SCALE = 1;
|
|
635
|
+
var SEAT_TAP_SLOP_PX = 14;
|
|
635
636
|
var SECTION_PROMINENT_SCALE = 0.45 * SEAT_LEGIBLE_SCALE;
|
|
636
637
|
var BLOCK_MELT_TOP = 0.9 * SEAT_LEGIBLE_SCALE;
|
|
637
638
|
var ZONE_PROMINENT_SCALE = 0.55 * SECTION_PROMINENT_SCALE;
|
|
@@ -2533,27 +2534,84 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2533
2534
|
}
|
|
2534
2535
|
}
|
|
2535
2536
|
// ---- interaction ----------------------------------------------------------
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2537
|
+
/**
|
|
2538
|
+
* The stage scale `focusRegion(id)` would settle at — i.e. the zoom that
|
|
2539
|
+
* frames this section in the current viewport. Used to decide whether
|
|
2540
|
+
* redirecting a seat tap to section-focus would actually zoom in FURTHER, or
|
|
2541
|
+
* whether the section already fills the viewport (small container) so the tap
|
|
2542
|
+
* must fall through and pick.
|
|
2543
|
+
*/
|
|
2544
|
+
sectionFrameScale(id) {
|
|
2545
|
+
const sec = this.sections.find((s) => s.id === id);
|
|
2546
|
+
if (!sec) return this.stage.scaleX();
|
|
2547
|
+
const b = polyBounds(sec.outline);
|
|
2548
|
+
const w = this.stage.width();
|
|
2549
|
+
const h = this.stage.height();
|
|
2550
|
+
const { min, max } = this.zoomBounds();
|
|
2551
|
+
const margin = 1.12;
|
|
2552
|
+
if (b.width <= 0 || b.height <= 0) return this.stage.scaleX();
|
|
2553
|
+
return clamp(Math.min(w / (b.width * margin), h / (b.height * margin)), min, max);
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
|
|
2557
|
+
* then toggle. The gate (§4) redirects small on-screen seats to section-focus
|
|
2558
|
+
* to avoid blind mis-picks at overview scales — but ONLY when focusing would
|
|
2559
|
+
* zoom the seat up to a safe size. If we're already focused on the section, or
|
|
2560
|
+
* the section already fills the viewport (a narrow — OR even a wide — container
|
|
2561
|
+
* frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would
|
|
2562
|
+
* leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we
|
|
2563
|
+
* fall through and PICK. This is the invariant: seats are never unpickable.
|
|
2564
|
+
*/
|
|
2565
|
+
handleSeatTap(id) {
|
|
2566
|
+
if (this.stacked && this.opts.onDeckTap) {
|
|
2567
|
+
const floorId = this.objectFloor.get(this.seatById.get(id)?.rowId ?? "");
|
|
2568
|
+
if (floorId) {
|
|
2569
|
+
this.opts.onDeckTap(floorId);
|
|
2570
|
+
return;
|
|
2547
2571
|
}
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2572
|
+
}
|
|
2573
|
+
if (this.effScale() < LABEL_SCALE && this.sections.length) {
|
|
2574
|
+
const sec = this.seatSection.get(id);
|
|
2575
|
+
if (sec) {
|
|
2576
|
+
const alreadyFocused = this.focusedSectionId === sec.id;
|
|
2577
|
+
const canZoomInFurther = this.sectionFrameScale(sec.id) > this.stage.scaleX() * 1.02;
|
|
2578
|
+
if (!alreadyFocused && canZoomInFurther) {
|
|
2551
2579
|
if (this.opts.onSectionTap) this.opts.onSectionTap(sec.id);
|
|
2552
2580
|
else this.focusSection(sec.id);
|
|
2553
2581
|
return;
|
|
2554
2582
|
}
|
|
2555
2583
|
}
|
|
2556
|
-
|
|
2584
|
+
}
|
|
2585
|
+
this.toggleSeat(id);
|
|
2586
|
+
}
|
|
2587
|
+
/**
|
|
2588
|
+
* Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a
|
|
2589
|
+
* seat circle edge, or null. Enlarges the effective tap target for small seats
|
|
2590
|
+
* so a near-miss on mobile still lands on the intended seat, without ever
|
|
2591
|
+
* hijacking a clean tap on empty space beyond the slop.
|
|
2592
|
+
*/
|
|
2593
|
+
nearestSeatToScreen(screen, slopPx) {
|
|
2594
|
+
const s = this.stage.scaleX() || 1;
|
|
2595
|
+
const reachWorld = this.seatR + slopPx / s;
|
|
2596
|
+
const world = this.screenToWorld(screen);
|
|
2597
|
+
let best = null;
|
|
2598
|
+
let bestD = reachWorld;
|
|
2599
|
+
for (const seat of this.seats) {
|
|
2600
|
+
if (!this.selection.has(seat.id) && !this.isSelectable(seat.id)) continue;
|
|
2601
|
+
const d = Math.hypot(seat.x - world.x, seat.y - world.y);
|
|
2602
|
+
if (d < bestD) {
|
|
2603
|
+
bestD = d;
|
|
2604
|
+
best = seat.id;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
return best;
|
|
2608
|
+
}
|
|
2609
|
+
wireInteraction() {
|
|
2610
|
+
this.seatLayer.on("click tap", (e) => {
|
|
2611
|
+
if (this.moved > 8) return;
|
|
2612
|
+
const id = seatIdOf(e.target);
|
|
2613
|
+
if (!id) return;
|
|
2614
|
+
this.handleSeatTap(id);
|
|
2557
2615
|
});
|
|
2558
2616
|
this.seatLayer.on("mouseover", (e) => {
|
|
2559
2617
|
const id = seatIdOf(e.target);
|
|
@@ -2579,10 +2637,16 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2579
2637
|
const factor = Math.exp(-e.evt.deltaY * 2e-3);
|
|
2580
2638
|
this.zoomAbout(this.stage.scaleX() * clamp(factor, 0.5, 2), pointer);
|
|
2581
2639
|
});
|
|
2582
|
-
this.stage.on("click tap", () => {
|
|
2583
|
-
if (
|
|
2640
|
+
this.stage.on("click tap", (e) => {
|
|
2641
|
+
if (this.moved > 8) return;
|
|
2584
2642
|
const pointer = this.stage.getPointerPosition();
|
|
2585
2643
|
if (!pointer) return;
|
|
2644
|
+
if (!this.cached) {
|
|
2645
|
+
if (seatIdOf(e.target)) return;
|
|
2646
|
+
const near = this.nearestSeatToScreen(pointer, SEAT_TAP_SLOP_PX);
|
|
2647
|
+
if (near) this.handleSeatTap(near);
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2586
2650
|
if (this.stacked && this.opts.onDeckTap) {
|
|
2587
2651
|
const floorId = this.deckFloorAt();
|
|
2588
2652
|
if (floorId) {
|