@seatlayer/core 0.18.0 → 0.18.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 +40 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -5
- package/dist/index.d.ts +24 -5
- package/dist/index.js +40 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -139,6 +139,10 @@ interface SeatOverride {
|
|
|
139
139
|
commercial?: SeatCommercialAttributes;
|
|
140
140
|
/** Seat-specific view photo; falls back to the row photo. */
|
|
141
141
|
viewFromSeatUrl?: string;
|
|
142
|
+
/** Per-seat label size/color override; falls back to the row/theme default.
|
|
143
|
+
* Size is clamped to LABEL_STYLE_MIN_SIZE..MAX_SIZE; color is passed through
|
|
144
|
+
* the shared auto-contrast rule at paint time (see {@link LabelStyle}). */
|
|
145
|
+
labelStyle?: LabelStyle;
|
|
142
146
|
}
|
|
143
147
|
interface SeatCommercialAttributes {
|
|
144
148
|
restrictedView?: boolean;
|
|
@@ -640,6 +644,8 @@ interface ExpandedSeat {
|
|
|
640
644
|
commercial?: SeatCommercialAttributes;
|
|
641
645
|
/** Organizer-supplied view-from-seat image (inherited from the row). */
|
|
642
646
|
viewUrl?: string;
|
|
647
|
+
/** Per-seat label size/color override; absent = inherit the row/theme default. */
|
|
648
|
+
labelStyle?: LabelStyle;
|
|
643
649
|
}
|
|
644
650
|
type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';
|
|
645
651
|
interface RendererCallbacks {
|
|
@@ -1063,6 +1069,7 @@ interface RowSeatSlot {
|
|
|
1063
1069
|
accessibility: AccessibilityType[];
|
|
1064
1070
|
commercial?: RowObject['commercial'];
|
|
1065
1071
|
viewUrl?: string;
|
|
1072
|
+
labelStyle?: LabelStyle;
|
|
1066
1073
|
}
|
|
1067
1074
|
declare function expandRowSlots(row: RowObject): RowSeatSlot[];
|
|
1068
1075
|
declare function expandRow(row: RowObject): ExpandedSeat[];
|
|
@@ -1489,11 +1496,16 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1489
1496
|
private renderBoothUnit;
|
|
1490
1497
|
/** The category's display color — Okabe-Ito hue when colorblind-safe is on. */
|
|
1491
1498
|
private seatBaseColor;
|
|
1492
|
-
/**
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
|
|
1496
|
-
|
|
1499
|
+
/** Per-seat authored label size relative to the neutral default (1 = default),
|
|
1500
|
+
* mirroring the section convention (labelStyle.size ?? 18) / 18. Only real
|
|
1501
|
+
* seats carry labelStyle, so booths and unstyled seats resolve to 1. */
|
|
1502
|
+
private seatLabelScale;
|
|
1503
|
+
/** Preferred label ink for a seat: the authored per-seat colour when set,
|
|
1504
|
+
* otherwise today's theme default. Fed through auto-contrast by seatLabelInk. */
|
|
1505
|
+
private seatPreferredLabelInk;
|
|
1506
|
+
/** Resolve a seat's label ink against the paint actually visible, honouring an
|
|
1507
|
+
* authored per-seat colour through the same auto-contrast rule as sections. */
|
|
1508
|
+
private seatLabelInk;
|
|
1497
1509
|
/** Apply fill/stroke/opacity for a seat's current status + selection. */
|
|
1498
1510
|
private paintSeat;
|
|
1499
1511
|
/** True when a seat sits in a section/zone currently marked `closed`. */
|
|
@@ -2170,6 +2182,13 @@ declare class PickerController {
|
|
|
2170
2182
|
private applySeatsMap;
|
|
2171
2183
|
private clearBookedHoldIfSettled;
|
|
2172
2184
|
private resnapshot;
|
|
2185
|
+
/**
|
|
2186
|
+
* Re-pull the status snapshot on demand. Live surfaces rarely need this (the
|
|
2187
|
+
* socket keeps them fresh); local/mock transports with no socket call it
|
|
2188
|
+
* after they mutate state (e.g. the demo books a hold) so the renderer and
|
|
2189
|
+
* every onStatusChange consumer repaint from the new truth.
|
|
2190
|
+
*/
|
|
2191
|
+
refresh(): Promise<void>;
|
|
2173
2192
|
/**
|
|
2174
2193
|
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
2175
2194
|
* seat-status deltas that arrived over the WS mutated the scene graph but the
|
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,10 @@ interface SeatOverride {
|
|
|
139
139
|
commercial?: SeatCommercialAttributes;
|
|
140
140
|
/** Seat-specific view photo; falls back to the row photo. */
|
|
141
141
|
viewFromSeatUrl?: string;
|
|
142
|
+
/** Per-seat label size/color override; falls back to the row/theme default.
|
|
143
|
+
* Size is clamped to LABEL_STYLE_MIN_SIZE..MAX_SIZE; color is passed through
|
|
144
|
+
* the shared auto-contrast rule at paint time (see {@link LabelStyle}). */
|
|
145
|
+
labelStyle?: LabelStyle;
|
|
142
146
|
}
|
|
143
147
|
interface SeatCommercialAttributes {
|
|
144
148
|
restrictedView?: boolean;
|
|
@@ -640,6 +644,8 @@ interface ExpandedSeat {
|
|
|
640
644
|
commercial?: SeatCommercialAttributes;
|
|
641
645
|
/** Organizer-supplied view-from-seat image (inherited from the row). */
|
|
642
646
|
viewUrl?: string;
|
|
647
|
+
/** Per-seat label size/color override; absent = inherit the row/theme default. */
|
|
648
|
+
labelStyle?: LabelStyle;
|
|
643
649
|
}
|
|
644
650
|
type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';
|
|
645
651
|
interface RendererCallbacks {
|
|
@@ -1063,6 +1069,7 @@ interface RowSeatSlot {
|
|
|
1063
1069
|
accessibility: AccessibilityType[];
|
|
1064
1070
|
commercial?: RowObject['commercial'];
|
|
1065
1071
|
viewUrl?: string;
|
|
1072
|
+
labelStyle?: LabelStyle;
|
|
1066
1073
|
}
|
|
1067
1074
|
declare function expandRowSlots(row: RowObject): RowSeatSlot[];
|
|
1068
1075
|
declare function expandRow(row: RowObject): ExpandedSeat[];
|
|
@@ -1489,11 +1496,16 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
1489
1496
|
private renderBoothUnit;
|
|
1490
1497
|
/** The category's display color — Okabe-Ito hue when colorblind-safe is on. */
|
|
1491
1498
|
private seatBaseColor;
|
|
1492
|
-
/**
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
|
|
1496
|
-
|
|
1499
|
+
/** Per-seat authored label size relative to the neutral default (1 = default),
|
|
1500
|
+
* mirroring the section convention (labelStyle.size ?? 18) / 18. Only real
|
|
1501
|
+
* seats carry labelStyle, so booths and unstyled seats resolve to 1. */
|
|
1502
|
+
private seatLabelScale;
|
|
1503
|
+
/** Preferred label ink for a seat: the authored per-seat colour when set,
|
|
1504
|
+
* otherwise today's theme default. Fed through auto-contrast by seatLabelInk. */
|
|
1505
|
+
private seatPreferredLabelInk;
|
|
1506
|
+
/** Resolve a seat's label ink against the paint actually visible, honouring an
|
|
1507
|
+
* authored per-seat colour through the same auto-contrast rule as sections. */
|
|
1508
|
+
private seatLabelInk;
|
|
1497
1509
|
/** Apply fill/stroke/opacity for a seat's current status + selection. */
|
|
1498
1510
|
private paintSeat;
|
|
1499
1511
|
/** True when a seat sits in a section/zone currently marked `closed`. */
|
|
@@ -2170,6 +2182,13 @@ declare class PickerController {
|
|
|
2170
2182
|
private applySeatsMap;
|
|
2171
2183
|
private clearBookedHoldIfSettled;
|
|
2172
2184
|
private resnapshot;
|
|
2185
|
+
/**
|
|
2186
|
+
* Re-pull the status snapshot on demand. Live surfaces rarely need this (the
|
|
2187
|
+
* socket keeps them fresh); local/mock transports with no socket call it
|
|
2188
|
+
* after they mutate state (e.g. the demo books a hold) so the renderer and
|
|
2189
|
+
* every onStatusChange consumer repaint from the new truth.
|
|
2190
|
+
*/
|
|
2191
|
+
refresh(): Promise<void>;
|
|
2173
2192
|
/**
|
|
2174
2193
|
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
2175
2194
|
* seat-status deltas that arrived over the WS mutated the scene graph but the
|
package/dist/index.js
CHANGED
|
@@ -187,7 +187,8 @@ function expandRowSlots(row) {
|
|
|
187
187
|
accessible: accessibility.length > 0,
|
|
188
188
|
accessibility,
|
|
189
189
|
commercial: Object.values(commercial).some((value) => value !== void 0 && value !== false && value !== "") ? commercial : void 0,
|
|
190
|
-
viewUrl: o?.viewFromSeatUrl ?? row.viewFromSeatUrl
|
|
190
|
+
viewUrl: o?.viewFromSeatUrl ?? row.viewFromSeatUrl,
|
|
191
|
+
labelStyle: o?.labelStyle
|
|
191
192
|
};
|
|
192
193
|
});
|
|
193
194
|
}
|
|
@@ -206,7 +207,8 @@ function expandRow(row) {
|
|
|
206
207
|
accessible: slot.accessible || void 0,
|
|
207
208
|
accessibility: slot.accessibility.length ? slot.accessibility : void 0,
|
|
208
209
|
commercial: slot.commercial,
|
|
209
|
-
viewUrl: slot.viewUrl
|
|
210
|
+
viewUrl: slot.viewUrl,
|
|
211
|
+
labelStyle: slot.labelStyle
|
|
210
212
|
});
|
|
211
213
|
}
|
|
212
214
|
return seats;
|
|
@@ -2402,14 +2404,22 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2402
2404
|
const idx = this.catOrder.indexOf(categoryKey);
|
|
2403
2405
|
return CB_PALETTE[(idx >= 0 ? idx : 0) % CB_PALETTE.length];
|
|
2404
2406
|
}
|
|
2405
|
-
/**
|
|
2406
|
-
*
|
|
2407
|
-
*
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2407
|
+
/** Per-seat authored label size relative to the neutral default (1 = default),
|
|
2408
|
+
* mirroring the section convention (labelStyle.size ?? 18) / 18. Only real
|
|
2409
|
+
* seats carry labelStyle, so booths and unstyled seats resolve to 1. */
|
|
2410
|
+
seatLabelScale(seat) {
|
|
2411
|
+
return (seat.labelStyle?.size ?? 18) / 18;
|
|
2412
|
+
}
|
|
2413
|
+
/** Preferred label ink for a seat: the authored per-seat colour when set,
|
|
2414
|
+
* otherwise today's theme default. Fed through auto-contrast by seatLabelInk. */
|
|
2415
|
+
seatPreferredLabelInk(seat) {
|
|
2416
|
+
return seat.labelStyle?.color ?? this.theme.seatLabelColor ?? DEF_SEAT_LABEL;
|
|
2417
|
+
}
|
|
2418
|
+
/** Resolve a seat's label ink against the paint actually visible, honouring an
|
|
2419
|
+
* authored per-seat colour through the same auto-contrast rule as sections. */
|
|
2420
|
+
seatLabelInk(seat, shape) {
|
|
2411
2421
|
const fill = shape.fill();
|
|
2412
|
-
return stateAwareBookableLabelInk(typeof fill === "string" ? fill : "",
|
|
2422
|
+
return stateAwareBookableLabelInk(typeof fill === "string" ? fill : "", this.seatPreferredLabelInk(seat));
|
|
2413
2423
|
}
|
|
2414
2424
|
/** Apply fill/stroke/opacity for a seat's current status + selection. */
|
|
2415
2425
|
paintSeat(c, id) {
|
|
@@ -2493,7 +2503,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
2493
2503
|
if (this.selectionFocusId && id !== this.selectionFocusId) c.opacity(Math.min(c.opacity(), 0.16));
|
|
2494
2504
|
const bookableLabel = this.boothLabelById.get(id) ?? this.seatLabelById.get(id);
|
|
2495
2505
|
if (bookableLabel) {
|
|
2496
|
-
bookableLabel.fill(this.
|
|
2506
|
+
bookableLabel.fill(this.seatLabelInk(seat, c));
|
|
2497
2507
|
bookableLabel.visible(
|
|
2498
2508
|
isBookableLabelLegibleAtScale(bookableLabel.fontSize(), this.effScale()) && c.opacity() >= 0.5
|
|
2499
2509
|
);
|
|
@@ -3873,7 +3883,7 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
3873
3883
|
const labels = this.seats.map((seat) => {
|
|
3874
3884
|
const shape = this.circleById.get(seat.id);
|
|
3875
3885
|
const label = this.boothLabelById.get(seat.id) ?? this.seatLabelById.get(seat.id);
|
|
3876
|
-
const authoredFontSize = seat.kind === "booth" ? BOOTH_LABEL_FONT_SIZE : SEAT_LABEL_FONT_SIZE;
|
|
3886
|
+
const authoredFontSize = seat.kind === "booth" ? BOOTH_LABEL_FONT_SIZE : SEAT_LABEL_FONT_SIZE * this.seatLabelScale(seat);
|
|
3877
3887
|
const renderedFontPx = rounded((label?.fontSize() ?? authoredFontSize) * effectiveScale);
|
|
3878
3888
|
const screen = this.worldToScreen(seat);
|
|
3879
3889
|
const outside = screen.x < 0 || screen.x > viewport.width || screen.y < 0 || screen.y > viewport.height;
|
|
@@ -4190,9 +4200,10 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4190
4200
|
minimumFont = Math.min(minimumFont, BOOTH_LABEL_FONT_SIZE);
|
|
4191
4201
|
continue;
|
|
4192
4202
|
}
|
|
4193
|
-
|
|
4203
|
+
const authoredFontSize = SEAT_LABEL_FONT_SIZE * this.seatLabelScale(seat);
|
|
4204
|
+
measure.fontSize(authoredFontSize);
|
|
4194
4205
|
measure.text(bookableMarkerLabel(seat.displayLabel ?? seat.label));
|
|
4195
|
-
const fitted = measure.width() > maxWidth ? Math.max(MIN_FITTED_SEAT_LABEL_FONT_SIZE,
|
|
4206
|
+
const fitted = measure.width() > maxWidth ? Math.max(MIN_FITTED_SEAT_LABEL_FONT_SIZE, authoredFontSize * maxWidth / measure.width()) : authoredFontSize;
|
|
4196
4207
|
minimumFont = Math.min(minimumFont, fitted);
|
|
4197
4208
|
}
|
|
4198
4209
|
measure.destroy();
|
|
@@ -4342,19 +4353,20 @@ var _SeatmapRenderer = class _SeatmapRenderer {
|
|
|
4342
4353
|
if (++count >= MAX_LABELS) break;
|
|
4343
4354
|
continue;
|
|
4344
4355
|
}
|
|
4356
|
+
const authoredFontSize = SEAT_LABEL_FONT_SIZE * this.seatLabelScale(seat);
|
|
4345
4357
|
const t2 = new Text({
|
|
4346
4358
|
x: seat.x,
|
|
4347
4359
|
y: seat.y,
|
|
4348
4360
|
text: bookableMarkerLabel(seat.displayLabel ?? seat.label),
|
|
4349
|
-
fontSize:
|
|
4361
|
+
fontSize: authoredFontSize,
|
|
4350
4362
|
fontStyle: "600",
|
|
4351
4363
|
fontFamily: this.labelFont(),
|
|
4352
|
-
fill: shape ? this.
|
|
4364
|
+
fill: shape ? this.seatLabelInk(seat, shape) : this.seatPreferredLabelInk(seat),
|
|
4353
4365
|
listening: false,
|
|
4354
4366
|
perfectDrawEnabled: false
|
|
4355
4367
|
});
|
|
4356
4368
|
const maxW = this.seatR * 2 - 3;
|
|
4357
|
-
if (t2.width() > maxW) t2.fontSize(Math.max(MIN_FITTED_SEAT_LABEL_FONT_SIZE,
|
|
4369
|
+
if (t2.width() > maxW) t2.fontSize(Math.max(MIN_FITTED_SEAT_LABEL_FONT_SIZE, authoredFontSize * maxW / t2.width()));
|
|
4358
4370
|
if (t2.width() > maxW + 0.01) {
|
|
4359
4371
|
t2.destroy();
|
|
4360
4372
|
continue;
|
|
@@ -5314,6 +5326,15 @@ var PickerController = class {
|
|
|
5314
5326
|
} catch {
|
|
5315
5327
|
}
|
|
5316
5328
|
}
|
|
5329
|
+
/**
|
|
5330
|
+
* Re-pull the status snapshot on demand. Live surfaces rarely need this (the
|
|
5331
|
+
* socket keeps them fresh); local/mock transports with no socket call it
|
|
5332
|
+
* after they mutate state (e.g. the demo books a hold) so the renderer and
|
|
5333
|
+
* every onStatusChange consumer repaint from the new truth.
|
|
5334
|
+
*/
|
|
5335
|
+
async refresh() {
|
|
5336
|
+
await this.resnapshot();
|
|
5337
|
+
}
|
|
5317
5338
|
// ---- realtime socket ------------------------------------------------------
|
|
5318
5339
|
/**
|
|
5319
5340
|
* Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so
|
|
@@ -5348,9 +5369,11 @@ var PickerController = class {
|
|
|
5348
5369
|
}
|
|
5349
5370
|
connect() {
|
|
5350
5371
|
if (this.closed) return;
|
|
5372
|
+
const url = this.api.socketUrl(this.key);
|
|
5373
|
+
if (!url) return;
|
|
5351
5374
|
let ws;
|
|
5352
5375
|
try {
|
|
5353
|
-
ws = new WebSocket(
|
|
5376
|
+
ws = new WebSocket(url);
|
|
5354
5377
|
} catch {
|
|
5355
5378
|
this.scheduleReconnect();
|
|
5356
5379
|
return;
|