@seatlayer/core 0.1.0
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 +2418 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +826 -0
- package/dist/index.d.ts +826 -0
- package/dist/index.js +2377 -0
- package/dist/index.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/core/layout.ts","../src/engine/SeatmapRenderer.ts","../src/picker/PickerController.ts"],"sourcesContent":["/**\n * SeatMap chart document — the single source of truth shared by the\n * Designer (authoring) and the Renderer (buyer picker).\n *\n * Mirrors docs/seatmap-build-spec.md §5. Coordinates are abstract units\n * (roughly \"pixels at scale 1\"); the renderer fits the chart to its container.\n * Rows are PARAMETRIC (origin + count + spacing + curve + rotation) — never\n * store per-seat coordinates in the document; expansion happens in layout.ts.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Category {\n key: string;\n label: string;\n color: string;\n /** Demo-only convenience; real pricing comes from ticket tiers server-side. */\n price?: number;\n}\n\n/**\n * Accessibility accommodations a seat can carry. Mirrors the taxonomy real\n * venues (and seats.io) expose so buyers can filter for exactly what they need\n * and organizers can mark seats precisely. `wheelchair` is the legacy default.\n */\nexport type AccessibilityType =\n | 'wheelchair'\n | 'companion'\n | 'semi-ambulatory'\n | 'hearing'\n | 'sign-language'\n | 'plus-size'\n | 'lift-armrest';\n\nexport interface AccessibilityMeta {\n key: AccessibilityType;\n /** Full descriptive label (designer checkbox, picker legend). */\n label: string;\n /** Compact label for chips/badges. */\n short: string;\n /** Single-glyph badge shown on seat chips + filter chips. */\n icon: string;\n}\n\n/** Ordered taxonomy — drives the designer seat panel and the picker filters. */\nexport const ACCESSIBILITY_TYPES: AccessibilityMeta[] = [\n { key: 'wheelchair', label: 'Wheelchair space', short: 'Wheelchair', icon: '♿' },\n { key: 'companion', label: 'Companion seat', short: 'Companion', icon: '🧑🤝🧑' },\n { key: 'semi-ambulatory', label: 'Semi-ambulatory (limited mobility)', short: 'Limited mobility', icon: '🦯' },\n { key: 'hearing', label: 'Assistive listening', short: 'Hearing', icon: '🦻' },\n { key: 'sign-language', label: 'Sign-language view', short: 'Sign language', icon: '🤟' },\n { key: 'plus-size', label: 'Plus-size seat', short: 'Plus-size', icon: '💺' },\n { key: 'lift-armrest', label: 'Lift-up armrest', short: 'Lift armrest', icon: '↕️' },\n];\n\nconst ACCESSIBILITY_LABEL = new Map(ACCESSIBILITY_TYPES.map((a) => [a.key, a]));\n\n/** Metadata for one accessibility key (undefined for unknown keys). */\nexport function accessibilityMeta(key: AccessibilityType): AccessibilityMeta | undefined {\n return ACCESSIBILITY_LABEL.get(key);\n}\n\nexport interface SeatOverride {\n /** 0-based seat index within the row. */\n index: number;\n /** Physical seat absent (pillar, sound desk) — numbering gap preserved. */\n skip?: boolean;\n /** Position nudge in chart units. */\n dx?: number;\n dy?: number;\n /** Replace the computed label entirely. */\n label?: string;\n categoryKey?: string;\n /** @deprecated legacy flag — read as `['wheelchair']`; write `accessibility`. */\n accessible?: boolean;\n /** Accessibility accommodations of this seat (empty/absent = none). */\n accessibility?: AccessibilityType[];\n}\n\n/** Brand/venue theming — applied by the renderer in both designer and picker. */\nexport interface ChartTheme {\n /** Canvas background color (default dark: #0e1117-ish radial). */\n background?: string;\n /** Seat label text color (default dark ink #0b1220). */\n seatLabelColor?: string;\n /** Selection ring / accent color (default white ring + brand accent). */\n selectionColor?: string;\n /** Décor (stage/shape) default fill. */\n decorFill?: string;\n /** Free-text color default. */\n textColor?: string;\n /** Font family (CSS stack) for all rendered text — seat labels, sections, décor text. */\n fontFamily?: string;\n /** Seat size multiplier on the base radius (0.7–1.6, default 1) — bigger seats fit longer labels. */\n seatScale?: number;\n // ---- White-label branding (applied by the buyer picker chrome) ----\n /** Brand accent color — recolors buttons, links, the hold pill, selection UI. */\n accent?: string;\n /** Ink color for text on the accent (e.g. button labels). Default light. */\n accentInk?: string;\n /** Organizer logo shown in the picker header (data/R2 URL). Falls back to the name. */\n logoUrl?: string;\n /** Brand/venue name shown in the picker header when no event name is set. */\n brandName?: string;\n /** Paid-tier flag: hide the \"Powered by SeatMap\" badge. */\n hideBadge?: boolean;\n}\n\nexport interface RowObject {\n type: 'row';\n id: string;\n /** Row label, e.g. \"A\". Seat labels are `${label}-${n}`. */\n label: string;\n /** Position of the FIRST seat. */\n origin: Point;\n /** Degrees, clockwise. 0 = seats laid out along +x. */\n rotation: number;\n /**\n * Total arc sweep in degrees across the whole row. 0 = straight.\n * Positive bends away from +y (concave toward the focal point when the\n * row faces it). Typical theatre rows: 10–40.\n */\n curve: number;\n seatCount: number;\n /** Distance between adjacent seat centers, in chart units. */\n seatSpacing: number;\n categoryKey: string;\n /** First seat number (default 1). */\n seatLabelStart?: number;\n /** Seat numbering within the row (default ltr, step 1). */\n seatNumbering?: {\n direction: 'ltr' | 'rtl';\n /** 2 = odd/even numbering (1,3,5… — start at 2 for evens). */\n step?: 1 | 2;\n };\n /**\n * Per-seat exceptions, keyed by seat index (0-based position in the row).\n * `skip` removes the physical seat but keeps the numbering gap (theatre\n * convention: a pillar eats A-3; A-4 stays A-4).\n */\n overrides?: SeatOverride[];\n /**\n * Organizer-supplied equirectangular 360 (or wide photo) shown as the\n * view-from-seat for every seat in this row. When absent, the picker\n * generates a synthetic panorama from chart geometry.\n */\n viewFromSeatUrl?: string;\n}\n\nexport interface GAAreaObject {\n type: 'gaArea';\n id: string;\n label: string;\n /** Closed polygon, in chart units. */\n points: Point[];\n capacity: number;\n categoryKey: string;\n}\n\n/** Non-bookable décor: stage, walls, exits. */\nexport interface ShapeObject {\n type: 'shape';\n id: string;\n kind: 'rect' | 'ellipse' | 'polygon';\n label?: string;\n /** For rect/ellipse: bounding box. For a stage polygon: the base (pre-shape) box, so its kind can be regenerated. */\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n /** For polygon. */\n points?: Point[];\n fill?: string;\n /** Degrees clockwise about the shape's center (default 0). Applied at render time. */\n rotation?: number;\n /**\n * Semantic tag driving special rendering. `'stage'` gets the gradient +\n * prominent uppercase label treatment; a décor landmark role (bar, exit…)\n * gets a quieter label. Loose string to avoid a circular import with\n * stage.ts / decor.ts (see StageKind / DecorRole there).\n */\n role?: string;\n /** For a stage: which `StageKind` its polygon was generated from. */\n stageKind?: string;\n}\n\n/** Seats arranged around a table; bookable per-seat or as a whole. */\nexport interface TableObject {\n type: 'table';\n id: string;\n /** e.g. \"T1\" — seat labels are `${label}-${n}`. */\n label: string;\n center: Point;\n shape: 'round' | 'rect';\n /** Seats around the perimeter (round) or along the enabled edges (rect). */\n seatCount: number;\n /** Rect tables: which edges get seats (default ['top','bottom']). */\n sides?: Array<'top' | 'bottom' | 'left' | 'right'>;\n rotation: number;\n /** Round tables. */\n radius?: number;\n /** Rect tables. */\n width?: number;\n height?: number;\n categoryKey: string;\n /** Whole-table booking: buyers get all seats or none (per-event override later). */\n bookAsWhole?: boolean;\n}\n\n/** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */\nexport interface BoothObject {\n type: 'booth';\n id: string;\n label: string;\n center: Point;\n width: number;\n height: number;\n rotation: number;\n categoryKey: string;\n}\n\n/**\n * A named region of the venue (Balcony Left, Floor B…). Sections are outlines\n * only — objects belong to a section spatially (center inside the outline),\n * keeping the document flat (no nesting; simpler for tools and for AI edits).\n * Renderer: far zoom shows section shapes/labels instead of seats; clicking\n * a section zooms into it.\n */\nexport interface SectionObject {\n type: 'section';\n id: string;\n label: string;\n /** Closed polygon, chart units. */\n outline: Point[];\n /** Optional tint override (defaults to a neutral fill / dominant category mix). */\n color?: string;\n /** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */\n zone?: string;\n /**\n * Tier height. 0 = floor (default). Higher values lift the section in the\n * picker's isometric (\"3D\") view, drawn on extruded side faces. Same field a\n * future multi-floor mode reuses — authored in 2D, never drawn by the user.\n */\n elevation?: number;\n /** Uniform scale about the outline centroid (1 = as drawn). Scales members too. */\n scale?: number;\n /** 0–1: how strongly member-row curves are bent toward a common arc fitted to the outline. */\n smoothing?: number;\n /** Degrees clockwise about the outline centroid (default 0). Rotates members too. */\n rotation?: number;\n}\n\n/**\n * A group of sections (Lower Bowl, Upper Bowl, Floor…). One concept, three jobs:\n * the farthest-zoom navigation unit, a pricing group, and (Batch 3) a timed-\n * release unit. Kept as a flat list on the doc; sections point back by `zone` id.\n */\nexport interface ZoneDef {\n id: string;\n label: string;\n color?: string;\n}\n\n/**\n * Selection layer — a hit-test/dim filter in the designer, NOT z-order management.\n * Fixed set of four; derived from object type via `layerOf()` (no per-object field yet).\n */\nexport type SelectionLayer = 'interactive' | 'background' | 'foreground' | 'surroundings';\n\n/** Derive an object's selection layer from its type (design contract, HANDOFF §03). */\nexport function layerOf(obj: ChartObject): SelectionLayer {\n switch (obj.type) {\n case 'row':\n case 'table':\n case 'gaArea':\n case 'booth':\n case 'section':\n return 'interactive';\n // stage / décor live on 'shape'; free text is background furniture.\n case 'shape':\n case 'text':\n return 'background';\n default:\n return 'interactive';\n }\n}\n\n/** Free-standing text on the chart (aisle names, door labels…). */\nexport interface TextObject {\n type: 'text';\n id: string;\n text: string;\n position: Point;\n fontSize: number;\n rotation: number;\n color?: string;\n}\n\nexport type ChartObject =\n | RowObject\n | GAAreaObject\n | ShapeObject\n | TableObject\n | BoothObject\n | TextObject\n | SectionObject;\n\nexport interface ChartDoc {\n version: 1;\n name: string;\n venueType: 'SIMPLE' | 'MIXED';\n /** The stage / point every seat looks at. Anchors seat-view + sightlines. */\n focalPoint: Point;\n categories: Category[];\n /** Section groupings for far-zoom navigation + pricing (optional; sections reference by id). */\n zones?: ZoneDef[];\n objects: ChartObject[];\n /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */\n backgroundImage?: {\n url: string;\n center: Point;\n /** Rendered width in chart units (height follows the image aspect). */\n width: number;\n opacity: number;\n locked?: boolean;\n };\n /** Brand/venue theming (colors); categories carry their own colors separately. */\n theme?: ChartTheme;\n}\n\n// ---------------------------------------------------------------------------\n// Expanded (render-time) model — produced by layout.ts, consumed by the engine\n// ---------------------------------------------------------------------------\n\nexport interface ExpandedSeat {\n /** Stable id: `${rowId}:${index}` */\n id: string;\n /** Public label: `${rowLabel}-${seatNumber}` */\n label: string;\n x: number;\n y: number;\n rowId: string;\n categoryKey: string;\n /** 'booth' units render as blocks (dimensions looked up via rowId = booth id). */\n kind?: 'seat' | 'booth';\n /** True when the seat has any accessibility accommodation — renderer rings/dims these. */\n accessible?: boolean;\n /** Specific accessibility accommodations (absent = none) — picker badges/filters these. */\n accessibility?: AccessibilityType[];\n /** Organizer-supplied view-from-seat image (inherited from the row). */\n viewUrl?: string;\n}\n\nexport type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';\n\n// ---------------------------------------------------------------------------\n// Renderer engine public API — implemented in src/engine/SeatmapRenderer.ts\n// ---------------------------------------------------------------------------\n\nexport interface RendererCallbacks {\n onSelect?: (seat: ExpandedSeat) => void;\n onDeselect?: (seat: ExpandedSeat) => void;\n /** seat is null when the pointer leaves any seat. */\n onHover?: (seat: ExpandedSeat | null) => void;\n /** Keyboard focus moved to a seat (arrow-key navigation) — for screen-reader announcements. */\n onFocusSeat?: (seat: ExpandedSeat | null) => void;\n /** Called ~1×/sec with the measured frames-per-second. */\n onFps?: (fps: number) => void;\n /** Fired when a GA area is clicked (quantity picking is UI-side). */\n onGAClick?: (areaId: string) => void;\n /** Fired after any pan/zoom/resize settles — re-anchor screen-space overlays. */\n onViewChange?: () => void;\n}\n\nexport interface RendererOptions extends RendererCallbacks {\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /** Only these statuses are clickable (default ['free']). */\n selectableStatuses?: SeatStatus[];\n /**\n * Opt-in host behaviour flag — the renderer's own click/selection logic is\n * unchanged (it still selects + fires `onSelect` immediately, so the seat\n * highlights right away). When true, the host (e.g. PublicEventPage) treats\n * that `onSelect` as a pending candidate and shows a confirm card instead of\n * pushing straight into the cart; `deselect([seat.id])` on Cancel un-highlights.\n */\n confirmSelection?: boolean;\n}\n\nexport interface ISeatmapRenderer {\n /** Replace the chart. Resets selection and statuses, zooms to fit. */\n setChart(doc: ChartDoc): void;\n /** Bulk status update; re-renders affected seats only. */\n setStatus(seatIds: string[], status: SeatStatus): void;\n getStatus(seatId: string): SeatStatus;\n getSelection(): ExpandedSeat[];\n clearSelection(): void;\n /** Programmatic deselect of specific seats (e.g. chip × in the cart). */\n deselect(seatIds: string[]): void;\n /**\n * Brief attention pulse on a seat (a ring that expands + fades once) — used to\n * signal live activity, e.g. a seat \"just taken\" by another buyer via a WS\n * delta. Purely visual; no state change. `color` overrides the default.\n */\n flashSeat(seatId: string, color?: string): void;\n zoomToFit(): void;\n /** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */\n zoomIn(): void;\n /** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */\n zoomOut(): void;\n /** Total seat count of the current chart. */\n seatCount(): number;\n /**\n * Maps a chart-space point (or a seat, by its x/y) to container-relative\n * screen pixels, using the current stage scale/position. Lets host UI anchor\n * DOM overlays (confirm card, tooltip) over a live seat and re-anchor them\n * on `onViewChange`.\n */\n worldToScreen(point: Point): { x: number; y: number };\n /** When on, dim non-accessible free seats so accessible seats stand out. */\n setAccessibleFilter(on: boolean): void;\n /**\n * Dim free seats that lack ANY of these accessibility types. `null` clears the\n * filter; `[]` means \"any accessible seat\" (same as setAccessibleFilter(true)).\n */\n setAccessibilityFilter(types: AccessibilityType[] | null): void;\n /** Legend hover-highlight: dim free seats of other categories (null clears). */\n setCategoryHighlight?(key: string | null): void;\n /**\n * Switch the projection. `'flat'` = normal top-down; `'isometric'` = the \"3D\"\n * view (affine skew/rotate + elevation lift), hit-testing preserved in screen\n * space. Purely visual — the chart is authored flat. Animated unless reduced-motion.\n */\n setViewMode?(mode: 'flat' | 'isometric'): void;\n /**\n * Section id whose outline contains a container-relative screen point (or null).\n * Feeds the far-zoom \"tap a section to zoom in\" flow (Slice 5).\n */\n sectionAt?(clientPoint: Point): string | null;\n /** Seat ids belonging to a section — for the section-summary card (Slice 5). */\n sectionMembers?(id: string): string[];\n destroy(): void;\n}\n\n/** localStorage key the Designer writes and the Picker reads. */\nexport const CHART_STORAGE_KEY = 'seatmap.chart';\n","/**\n * Pure geometry helpers — no Konva, no DOM. Turns the parametric chart\n * document into concrete seat coordinates and computes bounding boxes.\n */\n\nimport type {\n AccessibilityType,\n BoothObject,\n ChartDoc,\n ChartObject,\n ExpandedSeat,\n Point,\n RowObject,\n SeatOverride,\n TableObject,\n} from './types';\n\n/** Resolve a seat override's accessibility, honouring the legacy boolean flag. */\nfunction overrideAccessibility(o: SeatOverride | undefined): AccessibilityType[] {\n if (!o) return [];\n if (o.accessibility && o.accessibility.length) return o.accessibility;\n return o.accessible ? ['wheelchair'] : [];\n}\n\nconst DEG = Math.PI / 180;\n/** Seat visual radius (mirrors the renderer) — used only for bounds padding. */\nconst SEAT_R = 9;\n/** How far outside a table's body its seats sit. */\nconst TABLE_SEAT_OFFSET = 16;\n\n/** Rotate a local point clockwise by `deg` (screen coords, +y down) then translate. */\nfunction place(lx: number, ly: number, deg: number, origin: Point): { x: number; y: number } {\n const a = deg * DEG;\n const cos = Math.cos(a);\n const sin = Math.sin(a);\n return {\n x: origin.x + lx * cos - ly * sin,\n y: origin.y + lx * sin + ly * cos,\n };\n}\n\n/**\n * Expand a parametric row into seat positions.\n *\n * Straight (curve === 0): seat i sits at local (i·spacing, 0).\n *\n * Curved: seats lie on a circular arc. Per-seat angular step is\n * `curve/(seatCount-1)`; radius is derived so the chord between neighbours\n * equals seatSpacing → radius = spacing / (2·sin(step/2)). Seat 0 sits at the\n * bottom of the arc (local origin) with the circle centre directly above it at\n * (0,-radius); increasing index sweeps toward +x while the ends rise toward -y,\n * i.e. positive curve is concave toward -y (a row wrapping a stage above it).\n * Local points are then rotated by `rotation` and translated to `origin`.\n *\n * Numbering (labels only, never geometry): `seatNumbering.direction === 'rtl'`\n * numbers from the far physical end; `step === 2` produces odd/even numbering\n * (start at 1 → 1,3,5…; start at 2 → 2,4,6…).\n */\n/** Base (pre-override) seat centre per index — shared by expandRow + designer edit mode. */\nfunction rowSeatPositions(row: RowObject): Point[] {\n const { seatCount, seatSpacing, curve, rotation, origin } = row;\n const out: Point[] = [];\n if (seatCount <= 1) {\n if (seatCount === 1) out.push({ x: origin.x, y: origin.y });\n return out;\n }\n if (curve === 0) {\n for (let i = 0; i < seatCount; i++) out.push(place(i * seatSpacing, 0, rotation, origin));\n return out;\n }\n const arcStep = (curve / (seatCount - 1)) * DEG; // radians per seat\n const radius = seatSpacing / (2 * Math.sin(Math.abs(arcStep) / 2));\n // Centre above seat 0. φ measured from the downward vertical, growing with index.\n for (let i = 0; i < seatCount; i++) {\n const phi = i * arcStep;\n const lx = radius * Math.sin(phi);\n const ly = -radius + radius * Math.cos(phi); // ≤ 0 → ends rise toward -y\n out.push(place(lx, ly, rotation, origin));\n }\n return out;\n}\n\nfunction overrideMap(row: RowObject): Map<number, SeatOverride> {\n const m = new Map<number, SeatOverride>();\n if (row.overrides) for (const o of row.overrides) m.set(o.index, o);\n return m;\n}\n\n/**\n * Every seat slot of a row INCLUDING skipped ones (designer seat-edit mode uses\n * this to draw un-skip handles). Overrides (dx/dy/label/categoryKey) are applied\n * but a skipped slot is flagged, not omitted.\n */\nexport interface RowSeatSlot {\n index: number;\n x: number;\n y: number;\n label: string;\n categoryKey: string;\n skipped: boolean;\n accessible: boolean;\n accessibility: AccessibilityType[];\n}\n\nexport function expandRowSlots(row: RowObject): RowSeatSlot[] {\n const start = row.seatLabelStart ?? 1;\n const dir = row.seatNumbering?.direction ?? 'ltr';\n const step = row.seatNumbering?.step ?? 1;\n const seatNumber = (i: number) => start + (dir === 'rtl' ? row.seatCount - 1 - i : i) * step;\n const ov = overrideMap(row);\n return rowSeatPositions(row).map((p, i) => {\n const o = ov.get(i);\n const accessibility = overrideAccessibility(o);\n return {\n index: i,\n x: p.x + (o?.dx ?? 0),\n y: p.y + (o?.dy ?? 0),\n label: o?.label ?? `${row.label}-${seatNumber(i)}`,\n categoryKey: o?.categoryKey ?? row.categoryKey,\n skipped: !!o?.skip,\n accessible: accessibility.length > 0,\n accessibility,\n };\n });\n}\n\nexport function expandRow(row: RowObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n for (const slot of expandRowSlots(row)) {\n if (slot.skipped) continue; // physical seat absent; numbering gap preserved\n seats.push({\n id: `${row.id}:${slot.index}`,\n label: slot.label,\n x: slot.x,\n y: slot.y,\n rowId: row.id,\n categoryKey: slot.categoryKey,\n accessible: slot.accessible || undefined,\n accessibility: slot.accessibility.length ? slot.accessibility : undefined,\n viewUrl: row.viewFromSeatUrl,\n });\n }\n return seats;\n}\n\n/**\n * Expand a table into its perimeter seats.\n *\n * Round: seats spread evenly on a circle of radius `radius + 16`, the first at\n * angle `rotation` (degrees, clockwise from +x). Rect: seats line the top and\n * bottom edges (split evenly, any remainder to the top), 16u outside the edge,\n * the whole set rotated about the table centre.\n */\nexport function expandTable(t: TableObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n const n = Math.max(0, Math.round(t.seatCount));\n if (n === 0) return seats;\n\n const mk = (i: number, x: number, y: number): ExpandedSeat => ({\n id: `${t.id}:${i}`,\n label: `${t.label}-${i + 1}`,\n x,\n y,\n rowId: t.id,\n categoryKey: t.categoryKey,\n });\n\n if (t.shape === 'round') {\n const R = (t.radius ?? 40) + TABLE_SEAT_OFFSET;\n const base = t.rotation * DEG;\n for (let i = 0; i < n; i++) {\n const a = base + (i / n) * 2 * Math.PI;\n seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));\n }\n return seats;\n }\n\n // Rect: seats line the enabled edges. Round-robin the count across sides in\n // canonical order so they stay balanced; top/bottom run along width, left/\n // right along height, all 16u outside and rotated with the table.\n const w = t.width ?? 80;\n const h = t.height ?? 50;\n const enabled: NonNullable<TableObject['sides']> =\n t.sides && t.sides.length ? t.sides : ['top', 'bottom'];\n const order = (['top', 'bottom', 'left', 'right'] as const).filter((s) => enabled.includes(s));\n if (!order.length) return seats;\n const counts = new Map<(typeof order)[number], number>(order.map((s) => [s, 0]));\n for (let i = 0; i < n; i++) {\n const s = order[i % order.length];\n counts.set(s, counts.get(s)! + 1);\n }\n let idx = 0;\n for (const side of order) {\n const count = counts.get(side)!;\n for (let j = 0; j < count; j++) {\n let localX: number;\n let localY: number;\n if (side === 'top') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = -h / 2 - TABLE_SEAT_OFFSET;\n } else if (side === 'bottom') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = h / 2 + TABLE_SEAT_OFFSET;\n } else if (side === 'left') {\n localX = -w / 2 - TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n } else {\n localX = w / 2 + TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n }\n const p = place(localX, localY, t.rotation, t.center);\n seats.push(mk(idx++, p.x, p.y));\n }\n }\n return seats;\n}\n\n/** Expand a booth into its single bookable block unit. */\nexport function expandBooth(b: BoothObject): ExpandedSeat[] {\n return [\n {\n id: `${b.id}:0`,\n label: b.label,\n x: b.center.x,\n y: b.center.y,\n rowId: b.id,\n categoryKey: b.categoryKey,\n kind: 'booth',\n },\n ];\n}\n\n/** Ray-cast point-in-polygon test — odd crossings ⇒ inside. */\nexport function pointInPolygon(p: Point, poly: Point[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x;\n const yi = poly[i].y;\n const xj = poly[j].x;\n const yj = poly[j].y;\n const hit = yi > p.y !== yj > p.y && p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;\n if (hit) inside = !inside;\n }\n return inside;\n}\n\n/** Average of polygon vertices (v1 centroid — good enough for labels/membership). */\nfunction polygonCentroid(pts: Point[]): Point {\n if (!pts.length) return { x: 0, y: 0 };\n let x = 0;\n let y = 0;\n for (const p of pts) {\n x += p.x;\n y += p.y;\n }\n return { x: x / pts.length, y: y / pts.length };\n}\n\n/**\n * Visual centre of any object — used for spatial section membership and for\n * rotating an object about its centre. Rows: centroid of expanded seats (or\n * origin when empty); tables/booths: centre; GA/section: polygon centroid;\n * shape: bbox centre; text: its position.\n */\nexport function objectCenter(o: ChartObject): Point {\n switch (o.type) {\n case 'row': {\n const seats = expandRow(o);\n if (!seats.length) return { x: o.origin.x, y: o.origin.y };\n let x = 0;\n let y = 0;\n for (const s of seats) {\n x += s.x;\n y += s.y;\n }\n return { x: x / seats.length, y: y / seats.length };\n }\n case 'table':\n case 'booth':\n return { x: o.center.x, y: o.center.y };\n case 'gaArea':\n return polygonCentroid(o.points);\n case 'section':\n return polygonCentroid(o.outline);\n case 'text':\n return { x: o.position.x, y: o.position.y };\n case 'shape':\n if (o.points && o.points.length) return polygonCentroid(o.points);\n if (o.x != null && o.y != null && o.width != null && o.height != null) {\n return { x: o.x + o.width / 2, y: o.y + o.height / 2 };\n }\n return { x: o.x ?? 0, y: o.y ?? 0 };\n }\n}\n\n/** Expand every seat-bearing object (rows, tables, booths). */\nexport function expandChart(doc: ChartDoc): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const obj of doc.objects) {\n if (obj.type === 'row') out.push(...expandRow(obj));\n else if (obj.type === 'table') out.push(...expandTable(obj));\n else if (obj.type === 'booth') out.push(...expandBooth(obj));\n }\n return out;\n}\n\nconst PAD = 40;\n\n/** Axis-aligned bounds over every object plus the background image, with padding. */\nexport function chartBounds(doc: ChartDoc): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n const acc = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n };\n\n for (const s of expandChart(doc)) acc(s.x, s.y);\n\n for (const obj of doc.objects) {\n if (obj.type === 'gaArea') {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.type === 'section') {\n for (const p of obj.outline) acc(p.x, p.y);\n } else if (obj.type === 'shape') {\n if (obj.points && obj.points.length) {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n acc(obj.x, obj.y);\n acc(obj.x + obj.width, obj.y + obj.height);\n }\n } else if (obj.type === 'table') {\n const off = TABLE_SEAT_OFFSET + SEAT_R;\n const ext =\n obj.shape === 'round'\n ? (obj.radius ?? 40) + off\n : Math.max((obj.width ?? 80) / 2, (obj.height ?? 50) / 2) + off; // rotation-agnostic over-approximation\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'booth') {\n const ext = Math.max(obj.width, obj.height) / 2;\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'text') {\n const w = obj.fontSize * obj.text.length * 0.6; // approximate glyph advance\n acc(obj.position.x, obj.position.y);\n acc(obj.position.x + w, obj.position.y + obj.fontSize);\n }\n }\n\n if (doc.backgroundImage) {\n const { center, width } = doc.backgroundImage;\n const bh = (width * 3) / 4; // assume 4:3 when the true aspect is unknown at bounds-time\n acc(center.x - width / 2, center.y - bh / 2);\n acc(center.x + width / 2, center.y + bh / 2);\n }\n\n // Empty document → a sane default box around the focal point.\n if (!isFinite(minX)) {\n const f = doc.focalPoint ?? { x: 0, y: 0 };\n return { x: f.x - 200, y: f.y - 200, width: 400, height: 400 };\n }\n\n return {\n x: minX - PAD,\n y: minY - PAD,\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n };\n}\n","/**\n * SeatmapRenderer — the shared canvas rendering core (buyer picker shell).\n *\n * Uses Konva directly with per-module imports to keep the bundle lean. The\n * whole point of the spike is staying smooth at ~5,000 seats on mobile, so the\n * hot paths lean on: layer bitmap caching + listening(false) when zoomed out,\n * per-seat fill updates (never full rebuilds) on status change, and viewport-\n * only label rendering rebuilt on interaction-end rather than per frame.\n */\n\n// Core (not Global): Core assembles the real Konva namespace — Global alone\n// lacks DD/Util and Stage._pointermove dereferences Konva.DD unconditionally.\nimport { Konva } from 'konva/lib/Core';\nimport { Stage } from 'konva/lib/Stage';\nimport { Layer } from 'konva/lib/Layer';\nimport { Group } from 'konva/lib/Group';\nimport { Circle } from 'konva/lib/shapes/Circle';\nimport { Rect } from 'konva/lib/shapes/Rect';\nimport { Ellipse } from 'konva/lib/shapes/Ellipse';\nimport { Line } from 'konva/lib/shapes/Line';\nimport { Text } from 'konva/lib/shapes/Text';\nimport { Image as KImage } from 'konva/lib/shapes/Image';\nimport type { KonvaEventObject } from 'konva/lib/Node';\nimport type { Shape } from 'konva/lib/Shape';\n\nimport type {\n AccessibilityType,\n ChartDoc,\n ChartTheme,\n ExpandedSeat,\n ISeatmapRenderer,\n Point,\n RendererOptions,\n SeatStatus,\n SectionObject,\n} from '../core/types';\nimport { chartBounds, expandChart, pointInPolygon } from '../core/layout';\n\nconst SEAT_RADIUS = 9;\n/** Absolute scale at which a seat (r=9) renders ~legibly (~8px). */\nconst SEAT_LEGIBLE_SCALE = 0.9;\n/** Below this absolute scale we swap seats for a cached bitmap. */\nconst CACHE_THRESHOLD = 0.55 * SEAT_LEGIBLE_SCALE;\n/** Show per-seat labels above this ABSOLUTE scale (seat ⌀ ≈ 18px) — chart-size independent. */\nconst LABEL_SCALE = 1.0;\n/** Below this scale, sections (if any) get a prominent outline/label — the far \"overview\" LOD. */\nconst SECTION_PROMINENT_SCALE = 0.35 * SEAT_LEGIBLE_SCALE;\n/**\n * Below this scale, ZONE blocks/labels take over from per-section detail (the\n * farthest rung). ~0.55× the section rung so: seats → section blocks → zones.\n */\nconst ZONE_PROMINENT_SCALE = 0.55 * SECTION_PROMINENT_SCALE;\n/** Never label more than this many seats at once (viewport clutter guard). */\nconst MAX_LABELS = 700;\n\n// ---- Isometric (\"3D\") view mode -------------------------------------------\n/** Full-iso rotation of the chart about its centre (degrees). */\nconst ISO_ANGLE_DEG = -11.5;\n/** Full-iso vertical squash (1 = flat). */\nconst ISO_SQUASH = 0.58;\n/** World units a section (and its members) lift per elevation step at full iso. */\nconst LIFT_PER_STEP = 46;\n/** Flat⇄iso tween duration (ms); reduced-motion snaps. */\nconst ISO_TWEEN_MS = 320;\n\n// ---- Section/zone LOD (\"melt\") tuning -------------------------------------\n/** Peak fill opacity of a solid section block at the block rung. */\nconst BLOCK_FILL_ALPHA = 0.85;\n/** How far a fully-sold section's fill darkens toward black. */\nconst SOLD_DARKEN = 0.5;\n/** Screen-space target sizes (px) for scale-compensated section/zone labels. */\nconst SECTION_LABEL_PX = 18;\nconst SECTION_SUB_PX = 11;\nconst ZONE_LABEL_PX = 30;\nconst ZONE_SUB_PX = 12;\n\nconst HELD_FILL = '#6b7280';\nconst TAKEN_FILL = '#374151';\nconst NFS_STROKE = '#4b5563';\n\n/** Outer-ring colour per accommodation (a seat's first-listed type wins). */\nconst ACCESS_RING: Record<AccessibilityType, string> = {\n wheelchair: '#3b82f6',\n companion: '#8b5cf6',\n 'semi-ambulatory': '#0ea5e9',\n hearing: '#14b8a6',\n 'sign-language': '#f59e0b',\n 'plus-size': '#ec4899',\n 'lift-armrest': '#22c55e',\n};\n\n/** Does a seat satisfy a filter? `[]` means \"any accessible seat\". */\nfunction seatMatchesAccess(seat: ExpandedSeat, filter: AccessibilityType[]): boolean {\n if (filter.length === 0) return !!seat.accessible;\n return !!seat.accessibility?.some((t) => filter.includes(t));\n}\n\n// Theme fallbacks (dark defaults) — used when doc.theme leaves a slot unset.\nconst DEF_SEAT_LABEL = '#0b1220';\nconst DEF_SELECTION = '#ffffff';\nconst DEF_DECOR_FILL = '#232c40';\nconst DEF_TEXT = '#8b93a7';\n\nconst clamp = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));\n\n/** Read a custom attr off an event target (Stage | Shape union isn't callable directly). */\nfunction seatIdOf(target: unknown): string | undefined {\n const n = target as { getAttr?: (k: string) => unknown } | null;\n return (n?.getAttr?.('seatId') as string | undefined) ?? undefined;\n}\n\n/** Mix a #rrggbb colour toward white by `amt` (0..1). */\nfunction lighten(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const r = (n >> 16) & 255;\n const g = (n >> 8) & 255;\n const b = n & 255;\n const mix = (c: number) => Math.round(c + (255 - c) * amt);\n return `#${((1 << 24) | (mix(r) << 16) | (mix(g) << 8) | mix(b)).toString(16).slice(1)}`;\n}\n\n/** Mix a #rrggbb colour toward black by `amt` (0..1). */\nfunction darken(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const mix = (c: number) => Math.round(c * (1 - amt));\n return `#${((1 << 24) | (mix((n >> 16) & 255) << 16) | (mix((n >> 8) & 255) << 8) | mix(n & 255)).toString(16).slice(1)}`;\n}\n\n/** Axis-aligned bounds of a polygon (no padding). */\nfunction polyBounds(pts: Point[]): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of pts) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) };\n}\n\n/** #rrggbb → rgba() string at alpha `a`; passes non-hex through unchanged. */\nfunction rgba(hex: string, a: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})`;\n}\n\n/** Parse #rrggbb → [r,g,b] (0..255); null for non-hex. */\nfunction hexToRgb(hex: string): [number, number, number] | null {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return null;\n const n = parseInt(m[1], 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nconst toHex = (r: number, g: number, b: number): string =>\n `#${((1 << 24) | (Math.round(r) << 16) | (Math.round(g) << 8) | Math.round(b)).toString(16).slice(1)}`;\n\n/**\n * Count-weighted RGB blend of member seat colours — a section reads as its\n * price makeup, not one flat colour. Falls back to `fallback` when empty.\n */\nfunction mixColors(parts: Array<{ hex: string; w: number }>, fallback: string): string {\n let r = 0;\n let g = 0;\n let b = 0;\n let tw = 0;\n for (const p of parts) {\n const rgb = hexToRgb(p.hex);\n if (!rgb || p.w <= 0) continue;\n r += rgb[0] * p.w;\n g += rgb[1] * p.w;\n b += rgb[2] * p.w;\n tw += p.w;\n }\n return tw > 0 ? toHex(r / tw, g / tw, b / tw) : fallback;\n}\n\n/** Linear interpolate between two #rrggbb colours (t 0..1); passes `a` through if unparseable. */\nfunction lerpColor(a: string, b: string, t: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n if (!ca || !cb) return a;\n return toHex(ca[0] + (cb[0] - ca[0]) * t, ca[1] + (cb[1] - ca[1]) * t, ca[2] + (cb[2] - ca[2]) * t);\n}\n\n/** Per-section render state for the block LOD rung (fills, labels, membership). */\ninterface SectionRender {\n id: string;\n label: string;\n outline: Point[];\n centroid: Point;\n zone?: string;\n /** Seats whose centre falls inside the outline (first-match, doc order). */\n memberIds: string[];\n total: number;\n free: number;\n /** Category-mix (or explicit override) fill BEFORE the availability tint. */\n baseFill: string;\n /** Faint outline drawn under seats — the existing near-zoom look, untouched. */\n outlinePoly: Line;\n /** Solid block fill that melts in at the block rung. */\n blockPoly: Line;\n /** Section name (always drawn; brightens at the block rung, hides at zone rung). */\n nameLabel: Text;\n /** Mono \"N LEFT\" availability sublabel (block rung only). */\n subLabel: Text;\n /** Tier height (0 = floor). Lifts the section + members in iso (\"3D\") view. */\n elevation: number;\n /**\n * When elevation > 0, the section's bg nodes + member seats live in these\n * groups so a single position offset lifts the whole tier in iso view.\n */\n liftGroupBg: Group | null;\n liftGroupSeat: Group | null;\n /** Extruded side faces (one per outline edge) shown only as isoT rises. */\n sideFaces: Line[];\n}\n\n/** Per-zone render state for the farthest LOD rung. */\ninterface ZoneRender {\n id: string;\n label: Text;\n sub: Text | null;\n}\n\nexport class SeatmapRenderer implements ISeatmapRenderer {\n private container: HTMLDivElement;\n private opts: Required<Pick<RendererOptions, 'maxSelection'>> & RendererOptions;\n\n private stage: Stage;\n private bgLayer: Layer;\n private seatLayer: Layer;\n private overlayLayer: Layer;\n private labelGroup: Group;\n\n private seats: ExpandedSeat[] = [];\n private seatById = new Map<string, ExpandedSeat>();\n /** Interactive node per seat/booth — a Circle for seats, a Rect for booths. */\n private circleById = new Map<string, Shape>();\n /** Booth block geometry, keyed by booth id (= the unit's rowId). */\n private boothDims = new Map<string, { width: number; height: number; rotation: number }>();\n private statusById = new Map<string, SeatStatus>();\n private catColor = new Map<string, string>();\n private theme: ChartTheme = {};\n\n private selection = new Set<string>();\n private selectionRings = new Map<string, Circle>();\n private hoverRing: Circle;\n /** Keyboard-navigation focus ring + the currently focused seat id. */\n private focusRing: Circle;\n private focusedId: string | null = null;\n /**\n * Accessibility filter: `null` = off; `[]` = dim all non-accessible free seats;\n * a type list = dim free seats lacking any of those accommodations.\n */\n private accessFilter: AccessibilityType[] | null = null;\n /** Category highlight (legend hover): dims free seats NOT of this category. */\n private categoryHighlight: string | null = null;\n\n // Section/zone overlays (bgLayer) — the 3-rung LOD: seats → section blocks →\n // zone blocks. Kept for the melt restyle and for hit-testing a zoomed-out tap.\n private sections: SectionRender[] = [];\n private zones: ZoneRender[] = [];\n private seatSection = new Map<string, SectionRender>();\n private catPrice = new Map<string, number>();\n /** Zone id → colour (drives extruded side faces in iso view). */\n private zoneColor = new Map<string, string>();\n private hasSections = false;\n /** seatLayer carries Text (booth labels) — gate the upright-label scan. */\n private hasBoothText = false;\n\n // Isometric (\"3D\") view — an affine skew/rotate + elevation lift, tweened.\n /** 0 = flat (default), 1 = full isometric; animated by setViewMode. */\n private isoT = 0;\n private isoTarget = 0;\n private isoRaf = 0;\n /** Chart centre the iso projection pivots about (bounds centre). */\n private isoCentre = { x: 0, y: 0 };\n /** Set in destroy() so an in-flight iso tween bails. */\n private destroyed = false;\n /** Cached scale the section/zone labels were last sized for (scale-compensation). */\n private lodScale = 0;\n /** prefers-reduced-motion → hard-swap rungs instead of cross-fading. */\n private reducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n private fitScale = 1;\n /** Effective seat radius (base × theme.seatScale), set per chart in setChart. */\n private seatR = SEAT_RADIUS;\n private bounds = { x: 0, y: 0, width: 1, height: 1 };\n private cached = false;\n private dpr = Math.min(typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1, 2);\n\n private rafId = 0;\n private frames = 0;\n private lastFpsAt = 0;\n private recacheTimer: ReturnType<typeof setTimeout> | null = null;\n private resizeObs: ResizeObserver | null = null;\n /** Coalesces bursty view-change sources (pointermove, wheel) into ≤1 callback/frame. */\n private viewChangeRaf = 0;\n\n // Gesture state — pan/pinch are handled with raw pointer events on the\n // container (Konva stage dragging is off; its touch pipeline proved\n // unreliable for multi-touch on real devices).\n private pointers = new Map<number, { x: number; y: number }>();\n private pinch: { startDist: number; startScale: number; worldMid: { x: number; y: number } } | null = null;\n private panLast: { x: number; y: number } | null = null;\n /** Cumulative gesture movement in px — clicks are suppressed after a real pan/pinch. */\n private moved = 0;\n\n constructor(container: HTMLDivElement, options: RendererOptions = {}) {\n this.container = container;\n this.opts = { maxSelection: 10, selectableStatuses: ['free'], ...options };\n\n Konva.pixelRatio = this.dpr;\n\n this.stage = new Stage({\n container,\n width: container.clientWidth || 1,\n height: container.clientHeight || 1,\n draggable: false, // pan/pinch are ours, via pointer events\n });\n\n container.style.touchAction = 'none';\n container.addEventListener('pointerdown', this.onPointerDown, { passive: false });\n container.addEventListener('pointermove', this.onPointerMove, { passive: false });\n container.addEventListener('pointerup', this.onPointerEnd, { passive: false });\n container.addEventListener('pointercancel', this.onPointerEnd, { passive: false });\n\n // Keyboard accessibility: the canvas is focusable and navigable seat-by-seat.\n if (container.tabIndex < 0) container.tabIndex = 0;\n container.setAttribute('role', 'application');\n if (!container.getAttribute('aria-label')) {\n container.setAttribute('aria-label', 'Seating map. Use arrow keys to move between seats, Enter to select.');\n }\n container.addEventListener('keydown', this.onKeyDown);\n\n this.bgLayer = new Layer({ listening: true });\n this.seatLayer = new Layer({ listening: true });\n this.overlayLayer = new Layer({ listening: false });\n this.labelGroup = new Group({ listening: false });\n this.overlayLayer.add(this.labelGroup);\n\n this.hoverRing = new Circle({\n radius: SEAT_RADIUS + 2,\n stroke: '#ffffff',\n strokeWidth: 2,\n opacity: 0.85,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.hoverRing);\n\n this.focusRing = new Circle({\n radius: SEAT_RADIUS + 3,\n stroke: '#38bdf8',\n strokeWidth: 2.5,\n dash: [4, 3],\n opacity: 0.95,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.focusRing);\n\n this.stage.add(this.bgLayer, this.seatLayer, this.overlayLayer);\n\n this.wireInteraction();\n this.startFpsLoop();\n\n if (import.meta.env.DEV) {\n (window as unknown as Record<string, unknown>).__seatmap = this;\n }\n\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObs = new ResizeObserver(() => this.handleResize());\n this.resizeObs.observe(container);\n }\n }\n\n // ---- ISeatmapRenderer -----------------------------------------------------\n\n setChart(doc: ChartDoc): void {\n this.focusedId = null;\n this.focusRing.visible(false);\n this.bgLayer.destroyChildren();\n this.seatLayer.destroyChildren();\n this.labelGroup.destroyChildren();\n this.circleById.clear();\n this.boothDims.clear();\n this.selectionRings.clear();\n this.statusById.clear();\n this.selection.clear();\n this.seatById.clear();\n this.cached = false;\n this.accessFilter = null;\n this.sections = [];\n this.zones = [];\n this.seatSection.clear();\n this.catPrice.clear();\n this.zoneColor.clear();\n this.lodScale = 0;\n this.hasBoothText = false;\n // Reloading the chart resets the view to flat (identity layer transforms).\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n this.isoT = 0;\n this.isoTarget = 0;\n this.resetLayerTransforms();\n this.hasSections = doc.objects.some((o) => o.type === 'section');\n for (const z of doc.zones ?? []) if (z.color) this.zoneColor.set(z.id, z.color);\n // Seats fade against the block fill during the melt; reset to fully opaque.\n this.seatLayer.opacity(1);\n this.hoverRing.visible(false);\n\n this.theme = doc.theme ?? {};\n // Adjustable seat size: a chart-level scale on the base radius. Clamped so\n // enlarged seats don't collide with typical row spacing (~24 units).\n this.seatR = clamp(this.theme.seatScale ?? 1, 0.7, 1.6) * SEAT_RADIUS;\n // Canvas background via container style (reset to '' when theme omits it).\n this.container.style.background = this.theme.background ?? '';\n this.hoverRing.stroke(this.theme.selectionColor ?? DEF_SELECTION);\n this.hoverRing.radius(this.seatR + 2);\n\n this.catColor.clear();\n this.catPrice.clear();\n for (const c of doc.categories) {\n this.catColor.set(c.key, c.color);\n if (typeof c.price === 'number') this.catPrice.set(c.key, c.price);\n }\n\n for (const obj of doc.objects) {\n if (obj.type === 'booth') {\n this.boothDims.set(obj.id, { width: obj.width, height: obj.height, rotation: obj.rotation });\n }\n }\n\n this.seats = expandChart(doc);\n for (const s of this.seats) {\n this.seatById.set(s.id, s);\n this.statusById.set(s.id, 'free');\n }\n\n this.renderBackground(doc);\n this.renderSeats();\n // re-add overlay furniture wiped by destroyChildren above\n this.overlayLayer.add(this.labelGroup);\n this.overlayLayer.add(this.hoverRing);\n\n this.bounds = chartBounds(doc);\n this.isoCentre = { x: this.bounds.x + this.bounds.width / 2, y: this.bounds.y + this.bounds.height / 2 };\n this.zoomToFit();\n }\n\n setStatus(seatIds: string[], status: SeatStatus): void {\n let touched = false;\n // Sections whose availability tint / \"N LEFT\" needs a cheap recompute.\n const affected = this.hasSections ? new Set<SectionRender>() : null;\n for (const id of seatIds) {\n if (!this.statusById.has(id)) continue;\n const prev = this.statusById.get(id);\n this.statusById.set(id, status);\n const c = this.circleById.get(id);\n if (c) {\n this.paintSeat(c, id);\n touched = true;\n }\n if (affected) {\n const sec = this.seatSection.get(id);\n if (sec) {\n if ((prev === 'free') !== (status === 'free')) {\n sec.free += status === 'free' ? 1 : -1;\n }\n affected.add(sec);\n }\n }\n }\n if (affected && affected.size) {\n for (const sec of affected) this.refreshSectionFill(sec);\n this.bgLayer.batchDraw();\n }\n if (!touched) return;\n if (this.cached) {\n // bitmap is stale; debounce a re-cache so bulk updates coalesce\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.recacheTimer = setTimeout(() => this.cacheSeatLayer(), 150);\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n getStatus(seatId: string): SeatStatus {\n return this.statusById.get(seatId) ?? 'free';\n }\n\n getSelection(): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const id of this.selection) {\n const s = this.seatById.get(id);\n if (s) out.push(s);\n }\n return out;\n }\n\n clearSelection(): void {\n const ids = [...this.selection];\n for (const id of ids) this.setSelected(id, false, true);\n this.overlayLayer.batchDraw();\n }\n\n deselect(seatIds: string[]): void {\n let changed = false;\n for (const id of seatIds) {\n if (this.selection.has(id)) {\n this.setSelected(id, false, true);\n changed = true;\n }\n }\n if (changed) this.overlayLayer.batchDraw();\n }\n\n flashSeat(seatId: string, color = '#f43f5e'): void {\n const seat = this.seatById.get(seatId);\n if (!seat) return;\n const ring = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n stroke: color,\n strokeWidth: 3,\n opacity: 0.9,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(ring);\n const start = performance.now();\n const dur = 620;\n const step = (now: number): void => {\n // Guard against a destroy() mid-animation (layer torn down).\n if (!ring.getLayer()) return;\n const t = Math.min(1, (now - start) / dur);\n ring.radius(this.seatR * (1 + t * 1.8));\n ring.opacity(0.9 * (1 - t));\n this.overlayLayer.batchDraw();\n if (t < 1) requestAnimationFrame(step);\n else {\n ring.destroy();\n this.overlayLayer.batchDraw();\n }\n };\n requestAnimationFrame(step);\n }\n\n // ---- keyboard navigation (accessibility) ----------------------------------\n\n private onKeyDown = (e: KeyboardEvent): void => {\n const dir =\n e.key === 'ArrowLeft' ? { x: -1, y: 0 }\n : e.key === 'ArrowRight' ? { x: 1, y: 0 }\n : e.key === 'ArrowUp' ? { x: 0, y: -1 }\n : e.key === 'ArrowDown' ? { x: 0, y: 1 }\n : null;\n if (dir) {\n e.preventDefault();\n const next = this.focusedId ? this.nearestSeat(this.focusedId, dir) : this.seats[0]?.id ?? null;\n if (next) this.focusSeat(next);\n return;\n }\n if ((e.key === 'Enter' || e.key === ' ') && this.focusedId) {\n e.preventDefault();\n this.toggleSeat(this.focusedId);\n const s = this.seatById.get(this.focusedId);\n if (s) this.opts.onFocusSeat?.(s); // re-announce; status may have changed\n }\n };\n\n /** Nearest seat from `fromId` in a cardinal direction (aligned + close wins). */\n private nearestSeat(fromId: string, dir: { x: number; y: number }): string | null {\n const from = this.seatById.get(fromId);\n if (!from) return null;\n let best: string | null = null;\n let bestScore = Infinity;\n for (const s of this.seats) {\n if (s.id === fromId) continue;\n const dx = s.x - from.x;\n const dy = s.y - from.y;\n const proj = dx * dir.x + dy * dir.y; // along the chosen direction\n if (proj <= 0.5) continue; // must lie in that direction\n const perp = Math.abs(dx * dir.y - dy * dir.x); // lateral offset\n const score = proj + perp * 2.5; // reward alignment + proximity\n if (score < bestScore) {\n bestScore = score;\n best = s.id;\n }\n }\n return best;\n }\n\n private focusSeat(id: string): void {\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.focusedId = id;\n this.focusRing.radius(this.seatR + 3);\n this.focusRing.position({ x: seat.x, y: seat.y });\n this.focusRing.visible(true);\n this.ensureVisible(seat);\n this.overlayLayer.batchDraw();\n this.opts.onFocusSeat?.(seat);\n }\n\n /** Pan/zoom so a seat sits on-screen at a legible scale (for keyboard focus). */\n private ensureVisible(seat: ExpandedSeat): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const target = Math.max(this.stage.scaleX(), SEAT_LEGIBLE_SCALE * 1.2);\n const p = this.worldToScreen(seat);\n const margin = 70;\n const offscreen = p.x < margin || p.x > w - margin || p.y < margin || p.y > h - margin;\n if (this.stage.scaleX() < target || offscreen) {\n // Centre on the PROJECTED seat position so iso view frames it correctly.\n const ip = this.isoT === 0 ? seat : this.isoForward(seat);\n this.stage.scale({ x: target, y: target });\n this.stage.position({ x: w / 2 - ip.x * target, y: h / 2 - ip.y * target });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n }\n\n zoomToFit(): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const b = this.bounds;\n this.fitScale = Math.min(w / b.width, h / b.height) || 1;\n const s = this.fitScale;\n this.stage.scale({ x: s, y: s });\n this.stage.position({\n x: (w - b.width * s) / 2 - b.x * s,\n y: (h - b.height * s) / 2 - b.y * s,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Step factor for the on-screen +/− buttons (B1) — same clamp path as pinch/wheel. */\n private static readonly ZOOM_STEP = 1.4;\n\n zoomIn(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() * SeatmapRenderer.ZOOM_STEP, center);\n }\n\n zoomOut(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() / SeatmapRenderer.ZOOM_STEP, center);\n }\n\n seatCount(): number {\n return this.seats.length;\n }\n\n worldToScreen(point: Point): { x: number; y: number } {\n const s = this.stage.scaleX();\n // In iso view, host overlays (confirm card, tooltip) must anchor to the\n // PROJECTED seat, so run the point through the iso affine first. At isoT=0\n // isoForward is the identity — byte-for-byte the flat behaviour.\n const p = this.isoT === 0 ? point : this.isoForward(point);\n return { x: p.x * s + this.stage.x(), y: p.y * s + this.stage.y() };\n }\n\n setAccessibleFilter(on: boolean): void {\n this.setAccessibilityFilter(on ? [] : null);\n }\n\n setAccessibilityFilter(types: AccessibilityType[] | null): void {\n const next = types === null ? null : [...types];\n if (this.sameAccessFilter(next)) return;\n this.accessFilter = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private sameAccessFilter(next: AccessibilityType[] | null): boolean {\n const cur = this.accessFilter;\n if (cur === null || next === null) return cur === next;\n return cur.length === next.length && cur.every((t, i) => t === next[i]);\n }\n\n // ---- isometric (\"3D\") view mode -------------------------------------------\n\n /**\n * Switch the projection between flat top-down and the isometric \"3D\" view\n * (rotate + y-squash about the chart centre, plus per-elevation lift). Tweens\n * `isoT` 0⇄1 over ~0.32s (ease in-out); reduced-motion snaps. Purely visual —\n * geometry stays flat, so hit-testing (Konva's own, plus the manual section\n * inverse) keeps landing on the projected seats/sections.\n */\n setViewMode(mode: 'flat' | 'isometric'): void {\n const target = mode === 'isometric' ? 1 : 0;\n this.isoTarget = target;\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n if (this.reducedMotion) {\n this.isoT = target;\n this.applyIso();\n this.afterViewChange();\n return;\n }\n const from = this.isoT;\n if (from === target) { this.applyIso(); this.afterViewChange(); return; }\n const start = performance.now();\n const step = (now: number): void => {\n if (this.destroyed) return; // guard a destroy() mid-tween\n const raw = Math.min(1, (now - start) / ISO_TWEEN_MS);\n // easeInOutCubic — matches the melt's camera glide.\n const e = raw < 0.5 ? 4 * raw * raw * raw : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n this.isoT = from + (this.isoTarget - from) * e;\n this.applyIso();\n this.scheduleViewChange();\n if (raw < 1) {\n this.isoRaf = requestAnimationFrame(step);\n } else {\n this.isoT = this.isoTarget;\n this.isoRaf = 0;\n this.applyIso();\n this.afterViewChange(); // re-evaluate cache/labels at the settled effective scale\n }\n };\n this.isoRaf = requestAnimationFrame(step);\n }\n\n /** Iso angle (rad) + y-squash for the current isoT. */\n private isoParams(): { th: number; sg: number } {\n return { th: (ISO_ANGLE_DEG * Math.PI) / 180 * this.isoT, sg: 1 - (1 - ISO_SQUASH) * this.isoT };\n }\n\n /** Effective vertical scale = stage scale × iso squash — legibility math uses this. */\n private effScale(): number {\n return this.stage.scaleX() * (1 - (1 - ISO_SQUASH) * this.isoT);\n }\n\n /** Project a world point through the iso affine about the chart centre (→ iso-world). */\n private isoForward(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const rx = dx * Math.cos(th) - dy * Math.sin(th);\n const ry = (dx * Math.sin(th) + dy * Math.cos(th)) * sg;\n return { x: c.x + rx, y: c.y + ry };\n }\n\n /** Inverse of isoForward (iso-world → world) for screen-space hit-testing. */\n private isoInverse(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const uy = dy / sg;\n const wx = dx * Math.cos(th) + uy * Math.sin(th);\n const wy = -dx * Math.sin(th) + uy * Math.cos(th);\n return { x: c.x + wx, y: c.y + wy };\n }\n\n /**\n * Local-space offset that, once the layer applies the iso affine, lifts an\n * object straight UP in iso-world by `elevation × LIFT_PER_STEP × isoT`\n * (= inverse-linear of the pure vertical lift). Zero at isoT=0.\n */\n private isoLiftLocal(elevation: number): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const delta = elevation * LIFT_PER_STEP * this.isoT;\n return { x: -(delta / sg) * Math.sin(th), y: -(delta / sg) * Math.cos(th) };\n }\n\n /** Restore the three layers to identity (flat) — byte-for-byte the original. */\n private resetLayerTransforms(): void {\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: 0, y: 0 });\n layer.offset({ x: 0, y: 0 });\n layer.scale({ x: 1, y: 1 });\n layer.rotation(0);\n layer.skewX(0);\n layer.skewY(0);\n }\n }\n\n /**\n * Apply the current isoT to the scene: the base rotate+squash as a decomposed\n * layer transform (so seats/décor/rings project together and Konva's own\n * hit-testing follows), upright counter-transforms on text, and the elevation\n * lift + extruded side faces on elevated sections.\n */\n private applyIso(): void {\n const t = this.isoT;\n if (t === 0) {\n this.resetLayerTransforms();\n } else {\n const { th, sg } = this.isoParams();\n // L_iso = Scale(1,sg)·Rot(th) about the centre; decompose to Konva props.\n const a = Math.cos(th);\n const b = sg * Math.sin(th);\n const cc = -Math.sin(th);\n const d = sg * Math.cos(th);\n const r = Math.sqrt(a * a + b * b);\n const delta = a * d - b * cc; // = sg\n const rotationDeg = (Math.atan2(b, a) * 180) / Math.PI;\n const scaleX = r;\n const scaleY = delta / r;\n const skewX = (a * cc + b * d) / delta;\n const c = this.isoCentre;\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: c.x, y: c.y });\n layer.offset({ x: c.x, y: c.y });\n layer.rotation(rotationDeg);\n layer.scaleX(scaleX);\n layer.scaleY(scaleY);\n layer.skewX(skewX);\n layer.skewY(0);\n }\n }\n\n this.applyUprightLabels();\n this.applyElevation();\n\n this.bgLayer.batchDraw();\n this.seatLayer.batchDraw();\n this.overlayLayer.batchDraw();\n }\n\n /** Counter-skew every visible label so it renders upright at its projected anchor. */\n private applyUprightLabels(): void {\n const thDeg = ISO_ANGLE_DEG * this.isoT;\n const invScaleY = 1 / (1 - (1 - ISO_SQUASH) * this.isoT);\n // Seat labels live in overlayLayer (labelGroup); section/zone/décor in bgLayer.\n // Skip the seatLayer scan unless it actually holds booth labels (else it is\n // thousands of Circles with no Text).\n const layers = this.hasBoothText\n ? [this.bgLayer, this.seatLayer, this.overlayLayer]\n : [this.bgLayer, this.overlayLayer];\n for (const layer of layers) {\n const texts = layer.find('Text') as unknown as Text[];\n for (const tn of texts) {\n let base = tn.getAttr('uprightBase') as number | undefined;\n if (base == null) {\n base = tn.rotation();\n tn.setAttr('uprightBase', base);\n }\n tn.rotation(base - thDeg);\n tn.scaleX(1);\n tn.scaleY(invScaleY);\n tn.skewX(0);\n }\n }\n }\n\n /** Lift elevated sections (+ their members) and update their extruded side faces. */\n private applyElevation(): void {\n const t = this.isoT;\n for (const sec of this.sections) {\n if (sec.elevation <= 0) continue;\n const off = this.isoLiftLocal(sec.elevation);\n sec.liftGroupBg?.position(off);\n sec.liftGroupSeat?.position(off);\n // Side faces: quad per edge from base outline to the lifted outline, in\n // local (world) space — the layer projects them. Invisible at isoT=0.\n const alpha = 0.9 * t;\n for (let i = 0; i < sec.sideFaces.length; i++) {\n const face = sec.sideFaces[i];\n const p0 = sec.outline[i];\n const p1 = sec.outline[(i + 1) % sec.outline.length];\n face.points([p0.x, p0.y, p1.x, p1.y, p1.x + off.x, p1.y + off.y, p0.x + off.x, p0.y + off.y]);\n face.opacity(alpha);\n }\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId) cancelAnimationFrame(this.rafId);\n if (this.isoRaf) cancelAnimationFrame(this.isoRaf);\n if (this.viewChangeRaf) cancelAnimationFrame(this.viewChangeRaf);\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.resizeObs?.disconnect();\n this.container.removeEventListener('pointerdown', this.onPointerDown);\n this.container.removeEventListener('pointermove', this.onPointerMove);\n this.container.removeEventListener('pointerup', this.onPointerEnd);\n this.container.removeEventListener('pointercancel', this.onPointerEnd);\n this.container.removeEventListener('keydown', this.onKeyDown);\n this.stage.destroy();\n }\n\n // ---- rendering ------------------------------------------------------------\n\n /** Theme font stack for all rendered text (falls back to Inter). */\n private labelFont(): string {\n return this.theme.fontFamily || 'Inter, sans-serif';\n }\n\n /**\n * Where a seat's nodes live: an elevated section's lift group (so the whole\n * tier shifts with one offset in iso view) or the seat layer directly.\n */\n private seatContainer(id: string): Group | Layer {\n return this.seatSection.get(id)?.liftGroupSeat ?? this.seatLayer;\n }\n\n private renderSeats(): void {\n for (const seat of this.seats) {\n if (seat.kind === 'booth') {\n this.renderBoothUnit(seat);\n continue;\n }\n const target = this.seatContainer(seat.id);\n const c = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n c.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, c);\n this.paintSeat(c, seat.id);\n target.add(c);\n // Accessible seats get a static 2px outer ring, coloured by their primary\n // accommodation (few per chart, so the extra node is cheap).\n if (seat.accessible) {\n const primary = seat.accessibility?.[0];\n target.add(\n new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR + 1,\n stroke: (primary && ACCESS_RING[primary]) || '#3b82f6',\n strokeWidth: 2,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n }),\n );\n }\n }\n }\n\n /** A booth renders as a click-selectable rounded block (dims from the doc). */\n private renderBoothUnit(seat: ExpandedSeat): void {\n const target = this.seatContainer(seat.id);\n const dims = this.boothDims.get(seat.rowId) ?? { width: 40, height: 30, rotation: 0 };\n const rect = new Rect({\n x: seat.x,\n y: seat.y,\n width: dims.width,\n height: dims.height,\n offsetX: dims.width / 2,\n offsetY: dims.height / 2,\n rotation: dims.rotation,\n cornerRadius: 4,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n rect.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, rect);\n this.paintSeat(rect, seat.id);\n target.add(rect);\n\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: seat.label,\n fontSize: 10,\n fontStyle: '600',\n fontFamily: this.labelFont(),\n fill: this.theme.seatLabelColor ?? DEF_SEAT_LABEL,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.hasBoothText = true; // gate the upright-label scan of the seat layer\n target.add(t);\n }\n\n /** Apply fill/stroke/opacity for a seat's current status + selection. */\n private paintSeat(c: Shape, id: string): void {\n const seat = this.seatById.get(id)!;\n const status = this.statusById.get(id) ?? 'free';\n const selected = this.selection.has(id);\n const base = this.catColor.get(seat.categoryKey) ?? '#6e7bff';\n\n c.dash([]);\n c.strokeWidth(0);\n c.stroke('');\n c.opacity(1);\n\n switch (status) {\n case 'free':\n c.fill(selected ? lighten(base, 0.28) : base);\n break;\n case 'held':\n c.fill(HELD_FILL);\n break;\n case 'booked':\n c.fill(TAKEN_FILL);\n c.opacity(0.45);\n break;\n case 'not_for_sale':\n c.fill(TAKEN_FILL);\n c.stroke(NFS_STROKE);\n c.strokeWidth(1);\n c.dash([2, 2]);\n break;\n }\n\n // Accessibility filter dims free, unselected seats that don't match.\n if (this.accessFilter && status === 'free' && !selected && !seatMatchesAccess(seat, this.accessFilter)) {\n c.opacity(0.25);\n }\n // Legend hover-highlight dims free, unselected seats of other categories.\n if (this.categoryHighlight && status === 'free' && !selected && seat.categoryKey !== this.categoryHighlight) {\n c.opacity(0.25);\n }\n }\n\n /** Legend hover: highlight one category (dim the rest), or null to clear. */\n setCategoryHighlight(key: string | null): void {\n if (this.categoryHighlight === key) return;\n this.categoryHighlight = key;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private renderBackground(doc: ChartDoc): void {\n if (doc.backgroundImage) this.renderBackgroundImage(doc.backgroundImage);\n // Sections sit under all other décor so their outlines never occlude seats.\n for (const obj of doc.objects) if (obj.type === 'section') this.renderSection(obj);\n // Zone labels sit above section blocks (drawn after) — the farthest rung.\n this.renderZones(doc);\n for (const obj of doc.objects) {\n if (obj.type === 'shape') {\n this.renderShape(obj);\n } else if (obj.type === 'gaArea') {\n this.renderGA(obj);\n } else if (obj.type === 'table') {\n this.renderTable(obj);\n } else if (obj.type === 'text') {\n this.renderText(obj);\n }\n }\n // Focal-point crosshair marker.\n const f = doc.focalPoint;\n if (f) {\n const size = 14;\n const cross = new Group({ listening: false });\n cross.add(\n new Line({ points: [f.x - size, f.y, f.x + size, f.y], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Line({ points: [f.x, f.y - size, f.x, f.y + size], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Circle({ x: f.x, y: f.y, radius: 3, fill: '#4b5563' }),\n );\n this.bgLayer.add(cross);\n }\n }\n\n /** Organizer floor-plan photo, dimmed, at the very bottom of the bg layer. */\n private renderBackgroundImage(bg: NonNullable<ChartDoc['backgroundImage']>): void {\n const img = new window.Image();\n img.onload = () => {\n const natW = img.naturalWidth || 4;\n const natH = img.naturalHeight || 3;\n const w = bg.width;\n const h = w * (natH / natW);\n const node = new KImage({\n image: img,\n x: bg.center.x - w / 2,\n y: bg.center.y - h / 2,\n width: w,\n height: h,\n opacity: bg.opacity,\n listening: false,\n });\n this.bgLayer.add(node);\n node.moveToBottom();\n this.bgLayer.batchDraw();\n };\n img.src = bg.url;\n }\n\n private renderTable(obj: Extract<ChartDoc['objects'][number], { type: 'table' }>): void {\n if (obj.shape === 'round') {\n this.bgLayer.add(\n new Circle({\n x: obj.center.x,\n y: obj.center.y,\n radius: obj.radius ?? 40,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n listening: false,\n }),\n );\n } else {\n const w = obj.width ?? 80;\n const h = obj.height ?? 50;\n this.bgLayer.add(\n new Rect({\n x: obj.center.x,\n y: obj.center.y,\n width: w,\n height: h,\n offsetX: w / 2,\n offsetY: h / 2,\n rotation: obj.rotation,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n cornerRadius: 4,\n listening: false,\n }),\n );\n }\n this.addCentredLabel(this.bgLayer, obj.label, obj.center.x, obj.center.y, '#cbd5e1', 12, true);\n }\n\n private renderText(obj: Extract<ChartDoc['objects'][number], { type: 'text' }>): void {\n this.bgLayer.add(\n new Text({\n x: obj.position.x,\n y: obj.position.y,\n text: obj.text,\n fontSize: obj.fontSize,\n rotation: obj.rotation,\n fill: obj.color ?? this.theme.textColor ?? DEF_TEXT,\n fontFamily: this.labelFont(),\n listening: false,\n perfectDrawEnabled: false,\n }),\n );\n }\n\n private renderShape(obj: Extract<ChartDoc['objects'][number], { type: 'shape' }>): void {\n const fill = obj.fill ?? this.theme.decorFill ?? DEF_DECOR_FILL;\n const isStage = obj.role === 'stage';\n const isDecor = !!obj.role && !isStage;\n // Stage: darker at the back (min-y), brighter toward the audience edge (max-y).\n const stroke = isStage ? lighten(fill, 0.28) : undefined;\n let cx = 0;\n let cy = 0;\n if (obj.kind === 'rect' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: 0 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n // Rotate about center: pivot at (cx,cy) via offset; local coords (and the\n // gradient) are unchanged, so the fill spans the box regardless of angle.\n this.bgLayer.add(\n new Rect({\n x: cx,\n y: cy,\n offsetX: obj.width / 2,\n offsetY: obj.height / 2,\n rotation: obj.rotation ?? 0,\n width: obj.width,\n height: obj.height,\n ...grad,\n stroke,\n strokeWidth: isStage ? 1 : 0,\n cornerRadius: 4,\n listening: false,\n }),\n );\n } else if (obj.kind === 'ellipse' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: -obj.height / 2 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height / 2 },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n this.bgLayer.add(\n new Ellipse({ x: cx, y: cy, rotation: obj.rotation ?? 0, radiusX: obj.width / 2, radiusY: obj.height / 2, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n } else if (obj.kind === 'polygon' && obj.points && obj.points.length) {\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const b = polyBounds(obj.points);\n cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n const grad = isStage\n ? {\n // Line points are absolute chart coords; the gradient endpoints share\n // that space and rotate with the node (pivot at the centroid below).\n fillLinearGradientStartPoint: { x: 0, y: b.y },\n fillLinearGradientEndPoint: { x: 0, y: b.y + b.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n // Rotate about the centroid: position=offset=centroid leaves the polygon\n // in place at rotation 0 and pivots there for any angle.\n this.bgLayer.add(\n new Line({ points: pts, closed: true, x: cx, y: cy, offsetX: cx, offsetY: cy, rotation: obj.rotation ?? 0, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n }\n if (obj.label) {\n if (isStage) this.addStageLabel(cx, cy, obj.label);\n else if (isDecor) this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#9aa3b5', 12, false);\n else this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#cbd5e1', 16, true);\n }\n }\n\n /** Prominent stage caption: uppercase, letter-spaced, larger, softly dimmed. */\n private addStageLabel(x: number, y: number, text: string): void {\n const t = new Text({\n x,\n y,\n text: text.toUpperCase(),\n fontSize: 22,\n fontStyle: '700',\n letterSpacing: 4,\n fontFamily: this.labelFont(),\n fill: rgba('#e6e9f0', 0.62),\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.bgLayer.add(t);\n }\n\n private renderGA(obj: Extract<ChartDoc['objects'][number], { type: 'gaArea' }>): void {\n const color = this.catColor.get(obj.categoryKey) ?? '#6e7bff';\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const poly = new Line({\n points: pts,\n closed: true,\n fill: color,\n opacity: 0.22,\n stroke: color,\n strokeWidth: 1.5,\n });\n poly.setAttr('gaId', obj.id);\n poly.on('click tap', () => this.opts.onGAClick?.(obj.id));\n poly.on('mouseenter', () => {\n this.container.style.cursor = 'pointer';\n });\n poly.on('mouseleave', () => {\n this.container.style.cursor = 'default';\n });\n this.bgLayer.add(poly);\n\n const cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n const cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n this.addCentredLabel(this.bgLayer, obj.label, cx, cy - 8, '#e6e9f0', 15, false);\n this.addCentredLabel(this.bgLayer, `cap ${obj.capacity}`, cx, cy + 10, '#8b93a7', 11, false);\n }\n\n /**\n * A section renders in three coordinated layers driven by the LOD melt:\n * • a faint outline (the existing near-zoom look, untouched),\n * • a solid category-mix block that fades in at the block rung, and\n * • a name + \"N LEFT\" sublabel.\n * Membership (which seats live inside the outline) + the mix fill + the live\n * availability count are precomputed here (once), not per frame.\n */\n private renderSection(obj: SectionObject): void {\n const pts = obj.outline.flatMap((p) => [p.x, p.y]);\n const centroid = {\n x: obj.outline.reduce((a, p) => a + p.x, 0) / obj.outline.length,\n y: obj.outline.reduce((a, p) => a + p.y, 0) / obj.outline.length,\n };\n\n // Membership: seats inside the outline, first section (doc order) wins.\n const memberIds: string[] = [];\n const catCounts = new Map<string, number>();\n let free = 0;\n for (const seat of this.seats) {\n if (this.seatSection.has(seat.id)) continue;\n if (!pointInPolygon(seat, obj.outline)) continue;\n memberIds.push(seat.id);\n catCounts.set(seat.categoryKey, (catCounts.get(seat.categoryKey) ?? 0) + 1);\n if ((this.statusById.get(seat.id) ?? 'free') === 'free') free++;\n }\n\n // Category-mix fill: explicit override wins, else blend member colours by count.\n const baseFill =\n obj.color ??\n mixColors(\n [...catCounts].map(([key, w]) => ({ hex: this.catColor.get(key) ?? '#6e7bff', w })),\n '#3a4358',\n );\n\n // Elevation: elevated sections lift as one tier in the iso view, so their bg\n // nodes + member seats go into lift groups (positioned in applyElevation).\n // Side faces (a zone-coloured quad per outline edge) extrude only as isoT rises.\n const elevation = Math.max(0, Math.round(obj.elevation ?? 0));\n let liftGroupBg: Group | null = null;\n let liftGroupSeat: Group | null = null;\n const sideFaces: Line[] = [];\n if (elevation > 0) {\n const faceFill = darken(this.zoneColor.get(obj.zone ?? '') ?? baseFill, 0.42);\n for (let i = 0; i < obj.outline.length; i++) {\n const face = new Line({\n points: [],\n closed: true,\n fill: faceFill,\n stroke: rgba('#000000', 0.25),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sideFaces.push(face);\n this.bgLayer.add(face); // behind the group added next → behind the fill\n }\n liftGroupBg = new Group({ listening: false });\n this.bgLayer.add(liftGroupBg);\n liftGroupSeat = new Group({ listening: false });\n this.seatLayer.add(liftGroupSeat);\n }\n const bgTarget: Group | Layer = liftGroupBg ?? this.bgLayer;\n\n // Faint outline — the pre-existing under-seat look, unchanged at near zoom.\n const outlinePoly = new Line({\n points: pts,\n closed: true,\n stroke: '#3a4358',\n strokeWidth: 1.5,\n fill: rgba(obj.color ?? '#3a4358', 0.06),\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(outlinePoly);\n\n // Solid block fill — melts in at the block rung (opacity driven by the LOD).\n const blockPoly = new Line({\n points: pts,\n closed: true,\n fill: baseFill,\n stroke: rgba('#ffffff', 0.12),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(blockPoly);\n\n const nameLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: obj.label,\n fontSize: 22,\n fontStyle: '700',\n fontFamily: this.labelFont(),\n fill: '#8b93a7',\n listening: false,\n perfectDrawEnabled: false,\n });\n nameLabel.offsetX(nameLabel.width() / 2);\n nameLabel.offsetY(nameLabel.height() / 2);\n bgTarget.add(nameLabel);\n\n const subLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: `${free} LEFT`,\n fontSize: 12,\n fontStyle: '600',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: rgba('#e6e9f0', 0.8),\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n subLabel.offsetX(subLabel.width() / 2);\n bgTarget.add(subLabel);\n\n const sec: SectionRender = {\n id: obj.id,\n label: obj.label,\n outline: obj.outline,\n centroid,\n zone: obj.zone,\n memberIds,\n total: memberIds.length,\n free,\n baseFill,\n outlinePoly,\n blockPoly,\n nameLabel,\n subLabel,\n elevation,\n liftGroupBg,\n liftGroupSeat,\n sideFaces,\n };\n for (const id of memberIds) this.seatSection.set(id, sec);\n this.refreshSectionFill(sec);\n this.sections.push(sec);\n }\n\n /** Recompute a section's availability-tinted fill + \"N LEFT\" (cheap; on status change). */\n private refreshSectionFill(sec: SectionRender): void {\n const sold = sec.total > 0 ? (sec.total - sec.free) / sec.total : 0;\n sec.blockPoly.fill(darken(sec.baseFill, sold * SOLD_DARKEN));\n sec.subLabel.text(`${sec.free} LEFT`);\n sec.subLabel.offsetX(sec.subLabel.width() / 2);\n }\n\n /**\n * Zone rung: one giant screen-constant label per zone (+ optional \"FROM $n\"),\n * shown at the farthest zoom in place of per-section detail. Skipped entirely\n * when the doc declares no zones — sections then stay the far rung (graceful).\n */\n private renderZones(doc: ChartDoc): void {\n if (!doc.zones?.length || !this.sections.length) return;\n const byZone = new Map<string, SectionRender[]>();\n for (const sec of this.sections) {\n if (!sec.zone) continue;\n (byZone.get(sec.zone) ?? byZone.set(sec.zone, []).get(sec.zone)!).push(sec);\n }\n for (const z of doc.zones) {\n const members = byZone.get(z.id);\n if (!members || !members.length) continue;\n const cx = members.reduce((a, s) => a + s.centroid.x, 0) / members.length;\n const cy = members.reduce((a, s) => a + s.centroid.y, 0) / members.length;\n\n // \"FROM $n\" = cheapest category price found among this zone's member seats.\n let minPrice = Infinity;\n for (const sec of members) {\n for (const id of sec.memberIds) {\n const seat = this.seatById.get(id);\n const p = seat && this.catPrice.get(seat.categoryKey);\n if (typeof p === 'number' && p < minPrice) minPrice = p;\n }\n }\n\n const label = new Text({\n x: cx,\n y: cy,\n text: z.label.toUpperCase(),\n fontSize: 34,\n fontStyle: '800',\n letterSpacing: 2,\n fontFamily: this.labelFont(),\n fill: z.color ?? '#f2f4f8',\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n label.offsetX(label.width() / 2);\n label.offsetY(label.height() / 2);\n this.bgLayer.add(label);\n\n let sub: Text | null = null;\n if (isFinite(minPrice)) {\n sub = new Text({\n x: cx,\n y: cy,\n text: `FROM $${minPrice}`,\n fontSize: 14,\n fontStyle: '600',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: rgba('#e6e9f0', 0.75),\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sub.offsetX(sub.width() / 2);\n this.bgLayer.add(sub);\n }\n this.zones.push({ id: z.id, label, sub });\n }\n }\n\n /**\n * THE MELT — a continuous, scale-driven cross-fade across the three rungs:\n * seats ⇄ section blocks ⇄ zone blocks.\n * `blockT` ramps 0→1 as scale falls through [SECTION_PROMINENT, CACHE_THRESHOLD]\n * so the solid fill is fully present exactly as seats become the cached bitmap\n * and fade out; `zoneT` ramps 0→1 across [ZONE_PROMINENT, SECTION_PROMINENT] so\n * per-section detail hands off to giant zone labels. Reduced-motion hard-swaps.\n * Section/zone labels are scale-compensated to hold a roughly constant screen size.\n */\n private applySectionLod(scale: number): void {\n let blockT: number;\n let zoneT: number;\n if (this.reducedMotion) {\n blockT = scale <= SECTION_PROMINENT_SCALE ? 1 : 0;\n zoneT = scale <= ZONE_PROMINENT_SCALE ? 1 : 0;\n } else {\n blockT = clamp((CACHE_THRESHOLD - scale) / (CACHE_THRESHOLD - SECTION_PROMINENT_SCALE), 0, 1);\n zoneT = clamp((SECTION_PROMINENT_SCALE - scale) / (SECTION_PROMINENT_SCALE - ZONE_PROMINENT_SCALE), 0, 1);\n }\n // No zones ⇒ skip the zone rung: sections stay the far rung (graceful).\n if (!this.zones.length) zoneT = 0;\n\n // Seats melt out as the block fill melts in (coordinated with the bitmap swap).\n this.seatLayer.opacity(1 - blockT);\n\n // Labels are drawn UPRIGHT (the iso squash is cancelled per-text), so their\n // on-screen size follows the raw stage scale, not the squashed effective one.\n const sx = this.stage.scaleX();\n // Scale-compensate label sizes only when the scale meaningfully changed.\n const rescale = this.lodScale === 0 || Math.abs(scale - this.lodScale) / (this.lodScale || 1) > 0.02;\n if (rescale) this.lodScale = scale;\n\n for (const sec of this.sections) {\n sec.blockPoly.opacity(BLOCK_FILL_ALPHA * blockT);\n // Name: faint→bright with blockT, then fades out as zones take over.\n sec.nameLabel.fill(lerpColor('#8b93a7', '#f2f4f8', blockT));\n sec.nameLabel.opacity(1 - zoneT);\n sec.subLabel.opacity(blockT * (1 - zoneT));\n if (rescale) {\n this.sizeLabel(sec.nameLabel, SECTION_LABEL_PX / sx, sec.centroid.y - SECTION_SUB_PX / sx);\n this.sizeLabel(sec.subLabel, SECTION_SUB_PX / sx, sec.centroid.y + SECTION_LABEL_PX / sx);\n }\n }\n\n for (const zone of this.zones) {\n zone.label.opacity(zoneT);\n if (zone.sub) zone.sub.opacity(zoneT);\n if (rescale) {\n const cy = zone.label.y();\n this.sizeLabel(zone.label, ZONE_LABEL_PX / sx, cy);\n if (zone.sub) this.sizeLabel(zone.sub, ZONE_SUB_PX / sx, cy + ZONE_LABEL_PX / sx);\n }\n }\n this.bgLayer.batchDraw();\n }\n\n /** Set a centred label's world fontSize (for a target screen px) and re-anchor it. */\n private sizeLabel(t: Text, fontSize: number, y: number): void {\n t.fontSize(Math.max(1, fontSize));\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n t.y(y);\n }\n\n /**\n * Map a container-relative screen point back to world coords. Inverts the\n * stage (scale/pos) and, in iso view, the iso affine — so screen-space taps\n * test against the flat world outlines/geometry. Identity-equivalent at isoT=0.\n */\n private screenToWorld(clientPoint: { x: number; y: number }): { x: number; y: number } {\n const s = this.stage.scaleX();\n const iso = { x: (clientPoint.x - this.stage.x()) / s, y: (clientPoint.y - this.stage.y()) / s };\n return this.isoT === 0 ? iso : this.isoInverse(iso);\n }\n\n /** Section id under a container-relative screen point, or null (Slice 5 tap-to-zoom). */\n sectionAt(clientPoint: { x: number; y: number }): string | null {\n if (!this.sections.length) return null;\n const world = this.screenToWorld(clientPoint);\n const hit = this.sections.find((sec) => pointInPolygon(world, sec.outline));\n return hit ? hit.id : null;\n }\n\n /** Seat ids belonging to a section (Slice 5 section-summary card). */\n sectionMembers(id: string): string[] {\n return this.sections.find((s) => s.id === id)?.memberIds.slice() ?? [];\n }\n\n private addCentredLabel(\n layer: Layer,\n text: string,\n x: number,\n y: number,\n fill: string,\n fontSize: number,\n bold: boolean,\n ): void {\n const t = new Text({\n x,\n y,\n text,\n fontSize,\n fontStyle: bold ? '700' : '500',\n fontFamily: this.labelFont(),\n fill,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n layer.add(t);\n }\n\n // ---- selection ------------------------------------------------------------\n\n private isSelectable(id: string): boolean {\n const statuses = this.opts.selectableStatuses ?? ['free'];\n return statuses.includes(this.statusById.get(id) ?? 'free');\n }\n\n private toggleSeat(id: string): void {\n if (this.selection.has(id)) {\n this.setSelected(id, false);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onDeselect?.(seat);\n } else {\n if (!this.isSelectable(id)) return;\n if (this.selection.size >= this.opts.maxSelection) return; // ignore beyond cap\n this.setSelected(id, true);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onSelect?.(seat);\n }\n this.overlayLayer.batchDraw();\n }\n\n private setSelected(id: string, on: boolean, silent = false): void {\n const c = this.circleById.get(id);\n if (on) {\n this.selection.add(id);\n const seat = this.seatById.get(id)!;\n const ring = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n stroke: this.theme.selectionColor ?? DEF_SELECTION,\n strokeWidth: 3,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.selectionRings.set(id, ring);\n this.overlayLayer.add(ring);\n } else {\n this.selection.delete(id);\n const ring = this.selectionRings.get(id);\n ring?.destroy();\n this.selectionRings.delete(id);\n }\n if (c) {\n this.paintSeat(c, id);\n if (!silent && !this.cached) this.seatLayer.batchDraw();\n }\n }\n\n // ---- interaction ----------------------------------------------------------\n\n private wireInteraction(): void {\n this.seatLayer.on('click tap', (e: KonvaEventObject<Event>) => {\n if (this.moved > 8) return; // it was a pan/pinch, not a tap\n const id = seatIdOf(e.target);\n if (id) this.toggleSeat(id);\n });\n\n // Hover (mouse only) via delegated enter/leave on seat circles.\n this.seatLayer.on('mouseover', (e: KonvaEventObject<MouseEvent>) => {\n const id = seatIdOf(e.target);\n if (!id) return;\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.hoverRing.position({ x: seat.x, y: seat.y });\n this.hoverRing.visible(true);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'pointer';\n this.opts.onHover?.(seat);\n });\n this.seatLayer.on('mouseout', () => {\n this.hoverRing.visible(false);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'default';\n this.opts.onHover?.(null);\n });\n\n this.stage.on('wheel', (e: KonvaEventObject<WheelEvent>) => {\n e.evt.preventDefault();\n // Position from the event itself — Konva's tracked pointer position is\n // unreliable when the last pointer event went elsewhere.\n const r = this.container.getBoundingClientRect();\n const pointer = { x: e.evt.clientX - r.left, y: e.evt.clientY - r.top };\n // Scale with the actual wheel delta so trackpad flings and fast wheels\n // zoom proportionally (a fixed step per event ignores delta magnitude).\n const factor = Math.exp(-e.evt.deltaY * 0.002);\n this.zoomAbout(this.stage.scaleX() * clamp(factor, 0.5, 2), pointer);\n });\n\n // Zoomed out, the seat layer is a non-listening cached bitmap and seats\n // are finger-width anyway — a tap zooms into that area instead of\n // attempting a 4px-precision selection (same behaviour as seats.io).\n this.stage.on('click tap', () => {\n if (!this.cached || this.moved > 8) return;\n const pointer = this.stage.getPointerPosition();\n if (!pointer) return;\n // A tap inside a section zooms to fit that section, not a generic 2.5×.\n if (this.sections.length) {\n const world = this.screenToWorld(pointer);\n const hit = this.sections.find((sn) => pointInPolygon(world, sn.outline));\n if (hit) {\n this.zoomToBounds(polyBounds(hit.outline));\n return;\n }\n }\n const target = Math.max(SEAT_LEGIBLE_SCALE * 1.2, this.stage.scaleX() * 2.5);\n this.zoomAbout(target, pointer);\n });\n }\n\n // ---- Pan & pinch (raw pointer events — mouse, touch and pen alike) --------\n\n private toLocal(e: PointerEvent): { x: number; y: number } {\n const r = this.container.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n }\n\n // NOTE: no setPointerCapture here — capturing on the container retargets\n // pointer events away from Konva's canvas, killing its click/tap/hover\n // pipeline. We rely on bubbling instead.\n private onPointerDown = (e: PointerEvent): void => {\n this.pointers.set(e.pointerId, this.toLocal(e));\n if (this.pointers.size === 1) {\n this.moved = 0;\n this.panLast = this.toLocal(e);\n this.pinch = null;\n } else if (this.pointers.size === 2) {\n // Anchor the whole pinch to its starting geometry: scale follows the\n // finger-distance ratio and the world point under the midpoint stays\n // glued to the midpoint. No per-event compounding → no drift.\n const [a, b] = [...this.pointers.values()];\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const s = this.stage.scaleX();\n this.pinch = {\n startDist: Math.hypot(b.x - a.x, b.y - a.y),\n startScale: s,\n worldMid: { x: (mid.x - this.stage.x()) / s, y: (mid.y - this.stage.y()) / s },\n };\n this.panLast = null;\n }\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this.pointers.has(e.pointerId)) return;\n e.preventDefault();\n const p = this.toLocal(e);\n const prev = this.pointers.get(e.pointerId)!;\n this.moved += Math.hypot(p.x - prev.x, p.y - prev.y);\n this.pointers.set(e.pointerId, p);\n\n if (this.pinch && this.pointers.size >= 2) {\n const [a, b] = [...this.pointers.values()];\n const dist = Math.hypot(b.x - a.x, b.y - a.y);\n if (this.pinch.startDist < 1) return;\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const { min, max } = this.zoomBounds();\n const scale = clamp(this.pinch.startScale * (dist / this.pinch.startDist), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: mid.x - this.pinch.worldMid.x * scale,\n y: mid.y - this.pinch.worldMid.y * scale,\n });\n this.stage.batchDraw();\n this.scheduleViewChange();\n } else if (this.panLast && this.pointers.size === 1) {\n this.stage.position({\n x: this.stage.x() + (p.x - this.panLast.x),\n y: this.stage.y() + (p.y - this.panLast.y),\n });\n this.panLast = p;\n this.stage.batchDraw();\n this.scheduleViewChange();\n }\n };\n\n private onPointerEnd = (e: PointerEvent): void => {\n this.pointers.delete(e.pointerId);\n if (this.pointers.size < 2) this.pinch = null;\n if (this.pointers.size === 1) {\n // pinch → single finger: continue as a pan without jumping\n this.panLast = [...this.pointers.values()][0];\n }\n if (this.pointers.size === 0) {\n this.panLast = null;\n this.afterViewChange();\n }\n };\n\n /**\n * Min is chart-relative (never lose the room); max is absolute so seats\n * reach a readable size on any chart, however large the venue.\n */\n private zoomBounds(): { min: number; max: number } {\n return { min: 0.5 * this.fitScale, max: Math.max(10 * this.fitScale, 4) };\n }\n\n /** Zoom so `clientPoint` (stage-relative px) stays fixed under the cursor. */\n private zoomAbout(nextScale: number, clientPoint: { x: number; y: number }): void {\n const { min, max } = this.zoomBounds();\n const scale = clamp(nextScale, min, max);\n const old = this.stage.scaleX();\n if (scale === old) return;\n const worldX = (clientPoint.x - this.stage.x()) / old;\n const worldY = (clientPoint.y - this.stage.y()) / old;\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: clientPoint.x - worldX * scale,\n y: clientPoint.y - worldY * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Zoom + pan so world-rect `b` fills the viewport (with a small margin). */\n private zoomToBounds(b: { x: number; y: number; width: number; height: number }): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n const scale = clamp(Math.min(w / (b.width * margin), h / (b.height * margin)), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: w / 2 - (b.x + b.width / 2) * scale,\n y: h / 2 - (b.y + b.height / 2) * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Recompute LOD (cache/labels) after any pan/zoom settles. */\n private afterViewChange(): void {\n this.updateLOD();\n this.updateLabels();\n this.scheduleViewChange();\n }\n\n /** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */\n private scheduleViewChange(): void {\n if (this.viewChangeRaf) return;\n this.viewChangeRaf = requestAnimationFrame(() => {\n this.viewChangeRaf = 0;\n this.opts.onViewChange?.();\n });\n }\n\n private updateLOD(): void {\n // Effective scale folds in the iso y-squash (smaller ⇒ seats read smaller),\n // so LOD/melt thresholds trip correctly in 3D view. Equals the raw stage\n // scale at isoT=0 → flat behaviour is unchanged.\n const scale = this.effScale();\n if (this.hasSections) this.applySectionLod(scale);\n const shouldCache = scale < CACHE_THRESHOLD;\n if (shouldCache && !this.cached) {\n this.cacheSeatLayer();\n } else if (!shouldCache && this.cached) {\n this.seatLayer.clearCache();\n this.seatLayer.listening(true);\n this.cached = false;\n this.seatLayer.batchDraw();\n }\n }\n\n private cacheSeatLayer(): void {\n // Cache at ~screen resolution: bitmap px ≈ on-screen px, so a huge chart in\n // chart-units doesn't blow up into a gigapixel canvas when zoomed out.\n const pr = clamp(this.stage.scaleX() * this.dpr, 0.15, 2);\n this.seatLayer.clearCache();\n this.seatLayer.cache({ pixelRatio: pr });\n this.seatLayer.listening(false);\n this.cached = true;\n this.seatLayer.batchDraw();\n }\n\n private updateLabels(): void {\n const show = this.effScale() > LABEL_SCALE;\n this.labelGroup.destroyChildren();\n if (!show) {\n this.overlayLayer.batchDraw();\n return;\n }\n // Visible chart rect (with a small margin) in chart coordinates.\n const s = this.stage.scaleX();\n const x0 = (-this.stage.x()) / s;\n const y0 = (-this.stage.y()) / s;\n const x1 = (this.stage.width() - this.stage.x()) / s;\n const y1 = (this.stage.height() - this.stage.y()) / s;\n\n let count = 0;\n for (const seat of this.seats) {\n if (seat.x < x0 || seat.x > x1 || seat.y < y0 || seat.y > y1) continue;\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: seat.label,\n fontSize: 7,\n fontStyle: '600',\n fontFamily: this.labelFont(),\n fill: this.theme.seatLabelColor ?? DEF_SEAT_LABEL,\n listening: false,\n perfectDrawEnabled: false,\n });\n // Auto-fit: shrink long labels (e.g. \"T10-10\") so they never spill out of\n // the seat circle. Down to a legibility floor; below that the label is\n // dropped rather than rendered as an unreadable speck.\n const maxW = this.seatR * 2 - 3;\n if (t.width() > maxW) t.fontSize(Math.max(4, (7 * maxW) / t.width()));\n if (t.fontSize() < 4.2) { t.destroy(); continue; }\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.labelGroup.add(t);\n if (++count >= MAX_LABELS) break;\n }\n // Keep freshly-built seat labels upright under the iso layer skew.\n if (this.isoT > 0) this.applyUprightLabels();\n this.overlayLayer.batchDraw();\n }\n\n private handleResize(): void {\n const w = this.container.clientWidth || 1;\n const h = this.container.clientHeight || 1;\n if (w === this.stage.width() && h === this.stage.height()) return;\n this.stage.size({ width: w, height: h });\n // Keep the chart framed; refit is the least surprising behaviour on resize.\n this.zoomToFit();\n }\n\n private startFpsLoop(): void {\n const tick = (now: number) => {\n if (!this.lastFpsAt) this.lastFpsAt = now;\n this.frames++;\n const elapsed = now - this.lastFpsAt;\n if (elapsed >= 1000) {\n this.opts.onFps?.(Math.round((this.frames * 1000) / elapsed));\n this.frames = 0;\n this.lastFpsAt = now;\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n}\n\nexport function createRenderer(container: HTMLDivElement, opts?: RendererOptions): ISeatmapRenderer {\n return new SeatmapRenderer(container, opts);\n}\n","/**\n * PickerController — the single, framework-agnostic buyer-picker core.\n *\n * Consolidates the transport + booking logic that was copy-pasted across\n * sdk/src/SeatingChart.ts, src/pages/PublicEventPage.tsx and PickerPage.tsx:\n * fetch the published chart, mount the Konva renderer, seed statuses from a REST\n * snapshot, keep them live over a WebSocket (reconnect w/ backoff, re-snapshot on\n * every open), and run the hold → book state machine (best-available, hold reuse,\n * per-label partial release, 409 semantics, server-authoritative hold expiry).\n *\n * The SDK, the live buyer page, and the demo picker all drive this one class;\n * presentation (confirm card, legend, cart, etc.) lives in the consumers.\n *\n * Transport is injected (PickerTransport) so the SDK can use its CORS-trivial\n * PubApi while the dashboard uses an adapter over src/lib/api.ts.\n */\nimport { createRenderer } from '../engine/SeatmapRenderer';\nimport { expandChart } from '../core/layout';\nimport type {\n ChartDoc,\n ExpandedSeat,\n ISeatmapRenderer,\n RendererCallbacks,\n SeatStatus,\n} from '../core/types';\n\nconst DEFAULT_MAX_SELECTION = 10;\nconst MAX_BACKOFF_MS = 15_000;\n\nexport interface PickerSeat {\n id: string;\n label: string;\n categoryKey: string;\n price: number;\n}\n\nexport interface HoldConflict {\n label: string;\n reason: string;\n}\n\n/** An open hold — its id, the labels it covers, and the server's expiry time (ms epoch). */\nexport interface HoldInfo {\n holdId: string;\n labels: string[];\n expiresAt: number;\n}\n\ninterface HoldResponse {\n holdId: string;\n expiresAt: number;\n}\ninterface BestAvailableResponse extends HoldResponse {\n labels: string[];\n}\n\n/** Swappable public-surface transport (SDK PubApi or a dashboard `api.pub.*` adapter). */\nexport interface PickerTransport {\n chart(key: string): Promise<{\n doc: ChartDoc;\n event: { key: string; name: string; salesClosed?: boolean; venue?: string | null; startsAt?: number | null };\n }>;\n objects(key: string): Promise<{ seats: Record<string, string> }>;\n hold(key: string, labels: string[]): Promise<HoldResponse>;\n bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;\n release(key: string, labels: string[], holdId: string): Promise<unknown>;\n /** Optional — the SDK omits booking (it hands the holdId to the host page). */\n book?(key: string, labels: string[], holdId: string, bookingRef: string): Promise<unknown>;\n socketUrl(key: string): string;\n}\n\nexport interface PickerCallbacks extends RendererCallbacks {\n /** Selection changed (manual clicks or a server best-available pick). */\n onSelectionChange?: (seats: PickerSeat[]) => void;\n /** A hold opened (manual hold or best-available). */\n onHold?: (hold: HoldInfo) => void;\n /** The open hold expired server-side (the controller has already released it). */\n onHoldExpired?: () => void;\n /** A booking completed with this ref. */\n onBook?: (bookingRef: string) => void;\n /** Any live seat-status change arrived (delta or snapshot) — e.g. to recount \"N left\". */\n onStatusChange?: () => void;\n /** The server declared the event closed (a 409 event_closed). */\n onSalesClosed?: () => void;\n onError?: (err: unknown) => void;\n}\n\nexport interface PickerOptions extends PickerCallbacks {\n transport: PickerTransport;\n eventKey: string;\n maxSelection?: number;\n /** Renderer confirm-card mode (host shows a confirm popover instead of instant cart add). */\n confirmSelection?: boolean;\n /** Flash a pulse when a seat we didn't touch goes free→taken (live-activity cue). */\n flashOnLiveChange?: boolean;\n}\n\n/** Read `status`/`conflicts`/`reason` off any thrown error without importing a specific ApiError. */\nfunction errInfo(err: unknown): { status?: number; conflicts?: HoldConflict[]; reason?: string } {\n const e = (err ?? {}) as { status?: number; conflicts?: HoldConflict[]; reason?: string };\n return { status: e.status, conflicts: e.conflicts, reason: e.reason };\n}\n\n/** DO seat status → renderer status ('blocked' has no renderer analogue → 'not_for_sale'). */\nfunction mapStatus(s: string): SeatStatus {\n if (s === 'blocked') return 'not_for_sale';\n if (s === 'held' || s === 'booked' || s === 'free' || s === 'not_for_sale') return s;\n return 'free';\n}\n\nexport class PickerController {\n private readonly opts: PickerOptions;\n private readonly api: PickerTransport;\n private readonly key: string;\n private readonly maxSelection: number;\n\n private renderer: ISeatmapRenderer | null = null;\n private _doc: ChartDoc | null = null;\n\n /** label ⇄ id maps — backend speaks labels, the engine speaks ids. */\n private labelToId = new Map<string, string>();\n private labelToSeat = new Map<string, ExpandedSeat>();\n private allIds: string[] = [];\n\n // realtime socket\n private ws: WebSocket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private closed = false;\n\n // hold state\n private hold_: HoldInfo | null = null;\n private expiryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: PickerOptions) {\n this.opts = options;\n this.api = options.transport;\n this.key = options.eventKey;\n this.maxSelection = options.maxSelection ?? DEFAULT_MAX_SELECTION;\n }\n\n get doc(): ChartDoc | null {\n return this._doc;\n }\n currentHold(): HoldInfo | null {\n return this.hold_;\n }\n getRenderer(): ISeatmapRenderer | null {\n return this.renderer;\n }\n seatByLabel(label: string): ExpandedSeat | undefined {\n return this.labelToSeat.get(label);\n }\n idForLabel(label: string): string | undefined {\n return this.labelToId.get(label);\n }\n\n /** Fetch chart, build label maps, mount the renderer, seed statuses, go live. */\n async render(host: HTMLDivElement): Promise<{\n doc: ChartDoc;\n salesClosed: boolean;\n eventName: string;\n venue?: string | null;\n startsAt?: number | null;\n } | null> {\n if (this.renderer) return null; // already rendered — never mount twice on one controller\n this.closed = false;\n let res;\n try {\n res = await this.api.chart(this.key);\n } catch (err) {\n this.emitError(err);\n return null;\n }\n // destroy() may have run while the chart fetch was in flight (StrictMode\n // double-mount, or a fast key change) — bail before mounting anything.\n if (this.closed) return null;\n this._doc = res.doc;\n\n this.labelToId = new Map();\n this.labelToSeat = new Map();\n this.allIds = [];\n for (const s of expandChart(res.doc)) {\n this.labelToId.set(s.label, s.id);\n this.labelToSeat.set(s.label, s);\n this.allIds.push(s.id);\n }\n\n const renderer = createRenderer(host, {\n maxSelection: this.maxSelection,\n confirmSelection: this.opts.confirmSelection,\n onSelect: (seat) => {\n this.opts.onSelect?.(seat);\n this.emitSelectionChange();\n },\n onDeselect: (seat) => {\n this.opts.onDeselect?.(seat);\n this.emitSelectionChange();\n },\n onHover: this.opts.onHover,\n onFocusSeat: this.opts.onFocusSeat,\n onViewChange: this.opts.onViewChange,\n onGAClick: this.opts.onGAClick,\n onFps: this.opts.onFps,\n });\n if (this.closed) {\n renderer.destroy(); // destroyed during createRenderer — don't leak the stage\n return null;\n }\n this.renderer = renderer;\n renderer.setChart(res.doc);\n\n await this.resnapshot();\n this.connect();\n return {\n doc: res.doc,\n salesClosed: !!res.event.salesClosed,\n eventName: res.event.name,\n venue: res.event.venue,\n startsAt: res.event.startsAt,\n };\n }\n\n // ---- selection ------------------------------------------------------------\n\n getSelection(): PickerSeat[] {\n if (!this.renderer) return [];\n return this.renderer.getSelection().map((s) => this.toSeat(s));\n }\n clearSelection(): void {\n this.renderer?.clearSelection();\n this.emitSelectionChange();\n }\n deselect(ids: string[]): void {\n this.renderer?.deselect(ids);\n this.emitSelectionChange();\n }\n\n // ---- booking machine ------------------------------------------------------\n\n /**\n * Hold the current selection (or a given label set). The controller does the\n * renderer/hold side (409 → deselect + repaint the taken seats held) and then\n * re-throws so the caller can choose the banner copy. Returns null only when\n * there's nothing to hold.\n */\n async hold(labelsArg?: string[]): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n if (!labels.length) return null;\n\n // Reuse an existing hold that exactly covers this selection (re-holding 409s).\n if (this.hold_ && this.holdCovers(labels)) return this.hold_;\n\n try {\n const result = await this.api.hold(this.key, labels);\n this.setHold({ holdId: result.holdId, labels: [...labels], expiresAt: result.expiresAt });\n return this.hold_;\n } catch (err) {\n this.handle409Conflicts(err);\n throw err;\n }\n }\n\n /** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n // Drop any prior auto-hold first.\n if (this.hold_) await this.release();\n try {\n const result = await this.api.bestAvailable(this.key, qty, categoryKey);\n r.clearSelection();\n const ids = result.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) r.setStatus(ids, 'held');\n this.setHold({ holdId: result.holdId, labels: [...result.labels], expiresAt: result.expiresAt });\n const seats = result.labels\n .map((l) => this.labelToSeat.get(l))\n .filter((s): s is ExpandedSeat => !!s)\n .map((s) => this.toSeat(s));\n this.opts.onSelectionChange?.(seats);\n return this.hold_;\n } catch (err) {\n const { status, reason } = errInfo(err);\n if (status === 409 && reason === 'event_closed') this.opts.onSalesClosed?.();\n throw err;\n }\n }\n\n /**\n * Complete a booking. Requires a transport that supports book() (the SDK\n * deliberately does not). `bookingRef` MUST be a real reference from the caller.\n * `labelsArg` lets the caller book its own cart (the live page's confirm-flow\n * cart can hold best-available seats that aren't in the renderer selection);\n * defaults to the renderer selection. Reuses an existing exact-match hold, else\n * holds first. Returns the labels booked, or null on failure (conflicts painted).\n */\n async book(bookingRef: string, labelsArg?: string[]): Promise<string[] | null> {\n const r = this.renderer;\n if (!r) return null;\n if (!this.api.book) throw new Error('picker: transport has no book() — hold-only mode');\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n if (!labels.length) return null;\n\n let holdId: string | undefined;\n try {\n if (this.hold_ && this.holdCovers(labels)) {\n holdId = this.hold_.holdId; // already held server-side — re-holding would 409\n } else {\n const h = await this.api.hold(this.key, labels);\n holdId = h.holdId;\n this.setHold({ holdId, labels: [...labels], expiresAt: h.expiresAt });\n }\n await this.api.book(this.key, labels, holdId, bookingRef);\n } catch (err) {\n const { status, conflicts, reason } = errInfo(err);\n this.clearHold();\n if (status === 409 && reason === 'event_closed') {\n this.opts.onSalesClosed?.();\n } else if (status === 409 && conflicts?.length) {\n // Paint the taken seats, deselect them, release the still-free remainder.\n const takenLabels = new Set(conflicts.map((c) => c.label));\n const takenIds = [...takenLabels].map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.setStatus(takenIds, 'booked');\n r.deselect(takenIds);\n }\n const stillFree = labels.filter((l) => !takenLabels.has(l));\n if (stillFree.length && holdId) void this.api.release(this.key, stillFree, holdId).catch(() => {});\n this.emitSelectionChange();\n } else if (holdId) {\n // Non-conflict failure after a hold landed — release it so seats aren't stranded.\n void this.api.release(this.key, labels, holdId).catch(() => {});\n }\n throw err;\n }\n // Success — optimistically paint booked, deselect just the booked seats\n // (not the whole selection — the cart may be an explicit subset), clear hold.\n const ids = labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n r.setStatus(ids, 'booked');\n r.deselect(ids);\n }\n this.clearHold();\n this.emitSelectionChange();\n this.opts.onBook?.(bookingRef);\n return labels;\n }\n\n /** Release the whole open hold (if any), repaint those seats free. */\n async release(): Promise<void> {\n const hold = this.hold_;\n if (!hold) return;\n this.clearHold();\n const ids = hold.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) this.renderer?.setStatus(ids, 'free');\n try {\n await this.api.release(this.key, hold.labels, hold.holdId);\n } catch (err) {\n this.emitError(err);\n }\n }\n\n /**\n * Release just some labels from the open hold, keeping the rest held (used when\n * a buyer removes one seat chip). Clears the hold entirely once it empties.\n */\n async releaseLabels(labels: string[]): Promise<void> {\n const hold = this.hold_;\n if (!hold) return;\n const drop = labels.filter((l) => hold.labels.includes(l));\n if (!drop.length) return;\n const remaining = hold.labels.filter((l) => !drop.includes(l));\n if (remaining.length) this.setHold({ ...hold, labels: remaining });\n else this.clearHold();\n const ids = drop.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) this.renderer?.setStatus(ids, 'free');\n try {\n await this.api.release(this.key, drop, hold.holdId);\n } catch (err) {\n this.emitError(err);\n }\n }\n\n // ---- renderer proxies (so consumers don't reach through) ------------------\n\n setStatus(ids: string[], status: SeatStatus): void {\n this.renderer?.setStatus(ids, status);\n }\n getStatus(id: string): SeatStatus | undefined {\n return this.renderer?.getStatus(id);\n }\n flashSeat(id: string, color?: string): void {\n this.renderer?.flashSeat(id, color);\n }\n zoomIn(): void {\n this.renderer?.zoomIn();\n }\n zoomOut(): void {\n this.renderer?.zoomOut();\n }\n zoomToFit(): void {\n this.renderer?.zoomToFit();\n }\n worldToScreen(p: { x: number; y: number }): { x: number; y: number } {\n return this.renderer?.worldToScreen(p) ?? { x: 0, y: 0 };\n }\n setAccessibilityFilter(types: string[] | null): void {\n this.renderer?.setAccessibilityFilter?.(types as never);\n }\n\n destroy(): void {\n this.closed = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n /* ignore */\n }\n this.ws = null;\n }\n this.renderer?.destroy();\n this.renderer = null;\n }\n\n // ---- internals ------------------------------------------------------------\n\n private toSeat(s: ExpandedSeat): PickerSeat {\n return { id: s.id, label: s.label, categoryKey: s.categoryKey, price: this.priceFor(s.categoryKey) };\n }\n private priceFor(categoryKey: string): number {\n return this._doc?.categories.find((c) => c.key === categoryKey)?.price ?? 0;\n }\n private emitSelectionChange(): void {\n this.opts.onSelectionChange?.(this.getSelection());\n }\n private emitError(err: unknown): void {\n if (this.opts.onError) this.opts.onError(err);\n else console.error('[picker]', err);\n }\n\n private holdCovers(labels: string[]): boolean {\n const h = this.hold_;\n return !!h && h.labels.length === labels.length && labels.every((l) => h.labels.includes(l));\n }\n\n private handle409Conflicts(err: unknown): void {\n const { status, conflicts } = errInfo(err);\n if (status !== 409 || !conflicts?.length) return;\n const r = this.renderer;\n if (!r) return;\n const takenIds = conflicts.map((c) => this.labelToId.get(c.label)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.deselect(takenIds);\n r.setStatus(takenIds, 'held');\n }\n this.emitSelectionChange();\n }\n\n /** Set the open hold + (re)arm the server-authoritative expiry timer. */\n private setHold(hold: HoldInfo): void {\n this.hold_ = hold;\n if (this.expiryTimer) clearTimeout(this.expiryTimer);\n const ms = Math.max(0, hold.expiresAt - Date.now());\n this.expiryTimer = setTimeout(() => this.onHoldExpired(), ms);\n this.opts.onHold?.(hold);\n }\n private clearHold(): void {\n this.hold_ = null;\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n }\n private onHoldExpired(): void {\n const hold = this.hold_;\n this.clearHold();\n if (hold) {\n const ids = hold.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) this.renderer?.setStatus(ids, 'free');\n }\n this.opts.onHoldExpired?.();\n }\n\n private applySeatsMap(seats: Record<string, string>): void {\n const r = this.renderer;\n if (!r) return;\n if (this.allIds.length) r.setStatus(this.allIds, 'free');\n const byStatus: Record<SeatStatus, string[]> = { free: [], held: [], booked: [], not_for_sale: [] };\n for (const [label, st] of Object.entries(seats)) {\n const id = this.labelToId.get(label);\n if (id) byStatus[mapStatus(st)].push(id);\n }\n (['held', 'booked', 'not_for_sale'] as SeatStatus[]).forEach((st) => {\n if (byStatus[st].length) r.setStatus(byStatus[st], st);\n });\n this.opts.onStatusChange?.();\n }\n\n private async resnapshot(): Promise<void> {\n try {\n const objs = await this.api.objects(this.key);\n this.applySeatsMap(objs.seats);\n } catch {\n /* transient — the socket delta stream keeps us fresh */\n }\n }\n\n // ---- realtime socket ------------------------------------------------------\n\n private connect(): void {\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key));\n } catch {\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n\n ws.onopen = () => {\n this.attempt = 0;\n void this.resnapshot();\n };\n ws.onmessage = (e) => {\n let msg: unknown;\n try {\n msg = JSON.parse(typeof e.data === 'string' ? e.data : '');\n } catch {\n return;\n }\n const r = this.renderer;\n if (!r || !msg || typeof msg !== 'object') return;\n const m = msg as { seats?: Record<string, string>; changes?: { label: string; status: string }[] };\n if (m.seats && typeof m.seats === 'object') {\n this.applySeatsMap(m.seats);\n } else if (Array.isArray(m.changes)) {\n for (const ch of m.changes) {\n const id = this.labelToId.get(ch.label);\n if (!id) continue;\n const next = mapStatus(ch.status);\n // Flash a live free→taken change — but not the buyer's OWN just-held\n // seats (a manual hold leaves them 'free' locally, so the server's\n // held-delta would otherwise flash them as if someone else grabbed them).\n if (\n this.opts.flashOnLiveChange &&\n next !== 'free' &&\n r.getStatus(id) === 'free' &&\n !this.hold_?.labels.includes(ch.label)\n ) {\n r.flashSeat(id);\n }\n r.setStatus([id], next);\n }\n this.opts.onStatusChange?.();\n }\n };\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.scheduleReconnect();\n };\n ws.onerror = () => {\n try {\n ws.close();\n } catch {\n /* onclose drives reconnect */\n }\n };\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnectTimer) return;\n const attempt = Math.min(this.attempt++, 5);\n const delay = Math.min(1000 * 2 ** attempt, MAX_BACKOFF_MS);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seatlayer/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-agnostic seat-rendering engine (Konva) shared by the SeatLayer SDKs.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": ["dist"],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"typecheck": "tsc --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"konva": "^10.3.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsup": "^8.5.1",
|
|
28
|
+
"typescript": "^5.9.0"
|
|
29
|
+
}
|
|
30
|
+
}
|