@nex125/seatmap-core 0.1.0 → 0.1.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 +91 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -12
- package/dist/index.d.ts +27 -12
- package/dist/index.js +90 -21
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var uuid = require('uuid');
|
|
3
4
|
var RBush = require('rbush');
|
|
4
5
|
var pixi_js = require('pixi.js');
|
|
5
6
|
|
|
@@ -8,6 +9,22 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
8
9
|
var RBush__default = /*#__PURE__*/_interopDefault(RBush);
|
|
9
10
|
|
|
10
11
|
// src/models/helpers.ts
|
|
12
|
+
var AVAILABLE_STATUS_ID = "available";
|
|
13
|
+
var DEFAULT_SEAT_STATUSES = [
|
|
14
|
+
{ id: AVAILABLE_STATUS_ID, name: "Available", color: "#4caf50" },
|
|
15
|
+
{ id: "locked", name: "Locked", color: "#f44336" },
|
|
16
|
+
{ id: "booked", name: "Booked", color: "#9e9e9e" }
|
|
17
|
+
];
|
|
18
|
+
var LEGACY_STATUS_MAP = {
|
|
19
|
+
held: "locked",
|
|
20
|
+
blocked: "locked",
|
|
21
|
+
sold: "booked"
|
|
22
|
+
};
|
|
23
|
+
function normalizeStatusId(rawStatus, allowedStatuses) {
|
|
24
|
+
const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;
|
|
25
|
+
if (allowedStatuses.has(mapped)) return mapped;
|
|
26
|
+
return AVAILABLE_STATUS_ID;
|
|
27
|
+
}
|
|
11
28
|
function seatWorldPosition(section, seat) {
|
|
12
29
|
const cos = Math.cos(section.rotation);
|
|
13
30
|
const sin = Math.sin(section.rotation);
|
|
@@ -111,9 +128,48 @@ function clampToPolygon(point, polygon, margin = 5) {
|
|
|
111
128
|
}
|
|
112
129
|
return { x: bestX, y: bestY };
|
|
113
130
|
}
|
|
114
|
-
|
|
131
|
+
function normalizeVenue(venue) {
|
|
132
|
+
const seatStatuses = venue.seatStatuses && venue.seatStatuses.length > 0 ? venue.seatStatuses : DEFAULT_SEAT_STATUSES;
|
|
133
|
+
const clonedStatuses = seatStatuses.map((status) => ({ ...status }));
|
|
134
|
+
const allowedStatuses = new Set(clonedStatuses.map((status) => status.id));
|
|
135
|
+
const categories = venue.categories.map((category) => {
|
|
136
|
+
const hasBackendPrice = Number.isFinite(category.backendPrice);
|
|
137
|
+
const hasOverriddenPrice = Number.isFinite(category.overriddenPrice);
|
|
138
|
+
return {
|
|
139
|
+
...category,
|
|
140
|
+
backendPrice: hasBackendPrice ? category.backendPrice : void 0,
|
|
141
|
+
overriddenPrice: hasOverriddenPrice ? category.overriddenPrice : void 0,
|
|
142
|
+
isPriceOverridden: Boolean(category.isPriceOverridden) && hasOverriddenPrice
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
const sections = venue.sections.map((section) => ({
|
|
146
|
+
...section,
|
|
147
|
+
rows: section.rows.map((row) => ({
|
|
148
|
+
...row,
|
|
149
|
+
seats: row.seats.map((seat) => ({
|
|
150
|
+
...seat,
|
|
151
|
+
status: normalizeStatusId(seat.status, allowedStatuses)
|
|
152
|
+
}))
|
|
153
|
+
}))
|
|
154
|
+
}));
|
|
155
|
+
const tables = venue.tables.map((table) => ({
|
|
156
|
+
...table,
|
|
157
|
+
seats: table.seats.map((seat) => ({
|
|
158
|
+
...seat,
|
|
159
|
+
status: normalizeStatusId(seat.status, allowedStatuses)
|
|
160
|
+
}))
|
|
161
|
+
}));
|
|
162
|
+
return {
|
|
163
|
+
...venue,
|
|
164
|
+
categories,
|
|
165
|
+
seatStatuses: clonedStatuses,
|
|
166
|
+
sections,
|
|
167
|
+
tables
|
|
168
|
+
};
|
|
169
|
+
}
|
|
115
170
|
function generateId(prefix = "") {
|
|
116
|
-
|
|
171
|
+
const id = uuid.v7();
|
|
172
|
+
return prefix ? `${prefix}-${id}` : id;
|
|
117
173
|
}
|
|
118
174
|
var SpatialIndex = class {
|
|
119
175
|
tree = new RBush__default.default();
|
|
@@ -256,31 +312,44 @@ function getLODLevel(zoom) {
|
|
|
256
312
|
if (zoom < DETAIL_THRESHOLD) return "section" /* Section */;
|
|
257
313
|
return "detail" /* Detail */;
|
|
258
314
|
}
|
|
259
|
-
var
|
|
260
|
-
available: 5025616,
|
|
261
|
-
held: 16750592,
|
|
262
|
-
sold: 10395294,
|
|
263
|
-
blocked: 16007990,
|
|
315
|
+
var UI_TEXTURE_COLORS = {
|
|
264
316
|
selected: 2201331,
|
|
265
317
|
hovered: 6600182
|
|
266
318
|
};
|
|
267
|
-
function
|
|
319
|
+
function parseHexColor(color) {
|
|
320
|
+
return parseInt(color.replace("#", ""), 16);
|
|
321
|
+
}
|
|
322
|
+
function createSeatTextures(renderer, seatStatuses, radius = 7, categoryColor, textureResolution) {
|
|
268
323
|
const result = {};
|
|
269
|
-
const diameter = (radius + 4) * 2;
|
|
270
324
|
const resolution = textureResolution ?? 4 * (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1);
|
|
271
|
-
for (const
|
|
325
|
+
for (const status of seatStatuses) {
|
|
272
326
|
const g = new pixi_js.Graphics();
|
|
273
|
-
const fillColor = status === "available" && categoryColor != null ? categoryColor : color;
|
|
327
|
+
const fillColor = status.id === "available" && categoryColor != null ? categoryColor : parseHexColor(status.color);
|
|
274
328
|
g.circle(radius + 4, radius + 4, radius);
|
|
275
329
|
g.fill({ color: fillColor });
|
|
276
|
-
|
|
330
|
+
const texture = renderer.textureGenerator.generateTexture({
|
|
331
|
+
target: g,
|
|
332
|
+
resolution,
|
|
333
|
+
antialias: true
|
|
334
|
+
});
|
|
335
|
+
g.destroy();
|
|
336
|
+
result[status.id] = texture;
|
|
337
|
+
}
|
|
338
|
+
for (const [statusId, color] of Object.entries(UI_TEXTURE_COLORS)) {
|
|
339
|
+
const g = new pixi_js.Graphics();
|
|
340
|
+
g.circle(radius + 4, radius + 4, radius);
|
|
341
|
+
g.fill({ color });
|
|
342
|
+
if (statusId === "selected") {
|
|
277
343
|
g.circle(radius + 4, radius + 4, radius + 2);
|
|
278
344
|
g.stroke({ color: 16777215, width: 2 });
|
|
279
345
|
}
|
|
280
|
-
const texture =
|
|
281
|
-
|
|
346
|
+
const texture = renderer.textureGenerator.generateTexture({
|
|
347
|
+
target: g,
|
|
348
|
+
resolution,
|
|
349
|
+
antialias: true
|
|
350
|
+
});
|
|
282
351
|
g.destroy();
|
|
283
|
-
result[
|
|
352
|
+
result[statusId] = texture;
|
|
284
353
|
}
|
|
285
354
|
return result;
|
|
286
355
|
}
|
|
@@ -294,12 +363,12 @@ function destroySeatTextures(textures) {
|
|
|
294
363
|
var CategoryTextureCache = class {
|
|
295
364
|
cache = /* @__PURE__ */ new Map();
|
|
296
365
|
defaultTextures = null;
|
|
297
|
-
create(renderer, categories, seatRadius = 7) {
|
|
366
|
+
create(renderer, categories, seatStatuses, seatRadius = 7) {
|
|
298
367
|
this.destroy();
|
|
299
|
-
this.defaultTextures = createSeatTextures(renderer, seatRadius);
|
|
368
|
+
this.defaultTextures = createSeatTextures(renderer, seatStatuses, seatRadius);
|
|
300
369
|
for (const cat of categories) {
|
|
301
370
|
const color = parseInt(cat.color.replace("#", ""), 16);
|
|
302
|
-
this.cache.set(cat.id, createSeatTextures(renderer, seatRadius, color));
|
|
371
|
+
this.cache.set(cat.id, createSeatTextures(renderer, seatStatuses, seatRadius, color));
|
|
303
372
|
}
|
|
304
373
|
}
|
|
305
374
|
get(categoryId) {
|
|
@@ -369,11 +438,13 @@ function serializeVenue(venue) {
|
|
|
369
438
|
return JSON.stringify(venue, null, 2);
|
|
370
439
|
}
|
|
371
440
|
function deserializeVenue(json) {
|
|
372
|
-
return JSON.parse(json);
|
|
441
|
+
return normalizeVenue(JSON.parse(json));
|
|
373
442
|
}
|
|
374
443
|
|
|
444
|
+
exports.AVAILABLE_STATUS_ID = AVAILABLE_STATUS_ID;
|
|
375
445
|
exports.CategoryTextureCache = CategoryTextureCache;
|
|
376
446
|
exports.CommandHistory = CommandHistory;
|
|
447
|
+
exports.DEFAULT_SEAT_STATUSES = DEFAULT_SEAT_STATUSES;
|
|
377
448
|
exports.LODLevel = LODLevel;
|
|
378
449
|
exports.SpatialIndex = SpatialIndex;
|
|
379
450
|
exports.Viewport = Viewport;
|
|
@@ -383,6 +454,7 @@ exports.deserializeVenue = deserializeVenue;
|
|
|
383
454
|
exports.destroySeatTextures = destroySeatTextures;
|
|
384
455
|
exports.generateId = generateId;
|
|
385
456
|
exports.getLODLevel = getLODLevel;
|
|
457
|
+
exports.normalizeVenue = normalizeVenue;
|
|
386
458
|
exports.pointInPolygon = pointInPolygon;
|
|
387
459
|
exports.seatWorldPosition = seatWorldPosition;
|
|
388
460
|
exports.sectionAABB = sectionAABB;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/models/helpers.ts","../src/spatial/SpatialIndex.ts","../src/rendering/Viewport.ts","../src/rendering/LODLevel.ts","../src/rendering/SpriteAtlas.ts","../src/rendering/CategoryTextureCache.ts","../src/commands/CommandHistory.ts","../src/serialization/index.ts"],"names":["RBush","LODLevel","Graphics","RenderTexture"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AABB, Section, Seat, Vec2, Venue } from \"./types\";\n\nexport function seatWorldPosition(section: Section, seat: Seat): Vec2 {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n return {\n x: section.position.x + seat.position.x * cos - seat.position.y * sin,\n y: section.position.y + seat.position.x * sin + seat.position.y * cos,\n };\n}\n\nexport function sectionAABB(section: Section): AABB {\n const allPoints: Vec2[] = [];\n\n if (section.outline.length > 0) {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n for (const p of section.outline) {\n allPoints.push({\n x: section.position.x + p.x * cos - p.y * sin,\n y: section.position.y + p.x * sin + p.y * cos,\n });\n }\n }\n\n const allSeats = section.rows.flatMap((r) => r.seats);\n for (const seat of allSeats) {\n allPoints.push(seatWorldPosition(section, seat));\n }\n\n if (allPoints.length === 0) {\n return {\n minX: section.position.x,\n minY: section.position.y,\n maxX: section.position.x,\n maxY: section.position.y,\n };\n }\n\n const pad = 10;\n return {\n minX: Math.min(...allPoints.map((p) => p.x)) - pad,\n minY: Math.min(...allPoints.map((p) => p.y)) - pad,\n maxX: Math.max(...allPoints.map((p) => p.x)) + pad,\n maxY: Math.max(...allPoints.map((p) => p.y)) + pad,\n };\n}\n\nexport function venueAABB(venue: Venue): AABB {\n if (venue.sections.length === 0) {\n return { minX: 0, minY: 0, maxX: venue.bounds.width, maxY: venue.bounds.height };\n }\n const boxes = venue.sections.map(sectionAABB);\n return {\n minX: Math.min(...boxes.map((b) => b.minX)),\n minY: Math.min(...boxes.map((b) => b.minY)),\n maxX: Math.max(...boxes.map((b) => b.maxX)),\n maxY: Math.max(...boxes.map((b) => b.maxY)),\n };\n}\n\n/** Ray-casting point-in-polygon test. Works with any simple polygon. */\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n if (polygon.length < 3) return false;\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if ((yi > point.y) !== (yj > point.y) &&\n point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/** Clamp a point to the nearest position inside a polygon (with margin). */\nexport function clampToPolygon(point: Vec2, polygon: Vec2[], margin = 5): Vec2 {\n if (polygon.length < 3 || pointInPolygon(point, polygon)) return point;\n\n // Find the closest point on any polygon edge\n let bestX = point.x, bestY = point.y, bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx - margin * dy / Math.sqrt(len2);\n const cy = ay + t * dy + margin * dx / Math.sqrt(len2);\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n\n // Verify the clamped point is inside; if not just project onto edge without margin\n if (!pointInPolygon({ x: bestX, y: bestY }, polygon)) {\n bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx, cy = ay + t * dy;\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n }\n\n return { x: bestX, y: bestY };\n}\n\nlet _nextId = 1;\nexport function generateId(prefix = \"\"): string {\n return `${prefix}${prefix ? \"-\" : \"\"}${Date.now().toString(36)}-${(_nextId++).toString(36)}`;\n}\n","import RBush from \"rbush\";\nimport type { AABB, Section, Vec2 } from \"../models/types\";\nimport { seatWorldPosition, sectionAABB } from \"../models/helpers\";\n\nexport interface SpatialItem extends AABB {\n type: \"section\" | \"seat\";\n sectionId: string;\n seatId?: string;\n}\n\nexport class SpatialIndex {\n private tree = new RBush<SpatialItem>();\n private items: SpatialItem[] = [];\n\n buildFromSections(sections: Section[]): void {\n this.items = [];\n\n for (const section of sections) {\n const box = sectionAABB(section);\n this.items.push({\n ...box,\n type: \"section\",\n sectionId: section.id,\n });\n\n for (const row of section.rows) {\n for (const seat of row.seats) {\n const wp = seatWorldPosition(section, seat);\n const r = 8;\n this.items.push({\n minX: wp.x - r,\n minY: wp.y - r,\n maxX: wp.x + r,\n maxY: wp.y + r,\n type: \"seat\",\n sectionId: section.id,\n seatId: seat.id,\n });\n }\n }\n }\n\n this.tree.clear();\n this.tree.load(this.items);\n }\n\n queryViewport(viewport: AABB): SpatialItem[] {\n return this.tree.search(viewport);\n }\n\n queryPoint(point: Vec2, radius = 8): SpatialItem[] {\n return this.tree.search({\n minX: point.x - radius,\n minY: point.y - radius,\n maxX: point.x + radius,\n maxY: point.y + radius,\n });\n }\n\n queryRect(rect: AABB): SpatialItem[] {\n return this.tree.search(rect);\n }\n}\n","import type { AABB, Vec2 } from \"../models/types\";\n\nexport interface ViewportState {\n x: number;\n y: number;\n zoom: number;\n}\n\nconst MIN_ZOOM = 0.05;\nconst MAX_ZOOM = 4;\n\nexport class Viewport {\n x = 0;\n y = 0;\n zoom = 1;\n screenWidth = 0;\n screenHeight = 0;\n\n private listeners = new Set<() => void>();\n\n setScreenSize(width: number, height: number): void {\n this.screenWidth = width;\n this.screenHeight = height;\n this.notify();\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx / this.zoom;\n this.y += dy / this.zoom;\n this.notify();\n }\n\n zoomAt(screenPoint: Vec2, factor: number): void {\n const newZoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, this.zoom * factor));\n\n // 1) World coordinate currently under the cursor\n const wx = screenPoint.x / this.zoom - this.x;\n const wy = screenPoint.y / this.zoom - this.y;\n\n // 2) Solve for the offset that keeps that world point at the same screen position\n // screenPoint = (world + offset) * newZoom → offset = screenPoint / newZoom - world\n this.x = screenPoint.x / newZoom - wx;\n this.y = screenPoint.y / newZoom - wy;\n this.zoom = newZoom;\n this.notify();\n }\n\n setZoom(zoom: number): void {\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n this.notify();\n }\n\n fitBounds(aabb: AABB, padding = 40): void {\n const contentW = aabb.maxX - aabb.minX;\n const contentH = aabb.maxY - aabb.minY;\n if (contentW <= 0 || contentH <= 0) return;\n\n const scaleX = (this.screenWidth - padding * 2) / contentW;\n const scaleY = (this.screenHeight - padding * 2) / contentH;\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.min(scaleX, scaleY)));\n\n this.x = -(aabb.minX + contentW / 2) + this.screenWidth / (2 * this.zoom);\n this.y = -(aabb.minY + contentH / 2) + this.screenHeight / (2 * this.zoom);\n this.notify();\n }\n\n screenToWorld(screenX: number, screenY: number): Vec2 {\n return {\n x: screenX / this.zoom - this.x,\n y: screenY / this.zoom - this.y,\n };\n }\n\n worldToScreen(worldX: number, worldY: number): Vec2 {\n return {\n x: (worldX + this.x) * this.zoom,\n y: (worldY + this.y) * this.zoom,\n };\n }\n\n getVisibleAABB(): AABB {\n const topLeft = this.screenToWorld(0, 0);\n const bottomRight = this.screenToWorld(this.screenWidth, this.screenHeight);\n return {\n minX: topLeft.x,\n minY: topLeft.y,\n maxX: bottomRight.x,\n maxY: bottomRight.y,\n };\n }\n\n getState(): ViewportState {\n return { x: this.x, y: this.y, zoom: this.zoom };\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","export enum LODLevel {\n Overview = \"overview\",\n Section = \"section\",\n Detail = \"detail\",\n}\n\nconst SECTION_THRESHOLD = 0.3;\nconst DETAIL_THRESHOLD = 0.7;\n\nexport function getLODLevel(zoom: number): LODLevel {\n if (zoom < SECTION_THRESHOLD) return LODLevel.Overview;\n if (zoom < DETAIL_THRESHOLD) return LODLevel.Section;\n return LODLevel.Detail;\n}\n","import { Graphics, RenderTexture, type Renderer } from \"pixi.js\";\n\nexport interface SeatTextureSet {\n available: RenderTexture;\n held: RenderTexture;\n sold: RenderTexture;\n blocked: RenderTexture;\n selected: RenderTexture;\n hovered: RenderTexture;\n}\n\nconst STATUS_COLORS: Record<string, number> = {\n available: 0x4caf50,\n held: 0xff9800,\n sold: 0x9e9e9e,\n blocked: 0xf44336,\n selected: 0x2196f3,\n hovered: 0x64b5f6,\n};\n\nexport function createSeatTextures(\n renderer: Renderer,\n radius = 7,\n categoryColor?: number,\n textureResolution?: number,\n): SeatTextureSet {\n const result: Partial<SeatTextureSet> = {};\n const diameter = (radius + 4) * 2;\n const resolution = textureResolution ?? (4 * (typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1));\n\n for (const [status, color] of Object.entries(STATUS_COLORS)) {\n const g = new Graphics();\n const fillColor = status === \"available\" && categoryColor != null ? categoryColor : color;\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color: fillColor });\n\n if (status === \"selected\") {\n g.circle(radius + 4, radius + 4, radius + 2);\n g.stroke({ color: 0xffffff, width: 2 });\n }\n\n const texture = RenderTexture.create({ width: diameter, height: diameter, resolution });\n renderer.render({ container: g, target: texture });\n g.destroy();\n\n result[status as keyof SeatTextureSet] = texture;\n }\n\n return result as SeatTextureSet;\n}\n\nexport function destroySeatTextures(textures: SeatTextureSet): void {\n for (const tex of Object.values(textures)) {\n (tex as RenderTexture).destroy(true);\n }\n}\n","import type { Renderer } from \"pixi.js\";\nimport {\n createSeatTextures,\n destroySeatTextures,\n type SeatTextureSet,\n} from \"./SpriteAtlas\";\n\nexport class CategoryTextureCache {\n private cache = new Map<string, SeatTextureSet>();\n private defaultTextures: SeatTextureSet | null = null;\n\n create(renderer: Renderer, categories: { id: string; color: string }[], seatRadius = 7): void {\n this.destroy();\n this.defaultTextures = createSeatTextures(renderer, seatRadius);\n\n for (const cat of categories) {\n const color = parseInt(cat.color.replace(\"#\", \"\"), 16);\n this.cache.set(cat.id, createSeatTextures(renderer, seatRadius, color));\n }\n }\n\n get(categoryId: string): SeatTextureSet {\n return this.cache.get(categoryId) ?? this.defaultTextures!;\n }\n\n destroy(): void {\n for (const textures of this.cache.values()) {\n destroySeatTextures(textures);\n }\n if (this.defaultTextures) {\n destroySeatTextures(this.defaultTextures);\n }\n this.cache.clear();\n this.defaultTextures = null;\n }\n}\n","export interface Command {\n execute(): void;\n undo(): void;\n description: string;\n}\n\nexport class CommandHistory {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private listeners = new Set<() => void>();\n\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n this.redoStack = [];\n this.notify();\n }\n\n undo(): void {\n const command = this.undoStack.pop();\n if (!command) return;\n command.undo();\n this.redoStack.push(command);\n this.notify();\n }\n\n redo(): void {\n const command = this.redoStack.pop();\n if (!command) return;\n command.execute();\n this.undoStack.push(command);\n this.notify();\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notify();\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import type { Venue } from \"../models/types\";\n\nexport function serializeVenue(venue: Venue): string {\n return JSON.stringify(venue, null, 2);\n}\n\nexport function deserializeVenue(json: string): Venue {\n return JSON.parse(json) as Venue;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/models/helpers.ts","../src/spatial/SpatialIndex.ts","../src/rendering/Viewport.ts","../src/rendering/LODLevel.ts","../src/rendering/SpriteAtlas.ts","../src/rendering/CategoryTextureCache.ts","../src/commands/CommandHistory.ts","../src/serialization/index.ts"],"names":["uuidv7","RBush","LODLevel","Graphics"],"mappings":"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","file":"index.cjs","sourcesContent":["import { v7 as uuidv7 } from \"uuid\";\nimport type { AABB, Section, Seat, SeatStatusDefinition, Vec2, Venue } from \"./types\";\n\nexport const AVAILABLE_STATUS_ID = \"available\";\n\nexport const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[] = [\n { id: AVAILABLE_STATUS_ID, name: \"Available\", color: \"#4caf50\" },\n { id: \"locked\", name: \"Locked\", color: \"#f44336\" },\n { id: \"booked\", name: \"Booked\", color: \"#9e9e9e\" },\n];\n\nconst LEGACY_STATUS_MAP: Record<string, string> = {\n held: \"locked\",\n blocked: \"locked\",\n sold: \"booked\",\n};\n\nfunction normalizeStatusId(rawStatus: string, allowedStatuses: Set<string>): string {\n const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;\n if (allowedStatuses.has(mapped)) return mapped;\n return AVAILABLE_STATUS_ID;\n}\n\nexport function seatWorldPosition(section: Section, seat: Seat): Vec2 {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n return {\n x: section.position.x + seat.position.x * cos - seat.position.y * sin,\n y: section.position.y + seat.position.x * sin + seat.position.y * cos,\n };\n}\n\nexport function sectionAABB(section: Section): AABB {\n const allPoints: Vec2[] = [];\n\n if (section.outline.length > 0) {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n for (const p of section.outline) {\n allPoints.push({\n x: section.position.x + p.x * cos - p.y * sin,\n y: section.position.y + p.x * sin + p.y * cos,\n });\n }\n }\n\n const allSeats = section.rows.flatMap((r) => r.seats);\n for (const seat of allSeats) {\n allPoints.push(seatWorldPosition(section, seat));\n }\n\n if (allPoints.length === 0) {\n return {\n minX: section.position.x,\n minY: section.position.y,\n maxX: section.position.x,\n maxY: section.position.y,\n };\n }\n\n const pad = 10;\n return {\n minX: Math.min(...allPoints.map((p) => p.x)) - pad,\n minY: Math.min(...allPoints.map((p) => p.y)) - pad,\n maxX: Math.max(...allPoints.map((p) => p.x)) + pad,\n maxY: Math.max(...allPoints.map((p) => p.y)) + pad,\n };\n}\n\nexport function venueAABB(venue: Venue): AABB {\n if (venue.sections.length === 0) {\n return { minX: 0, minY: 0, maxX: venue.bounds.width, maxY: venue.bounds.height };\n }\n const boxes = venue.sections.map(sectionAABB);\n return {\n minX: Math.min(...boxes.map((b) => b.minX)),\n minY: Math.min(...boxes.map((b) => b.minY)),\n maxX: Math.max(...boxes.map((b) => b.maxX)),\n maxY: Math.max(...boxes.map((b) => b.maxY)),\n };\n}\n\n/** Ray-casting point-in-polygon test. Works with any simple polygon. */\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n if (polygon.length < 3) return false;\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if ((yi > point.y) !== (yj > point.y) &&\n point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/** Clamp a point to the nearest position inside a polygon (with margin). */\nexport function clampToPolygon(point: Vec2, polygon: Vec2[], margin = 5): Vec2 {\n if (polygon.length < 3 || pointInPolygon(point, polygon)) return point;\n\n // Find the closest point on any polygon edge\n let bestX = point.x, bestY = point.y, bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx - margin * dy / Math.sqrt(len2);\n const cy = ay + t * dy + margin * dx / Math.sqrt(len2);\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n\n // Verify the clamped point is inside; if not just project onto edge without margin\n if (!pointInPolygon({ x: bestX, y: bestY }, polygon)) {\n bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx, cy = ay + t * dy;\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n }\n\n return { x: bestX, y: bestY };\n}\n\nexport function normalizeVenue(venue: Venue): Venue {\n const seatStatuses =\n venue.seatStatuses && venue.seatStatuses.length > 0\n ? venue.seatStatuses\n : DEFAULT_SEAT_STATUSES;\n const clonedStatuses = seatStatuses.map((status) => ({ ...status }));\n const allowedStatuses = new Set(clonedStatuses.map((status) => status.id));\n const categories = venue.categories.map((category) => {\n const hasBackendPrice = Number.isFinite(category.backendPrice);\n const hasOverriddenPrice = Number.isFinite(category.overriddenPrice);\n return {\n ...category,\n backendPrice: hasBackendPrice ? category.backendPrice : undefined,\n overriddenPrice: hasOverriddenPrice ? category.overriddenPrice : undefined,\n isPriceOverridden:\n Boolean(category.isPriceOverridden) && hasOverriddenPrice,\n };\n });\n\n const sections = venue.sections.map((section) => ({\n ...section,\n rows: section.rows.map((row) => ({\n ...row,\n seats: row.seats.map((seat) => ({\n ...seat,\n status: normalizeStatusId(seat.status, allowedStatuses),\n })),\n })),\n }));\n\n const tables = venue.tables.map((table) => ({\n ...table,\n seats: table.seats.map((seat) => ({\n ...seat,\n status: normalizeStatusId(seat.status, allowedStatuses),\n })),\n }));\n\n return {\n ...venue,\n categories,\n seatStatuses: clonedStatuses,\n sections,\n tables,\n };\n}\n\nexport function generateId(prefix = \"\"): string {\n const id = uuidv7();\n return prefix ? `${prefix}-${id}` : id;\n}\n","import RBush from \"rbush\";\nimport type { AABB, Section, Vec2 } from \"../models/types\";\nimport { seatWorldPosition, sectionAABB } from \"../models/helpers\";\n\nexport interface SpatialItem extends AABB {\n type: \"section\" | \"seat\";\n sectionId: string;\n seatId?: string;\n}\n\nexport class SpatialIndex {\n private tree = new RBush<SpatialItem>();\n private items: SpatialItem[] = [];\n\n buildFromSections(sections: Section[]): void {\n this.items = [];\n\n for (const section of sections) {\n const box = sectionAABB(section);\n this.items.push({\n ...box,\n type: \"section\",\n sectionId: section.id,\n });\n\n for (const row of section.rows) {\n for (const seat of row.seats) {\n const wp = seatWorldPosition(section, seat);\n const r = 8;\n this.items.push({\n minX: wp.x - r,\n minY: wp.y - r,\n maxX: wp.x + r,\n maxY: wp.y + r,\n type: \"seat\",\n sectionId: section.id,\n seatId: seat.id,\n });\n }\n }\n }\n\n this.tree.clear();\n this.tree.load(this.items);\n }\n\n queryViewport(viewport: AABB): SpatialItem[] {\n return this.tree.search(viewport);\n }\n\n queryPoint(point: Vec2, radius = 8): SpatialItem[] {\n return this.tree.search({\n minX: point.x - radius,\n minY: point.y - radius,\n maxX: point.x + radius,\n maxY: point.y + radius,\n });\n }\n\n queryRect(rect: AABB): SpatialItem[] {\n return this.tree.search(rect);\n }\n}\n","import type { AABB, Vec2 } from \"../models/types\";\n\nexport interface ViewportState {\n x: number;\n y: number;\n zoom: number;\n}\n\nconst MIN_ZOOM = 0.05;\nconst MAX_ZOOM = 4;\n\nexport class Viewport {\n x = 0;\n y = 0;\n zoom = 1;\n screenWidth = 0;\n screenHeight = 0;\n\n private listeners = new Set<() => void>();\n\n setScreenSize(width: number, height: number): void {\n this.screenWidth = width;\n this.screenHeight = height;\n this.notify();\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx / this.zoom;\n this.y += dy / this.zoom;\n this.notify();\n }\n\n zoomAt(screenPoint: Vec2, factor: number): void {\n const newZoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, this.zoom * factor));\n\n // 1) World coordinate currently under the cursor\n const wx = screenPoint.x / this.zoom - this.x;\n const wy = screenPoint.y / this.zoom - this.y;\n\n // 2) Solve for the offset that keeps that world point at the same screen position\n // screenPoint = (world + offset) * newZoom → offset = screenPoint / newZoom - world\n this.x = screenPoint.x / newZoom - wx;\n this.y = screenPoint.y / newZoom - wy;\n this.zoom = newZoom;\n this.notify();\n }\n\n setZoom(zoom: number): void {\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n this.notify();\n }\n\n fitBounds(aabb: AABB, padding = 40): void {\n const contentW = aabb.maxX - aabb.minX;\n const contentH = aabb.maxY - aabb.minY;\n if (contentW <= 0 || contentH <= 0) return;\n\n const scaleX = (this.screenWidth - padding * 2) / contentW;\n const scaleY = (this.screenHeight - padding * 2) / contentH;\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.min(scaleX, scaleY)));\n\n this.x = -(aabb.minX + contentW / 2) + this.screenWidth / (2 * this.zoom);\n this.y = -(aabb.minY + contentH / 2) + this.screenHeight / (2 * this.zoom);\n this.notify();\n }\n\n screenToWorld(screenX: number, screenY: number): Vec2 {\n return {\n x: screenX / this.zoom - this.x,\n y: screenY / this.zoom - this.y,\n };\n }\n\n worldToScreen(worldX: number, worldY: number): Vec2 {\n return {\n x: (worldX + this.x) * this.zoom,\n y: (worldY + this.y) * this.zoom,\n };\n }\n\n getVisibleAABB(): AABB {\n const topLeft = this.screenToWorld(0, 0);\n const bottomRight = this.screenToWorld(this.screenWidth, this.screenHeight);\n return {\n minX: topLeft.x,\n minY: topLeft.y,\n maxX: bottomRight.x,\n maxY: bottomRight.y,\n };\n }\n\n getState(): ViewportState {\n return { x: this.x, y: this.y, zoom: this.zoom };\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","export enum LODLevel {\n Overview = \"overview\",\n Section = \"section\",\n Detail = \"detail\",\n}\n\nconst SECTION_THRESHOLD = 0.3;\nconst DETAIL_THRESHOLD = 0.7;\n\nexport function getLODLevel(zoom: number): LODLevel {\n if (zoom < SECTION_THRESHOLD) return LODLevel.Overview;\n if (zoom < DETAIL_THRESHOLD) return LODLevel.Section;\n return LODLevel.Detail;\n}\n","import { Graphics, type Texture, type Renderer } from \"pixi.js\";\nimport type { SeatStatusDefinition } from \"../models\";\n\nexport interface SeatTextureSet {\n [statusId: string]: Texture;\n selected: Texture;\n hovered: Texture;\n}\n\nconst UI_TEXTURE_COLORS: Record<string, number> = {\n selected: 0x2196f3,\n hovered: 0x64b5f6,\n};\n\nfunction parseHexColor(color: string): number {\n return parseInt(color.replace(\"#\", \"\"), 16);\n}\n\nexport function createSeatTextures(\n renderer: Renderer,\n seatStatuses: SeatStatusDefinition[],\n radius = 7,\n categoryColor?: number,\n textureResolution?: number,\n): SeatTextureSet {\n const result: Partial<SeatTextureSet> = {};\n const resolution = textureResolution ?? (4 * (typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1));\n\n for (const status of seatStatuses) {\n const g = new Graphics();\n const fillColor = status.id === \"available\" && categoryColor != null\n ? categoryColor\n : parseHexColor(status.color);\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color: fillColor });\n\n const texture = renderer.textureGenerator.generateTexture({\n target: g,\n resolution,\n antialias: true,\n });\n g.destroy();\n\n result[status.id] = texture;\n }\n\n for (const [statusId, color] of Object.entries(UI_TEXTURE_COLORS)) {\n const g = new Graphics();\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color });\n\n if (statusId === \"selected\") {\n g.circle(radius + 4, radius + 4, radius + 2);\n g.stroke({ color: 0xffffff, width: 2 });\n }\n\n const texture = renderer.textureGenerator.generateTexture({\n target: g,\n resolution,\n antialias: true,\n });\n g.destroy();\n\n result[statusId] = texture;\n }\n\n return result as SeatTextureSet;\n}\n\nexport function destroySeatTextures(textures: SeatTextureSet): void {\n for (const tex of Object.values(textures)) {\n tex.destroy(true);\n }\n}\n","import type { Renderer } from \"pixi.js\";\nimport type { SeatStatusDefinition } from \"../models\";\nimport {\n createSeatTextures,\n destroySeatTextures,\n type SeatTextureSet,\n} from \"./SpriteAtlas\";\n\nexport class CategoryTextureCache {\n private cache = new Map<string, SeatTextureSet>();\n private defaultTextures: SeatTextureSet | null = null;\n\n create(\n renderer: Renderer,\n categories: { id: string; color: string }[],\n seatStatuses: SeatStatusDefinition[],\n seatRadius = 7,\n ): void {\n this.destroy();\n this.defaultTextures = createSeatTextures(renderer, seatStatuses, seatRadius);\n\n for (const cat of categories) {\n const color = parseInt(cat.color.replace(\"#\", \"\"), 16);\n this.cache.set(cat.id, createSeatTextures(renderer, seatStatuses, seatRadius, color));\n }\n }\n\n get(categoryId: string): SeatTextureSet {\n return this.cache.get(categoryId) ?? this.defaultTextures!;\n }\n\n destroy(): void {\n for (const textures of this.cache.values()) {\n destroySeatTextures(textures);\n }\n if (this.defaultTextures) {\n destroySeatTextures(this.defaultTextures);\n }\n this.cache.clear();\n this.defaultTextures = null;\n }\n}\n","export interface Command {\n execute(): void;\n undo(): void;\n description: string;\n}\n\nexport class CommandHistory {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private listeners = new Set<() => void>();\n\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n this.redoStack = [];\n this.notify();\n }\n\n undo(): void {\n const command = this.undoStack.pop();\n if (!command) return;\n command.undo();\n this.redoStack.push(command);\n this.notify();\n }\n\n redo(): void {\n const command = this.redoStack.pop();\n if (!command) return;\n command.execute();\n this.undoStack.push(command);\n this.notify();\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notify();\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import type { Venue } from \"../models/types\";\nimport { normalizeVenue } from \"../models/helpers\";\n\nexport function serializeVenue(venue: Venue): string {\n return JSON.stringify(venue, null, 2);\n}\n\nexport function deserializeVenue(json: string): Venue {\n return normalizeVenue(JSON.parse(json) as Venue);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Texture, Renderer } from 'pixi.js';
|
|
2
2
|
|
|
3
3
|
interface Vec2 {
|
|
4
4
|
x: number;
|
|
@@ -14,11 +14,19 @@ interface AABB {
|
|
|
14
14
|
maxX: number;
|
|
15
15
|
maxY: number;
|
|
16
16
|
}
|
|
17
|
-
type SeatStatus =
|
|
17
|
+
type SeatStatus = string;
|
|
18
|
+
interface SeatStatusDefinition {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
color: string;
|
|
22
|
+
}
|
|
18
23
|
interface PricingCategory {
|
|
19
24
|
id: string;
|
|
20
25
|
name: string;
|
|
21
26
|
color: string;
|
|
27
|
+
backendPrice?: number;
|
|
28
|
+
isPriceOverridden?: boolean;
|
|
29
|
+
overriddenPrice?: number;
|
|
22
30
|
}
|
|
23
31
|
interface Seat {
|
|
24
32
|
id: string;
|
|
@@ -62,12 +70,21 @@ interface Venue {
|
|
|
62
70
|
bounds: Bounds;
|
|
63
71
|
backgroundImage?: string;
|
|
64
72
|
backgroundImageOpacity?: number;
|
|
73
|
+
backgroundImageWidth?: number;
|
|
74
|
+
backgroundImageHeight?: number;
|
|
75
|
+
backgroundImageX?: number;
|
|
76
|
+
backgroundImageY?: number;
|
|
77
|
+
backgroundImageAspectRatio?: number;
|
|
78
|
+
backgroundImageKeepAspectRatio?: boolean;
|
|
65
79
|
sections: Section[];
|
|
66
80
|
gaAreas: GeneralAdmissionArea[];
|
|
67
81
|
tables: Table[];
|
|
68
82
|
categories: PricingCategory[];
|
|
83
|
+
seatStatuses: SeatStatusDefinition[];
|
|
69
84
|
}
|
|
70
85
|
|
|
86
|
+
declare const AVAILABLE_STATUS_ID = "available";
|
|
87
|
+
declare const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[];
|
|
71
88
|
declare function seatWorldPosition(section: Section, seat: Seat): Vec2;
|
|
72
89
|
declare function sectionAABB(section: Section): AABB;
|
|
73
90
|
declare function venueAABB(venue: Venue): AABB;
|
|
@@ -75,6 +92,7 @@ declare function venueAABB(venue: Venue): AABB;
|
|
|
75
92
|
declare function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean;
|
|
76
93
|
/** Clamp a point to the nearest position inside a polygon (with margin). */
|
|
77
94
|
declare function clampToPolygon(point: Vec2, polygon: Vec2[], margin?: number): Vec2;
|
|
95
|
+
declare function normalizeVenue(venue: Venue): Venue;
|
|
78
96
|
declare function generateId(prefix?: string): string;
|
|
79
97
|
|
|
80
98
|
interface SpatialItem extends AABB {
|
|
@@ -124,14 +142,11 @@ declare enum LODLevel {
|
|
|
124
142
|
declare function getLODLevel(zoom: number): LODLevel;
|
|
125
143
|
|
|
126
144
|
interface SeatTextureSet {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
hovered: RenderTexture;
|
|
133
|
-
}
|
|
134
|
-
declare function createSeatTextures(renderer: Renderer, radius?: number, categoryColor?: number, textureResolution?: number): SeatTextureSet;
|
|
145
|
+
[statusId: string]: Texture;
|
|
146
|
+
selected: Texture;
|
|
147
|
+
hovered: Texture;
|
|
148
|
+
}
|
|
149
|
+
declare function createSeatTextures(renderer: Renderer, seatStatuses: SeatStatusDefinition[], radius?: number, categoryColor?: number, textureResolution?: number): SeatTextureSet;
|
|
135
150
|
declare function destroySeatTextures(textures: SeatTextureSet): void;
|
|
136
151
|
|
|
137
152
|
declare class CategoryTextureCache {
|
|
@@ -140,7 +155,7 @@ declare class CategoryTextureCache {
|
|
|
140
155
|
create(renderer: Renderer, categories: {
|
|
141
156
|
id: string;
|
|
142
157
|
color: string;
|
|
143
|
-
}[], seatRadius?: number): void;
|
|
158
|
+
}[], seatStatuses: SeatStatusDefinition[], seatRadius?: number): void;
|
|
144
159
|
get(categoryId: string): SeatTextureSet;
|
|
145
160
|
destroy(): void;
|
|
146
161
|
}
|
|
@@ -167,4 +182,4 @@ declare class CommandHistory {
|
|
|
167
182
|
declare function serializeVenue(venue: Venue): string;
|
|
168
183
|
declare function deserializeVenue(json: string): Venue;
|
|
169
184
|
|
|
170
|
-
export { type AABB, type Bounds, CategoryTextureCache, type Command, CommandHistory, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, type Seat, type SeatStatus, type SeatTextureSet, type Section, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
|
185
|
+
export { type AABB, AVAILABLE_STATUS_ID, type Bounds, CategoryTextureCache, type Command, CommandHistory, DEFAULT_SEAT_STATUSES, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, type Seat, type SeatStatus, type SeatStatusDefinition, type SeatTextureSet, type Section, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Texture, Renderer } from 'pixi.js';
|
|
2
2
|
|
|
3
3
|
interface Vec2 {
|
|
4
4
|
x: number;
|
|
@@ -14,11 +14,19 @@ interface AABB {
|
|
|
14
14
|
maxX: number;
|
|
15
15
|
maxY: number;
|
|
16
16
|
}
|
|
17
|
-
type SeatStatus =
|
|
17
|
+
type SeatStatus = string;
|
|
18
|
+
interface SeatStatusDefinition {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
color: string;
|
|
22
|
+
}
|
|
18
23
|
interface PricingCategory {
|
|
19
24
|
id: string;
|
|
20
25
|
name: string;
|
|
21
26
|
color: string;
|
|
27
|
+
backendPrice?: number;
|
|
28
|
+
isPriceOverridden?: boolean;
|
|
29
|
+
overriddenPrice?: number;
|
|
22
30
|
}
|
|
23
31
|
interface Seat {
|
|
24
32
|
id: string;
|
|
@@ -62,12 +70,21 @@ interface Venue {
|
|
|
62
70
|
bounds: Bounds;
|
|
63
71
|
backgroundImage?: string;
|
|
64
72
|
backgroundImageOpacity?: number;
|
|
73
|
+
backgroundImageWidth?: number;
|
|
74
|
+
backgroundImageHeight?: number;
|
|
75
|
+
backgroundImageX?: number;
|
|
76
|
+
backgroundImageY?: number;
|
|
77
|
+
backgroundImageAspectRatio?: number;
|
|
78
|
+
backgroundImageKeepAspectRatio?: boolean;
|
|
65
79
|
sections: Section[];
|
|
66
80
|
gaAreas: GeneralAdmissionArea[];
|
|
67
81
|
tables: Table[];
|
|
68
82
|
categories: PricingCategory[];
|
|
83
|
+
seatStatuses: SeatStatusDefinition[];
|
|
69
84
|
}
|
|
70
85
|
|
|
86
|
+
declare const AVAILABLE_STATUS_ID = "available";
|
|
87
|
+
declare const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[];
|
|
71
88
|
declare function seatWorldPosition(section: Section, seat: Seat): Vec2;
|
|
72
89
|
declare function sectionAABB(section: Section): AABB;
|
|
73
90
|
declare function venueAABB(venue: Venue): AABB;
|
|
@@ -75,6 +92,7 @@ declare function venueAABB(venue: Venue): AABB;
|
|
|
75
92
|
declare function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean;
|
|
76
93
|
/** Clamp a point to the nearest position inside a polygon (with margin). */
|
|
77
94
|
declare function clampToPolygon(point: Vec2, polygon: Vec2[], margin?: number): Vec2;
|
|
95
|
+
declare function normalizeVenue(venue: Venue): Venue;
|
|
78
96
|
declare function generateId(prefix?: string): string;
|
|
79
97
|
|
|
80
98
|
interface SpatialItem extends AABB {
|
|
@@ -124,14 +142,11 @@ declare enum LODLevel {
|
|
|
124
142
|
declare function getLODLevel(zoom: number): LODLevel;
|
|
125
143
|
|
|
126
144
|
interface SeatTextureSet {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
hovered: RenderTexture;
|
|
133
|
-
}
|
|
134
|
-
declare function createSeatTextures(renderer: Renderer, radius?: number, categoryColor?: number, textureResolution?: number): SeatTextureSet;
|
|
145
|
+
[statusId: string]: Texture;
|
|
146
|
+
selected: Texture;
|
|
147
|
+
hovered: Texture;
|
|
148
|
+
}
|
|
149
|
+
declare function createSeatTextures(renderer: Renderer, seatStatuses: SeatStatusDefinition[], radius?: number, categoryColor?: number, textureResolution?: number): SeatTextureSet;
|
|
135
150
|
declare function destroySeatTextures(textures: SeatTextureSet): void;
|
|
136
151
|
|
|
137
152
|
declare class CategoryTextureCache {
|
|
@@ -140,7 +155,7 @@ declare class CategoryTextureCache {
|
|
|
140
155
|
create(renderer: Renderer, categories: {
|
|
141
156
|
id: string;
|
|
142
157
|
color: string;
|
|
143
|
-
}[], seatRadius?: number): void;
|
|
158
|
+
}[], seatStatuses: SeatStatusDefinition[], seatRadius?: number): void;
|
|
144
159
|
get(categoryId: string): SeatTextureSet;
|
|
145
160
|
destroy(): void;
|
|
146
161
|
}
|
|
@@ -167,4 +182,4 @@ declare class CommandHistory {
|
|
|
167
182
|
declare function serializeVenue(venue: Venue): string;
|
|
168
183
|
declare function deserializeVenue(json: string): Venue;
|
|
169
184
|
|
|
170
|
-
export { type AABB, type Bounds, CategoryTextureCache, type Command, CommandHistory, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, type Seat, type SeatStatus, type SeatTextureSet, type Section, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
|
185
|
+
export { type AABB, AVAILABLE_STATUS_ID, type Bounds, CategoryTextureCache, type Command, CommandHistory, DEFAULT_SEAT_STATUSES, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, type Seat, type SeatStatus, type SeatStatusDefinition, type SeatTextureSet, type Section, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
|
+
import { v7 } from 'uuid';
|
|
1
2
|
import RBush from 'rbush';
|
|
2
|
-
import { Graphics
|
|
3
|
+
import { Graphics } from 'pixi.js';
|
|
3
4
|
|
|
4
5
|
// src/models/helpers.ts
|
|
6
|
+
var AVAILABLE_STATUS_ID = "available";
|
|
7
|
+
var DEFAULT_SEAT_STATUSES = [
|
|
8
|
+
{ id: AVAILABLE_STATUS_ID, name: "Available", color: "#4caf50" },
|
|
9
|
+
{ id: "locked", name: "Locked", color: "#f44336" },
|
|
10
|
+
{ id: "booked", name: "Booked", color: "#9e9e9e" }
|
|
11
|
+
];
|
|
12
|
+
var LEGACY_STATUS_MAP = {
|
|
13
|
+
held: "locked",
|
|
14
|
+
blocked: "locked",
|
|
15
|
+
sold: "booked"
|
|
16
|
+
};
|
|
17
|
+
function normalizeStatusId(rawStatus, allowedStatuses) {
|
|
18
|
+
const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;
|
|
19
|
+
if (allowedStatuses.has(mapped)) return mapped;
|
|
20
|
+
return AVAILABLE_STATUS_ID;
|
|
21
|
+
}
|
|
5
22
|
function seatWorldPosition(section, seat) {
|
|
6
23
|
const cos = Math.cos(section.rotation);
|
|
7
24
|
const sin = Math.sin(section.rotation);
|
|
@@ -105,9 +122,48 @@ function clampToPolygon(point, polygon, margin = 5) {
|
|
|
105
122
|
}
|
|
106
123
|
return { x: bestX, y: bestY };
|
|
107
124
|
}
|
|
108
|
-
|
|
125
|
+
function normalizeVenue(venue) {
|
|
126
|
+
const seatStatuses = venue.seatStatuses && venue.seatStatuses.length > 0 ? venue.seatStatuses : DEFAULT_SEAT_STATUSES;
|
|
127
|
+
const clonedStatuses = seatStatuses.map((status) => ({ ...status }));
|
|
128
|
+
const allowedStatuses = new Set(clonedStatuses.map((status) => status.id));
|
|
129
|
+
const categories = venue.categories.map((category) => {
|
|
130
|
+
const hasBackendPrice = Number.isFinite(category.backendPrice);
|
|
131
|
+
const hasOverriddenPrice = Number.isFinite(category.overriddenPrice);
|
|
132
|
+
return {
|
|
133
|
+
...category,
|
|
134
|
+
backendPrice: hasBackendPrice ? category.backendPrice : void 0,
|
|
135
|
+
overriddenPrice: hasOverriddenPrice ? category.overriddenPrice : void 0,
|
|
136
|
+
isPriceOverridden: Boolean(category.isPriceOverridden) && hasOverriddenPrice
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
const sections = venue.sections.map((section) => ({
|
|
140
|
+
...section,
|
|
141
|
+
rows: section.rows.map((row) => ({
|
|
142
|
+
...row,
|
|
143
|
+
seats: row.seats.map((seat) => ({
|
|
144
|
+
...seat,
|
|
145
|
+
status: normalizeStatusId(seat.status, allowedStatuses)
|
|
146
|
+
}))
|
|
147
|
+
}))
|
|
148
|
+
}));
|
|
149
|
+
const tables = venue.tables.map((table) => ({
|
|
150
|
+
...table,
|
|
151
|
+
seats: table.seats.map((seat) => ({
|
|
152
|
+
...seat,
|
|
153
|
+
status: normalizeStatusId(seat.status, allowedStatuses)
|
|
154
|
+
}))
|
|
155
|
+
}));
|
|
156
|
+
return {
|
|
157
|
+
...venue,
|
|
158
|
+
categories,
|
|
159
|
+
seatStatuses: clonedStatuses,
|
|
160
|
+
sections,
|
|
161
|
+
tables
|
|
162
|
+
};
|
|
163
|
+
}
|
|
109
164
|
function generateId(prefix = "") {
|
|
110
|
-
|
|
165
|
+
const id = v7();
|
|
166
|
+
return prefix ? `${prefix}-${id}` : id;
|
|
111
167
|
}
|
|
112
168
|
var SpatialIndex = class {
|
|
113
169
|
tree = new RBush();
|
|
@@ -250,31 +306,44 @@ function getLODLevel(zoom) {
|
|
|
250
306
|
if (zoom < DETAIL_THRESHOLD) return "section" /* Section */;
|
|
251
307
|
return "detail" /* Detail */;
|
|
252
308
|
}
|
|
253
|
-
var
|
|
254
|
-
available: 5025616,
|
|
255
|
-
held: 16750592,
|
|
256
|
-
sold: 10395294,
|
|
257
|
-
blocked: 16007990,
|
|
309
|
+
var UI_TEXTURE_COLORS = {
|
|
258
310
|
selected: 2201331,
|
|
259
311
|
hovered: 6600182
|
|
260
312
|
};
|
|
261
|
-
function
|
|
313
|
+
function parseHexColor(color) {
|
|
314
|
+
return parseInt(color.replace("#", ""), 16);
|
|
315
|
+
}
|
|
316
|
+
function createSeatTextures(renderer, seatStatuses, radius = 7, categoryColor, textureResolution) {
|
|
262
317
|
const result = {};
|
|
263
|
-
const diameter = (radius + 4) * 2;
|
|
264
318
|
const resolution = textureResolution ?? 4 * (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1);
|
|
265
|
-
for (const
|
|
319
|
+
for (const status of seatStatuses) {
|
|
266
320
|
const g = new Graphics();
|
|
267
|
-
const fillColor = status === "available" && categoryColor != null ? categoryColor : color;
|
|
321
|
+
const fillColor = status.id === "available" && categoryColor != null ? categoryColor : parseHexColor(status.color);
|
|
268
322
|
g.circle(radius + 4, radius + 4, radius);
|
|
269
323
|
g.fill({ color: fillColor });
|
|
270
|
-
|
|
324
|
+
const texture = renderer.textureGenerator.generateTexture({
|
|
325
|
+
target: g,
|
|
326
|
+
resolution,
|
|
327
|
+
antialias: true
|
|
328
|
+
});
|
|
329
|
+
g.destroy();
|
|
330
|
+
result[status.id] = texture;
|
|
331
|
+
}
|
|
332
|
+
for (const [statusId, color] of Object.entries(UI_TEXTURE_COLORS)) {
|
|
333
|
+
const g = new Graphics();
|
|
334
|
+
g.circle(radius + 4, radius + 4, radius);
|
|
335
|
+
g.fill({ color });
|
|
336
|
+
if (statusId === "selected") {
|
|
271
337
|
g.circle(radius + 4, radius + 4, radius + 2);
|
|
272
338
|
g.stroke({ color: 16777215, width: 2 });
|
|
273
339
|
}
|
|
274
|
-
const texture =
|
|
275
|
-
|
|
340
|
+
const texture = renderer.textureGenerator.generateTexture({
|
|
341
|
+
target: g,
|
|
342
|
+
resolution,
|
|
343
|
+
antialias: true
|
|
344
|
+
});
|
|
276
345
|
g.destroy();
|
|
277
|
-
result[
|
|
346
|
+
result[statusId] = texture;
|
|
278
347
|
}
|
|
279
348
|
return result;
|
|
280
349
|
}
|
|
@@ -288,12 +357,12 @@ function destroySeatTextures(textures) {
|
|
|
288
357
|
var CategoryTextureCache = class {
|
|
289
358
|
cache = /* @__PURE__ */ new Map();
|
|
290
359
|
defaultTextures = null;
|
|
291
|
-
create(renderer, categories, seatRadius = 7) {
|
|
360
|
+
create(renderer, categories, seatStatuses, seatRadius = 7) {
|
|
292
361
|
this.destroy();
|
|
293
|
-
this.defaultTextures = createSeatTextures(renderer, seatRadius);
|
|
362
|
+
this.defaultTextures = createSeatTextures(renderer, seatStatuses, seatRadius);
|
|
294
363
|
for (const cat of categories) {
|
|
295
364
|
const color = parseInt(cat.color.replace("#", ""), 16);
|
|
296
|
-
this.cache.set(cat.id, createSeatTextures(renderer, seatRadius, color));
|
|
365
|
+
this.cache.set(cat.id, createSeatTextures(renderer, seatStatuses, seatRadius, color));
|
|
297
366
|
}
|
|
298
367
|
}
|
|
299
368
|
get(categoryId) {
|
|
@@ -363,9 +432,9 @@ function serializeVenue(venue) {
|
|
|
363
432
|
return JSON.stringify(venue, null, 2);
|
|
364
433
|
}
|
|
365
434
|
function deserializeVenue(json) {
|
|
366
|
-
return JSON.parse(json);
|
|
435
|
+
return normalizeVenue(JSON.parse(json));
|
|
367
436
|
}
|
|
368
437
|
|
|
369
|
-
export { CategoryTextureCache, CommandHistory, LODLevel, SpatialIndex, Viewport, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
|
438
|
+
export { AVAILABLE_STATUS_ID, CategoryTextureCache, CommandHistory, DEFAULT_SEAT_STATUSES, LODLevel, SpatialIndex, Viewport, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
|
|
370
439
|
//# sourceMappingURL=index.js.map
|
|
371
440
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/models/helpers.ts","../src/spatial/SpatialIndex.ts","../src/rendering/Viewport.ts","../src/rendering/LODLevel.ts","../src/rendering/SpriteAtlas.ts","../src/rendering/CategoryTextureCache.ts","../src/commands/CommandHistory.ts","../src/serialization/index.ts"],"names":["LODLevel"],"mappings":"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","file":"index.js","sourcesContent":["import type { AABB, Section, Seat, Vec2, Venue } from \"./types\";\n\nexport function seatWorldPosition(section: Section, seat: Seat): Vec2 {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n return {\n x: section.position.x + seat.position.x * cos - seat.position.y * sin,\n y: section.position.y + seat.position.x * sin + seat.position.y * cos,\n };\n}\n\nexport function sectionAABB(section: Section): AABB {\n const allPoints: Vec2[] = [];\n\n if (section.outline.length > 0) {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n for (const p of section.outline) {\n allPoints.push({\n x: section.position.x + p.x * cos - p.y * sin,\n y: section.position.y + p.x * sin + p.y * cos,\n });\n }\n }\n\n const allSeats = section.rows.flatMap((r) => r.seats);\n for (const seat of allSeats) {\n allPoints.push(seatWorldPosition(section, seat));\n }\n\n if (allPoints.length === 0) {\n return {\n minX: section.position.x,\n minY: section.position.y,\n maxX: section.position.x,\n maxY: section.position.y,\n };\n }\n\n const pad = 10;\n return {\n minX: Math.min(...allPoints.map((p) => p.x)) - pad,\n minY: Math.min(...allPoints.map((p) => p.y)) - pad,\n maxX: Math.max(...allPoints.map((p) => p.x)) + pad,\n maxY: Math.max(...allPoints.map((p) => p.y)) + pad,\n };\n}\n\nexport function venueAABB(venue: Venue): AABB {\n if (venue.sections.length === 0) {\n return { minX: 0, minY: 0, maxX: venue.bounds.width, maxY: venue.bounds.height };\n }\n const boxes = venue.sections.map(sectionAABB);\n return {\n minX: Math.min(...boxes.map((b) => b.minX)),\n minY: Math.min(...boxes.map((b) => b.minY)),\n maxX: Math.max(...boxes.map((b) => b.maxX)),\n maxY: Math.max(...boxes.map((b) => b.maxY)),\n };\n}\n\n/** Ray-casting point-in-polygon test. Works with any simple polygon. */\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n if (polygon.length < 3) return false;\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if ((yi > point.y) !== (yj > point.y) &&\n point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/** Clamp a point to the nearest position inside a polygon (with margin). */\nexport function clampToPolygon(point: Vec2, polygon: Vec2[], margin = 5): Vec2 {\n if (polygon.length < 3 || pointInPolygon(point, polygon)) return point;\n\n // Find the closest point on any polygon edge\n let bestX = point.x, bestY = point.y, bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx - margin * dy / Math.sqrt(len2);\n const cy = ay + t * dy + margin * dx / Math.sqrt(len2);\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n\n // Verify the clamped point is inside; if not just project onto edge without margin\n if (!pointInPolygon({ x: bestX, y: bestY }, polygon)) {\n bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx, cy = ay + t * dy;\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n }\n\n return { x: bestX, y: bestY };\n}\n\nlet _nextId = 1;\nexport function generateId(prefix = \"\"): string {\n return `${prefix}${prefix ? \"-\" : \"\"}${Date.now().toString(36)}-${(_nextId++).toString(36)}`;\n}\n","import RBush from \"rbush\";\nimport type { AABB, Section, Vec2 } from \"../models/types\";\nimport { seatWorldPosition, sectionAABB } from \"../models/helpers\";\n\nexport interface SpatialItem extends AABB {\n type: \"section\" | \"seat\";\n sectionId: string;\n seatId?: string;\n}\n\nexport class SpatialIndex {\n private tree = new RBush<SpatialItem>();\n private items: SpatialItem[] = [];\n\n buildFromSections(sections: Section[]): void {\n this.items = [];\n\n for (const section of sections) {\n const box = sectionAABB(section);\n this.items.push({\n ...box,\n type: \"section\",\n sectionId: section.id,\n });\n\n for (const row of section.rows) {\n for (const seat of row.seats) {\n const wp = seatWorldPosition(section, seat);\n const r = 8;\n this.items.push({\n minX: wp.x - r,\n minY: wp.y - r,\n maxX: wp.x + r,\n maxY: wp.y + r,\n type: \"seat\",\n sectionId: section.id,\n seatId: seat.id,\n });\n }\n }\n }\n\n this.tree.clear();\n this.tree.load(this.items);\n }\n\n queryViewport(viewport: AABB): SpatialItem[] {\n return this.tree.search(viewport);\n }\n\n queryPoint(point: Vec2, radius = 8): SpatialItem[] {\n return this.tree.search({\n minX: point.x - radius,\n minY: point.y - radius,\n maxX: point.x + radius,\n maxY: point.y + radius,\n });\n }\n\n queryRect(rect: AABB): SpatialItem[] {\n return this.tree.search(rect);\n }\n}\n","import type { AABB, Vec2 } from \"../models/types\";\n\nexport interface ViewportState {\n x: number;\n y: number;\n zoom: number;\n}\n\nconst MIN_ZOOM = 0.05;\nconst MAX_ZOOM = 4;\n\nexport class Viewport {\n x = 0;\n y = 0;\n zoom = 1;\n screenWidth = 0;\n screenHeight = 0;\n\n private listeners = new Set<() => void>();\n\n setScreenSize(width: number, height: number): void {\n this.screenWidth = width;\n this.screenHeight = height;\n this.notify();\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx / this.zoom;\n this.y += dy / this.zoom;\n this.notify();\n }\n\n zoomAt(screenPoint: Vec2, factor: number): void {\n const newZoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, this.zoom * factor));\n\n // 1) World coordinate currently under the cursor\n const wx = screenPoint.x / this.zoom - this.x;\n const wy = screenPoint.y / this.zoom - this.y;\n\n // 2) Solve for the offset that keeps that world point at the same screen position\n // screenPoint = (world + offset) * newZoom → offset = screenPoint / newZoom - world\n this.x = screenPoint.x / newZoom - wx;\n this.y = screenPoint.y / newZoom - wy;\n this.zoom = newZoom;\n this.notify();\n }\n\n setZoom(zoom: number): void {\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n this.notify();\n }\n\n fitBounds(aabb: AABB, padding = 40): void {\n const contentW = aabb.maxX - aabb.minX;\n const contentH = aabb.maxY - aabb.minY;\n if (contentW <= 0 || contentH <= 0) return;\n\n const scaleX = (this.screenWidth - padding * 2) / contentW;\n const scaleY = (this.screenHeight - padding * 2) / contentH;\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.min(scaleX, scaleY)));\n\n this.x = -(aabb.minX + contentW / 2) + this.screenWidth / (2 * this.zoom);\n this.y = -(aabb.minY + contentH / 2) + this.screenHeight / (2 * this.zoom);\n this.notify();\n }\n\n screenToWorld(screenX: number, screenY: number): Vec2 {\n return {\n x: screenX / this.zoom - this.x,\n y: screenY / this.zoom - this.y,\n };\n }\n\n worldToScreen(worldX: number, worldY: number): Vec2 {\n return {\n x: (worldX + this.x) * this.zoom,\n y: (worldY + this.y) * this.zoom,\n };\n }\n\n getVisibleAABB(): AABB {\n const topLeft = this.screenToWorld(0, 0);\n const bottomRight = this.screenToWorld(this.screenWidth, this.screenHeight);\n return {\n minX: topLeft.x,\n minY: topLeft.y,\n maxX: bottomRight.x,\n maxY: bottomRight.y,\n };\n }\n\n getState(): ViewportState {\n return { x: this.x, y: this.y, zoom: this.zoom };\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","export enum LODLevel {\n Overview = \"overview\",\n Section = \"section\",\n Detail = \"detail\",\n}\n\nconst SECTION_THRESHOLD = 0.3;\nconst DETAIL_THRESHOLD = 0.7;\n\nexport function getLODLevel(zoom: number): LODLevel {\n if (zoom < SECTION_THRESHOLD) return LODLevel.Overview;\n if (zoom < DETAIL_THRESHOLD) return LODLevel.Section;\n return LODLevel.Detail;\n}\n","import { Graphics, RenderTexture, type Renderer } from \"pixi.js\";\n\nexport interface SeatTextureSet {\n available: RenderTexture;\n held: RenderTexture;\n sold: RenderTexture;\n blocked: RenderTexture;\n selected: RenderTexture;\n hovered: RenderTexture;\n}\n\nconst STATUS_COLORS: Record<string, number> = {\n available: 0x4caf50,\n held: 0xff9800,\n sold: 0x9e9e9e,\n blocked: 0xf44336,\n selected: 0x2196f3,\n hovered: 0x64b5f6,\n};\n\nexport function createSeatTextures(\n renderer: Renderer,\n radius = 7,\n categoryColor?: number,\n textureResolution?: number,\n): SeatTextureSet {\n const result: Partial<SeatTextureSet> = {};\n const diameter = (radius + 4) * 2;\n const resolution = textureResolution ?? (4 * (typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1));\n\n for (const [status, color] of Object.entries(STATUS_COLORS)) {\n const g = new Graphics();\n const fillColor = status === \"available\" && categoryColor != null ? categoryColor : color;\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color: fillColor });\n\n if (status === \"selected\") {\n g.circle(radius + 4, radius + 4, radius + 2);\n g.stroke({ color: 0xffffff, width: 2 });\n }\n\n const texture = RenderTexture.create({ width: diameter, height: diameter, resolution });\n renderer.render({ container: g, target: texture });\n g.destroy();\n\n result[status as keyof SeatTextureSet] = texture;\n }\n\n return result as SeatTextureSet;\n}\n\nexport function destroySeatTextures(textures: SeatTextureSet): void {\n for (const tex of Object.values(textures)) {\n (tex as RenderTexture).destroy(true);\n }\n}\n","import type { Renderer } from \"pixi.js\";\nimport {\n createSeatTextures,\n destroySeatTextures,\n type SeatTextureSet,\n} from \"./SpriteAtlas\";\n\nexport class CategoryTextureCache {\n private cache = new Map<string, SeatTextureSet>();\n private defaultTextures: SeatTextureSet | null = null;\n\n create(renderer: Renderer, categories: { id: string; color: string }[], seatRadius = 7): void {\n this.destroy();\n this.defaultTextures = createSeatTextures(renderer, seatRadius);\n\n for (const cat of categories) {\n const color = parseInt(cat.color.replace(\"#\", \"\"), 16);\n this.cache.set(cat.id, createSeatTextures(renderer, seatRadius, color));\n }\n }\n\n get(categoryId: string): SeatTextureSet {\n return this.cache.get(categoryId) ?? this.defaultTextures!;\n }\n\n destroy(): void {\n for (const textures of this.cache.values()) {\n destroySeatTextures(textures);\n }\n if (this.defaultTextures) {\n destroySeatTextures(this.defaultTextures);\n }\n this.cache.clear();\n this.defaultTextures = null;\n }\n}\n","export interface Command {\n execute(): void;\n undo(): void;\n description: string;\n}\n\nexport class CommandHistory {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private listeners = new Set<() => void>();\n\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n this.redoStack = [];\n this.notify();\n }\n\n undo(): void {\n const command = this.undoStack.pop();\n if (!command) return;\n command.undo();\n this.redoStack.push(command);\n this.notify();\n }\n\n redo(): void {\n const command = this.redoStack.pop();\n if (!command) return;\n command.execute();\n this.undoStack.push(command);\n this.notify();\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notify();\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import type { Venue } from \"../models/types\";\n\nexport function serializeVenue(venue: Venue): string {\n return JSON.stringify(venue, null, 2);\n}\n\nexport function deserializeVenue(json: string): Venue {\n return JSON.parse(json) as Venue;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/models/helpers.ts","../src/spatial/SpatialIndex.ts","../src/rendering/Viewport.ts","../src/rendering/LODLevel.ts","../src/rendering/SpriteAtlas.ts","../src/rendering/CategoryTextureCache.ts","../src/commands/CommandHistory.ts","../src/serialization/index.ts"],"names":["uuidv7","LODLevel"],"mappings":";;;;;AAGO,IAAM,mBAAA,GAAsB;AAE5B,IAAM,qBAAA,GAAgD;AAAA,EAC3D,EAAE,EAAA,EAAI,mBAAA,EAAqB,IAAA,EAAM,WAAA,EAAa,OAAO,SAAA,EAAU;AAAA,EAC/D,EAAE,EAAA,EAAI,QAAA,EAAU,IAAA,EAAM,QAAA,EAAU,OAAO,SAAA,EAAU;AAAA,EACjD,EAAE,EAAA,EAAI,QAAA,EAAU,IAAA,EAAM,QAAA,EAAU,OAAO,SAAA;AACzC;AAEA,IAAM,iBAAA,GAA4C;AAAA,EAChD,IAAA,EAAM,QAAA;AAAA,EACN,OAAA,EAAS,QAAA;AAAA,EACT,IAAA,EAAM;AACR,CAAA;AAEA,SAAS,iBAAA,CAAkB,WAAmB,eAAA,EAAsC;AAClF,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,SAAS,CAAA,IAAK,SAAA;AAC/C,EAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAA,EAAG,OAAO,MAAA;AACxC,EAAA,OAAO,mBAAA;AACT;AAEO,SAAS,iBAAA,CAAkB,SAAkB,IAAA,EAAkB;AACpE,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,QAAQ,CAAA;AACrC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,QAAQ,CAAA;AACrC,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,OAAA,CAAQ,QAAA,CAAS,CAAA,GAAI,IAAA,CAAK,SAAS,CAAA,GAAI,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,CAAA,GAAI,GAAA;AAAA,IAClE,CAAA,EAAG,OAAA,CAAQ,QAAA,CAAS,CAAA,GAAI,IAAA,CAAK,SAAS,CAAA,GAAI,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,CAAA,GAAI;AAAA,GACpE;AACF;AAEO,SAAS,YAAY,OAAA,EAAwB;AAClD,EAAA,MAAM,YAAoB,EAAC;AAE3B,EAAA,IAAI,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC9B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,QAAQ,CAAA;AACrC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,QAAQ,CAAA;AACrC,IAAA,KAAA,MAAW,CAAA,IAAK,QAAQ,OAAA,EAAS;AAC/B,MAAA,SAAA,CAAU,IAAA,CAAK;AAAA,QACb,CAAA,EAAG,QAAQ,QAAA,CAAS,CAAA,GAAI,EAAE,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,GAAI,GAAA;AAAA,QAC1C,CAAA,EAAG,QAAQ,QAAA,CAAS,CAAA,GAAI,EAAE,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,GAAI;AAAA,OAC3C,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,MAAM,WAAW,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AACpD,EAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,IAAA,SAAA,CAAU,IAAA,CAAK,iBAAA,CAAkB,OAAA,EAAS,IAAI,CAAC,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,QAAQ,QAAA,CAAS,CAAA;AAAA,MACvB,IAAA,EAAM,QAAQ,QAAA,CAAS,CAAA;AAAA,MACvB,IAAA,EAAM,QAAQ,QAAA,CAAS,CAAA;AAAA,MACvB,IAAA,EAAM,QAAQ,QAAA,CAAS;AAAA,KACzB;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,GAAM,EAAA;AACZ,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAA;AAAA,IAC/C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAA;AAAA,IAC/C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAA;AAAA,IAC/C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI;AAAA,GACjD;AACF;AAEO,SAAS,UAAU,KAAA,EAAoB;AAC5C,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AAC/B,IAAA,OAAO,EAAE,IAAA,EAAM,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,IAAA,EAAM,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO;AAAA,EACjF;AACA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,WAAW,CAAA;AAC5C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,IAC1C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,IAC1C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,IAC1C,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC;AAAA,GAC5C;AACF;AAGO,SAAS,cAAA,CAAe,OAAa,OAAA,EAA0B;AACpE,EAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAC/B,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,EAAQ,CAAA,GAAI,CAAA,EAAA,EAAK;AACnE,IAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,IAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,IAAA,IAAK,EAAA,GAAK,KAAA,CAAM,CAAA,KAAQ,EAAA,GAAK,MAAM,CAAA,IAC/B,KAAA,CAAM,CAAA,GAAA,CAAK,EAAA,GAAK,OAAO,KAAA,CAAM,CAAA,GAAI,EAAA,CAAA,IAAO,EAAA,GAAK,MAAM,EAAA,EAAI;AACzD,MAAA,MAAA,GAAS,CAAC,MAAA;AAAA,IACZ;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,cAAA,CAAe,KAAA,EAAa,OAAA,EAAiB,MAAA,GAAS,CAAA,EAAS;AAC7E,EAAA,IAAI,QAAQ,MAAA,GAAS,CAAA,IAAK,eAAe,KAAA,EAAO,OAAO,GAAG,OAAO,KAAA;AAGjE,EAAA,IAAI,QAAQ,KAAA,CAAM,CAAA,EAAG,KAAA,GAAQ,KAAA,CAAM,GAAG,QAAA,GAAW,QAAA;AACjD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,EAAQ,CAAA,GAAI,CAAA,EAAA,EAAK;AACnE,IAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,IAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,IAAA,MAAM,EAAA,GAAK,EAAA,GAAK,EAAA,EAAI,EAAA,GAAK,EAAA,GAAK,EAAA;AAC9B,IAAA,MAAM,IAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAC5B,IAAA,IAAI,SAAS,CAAA,EAAG;AAChB,IAAA,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAA,CAAA,CAAK,KAAA,CAAM,CAAA,GAAI,EAAA,IAAM,MAAM,KAAA,CAAM,CAAA,GAAI,EAAA,IAAM,EAAA,IAAM,IAAI,CAAC,CAAA;AACrF,IAAA,MAAM,EAAA,GAAK,KAAK,CAAA,GAAI,EAAA,GAAK,SAAS,EAAA,GAAK,IAAA,CAAK,KAAK,IAAI,CAAA;AACrD,IAAA,MAAM,EAAA,GAAK,KAAK,CAAA,GAAI,EAAA,GAAK,SAAS,EAAA,GAAK,IAAA,CAAK,KAAK,IAAI,CAAA;AACrD,IAAA,MAAM,CAAA,GAAI,KAAK,KAAA,CAAM,KAAA,CAAM,IAAI,EAAA,EAAI,KAAA,CAAM,IAAI,EAAE,CAAA;AAC/C,IAAA,IAAI,IAAI,QAAA,EAAU;AAAE,MAAA,QAAA,GAAW,CAAA;AAAG,MAAA,KAAA,GAAQ,EAAA;AAAI,MAAA,KAAA,GAAQ,EAAA;AAAA,IAAI;AAAA,EAC5D;AAGA,EAAA,IAAI,CAAC,eAAe,EAAE,CAAA,EAAG,OAAO,CAAA,EAAG,KAAA,EAAM,EAAG,OAAO,CAAA,EAAG;AACpD,IAAA,QAAA,GAAW,QAAA;AACX,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,EAAQ,CAAA,GAAI,CAAA,EAAA,EAAK;AACnE,MAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,MAAA,MAAM,EAAA,GAAK,QAAQ,CAAC,CAAA,CAAE,GAAG,EAAA,GAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,CAAA;AACzC,MAAA,MAAM,EAAA,GAAK,EAAA,GAAK,EAAA,EAAI,EAAA,GAAK,EAAA,GAAK,EAAA;AAC9B,MAAA,MAAM,IAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAC5B,MAAA,IAAI,SAAS,CAAA,EAAG;AAChB,MAAA,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAA,CAAA,CAAK,KAAA,CAAM,CAAA,GAAI,EAAA,IAAM,MAAM,KAAA,CAAM,CAAA,GAAI,EAAA,IAAM,EAAA,IAAM,IAAI,CAAC,CAAA;AACrF,MAAA,MAAM,KAAK,EAAA,GAAK,CAAA,GAAI,EAAA,EAAI,EAAA,GAAK,KAAK,CAAA,GAAI,EAAA;AACtC,MAAA,MAAM,CAAA,GAAI,KAAK,KAAA,CAAM,KAAA,CAAM,IAAI,EAAA,EAAI,KAAA,CAAM,IAAI,EAAE,CAAA;AAC/C,MAAA,IAAI,IAAI,QAAA,EAAU;AAAE,QAAA,QAAA,GAAW,CAAA;AAAG,QAAA,KAAA,GAAQ,EAAA;AAAI,QAAA,KAAA,GAAQ,EAAA;AAAA,MAAI;AAAA,IAC5D;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,KAAA,EAAM;AAC9B;AAEO,SAAS,eAAe,KAAA,EAAqB;AAClD,EAAA,MAAM,YAAA,GACJ,MAAM,YAAA,IAAgB,KAAA,CAAM,aAAa,MAAA,GAAS,CAAA,GAC9C,MAAM,YAAA,GACN,qBAAA;AACN,EAAA,MAAM,cAAA,GAAiB,aAAa,GAAA,CAAI,CAAC,YAAY,EAAE,GAAG,QAAO,CAAE,CAAA;AACnE,EAAA,MAAM,eAAA,GAAkB,IAAI,GAAA,CAAI,cAAA,CAAe,IAAI,CAAC,MAAA,KAAW,MAAA,CAAO,EAAE,CAAC,CAAA;AACzE,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,CAAC,QAAA,KAAa;AACpD,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,QAAA,CAAS,QAAA,CAAS,YAAY,CAAA;AAC7D,IAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,QAAA,CAAS,QAAA,CAAS,eAAe,CAAA;AACnE,IAAA,OAAO;AAAA,MACL,GAAG,QAAA;AAAA,MACH,YAAA,EAAc,eAAA,GAAkB,QAAA,CAAS,YAAA,GAAe,MAAA;AAAA,MACxD,eAAA,EAAiB,kBAAA,GAAqB,QAAA,CAAS,eAAA,GAAkB,MAAA;AAAA,MACjE,iBAAA,EACE,OAAA,CAAQ,QAAA,CAAS,iBAAiB,CAAA,IAAK;AAAA,KAC3C;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,IAChD,GAAG,OAAA;AAAA,IACH,IAAA,EAAM,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC/B,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,QAC9B,GAAG,IAAA;AAAA,QACH,MAAA,EAAQ,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,eAAe;AAAA,OACxD,CAAE;AAAA,KACJ,CAAE;AAAA,GACJ,CAAE,CAAA;AAEF,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IAC1C,GAAG,KAAA;AAAA,IACH,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,MAChC,GAAG,IAAA;AAAA,MACH,MAAA,EAAQ,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,eAAe;AAAA,KACxD,CAAE;AAAA,GACJ,CAAE,CAAA;AAEF,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,UAAA;AAAA,IACA,YAAA,EAAc,cAAA;AAAA,IACd,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,SAAS,UAAA,CAAW,SAAS,EAAA,EAAY;AAC9C,EAAA,MAAM,KAAKA,EAAA,EAAO;AAClB,EAAA,OAAO,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,EAAA;AACtC;AC/KO,IAAM,eAAN,MAAmB;AAAA,EAChB,IAAA,GAAO,IAAI,KAAA,EAAmB;AAAA,EAC9B,QAAuB,EAAC;AAAA,EAEhC,kBAAkB,QAAA,EAA2B;AAC3C,IAAA,IAAA,CAAK,QAAQ,EAAC;AAEd,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,GAAA,GAAM,YAAY,OAAO,CAAA;AAC/B,MAAA,IAAA,CAAK,MAAM,IAAA,CAAK;AAAA,QACd,GAAG,GAAA;AAAA,QACH,IAAA,EAAM,SAAA;AAAA,QACN,WAAW,OAAA,CAAQ;AAAA,OACpB,CAAA;AAED,MAAA,KAAA,MAAW,GAAA,IAAO,QAAQ,IAAA,EAAM;AAC9B,QAAA,KAAA,MAAW,IAAA,IAAQ,IAAI,KAAA,EAAO;AAC5B,UAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,OAAA,EAAS,IAAI,CAAA;AAC1C,UAAA,MAAM,CAAA,GAAI,CAAA;AACV,UAAA,IAAA,CAAK,MAAM,IAAA,CAAK;AAAA,YACd,IAAA,EAAM,GAAG,CAAA,GAAI,CAAA;AAAA,YACb,IAAA,EAAM,GAAG,CAAA,GAAI,CAAA;AAAA,YACb,IAAA,EAAM,GAAG,CAAA,GAAI,CAAA;AAAA,YACb,IAAA,EAAM,GAAG,CAAA,GAAI,CAAA;AAAA,YACb,IAAA,EAAM,MAAA;AAAA,YACN,WAAW,OAAA,CAAQ,EAAA;AAAA,YACnB,QAAQ,IAAA,CAAK;AAAA,WACd,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,KAAK,KAAA,EAAM;AAChB,IAAA,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,KAAK,CAAA;AAAA,EAC3B;AAAA,EAEA,cAAc,QAAA,EAA+B;AAC3C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AAAA,EAClC;AAAA,EAEA,UAAA,CAAW,KAAA,EAAa,MAAA,GAAS,CAAA,EAAkB;AACjD,IAAA,OAAO,IAAA,CAAK,KAAK,MAAA,CAAO;AAAA,MACtB,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAAA,MAChB,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAAA,MAChB,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAAA,MAChB,IAAA,EAAM,MAAM,CAAA,GAAI;AAAA,KACjB,CAAA;AAAA,EACH;AAAA,EAEA,UAAU,IAAA,EAA2B;AACnC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAAA,EAC9B;AACF;;;ACtDA,IAAM,QAAA,GAAW,IAAA;AACjB,IAAM,QAAA,GAAW,CAAA;AAEV,IAAM,WAAN,MAAe;AAAA,EACpB,CAAA,GAAI,CAAA;AAAA,EACJ,CAAA,GAAI,CAAA;AAAA,EACJ,IAAA,GAAO,CAAA;AAAA,EACP,WAAA,GAAc,CAAA;AAAA,EACd,YAAA,GAAe,CAAA;AAAA,EAEP,SAAA,uBAAgB,GAAA,EAAgB;AAAA,EAExC,aAAA,CAAc,OAAe,MAAA,EAAsB;AACjD,IAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AACnB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AACpB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,GAAA,CAAI,IAAY,EAAA,EAAkB;AAChC,IAAA,IAAA,CAAK,CAAA,IAAK,KAAK,IAAA,CAAK,IAAA;AACpB,IAAA,IAAA,CAAK,CAAA,IAAK,KAAK,IAAA,CAAK,IAAA;AACpB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,MAAA,CAAO,aAAmB,MAAA,EAAsB;AAC9C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,IAAI,QAAA,EAAU,IAAA,CAAK,IAAA,GAAO,MAAM,CAAC,CAAA;AAGzE,IAAA,MAAM,EAAA,GAAK,WAAA,CAAY,CAAA,GAAI,IAAA,CAAK,OAAO,IAAA,CAAK,CAAA;AAC5C,IAAA,MAAM,EAAA,GAAK,WAAA,CAAY,CAAA,GAAI,IAAA,CAAK,OAAO,IAAA,CAAK,CAAA;AAI5C,IAAA,IAAA,CAAK,CAAA,GAAI,WAAA,CAAY,CAAA,GAAI,OAAA,GAAU,EAAA;AACnC,IAAA,IAAA,CAAK,CAAA,GAAI,WAAA,CAAY,CAAA,GAAI,OAAA,GAAU,EAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA;AACZ,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,QAAQ,IAAA,EAAoB;AAC1B,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,GAAA,CAAI,QAAA,EAAU,KAAK,GAAA,CAAI,QAAA,EAAU,IAAI,CAAC,CAAA;AACvD,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,SAAA,CAAU,IAAA,EAAY,OAAA,GAAU,EAAA,EAAU;AACxC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA;AAClC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA;AAClC,IAAA,IAAI,QAAA,IAAY,CAAA,IAAK,QAAA,IAAY,CAAA,EAAG;AAEpC,IAAA,MAAM,MAAA,GAAA,CAAU,IAAA,CAAK,WAAA,GAAc,OAAA,GAAU,CAAA,IAAK,QAAA;AAClD,IAAA,MAAM,MAAA,GAAA,CAAU,IAAA,CAAK,YAAA,GAAe,OAAA,GAAU,CAAA,IAAK,QAAA;AACnD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAC,CAAC,CAAA;AAE3E,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,IAAA,CAAK,IAAA,GAAO,WAAW,CAAA,CAAA,GAAK,IAAA,CAAK,WAAA,IAAe,CAAA,GAAI,IAAA,CAAK,IAAA,CAAA;AACpE,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,IAAA,CAAK,IAAA,GAAO,WAAW,CAAA,CAAA,GAAK,IAAA,CAAK,YAAA,IAAgB,CAAA,GAAI,IAAA,CAAK,IAAA,CAAA;AACrE,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,aAAA,CAAc,SAAiB,OAAA,EAAuB;AACpD,IAAA,OAAO;AAAA,MACL,CAAA,EAAG,OAAA,GAAU,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,CAAA;AAAA,MAC9B,CAAA,EAAG,OAAA,GAAU,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK;AAAA,KAChC;AAAA,EACF;AAAA,EAEA,aAAA,CAAc,QAAgB,MAAA,EAAsB;AAClD,IAAA,OAAO;AAAA,MACL,CAAA,EAAA,CAAI,MAAA,GAAS,IAAA,CAAK,CAAA,IAAK,IAAA,CAAK,IAAA;AAAA,MAC5B,CAAA,EAAA,CAAI,MAAA,GAAS,IAAA,CAAK,CAAA,IAAK,IAAA,CAAK;AAAA,KAC9B;AAAA,EACF;AAAA,EAEA,cAAA,GAAuB;AACrB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,aAAA,CAAc,CAAA,EAAG,CAAC,CAAA;AACvC,IAAA,MAAM,cAAc,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,WAAA,EAAa,KAAK,YAAY,CAAA;AAC1E,IAAA,OAAO;AAAA,MACL,MAAM,OAAA,CAAQ,CAAA;AAAA,MACd,MAAM,OAAA,CAAQ,CAAA;AAAA,MACd,MAAM,WAAA,CAAY,CAAA;AAAA,MAClB,MAAM,WAAA,CAAY;AAAA,KACpB;AAAA,EACF;AAAA,EAEA,QAAA,GAA0B;AACxB,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,CAAA,EAAG,GAAG,IAAA,CAAK,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,IAAA,EAAK;AAAA,EACjD;AAAA,EAEA,UAAU,QAAA,EAAkC;AAC1C,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC3B,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,EAC7C;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,SAAA,EAAW;AACrC,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACzGO,IAAK,QAAA,qBAAAC,SAAAA,KAAL;AACL,EAAAA,UAAA,UAAA,CAAA,GAAW,UAAA;AACX,EAAAA,UAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,UAAA,QAAA,CAAA,GAAS,QAAA;AAHC,EAAA,OAAAA,SAAAA;AAAA,CAAA,EAAA,QAAA,IAAA,EAAA;AAMZ,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,gBAAA,GAAmB,GAAA;AAElB,SAAS,YAAY,IAAA,EAAwB;AAClD,EAAA,IAAI,IAAA,GAAO,mBAAmB,OAAO,UAAA;AACrC,EAAA,IAAI,IAAA,GAAO,kBAAkB,OAAO,SAAA;AACpC,EAAA,OAAO,QAAA;AACT;ACJA,IAAM,iBAAA,GAA4C;AAAA,EAChD,QAAA,EAAU,OAAA;AAAA,EACV,OAAA,EAAS;AACX,CAAA;AAEA,SAAS,cAAc,KAAA,EAAuB;AAC5C,EAAA,OAAO,SAAS,KAAA,CAAM,OAAA,CAAQ,GAAA,EAAK,EAAE,GAAG,EAAE,CAAA;AAC5C;AAEO,SAAS,mBACd,QAAA,EACA,YAAA,EACA,MAAA,GAAS,CAAA,EACT,eACA,iBAAA,EACgB;AAChB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,MAAM,UAAA,GAAa,qBAAsB,CAAA,IAAK,OAAO,WAAW,WAAA,GAAc,MAAA,CAAO,oBAAoB,CAAA,GAAI,CAAA,CAAA;AAE7G,EAAA,KAAA,MAAW,UAAU,YAAA,EAAc;AACjC,IAAA,MAAM,CAAA,GAAI,IAAI,QAAA,EAAS;AACvB,IAAA,MAAM,SAAA,GAAY,OAAO,EAAA,KAAO,WAAA,IAAe,iBAAiB,IAAA,GAC5D,aAAA,GACA,aAAA,CAAc,MAAA,CAAO,KAAK,CAAA;AAC9B,IAAA,CAAA,CAAE,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,GAAG,MAAM,CAAA;AACvC,IAAA,CAAA,CAAE,IAAA,CAAK,EAAE,KAAA,EAAO,SAAA,EAAW,CAAA;AAE3B,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,gBAAA,CAAiB,eAAA,CAAgB;AAAA,MACxD,MAAA,EAAQ,CAAA;AAAA,MACR,UAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACZ,CAAA;AACD,IAAA,CAAA,CAAE,OAAA,EAAQ;AAEV,IAAA,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA,GAAI,OAAA;AAAA,EACtB;AAEA,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,iBAAiB,CAAA,EAAG;AACjE,IAAA,MAAM,CAAA,GAAI,IAAI,QAAA,EAAS;AACvB,IAAA,CAAA,CAAE,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,GAAG,MAAM,CAAA;AACvC,IAAA,CAAA,CAAE,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA;AAEhB,IAAA,IAAI,aAAa,UAAA,EAAY;AAC3B,MAAA,CAAA,CAAE,OAAO,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,CAAA,EAAG,SAAS,CAAC,CAAA;AAC3C,MAAA,CAAA,CAAE,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,GAAG,CAAA;AAAA,IACxC;AAEA,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,gBAAA,CAAiB,eAAA,CAAgB;AAAA,MACxD,MAAA,EAAQ,CAAA;AAAA,MACR,UAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACZ,CAAA;AACD,IAAA,CAAA,CAAE,OAAA,EAAQ;AAEV,IAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,OAAA;AAAA,EACrB;AAEA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,oBAAoB,QAAA,EAAgC;AAClE,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA,EAAG;AACzC,IAAA,GAAA,CAAI,QAAQ,IAAI,CAAA;AAAA,EAClB;AACF;;;ACjEO,IAAM,uBAAN,MAA2B;AAAA,EACxB,KAAA,uBAAY,GAAA,EAA4B;AAAA,EACxC,eAAA,GAAyC,IAAA;AAAA,EAEjD,MAAA,CACE,QAAA,EACA,UAAA,EACA,YAAA,EACA,aAAa,CAAA,EACP;AACN,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,IAAA,CAAK,eAAA,GAAkB,kBAAA,CAAmB,QAAA,EAAU,YAAA,EAAc,UAAU,CAAA;AAE5E,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,MAAM,KAAA,GAAQ,SAAS,GAAA,CAAI,KAAA,CAAM,QAAQ,GAAA,EAAK,EAAE,GAAG,EAAE,CAAA;AACrD,MAAA,IAAA,CAAK,KAAA,CAAM,IAAI,GAAA,CAAI,EAAA,EAAI,mBAAmB,QAAA,EAAU,YAAA,EAAc,UAAA,EAAY,KAAK,CAAC,CAAA;AAAA,IACtF;AAAA,EACF;AAAA,EAEA,IAAI,UAAA,EAAoC;AACtC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,KAAK,IAAA,CAAK,eAAA;AAAA,EAC5C;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,KAAA,CAAM,MAAA,EAAO,EAAG;AAC1C,MAAA,mBAAA,CAAoB,QAAQ,CAAA;AAAA,IAC9B;AACA,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,mBAAA,CAAoB,KAAK,eAAe,CAAA;AAAA,IAC1C;AACA,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,EACzB;AACF;;;ACnCO,IAAM,iBAAN,MAAqB;AAAA,EAClB,YAAuB,EAAC;AAAA,EACxB,YAAuB,EAAC;AAAA,EACxB,SAAA,uBAAgB,GAAA,EAAgB;AAAA,EAExC,QAAQ,OAAA,EAAwB;AAC9B,IAAA,OAAA,CAAQ,OAAA,EAAQ;AAChB,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,OAAO,CAAA;AAC3B,IAAA,IAAA,CAAK,YAAY,EAAC;AAClB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,IAAA,GAAa;AACX,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,GAAA,EAAI;AACnC,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,IAAA,EAAK;AACb,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,OAAO,CAAA;AAC3B,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,IAAA,GAAa;AACX,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,GAAA,EAAI;AACnC,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,OAAA,EAAQ;AAChB,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,OAAO,CAAA;AAC3B,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,IAAI,OAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA;AAAA,EACjC;AAAA,EAEA,IAAI,OAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA;AAAA,EACjC;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,YAAY,EAAC;AAClB,IAAA,IAAA,CAAK,YAAY,EAAC;AAClB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEA,UAAU,QAAA,EAAkC;AAC1C,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC3B,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,EAC7C;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,SAAA,EAAW;AACrC,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACvDO,SAAS,eAAe,KAAA,EAAsB;AACnD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,CAAC,CAAA;AACtC;AAEO,SAAS,iBAAiB,IAAA,EAAqB;AACpD,EAAA,OAAO,cAAA,CAAe,IAAA,CAAK,KAAA,CAAM,IAAI,CAAU,CAAA;AACjD","file":"index.js","sourcesContent":["import { v7 as uuidv7 } from \"uuid\";\nimport type { AABB, Section, Seat, SeatStatusDefinition, Vec2, Venue } from \"./types\";\n\nexport const AVAILABLE_STATUS_ID = \"available\";\n\nexport const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[] = [\n { id: AVAILABLE_STATUS_ID, name: \"Available\", color: \"#4caf50\" },\n { id: \"locked\", name: \"Locked\", color: \"#f44336\" },\n { id: \"booked\", name: \"Booked\", color: \"#9e9e9e\" },\n];\n\nconst LEGACY_STATUS_MAP: Record<string, string> = {\n held: \"locked\",\n blocked: \"locked\",\n sold: \"booked\",\n};\n\nfunction normalizeStatusId(rawStatus: string, allowedStatuses: Set<string>): string {\n const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;\n if (allowedStatuses.has(mapped)) return mapped;\n return AVAILABLE_STATUS_ID;\n}\n\nexport function seatWorldPosition(section: Section, seat: Seat): Vec2 {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n return {\n x: section.position.x + seat.position.x * cos - seat.position.y * sin,\n y: section.position.y + seat.position.x * sin + seat.position.y * cos,\n };\n}\n\nexport function sectionAABB(section: Section): AABB {\n const allPoints: Vec2[] = [];\n\n if (section.outline.length > 0) {\n const cos = Math.cos(section.rotation);\n const sin = Math.sin(section.rotation);\n for (const p of section.outline) {\n allPoints.push({\n x: section.position.x + p.x * cos - p.y * sin,\n y: section.position.y + p.x * sin + p.y * cos,\n });\n }\n }\n\n const allSeats = section.rows.flatMap((r) => r.seats);\n for (const seat of allSeats) {\n allPoints.push(seatWorldPosition(section, seat));\n }\n\n if (allPoints.length === 0) {\n return {\n minX: section.position.x,\n minY: section.position.y,\n maxX: section.position.x,\n maxY: section.position.y,\n };\n }\n\n const pad = 10;\n return {\n minX: Math.min(...allPoints.map((p) => p.x)) - pad,\n minY: Math.min(...allPoints.map((p) => p.y)) - pad,\n maxX: Math.max(...allPoints.map((p) => p.x)) + pad,\n maxY: Math.max(...allPoints.map((p) => p.y)) + pad,\n };\n}\n\nexport function venueAABB(venue: Venue): AABB {\n if (venue.sections.length === 0) {\n return { minX: 0, minY: 0, maxX: venue.bounds.width, maxY: venue.bounds.height };\n }\n const boxes = venue.sections.map(sectionAABB);\n return {\n minX: Math.min(...boxes.map((b) => b.minX)),\n minY: Math.min(...boxes.map((b) => b.minY)),\n maxX: Math.max(...boxes.map((b) => b.maxX)),\n maxY: Math.max(...boxes.map((b) => b.maxY)),\n };\n}\n\n/** Ray-casting point-in-polygon test. Works with any simple polygon. */\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n if (polygon.length < 3) return false;\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if ((yi > point.y) !== (yj > point.y) &&\n point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/** Clamp a point to the nearest position inside a polygon (with margin). */\nexport function clampToPolygon(point: Vec2, polygon: Vec2[], margin = 5): Vec2 {\n if (polygon.length < 3 || pointInPolygon(point, polygon)) return point;\n\n // Find the closest point on any polygon edge\n let bestX = point.x, bestY = point.y, bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx - margin * dy / Math.sqrt(len2);\n const cy = ay + t * dy + margin * dx / Math.sqrt(len2);\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n\n // Verify the clamped point is inside; if not just project onto edge without margin\n if (!pointInPolygon({ x: bestX, y: bestY }, polygon)) {\n bestDist = Infinity;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const ax = polygon[j].x, ay = polygon[j].y;\n const bx = polygon[i].x, by = polygon[i].y;\n const dx = bx - ax, dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) continue;\n const t = Math.max(0, Math.min(1, ((point.x - ax) * dx + (point.y - ay) * dy) / len2));\n const cx = ax + t * dx, cy = ay + t * dy;\n const d = Math.hypot(point.x - cx, point.y - cy);\n if (d < bestDist) { bestDist = d; bestX = cx; bestY = cy; }\n }\n }\n\n return { x: bestX, y: bestY };\n}\n\nexport function normalizeVenue(venue: Venue): Venue {\n const seatStatuses =\n venue.seatStatuses && venue.seatStatuses.length > 0\n ? venue.seatStatuses\n : DEFAULT_SEAT_STATUSES;\n const clonedStatuses = seatStatuses.map((status) => ({ ...status }));\n const allowedStatuses = new Set(clonedStatuses.map((status) => status.id));\n const categories = venue.categories.map((category) => {\n const hasBackendPrice = Number.isFinite(category.backendPrice);\n const hasOverriddenPrice = Number.isFinite(category.overriddenPrice);\n return {\n ...category,\n backendPrice: hasBackendPrice ? category.backendPrice : undefined,\n overriddenPrice: hasOverriddenPrice ? category.overriddenPrice : undefined,\n isPriceOverridden:\n Boolean(category.isPriceOverridden) && hasOverriddenPrice,\n };\n });\n\n const sections = venue.sections.map((section) => ({\n ...section,\n rows: section.rows.map((row) => ({\n ...row,\n seats: row.seats.map((seat) => ({\n ...seat,\n status: normalizeStatusId(seat.status, allowedStatuses),\n })),\n })),\n }));\n\n const tables = venue.tables.map((table) => ({\n ...table,\n seats: table.seats.map((seat) => ({\n ...seat,\n status: normalizeStatusId(seat.status, allowedStatuses),\n })),\n }));\n\n return {\n ...venue,\n categories,\n seatStatuses: clonedStatuses,\n sections,\n tables,\n };\n}\n\nexport function generateId(prefix = \"\"): string {\n const id = uuidv7();\n return prefix ? `${prefix}-${id}` : id;\n}\n","import RBush from \"rbush\";\nimport type { AABB, Section, Vec2 } from \"../models/types\";\nimport { seatWorldPosition, sectionAABB } from \"../models/helpers\";\n\nexport interface SpatialItem extends AABB {\n type: \"section\" | \"seat\";\n sectionId: string;\n seatId?: string;\n}\n\nexport class SpatialIndex {\n private tree = new RBush<SpatialItem>();\n private items: SpatialItem[] = [];\n\n buildFromSections(sections: Section[]): void {\n this.items = [];\n\n for (const section of sections) {\n const box = sectionAABB(section);\n this.items.push({\n ...box,\n type: \"section\",\n sectionId: section.id,\n });\n\n for (const row of section.rows) {\n for (const seat of row.seats) {\n const wp = seatWorldPosition(section, seat);\n const r = 8;\n this.items.push({\n minX: wp.x - r,\n minY: wp.y - r,\n maxX: wp.x + r,\n maxY: wp.y + r,\n type: \"seat\",\n sectionId: section.id,\n seatId: seat.id,\n });\n }\n }\n }\n\n this.tree.clear();\n this.tree.load(this.items);\n }\n\n queryViewport(viewport: AABB): SpatialItem[] {\n return this.tree.search(viewport);\n }\n\n queryPoint(point: Vec2, radius = 8): SpatialItem[] {\n return this.tree.search({\n minX: point.x - radius,\n minY: point.y - radius,\n maxX: point.x + radius,\n maxY: point.y + radius,\n });\n }\n\n queryRect(rect: AABB): SpatialItem[] {\n return this.tree.search(rect);\n }\n}\n","import type { AABB, Vec2 } from \"../models/types\";\n\nexport interface ViewportState {\n x: number;\n y: number;\n zoom: number;\n}\n\nconst MIN_ZOOM = 0.05;\nconst MAX_ZOOM = 4;\n\nexport class Viewport {\n x = 0;\n y = 0;\n zoom = 1;\n screenWidth = 0;\n screenHeight = 0;\n\n private listeners = new Set<() => void>();\n\n setScreenSize(width: number, height: number): void {\n this.screenWidth = width;\n this.screenHeight = height;\n this.notify();\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx / this.zoom;\n this.y += dy / this.zoom;\n this.notify();\n }\n\n zoomAt(screenPoint: Vec2, factor: number): void {\n const newZoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, this.zoom * factor));\n\n // 1) World coordinate currently under the cursor\n const wx = screenPoint.x / this.zoom - this.x;\n const wy = screenPoint.y / this.zoom - this.y;\n\n // 2) Solve for the offset that keeps that world point at the same screen position\n // screenPoint = (world + offset) * newZoom → offset = screenPoint / newZoom - world\n this.x = screenPoint.x / newZoom - wx;\n this.y = screenPoint.y / newZoom - wy;\n this.zoom = newZoom;\n this.notify();\n }\n\n setZoom(zoom: number): void {\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n this.notify();\n }\n\n fitBounds(aabb: AABB, padding = 40): void {\n const contentW = aabb.maxX - aabb.minX;\n const contentH = aabb.maxY - aabb.minY;\n if (contentW <= 0 || contentH <= 0) return;\n\n const scaleX = (this.screenWidth - padding * 2) / contentW;\n const scaleY = (this.screenHeight - padding * 2) / contentH;\n this.zoom = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.min(scaleX, scaleY)));\n\n this.x = -(aabb.minX + contentW / 2) + this.screenWidth / (2 * this.zoom);\n this.y = -(aabb.minY + contentH / 2) + this.screenHeight / (2 * this.zoom);\n this.notify();\n }\n\n screenToWorld(screenX: number, screenY: number): Vec2 {\n return {\n x: screenX / this.zoom - this.x,\n y: screenY / this.zoom - this.y,\n };\n }\n\n worldToScreen(worldX: number, worldY: number): Vec2 {\n return {\n x: (worldX + this.x) * this.zoom,\n y: (worldY + this.y) * this.zoom,\n };\n }\n\n getVisibleAABB(): AABB {\n const topLeft = this.screenToWorld(0, 0);\n const bottomRight = this.screenToWorld(this.screenWidth, this.screenHeight);\n return {\n minX: topLeft.x,\n minY: topLeft.y,\n maxX: bottomRight.x,\n maxY: bottomRight.y,\n };\n }\n\n getState(): ViewportState {\n return { x: this.x, y: this.y, zoom: this.zoom };\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","export enum LODLevel {\n Overview = \"overview\",\n Section = \"section\",\n Detail = \"detail\",\n}\n\nconst SECTION_THRESHOLD = 0.3;\nconst DETAIL_THRESHOLD = 0.7;\n\nexport function getLODLevel(zoom: number): LODLevel {\n if (zoom < SECTION_THRESHOLD) return LODLevel.Overview;\n if (zoom < DETAIL_THRESHOLD) return LODLevel.Section;\n return LODLevel.Detail;\n}\n","import { Graphics, type Texture, type Renderer } from \"pixi.js\";\nimport type { SeatStatusDefinition } from \"../models\";\n\nexport interface SeatTextureSet {\n [statusId: string]: Texture;\n selected: Texture;\n hovered: Texture;\n}\n\nconst UI_TEXTURE_COLORS: Record<string, number> = {\n selected: 0x2196f3,\n hovered: 0x64b5f6,\n};\n\nfunction parseHexColor(color: string): number {\n return parseInt(color.replace(\"#\", \"\"), 16);\n}\n\nexport function createSeatTextures(\n renderer: Renderer,\n seatStatuses: SeatStatusDefinition[],\n radius = 7,\n categoryColor?: number,\n textureResolution?: number,\n): SeatTextureSet {\n const result: Partial<SeatTextureSet> = {};\n const resolution = textureResolution ?? (4 * (typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1));\n\n for (const status of seatStatuses) {\n const g = new Graphics();\n const fillColor = status.id === \"available\" && categoryColor != null\n ? categoryColor\n : parseHexColor(status.color);\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color: fillColor });\n\n const texture = renderer.textureGenerator.generateTexture({\n target: g,\n resolution,\n antialias: true,\n });\n g.destroy();\n\n result[status.id] = texture;\n }\n\n for (const [statusId, color] of Object.entries(UI_TEXTURE_COLORS)) {\n const g = new Graphics();\n g.circle(radius + 4, radius + 4, radius);\n g.fill({ color });\n\n if (statusId === \"selected\") {\n g.circle(radius + 4, radius + 4, radius + 2);\n g.stroke({ color: 0xffffff, width: 2 });\n }\n\n const texture = renderer.textureGenerator.generateTexture({\n target: g,\n resolution,\n antialias: true,\n });\n g.destroy();\n\n result[statusId] = texture;\n }\n\n return result as SeatTextureSet;\n}\n\nexport function destroySeatTextures(textures: SeatTextureSet): void {\n for (const tex of Object.values(textures)) {\n tex.destroy(true);\n }\n}\n","import type { Renderer } from \"pixi.js\";\nimport type { SeatStatusDefinition } from \"../models\";\nimport {\n createSeatTextures,\n destroySeatTextures,\n type SeatTextureSet,\n} from \"./SpriteAtlas\";\n\nexport class CategoryTextureCache {\n private cache = new Map<string, SeatTextureSet>();\n private defaultTextures: SeatTextureSet | null = null;\n\n create(\n renderer: Renderer,\n categories: { id: string; color: string }[],\n seatStatuses: SeatStatusDefinition[],\n seatRadius = 7,\n ): void {\n this.destroy();\n this.defaultTextures = createSeatTextures(renderer, seatStatuses, seatRadius);\n\n for (const cat of categories) {\n const color = parseInt(cat.color.replace(\"#\", \"\"), 16);\n this.cache.set(cat.id, createSeatTextures(renderer, seatStatuses, seatRadius, color));\n }\n }\n\n get(categoryId: string): SeatTextureSet {\n return this.cache.get(categoryId) ?? this.defaultTextures!;\n }\n\n destroy(): void {\n for (const textures of this.cache.values()) {\n destroySeatTextures(textures);\n }\n if (this.defaultTextures) {\n destroySeatTextures(this.defaultTextures);\n }\n this.cache.clear();\n this.defaultTextures = null;\n }\n}\n","export interface Command {\n execute(): void;\n undo(): void;\n description: string;\n}\n\nexport class CommandHistory {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private listeners = new Set<() => void>();\n\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n this.redoStack = [];\n this.notify();\n }\n\n undo(): void {\n const command = this.undoStack.pop();\n if (!command) return;\n command.undo();\n this.redoStack.push(command);\n this.notify();\n }\n\n redo(): void {\n const command = this.redoStack.pop();\n if (!command) return;\n command.execute();\n this.undoStack.push(command);\n this.notify();\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notify();\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import type { Venue } from \"../models/types\";\nimport { normalizeVenue } from \"../models/helpers\";\n\nexport function serializeVenue(venue: Venue): string {\n return JSON.stringify(venue, null, 2);\n}\n\nexport function deserializeVenue(json: string): Venue {\n return normalizeVenue(JSON.parse(json) as Venue);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nex125/seatmap-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/rbush": "^4.0.0",
|
|
30
30
|
"pixi.js": "^8",
|
|
31
|
-
"tsup": "^8",
|
|
32
|
-
"typescript": "
|
|
31
|
+
"tsup": "^8.4.0",
|
|
32
|
+
"typescript": "~5.9.3"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"rbush": "^4.0.1"
|
|
35
|
+
"rbush": "^4.0.1",
|
|
36
|
+
"uuid": "^13.0.0"
|
|
36
37
|
}
|
|
37
38
|
}
|