@nex125/seatmap-core 0.1.9 → 0.1.13

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 CHANGED
@@ -10,6 +10,22 @@ var RBush__default = /*#__PURE__*/_interopDefault(RBush);
10
10
 
11
11
  // src/models/helpers.ts
12
12
  var AVAILABLE_STATUS_ID = "available";
13
+ var STAGE_SECTION_KIND = "stage";
14
+ var DANCEFLOOR_SECTION_KIND = "dancefloor";
15
+ function isStageSection(section) {
16
+ return section.kind === STAGE_SECTION_KIND;
17
+ }
18
+ function isDancefloorSection(section) {
19
+ return section.kind === DANCEFLOOR_SECTION_KIND;
20
+ }
21
+ function getSectionSeatCount(section) {
22
+ return section.rows.reduce((count, row) => count + row.seats.length, 0);
23
+ }
24
+ function isAreaSeatSection(section) {
25
+ if (isDancefloorSection(section)) return true;
26
+ if (isStageSection(section)) return false;
27
+ return section.outline.length >= 3 && getSectionSeatCount(section) === 1;
28
+ }
13
29
  var DEFAULT_SEAT_STATUSES = [
14
30
  { id: AVAILABLE_STATUS_ID, name: "Available", color: "#4caf50" },
15
31
  { id: "locked", name: "Locked", color: "#f44336" },
@@ -21,7 +37,8 @@ var LEGACY_STATUS_MAP = {
21
37
  sold: "booked"
22
38
  };
23
39
  function normalizeStatusId(rawStatus, allowedStatuses) {
24
- const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;
40
+ const lower = rawStatus.toLowerCase();
41
+ const mapped = LEGACY_STATUS_MAP[lower] ?? lower;
25
42
  if (allowedStatuses.has(mapped)) return mapped;
26
43
  return AVAILABLE_STATUS_ID;
27
44
  }
@@ -144,6 +161,8 @@ function normalizeVenue(venue) {
144
161
  });
145
162
  const sections = venue.sections.map((section) => ({
146
163
  ...section,
164
+ kind: section.kind === STAGE_SECTION_KIND ? "stage" : section.kind === DANCEFLOOR_SECTION_KIND ? "dancefloor" : "section",
165
+ categoryId: section.kind === STAGE_SECTION_KIND ? "" : section.categoryId,
147
166
  rows: section.rows.map((row) => ({
148
167
  ...row,
149
168
  seats: row.seats.map((seat) => ({
@@ -186,12 +205,13 @@ var SpatialIndex = class {
186
205
  for (const row of section.rows) {
187
206
  for (const seat of row.seats) {
188
207
  const wp = seatWorldPosition(section, seat);
208
+ const dancefloorBounds = isAreaSeatSection(section) ? getSectionOutlineWorldBounds(section) : null;
189
209
  const r = 8;
190
210
  this.items.push({
191
- minX: wp.x - r,
192
- minY: wp.y - r,
193
- maxX: wp.x + r,
194
- maxY: wp.y + r,
211
+ minX: dancefloorBounds?.minX ?? wp.x - r,
212
+ minY: dancefloorBounds?.minY ?? wp.y - r,
213
+ maxX: dancefloorBounds?.maxX ?? wp.x + r,
214
+ maxY: dancefloorBounds?.maxY ?? wp.y + r,
195
215
  type: "seat",
196
216
  sectionId: section.id,
197
217
  seatId: seat.id
@@ -217,6 +237,21 @@ var SpatialIndex = class {
217
237
  return this.tree.search(rect);
218
238
  }
219
239
  };
240
+ function getSectionOutlineWorldBounds(section) {
241
+ if (section.outline.length < 3) return null;
242
+ const c = Math.cos(section.rotation);
243
+ const s = Math.sin(section.rotation);
244
+ const worldPoints = section.outline.map((point) => ({
245
+ x: section.position.x + point.x * c - point.y * s,
246
+ y: section.position.y + point.x * s + point.y * c
247
+ }));
248
+ return {
249
+ minX: Math.min(...worldPoints.map((point) => point.x)),
250
+ minY: Math.min(...worldPoints.map((point) => point.y)),
251
+ maxX: Math.max(...worldPoints.map((point) => point.x)),
252
+ maxY: Math.max(...worldPoints.map((point) => point.y))
253
+ };
254
+ }
220
255
 
221
256
  // src/rendering/Viewport.ts
222
257
  var MIN_ZOOM = 0.05;
@@ -444,8 +479,10 @@ function deserializeVenue(json) {
444
479
  exports.AVAILABLE_STATUS_ID = AVAILABLE_STATUS_ID;
445
480
  exports.CategoryTextureCache = CategoryTextureCache;
446
481
  exports.CommandHistory = CommandHistory;
482
+ exports.DANCEFLOOR_SECTION_KIND = DANCEFLOOR_SECTION_KIND;
447
483
  exports.DEFAULT_SEAT_STATUSES = DEFAULT_SEAT_STATUSES;
448
484
  exports.LODLevel = LODLevel;
485
+ exports.STAGE_SECTION_KIND = STAGE_SECTION_KIND;
449
486
  exports.SpatialIndex = SpatialIndex;
450
487
  exports.Viewport = Viewport;
451
488
  exports.clampToPolygon = clampToPolygon;
@@ -454,6 +491,9 @@ exports.deserializeVenue = deserializeVenue;
454
491
  exports.destroySeatTextures = destroySeatTextures;
455
492
  exports.generateId = generateId;
456
493
  exports.getLODLevel = getLODLevel;
494
+ exports.isAreaSeatSection = isAreaSeatSection;
495
+ exports.isDancefloorSection = isDancefloorSection;
496
+ exports.isStageSection = isStageSection;
457
497
  exports.normalizeVenue = normalizeVenue;
458
498
  exports.pointInPolygon = pointInPolygon;
459
499
  exports.seatWorldPosition = seatWorldPosition;
@@ -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":["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"]}
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\";\nexport const STAGE_SECTION_KIND = \"stage\";\nexport const DANCEFLOOR_SECTION_KIND = \"dancefloor\";\n\nexport function isStageSection(section: Section): boolean {\n return section.kind === STAGE_SECTION_KIND;\n}\n\nexport function isDancefloorSection(section: Section): boolean {\n return section.kind === DANCEFLOOR_SECTION_KIND;\n}\n\nfunction getSectionSeatCount(section: Section): number {\n return section.rows.reduce((count, row) => count + row.seats.length, 0);\n}\n\n/**\n * Area-seat sections should use the whole outline for rendering/hit testing.\n * This includes explicit dancefloors and legacy single-seat outlined sections.\n */\nexport function isAreaSeatSection(section: Section): boolean {\n if (isDancefloorSection(section)) return true;\n if (isStageSection(section)) return false;\n return section.outline.length >= 3 && getSectionSeatCount(section) === 1;\n}\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 lower = rawStatus.toLowerCase();\n const mapped = LEGACY_STATUS_MAP[lower] ?? lower;\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: Section[] = venue.sections.map((section): Section => ({\n ...section,\n kind:\n section.kind === STAGE_SECTION_KIND\n ? \"stage\"\n : section.kind === DANCEFLOOR_SECTION_KIND\n ? \"dancefloor\"\n : \"section\",\n categoryId: section.kind === STAGE_SECTION_KIND ? \"\" : section.categoryId,\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 { isAreaSeatSection, 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 dancefloorBounds =\n isAreaSeatSection(section)\n ? getSectionOutlineWorldBounds(section)\n : null;\n const r = 8;\n this.items.push({\n minX: dancefloorBounds?.minX ?? wp.x - r,\n minY: dancefloorBounds?.minY ?? wp.y - r,\n maxX: dancefloorBounds?.maxX ?? wp.x + r,\n maxY: dancefloorBounds?.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\nfunction getSectionOutlineWorldBounds(section: Section): AABB | null {\n if (section.outline.length < 3) return null;\n const c = Math.cos(section.rotation);\n const s = Math.sin(section.rotation);\n const worldPoints = section.outline.map((point) => ({\n x: section.position.x + point.x * c - point.y * s,\n y: section.position.y + point.x * s + point.y * c,\n }));\n return {\n minX: Math.min(...worldPoints.map((point) => point.x)),\n minY: Math.min(...worldPoints.map((point) => point.y)),\n maxX: Math.max(...worldPoints.map((point) => point.x)),\n maxY: Math.max(...worldPoints.map((point) => point.y)),\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
@@ -40,9 +40,11 @@ interface Row {
40
40
  label: string;
41
41
  seats: Seat[];
42
42
  }
43
+ type SectionKind = "section" | "stage" | "dancefloor";
43
44
  interface Section {
44
45
  id: string;
45
46
  label: string;
47
+ kind?: SectionKind;
46
48
  position: Vec2;
47
49
  rotation: number;
48
50
  categoryId: string;
@@ -84,6 +86,15 @@ interface Venue {
84
86
  }
85
87
 
86
88
  declare const AVAILABLE_STATUS_ID = "available";
89
+ declare const STAGE_SECTION_KIND = "stage";
90
+ declare const DANCEFLOOR_SECTION_KIND = "dancefloor";
91
+ declare function isStageSection(section: Section): boolean;
92
+ declare function isDancefloorSection(section: Section): boolean;
93
+ /**
94
+ * Area-seat sections should use the whole outline for rendering/hit testing.
95
+ * This includes explicit dancefloors and legacy single-seat outlined sections.
96
+ */
97
+ declare function isAreaSeatSection(section: Section): boolean;
87
98
  declare const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[];
88
99
  declare function seatWorldPosition(section: Section, seat: Seat): Vec2;
89
100
  declare function sectionAABB(section: Section): AABB;
@@ -182,4 +193,4 @@ declare class CommandHistory {
182
193
  declare function serializeVenue(venue: Venue): string;
183
194
  declare function deserializeVenue(json: string): Venue;
184
195
 
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 };
196
+ export { type AABB, AVAILABLE_STATUS_ID, type Bounds, CategoryTextureCache, type Command, CommandHistory, DANCEFLOOR_SECTION_KIND, DEFAULT_SEAT_STATUSES, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, STAGE_SECTION_KIND, type Seat, type SeatStatus, type SeatStatusDefinition, type SeatTextureSet, type Section, type SectionKind, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, isAreaSeatSection, isDancefloorSection, isStageSection, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
package/dist/index.d.ts CHANGED
@@ -40,9 +40,11 @@ interface Row {
40
40
  label: string;
41
41
  seats: Seat[];
42
42
  }
43
+ type SectionKind = "section" | "stage" | "dancefloor";
43
44
  interface Section {
44
45
  id: string;
45
46
  label: string;
47
+ kind?: SectionKind;
46
48
  position: Vec2;
47
49
  rotation: number;
48
50
  categoryId: string;
@@ -84,6 +86,15 @@ interface Venue {
84
86
  }
85
87
 
86
88
  declare const AVAILABLE_STATUS_ID = "available";
89
+ declare const STAGE_SECTION_KIND = "stage";
90
+ declare const DANCEFLOOR_SECTION_KIND = "dancefloor";
91
+ declare function isStageSection(section: Section): boolean;
92
+ declare function isDancefloorSection(section: Section): boolean;
93
+ /**
94
+ * Area-seat sections should use the whole outline for rendering/hit testing.
95
+ * This includes explicit dancefloors and legacy single-seat outlined sections.
96
+ */
97
+ declare function isAreaSeatSection(section: Section): boolean;
87
98
  declare const DEFAULT_SEAT_STATUSES: SeatStatusDefinition[];
88
99
  declare function seatWorldPosition(section: Section, seat: Seat): Vec2;
89
100
  declare function sectionAABB(section: Section): AABB;
@@ -182,4 +193,4 @@ declare class CommandHistory {
182
193
  declare function serializeVenue(venue: Venue): string;
183
194
  declare function deserializeVenue(json: string): Venue;
184
195
 
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 };
196
+ export { type AABB, AVAILABLE_STATUS_ID, type Bounds, CategoryTextureCache, type Command, CommandHistory, DANCEFLOOR_SECTION_KIND, DEFAULT_SEAT_STATUSES, type GeneralAdmissionArea, LODLevel, type PricingCategory, type Row, STAGE_SECTION_KIND, type Seat, type SeatStatus, type SeatStatusDefinition, type SeatTextureSet, type Section, type SectionKind, SpatialIndex, type SpatialItem, type Table, type Vec2, type Venue, Viewport, type ViewportState, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, isAreaSeatSection, isDancefloorSection, isStageSection, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
package/dist/index.js CHANGED
@@ -4,6 +4,22 @@ import { Graphics } from 'pixi.js';
4
4
 
5
5
  // src/models/helpers.ts
6
6
  var AVAILABLE_STATUS_ID = "available";
7
+ var STAGE_SECTION_KIND = "stage";
8
+ var DANCEFLOOR_SECTION_KIND = "dancefloor";
9
+ function isStageSection(section) {
10
+ return section.kind === STAGE_SECTION_KIND;
11
+ }
12
+ function isDancefloorSection(section) {
13
+ return section.kind === DANCEFLOOR_SECTION_KIND;
14
+ }
15
+ function getSectionSeatCount(section) {
16
+ return section.rows.reduce((count, row) => count + row.seats.length, 0);
17
+ }
18
+ function isAreaSeatSection(section) {
19
+ if (isDancefloorSection(section)) return true;
20
+ if (isStageSection(section)) return false;
21
+ return section.outline.length >= 3 && getSectionSeatCount(section) === 1;
22
+ }
7
23
  var DEFAULT_SEAT_STATUSES = [
8
24
  { id: AVAILABLE_STATUS_ID, name: "Available", color: "#4caf50" },
9
25
  { id: "locked", name: "Locked", color: "#f44336" },
@@ -15,7 +31,8 @@ var LEGACY_STATUS_MAP = {
15
31
  sold: "booked"
16
32
  };
17
33
  function normalizeStatusId(rawStatus, allowedStatuses) {
18
- const mapped = LEGACY_STATUS_MAP[rawStatus] ?? rawStatus;
34
+ const lower = rawStatus.toLowerCase();
35
+ const mapped = LEGACY_STATUS_MAP[lower] ?? lower;
19
36
  if (allowedStatuses.has(mapped)) return mapped;
20
37
  return AVAILABLE_STATUS_ID;
21
38
  }
@@ -138,6 +155,8 @@ function normalizeVenue(venue) {
138
155
  });
139
156
  const sections = venue.sections.map((section) => ({
140
157
  ...section,
158
+ kind: section.kind === STAGE_SECTION_KIND ? "stage" : section.kind === DANCEFLOOR_SECTION_KIND ? "dancefloor" : "section",
159
+ categoryId: section.kind === STAGE_SECTION_KIND ? "" : section.categoryId,
141
160
  rows: section.rows.map((row) => ({
142
161
  ...row,
143
162
  seats: row.seats.map((seat) => ({
@@ -180,12 +199,13 @@ var SpatialIndex = class {
180
199
  for (const row of section.rows) {
181
200
  for (const seat of row.seats) {
182
201
  const wp = seatWorldPosition(section, seat);
202
+ const dancefloorBounds = isAreaSeatSection(section) ? getSectionOutlineWorldBounds(section) : null;
183
203
  const r = 8;
184
204
  this.items.push({
185
- minX: wp.x - r,
186
- minY: wp.y - r,
187
- maxX: wp.x + r,
188
- maxY: wp.y + r,
205
+ minX: dancefloorBounds?.minX ?? wp.x - r,
206
+ minY: dancefloorBounds?.minY ?? wp.y - r,
207
+ maxX: dancefloorBounds?.maxX ?? wp.x + r,
208
+ maxY: dancefloorBounds?.maxY ?? wp.y + r,
189
209
  type: "seat",
190
210
  sectionId: section.id,
191
211
  seatId: seat.id
@@ -211,6 +231,21 @@ var SpatialIndex = class {
211
231
  return this.tree.search(rect);
212
232
  }
213
233
  };
234
+ function getSectionOutlineWorldBounds(section) {
235
+ if (section.outline.length < 3) return null;
236
+ const c = Math.cos(section.rotation);
237
+ const s = Math.sin(section.rotation);
238
+ const worldPoints = section.outline.map((point) => ({
239
+ x: section.position.x + point.x * c - point.y * s,
240
+ y: section.position.y + point.x * s + point.y * c
241
+ }));
242
+ return {
243
+ minX: Math.min(...worldPoints.map((point) => point.x)),
244
+ minY: Math.min(...worldPoints.map((point) => point.y)),
245
+ maxX: Math.max(...worldPoints.map((point) => point.x)),
246
+ maxY: Math.max(...worldPoints.map((point) => point.y))
247
+ };
248
+ }
214
249
 
215
250
  // src/rendering/Viewport.ts
216
251
  var MIN_ZOOM = 0.05;
@@ -435,6 +470,6 @@ function deserializeVenue(json) {
435
470
  return normalizeVenue(JSON.parse(json));
436
471
  }
437
472
 
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 };
473
+ export { AVAILABLE_STATUS_ID, CategoryTextureCache, CommandHistory, DANCEFLOOR_SECTION_KIND, DEFAULT_SEAT_STATUSES, LODLevel, STAGE_SECTION_KIND, SpatialIndex, Viewport, clampToPolygon, createSeatTextures, deserializeVenue, destroySeatTextures, generateId, getLODLevel, isAreaSeatSection, isDancefloorSection, isStageSection, normalizeVenue, pointInPolygon, seatWorldPosition, sectionAABB, serializeVenue, venueAABB };
439
474
  //# sourceMappingURL=index.js.map
440
475
  //# 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":["uuidv7","LODLevel"],"mappings":"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","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"]}
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":"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","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\";\nexport const STAGE_SECTION_KIND = \"stage\";\nexport const DANCEFLOOR_SECTION_KIND = \"dancefloor\";\n\nexport function isStageSection(section: Section): boolean {\n return section.kind === STAGE_SECTION_KIND;\n}\n\nexport function isDancefloorSection(section: Section): boolean {\n return section.kind === DANCEFLOOR_SECTION_KIND;\n}\n\nfunction getSectionSeatCount(section: Section): number {\n return section.rows.reduce((count, row) => count + row.seats.length, 0);\n}\n\n/**\n * Area-seat sections should use the whole outline for rendering/hit testing.\n * This includes explicit dancefloors and legacy single-seat outlined sections.\n */\nexport function isAreaSeatSection(section: Section): boolean {\n if (isDancefloorSection(section)) return true;\n if (isStageSection(section)) return false;\n return section.outline.length >= 3 && getSectionSeatCount(section) === 1;\n}\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 lower = rawStatus.toLowerCase();\n const mapped = LEGACY_STATUS_MAP[lower] ?? lower;\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: Section[] = venue.sections.map((section): Section => ({\n ...section,\n kind:\n section.kind === STAGE_SECTION_KIND\n ? \"stage\"\n : section.kind === DANCEFLOOR_SECTION_KIND\n ? \"dancefloor\"\n : \"section\",\n categoryId: section.kind === STAGE_SECTION_KIND ? \"\" : section.categoryId,\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 { isAreaSeatSection, 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 dancefloorBounds =\n isAreaSeatSection(section)\n ? getSectionOutlineWorldBounds(section)\n : null;\n const r = 8;\n this.items.push({\n minX: dancefloorBounds?.minX ?? wp.x - r,\n minY: dancefloorBounds?.minY ?? wp.y - r,\n maxX: dancefloorBounds?.maxX ?? wp.x + r,\n maxY: dancefloorBounds?.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\nfunction getSectionOutlineWorldBounds(section: Section): AABB | null {\n if (section.outline.length < 3) return null;\n const c = Math.cos(section.rotation);\n const s = Math.sin(section.rotation);\n const worldPoints = section.outline.map((point) => ({\n x: section.position.x + point.x * c - point.y * s,\n y: section.position.y + point.x * s + point.y * c,\n }));\n return {\n minX: Math.min(...worldPoints.map((point) => point.x)),\n minY: Math.min(...worldPoints.map((point) => point.y)),\n maxX: Math.max(...worldPoints.map((point) => point.x)),\n maxY: Math.max(...worldPoints.map((point) => point.y)),\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.9",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -21,7 +21,10 @@
21
21
  "dev": "tsup --watch",
22
22
  "lint": "tsc --noEmit",
23
23
  "test": "bun test",
24
- "clean": "rm -rf dist"
24
+ "clean": "rm -rf dist",
25
+ "verify:package-exports": "bun run scripts/verify-package-exports.ts",
26
+ "prepack": "bun run clean && bun run build && bun run verify:package-exports",
27
+ "prepublishOnly": "bun run prepack"
25
28
  },
26
29
  "peerDependencies": {
27
30
  "pixi.js": "^8"