@seatlayer/core 0.10.1 → 0.10.2
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 +67 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +67 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -411,6 +411,18 @@ interface ISeatmapRenderer {
|
|
|
411
411
|
}): void;
|
|
412
412
|
/** Bulk status update; re-renders affected seats only. */
|
|
413
413
|
setStatus(seatIds: string[], status: SeatStatus): void;
|
|
414
|
+
/**
|
|
415
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame. Konva's batchDraw()
|
|
416
|
+
* (used by setStatus and friends) schedules the actual paint on the next rAF
|
|
417
|
+
* tick, which Chrome throttles/pauses on hidden, backgrounded, or occluded
|
|
418
|
+
* tabs — so a seat-status delta updates the scene graph but the pixels never
|
|
419
|
+
* change until the tab is foregrounded again. forceDraw() paints the affected
|
|
420
|
+
* layers immediately (Layer.draw() is synchronous) and flushes any pending
|
|
421
|
+
* cache-debounce, so a caller (visibilitychange catch-up, or an opted-in
|
|
422
|
+
* always-live board) can guarantee the canvas reflects current state
|
|
423
|
+
* regardless of tab visibility. No-op difference in the foreground.
|
|
424
|
+
*/
|
|
425
|
+
forceDraw(): void;
|
|
414
426
|
getStatus(seatId: string): SeatStatus;
|
|
415
427
|
getSelection(): ExpandedSeat[];
|
|
416
428
|
clearSelection(): void;
|
|
@@ -1109,7 +1121,22 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1109
1121
|
/** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */
|
|
1110
1122
|
private scheduleViewChange;
|
|
1111
1123
|
private updateLOD;
|
|
1124
|
+
/** Rebuild the seat-layer bitmap synchronously (no paint). Shared by the
|
|
1125
|
+
* debounced cacheSeatLayer() and the synchronous forceDraw() catch-up. */
|
|
1126
|
+
private rebuildSeatCache;
|
|
1112
1127
|
private cacheSeatLayer;
|
|
1128
|
+
/**
|
|
1129
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame — see the
|
|
1130
|
+
* ISeatmapRenderer.forceDraw() contract. Chrome pauses rAF (and therefore
|
|
1131
|
+
* Konva's batchDraw) on hidden/backgrounded/occluded tabs, so seat-status
|
|
1132
|
+
* deltas applied via setStatus() mutate the scene graph but never reach the
|
|
1133
|
+
* canvas until the tab is foregrounded. This flushes the cache-debounce and
|
|
1134
|
+
* paints every layer setStatus() can touch, immediately.
|
|
1135
|
+
*
|
|
1136
|
+
* Additive: the foreground path never calls this, so foreground behaviour is
|
|
1137
|
+
* byte-identical.
|
|
1138
|
+
*/
|
|
1139
|
+
forceDraw(): void;
|
|
1113
1140
|
private updateLabels;
|
|
1114
1141
|
private handleResize;
|
|
1115
1142
|
private startFpsLoop;
|
|
@@ -1280,6 +1307,18 @@ interface PickerOptions extends PickerCallbacks {
|
|
|
1280
1307
|
flashOnLiveChange?: boolean;
|
|
1281
1308
|
/** Start in colorblind-safe rendering (Okabe-Ito hues + hollow booked seats). */
|
|
1282
1309
|
colorblindSafe?: boolean;
|
|
1310
|
+
/**
|
|
1311
|
+
* Keep painting seat-status deltas even while the tab is hidden/backgrounded.
|
|
1312
|
+
*
|
|
1313
|
+
* Default FALSE — the buyer widget stays efficient: it lets rAF stay paused
|
|
1314
|
+
* while hidden and does a single synchronous catch-up repaint on regain (the
|
|
1315
|
+
* visibilitychange handler resnapshots + forceDraw()s). Set TRUE only for an
|
|
1316
|
+
* always-live surface — the future organizer control-room board — where a
|
|
1317
|
+
* backgrounded monitor must keep repainting; then each delta calls
|
|
1318
|
+
* renderer.forceDraw() when the tab is hidden. Purely a paint hint; enforcement
|
|
1319
|
+
* and the WS protocol are identical either way.
|
|
1320
|
+
*/
|
|
1321
|
+
keepLiveWhileHidden?: boolean;
|
|
1283
1322
|
}
|
|
1284
1323
|
declare class PickerController {
|
|
1285
1324
|
private readonly opts;
|
|
@@ -1305,6 +1344,10 @@ declare class PickerController {
|
|
|
1305
1344
|
private reconnectTimer;
|
|
1306
1345
|
private attempt;
|
|
1307
1346
|
private closed;
|
|
1347
|
+
/** Bound visibilitychange listener (buyer catch-up on tab regain). Kept on the
|
|
1348
|
+
* instance so destroy() can detach it; null when not attached (guards double
|
|
1349
|
+
* mounts / non-DOM environments). */
|
|
1350
|
+
private onVisibilityChange;
|
|
1308
1351
|
private hold_;
|
|
1309
1352
|
private liveStatuses;
|
|
1310
1353
|
private currency;
|
|
@@ -1498,6 +1541,19 @@ declare class PickerController {
|
|
|
1498
1541
|
private applySeatsMap;
|
|
1499
1542
|
private clearBookedHoldIfSettled;
|
|
1500
1543
|
private resnapshot;
|
|
1544
|
+
/**
|
|
1545
|
+
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
1546
|
+
* seat-status deltas that arrived over the WS mutated the scene graph but the
|
|
1547
|
+
* canvas colors never repainted. When the tab becomes visible again we (1)
|
|
1548
|
+
* resnapshot to pull authoritative state for anything the socket may have
|
|
1549
|
+
* missed while backgrounded, then (2) forceDraw() a synchronous repaint so the
|
|
1550
|
+
* seat colors are correct immediately rather than on the next incidental draw.
|
|
1551
|
+
*
|
|
1552
|
+
* Attached once per mount; guarded against double-attach and non-DOM
|
|
1553
|
+
* environments; detached in destroy() (no leaks).
|
|
1554
|
+
*/
|
|
1555
|
+
private attachVisibilityListener;
|
|
1556
|
+
private detachVisibilityListener;
|
|
1501
1557
|
private connect;
|
|
1502
1558
|
private scheduleReconnect;
|
|
1503
1559
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -411,6 +411,18 @@ interface ISeatmapRenderer {
|
|
|
411
411
|
}): void;
|
|
412
412
|
/** Bulk status update; re-renders affected seats only. */
|
|
413
413
|
setStatus(seatIds: string[], status: SeatStatus): void;
|
|
414
|
+
/**
|
|
415
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame. Konva's batchDraw()
|
|
416
|
+
* (used by setStatus and friends) schedules the actual paint on the next rAF
|
|
417
|
+
* tick, which Chrome throttles/pauses on hidden, backgrounded, or occluded
|
|
418
|
+
* tabs — so a seat-status delta updates the scene graph but the pixels never
|
|
419
|
+
* change until the tab is foregrounded again. forceDraw() paints the affected
|
|
420
|
+
* layers immediately (Layer.draw() is synchronous) and flushes any pending
|
|
421
|
+
* cache-debounce, so a caller (visibilitychange catch-up, or an opted-in
|
|
422
|
+
* always-live board) can guarantee the canvas reflects current state
|
|
423
|
+
* regardless of tab visibility. No-op difference in the foreground.
|
|
424
|
+
*/
|
|
425
|
+
forceDraw(): void;
|
|
414
426
|
getStatus(seatId: string): SeatStatus;
|
|
415
427
|
getSelection(): ExpandedSeat[];
|
|
416
428
|
clearSelection(): void;
|
|
@@ -1109,7 +1121,22 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1109
1121
|
/** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */
|
|
1110
1122
|
private scheduleViewChange;
|
|
1111
1123
|
private updateLOD;
|
|
1124
|
+
/** Rebuild the seat-layer bitmap synchronously (no paint). Shared by the
|
|
1125
|
+
* debounced cacheSeatLayer() and the synchronous forceDraw() catch-up. */
|
|
1126
|
+
private rebuildSeatCache;
|
|
1112
1127
|
private cacheSeatLayer;
|
|
1128
|
+
/**
|
|
1129
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame — see the
|
|
1130
|
+
* ISeatmapRenderer.forceDraw() contract. Chrome pauses rAF (and therefore
|
|
1131
|
+
* Konva's batchDraw) on hidden/backgrounded/occluded tabs, so seat-status
|
|
1132
|
+
* deltas applied via setStatus() mutate the scene graph but never reach the
|
|
1133
|
+
* canvas until the tab is foregrounded. This flushes the cache-debounce and
|
|
1134
|
+
* paints every layer setStatus() can touch, immediately.
|
|
1135
|
+
*
|
|
1136
|
+
* Additive: the foreground path never calls this, so foreground behaviour is
|
|
1137
|
+
* byte-identical.
|
|
1138
|
+
*/
|
|
1139
|
+
forceDraw(): void;
|
|
1113
1140
|
private updateLabels;
|
|
1114
1141
|
private handleResize;
|
|
1115
1142
|
private startFpsLoop;
|
|
@@ -1280,6 +1307,18 @@ interface PickerOptions extends PickerCallbacks {
|
|
|
1280
1307
|
flashOnLiveChange?: boolean;
|
|
1281
1308
|
/** Start in colorblind-safe rendering (Okabe-Ito hues + hollow booked seats). */
|
|
1282
1309
|
colorblindSafe?: boolean;
|
|
1310
|
+
/**
|
|
1311
|
+
* Keep painting seat-status deltas even while the tab is hidden/backgrounded.
|
|
1312
|
+
*
|
|
1313
|
+
* Default FALSE — the buyer widget stays efficient: it lets rAF stay paused
|
|
1314
|
+
* while hidden and does a single synchronous catch-up repaint on regain (the
|
|
1315
|
+
* visibilitychange handler resnapshots + forceDraw()s). Set TRUE only for an
|
|
1316
|
+
* always-live surface — the future organizer control-room board — where a
|
|
1317
|
+
* backgrounded monitor must keep repainting; then each delta calls
|
|
1318
|
+
* renderer.forceDraw() when the tab is hidden. Purely a paint hint; enforcement
|
|
1319
|
+
* and the WS protocol are identical either way.
|
|
1320
|
+
*/
|
|
1321
|
+
keepLiveWhileHidden?: boolean;
|
|
1283
1322
|
}
|
|
1284
1323
|
declare class PickerController {
|
|
1285
1324
|
private readonly opts;
|
|
@@ -1305,6 +1344,10 @@ declare class PickerController {
|
|
|
1305
1344
|
private reconnectTimer;
|
|
1306
1345
|
private attempt;
|
|
1307
1346
|
private closed;
|
|
1347
|
+
/** Bound visibilitychange listener (buyer catch-up on tab regain). Kept on the
|
|
1348
|
+
* instance so destroy() can detach it; null when not attached (guards double
|
|
1349
|
+
* mounts / non-DOM environments). */
|
|
1350
|
+
private onVisibilityChange;
|
|
1308
1351
|
private hold_;
|
|
1309
1352
|
private liveStatuses;
|
|
1310
1353
|
private currency;
|
|
@@ -1498,6 +1541,19 @@ declare class PickerController {
|
|
|
1498
1541
|
private applySeatsMap;
|
|
1499
1542
|
private clearBookedHoldIfSettled;
|
|
1500
1543
|
private resnapshot;
|
|
1544
|
+
/**
|
|
1545
|
+
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
1546
|
+
* seat-status deltas that arrived over the WS mutated the scene graph but the
|
|
1547
|
+
* canvas colors never repainted. When the tab becomes visible again we (1)
|
|
1548
|
+
* resnapshot to pull authoritative state for anything the socket may have
|
|
1549
|
+
* missed while backgrounded, then (2) forceDraw() a synchronous repaint so the
|
|
1550
|
+
* seat colors are correct immediately rather than on the next incidental draw.
|
|
1551
|
+
*
|
|
1552
|
+
* Attached once per mount; guarded against double-attach and non-DOM
|
|
1553
|
+
* environments; detached in destroy() (no leaks).
|
|
1554
|
+
*/
|
|
1555
|
+
private attachVisibilityListener;
|
|
1556
|
+
private detachVisibilityListener;
|
|
1501
1557
|
private connect;
|
|
1502
1558
|
private scheduleReconnect;
|
|
1503
1559
|
}
|
package/dist/index.js
CHANGED
|
@@ -2849,14 +2849,40 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2849
2849
|
this.seatLayer.batchDraw();
|
|
2850
2850
|
}
|
|
2851
2851
|
}
|
|
2852
|
-
|
|
2852
|
+
/** Rebuild the seat-layer bitmap synchronously (no paint). Shared by the
|
|
2853
|
+
* debounced cacheSeatLayer() and the synchronous forceDraw() catch-up. */
|
|
2854
|
+
rebuildSeatCache() {
|
|
2853
2855
|
const pr = clamp(this.stage.scaleX() * this.dpr, 0.15, 2);
|
|
2854
2856
|
this.seatLayer.clearCache();
|
|
2855
2857
|
this.seatLayer.cache({ pixelRatio: pr });
|
|
2856
2858
|
this.seatLayer.listening(false);
|
|
2857
2859
|
this.cached = true;
|
|
2860
|
+
}
|
|
2861
|
+
cacheSeatLayer() {
|
|
2862
|
+
this.rebuildSeatCache();
|
|
2858
2863
|
this.seatLayer.batchDraw();
|
|
2859
2864
|
}
|
|
2865
|
+
/**
|
|
2866
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame — see the
|
|
2867
|
+
* ISeatmapRenderer.forceDraw() contract. Chrome pauses rAF (and therefore
|
|
2868
|
+
* Konva's batchDraw) on hidden/backgrounded/occluded tabs, so seat-status
|
|
2869
|
+
* deltas applied via setStatus() mutate the scene graph but never reach the
|
|
2870
|
+
* canvas until the tab is foregrounded. This flushes the cache-debounce and
|
|
2871
|
+
* paints every layer setStatus() can touch, immediately.
|
|
2872
|
+
*
|
|
2873
|
+
* Additive: the foreground path never calls this, so foreground behaviour is
|
|
2874
|
+
* byte-identical.
|
|
2875
|
+
*/
|
|
2876
|
+
forceDraw() {
|
|
2877
|
+
if (this.recacheTimer) {
|
|
2878
|
+
clearTimeout(this.recacheTimer);
|
|
2879
|
+
this.recacheTimer = null;
|
|
2880
|
+
this.rebuildSeatCache();
|
|
2881
|
+
}
|
|
2882
|
+
this.bgLayer.draw();
|
|
2883
|
+
this.seatLayer.draw();
|
|
2884
|
+
this.overlayLayer.draw();
|
|
2885
|
+
}
|
|
2860
2886
|
updateLabels() {
|
|
2861
2887
|
const show = this.effScale() > LABEL_SCALE;
|
|
2862
2888
|
this.labelGroup.destroyChildren();
|
|
@@ -2992,6 +3018,10 @@ var PickerController = class {
|
|
|
2992
3018
|
this.reconnectTimer = null;
|
|
2993
3019
|
this.attempt = 0;
|
|
2994
3020
|
this.closed = false;
|
|
3021
|
+
/** Bound visibilitychange listener (buyer catch-up on tab regain). Kept on the
|
|
3022
|
+
* instance so destroy() can detach it; null when not attached (guards double
|
|
3023
|
+
* mounts / non-DOM environments). */
|
|
3024
|
+
this.onVisibilityChange = null;
|
|
2995
3025
|
// hold state
|
|
2996
3026
|
this.hold_ = null;
|
|
2997
3027
|
this.liveStatuses = /* @__PURE__ */ new Map();
|
|
@@ -3117,6 +3147,7 @@ var PickerController = class {
|
|
|
3117
3147
|
this.closedSections = new Set(closedIds);
|
|
3118
3148
|
if (closedIds.length) renderer.setClosedSections?.(closedIds);
|
|
3119
3149
|
if (seats) this.applySeatsMap(seats);
|
|
3150
|
+
this.attachVisibilityListener();
|
|
3120
3151
|
this.connect();
|
|
3121
3152
|
return {
|
|
3122
3153
|
doc: res.doc,
|
|
@@ -3543,6 +3574,7 @@ var PickerController = class {
|
|
|
3543
3574
|
}
|
|
3544
3575
|
destroy() {
|
|
3545
3576
|
this.closed = true;
|
|
3577
|
+
this.detachVisibilityListener();
|
|
3546
3578
|
if (this.reconnectTimer) {
|
|
3547
3579
|
clearTimeout(this.reconnectTimer);
|
|
3548
3580
|
this.reconnectTimer = null;
|
|
@@ -3739,6 +3771,37 @@ var PickerController = class {
|
|
|
3739
3771
|
}
|
|
3740
3772
|
}
|
|
3741
3773
|
// ---- realtime socket ------------------------------------------------------
|
|
3774
|
+
/**
|
|
3775
|
+
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
3776
|
+
* seat-status deltas that arrived over the WS mutated the scene graph but the
|
|
3777
|
+
* canvas colors never repainted. When the tab becomes visible again we (1)
|
|
3778
|
+
* resnapshot to pull authoritative state for anything the socket may have
|
|
3779
|
+
* missed while backgrounded, then (2) forceDraw() a synchronous repaint so the
|
|
3780
|
+
* seat colors are correct immediately rather than on the next incidental draw.
|
|
3781
|
+
*
|
|
3782
|
+
* Attached once per mount; guarded against double-attach and non-DOM
|
|
3783
|
+
* environments; detached in destroy() (no leaks).
|
|
3784
|
+
*/
|
|
3785
|
+
attachVisibilityListener() {
|
|
3786
|
+
if (this.onVisibilityChange) return;
|
|
3787
|
+
if (typeof document === "undefined" || typeof document.addEventListener !== "function") return;
|
|
3788
|
+
const handler = () => {
|
|
3789
|
+
if (this.closed) return;
|
|
3790
|
+
if (document.visibilityState !== "visible") return;
|
|
3791
|
+
void this.resnapshot().then(() => {
|
|
3792
|
+
if (!this.closed) this.renderer?.forceDraw();
|
|
3793
|
+
});
|
|
3794
|
+
};
|
|
3795
|
+
this.onVisibilityChange = handler;
|
|
3796
|
+
document.addEventListener("visibilitychange", handler);
|
|
3797
|
+
}
|
|
3798
|
+
detachVisibilityListener() {
|
|
3799
|
+
if (!this.onVisibilityChange) return;
|
|
3800
|
+
if (typeof document !== "undefined" && typeof document.removeEventListener === "function") {
|
|
3801
|
+
document.removeEventListener("visibilitychange", this.onVisibilityChange);
|
|
3802
|
+
}
|
|
3803
|
+
this.onVisibilityChange = null;
|
|
3804
|
+
}
|
|
3742
3805
|
connect() {
|
|
3743
3806
|
if (this.closed) return;
|
|
3744
3807
|
let ws;
|
|
@@ -3784,6 +3847,9 @@ var PickerController = class {
|
|
|
3784
3847
|
}
|
|
3785
3848
|
r.setStatus([id], next);
|
|
3786
3849
|
}
|
|
3850
|
+
if (this.opts.keepLiveWhileHidden && typeof document !== "undefined" && document.visibilityState === "hidden") {
|
|
3851
|
+
r.forceDraw();
|
|
3852
|
+
}
|
|
3787
3853
|
this.clearBookedHoldIfSettled();
|
|
3788
3854
|
this.opts.onStatusChange?.();
|
|
3789
3855
|
}
|