@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.cjs
CHANGED
|
@@ -951,6 +951,7 @@ var SEAT_RADIUS = 9;
|
|
|
951
951
|
var SEAT_LEGIBLE_SCALE = 0.9;
|
|
952
952
|
var CACHE_THRESHOLD = 0.55 * SEAT_LEGIBLE_SCALE;
|
|
953
953
|
var LABEL_SCALE = 1;
|
|
954
|
+
var SEAT_TAP_SLOP_PX = 14;
|
|
954
955
|
var SECTION_PROMINENT_SCALE = 0.45 * SEAT_LEGIBLE_SCALE;
|
|
955
956
|
var BLOCK_MELT_TOP = 0.9 * SEAT_LEGIBLE_SCALE;
|
|
956
957
|
var ZONE_PROMINENT_SCALE = 0.55 * SECTION_PROMINENT_SCALE;
|
|
@@ -2852,27 +2853,84 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2852
2853
|
}
|
|
2853
2854
|
}
|
|
2854
2855
|
// ---- interaction ----------------------------------------------------------
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2856
|
+
/**
|
|
2857
|
+
* The stage scale `focusRegion(id)` would settle at — i.e. the zoom that
|
|
2858
|
+
* frames this section in the current viewport. Used to decide whether
|
|
2859
|
+
* redirecting a seat tap to section-focus would actually zoom in FURTHER, or
|
|
2860
|
+
* whether the section already fills the viewport (small container) so the tap
|
|
2861
|
+
* must fall through and pick.
|
|
2862
|
+
*/
|
|
2863
|
+
sectionFrameScale(id) {
|
|
2864
|
+
const sec = this.sections.find((s) => s.id === id);
|
|
2865
|
+
if (!sec) return this.stage.scaleX();
|
|
2866
|
+
const b = polyBounds(sec.outline);
|
|
2867
|
+
const w = this.stage.width();
|
|
2868
|
+
const h = this.stage.height();
|
|
2869
|
+
const { min, max } = this.zoomBounds();
|
|
2870
|
+
const margin = 1.12;
|
|
2871
|
+
if (b.width <= 0 || b.height <= 0) return this.stage.scaleX();
|
|
2872
|
+
return clamp(Math.min(w / (b.width * margin), h / (b.height * margin)), min, max);
|
|
2873
|
+
}
|
|
2874
|
+
/**
|
|
2875
|
+
* Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
|
|
2876
|
+
* then toggle. The gate (§4) redirects small on-screen seats to section-focus
|
|
2877
|
+
* to avoid blind mis-picks at overview scales — but ONLY when focusing would
|
|
2878
|
+
* zoom the seat up to a safe size. If we're already focused on the section, or
|
|
2879
|
+
* the section already fills the viewport (a narrow — OR even a wide — container
|
|
2880
|
+
* frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would
|
|
2881
|
+
* leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we
|
|
2882
|
+
* fall through and PICK. This is the invariant: seats are never unpickable.
|
|
2883
|
+
*/
|
|
2884
|
+
handleSeatTap(id) {
|
|
2885
|
+
if (this.stacked && this.opts.onDeckTap) {
|
|
2886
|
+
const floorId = this.objectFloor.get(this.seatById.get(id)?.rowId ?? "");
|
|
2887
|
+
if (floorId) {
|
|
2888
|
+
this.opts.onDeckTap(floorId);
|
|
2889
|
+
return;
|
|
2866
2890
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2891
|
+
}
|
|
2892
|
+
if (this.effScale() < LABEL_SCALE && this.sections.length) {
|
|
2893
|
+
const sec = this.seatSection.get(id);
|
|
2894
|
+
if (sec) {
|
|
2895
|
+
const alreadyFocused = this.focusedSectionId === sec.id;
|
|
2896
|
+
const canZoomInFurther = this.sectionFrameScale(sec.id) > this.stage.scaleX() * 1.02;
|
|
2897
|
+
if (!alreadyFocused && canZoomInFurther) {
|
|
2870
2898
|
if (this.opts.onSectionTap) this.opts.onSectionTap(sec.id);
|
|
2871
2899
|
else this.focusSection(sec.id);
|
|
2872
2900
|
return;
|
|
2873
2901
|
}
|
|
2874
2902
|
}
|
|
2875
|
-
|
|
2903
|
+
}
|
|
2904
|
+
this.toggleSeat(id);
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a
|
|
2908
|
+
* seat circle edge, or null. Enlarges the effective tap target for small seats
|
|
2909
|
+
* so a near-miss on mobile still lands on the intended seat, without ever
|
|
2910
|
+
* hijacking a clean tap on empty space beyond the slop.
|
|
2911
|
+
*/
|
|
2912
|
+
nearestSeatToScreen(screen, slopPx) {
|
|
2913
|
+
const s = this.stage.scaleX() || 1;
|
|
2914
|
+
const reachWorld = this.seatR + slopPx / s;
|
|
2915
|
+
const world = this.screenToWorld(screen);
|
|
2916
|
+
let best = null;
|
|
2917
|
+
let bestD = reachWorld;
|
|
2918
|
+
for (const seat of this.seats) {
|
|
2919
|
+
if (!this.selection.has(seat.id) && !this.isSelectable(seat.id)) continue;
|
|
2920
|
+
const d = Math.hypot(seat.x - world.x, seat.y - world.y);
|
|
2921
|
+
if (d < bestD) {
|
|
2922
|
+
bestD = d;
|
|
2923
|
+
best = seat.id;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
return best;
|
|
2927
|
+
}
|
|
2928
|
+
wireInteraction() {
|
|
2929
|
+
this.seatLayer.on("click tap", (e) => {
|
|
2930
|
+
if (this.moved > 8) return;
|
|
2931
|
+
const id = seatIdOf(e.target);
|
|
2932
|
+
if (!id) return;
|
|
2933
|
+
this.handleSeatTap(id);
|
|
2876
2934
|
});
|
|
2877
2935
|
this.seatLayer.on("mouseover", (e) => {
|
|
2878
2936
|
const id = seatIdOf(e.target);
|
|
@@ -2898,10 +2956,16 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2898
2956
|
const factor = Math.exp(-e.evt.deltaY * 2e-3);
|
|
2899
2957
|
this.zoomAbout(this.stage.scaleX() * clamp(factor, 0.5, 2), pointer);
|
|
2900
2958
|
});
|
|
2901
|
-
this.stage.on("click tap", () => {
|
|
2902
|
-
if (
|
|
2959
|
+
this.stage.on("click tap", (e) => {
|
|
2960
|
+
if (this.moved > 8) return;
|
|
2903
2961
|
const pointer = this.stage.getPointerPosition();
|
|
2904
2962
|
if (!pointer) return;
|
|
2963
|
+
if (!this.cached) {
|
|
2964
|
+
if (seatIdOf(e.target)) return;
|
|
2965
|
+
const near = this.nearestSeatToScreen(pointer, SEAT_TAP_SLOP_PX);
|
|
2966
|
+
if (near) this.handleSeatTap(near);
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2905
2969
|
if (this.stacked && this.opts.onDeckTap) {
|
|
2906
2970
|
const floorId = this.deckFloorAt();
|
|
2907
2971
|
if (floorId) {
|