Skip to content

Schema, validation, generators · Browser + Node

@openseat/core

Framework-independent layout schema, validation, geometry and generators for OpenSeat.

Layout schema, validation, serialisation, migrations, geometry, generators and layout operations for OpenSeat. No React, Konva, DOM or network dependencies; runs in browsers, Node and workers.

  • 210 functions
  • 2 classes
  • 88 interfaces
  • 53 types
  • 64 constants
  • MIT
npm i @openseat/core
first npm release pending

Install commands show the public npm names. The first npm release is pending; the packages are free and MIT licensed.

depends on zod

Import
import {
  validateLayout,
  generateStraightRows,
  generateCurvedRows,
  arenaPreset,
  createLayout,
} from "@openseat/core";

Functions210

function

addSeatsToRow

Moves seats into a row, detaching them from other rows and tables first. They are inserted at atIndex of seatObjectIds, or by their position along the row when omitted. The row is refitted (no seat moves); it stays freeform when no line or arc fits.

function addSeatsToRow(
  layout: LayoutDocument,
  rowId: string,
  seatIds: readonly string[],
  atIndex?: number,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
seatIdsreadonly string[]
atIndexoptionalnumber

Returns

@openseat/core/src/row-ops.ts

function

ancestorsOf

Ancestors of an object, nearest first (e.g. a grouped seat: [row, section]).

function ancestorsOf(index: LayoutIndex, id: string): string[];

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

string[]

@openseat/core/src/membership.ts

function

annularSectorPoints

The outline of a ring segment between two radii and two angles: the outer arc from startAngle to endAngle, then the inner arc back from endAngle to startAngle. An inner radius of 0 or less closes the wedge at the centre instead.

function annularSectorPoints(
  options: AnnularSectorOptions,
): Point[];

Parameters

ParameterTypeDescription
optionsAnnularSectorOptions

options takes AnnularSectorOptions:

Returns

@openseat/core/src/generators/shapes.ts

function

applySectionSeating

(Re)generates a section's rows and seats from parametric seating, keeping identities:

  • Existing rows are taken front to back (rowOrder, else geometrically) and row r keeps its object ID, other fields and label (unless relabel, or the row count changes while every row is still labelled as the section's rowLabeling numbers it: then all rows follow it). Its seats keep their object and public IDs by slot; holes (deleted seats) below the new slot count stay holes; labels follow the seat labeling except for labelLocked seats (or with keepLabels).
  • Surplus rows and seats are removed and reported; new rows get fresh IDs and labels that do not collide with the kept rows.
  • The section stores seating, its rowOrder, and, when its outline is "auto", an outline recomputed from the seats.

Without seating, the section's current seating is re-applied. Throws a RangeError when the section is missing or the seating is invalid.

function applySectionSeating(
  layout: LayoutDocument,
  sectionId: string,
  seating?: SectionSeating,
  opts?: ApplySectionSeatingOptions,
): SectionSeatingResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring
seatingoptionalSectionSeating
optsoptionalApplySectionSeatingOptions

Default {}

Returns

@openseat/core/src/section-ops.ts

function

arenaPreset

Ready-made arenas, each with its ARENA_PRESET_TITLES title:

  • "hockey": a 1160 x 540 rink (corner radius 110) in a bowl of about 9,800 seats, numbered clockwise from the top-left corner like a typical NHL arena: a 16-row lower bowl 101-119 (three straight blocks per long side, two per short end, two fans per corner and a third in the top-left, so 101, 118 and 119 share that corner), a ring of single-row 200-level boxes 201-232, and an 18-row upper bowl 301-321 in the same pattern with four blocks per long side. Every short-end section is 7 seats wide.
  • "basketball": a smaller court with fully rounded ends and two levels of sections along the sidelines and around the ends.
  • "concert-in-round": a round centre stage with fan sections all around.
  • "football": a large pitch with square corners, two tiers of sections on every side and a single fan section in each corner.
function arenaPreset(name: ArenaPresetName): ArenaPreset;

Parameters

ParameterTypeDescription
nameArenaPresetName

Returns

Example

arena.ts
import { arenaPreset, createArenaLayout, estimateArenaSeats } from "@openseat/core";

const options = { ...arenaPreset("hockey"), idPrefix: "a", center: { x: 0, y: 0 } };
console.log(estimateArenaSeats(options)); // 9758, exact and effectively free

const arena = createArenaLayout({ ...options, layoutId: "arena" });
// Presets: "hockey" | "basketball" | "concert-in-round" | "football"

Recipe: an arena in one call

@openseat/core/src/generators/arena.ts

function

assignSeatsToSection

Assigns objects inside a section's boundary to it. Rows and tables move as a whole: one joins when at least half of its seats are inside (an exact half is decided by the seats' centroid). Loose seats go by their centre and GA areas by their centroid. Seat caches are updated. With mode: "sync", members of this section that now lie fully outside it leave it. count is the number of seats whose centre is inside the boundary.

function assignSeatsToSection(
  layout: LayoutDocument,
  sectionId: string,
  opts?: { readonly mode?: "add" | "sync" },
): { layout: LayoutDocument; count: number };

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring
optsoptional{ readonly mode?: "add" | "sync"; }

Default {}

Returns

{ layout: LayoutDocument; count: number; }

@openseat/core/src/operations.ts

function

autoAssignSections

Tags untagged rows, tables, loose seats and GA areas among ids with the section under their centre (seat centroid for groups, boundary centroid for GA areas). Objects already in a section are left alone.

function autoAssignSections(
  layout: LayoutDocument,
  ids: readonly string[],
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]

Returns

@openseat/core/src/operations.ts

function

blockCurvatureRange

The exact curvature range applySectionSeating accepts for a block seating, row by row: per-row lengths (rowSeats), aisles and the row's own radius are all taken into account, so it is never stricter or looser than the check itself. min is in [-100, 0] and max in [0, 100]; bound a block's curvature slider with them. minBlockCurvature and maxBlockCurvature are the uniform-row shortcuts for a block that does not exist yet.

function blockCurvatureRange(
  seating: Pick<
    BlockSeating,
    | "rows"
    | "rowSpacing"
    | "seatSpacing"
    | "seatsPerRow"
    | "rowSeats"
    | "aisles"
    | "aisleWidth"
  >,
): { readonly min: number; readonly max: number };

Parameters

ParameterTypeDescription
seatingPick<BlockSeating, "rows" | "rowSpacing" | "seatSpacing" | "seatsPerRow" | "rowSeats" | "aisles" | "aisleWidth">

Returns

{ readonly min: number; readonly max: number; }

@openseat/core/src/section-ops.ts

function

boundsContain

True when inner lies entirely inside outer (edges may touch).

function boundsContain(outer: Bounds, inner: Bounds): boolean;

Parameters

ParameterTypeDescription
outerBounds
innerBounds

Returns

boolean

@openseat/core/src/geometry.ts

function

boundsIntersect

True when the rectangles overlap or touch.

function boundsIntersect(a: Bounds, b: Bounds): boolean;

Parameters

ParameterTypeDescription
aBounds
bBounds

Returns

boolean

@openseat/core/src/geometry.ts

function

boxesOverlap

Strictly overlapping by more than tolerance on both axes; touching boxes do not overlap.

function boxesOverlap(
  a: Bounds,
  b: Bounds,
  tolerance?: number,
): boolean;

Parameters

ParameterTypeDescription
aBounds
bBounds
toleranceoptionalnumber

Default 0

Returns

boolean

@openseat/core/src/label-layout.ts

function

buildArcSection

Builds an arc (wedge) section without adding it: concentric rows between two angles around center, outer rows holding more seats. The section's origin is the area centroid of its ring-segment outline (rotation 0), and the seating stores the centre relative to it; the outline is "auto".

function buildArcSection(
  layout: LayoutDocument,
  params: ArcSectionParams,
): { objects: LayoutObject[]; sectionId: string };

Parameters

ParameterTypeDescription
layoutLayoutDocument
paramsArcSectionParams

Returns

{ objects: LayoutObject[]; sectionId: string; }

@openseat/core/src/section-ops.ts

function

buildBlockSection

Builds a parametric block section (rows x seats, optionally curved, ragged or staggered) without adding it: the section followed by each row's seats and the row. IDs are unique against layout. Used for drawing previews; createBlockSection adds the result.

function buildBlockSection(
  layout: LayoutDocument,
  params: BlockSectionParams,
): { objects: LayoutObject[]; sectionId: string };

Parameters

ParameterTypeDescription
layoutLayoutDocument
paramsBlockSectionParams

Returns

{ objects: LayoutObject[]; sectionId: string; }

@openseat/core/src/section-ops.ts

function

buildInventoryManifest

Builds the inventory manifest of a layout.

  • A seat's effective section is its group's sectionId (row or table; the source of truth), else its own; only sections that exist count. Row and table come from the group that owns the seat.
  • Seats appear in document order; positions are rounded to 3 decimals.
  • Areas: every GA area; booths only when they have an inventoryId (capacity 1); tables with bookAsWhole (kind "table", capacity = seats); zone sections (showSeats: false) as kind "ga" with objectType: "section", seated: true, inventory ID = the section ID and their zone capacity. The seats, and whole tables, inside a zone section are not sold on their own and are left out of seats and areas.
  • Hidden objects are included, whether hidden themselves or through a hidden row, table or section: visibility is an editing and drawing state, not an inventory change, so hiding a section does not drop its seats from the host's inventory. The booking SDK refuses hidden seats.

Optional fields are omitted rather than undefined, so the manifest serialises compactly and compares equal after a JSON round trip.

function buildInventoryManifest(
  layout: LayoutDocument,
): InventoryManifest;

Parameters

ParameterTypeDescription
layoutLayoutDocument

layout takes LayoutDocument:

Returns

Example

save-layout.ts
import { buildInventoryManifest, diffManifests, validateLayout } from "@openseat/core";

const result = validateLayout(body.layout); // never trust the client's layout
if (!result.valid || !result.layout) throw new Error("invalid layout"); // result.errors says why
const next = buildInventoryManifest(result.layout);
const { removedSeatIds } = diffManifests(previousManifest, next);
// Refuse the save if any removed seat is held or sold for a live event.

Your backend: the REST contract

@openseat/core/src/manifest.ts

function

buildSectionContents

Generates the rows and seats of a section from its seating, without touching any document. Row r (0 = front) gets the ID ${prefix}:r${r+1}, its slot k the seat object ID ${prefix}:r${r+1}:s${k+1} and the public seat ID ${section.label}-${rowLabel}-${seatLabel} (made unique against existing). Row labels follow section.rowLabeling (A, B, C… by default), seat labels the seating's seatLabeling. Seats take the section's category. Throws a RangeError when the section has no seating or the seating is invalid.

function buildSectionContents(
  section: Section,
  opts?: BuildSectionContentsOptions,
): SectionContents;

Parameters

ParameterTypeDescription
sectionSection
optsoptionalBuildSectionContentsOptions

Default {}

Returns

@openseat/core/src/section-ops.ts

function

centredRectCorners

Corners of a width × height rectangle centred on the object's origin, in world space.

function centredRectCorners(
  width: number,
  height: number,
  placement: { position: Point; rotation: number },
): Point[];

Parameters

ParameterTypeDescription
widthnumber
heightnumber
placement{ position: Point; rotation: number; }

Returns

@openseat/core/src/object-geometry.ts

function

checkStructure

Reports structural problems: shared or repeated group members, stale seat caches, duplicate labels, empty rows, uncategorised seats, and invalid parametric fields (row layout, section row order and seating).

Reference checks (dangling IDs) and geometry checks stay in validateLayout; this function assumes nothing about them and skips references it cannot resolve.

function checkStructure(doc: LayoutDocument): {
  errors: LayoutIssue[];
  warnings: LayoutIssue[];
};

Parameters

ParameterTypeDescription
docLayoutDocument

doc takes LayoutDocument:

Returns

{ errors: LayoutIssue[]; warnings: LayoutIssue[]; }

@openseat/core/src/structure-checks.ts

function

cloneForClipboard

Deep-copies the objects of ids (expanded recursively) and the categories they reference into a clipboard payload. Null when nothing is copied.

function cloneForClipboard(
  layout: LayoutDocument,
  ids: readonly string[],
): ClipboardPayload | null;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]

Returns

@openseat/core/src/operations.ts

function

convertToSection

Turns a polygon into a section in place: same ID, outline, placement, layer flags, category, fill and stroke; the label is the next free section label. Throws a RangeError when polygonId is not a polygon.

function convertToSection(
  layout: LayoutDocument,
  polygonId: string,
): { layout: LayoutDocument; sectionId: string };

Parameters

ParameterTypeDescription
layoutLayoutDocument
polygonIdstring

Returns

{ layout: LayoutDocument; sectionId: string; }

@openseat/core/src/section-ops.ts

function

convexHull

Convex hull by Andrew's monotone chain. Returns the hull vertices without a repeated closing point and without collinear points along edges. Fewer than three distinct input points are returned as they are (deduplicated).

function convexHull(points: readonly Point[]): Point[];

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

@openseat/core/src/geometry.ts

function

createArenaLayout

A complete arena layout document: generateArena's objects, venue and categories in a new layout whose focal point is the field centre. When the venue would reach past the top or left canvas edge, everything is moved (by whole grid cells) to make room, and the canvas grows to fit the venue and every object.

function createArenaLayout(
  options: CreateArenaLayoutOptions,
): LayoutDocument;

Parameters

ParameterTypeDescription
optionsCreateArenaLayoutOptions

options takes CreateArenaLayoutOptions:

Returns

@openseat/core/src/generators/arena.ts

function

createBlockSection

buildBlockSection plus adding the objects to the layout.

function createBlockSection(
  layout: LayoutDocument,
  params: BlockSectionParams,
): { layout: LayoutDocument; sectionId: string };

Parameters

ParameterTypeDescription
layoutLayoutDocument
paramsBlockSectionParams

Returns

{ layout: LayoutDocument; sectionId: string; }

Example

hall.ts
import { createLayout, createBlockSection, updateSectionSeating, validateLayout } from "@openseat/core";

const empty = createLayout({
  id: "hall",
  name: "Main hall",
  width: 1200,
  height: 800,
  categories: [{ id: "general", name: "General", colour: "#2563EB" }], // "colour", not "color"
});

const { layout, sectionId } = createBlockSection(empty, {
  position: { x: 600, y: 400 },
  categoryId: "general",
  seating: {
    kind: "block",
    rows: 10,
    seatsPerRow: 20,
    seatSpacing: 24,
    rowSpacing: 30,
    curvature: 20, // -100..100; > 0 arcs around the stage in front
    align: "center",
    aisles: [10],
    aisleWidth: 30,
    seatShape: { kind: "circle", radius: 9 },
    seatLabeling: { format: "numeric", start: 1, step: 1, direction: "ltr" },
  },
});

// Change a parameter later: seats that still have a slot keep their IDs.
const { layout: bigger, report } = updateSectionSeating(layout, sectionId, { rows: 14, curvature: 35 });
console.log(validateLayout(bigger).valid, report.removedSeatIds); // true []

Recipe: generate sections

@openseat/core/src/section-ops.ts

function

createDivider

A new floor divider (not yet added): an open path through the world points (at least 2), 1 unit wide, with caption (trimmed; left out when empty) drawn on it as "▾ CAPTION ▾". Throws a RangeError for fewer than 2 points.

function createDivider(
  layout: LayoutDocument,
  points: readonly Point[],
  caption: string,
): CustomPath;

Parameters

ParameterTypeDescription
layoutLayoutDocument
pointsreadonly Point[]
captionstring

Returns

@openseat/core/src/zone-ops.ts

function

createFootnote

A new footnote label (not yet added) centred at at: 12 units, bold, letter-spaced 0.08 em, in muted grey (#9e9e9e), such as "ALL THE SECTIONS ARE SEATED". Throws a RangeError for empty text.

function createFootnote(
  layout: LayoutDocument,
  at: Point,
  text: string,
): Label;

Parameters

ParameterTypeDescription
layoutLayoutDocument
atPoint
textstring

Returns

@openseat/core/src/zone-ops.ts

function

createId

Creates a random object ID. Does not depend on DOM typings.

function createId(prefix?: string): string;

Parameters

ParameterTypeDescription
prefixoptionalstring

Default "obj"

Returns

string

@openseat/core/src/ids.ts

function

createLayout

Creates an empty layout at the current schema version. The result is not validated; call validateLayout after adding objects.

function createLayout(options: CreateLayoutOptions): LayoutDocument;

Parameters

ParameterTypeDescription
optionsCreateLayoutOptions

options takes CreateLayoutOptions:

Returns

Example

hall.ts
import { createLayout, createBlockSection, updateSectionSeating, validateLayout } from "@openseat/core";

const empty = createLayout({
  id: "hall",
  name: "Main hall",
  width: 1200,
  height: 800,
  categories: [{ id: "general", name: "General", colour: "#2563EB" }], // "colour", not "color"
});

const { layout, sectionId } = createBlockSection(empty, {
  position: { x: 600, y: 400 },
  categoryId: "general",
  seating: {
    kind: "block",
    rows: 10,
    seatsPerRow: 20,
    seatSpacing: 24,
    rowSpacing: 30,
    curvature: 20, // -100..100; > 0 arcs around the stage in front
    align: "center",
    aisles: [10],
    aisleWidth: 30,
    seatShape: { kind: "circle", radius: 9 },
    seatLabeling: { format: "numeric", start: 1, step: 1, direction: "ltr" },
  },
});

// Change a parameter later: seats that still have a slot keep their IDs.
const { layout: bigger, report } = updateSectionSeating(layout, sectionId, { rows: 14, curvature: 35 });
console.log(validateLayout(bigger).valid, report.removedSeatIds); // true []

Recipe: generate sections

@openseat/core/src/factory.ts

function

createSectionFromSelection

Wraps the selected rows, tables, loose seats and GA areas (a selected seat stands for its row or table) in a new section with a custom outline around them, and makes them its members. The rows are ordered front to back (nearest the layout's focal point first when it has one). Returns sectionId: null and the same layout when the selection holds nothing that can join a section.

function createSectionFromSelection(
  layout: LayoutDocument,
  ids: readonly string[],
  opts?: SectionFromSelectionOptions,
): { layout: LayoutDocument; sectionId: string | null };

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
optsoptionalSectionFromSelectionOptions

Default {}

Returns

{ layout: LayoutDocument; sectionId: string | null; }

@openseat/core/src/section-ops.ts

function

createZone

A new GA zone (not yet added to the layout) with an object ID and an inventory ID unused in layout. rect, rounded and trapezoid zones are built from rect and centred on it; a polygon zone from points, its origin at their centroid. A rounded zone gets cornerRadius = min(w, h) × 0.12; a trapezoid keeps one edge w wide and insets the other by 15% on each side (bottom inset by default, top with flip). Throws a RangeError for a degenerate shape, a bad capacity or an empty label.

function createZone(
  opts: CreateZoneOptions,
  layout: LayoutDocument,
): GaArea;

Parameters

ParameterTypeDescription
optsCreateZoneOptions
layoutLayoutDocument

Returns

@openseat/core/src/zone-ops.ts

function

descendantsOf

Everything below an object: a section's rows, tables, GA areas and loose seats, each group followed by its seats; a row's or table's seats. Empty for other objects.

function descendantsOf(index: LayoutIndex, id: string): string[];

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

string[]

@openseat/core/src/membership.ts

function

dissolveSection

Removes a section but keeps its contents, which lose their sectionId.

function dissolveSection(
  layout: LayoutDocument,
  sectionId: string,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring

Returns

@openseat/core/src/section-ops.ts

function

distance

function distance(a: Point, b: Point): number;

Parameters

ParameterTypeDescription
aPoint
bPoint

Returns

number

@openseat/core/src/geometry.ts

function

distanceToSegment

Shortest distance from p to the segment ab.

function distanceToSegment(p: Point, a: Point, b: Point): number;

Parameters

ParameterTypeDescription
pPoint
aPoint
bPoint

Returns

number

@openseat/core/src/geometry.ts

function

distributeObjects

Spaces objects so their centres are evenly spread between the first and last. Needs three or more.

function distributeObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  axis: "x" | "y",
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
axis"x" | "y"

Returns

@openseat/core/src/operations.ts

function

distributeSeatsOnEdges

Spreads count seats over the four edges of a width x height table in proportion to the edge lengths (largest remainder method; ties go to the first edge clockwise from the top).

function distributeSeatsOnEdges(
  count: number,
  width: number,
  height: number,
): TableEdgeCounts;

Parameters

ParameterTypeDescription
countnumber
widthnumber
heightnumber

Returns

@openseat/core/src/table-ops.ts

function

dividerCaptionText

The text a divider draws for caption: upper-cased between two markers ("▾ GROUND FLOOR ▾").

function dividerCaptionText(caption: string): string;

Parameters

ParameterTypeDescription
captionstring

Returns

string

@openseat/core/src/object-geometry.ts

function

drawBand

function drawBand(type: LayoutObject["type"]): number;

Parameters

ParameterTypeDescription
typeLayoutObject["type"]

Returns

number

@openseat/core/src/object-geometry.ts

function

duplicateObjects

Copies objects, offset by offset. Sections are copied with their contents and rows and tables with their seats; the copies reference each other. Every copy gets a new object ID and every copied seat a new public seat ID (<old>-copy, then <old>-copy-2, …), so the result never has duplicates. Copies whose section was not copied keep it, unless opts.sectionId says otherwise.

function duplicateObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  offset: Point,
  opts?: DuplicateOptions,
): DuplicateResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
offsetPoint
optsoptionalDuplicateOptions

Default {}

Returns

@openseat/core/src/operations.ts

function

ellipsePoints

An ellipse of width x height centred on center, clockwise on screen from its rightmost point.

function ellipsePoints(
  width: number,
  height: number,
  segments?: number,
  center?: Point,
): Point[];

Parameters

ParameterTypeDescription
widthnumber
heightnumber
segmentsoptionalnumber

Default 48

centeroptionalPoint

Default { x: 0, y: 0 }

Returns

@openseat/core/src/generators/shapes.ts

function

ensureRowLayout

Writes a fitted layout to a row that has none, when the fit reproduces its seats within ROW_LAYOUT_FIT_TOLERANCE. Never moves seats. fitted is true when the row has a layout afterwards; residual is the fit error (0 for rows that already had a layout, Infinity for rows without seats).

function ensureRowLayout(
  layout: LayoutDocument,
  rowId: string,
): { layout: LayoutDocument; fitted: boolean; residual: number };

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring

Returns

{ layout: LayoutDocument; fitted: boolean; residual: number; }

@openseat/core/src/row-ops.ts

function

estimateArenaSeats

Seats generateArena would create for options, computed from the section plans without generating any seat (milliseconds even for invalid sizes). Exact for the generator's default sections; use it to warn about or reject oversized arenas before generating. Throws a GeneratorInputError for invalid options, including a row longer than ARENA_LIMITS.maxSeatsPerRow seats.

function estimateArenaSeats(options: ArenaOptions): number;

Parameters

ParameterTypeDescription
optionsArenaOptions

options takes ArenaOptions:

Returns

number

@openseat/core/src/generators/arena.ts

function

estimateArenaSections

Sections generateArena would create for options, without generating any seat. Sides too short for their sections are left empty, so this can be well below the requested counts (a round field has no straight sides). Throws a GeneratorInputError for invalid options.

function estimateArenaSections(options: ArenaOptions): number;

Parameters

ParameterTypeDescription
optionsArenaOptions

options takes ArenaOptions:

Returns

number

@openseat/core/src/generators/arena.ts

function

estimateTextBox

Conservative box of one line of text: `n × fontSize × (bold ? 0.68 : 0.62)

  • letterSpacing × fontSize × (n - 1)wide and1.2 × fontSizehigh, forn` characters. Wider than real text in common UI fonts, so a renderer that shrinks its measured text to fit this box can guarantee that what it draws stays inside what the label layout reserved.
function estimateTextBox(
  text: string,
  fontSize: number,
  opts?: TextBoxOptions,
): { width: number; height: number };

Parameters

ParameterTypeDescription
textstring
fontSizenumber
optsoptionalTextBoxOptions

Default {}

Returns

{ width: number; height: number; }

@openseat/core/src/object-geometry.ts

function

estimateTextSize

Approximate text box for a label. Exact metrics need a font engine, which core does not have; renderers measure real text, but core needs a stable estimate for hit testing and bounds that does not depend on the browser.

function estimateTextSize(
  text: string,
  fontSize: number,
): { width: number; height: number };

Parameters

ParameterTypeDescription
textstring
fontSizenumber

Returns

{ width: number; height: number; }

@openseat/core/src/object-geometry.ts

function

expandBounds

Expands bounds by amount on every side.

function expandBounds(b: Bounds, amount: number): Bounds;

Parameters

ParameterTypeDescription
bBounds
amountnumber

Returns

@openseat/core/src/geometry.ts

function

expandWithMembers

Adds everything that moves with the given objects, recursively. A section brings every row, table, GA area and loose seat (a seat in no row or table) whose sectionId is the section; a row or table brings its seats. Moving a table moves its chairs and moving a section moves its contents: this is the single place that rule is defined.

Output order: the known input IDs first (deduplicated), then the added members in document order (the iteration order of objectsById). Unknown IDs are ignored. One pass over the objects, so O(n) per call.

function expandWithMembers(
  ids: readonly string[],
  objectsById: ReadonlyMap<string, LayoutObject>,
): string[];

Parameters

ParameterTypeDescription
idsreadonly string[]
objectsByIdReadonlyMap<string, LayoutObject>

Returns

string[]

@openseat/core/src/object-geometry.ts

function

extendRow

Adds seats at one end of a row (count > 0) or trims them (count < 0). Seats already in the row stay where they are and keep their labels and seat IDs. Extending or trimming the start of a left-to-right numbered row shifts labeling.start so the new seats continue the numbers downwards when that stays at 1 or above; otherwise the new seats continue after the row's highest number, the row's labeling is removed (it keeps custom numbers) and the result's message says so. New seat IDs follow the row's pattern (prefix + label). Never produces label 0, a negative number or a duplicate.

function extendRow(
  layout: LayoutDocument,
  rowId: string,
  end: "start" | "end",
  count: number,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
end"start" | "end"
countnumber

Returns

@openseat/core/src/row-ops.ts

function

extractSeats

Takes seats out of their rows and tables (parametric rows keep holes, so nothing else moves). With asRow, the seats become a new row (ID row-N, label rowLabel or the next free label) with a fitted layout when one fits. Seats never move.

function extractSeats(
  layout: LayoutDocument,
  seatIds: readonly string[],
  opts?: { readonly asRow?: boolean; readonly rowLabel?: string },
): { layout: LayoutDocument; rowId: string | null };

Parameters

ParameterTypeDescription
layoutLayoutDocument
seatIdsreadonly string[]
optsoptional{ readonly asRow?: boolean; readonly rowLabel?: string; }

Default {}

Returns

{ layout: LayoutDocument; rowId: string | null; }

@openseat/core/src/row-ops.ts

function

findLabelSeatOverlaps

Text boxes (layoutTextBoxes) that overlap drawn seats (seatBoxes), one entry per text and seat, in text order. At "overview" no seats are drawn (the map shows filled sections), so only "detail" can report overlaps. The check behind the "no text over seats" gate.

function findLabelSeatOverlaps(
  layout: LayoutDocument,
  opts: LabelSeatOverlapOptions,
): LabelSeatOverlap[];

Parameters

ParameterTypeDescription
layoutLayoutDocument
optsLabelSeatOverlapOptions

Returns

@openseat/core/src/label-layout.ts

function

findRowLayoutDrift

Rows whose stored seat positions deviate from their layout by more than tolerance, with the largest deviation. Rows without a layout are skipped.

function findRowLayoutDrift(
  layout: LayoutDocument,
  tolerance?: number,
): { rowId: string; maxDeviation: number }[];

Parameters

ParameterTypeDescription
layoutLayoutDocument
toleranceoptionalnumber

Default ROW_LAYOUT_FIT_TOLERANCE

Returns

{ rowId: string; maxDeviation: number; }[]

@openseat/core/src/row-geometry.ts

function

fitCanvasToContent

Grows the canvas until every object fits inside it, with margin to spare. Content above or left of the origin is shifted (all objects together, locked ones included, with the venue outline and focal point) by a whole number of grid cells, so grid alignment survives. The canvas never shrinks; a layout that already fits is returned unchanged.

function fitCanvasToContent(
  layout: LayoutDocument,
  margin?: number,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
marginoptionalnumber

Default layout.canvas.gridSize * 4

Returns

@openseat/core/src/operations.ts

function

fitRowLayout

Fits a parametric layout to seats given in row order. Returns null for no seats. Tries a principal-axis line and a Kasa circle: the line wins when it fits within max(0.5, 2% of the median step) or the circle is nearly flat (radius above 50 times the extent); otherwise the circle wins when it fits within the same tolerance; otherwise the better of the two is returned with its residual. The placement is anchored at the first seat ("start") with the tangent pointing towards the second seat.

function fitRowLayout(seats: readonly Seat[]): RowLayoutFit | null;

Parameters

ParameterTypeDescription
seatsreadonly Seat[]

Returns

@openseat/core/src/row-geometry.ts

function

formatLabelIndex

Formats a label index. numeric: n >= 0; alpha: n >= 1 in spreadsheet order (1 = A, 26 = Z, 27 = AA); alpha-lower: the same in lowercase; roman: 1..3999, uppercase. Throws a RangeError when n is out of range.

function formatLabelIndex(n: number, format: LabelFormat): string;

Parameters

ParameterTypeDescription
nnumber
formatLabelFormat

Returns

string

@openseat/core/src/labeling.ts

function

generateArena

Generates a concentric arena: the field and every tier's sections with their rows and seats, a venue outline and per-tier categories. Section k of a tier (in numbering order) is labelled firstNumber + k; its ID is ${idPrefix}-sec-${label} and its rows and seats follow buildSectionContents (${sectionId}:r1, ${sectionId}:r1:s1, seat IDs ${label}-${row}-${seat}). The field is a stage with the field kind's style and markings. Throws a GeneratorInputError for invalid options, beyond ARENA_LIMITS, or when estimateArenaSeats exceeds ARENA_LIMITS.maxSeats.

function generateArena(options: ArenaOptions): GeneratedArena;

Parameters

ParameterTypeDescription
optionsArenaOptions

options takes ArenaOptions:

Returns

@openseat/core/src/generators/arena.ts

function

generateCurvedRows

Generates concentric arc rows. Seats are spaced evenly by angle within each row, or by arc length when seatSpacing is given. Each row gets a parametric layout whose signed radius reproduces the generated seats.

function generateCurvedRows(
  options: CurvedRowsOptions,
): GeneratedRows;

Parameters

ParameterTypeDescription
optionsCurvedRowsOptions

options takes CurvedRowsOptions:

Returns

Example

amphitheatre.ts
import { createLayout, generateCurvedRows, validateLayout } from "@openseat/core";

const layout = createLayout({ id: "amphi", name: "Amphitheatre", width: 1200, height: 900 });
layout.objects = generateCurvedRows({
  idPrefix: "bowl", // unique per generated block
  rowCount: 8,
  seatsPerRow: 24,
  center: { x: 600, y: 120 }, // the stage
  innerRadius: 220,
  rowSpacing: 34,
  startAngle: 30, // degrees: 0 points right, 90 points down
  endAngle: 150,
  tangentRotation: true, // seats face the centre
}).objects;

validateLayout(layout).valid; // true: 192 seats

Recipe: generate sections

@openseat/core/src/generators/rows.ts

function

generateRectTable

Generates a rectangular table with seats along selected edges. Seats are numbered clockwise starting from the top edge; on each edge the n seats sit at k / (n + 1) of the edge length. The table records the parameters as its arrangement.

function generateRectTable(
  options: RectTableOptions,
): GeneratedRows;

Parameters

ParameterTypeDescription
optionsRectTableOptions

options takes RectTableOptions:

Returns

@openseat/core/src/generators/tables.ts

function

generateRoundTable

Generates a round table with seats spread evenly around it, clockwise from startAngle. The table records the parameters as its arrangement.

function generateRoundTable(
  options: RoundTableOptions,
): GeneratedRows;

Parameters

ParameterTypeDescription
optionsRoundTableOptions

options takes RoundTableOptions:

Returns

@openseat/core/src/generators/tables.ts

function

generateSectionSeating

Fills a polygon with rows of seats, as for a stadium or arena section.

The rows come from planFillRows: every seat lies fully inside the boundary, and a concave section can give a row several spans. Each row gets a straight parametric layout (span breaks and aisles become gaps), and the section records the fill as seating (kind "fill") with its rowOrder, so it can be refilled later without losing seat IDs.

function generateSectionSeating(
  options: SectionSeatingOptions,
): GeneratedRows & { section: Section };

Parameters

ParameterTypeDescription
optionsSectionSeatingOptions

options takes SectionSeatingOptions:

Returns

GeneratedRows & { section: Section; }

@openseat/core/src/generators/section.ts

function

generateStraightRows

Generates straight, optionally staggered rows with aisle gaps. Seat positions are absolute layout coordinates. Output is deterministic for the same options. Each row gets a parametric layout (start anchor at its first seat, aisle gaps, seat rotation "row", labeling from the numbering).

function generateStraightRows(
  options: StraightRowsOptions,
): GeneratedRows;

Parameters

ParameterTypeDescription
optionsStraightRowsOptions

options takes StraightRowsOptions:

Returns

Example

Venue.tsx
import { useState } from "react";
import { createLayout, generateStraightRows } from "@openseat/core";
import { createRestAdapter } from "@openseat/adapter-rest";
import { BookingMap, useInventory } from "@openseat/react";

const layout = createLayout({ id: "hall", name: "Main hall", width: 1000, height: 800 });
layout.objects = generateStraightRows({
  idPrefix: "stalls",
  rowCount: 10,
  seatsPerRow: 20,
  origin: { x: 100, y: 100 },
  seatSpacing: 28,
  rowSpacing: 32,
  aisleAfter: [10],
}).objects;

const api = createRestAdapter({ baseUrl: "https://api.example.com" });

export function Venue() {
  const { statuses } = useInventory(api, "show-2026-11-20");
  const [selection, setSelection] = useState<readonly string[]>([]);
  return (
    <BookingMap
      layout={layout}
      statuses={statuses}
      selectedSeatIds={selection}
      onSelectionChange={(next) => setSelection(next)}
      rules={{ maxSeats: 8, preventOrphans: true }}
    />
  );
}

Recipe: generate sections

@openseat/core/src/generators/rows.ts

function

generateTableSeats

The seats of a table arrangement, unrotated around center, with the same IDs and labels as generateRoundTable and generateRectTable. Unlike those, an arrangement without seats gives an empty list.

function generateTableSeats(options: TableSeatsOptions): Seat[];

Parameters

ParameterTypeDescription
optionsTableSeatsOptions

options takes TableSeatsOptions:

Returns

@openseat/core/src/generators/tables.ts

function

getBounds

function getBounds(points: readonly Point[]): Bounds | null;

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

Bounds | null

@openseat/core/src/geometry.ts

function

getDrawOrder

Returns object IDs in paint order (bottom first). Hit testing walks this order in reverse so the topmost object wins.

function getDrawOrder(objects: readonly LayoutObject[]): string[];

Parameters

ParameterTypeDescription
objectsreadonly LayoutObject[]

Returns

string[]

@openseat/core/src/object-geometry.ts

function

getMemberSeatObjectIds

Seat object IDs owned by a row or table. Empty for other objects.

function getMemberSeatObjectIds(
  obj: LayoutObject,
): readonly string[];

Parameters

ParameterTypeDescription
objLayoutObject

Returns

readonly string[]

@openseat/core/src/object-geometry.ts

function

getObjectBounds

World-space axis-aligned bounds of an object, or null for objects with no geometry of their own (rows).

function getObjectBounds(obj: LayoutObject): Bounds | null;

Parameters

ParameterTypeDescription
objLayoutObject

Returns

Bounds | null

@openseat/core/src/object-geometry.ts

function

getWorldBounds

Bounds of the transformed points, computed without a second pass over the input.

function getWorldBounds(
  points: readonly Point[],
  placement: Placement,
): Bounds | null;

Parameters

ParameterTypeDescription
pointsreadonly Point[]
placementPlacement

Returns

Bounds | null

@openseat/core/src/geometry.ts

function

groupSeatsIntoRow

Makes a row from loose or grouped seats. Seats are ordered along their principal axis (oriented left to right, or top to bottom when vertical) and detached from any row or table they were in (a parametric source row keeps their slots as holes; a table's capacity follows). Source rows left empty are removed. The row is rotated along its first-to-last seat direction and joins the seats' common section; seat caches (rowLabel, sectionId) are updated. Returns the new row's ID.

function groupSeatsIntoRow(
  layout: LayoutDocument,
  seatObjectIds: readonly string[],
  rowLabel: string,
): { layout: LayoutDocument; rowId: string | null };

Parameters

ParameterTypeDescription
layoutLayoutDocument
seatObjectIdsreadonly string[]
rowLabelstring

Returns

{ layout: LayoutDocument; rowId: string | null; }

@openseat/core/src/operations.ts

function

hitShapeBounds

function hitShapeBounds(shape: HitShape): Bounds | null;

Parameters

ParameterTypeDescription
shapeHitShape

Returns

Bounds | null

@openseat/core/src/object-geometry.ts

function

hitShapeContains

True when point hits the shape. tolerance widens the target, which helps touch input.

function hitShapeContains(
  shape: HitShape,
  point: Point,
  tolerance?: number,
): boolean;

Parameters

ParameterTypeDescription
shapeHitShape
pointPoint
toleranceoptionalnumber

Default 0

Returns

boolean

@openseat/core/src/object-geometry.ts

function

indexLayout

Builds (or returns the memoised) membership index of a layout. Memoised by the objects array, so every operation on the same immutable document shares one O(n) build (for the most recently used documents).

function indexLayout(layout: {
  readonly objects: readonly LayoutObject[];
}): LayoutIndex;

Parameters

ParameterTypeDescription
layout{ readonly objects: readonly LayoutObject[]; }

Returns

@openseat/core/src/membership.ts

function

indexToLetters

Converts a zero-based index to a spreadsheet-style label: 0 → A, 25 → Z, 26 → AA. Used for default row labels.

function indexToLetters(index: number): string;

Parameters

ParameterTypeDescription
indexnumber

Returns

string

@openseat/core/src/ids.ts

function

inferSeatIdPrefix

The shared prefix of a group's public seat IDs, for numbering new seats in the same pattern. Returns the longest common prefix that ends in a non-digit when every seat ID is that prefix followed by digits (so c:A:1…c:A:5 gives c:A:), and fallback otherwise.

function inferSeatIdPrefix(
  seatIds: readonly string[],
  fallback: string,
): string;

Parameters

ParameterTypeDescription
seatIdsreadonly string[]
fallbackstring

Returns

string

@openseat/core/src/ids.ts

function

inferTableArrangement

Infers a table's arrangement from where its seats are, for tables drawn before arrangements existed or edited seat by seat.

  • Round: the median distance of the seats from the centre, and the angle of the first seat (seatObjectIds[0]).
  • Rect: each seat counts for the edge it lies furthest beyond, in table-local coordinates; the offset is the median distance of the seat centres beyond their edge (the generator's seatOffset).

A table without seats gives the generator defaults (seat radius + 4 clear of the edge, first seat at the top). The table's stored arrangement is ignored; see setTableArrangement for the one in effect.

function inferTableArrangement(
  layout: LayoutDocument,
  tableId: string,
): TableArrangement;

Parameters

ParameterTypeDescription
layoutLayoutDocument
tableIdstring

Returns

@openseat/core/src/table-ops.ts

function

insertSeats

Inserts count new seats before slot atSlot (0..slotCount). Holes and gaps at or after atSlot shift with the seats; the first retained seat stays where it is.

Existing seats keep their labels and seat IDs. New seats take the labeling's label for their slot when it is free (inserting at slot 0 of a left-to-right row shifts the labeling start down, as extendRow does), else the next number after the row's highest; their seat IDs follow the row's pattern (prefix + label). When the labels then no longer follow the row's labeling, the labeling is removed (the row keeps custom numbers) and the result's message says so.

function insertSeats(
  layout: LayoutDocument,
  rowId: string,
  atSlot: number,
  count?: number,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
atSlotnumber
countoptionalnumber

Default 1

Returns

@openseat/core/src/row-ops.ts

function

insertVertex

Inserts a vertex on edge edgeIndex (from vertex edgeIndex to the next; closed outlines wrap around), at world or the edge midpoint.

function insertVertex(
  layout: LayoutDocument,
  id: string,
  edgeIndex: number,
  world?: Point,
): VertexEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
edgeIndexnumber
worldoptionalPoint

Returns

@openseat/core/src/section-ops.ts

function

internalValidationFailure

Result for an unexpected exception inside validation. Validation never throws: a bug or a hostile input that trips one becomes an error instead.

function internalValidationFailure(
  cause: unknown,
): ValidationResult;

Parameters

ParameterTypeDescription
causeunknown

Returns

@openseat/core/src/validate.ts

function

isEffectivelyHidden

True when the object or any ancestor is hidden. Unknown IDs are not hidden.

function isEffectivelyHidden(
  index: LayoutIndex,
  id: string,
): boolean;

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

boolean

@openseat/core/src/membership.ts

function

isEffectivelyLocked

True when the object or any ancestor is locked. Unknown IDs are not locked.

function isEffectivelyLocked(
  index: LayoutIndex,
  id: string,
): boolean;

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

boolean

@openseat/core/src/membership.ts

function

isSimplePolygon

A polygon is simple when no two non-adjacent edges touch. Adjacent edges always share a vertex, so they are excluded from the check. See polygonSimplicity for a version with a work budget.

function isSimplePolygon(points: readonly Point[]): boolean;

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

boolean

@openseat/core/src/geometry.ts

function

isZoneSection

True for a section shown as a zone (showSeats: false): sold by quantity, seats not drawn.

function isZoneSection(
  obj: LayoutObject | undefined | null,
): obj is Section;

Parameters

ParameterTypeDescription
objLayoutObject | undefined | null

Returns

obj is Section

@openseat/core/src/zone-ops.ts

function

keptRoundSeatDistance

Seat distance for a round table whose radius changes from oldRadius to newRadius: the clear gap oldSeatDistance - oldRadius is kept, floored at the seat radius so seats never slide under the table edge.

function keptRoundSeatDistance(
  oldRadius: number,
  oldSeatDistance: number,
  newRadius: number,
  seatRadius: number,
): number;

Parameters

ParameterTypeDescription
oldRadiusnumber
oldSeatDistancenumber
newRadiusnumber
seatRadiusnumber

Returns

number

@openseat/core/src/table-ops.ts

function

layoutRowSlots

World positions and seat rotations of slotCount slots. Rotation is placement.rotation + tangent for "tangent" (the default), placement.rotation for "row", and NaN for "keep".

function layoutRowSlots(
  placement: Placement,
  spec: RowLayout,
  slotCount: number,
): RowSlotPose[];

Parameters

ParameterTypeDescription
placementPlacement
specRowLayout
slotCountnumber

Returns

@openseat/core/src/row-geometry.ts

function

layoutTextBoxes

Every piece of text the layout draws at a level of detail, with its reserved world box: section titles (sectionTitlePlacement), row labels (detail only; resolveRowLabelPlacements, hidden ones left out), zone labels (GA zones and zone sections), stage labels, free labels, divider captions, and table and booth labels (objectLabelPlacement). Hidden objects and the contents of zone sections are left out, and so are seat numbers, which sit inside their seats by design. Memoised per layout object.

function layoutTextBoxes(
  layout: LayoutDocument,
  opts: { readonly lod: LabelLod },
): readonly LayoutTextBox[];

Parameters

ParameterTypeDescription
layoutLayoutDocument
opts{ readonly lod: LabelLod; }

Returns

readonly LayoutTextBox[]

@openseat/core/src/label-layout.ts

function

localToWorld

Maps a point from an object's local space into layout space. Local points are rotated around the local origin, then translated by position.

function localToWorld(point: Point, placement: Placement): Point;

Parameters

ParameterTypeDescription
pointPoint
placementPlacement

Returns

@openseat/core/src/geometry.ts

function

maxBlockCurvature

The strongest positive block curvature at which the longest row (longestRow seats) still fits on the tightest (front) row's radius, with the same limits as minBlockCurvature. Rows grow outwards with positive curvature, so the row count does not matter. 100 when any curvature works.

function maxBlockCurvature(
  seatSpacing: number,
  longestRow?: number,
): number;

Parameters

ParameterTypeDescription
seatSpacingnumber
longestRowoptionalnumber

Default 1

Returns

number

@openseat/core/src/section-ops.ts

function

maxSeatsForTable

The most seats a table can take without neighbouring seats coming closer than minGap. Round tables: the seats sit on a circle of radius seatDistance (from a round arrangement, else the radius plus the rect offset), so n seats fit while the chord between neighbours is at least 2 * seatRadius + minGap. Rect tables: the sum over the edges of the seats whose spacing edgeLength / (n + 1) stays at least that pitch (at least one per edge, centred).

function maxSeatsForTable(
  shape: TableShape,
  arrangement: TableArrangement,
  seatShape: SeatShape,
  minGap?: number,
): number;

Parameters

ParameterTypeDescription
shapeTableShape
arrangementTableArrangement
seatShapeSeatShape
minGapoptionalnumber

Default DEFAULT_TABLE_SEAT_GAP

Returns

number

@openseat/core/src/table-ops.ts

function

mergeRegeneratedSeats

The regeneration strategy, in one place:

  1. Retain by slot or position. With slots, each generated seat takes over the listed existing seat; otherwise the i-th new seat takes over the i-th existing seat. A retained seat keeps its object ID, public seatId, accessibility metadata, category, name, tags and locked/visible flags. Its sectionId and rowLabel follow the group. Geometry and shape come from the generator. Labels are regenerated unless keepLabels is set or the seat is labelLocked.
  2. Add with fresh IDs. New seats get the object ID ${group.id}:s${slot + 1} and a seat ID in the pattern of the group's existing seat IDs (see inferSeatIdPrefix), numbered slot + 1 plus the offset the retained seats share (so a row numbered from 5 continues 9, 10…), made unique against the whole layout.
  3. Remove the rest, along with any references to them, and report their public seat IDs.

Nothing outside the group is changed. Unchanged seats and an unchanged group keep their object references; when nothing changes at all, the input layout is returned.

function mergeRegeneratedSeats(
  layout: LayoutDocument,
  group: Row | Table,
  generated: readonly Seat[],
  options?: RetentionOptions,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
groupRow | Table
generatedreadonly Seat[]
optionsoptionalRetentionOptions

Default {}

Returns

@openseat/core/src/regenerate.ts

function

mergeRows

Merges rows of one section into the first one. Rows are ordered along the first row's direction and their seats concatenated (a row running the other way is reversed); the layout is refitted with gaps for the distance between rows. The other rows are removed (their seats are kept). Throws a RangeError when the rows belong to different sections, or when their seats do not lie on one line or arc (parallel rows cannot be merged). When the merged seats would repeat a label, the row is numbered afresh from its labeling and renumbered is true.

function mergeRows(
  layout: LayoutDocument,
  rowIds: readonly string[],
  opts?: { readonly rowLabel?: string },
): { layout: LayoutDocument; rowId: string; renumbered: boolean };

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdsreadonly string[]
optsoptional{ readonly rowLabel?: string; }

Default {}

Returns

{ layout: LayoutDocument; rowId: string; renumbered: boolean; }

@openseat/core/src/row-ops.ts

function

migrateLayout

Upgrades a document through the registered migration chain until it reaches SCHEMA_VERSION. Documents from a newer schema are rejected rather than silently downgraded.

function migrateLayout(
  input: unknown,
  migrations?: readonly LayoutMigration[],
  currentVersion?: number,
): MigrationResult;

Parameters

ParameterTypeDescription
inputunknown
migrationsoptionalreadonly LayoutMigration[]

Override for tests or custom build pipelines.

Default builtinMigrations

currentVersionoptionalnumber

Override for tests; defaults to the built-in schema version.

Default SCHEMA_VERSION

Returns

@openseat/core/src/migrate.ts

function

minBlockCurvature

The most negative block curvature that still gives every row a radius larger than the seat spacing and lets the longest row (longestRow seats, default 1) fit on the tightest (back) row's radius: it bends through at most 162 degrees and neighbouring seats stay at least 0.95 x the seat spacing apart. Curvature below it fails applySectionSeating; use it to bound a curvature slider. -100 when any curvature works.

function minBlockCurvature(
  rows: number,
  rowSpacing: number,
  seatSpacing: number,
  longestRow?: number,
): number;

Parameters

ParameterTypeDescription
rowsnumber
rowSpacingnumber
seatSpacingnumber
longestRowoptionalnumber

Default 1

Returns

number

@openseat/core/src/section-ops.ts

function

minRoundTableRadiusForSeats

The smallest round-table radius at which maxSeatsForTable is at least seatCount, with the seats kept gap outside the table edge (the gap setTableArrangement keeps when the radius changes). At least 1. For clamping radius inputs so a table never shrinks below its seats.

function minRoundTableRadiusForSeats(
  seatCount: number,
  opts?: MinRoundTableRadiusOptions,
): number;

Parameters

ParameterTypeDescription
seatCountnumber
optsoptionalMinRoundTableRadiusOptions

Default {}

Returns

number

@openseat/core/src/table-ops.ts

function

moveObjects

Moves objects by delta. Sections bring their contents and rows and tables their seats. Effectively locked objects (locked themselves or inside a locked group or section) do not move. Moving part of a parametric row or section turns it freeform (see reconcileMoved).

function moveObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  delta: Point,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
deltaPoint

Returns

@openseat/core/src/operations.ts

function

moveVertex

Moves vertex index of a section, polygon, GA area, aisle or path outline to a layout-space point.

function moveVertex(
  layout: LayoutDocument,
  id: string,
  index: number,
  world: Point,
): VertexEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
indexnumber
worldPoint

Returns

@openseat/core/src/section-ops.ts

function

nextFreeRowLabel

The first label of spec's sequence not used by any row with the same sectionId.

function nextFreeRowLabel(
  layout: LayoutDocument,
  sectionId: string | undefined,
  spec?: RowLabeling,
): string;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring | undefined
specoptionalRowLabeling

Default DEFAULT_ROW_LABELING

Returns

string

@openseat/core/src/labeling.ts

function

nextFreeSectionLabel

The next section label: one more than the largest label when every section label is a number, otherwise the first free Section N (N = section count + 1 and up).

function nextFreeSectionLabel(layout: LayoutDocument): string;

Parameters

ParameterTypeDescription
layoutLayoutDocument

layout takes LayoutDocument:

Returns

string

@openseat/core/src/section-ops.ts

function

objectLabelPlacement

Where a table's or booth's label goes: centred on it and turned with it, at 12 units, shrunk (down to 4) so it fits 0.9 × the width of the booth or rect table, or 0.8 × a round table's diameter, and never spills onto the chairs.

function objectLabelPlacement(obj: Table | Booth): TextPlacement;

Parameters

ParameterTypeDescription
objTable | Booth

Returns

@openseat/core/src/label-layout.ts

function

parentOf

The direct parent of an object: a grouped seat gives its row or table; a row, table, GA area or loose seat gives its section when that section exists. Sections and free-standing objects have no parent.

function parentOf(
  index: LayoutIndex,
  id: string,
): string | undefined;

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

string | undefined

@openseat/core/src/membership.ts

function

parseLabelStart

Parses the first label a user typed: "12" is numeric 12, "A" alpha 1, "AA" alpha 27, "c" alpha-lower 3, "IV" roman 4 (only valid roman numerals longer than one character; "I" is alpha 9). Null when unrecognised.

function parseLabelStart(
  text: string,
): { format: LabelFormat; start: number } | null;

Parameters

ParameterTypeDescription
textstring

Returns

{ format: LabelFormat; start: number; } | null

@openseat/core/src/labeling.ts

function

parseLayout

Parses and validates JSON text from an untrusted source.

Failure modes are reported as validation errors, not exceptions:

  • malformed JSON → INVALID_DOCUMENT at path "" with the parser message
  • old schema versions are migrated first
  • everything else goes through validateLayout
  • an unexpected exception (from a migration, say) → INVALID_DOCUMENT "Internal validation error: ..."; this function never throws
function parseLayout(
  json: string,
  options?: ParseOptions,
): ValidationResult;

Parameters

ParameterTypeDescription
jsonstring
optionsoptionalParseOptions

Default {}

Returns

@openseat/core/src/serialize.ts

function

pasteObjects

Pastes a clipboard payload into a layout (the same one or another). Objects are re-identified as by duplicateObjects. A sectionId is kept only when that section is part of the payload; otherwise it is dropped. Missing categories are added; a category ID that exists with a different name gets a fresh ID. Returns the pasted top-level IDs and the copied row IDs.

function pasteObjects(
  layout: LayoutDocument,
  payload: ClipboardPayload,
  opts?: PasteOptions,
): { layout: LayoutDocument; ids: string[]; rowIds: string[] };

Parameters

ParameterTypeDescription
layoutLayoutDocument
payloadClipboardPayload
optsoptionalPasteOptions

Default {}

Returns

{ layout: LayoutDocument; ids: string[]; rowIds: string[]; }

@openseat/core/src/operations.ts

function

pathCaptionPlacement

Placement of a path's caption: centred at the arc-length midpoint of the (world) path, turned along the segment there and kept upright, with the reserved text box. fontSize defaults to captionSize, else DIVIDER_CAPTION_SIZE. Null when the path has no caption or no length.

function pathCaptionPlacement(
  path: Pick<
    CustomPath,
    | "points"
    | "position"
    | "rotation"
    | "closed"
    | "caption"
    | "captionSize"
  >,
  fontSize?: number,
): PathCaptionPlacement | null;

Parameters

ParameterTypeDescription
pathPick<CustomPath, "points" | "position" | "rotation" | "closed" | "caption" | "captionSize">
fontSizeoptionalnumber

Default path.captionSize ?? DIVIDER_CAPTION_SIZE

Returns

@openseat/core/src/object-geometry.ts

function

planFillRows

Plans the rows that fill a polygon, without creating objects. The boundary is rotated so rows run horizontally, each row is a scanline across the polygon, and seats are spaced along every span the line crosses (a concave outline can give a row several spans, which become row gaps). Seats too close to an edge are dropped, so every seat lies fully inside. Rows run along angle and are returned front (first scanline) to back, or the other way round with reverse.

Throws a GeneratorInputError before doing any work when the fill would exceed MAX_FILL_ROWS rows, when a span would exceed MAX_FILL_SEATS_PER_SPAN seats, or when a boundary coordinate is beyond LAYOUT_LIMITS.maxCoordinate.

function planFillRows(options: FillPlanOptions): {
  pivot: Point;
  angle: number;
  rows: FillRowPlan[];
};

Parameters

ParameterTypeDescription
optionsFillPlanOptions

options takes FillPlanOptions:

Returns

{ pivot: Point; angle: number; rows: FillRowPlan[]; }

@openseat/core/src/generators/section.ts

function

pointInPolygon

Point-in-polygon test using ray casting. Points on the boundary count as inside, so a seat sitting exactly on a section edge is not flagged.

function pointInPolygon(
  point: Point,
  polygon: readonly Point[],
): boolean;

Parameters

ParameterTypeDescription
pointPoint
polygonreadonly Point[]

Returns

boolean

@openseat/core/src/geometry.ts

function

poleOfInaccessibility

The interior point farthest from the polygon outline (the "visual centre"), found with the polylabel quadtree search. Better than the centroid for placing a label in a concave shape such as a C or an L: the result always lies inside the polygon. precision is the tolerance in layout units. Degenerate polygons (zero area) return the vertex mean.

function poleOfInaccessibility(
  points: readonly Point[],
  precision?: number,
): Point;

Parameters

ParameterTypeDescription
pointsreadonly Point[]
precisionoptionalnumber

Default 1

Returns

@openseat/core/src/geometry.ts

function

polygonArea

function polygonArea(points: readonly Point[]): number;

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

number

@openseat/core/src/geometry.ts

function

polygonCentroid

Area-weighted centroid of a simple polygon. Falls back to the mean of the vertices when the area is zero (collinear or degenerate input), and to the origin for an empty list.

function polygonCentroid(points: readonly Point[]): Point;

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

@openseat/core/src/geometry.ts

function

polygonSimplicity

Whether a polygon is simple (no two non-adjacent edges touch; adjacent edges always share a vertex, so they are excluded). Edges are sorted by their left x, and only pairs whose bounding boxes overlap are tested exactly, so real outlines cost about O(n log n) (about two candidate pairs per edge). Pathological shapes (many long edges whose x extents overlap) can still visit O(n^2) candidate pairs, whether or not their y extents overlap too: every candidate pair uses up one unit of budget.remaining, and when it runs out the answer is "unknown".

function polygonSimplicity(
  points: readonly Point[],
  budget?: SimplicityBudget,
): "simple" | "self-intersecting" | "unknown";

Parameters

ParameterTypeDescription
pointsreadonly Point[]
budgetoptionalSimplicityBudget

Returns

"simple" | "self-intersecting" | "unknown"

@openseat/core/src/geometry.ts

function

radiusToRowCurvature

Inverse of rowCurvatureToRadius: sign(r) * min(100, 13500 / |r|), 0 when straight.

function radiusToRowCurvature(r?: number): number;

Parameters

ParameterTypeDescription
roptionalnumber

Returns

number

@openseat/core/src/row-geometry.ts

function

rectTableSeatPlacements

Seats along the edges of a width x height rectangle, clockwise from the top edge: top left to right, right top to bottom, bottom right to left, left bottom to top. The n seats of an edge sit at k / (n + 1) of its length, seatOffset outside it.

function rectTableSeatPlacements(
  width: number,
  height: number,
  seatsPerEdge: RectTableSeatCounts,
  seatOffset: number,
): TableSeatPlacement[];

Parameters

ParameterTypeDescription
widthnumber
heightnumber
seatsPerEdgeRectTableSeatCounts
seatOffsetnumber

Returns

@openseat/core/src/generators/tables.ts

function

refreshAutoOutlines

Recomputes the outline of every section whose outline is "auto" (block seating, or no seating; arc seating gets its ring segment; fill seating is driven by its outline and is skipped) from its actual seats. With previous, only sections whose members (or the section itself) changed by reference are recomputed. Returns the same layout when nothing changes.

function refreshAutoOutlines(
  layout: LayoutDocument,
  previous?: LayoutDocument,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
previousoptionalLayoutDocument

Returns

@openseat/core/src/section-ops.ts

function

regenerateRow

Regenerates a row with seatCount seats seatSpacing apart, never flattening it:

  • a row with a parametric layout keeps its line or arc, anchor, gaps and holes (setRowLayout);
  • a legacy row with a nonzero rotation is laid out straight from its position along its rotation;
  • any other row is fitted (fitRowLayout) and regenerated along the fitted line or arc.

The row always ends up with a layout. IDs follow mergeRegeneratedSeats.

function regenerateRow(
  layout: LayoutDocument,
  rowId: string,
  options: RowRegenerationOptions,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
optionsRowRegenerationOptions

Returns

@openseat/core/src/regenerate.ts

function

regenerateTable

Regenerates a table's seats (and optionally its shape) around its current position and rotation, and records the parameters as the table's arrangement. A round table keeps the start angle of its current round arrangement (default -90, the top) and, without a seatDistance, the clear gap between its edge and its seats (floored at the seat radius). A seat count of 0, or no seats on any edge, empties the table. IDs follow mergeRegeneratedSeats: the i-th generated seat takes over the i-th existing seat.

function regenerateTable(
  layout: LayoutDocument,
  tableId: string,
  options: TableRegenerationOptions,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
tableIdstring
optionsTableRegenerationOptions

Returns

@openseat/core/src/regenerate.ts

function

relabelRows

Labels rows with a RowLabeling sequence, front row first.

"auto" order uses the section's rowOrder when every row shares a section that has one; otherwise rows are ordered by their seat centroid projected on the normal of the mean row direction (front = row-local -y side). Writes row.rowLabel, the seats' rowLabel caches, and row.name when it is the default Row X. When rowIds are exactly the rows of one section, also stores section.rowLabeling and section.rowOrder (front to back).

function relabelRows(
  layout: LayoutDocument,
  rowIds: readonly string[],
  spec: RowLabeling,
  opts?: { readonly order?: "auto" | "given" },
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdsreadonly string[]
specRowLabeling
optsoptional{ readonly order?: "auto" | "given"; }

Default {}

Returns

@openseat/core/src/labeling.ts

function

relabelSeats

Renumbers the seats of a row or table.

  • Rows: the row gets a fitted layout when it has none and one fits, stores spec as layout.labeling, and every seat takes the label of its slot.
  • With seatIds (a subset): only those seats are labelled, numbered in slot order from start; the spec is not stored. The new labels are locked (labelLocked), so regenerating the row or table keeps them.
  • Tables: seats are numbered in seatObjectIds order.

Seats with labelLocked keep their label unless respectLocks is false, in which case they are relabelled and unlocked.

function relabelSeats(
  layout: LayoutDocument,
  target: {
    readonly groupId: string;
    readonly seatIds?: readonly string[];
  },
  spec?: SeatLabeling,
  opts?: { readonly respectLocks?: boolean },
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
target{ readonly groupId: string; readonly seatIds?: readonly string[]; }
specoptionalSeatLabeling
optsoptional{ readonly respectLocks?: boolean; }

Default {}

Returns

@openseat/core/src/labeling.ts

function

removeObjects

Removes objects without leaving dangling references:

  • a row or table always takes its seats; a section takes its contents unless withContents is false, in which case they stay and lose the sectionId;
  • effectively locked objects survive unless force is set;
  • a parametric row that loses seats records their slots as holes, so the other seats keep their numbers; a row left with no seats is removed (unless pruneEmptyRows is false);
  • a table's capacity becomes the number of seats it still has;
  • section row orders drop removed rows.
function removeObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  opts?: RemoveOptions,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
optsoptionalRemoveOptions

Default {}

Returns

@openseat/core/src/operations.ts

function

removeSeatsFromRow

Removes seats from a row and deletes them.

  • "keep-positions": the other seats stay exactly where they are and keep their labels; the removed seats leave holes (parametric rows only).
  • "close-gap": the remaining seats close up towards the first remaining seat and are renumbered from the labeling.
function removeSeatsFromRow(
  layout: LayoutDocument,
  rowId: string,
  seatIds: readonly string[],
  mode: "close-gap" | "keep-positions",
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
seatIdsreadonly string[]
mode"close-gap" | "keep-positions"

Returns

@openseat/core/src/row-ops.ts

function

removeVertex

Removes vertex index of an outline. Closed outlines keep at least 3 points, open ones 2.

function removeVertex(
  layout: LayoutDocument,
  id: string,
  index: number,
): VertexEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
indexnumber

Returns

@openseat/core/src/section-ops.ts

function

renumberObjects

Relabels the tables and booths among ids as ${prefix}${start + k} in reading order. Objects are grouped into rows (or columns) with a tolerance: sorted by their centre across the reading direction, a new row starts when an object lies more than rowToleranceUnits beyond the first object of the current row. Within a row they are ordered along it. Other object types, unknown and repeated IDs are ignored. count is the number of labels that changed; the same layout object is returned when none does. Throws a RangeError for a non-integer or negative start or a negative tolerance.

function renumberObjects(
  layout: LayoutDocument,
  ids: Iterable<string>,
  opts: RenumberOptions,
): { layout: LayoutDocument; count: number };

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsIterable<string>
optsRenumberOptions

Returns

{ layout: LayoutDocument; count: number; }

@openseat/core/src/renumber-ops.ts

function

reorderObjects

Changes the paint order of objects (and what they carry) within their draw band. "front" / "back" lift the selection above / below every other object of the band, keeping its internal order; "forward" / "backward" swap each selected object with its neighbour and renumber the band's zIndex densely.

function reorderObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  direction: ReorderDirection,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
directionReorderDirection

Returns

@openseat/core/src/operations.ts

function

repairStructure

Fixes structural corruption in a valid document. Not a migration: the schema version is unchanged and only the broken relationships are edited.

Level "errors" (the default):

  • a seat in several rows/tables stays with the first owner in document order;
  • repeated IDs within one seatObjectIds are removed;
  • seatObjectIds entries that are not seats are removed;
  • sectionId / categoryId pointing at nothing is deleted;
  • invalid rowOrder entries are removed;
  • duplicate or out-of-range row layout holes are dropped.

Level "all" additionally syncs seat rowLabel / sectionId caches to the owning group (a row without a section adopts the one all its seats share), sets table capacity to the seat count, and removes empty rows that no section's rowOrder references.

Unchanged objects keep their identity, and the input layout is returned as is when nothing needed fixing.

function repairStructure(
  layout: LayoutDocument,
  options?: RepairOptions,
): { layout: LayoutDocument; repairs: StructureRepair[] };

Parameters

ParameterTypeDescription
layoutLayoutDocument
optionsoptionalRepairOptions

Default {}

Returns

{ layout: LayoutDocument; repairs: StructureRepair[]; }

@openseat/core/src/structure-checks.ts

function

requireFinitePoint

function requireFinitePoint(value: Point, name: string): void;

Parameters

ParameterTypeDescription
valuePoint
namestring

Returns

void

@openseat/core/src/generators/common.ts

function

requireNonNegativeFinite

function requireNonNegativeFinite(
  value: number,
  name: string,
): void;

Parameters

ParameterTypeDescription
valuenumber
namestring

Returns

void

@openseat/core/src/generators/common.ts

function

requirePositiveFinite

function requirePositiveFinite(value: number, name: string): void;

Parameters

ParameterTypeDescription
valuenumber
namestring

Returns

void

@openseat/core/src/generators/common.ts

function

requirePositiveInteger

function requirePositiveInteger(value: number, name: string): void;

Parameters

ParameterTypeDescription
valuenumber
namestring

Returns

void

@openseat/core/src/generators/common.ts

function

resizeTable

Changes a table's shape, keeping the clear gap between table and seats (round: seatDistance = newRadius + (oldSeatDistance - oldRadius); rect: the same seatOffset and edge counts). Grows the table when its seats no longer fit. Switching kind converts the arrangement as in setTableArrangement.

function resizeTable(
  layout: LayoutDocument,
  tableId: string,
  shape: TableShape,
): TableEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
tableIdstring
shapeTableShape

Returns

@openseat/core/src/table-ops.ts

function

resolveGroupLabels

Returns labels if given, otherwise A, B, C… for count groups. Labels must be unique.

function resolveGroupLabels(
  count: number,
  labels: readonly string[] | undefined,
): string[];

Parameters

ParameterTypeDescription
countnumber
labelsreadonly string[] | undefined

Returns

string[]

@openseat/core/src/generators/common.ts

function

resolveHitTarget

Maps the object under the pointer to the object a click selects:

  • seat granularity: a seat selects itself (null outside the scoped section);
  • inside a group scope: a seat of that group selects itself;
  • inside a section scope: objects outside the section give null, the section itself gives the section, a grouped seat gives its group, anything else itself;
  • at the top level: anything inside a section gives the section, a grouped seat gives its group, anything else itself. Unknown IDs give null.
function resolveHitTarget(
  index: LayoutIndex,
  hitId: string,
  ctx: HitContext,
): string | null;

Parameters

ParameterTypeDescription
indexLayoutIndex
hitIdstring
ctxHitContext

Returns

string | null

@openseat/core/src/membership.ts

function

resolveRowLabelPlacements

A row's labels, pushed clear of seats. Starts from core rowLabelPlacements (gap 8, font 11, bold); a label whose box overlaps any drawn seat in the layout moves outward along the row in steps of half its font size, at most 4 times. A label still blocked comes back with hidden: true and must not be drawn, so a drawn row label never overlaps a seat. seats are the row's seats in row order (as for rowLabelPlacements). Rows of zone sections and hidden rows get the same treatment here; layoutTextBoxes leaves them out.

function resolveRowLabelPlacements(
  layout: LayoutDocument,
  row: Row,
  seats: readonly Seat[],
): ResolvedRowLabel[];

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowRow
seatsreadonly Seat[]

Returns

@openseat/core/src/label-layout.ts

function

reverseRow

Reverses a row's direction: seatObjectIds are reversed and the layout is recomputed (row.position moves to the old last slot for a start anchor, rotation turns by 180 degrees and the radius sign flips), so no seat moves. Labels re-flow from the labeling. Seats that follow the row's direction ("tangent" or "row") turn by 180 degrees with it.

function reverseRow(
  layout: LayoutDocument,
  rowId: string,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring

Returns

@openseat/core/src/row-ops.ts

function

rotateAround

Rotates point around pivot by degrees. Same as rotatePoint with the pivot made explicit.

function rotateAround(
  point: Point,
  degrees: number,
  pivot: Point,
): Point;

Parameters

ParameterTypeDescription
pointPoint
degreesnumber
pivotPoint

Returns

@openseat/core/src/geometry.ts

function

rotatedBoxBounds

World AABB of a width × height text box centred on at and turned by rotation degrees about it.

function rotatedBoxBounds(
  at: Point,
  width: number,
  height: number,
  rotation: number,
): Bounds;

Parameters

ParameterTypeDescription
atPoint
widthnumber
heightnumber
rotationnumber

Returns

@openseat/core/src/object-geometry.ts

function

rotatePoint

Rotates point around origin by degrees.

function rotatePoint(
  point: Point,
  degrees: number,
  origin?: Point,
): Point;

Parameters

ParameterTypeDescription
pointPoint
degreesnumber
originoptionalPoint

Default { x: 0, y: 0 }

Returns

@openseat/core/src/geometry.ts

function

roundedPolygonPath

A closed polygon with its corners rounded by radius, as line and arc segments in drawing order (each segment starts where the previous one ends; the last one ends where the first starts). Each corner's radius is clamped so its tangent points stay within half of each adjacent edge; straight (collinear) and degenerate corners are left sharp. With radius <= 0 the result is the plain polygon as lines. Used to draw cornerRadius on GA zones and sections, in Konva and SVG alike.

function roundedPolygonPath(
  points: readonly Point[],
  radius: number,
): RoundedPathSegment[];

Parameters

ParameterTypeDescription
pointsreadonly Point[]
radiusnumber

Returns

@openseat/core/src/object-geometry.ts

function

roundedPolygonPoints

roundedPolygonPath flattened to points: each arc becomes stepsPerArc chords. Useful for hit testing and bounds of rounded zones.

function roundedPolygonPoints(
  points: readonly Point[],
  radius: number,
  stepsPerArc?: number,
): Point[];

Parameters

ParameterTypeDescription
pointsreadonly Point[]
radiusnumber
stepsPerArcoptionalnumber

Default 6

Returns

@openseat/core/src/object-geometry.ts

function

roundedRectPoints

A rectangle with rounded corners centred on center, clockwise on screen starting at the top-right corner. cornerRadius is clamped to min(width, height) / 2; 0 gives the four corners. Each corner is drawn with segmentsPerCorner segments.

function roundedRectPoints(
  width: number,
  height: number,
  cornerRadius: number,
  segmentsPerCorner?: number,
  center?: Point,
): Point[];

Parameters

ParameterTypeDescription
widthnumber
heightnumber
cornerRadiusnumber
segmentsPerCorneroptionalnumber

Default 8

centeroptionalPoint

Default { x: 0, y: 0 }

Returns

@openseat/core/src/generators/shapes.ts

function

roundTableSeatPlacements

Seats evenly spread on a circle of radius seatDistance, clockwise (screen convention) from startAngle degrees. Each seat faces the centre.

function roundTableSeatPlacements(
  seatDistance: number,
  startAngle: number,
  seatCount: number,
): TableSeatPlacement[];

Parameters

ParameterTypeDescription
seatDistancenumber
startAnglenumber
seatCountnumber

Returns

@openseat/core/src/generators/tables.ts

function

rowCurvatureToRadius

Block curvature (-100..100) to a signed row radius: 0 is straight, otherwise sign(c) * max(100, 13500 / |c|).

function rowCurvatureToRadius(c: number): number | undefined;

Parameters

ParameterTypeDescription
cnumber

Returns

number | undefined

@openseat/core/src/row-geometry.ts

function

rowCurvePoint

Row-local point at arc length t for a straight row (radius absent) or an arc.

function rowCurvePoint(
  spec: Pick<RowLayout, "radius">,
  t: number,
): Point;

Parameters

ParameterTypeDescription
specPick<RowLayout, "radius">
tnumber

Returns

@openseat/core/src/row-geometry.ts

function

rowCurveTangentDeg

Row-local tangent angle at arc length t, in degrees (0 for straight rows).

function rowCurveTangentDeg(
  spec: Pick<RowLayout, "radius">,
  t: number,
): number;

Parameters

ParameterTypeDescription
specPick<RowLayout, "radius">
tnumber

Returns

number

@openseat/core/src/row-geometry.ts

function

rowLabelPlacements

Where to draw a row's label(s): before the first seat and/or after the last one, along the row's tangent, seatRadius + gap away from the seat centre. Follows row.labelPosition (absent = "start"; "none" gives no labels). seats must be the row's seats in row order.

function rowLabelPlacements(
  row: Row,
  seats: readonly Seat[],
  opts: { readonly gap: number },
): RowLabelPlacement[];

Parameters

ParameterTypeDescription
rowRow
seatsreadonly Seat[]
opts{ readonly gap: number; }

Returns

@openseat/core/src/row-geometry.ts

function

rowLabels

count unique row labels. Walks start, start + step, … and, for the alpha formats, skips values whose uppercase form is in skip (numeric and roman labels ignore it). "back-to-front" reverses the returned list, so index 0 is always the front row.

function rowLabels(spec: RowLabeling, count: number): string[];

Parameters

ParameterTypeDescription
specRowLabeling
countnumber

Returns

string[]

@openseat/core/src/labeling.ts

function

rowPlacementForSlotPose

The placement that puts slot k of spec (with slotCount slots) at position with world tangent tangent degrees. Used to keep a seat fixed while the rest of the row changes.

function rowPlacementForSlotPose(
  spec: RowLayout,
  slotCount: number,
  k: number,
  position: Point,
  tangent: number,
): Placement;

Parameters

ParameterTypeDescription
specRowLayout
slotCountnumber
knumber
positionPoint
tangentnumber

Returns

@openseat/core/src/row-geometry.ts

function

rowSlotParams

Arc-length parameter t_i of every slot, anchor shift applied. Holes do not affect the parameters.

function rowSlotParams(
  spec: Pick<RowLayout, "seatSpacing" | "gaps" | "anchor">,
  slotCount: number,
): number[];

Parameters

ParameterTypeDescription
specPick<RowLayout, "seatSpacing" | "gaps" | "anchor">
slotCountnumber

Returns

number[]

@openseat/core/src/row-geometry.ts

function

rowSlotTangentPose

World position and tangent (degrees) of slot k.

function rowSlotTangentPose(
  placement: Placement,
  spec: RowLayout,
  slotCount: number,
  k: number,
): { position: Point; tangent: number };

Parameters

ParameterTypeDescription
placementPlacement
specRowLayout
slotCountnumber
knumber

Returns

{ position: Point; tangent: number; }

@openseat/core/src/row-geometry.ts

function

seatBoxes

World AABBs of every drawn seat, in document order. Hidden seats (also through a hidden row, table or section) and the seats of zone sections (showSeats: false) are left out. Memoised per layout object.

function seatBoxes(layout: LayoutDocument): readonly SeatBox[];

Parameters

ParameterTypeDescription
layoutLayoutDocument

layout takes LayoutDocument:

Returns

readonly SeatBox[]

@openseat/core/src/label-layout.ts

function

seatEnvelope

Convex hull around seats, each seat taken as a circle of its enclosing radius plus pad, sampled at 8 points. Coordinates are the seats' (layout space). Empty when there are no seats.

function seatEnvelope(seats: readonly Seat[], pad: number): Point[];

Parameters

ParameterTypeDescription
seatsreadonly Seat[]
padnumber

Returns

@openseat/core/src/generators/shapes.ts

function

seatIdFor

function seatIdFor(
  idPrefix: string,
  groupLabel: string,
  seatNumber: number,
): string;

Parameters

ParameterTypeDescription
idPrefixstring
groupLabelstring
seatNumbernumber

Returns

string

@openseat/core/src/generators/common.ts

function

seatLabelFor

Builds the displayed label for a seat number, applying the numbering prefix and suffix.

function seatLabelFor(
  seatNumber: number,
  numbering: SeatNumbering | undefined,
): string;

Parameters

ParameterTypeDescription
seatNumbernumber
numberingSeatNumbering | undefined

Returns

string

@openseat/core/src/generators/common.ts

function

seatLabels

One label per slot (holes included), so deleted seats keep their number. Slot i gets start + i * step ("ltr") or start + (slotCount - 1 - i) * step ("rtl").

function seatLabels(
  spec: SeatLabeling,
  slotCount: number,
): string[];

Parameters

ParameterTypeDescription
specSeatLabeling
slotCountnumber

Returns

string[]

@openseat/core/src/labeling.ts

function

seatLabelValue

The label index label stands for under labeling (prefix and suffix stripped): "12" is 12 when numeric, "C" 3 when alpha, "IV" 4 when roman. Null when the label does not belong to the labeling's sequence format.

function seatLabelValue(
  label: string,
  labeling: SeatLabeling,
): number | null;

Parameters

ParameterTypeDescription
labelstring
labelingSeatLabeling

Returns

number | null

@openseat/core/src/labeling.ts

function

seatNumberingLabels

Displayed labels for count seats. Uses seatLabels when the numbering sets a format, step or direction; otherwise exactly seatLabelFor for start + i.

function seatNumberingLabels(
  numbering: SeatNumbering | undefined,
  count: number,
): string[];

Parameters

ParameterTypeDescription
numberingSeatNumbering | undefined
countnumber

Returns

string[]

@openseat/core/src/generators/common.ts

function

seatNumberingToLabeling

The SeatLabeling equivalent of a numbering, or undefined when it cannot be stored (a start or step outside the schema's range, or an over-long prefix or suffix).

function seatNumberingToLabeling(
  numbering: SeatNumbering | undefined,
): SeatLabeling | undefined;

Parameters

ParameterTypeDescription
numberingSeatNumbering | undefined

Returns

SeatLabeling | undefined

@openseat/core/src/generators/common.ts

function

seatObjectIdFor

function seatObjectIdFor(
  idPrefix: string,
  groupLabel: string,
  seatNumber: number,
): string;

Parameters

ParameterTypeDescription
idPrefixstring
groupLabelstring
seatNumbernumber

Returns

string

@openseat/core/src/generators/common.ts

function

seatShapeRadius

Half the largest extent of a seat shape: its radius for circles.

function seatShapeRadius(shape: SeatShape): number;

Parameters

ParameterTypeDescription
shapeSeatShape

Returns

number

@openseat/core/src/generators/tables.ts

function

sectionAt

The topmost visible section whose boundary contains point.

function sectionAt(
  layout: LayoutDocument,
  point: Point,
): string | undefined;

Parameters

ParameterTypeDescription
layoutLayoutDocument
pointPoint

Returns

string | undefined

@openseat/core/src/operations.ts

function

sectionLabelPoint

Where a section's label goes, in section-local coordinates: the outline's visual centre plus labelOffset.

function sectionLabelPoint(section: Section): Point;

Parameters

ParameterTypeDescription
sectionSection

section takes Section:

Returns

@openseat/core/src/section-label.ts

function

sectionOf

The section that contains an object (through its group for grouped seats). A section is not inside itself, so a section gives undefined.

function sectionOf(
  index: LayoutIndex,
  id: string,
): string | undefined;

Parameters

ParameterTypeDescription
indexLayoutIndex
idstring

Returns

string | undefined

@openseat/core/src/membership.ts

function

sectionSeatCount

Seats of a section that are not hidden through a seat, row or table (the default zone capacity).

function sectionSeatCount(
  layout: LayoutDocument,
  sectionId: string,
): number;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring

Returns

number

@openseat/core/src/zone-ops.ts

function

sectionTitlePlacement

Where a section's title goes, or where: "hidden" when it is not drawn.

  • Overview, a zone section, or a section with no drawn seats: centred at sectionLabelPoint (the outline's pole plus labelOffset), turned by labelRotation, upper-case, sized by the long-standing rule (its labelSize, default 16, at most 0.45 × the outline's shorter side) and shrunk to fit inside. where: "inside".
  • Detail (seats drawn): a header band outside the AABB of the section's drawn seats and its row labels, upright whatever the section's rotation, half a font size away. Sides follow labelPlacement, or above, below, left, right for "auto". Size: labelSize (default 16), at most what fits 0.95 × the block's width (above/below) or 2 × its row pitch high (left/right), never below 8. A side is rejected when its box overlaps any drawn seat in the layout, any drawn row label or an earlier title (sections in document order); when every side is rejected they are retried at size 8, then the title is hidden. A placement never overlaps a seat.

labelPlacement: "hidden" hides the title in both levels of detail. Undefined when sectionId is not a visible section. Memoised per layout.

function sectionTitlePlacement(
  layout: LayoutDocument,
  sectionId: string,
  opts: { readonly lod: LabelLod },
): SectionTitlePlacement | undefined;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring
opts{ readonly lod: LabelLod; }

Returns

@openseat/core/src/label-layout.ts

function

sectionZoneCapacity

Places a section sells as a zone: its capacity, or else the number of its seats that are not hidden (themselves or through their row or table; the section's own visibility does not count). 0 when sectionId is not a section.

function sectionZoneCapacity(
  layout: LayoutDocument,
  sectionId: string,
): number;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring

Returns

number

@openseat/core/src/zone-ops.ts

function

segmentsIntersect

True when segments ab and cd share at least one point, including touching endpoints.

function segmentsIntersect(
  a: Point,
  b: Point,
  c: Point,
  d: Point,
): boolean;

Parameters

ParameterTypeDescription
aPoint
bPoint
cPoint
dPoint

Returns

boolean

@openseat/core/src/geometry.ts

function

selectionFromMarquee

Selection made by a marquee that fully contains containedIds. Each ID is resolved with resolveHitTarget and deduplicated. A section is only selected when its own outline is enclosed (its ID is in containedIds); a row or table is selected when at least one of its seats is.

function selectionFromMarquee(
  index: LayoutIndex,
  containedIds: readonly string[],
  ctx: HitContext,
): string[];

Parameters

ParameterTypeDescription
indexLayoutIndex
containedIdsreadonly string[]
ctxHitContext

Returns

string[]

@openseat/core/src/membership.ts

function

sellableSummary

What a layout offers for sale, after unsellableInventory: every seat, GA place and booth with an inventory ID, minus those held back. A table booked as a whole counts its seats, so holding back a 4-seat table lowers totalSellable by 4 either way.

function sellableSummary(layout: LayoutDocument): SellableSummary;

Parameters

ParameterTypeDescription
layoutLayoutDocument

layout takes LayoutDocument:

Returns

@openseat/core/src/category-ops.ts

function

serializeLayout

Serialises a layout to pretty-printed JSON with a canonical key order, so the same layout always produces the same text, however it was built. That keeps exports stable across round trips and makes diffs in version control show only real changes.

The input must be a valid document; this function does not validate, so callers that build documents by hand should run validateLayout first.

function serializeLayout(
  layout: LayoutDocument,
  indent?: number | string,
): string;

Parameters

ParameterTypeDescription
layoutLayoutDocument
indentoptionalnumber | string

Default 2

Returns

string

@openseat/core/src/serialize.ts

function

setFlags

Sets visibility and/or lock on exactly the given objects. What they carry (a section's rows, a row's seats) is not written: it inherits the state, read through isEffectivelyHidden and isEffectivelyLocked. So locking row B, hiding row C, then locking, hiding, unlocking and showing their section leaves B locked and C hidden.

function setFlags(
  layout: LayoutDocument,
  ids: readonly string[],
  flags: { readonly visible?: boolean; readonly locked?: boolean },
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
flags{ readonly visible?: boolean; readonly locked?: boolean; }

Returns

@openseat/core/src/operations.ts

function

setObjectsCategory

Writes categoryId on the objects that carry one (seats, sections, GA areas, booths and polygons), or removes it with null. Unknown IDs and objects without a category field are skipped. With withMembers, a section's seats and a row's or table's seats are written too (the editor's "set category" on a section, row or table). The category is not required to exist. count is the number of objects changed.

function setObjectsCategory(
  layout: LayoutDocument,
  ids: Iterable<string>,
  categoryId: string | null,
  opts?: SetObjectsCategoryOptions,
): { layout: LayoutDocument; count: number };

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsIterable<string>
categoryIdstring | null
optsoptionalSetObjectsCategoryOptions

Default {}

Returns

{ layout: LayoutDocument; count: number; }

@openseat/core/src/category-ops.ts

function

setObjectsNotForSale

Records ids as not for sale (or, with notForSale false, as for sale again) in metadata.openseat.notForSale. The stored list is deduplicated, sorted and pruned of IDs that no longer name an object; malformed entries are dropped. Categories are never touched. An empty list removes the key. Returns the same layout object when nothing changes.

function setObjectsNotForSale(
  layout: LayoutDocument,
  ids: readonly string[],
  notForSale: boolean,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
notForSaleboolean

Returns

@openseat/core/src/category-ops.ts

function

setRowLabel

Sets a row's label, its seats' rowLabel caches and its default name.

function setRowLabel(
  layout: LayoutDocument,
  rowId: string,
  label: string,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
labelstring

Returns

@openseat/core/src/labeling.ts

function

setRowLayout

Changes a row's parametric layout and regenerates its seats.

The patch is merged into the row's layout (fitted first when it has none); radius: null makes it straight. seatCount grows the row by appending slots, or shrinks it by removing the highest-slot seats and any holes left at the end. Positions and rotations come from the layout, labels from its labeling (locked labels stay). New seats copy the category and shape of the nearest seat. Returns the same layout when nothing changes.

function setRowLayout(
  layout: LayoutDocument,
  rowId: string,
  patch: RowLayoutPatch,
  opts?: SetRowLayoutOptions,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
patchRowLayoutPatch
optsoptionalSetRowLayoutOptions

Default {}

Returns

@openseat/core/src/row-ops.ts

function

setSectionMembership

Puts objects into a section (or takes them out with null). IDs map to their membership units: rows, tables, GA areas and loose seats (a grouped seat stands for its group). Seat caches follow. When the section keeps a rowOrder, joining rows are appended to it; rows leaving a section drop out of its order. count is the number of units written.

function setSectionMembership(
  layout: LayoutDocument,
  ids: readonly string[],
  sectionId: string | null,
): { layout: LayoutDocument; count: number };

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
sectionIdstring | null

Returns

{ layout: LayoutDocument; count: number; }

@openseat/core/src/operations.ts

function

setSectionShowSeats

Switches sections between seats and zone only. show false writes showSeats: false (the section is sold by quantity and its seats are not drawn); true deletes the key (seats as before). Rows, seats, tables and capacity are never touched, so switching back restores the seats exactly. Unknown IDs and non-sections are skipped.

function setSectionShowSeats(
  layout: LayoutDocument,
  ids: Iterable<string>,
  show: boolean,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsIterable<string>
showboolean

Returns

@openseat/core/src/zone-ops.ts

function

setShapePoints

Replaces an outline's points with layout-space points (stored relative to the unchanged origin).

function setShapePoints(
  layout: LayoutDocument,
  id: string,
  worldPoints: readonly Point[],
): VertexEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
worldPointsreadonly Point[]

Returns

@openseat/core/src/section-ops.ts

function

setTableArrangement

Edits a table's shape and seat arrangement and regenerates its seats.

  • The starting point is table.arrangement (or inferTableArrangement).
  • Round tables keep the gap between table edge and seats when the radius changes; switching between round and rect keeps the seat count and the gap, distributing the seats over the edges in proportion to their length. seatCount on a rect table redistributes; seatsPerEdge sets edges.
  • With grow (the default), a table too small for its seats is enlarged; otherwise a changed seat count is clamped to maxSeatsForTable (per edge for rect tables) and clamped is set.
  • A seat count of 0 removes every seat (reported) and gives capacity 0.
  • Seats are generated in table-local coordinates, then placed with the table's position and rotation. Identities follow clockwise slots: on rect to rect edits, the k-th seat of each edge stays the k-th seat of that edge; otherwise the i-th seat clockwise takes over the i-th existing seat. Seats beyond the new count are removed and reported.
  • Labels are renumbered clockwise from the current numbering start unless keepLabels; locked labels are kept.

Writes shape, arrangement, capacity and bookAsWhole. Returns the input layout when nothing changes.

function setTableArrangement(
  layout: LayoutDocument,
  tableId: string,
  patch: TableEditPatch,
  opts?: TableEditOptions,
): TableEditResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
tableIdstring
patchTableEditPatch
optsoptionalTableEditOptions

Default {}

Returns

@openseat/core/src/table-ops.ts

function

setZoneCapacity

Sets a zone's capacity. On a section, null deletes the override so the capacity follows the seat count again. On a GA zone, n replaces its capacity and null changes nothing (a GA zone always has one). Throws a RangeError for a capacity that is not a whole number from 1 to 1,000,000.

function setZoneCapacity(
  layout: LayoutDocument,
  id: string,
  capacity: number | null,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
capacitynumber | null

Returns

@openseat/core/src/zone-ops.ts

function

signedArea

Shoelace signed area. Positive for counter-clockwise order in a y-up system.

function signedArea(points: readonly Point[]): number;

Parameters

ParameterTypeDescription
pointsreadonly Point[]

Returns

number

@openseat/core/src/geometry.ts

function

snapToGrid

Rounds value to the nearest multiple of grid. A grid of 0 or less disables snapping.

function snapToGrid(value: number, grid: number): number;

Parameters

ParameterTypeDescription
valuenumber
gridnumber

Returns

number

@openseat/core/src/operations.ts

function

splitRow

Splits a row after the seat at afterIndex (an index into seatObjectIds). The second half becomes a new row ${row.id}-b in the same section, labelled newRowLabel or the next free row label. No seat moves and seat labels are unchanged.

function splitRow(
  layout: LayoutDocument,
  rowId: string,
  afterIndex: number,
  newRowLabel?: string,
): { layout: LayoutDocument; newRowId: string };

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring
afterIndexnumber
newRowLabeloptionalstring

Returns

{ layout: LayoutDocument; newRowId: string; }

@openseat/core/src/row-ops.ts

function

stageLabelPlacement

Where a stage's label goes: centred at stageLabelPoint, upper-case, letter-spaced 0.14 em, clamp(0.28 × min(w, h), 10, 36) and shrunk until it is at most 0.8 × the width available there. Turned with the stage. Null for a stage without a label.

function stageLabelPlacement(stage: Stage): TextPlacement | null;

Parameters

ParameterTypeDescription
stageStage

stage takes Stage:

Returns

@openseat/core/src/label-layout.ts

function

stageLabelPoint

Where a stage's label is centred, in its local space: the centre for rect and round stages, the centre of the main body for a thrust stage, and (0, -h/2 + 0.4 h) for a semicircle (inside its widest part).

function stageLabelPoint(stage: StageGeometry): Point;

Parameters

ParameterTypeDescription
stageStageGeometry

Returns

@openseat/core/src/object-geometry.ts

function

stageLabelWidth

Width available to a stage's label at its label point, in local units: the width for rect and round stages (round: the full ellipse width at the centre), the body width for thrust, and the chord at the label point for a semicircle.

function stageLabelWidth(stage: StageGeometry): number;

Parameters

ParameterTypeDescription
stageStageGeometry

Returns

number

@openseat/core/src/object-geometry.ts

function

stageOutline

Closed outline of a stage in its local space: the width × height box centred on the origin, with the audience on +y. No point is repeated at the end.

  • rect (and absent shape): the box, its corners rounded by cornerRadius (clamped to half the shorter side) with segments / 4 steps per corner; without a radius the four corners in the order top-left, top-right, bottom-right, bottom-left.
  • thrust: a main body across the full width from y = -h/2 to h/2 - depth, plus a centred runway thrust.width wide (default 0.4 w) down to y = h/2 (depth default 0.45 h).
  • round: an ellipse filling the box, segments points.
  • semicircle: a flat edge at y = -h/2 and a half-ellipse (rx = w/2, ry = h) bulging to +y, segments + 1 points.
function stageOutline(
  stage: StageGeometry,
  segments?: number,
): Point[];

Parameters

ParameterTypeDescription
stageStageGeometry
segmentsoptionalnumber

Default 24

Returns

@openseat/core/src/object-geometry.ts

function

stageThrustSize

Runway size of a thrust stage after defaults and clamping (width <= stage width, depth < stage height).

function stageThrustSize(stage: StageGeometry): {
  width: number;
  depth: number;
};

Parameters

ParameterTypeDescription
stageStageGeometry

Returns

{ width: number; depth: number; }

@openseat/core/src/object-geometry.ts

function

straightenRow

Makes a row straight, keeping its spacing and anchor. A curved row is laid along its chord: the straight row runs in the direction from its first slot to its last and keeps the chord's midpoint, so a row curved and then straightened again keeps its direction (it does not follow the tangent at its first seat).

function straightenRow(
  layout: LayoutDocument,
  rowId: string,
): RegenerationResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
rowIdstring

Returns

@openseat/core/src/row-ops.ts

function

toDegrees

function toDegrees(radians: number): number;

Parameters

ParameterTypeDescription
radiansnumber

Returns

number

@openseat/core/src/geometry.ts

function

topLevelUnits

The selection units among ids: drops unknown IDs, duplicates and every ID whose ancestor is also in ids (a seat of a selected row, a row of a selected section). Input order is kept.

function topLevelUnits(
  index: LayoutIndex,
  ids: readonly string[],
): string[];

Parameters

ParameterTypeDescription
indexLayoutIndex
idsreadonly string[]

Returns

string[]

@openseat/core/src/membership.ts

function

toRadians

function toRadians(degrees: number): number;

Parameters

ParameterTypeDescription
degreesnumber

Returns

number

@openseat/core/src/geometry.ts

function

toZoneOnlyLayout

Turns a layout into a zone map: every section with seats becomes a zone section (showSeats: false), so buyers pick a section and a quantity and no seat is drawn. Without sectionIds, rows, tables and loose seats that are in no section are first wrapped into new rectangular sections (createSectionFromSelection with shape: "bounds"): grouped by category and by proximity (units whose bounds are at most 3 × the median seat pitch apart join one section), each labelled with its category's name and an ordinal unique in the layout ("Stalls 1", "VIP 2"; "Zone N" without a category) and given that category. Seats themselves are never changed, so the sellable capacity stays the same (hidden seats aside, which zones do not count). With sectionIds, only those sections switch.

function toZoneOnlyLayout(
  layout: LayoutDocument,
  opts?: ZoneOnlyOptions,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
optsoptionalZoneOnlyOptions

Default {}

Returns

@openseat/core/src/zone-ops.ts

function

transformObject

Sets one object's position and absolute rotation and scales its dimensions along its local axes (the single-object transformer). Everything the object carries follows rigidly in its local frame: a table's chairs (radially for a round table), a row's seats (rotating about row.position), a section's rows, tables, GA areas and loose seats. Effectively locked objects do not change. Parametric rows and sections follow the same rules as transformObjects.

function transformObject(
  layout: LayoutDocument,
  id: string,
  transform: ObjectTransform,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idstring
transformObjectTransform

Returns

@openseat/core/src/operations.ts

function

transformObjects

Transforms objects together, as one rigid (or scaled, or mirrored) group. Selections expand recursively and effectively locked objects are skipped.

Per object: the position is mapped and the rotation follows the local +x axis. Point lists (section and GA boundaries, polygons, aisles, paths) are mapped in world space and re-localised. Booths, stages, rect tables and entrances stretch by how much the map stretches their local axes; seats keep their shape and labels their font size. Round tables scale their radius by sqrt(|sx·sy|) and their seats keep the gap to the table edge.

Parametric data: uniform scale scales a row layout and section seating; a mirror negates a row's radius and re-derives an arc section's centre and angles (block and fill seating is dropped); non-uniform scale drops both. The layout-level venue is not affected.

function transformObjects(
  layout: LayoutDocument,
  ids: readonly string[],
  t: SelectionTransform,
): LayoutDocument;

Parameters

ParameterTypeDescription
layoutLayoutDocument
idsreadonly string[]
tSelectionTransform

Returns

@openseat/core/src/operations.ts

function

translatePoints

function translatePoints(
  points: readonly Point[],
  dx: number,
  dy: number,
): Point[];

Parameters

ParameterTypeDescription
pointsreadonly Point[]
dxnumber
dynumber

Returns

@openseat/core/src/geometry.ts

function

uniqueId

Returns base, or base-2, base-3…, whichever is first not in taken, and adds it to taken.

function uniqueId(base: string, taken: Set<string>): string;

Parameters

ParameterTypeDescription
basestring
takenSet<string>

Returns

string

@openseat/core/src/ids.ts

function

unsellableInventory

The inventory a booking map must not sell: everything in a category listed in metadata.openseat.unsellableCategories, plus everything covered by an ID in metadata.openseat.notForSale:

  • a section covers every seat, row, table and GA area in it, and every booth whose centre lies inside its outline;
  • a row covers its seats;
  • a table booked as a whole gives its table object ID; any other table gives its seats' IDs;
  • a seat gives its seatId, a GA area or booth its inventoryId;
  • a zone section (showSeats: false) gives its own ID, and its seats and tables give nothing (they are not sold on their own).

Category membership follows the inventory manifest: a seat, GA area or booth by its own categoryId; a table booked as a whole by its first seat's; a zone section by its categoryId, else its seats' most common one. Malformed metadata (non-arrays, non-strings) is ignored, and at most 40,000 IDs of each list are read.

function unsellableInventory(
  layout: LayoutDocument,
): UnsellableInventory;

Parameters

ParameterTypeDescription
layoutLayoutDocument

layout takes LayoutDocument:

Returns

@openseat/core/src/category-ops.ts

function

updateSectionSeating

Changes a section's seating and regenerates it (applySectionSeating). A patch of the same kind is merged into the current seating (a key set to undefined is removed, e.g. { rowSeats: undefined }); a different kind, or a section without seating, needs a complete spec. Throws a RangeError when the result is not a valid seating.

function updateSectionSeating(
  layout: LayoutDocument,
  sectionId: string,
  patch: Partial<SectionSeating>,
  opts?: ApplySectionSeatingOptions,
): SectionSeatingResult;

Parameters

ParameterTypeDescription
layoutLayoutDocument
sectionIdstring
patchPartial<SectionSeating>
optsoptionalApplySectionSeatingOptions

Default {}

Returns

@openseat/core/src/section-ops.ts

function

uprightAngle

degrees normalised into (-90, 90], so text drawn at that angle is never upside down.

function uprightAngle(degrees: number): number;

Parameters

ParameterTypeDescription
degreesnumber

Returns

number

@openseat/core/src/object-geometry.ts

function

validateLayout

Validates an untrusted layout document. Returns structured errors and warnings rather than throwing, so editors can show every problem at once. Never throws: an unexpected internal failure is reported as an INVALID_DOCUMENT error.

Accepts only the current schema version. Run migrateLayout first to upgrade older documents.

options.rules re-maps the severity of semantic issues (or turns them off); valid reflects the re-mapped errors.

function validateLayout(
  input: unknown,
  options?: ValidateOptions,
): ValidationResult;

Parameters

ParameterTypeDescription
inputunknown
optionsoptionalValidateOptions

Default {}

Returns

Example

save-layout.ts
import { buildInventoryManifest, diffManifests, validateLayout } from "@openseat/core";

const result = validateLayout(body.layout); // never trust the client's layout
if (!result.valid || !result.layout) throw new Error("invalid layout"); // result.errors says why
const next = buildInventoryManifest(result.layout);
const { removedSeatIds } = diffManifests(previousManifest, next);
// Refuse the save if any removed seat is held or sold for a live event.

Your backend: the REST contract

@openseat/core/src/validate.ts

function

zoneLabelPlacement

Where a GA zone's label goes: centred at the pole of inaccessibility of its outline, turned by labelRotation, upper-case and bold, sized to fit inside (16 at most, never below 8).

function zoneLabelPlacement(area: GaArea): TextPlacement;

Parameters

ParameterTypeDescription
areaGaArea

area takes GaArea:

Returns

@openseat/core/src/label-layout.ts

function

zoneSectionMembers

Rows, tables and seats inside zone sections, mapped to their zone section's ID. These are kept in the document but never drawn, hit or sold on their own. GA areas inside a zone section are not included: they stay zones of their own. Memoised per objects array.

function zoneSectionMembers(layout: {
  readonly objects: readonly LayoutObject[];
}): ReadonlyMap<string, string>;

Parameters

ParameterTypeDescription
layout{ readonly objects: readonly LayoutObject[]; }

Returns

ReadonlyMap<string, string>

@openseat/core/src/zone-ops.ts

function

zoneSectionOf

The zone section a seat, row or table belongs to, if it is inside one.

function zoneSectionOf(
  layout: LayoutDocument,
  objectId: string,
): string | undefined;

Parameters

ParameterTypeDescription
layoutLayoutDocument
objectIdstring

Returns

string | undefined

@openseat/core/src/zone-ops.ts

Classes2

class

GeneratorInputError

Thrown when generator input is outside its valid range. These are programmer errors, not document errors.

class GeneratorInputError extends RangeError

Extends RangeError: its public members apply here too.

Members

MemberTypeDescription
constructorconstructor(message: string)

@openseat/core/src/generators/common.ts

class

SpatialIndex

Uniform-grid spatial index over axis-aligned bounds. Used for viewport culling and hit-test candidate lookup, so both stay proportional to what is on screen rather than to the size of the layout.

A grid suits seating layouts: objects are similar in size and spread evenly. Large objects (sections) are registered in every cell they cover, up to MAX_CELLS_PER_ENTRY; anything bigger is checked linearly on every query. No input makes the index throw or loop without bound.

class SpatialIndex

Members

MemberTypeDescription
cellSizenumber
constructorconstructor(cellSize?: number)

cellSize is clamped to [1e-3, 1e6]; a non-finite value falls back to 64.

sizegetternumber
insertmethod(id: string, bounds: Bounds) => void
removemethod(id: string) => void
clearmethod() => void
getBoundsmethod(id: string) => Bounds | undefined
querymethod(area: Bounds) => string[]

IDs whose bounds intersect area. Exact: candidates from cells are re-checked against their bounds.

queryPointmethod(point: Point, radius?: number) => string[]

Every member is readonly.

@openseat/core/src/spatial-index.ts

Interfaces88

interface

AnnularSectorOptions

interface AnnularSectorOptions

Members

MemberTypeDescription
centerPoint
innerRadiusnumber

0 or less gives a pie wedge with its tip at the centre.

outerRadiusnumber
startAnglenumber

Degrees, screen convention (clockwise on screen from +x).

endAnglenumber
segmentsoptionalnumber

Segments per arc. Defaults to one per 4 degrees of sweep, rounded up.

Every member is readonly.

@openseat/core/src/generators/shapes.ts

interface

ApplySectionSeatingOptions

interface ApplySectionSeatingOptions

Members

MemberTypeDescription
keepLabelsoptionalboolean

Keep existing seat labels instead of applying the seating's seat labeling. Locked labels are always kept.

relabeloptionalboolean

Relabel existing rows from section.rowLabeling instead of keeping their labels.

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

ArcSectionParams

interface ArcSectionParams

Members

MemberTypeDescription
centerPoint

Centre of the arc (the stage or field centre), in layout coordinates.

innerRadiusnumber

Radius of the front row.

rowsnumber
rowSpacingnumber
startAnglenumber

Degrees, screen convention; endAngle > startAngle.

endAnglenumber
seatSpacingnumber
edgeMarginoptionalnumber

Clear distance from the radial edges to the outermost seat centres. Defaults to the seat radius + 4.

seatShapeoptionalSeatShape
labeloptionalstring
rowLabelingoptionalRowLabeling
seatLabelingoptionalSeatLabeling
categoryIdoptionalstring
rowSeatsoptionalreadonly number[]

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

ArenaField

The playing area (or stage) in the middle of the arena.

interface ArenaField

Members

MemberTypeDescription
widthnumber
heightnumber
cornerRadiusnumber

Clamped to half the smaller side.

labeloptionalstring

Text drawn on the field. Defaults to the field kind's name ("Rink", "Court", "Pitch", "Stage").

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

ArenaNumbering

interface ArenaNumbering

Members

MemberTypeDescription
directionoptional"clockwise" | "counterclockwise"

Defaults to "clockwise".

Default "clockwise"

startOffsetoptionalnumber

Rotates the numbering sequence, which by default starts at the first (left-most) section of the top side. -1 gives the first number to the last section before it (the last top-left corner fan when the corners are filled), as in a typical hockey arena. Defaults to 0.

Default 0

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

ArenaOptions

interface ArenaOptions

Members

MemberTypeDescription
idPrefixstring

Prefix of every generated object and category ID.

centerPoint

Centre of the field, in layout coordinates.

fieldArenaField
tiersreadonly ArenaTier[]

Tiers from the field outwards.

numberingoptionalArenaNumbering
seatLabelingoptionalSeatLabeling

How seats are numbered within each row. Defaults to 1, 2, 3… from each spectator's left.

venueoptional{ readonly margin: number; readonly shape?: "rect" | "ellipse"; }

Venue outline around the outermost tier. Defaults to a rounded rectangle 40 units out.

fieldKindoptionalArenaFieldKind

Defaults to "rink". Sets the field's default label, colours and markings.

Default "rink"

titleoptionalstring

Human-readable name, e.g. "Ice hockey arena"; createArenaLayout's default layout name.

balanceSectionsoptionalboolean

Evens out the seats per section around each tier. The tier keeps its total section count (never more), but the sections are redistributed between the long sides, the short sides and the corners so the sections on every side and in every corner hold about the same number of seats: without it, a round-ended field gives huge corner fans next to thin side blocks. A side or corner left at 0 stays empty, and a side too short for any section gives its share to the others. Off by default, so existing options generate exactly what they did before.

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

ArenaTier

One ring ("level") of sections around the field.

interface ArenaTier

Members

MemberTypeDescription
labeloptionalstring

Name of the tier, e.g. "100 Level". Used for its generated category.

firstNumbernumber

Number of the tier's first section in numbering order, e.g. 101.

rowsnumber
rowSpacingnumber

Distance between rows.

seatSpacingnumber

Distance between seat centres along a row.

gapnumber

Distance from the field edge (tier 0) or from the previous tier's outer edge.

sectionsPerLongSidenumber

Sections along each long (top and bottom) side; 0 leaves the side empty.

sectionsPerShortSidenumber

Sections along each short (left and right) side; 0 leaves the side empty.

sectionsPerCornernumber

Fan sections per corner; 0 leaves the corners empty.

extraCornerSectionsoptionalreadonly [ number, number, number, number ]

Extra fan sections added to sectionsPerCorner in each corner, clockwise from the top-right: [top-right, bottom-right, bottom-left, top-left]. Lets a tier have an odd section count, like the 19-section lower bowl of the hockey preset (three fans in the top-left corner, two elsewhere).

aisleWidthnumber

Clear width of the aisles between neighbouring sections.

categoryIdoptionalstring

Category of the tier's seats. Without it the generator creates one category per tier.

seatShapeoptionalSeatShape

Defaults to a circle of radius 0.4 x the smaller of seat and row spacing.

rowLabelingoptionalRowLabeling

Defaults to A, B, C… front to back.

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

BlockSectionParams

interface BlockSectionParams

Members

MemberTypeDescription
positionPoint

Centre of the block (the section's origin), in layout coordinates.

rotationoptionalnumber
labeloptionalstring

Default nextFreeSectionLabel

seatingBlockSeating
rowLabelingoptionalRowLabeling
outlineoptional"auto" | "none"

Defaults to "auto". "none" still stores the outline but view mode does not draw it.

Default "auto"

categoryIdoptionalstring

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

BoothGridOptions

interface BoothGridOptions

Members

MemberTypeDescription
idPrefixstring

Prefix for booth object IDs: ${idPrefix}:booth:${number}.

originPoint

Centre of the first (top-left) booth.

columnsnumber
rowsnumber
widthnumber
heightnumber
gapXnumber

Space between booths horizontally.

gapYnumber

Space between booths vertically, for example an aisle between booth rows.

labelPrefixoptionalstring

Displayed label is ${labelPrefix}${number}. Defaults to "Booth ".

Default "Booth "

inventoryPrefixoptionalstring

When set, each booth gets inventoryId: ${inventoryPrefix}${number} so it can be sold as a unit.

categoryIdoptionalstring
startoptionalnumber

First booth number. Defaults to 1.

Default 1

Every member is readonly.

@openseat/core/src/generators/booths.ts

interface

Bounds

interface Bounds

Members

MemberTypeDescription
minXnumber
minYnumber
maxXnumber
maxYnumber

Every member is readonly.

@openseat/core/src/geometry.ts

interface

BuildSectionContentsOptions

interface BuildSectionContentsOptions

Members

MemberTypeDescription
idPrefixoptionalstring

Prefix of generated object IDs. Defaults to the section ID.

existingoptionalLayoutDocument

Document the contents will join; generated object IDs and seat IDs are made unique against it.

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

ClipboardPayload

Serializable clipboard content: deep copies of objects with what they carry and the categories they use.

interface ClipboardPayload

Members

MemberTypeDescription
format"openseat/objects"
version1
sourceLayoutIdstring
objectsreadonly LayoutObject[]
categoriesreadonly Category[]
boundsBounds

World bounds of the copied objects.

Every member is readonly.

@openseat/core/src/operations.ts

interface

CreateArenaLayoutOptions

Options of createArenaLayout.

interface CreateArenaLayoutOptions extends ArenaOptions

Extends ArenaOptions

Members

MemberTypeDescription
layoutIdstring
nameoptionalstring

Defaults to title (a preset's title, e.g. "Ice hockey arena"), else "Arena".

idPrefixstring

Prefix of every generated object and category ID.

From ArenaOptions

centerPoint

Centre of the field, in layout coordinates.

From ArenaOptions

fieldArenaField

From ArenaOptions

tiersreadonly ArenaTier[]

Tiers from the field outwards.

From ArenaOptions

numberingoptionalArenaNumbering

From ArenaOptions

seatLabelingoptionalSeatLabeling

How seats are numbered within each row. Defaults to 1, 2, 3… from each spectator's left.

From ArenaOptions

venueoptional{ readonly margin: number; readonly shape?: "rect" | "ellipse"; }

Venue outline around the outermost tier. Defaults to a rounded rectangle 40 units out.

From ArenaOptions

fieldKindoptionalArenaFieldKind

Defaults to "rink". Sets the field's default label, colours and markings.

From ArenaOptions

Default "rink"

titleoptionalstring

Human-readable name, e.g. "Ice hockey arena"; createArenaLayout's default layout name.

From ArenaOptions

balanceSectionsoptionalboolean

Evens out the seats per section around each tier. The tier keeps its total section count (never more), but the sections are redistributed between the long sides, the short sides and the corners so the sections on every side and in every corner hold about the same number of seats: without it, a round-ended field gives huge corner fans next to thin side blocks. A side or corner left at 0 stays empty, and a side too short for any section gives its share to the others. Off by default, so existing options generate exactly what they did before.

From ArenaOptions

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

CreateLayoutOptions

interface CreateLayoutOptions

Members

MemberTypeDescription
idstring
namestring
widthnumber

Canvas width in layout units.

heightnumber

Canvas height in layout units.

gridSizeoptionalnumber
categoriesoptionalreadonly Category[]
metadataoptionalRecord<string, unknown>

Every member is readonly.

@openseat/core/src/factory.ts

interface

CreateZoneOptions

interface CreateZoneOptions

Members

MemberTypeDescription
shape"rect" | "rounded" | "polygon" | "trapezoid"

rect: plain; rounded: corners rounded by 12% of the shorter side; trapezoid: one edge inset 15% per side; polygon: points.

rectoptionalZoneRect

World rectangle for rect, rounded and trapezoid.

pointsoptionalreadonly Point[]

World corners for polygon (at least 3).

labelstring
capacitynumber

Whole number from 1 to 1,000,000.

seatingGaSeating
categoryIdoptionalstring
inventoryIdoptionalstring

Host inventory key; defaults to an unused key derived from the label.

flipoptionalboolean

Trapezoid only: false (default) keeps the top edge full width and insets the bottom; true the reverse.

Every member is readonly.

@openseat/core/src/zone-ops.ts

interface

CurvedRowsOptions

interface CurvedRowsOptions extends GeneratorBaseOptions

Extends GeneratorBaseOptions

Members

MemberTypeDescription
rowCountnumber
seatsPerRownumber
centerPoint

Centre of the arc.

innerRadiusnumber

Radius of the first row.

rowSpacingnumber

Radial distance between rows. Must be positive when rowCount is greater than 1.

startAnglenumber

Start angle in degrees. Angles follow screen convention: 0 points right, 90 points down.

endAnglenumber

End angle in degrees. Seats are spread evenly from start to end, inclusive.

rowLabelsoptionalreadonly string[]
rowLabelingoptionalRowLabeling

Row label sequence used when rowLabels is absent. Row 0 (the innermost) is the front row.

tangentRotationoptionalboolean

When true, each seat is rotated to follow the arc's tangent.

seatSpacingoptionalnumber

Arc length between seat centres. When given, seats are spaced by this distance on every row, centred on the middle angle, instead of being spread from startAngle to endAngle.

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

sectionIdoptionalstring

From GeneratorBaseOptions

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptionalSeatShape

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/rows.ts

interface

DuplicateOptions

interface DuplicateOptions

Members

MemberTypeDescription
sectionIdoptionalreadonlystring | null

Section for copies whose section was not copied with them. Absent: keep the original section. null: leave them outside any section.

@openseat/core/src/operations.ts

interface

DuplicateResult

interface DuplicateResult

Members

MemberTypeDescription
layoutLayoutDocument
idsreadonly string[]

New IDs of the duplicated top-level objects, in input order. Select these after duplicating.

idMapReadonlyMap<string, string>

Old object ID -> new object ID, for every copied object.

rowIdsstring[]

IDs of the copied rows.

Every member is readonly.

@openseat/core/src/operations.ts

interface

FillPlanOptions

Options of planFillRows: the geometric part of SectionSeatingOptions.

interface FillPlanOptions

Members

MemberTypeDescription
boundaryreadonly Point[]

Outline in layout coordinates. Concave shapes are supported.

seatSpacingnumber
rowSpacingnumber
angleoptionalnumber

Direction rows run, in degrees. Defaults to 0.

Default 0

marginoptionalnumber

Clearance between seat edges and the boundary. Defaults to 2.

Default 2

aisleEveryoptionalnumber

Insert an aisle after every N seats in a row; 0 for none.

aisleWidthoptionalnumber

Extra space of each aisle. Defaults to seatSpacing.

Default seatSpacing

minSeatsPerRowoptionalnumber

Rows with fewer seats are skipped. Defaults to 1.

Default 1

reverseoptionalboolean

Fill from the far side (bottom first when angle is 0).

seatShapeoptionalSeatShape

Every member is readonly.

@openseat/core/src/generators/section.ts

interface

FillRowPlan

One planned row of a filled section.

interface FillRowPlan

Members

MemberTypeDescription
positionsreadonly Point[]

Seat centres in layout coordinates, in seating order.

gapsreadonly RowGap[]

Row gaps that reproduce the positions with a straight row layout anchored at the first seat: span breaks of concave outlines and aisles.

Every member is readonly.

@openseat/core/src/generators/section.ts

interface

GeneratedArena

interface GeneratedArena

Members

MemberTypeDescription
objectsLayoutObject[]

The field (a stage object) followed by each section, its seats and rows.

venueVenue
sectionIdsstring[]

Section IDs in tier order, each tier in numbering order.

categoriesCategory[]

One category per tier that has no categoryId.

Every member is readonly.

@openseat/core/src/generators/arena.ts

interface

GeneratedRows

Output of a row generator: a row object per row, plus the seat objects it references.

interface GeneratedRows

Members

MemberTypeDescription
objectsLayoutObject[]
seatIdsstring[]

Seat IDs in generation order (row by row, left to right).

Every member is readonly.

@openseat/core/src/generators/rows.ts

interface

GeneratorBaseOptions

Options shared by every generator.

interface GeneratorBaseOptions

Members

MemberTypeDescription
idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

sectionIdoptionalstring
categoryIdoptionalstring
seatShapeoptionalSeatShape
numberingoptionalSeatNumbering

Every member is readonly.

@openseat/core/src/generators/common.ts

interface

HitContext

Where the user is editing and what a click selects.

interface HitContext

Members

MemberTypeDescription
scopeSectionIdstring | null

The section being edited ("entered"), or null at the top level.

scopeGroupIdstring | null

The row or table being edited, or null.

granularity"objects" | "seats"

"seats" selects individual seats wherever they are.

Every member is readonly.

@openseat/core/src/membership.ts

interface

InventoryManifest

A flat, backend-friendly list of everything sellable in a layout: one entry per seat with its effective section, row or table and category, plus the areas sold as units (GA areas, booths with an inventory ID, tables booked as a whole). Hosts store it next to the layout on save and diff it against the previous save to reconcile inventory (diffManifests).

interface InventoryManifest

Members

MemberTypeDescription
version1
layoutIdstring
namestring
revisionnumber
categoriesreadonly InventoryManifestCategory[]
sectionsreadonly InventoryManifestSection[]
seatsreadonly InventoryManifestSeat[]
areasreadonly InventoryManifestArea[]

Every member is readonly.

@openseat/core/src/manifest.ts

interface

InventoryManifestArea

interface InventoryManifestArea

Members

MemberTypeDescription
inventoryIdstring

GA area and booth: their inventoryId. Table booked as a whole: the table's object ID. Zone section: the section's ID.

objectIdstring
kind"ga" | "booth" | "table"

Zone sections are listed as "ga": they are sold by quantity like GA zones.

objectTypeoptional"ga" | "section"

"section" for a zone section (showSeats: false); absent for every other area.

seatedoptionalboolean

True for a seated zone: a GA zone with seating: "seated", and every zone section. Absent otherwise.

labelstring
capacitynumber

GA: its capacity; zone section: its zone capacity; booth: 1; table: its seat count.

categoryIdoptionalstring

A zone section's categoryId, else the most common category of its seats.

sectionIdoptionalstring

Every member is readonly.

@openseat/core/src/manifest.ts

interface

InventoryManifestCategory

interface InventoryManifestCategory

Members

MemberTypeDescription
idstring
namestring
colouroptionalstring

Every member is readonly.

@openseat/core/src/manifest.ts

interface

InventoryManifestSeat

interface InventoryManifestSeat

Members

MemberTypeDescription
seatIdstring

Public seat ID, the inventory key.

objectIdstring

Layout object ID of the seat.

labelstring
sectionIdoptionalstring
sectionLabeloptionalstring
rowIdoptionalstring
rowLabeloptionalstring
tableIdoptionalstring
tableLabeloptionalstring
categoryIdoptionalstring
xnumber

World position, rounded to 3 decimals.

ynumber
wheelchairboolean
companionSeatboolean

Every member is readonly.

@openseat/core/src/manifest.ts

interface

InventoryManifestSection

interface InventoryManifestSection

Members

MemberTypeDescription
idstring
labelstring
categoryIdoptionalstring
rowCountnumber

Rows whose sectionId is this section.

seatCountnumber

Seats whose effective section is this section.

Every member is readonly.

@openseat/core/src/manifest.ts

interface

LabelSeatOverlap

One piece of text over one seat, from findLabelSeatOverlaps.

interface LabelSeatOverlap

Members

MemberTypeDescription
objectIdstring
kindTextBoxKind
seatObjectIdstring

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

LabelSeatOverlapOptions

interface LabelSeatOverlapOptions

Members

MemberTypeDescription
lodLabelLod
kindsoptionalreadonly TextBoxKind[]

Only these kinds of text. Default: all.

toleranceoptionalnumber

Boxes must overlap by more than this on both axes. Default 0 (touching is fine).

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

LayoutIndex

The membership hierarchy of a layout, derived from the flat object list:

section ─┬─ row ── seat ├─ table ── seat ├─ GA area └─ loose seat (a seat in no row or table)

sectionId on rows, tables, GA areas and loose seats is the source of truth; on grouped seats it is only a cache. A seat belongs to the first row or table (in document order) that lists it, matching the structural checks. Every other object (stage, booth, label, ...) is top level.

interface LayoutIndex

Members

MemberTypeDescription
byIdReadonlyMap<string, LayoutObject>

First object with each ID, as in validation.

groupOfSeatReadonlyMap<string, string>

Seat object ID -> owning row or table ID.

contentsOfSectionReadonlyMap<string, readonly string[]>

Section ID -> direct contents (rows, tables, GA areas and loose seats whose sectionId is the section), in document order. Only existing sections.

Every member is readonly.

@openseat/core/src/membership.ts

interface

LayoutIssue

A structured validation finding. path is a dotted field path into the document.

interface LayoutIssue

Members

MemberTypeDescription
codeLayoutIssueCode
severity"error" | "warning"
messagestring
pathstring

Dotted path such as objects.3.seatObjectIds.0.

objectIdoptionalstring

Set when the issue belongs to a specific object.

Every member is readonly.

@openseat/core/src/validate.ts

interface

LayoutMigration

A single explicit step between two adjacent schema versions. Migrations receive a plain object and return a new object; they must not mutate input.

interface LayoutMigration

Members

MemberTypeDescription
fromnumber
tonumber
migrate(document: Record<string, unknown>) => Record<string, unknown>

Every member is readonly.

@openseat/core/src/migrate.ts

interface

LayoutTextBox

One piece of text and its reserved world box.

interface LayoutTextBox

Members

MemberTypeDescription
kindTextBoxKind
objectIdstring
boxBounds

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

ManifestDiff

interface ManifestDiff

Members

MemberTypeDescription
addedSeatIdsstring[]

In the next manifest only (next order).

removedSeatIdsstring[]

In the previous manifest only (previous order).

movedSeatIdsstring[]

In both, at a different position (next order).

relabeledSeatIdsstring[]

In both, with a different seat, row, table or section label (next order).

Every member is readonly.

@openseat/core/src/manifest.ts

interface

MigrationResult

interface MigrationResult

Members

MemberTypeDescription
valueunknown

The migrated document, or the original input when no migration was needed.

errorsLayoutIssue[]

Errors encountered while migrating. Empty when the migration chain completed.

appliedVersionsreadonly number[]

Every member is readonly.

@openseat/core/src/migrate.ts

interface

MinRoundTableRadiusOptions

interface MinRoundTableRadiusOptions

Members

MemberTypeDescription
seatShapeoptionalSeatShape

Seat shape; defaults to the default seat circle.

gapoptionalnumber

Table edge to seat centre (seatDistance - radius), kept when the radius changes. Defaults to seat radius + 4, the generators' default; never taken below the seat radius (seats do not sit under the table edge).

minGapoptionalnumber

Clear space between neighbouring seats. Defaults to DEFAULT_TABLE_SEAT_GAP.

Default DEFAULT_TABLE_SEAT_GAP

Every member is readonly.

@openseat/core/src/table-ops.ts

interface

ObjectTransform

interface ObjectTransform

Members

MemberTypeDescription
positionPoint
rotationnumber

Absolute rotation in degrees.

scaleXnumber

Scale relative to the object's current size. 1 leaves dimensions unchanged.

scaleYnumber

Every member is readonly.

@openseat/core/src/operations.ts

interface

ParseOptions

interface ParseOptions

Members

MemberTypeDescription
migrationsoptionalreadonlyreadonly LayoutMigration[]

Extra migrations, merged with the built-in chain.

@openseat/core/src/serialize.ts

interface

PasteOptions

interface PasteOptions

Members

MemberTypeDescription
atoptionalPoint

Centre the pasted content on this point.

offsetoptionalPoint

Offset from the copied position, used when at is absent. Default (0, 0).

Every member is readonly.

@openseat/core/src/operations.ts

interface

PathCaptionPlacement

Where a divider's caption is drawn, from pathCaptionPlacement.

interface PathCaptionPlacement

Members

MemberTypeDescription
atPoint

World centre of the caption: the point halfway along the path.

rotationnumber

Degrees, the direction of the path there, normalised into (-90, 90] so the text stays upright.

textstring

The drawn text (dividerCaptionText).

fontSizenumber
widthnumber

Unrotated size of the reserved text box (estimateTextBox).

heightnumber
boxBounds

World AABB of the rotated text box.

distancenumber

Arc length from the path start to at, for breaking the line around the caption.

lengthnumber

Total arc length of the path.

Every member is readonly.

@openseat/core/src/object-geometry.ts

interface

Placement

Object placement: position is the local origin, rotation is in degrees.

interface Placement

Members

MemberTypeDescription
positionPoint
rotationnumber

Every member is readonly.

@openseat/core/src/geometry.ts

interface

Point

Pure 2D geometry helpers. Coordinates are in layout units; the y axis points down, matching canvas and SVG conventions. Angles are in degrees, measured clockwise on screen (positive rotation turns +x towards +y).

interface Point

Members

MemberTypeDescription
xnumber
ynumber

Every member is readonly.

@openseat/core/src/geometry.ts

interface

RectTableOptions

interface RectTableOptions extends GeneratorBaseOptions

Extends GeneratorBaseOptions

Members

MemberTypeDescription
labelstring
centerPoint
widthnumber
heightnumber
seatsPerEdgeRectTableSeatCounts

Seats per edge. Edges not listed have no seats. Counts are placed evenly along each edge.

seatOffsetoptionalnumber

Distance from the table edge to seat centres. Defaults to the seat radius plus 4.

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

sectionIdoptionalstring

From GeneratorBaseOptions

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptionalSeatShape

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/tables.ts

interface

RectTableSeatCounts

interface RectTableSeatCounts

Members

MemberTypeDescription
topoptionalnumber
rightoptionalnumber
bottomoptionalnumber
leftoptionalnumber

Every member is readonly.

@openseat/core/src/generators/tables.ts

interface

RegenerationReport

What a regeneration did to a group's seats, by seat object ID. Hosts should surface removed: those public seat IDs no longer exist, and any inventory mapped to them needs attention.

interface RegenerationReport

Members

MemberTypeDescription
retainedreadonly string[]
addedreadonly string[]
removedreadonly string[]
removedSeatIdsreadonly string[]

Public seat IDs of removed seats, for reconciling inventory.

Every member is readonly.

@openseat/core/src/regenerate.ts

interface

RegenerationResult

interface RegenerationResult

Members

MemberTypeDescription
layoutLayoutDocument
reportRegenerationReport
messageoptionalstring

A note for the user about how the edit was carried out (e.g. how new seats were numbered).

Every member is readonly.

@openseat/core/src/regenerate.ts

interface

RemoveOptions

interface RemoveOptions

Members

MemberTypeDescription
withContentsoptionalboolean

Remove a section's rows, tables, GA areas and loose seats with it. Default true.

Default true

forceoptionalboolean

Remove effectively locked objects too. Default false.

Default false

pruneEmptyRowsoptionalboolean

Remove rows that lost seats and now have none. Default true.

Default true

Every member is readonly.

@openseat/core/src/operations.ts

interface

RenumberOptions

Renumbering of tables and booths: rewrites their labels in reading order (front to back, then left to right, or by columns). Object IDs, inventory IDs and seat IDs are never touched, so renumbering is safe on a layout whose inventory is already on sale.

interface RenumberOptions

Members

MemberTypeDescription
order"rows" | "columns"

"rows": front to back (smaller y first), each row left to right. "columns": left to right, each column front to back.

prefixoptionalstring

Text placed before each number. Defaults to "".

Default ""

startoptionalnumber

First number. Defaults to 1.

Default 1

rowToleranceUnitsoptionalnumber

Objects whose centres differ by at most this much across the reading direction belong to the same row (or column). Defaults to half the smallest object depth among the targets.

Every member is readonly.

@openseat/core/src/renumber-ops.ts

interface

RepairOptions

interface RepairOptions

Members

MemberTypeDescription
leveloptionalreadonly"errors" | "all"

"errors" (default) fixes problems that make references ambiguous or dangling. "all" also re-syncs seat caches and table capacity and removes unreferenced empty rows.

@openseat/core/src/structure-checks.ts

interface

ResolvedRowLabel

A row label from resolveRowLabelPlacements: the core placement, pushed clear of seats.

interface ResolvedRowLabel extends RowLabelPlacement

Extends RowLabelPlacement

Members

MemberTypeDescription
fontSizenumber
boxBounds

World AABB of the label's reserved box.

pushednumber

Units the label was pushed outward along the row to clear seats (0 when it was clear).

hiddenboolean

True when no position within the pushes clears every seat: do not draw it.

positionPoint

From RowLabelPlacement

rotationnumber

Text rotation in degrees, normalised into (-90, 90] so the text is never upside down.

From RowLabelPlacement

align"left" | "right"

Text alignment relative to position.

From RowLabelPlacement

side"start" | "end"

From RowLabelPlacement

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

RetentionOptions

interface RetentionOptions

Members

MemberTypeDescription
keepLabelsoptionalboolean

Keep existing seat labels instead of the newly generated ones. Default false.

Default false

slotsoptionalreadonly (string | null)[]

Identity mapping: generated[i] takes over the existing seat whose object ID is slots[i]; null means a new seat. Existing seats of the group that are not listed are removed and reported. Without slots, the i-th generated seat takes over the i-th existing seat.

slotIndexesoptionalreadonly number[]

Slot index of each generated seat, used to name new seats (${group.id}:s${slot + 1}). Defaults to the generated index.

respectLabelLocksoptionalboolean

Seats with labelLocked keep their label. Default true.

Default true

newSeatIdoptional(slot: number, label: string) => string | undefined

Public seat ID for a new seat at slot with label label; made unique against the layout (a -2 suffix only on a real collision). Undefined falls back to the inferred prefix plus a number.

Every member is readonly.

@openseat/core/src/regenerate.ts

interface

RoundTableOptions

interface RoundTableOptions extends GeneratorBaseOptions

Extends GeneratorBaseOptions

Members

MemberTypeDescription
labelstring

Label shown on the table and used in its generated IDs. Must be unique within idPrefix.

centerPoint
tableRadiusnumber
seatCountnumber
seatDistanceoptionalnumber

Distance from the table centre to each seat centre. Defaults to the table radius plus the seat's own radius plus a small gap, so seats sit clear of the edge.

startAngleoptionalnumber

Angle of the first seat in degrees, screen convention. Defaults to -90 (top of the table).

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

sectionIdoptionalstring

From GeneratorBaseOptions

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptionalSeatShape

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/tables.ts

interface

RowCategoryBand

Assigns a category to a band of rows. Rows are numbered from 1, in generation order.

interface RowCategoryBand

Members

MemberTypeDescription
fromRownumber
toRownumber
categoryIdstring

Every member is readonly.

@openseat/core/src/generators/section.ts

interface

RowLabelPlacement

Where a row label is drawn, as computed by rowLabelPlacements.

interface RowLabelPlacement

Members

MemberTypeDescription
positionPoint
rotationnumber

Text rotation in degrees, normalised into (-90, 90] so the text is never upside down.

align"left" | "right"

Text alignment relative to position.

side"start" | "end"

Every member is readonly.

@openseat/core/src/row-geometry.ts

interface

RowLayoutFit

Result of fitRowLayout.

interface RowLayoutFit

Members

MemberTypeDescription
placementPlacement
layoutRowLayout
residualnumber

Largest distance between a stored seat and the place the fitted layout puts it.

Every member is readonly.

@openseat/core/src/row-geometry.ts

interface

RowRegenerationOptions

interface RowRegenerationOptions extends RetentionOptions

Extends RetentionOptions

Members

MemberTypeDescription
seatCountnumber
seatSpacingnumber
seatShapeoptionalSeatShape

Seat shape for every seat of the row. Defaults to each seat's own shape (new seats copy their neighbour).

numberingStartoptionalnumber

First seat number for generated labels. Default: the row's labeling start, or 1.

keepLabelsoptionalboolean

Keep existing seat labels instead of the newly generated ones. Default false.

From RetentionOptions

Default false

slotsoptionalreadonly (string | null)[]

Identity mapping: generated[i] takes over the existing seat whose object ID is slots[i]; null means a new seat. Existing seats of the group that are not listed are removed and reported. Without slots, the i-th generated seat takes over the i-th existing seat.

From RetentionOptions

slotIndexesoptionalreadonly number[]

Slot index of each generated seat, used to name new seats (${group.id}:s${slot + 1}). Defaults to the generated index.

From RetentionOptions

respectLabelLocksoptionalboolean

Seats with labelLocked keep their label. Default true.

From RetentionOptions

Default true

newSeatIdoptional(slot: number, label: string) => string | undefined

Public seat ID for a new seat at slot with label label; made unique against the layout (a -2 suffix only on a real collision). Undefined falls back to the inferred prefix plus a number.

From RetentionOptions

Every member is readonly.

@openseat/core/src/regenerate.ts

interface

RowSlotPose

A seat place derived from a row layout.

interface RowSlotPose

Members

MemberTypeDescription
positionPoint
rotationnumber

Seat rotation in degrees. NaN when the layout's seatRotation is "keep" (the caller keeps the old value).

Every member is readonly.

@openseat/core/src/row-geometry.ts

interface

SeatBox

World AABB of a drawn seat.

interface SeatBox

Members

MemberTypeDescription
objectIdstring
boxBounds

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

SeatInput

interface SeatInput

Members

MemberTypeDescription
idPrefixstring
groupLabelstring
seatNumbernumber
labelstring
positionPoint
rotationnumber
rowLabeloptionalstring
sectionIdoptionalstring
categoryIdoptionalstring
shapeSeatShape

Every member is readonly.

@openseat/core/src/generators/common.ts

interface

SeatNumbering

interface SeatNumbering

Members

MemberTypeDescription
startoptionalnumber

First seat number in each row or table. Defaults to 1.

Default 1

prefixoptionalstring

Text placed before the number in the displayed label.

suffixoptionalstring

Text placed after the number in the displayed label.

formatoptionalLabelFormat

Label format. Defaults to numeric.

Default "numeric"

stepoptionalnumber

Difference between consecutive seat numbers (2 numbers odd or even seats). Defaults to 1.

Default 1

directionoptional"ltr" | "rtl"

"rtl" gives the last seat of a row the first number. Defaults to "ltr".

Default "ltr"

Every member is readonly.

@openseat/core/src/generators/common.ts

interface

SectionContents

interface SectionContents

Members

MemberTypeDescription
rowsRow[]

Rows front to back.

seatsSeat[]
boundaryoptionalPoint[]

Section-local outline; only for outline "auto" or arc seating.

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

SectionFromSelectionOptions

interface SectionFromSelectionOptions

Members

MemberTypeDescription
labeloptionalstring

Default nextFreeSectionLabel

paddingoptionalnumber

Clearance between the seats' edges and the outline. Defaults to 8.

Default 8

shapeoptional"hull" | "bounds"

"hull" (default): convex envelope; "bounds": axis-aligned rectangle.

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

SectionSeatingOptions

interface SectionSeatingOptions extends Omit<
  GeneratorBaseOptions,
  "sectionId"
>

Extends Omit<GeneratorBaseOptions, "sectionId">

Members

MemberTypeDescription
sectionIdstring

Object ID for the generated section. Seats and rows reference it.

labelstring
boundaryreadonly Point[]

Section outline in layout coordinates. Concave shapes are supported.

seatSpacingnumber

Distance between seat centres along a row.

rowSpacingnumber

Distance between rows.

angleoptionalnumber

Direction rows run, in degrees. 0 gives horizontal rows filled top to bottom; 90 gives vertical rows. Seats are rotated to match.

marginoptionalnumber

Clearance between seat edges and the boundary. Defaults to 2.

Default 2

aisleEveryoptionalnumber

Insert an aisle after every N seats in a row.

aisleWidthoptionalnumber

Width of each aisle. Defaults to seatSpacing.

Default seatSpacing

minSeatsPerRowoptionalnumber

Rows with fewer seats than this are skipped. Defaults to 1.

Default 1

reverseoptionalboolean

Fill from the far side of the section instead (bottom first when angle is 0).

rowLabelsoptionalreadonly string[]
rowCategoriesoptionalreadonly RowCategoryBand[]

Category bands, for example rows 1–3 VIP and the rest standard. Falls back to categoryId.

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptional{ kind: "circle"; radius: number; } | { kind: "rect"; width: number; height: number; }

From GeneratorBaseOptions

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/section.ts

interface

SectionSeatingResult

interface SectionSeatingResult

Members

MemberTypeDescription
layoutLayoutDocument
reportRegenerationReport

Seat changes across all rows of the section.

addedRowIdsstring[]
removedRowIdsstring[]

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

SectionTitlePlacement

Where a section's title goes.

interface SectionTitlePlacement

Members

MemberTypeDescription
atPoint

World centre of the text.

fontSizenumber
rotationnumber

Degrees; 0 for header bands (upright whatever the section's rotation), labelRotation inside.

textstring

The text to draw: upper-case inside (overview and zones), the label as written in a header band.

widthnumber

Unrotated size of the reserved box.

heightnumber
boxBounds

World AABB of the reserved box.

where"inside" | "above" | "below" | "left" | "right" | "hidden"

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

SelectionTransform

A transform of a whole selection about a pivot, as produced by a group transformer: M = T(pivot + translate) · R(rotation) · S(sx·flipX, sy·flipY) · T(-pivot).

interface SelectionTransform

Members

MemberTypeDescription
pivotPoint
translateoptionalPoint
rotationoptionalnumber

Degrees, clockwise on screen.

scaleXoptionalnumber
scaleYoptionalnumber
flipXoptionalboolean
flipYoptionalboolean

Every member is readonly.

@openseat/core/src/operations.ts

interface

SellableSummary

Counts behind the editor's "Tickets for sale" figure.

interface SellableSummary

Members

MemberTypeDescription
seatsnumber

Seats that can be sold, including the seats of tables booked as a whole (not those of zone sections).

gaPlacesnumber

GA and zone-section capacity that can be sold.

boothsnumber

Booths with an inventory ID that can be sold.

wholeTablesnumber

Tables booked as a whole that can be sold.

notForSaleSeatsnumber

Seats held back (unsellable category or not for sale), including those of whole tables.

notForSalePlacesnumber

GA capacity and booths held back.

totalSellablenumber

seats + gaPlaces + booths.

Every member is readonly.

@openseat/core/src/category-ops.ts

interface

SetObjectsCategoryOptions

interface SetObjectsCategoryOptions

Members

MemberTypeDescription
withMembersoptionalreadonlyboolean

Also write the category on the members of each unit: a section's seats, a row's or table's seats. Rows and tables carry no category themselves.

@openseat/core/src/category-ops.ts

interface

SetRowLayoutOptions

interface SetRowLayoutOptions

Members

MemberTypeDescription
keepLabelsoptionalboolean

Keep existing seat labels instead of applying the layout's labeling.

seatShapeoptionalSeatShape

Shape for every seat of the row. Default: each seat keeps its own; new seats copy their nearest neighbour.

pinoptional"anchor" | "first-retained"

"anchor" (default) keeps row.position; "first-retained" moves the row so its first retained seat stays put.

Every member is readonly.

@openseat/core/src/row-ops.ts

interface

SimplicityBudget

A work allowance shared by several polygonSimplicity calls: candidate edge pairs (pairs whose x extents overlap) left to look at.

interface SimplicityBudget

Members

MemberTypeDescription
remainingnumber

@openseat/core/src/geometry.ts

interface

StraightRowsOptions

interface StraightRowsOptions extends GeneratorBaseOptions

Extends GeneratorBaseOptions

Members

MemberTypeDescription
rowCountnumber
seatsPerRownumber
originPoint

Position of the first seat in the first row.

seatSpacingnumber

Horizontal distance between adjacent seats in a row.

rowSpacingnumber

Vertical distance between rows.

rowLabelsoptionalreadonly string[]

Row labels. Defaults to A, B, C… and must be unique.

rowLabelingoptionalRowLabeling

Row label sequence used when rowLabels is absent. Row 0 is the front row.

staggeroptionalnumber

Horizontal offset applied to every odd-numbered row, for staggered seating.

aisleAfteroptionalreadonly number[]

Seat numbers (1-based, within a row) after which an aisle gap is inserted. Entry k places the gap between seat k and seat k+1.

aisleGapoptionalnumber

Extra horizontal space added at each aisle gap. Defaults to seatSpacing.

Default seatSpacing

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

sectionIdoptionalstring

From GeneratorBaseOptions

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptionalSeatShape

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/rows.ts

interface

StructureRepair

One change made by repairStructure.

interface StructureRepair

Members

MemberTypeDescription
kindStructureRepairKind
objectIdstring

The object that was changed or removed.

detailstring

Every member is readonly.

@openseat/core/src/structure-checks.ts

interface

TableEdgeCounts

Seat counts on the four edges of a rectangular table.

interface TableEdgeCounts

Members

MemberTypeDescription
topnumber
rightnumber
bottomnumber
leftnumber

Every member is readonly.

@openseat/core/src/table-ops.ts

interface

TableEditOptions

interface TableEditOptions

Members

MemberTypeDescription
growoptionalboolean

When seats would come closer than DEFAULT_TABLE_SEAT_GAP, enlarge the table (round: radius and seat distance; rect: the crowded edges) instead of dropping seats. Default true.

Default true

keepLabelsoptionalboolean

Keep existing seat labels instead of renumbering clockwise. Default false.

Default false

respectLabelLocksoptionalboolean

Seats with labelLocked keep their label. Default true.

Default true

Every member is readonly.

@openseat/core/src/table-ops.ts

interface

TableEditPatch

Changes to a table's shape and seat arrangement; see setTableArrangement.

interface TableEditPatch

Members

MemberTypeDescription
shapeoptionalTableShape

New table shape. Switching kind converts the arrangement, keeping the seat count.

seatCountoptionalnumber

Total seats. On a rect table it redistributes the seats over the edges (distributeSeatsOnEdges).

seatsPerEdgeoptionalPartial<{ top: number; right: number; bottom: number; left: number; }>

Rect only. Merged into the current edge counts; takes precedence over seatCount.

seatDistanceoptionalnumber

Round only: table centre to seat centre.

seatOffsetoptionalnumber

Rect only: table edge to seat centre.

startAngleoptionalnumber

Round only: angle of the first seat in degrees, screen convention.

seatShapeoptionalSeatShape

Shape of every seat. Defaults to the first seat's shape.

bookAsWholeoptionalboolean

Sell the whole table as one unit. false removes the flag.

Every member is readonly.

@openseat/core/src/table-ops.ts

interface

TableEditResult

interface TableEditResult

Members

MemberTypeDescription
layoutLayoutDocument
reportRegenerationReport
clampedboolean

True when grow was false and fewer seats than requested fit.

Every member is readonly.

@openseat/core/src/table-ops.ts

interface

TableSeatPlacement

Where one seat of a table sits, in table-local coordinates (origin at the table centre, unrotated).

interface TableSeatPlacement

Members

MemberTypeDescription
positionPoint
rotationnumber

Seat rotation in degrees, relative to the table.

Every member is readonly.

@openseat/core/src/generators/tables.ts

interface

TableSeatsOptions

interface TableSeatsOptions extends GeneratorBaseOptions

Extends GeneratorBaseOptions

Members

MemberTypeDescription
labelstring

Table label, used in the generated seat IDs.

centeroptionalPoint

Table centre. Defaults to the origin (table-local coordinates).

shapeTableShape
arrangementTableArrangement

Must have the same kind as shape.

seatCountoptionalnumber

Number of seats of a round arrangement. Ignored for rect arrangements, whose edge counts decide.

idPrefixstring

Prefix for every generated object ID and seat ID. Use a unique value per generated block so two blocks never collide. Re-running a generator with the same prefix and labels produces the same IDs.

From GeneratorBaseOptions

sectionIdoptionalstring

From GeneratorBaseOptions

categoryIdoptionalstring

From GeneratorBaseOptions

seatShapeoptionalSeatShape

From GeneratorBaseOptions

numberingoptionalSeatNumbering

From GeneratorBaseOptions

Every member is readonly.

@openseat/core/src/generators/tables.ts

interface

TextBoxOptions

Options of estimateTextBox.

interface TextBoxOptions

Members

MemberTypeDescription
boldoptionalboolean

Bold text is estimated wider (0.68 em per character instead of 0.62).

letterSpacingoptionalnumber

Extra space between letters, in em.

Every member is readonly.

@openseat/core/src/object-geometry.ts

interface

TextPlacement

Where a GA zone's or stage's label goes.

interface TextPlacement

Members

MemberTypeDescription
atPoint
fontSizenumber
rotationnumber
textstring
widthnumber
heightnumber
boxBounds
letterSpacingnumber

Letter spacing in em the size was computed with.

boldboolean

Every member is readonly.

@openseat/core/src/label-layout.ts

interface

UnsellableInventory

interface UnsellableInventory

Members

MemberTypeDescription
categoryIdsstring[]

metadata.openseat.unsellableCategories that name an existing category, in category order.

inventoryIdsstring[]

Inventory keys that must not be sold, sorted: seat seatIds, GA and booth inventoryIds and the object IDs of tables booked as a whole.

notForSaleIdsstring[]

metadata.openseat.notForSale entries that name an existing object, sorted.

Every member is readonly.

@openseat/core/src/category-ops.ts

interface

ValidateOptions

interface ValidateOptions

Members

MemberTypeDescription
rulesoptionalreadonlyPartial<Record<LayoutIssueCode, IssueRuleSetting>>

Re-maps the severity of semantic issues by code, e.g. { DUPLICATE_ROW_LABEL: "error", SEAT_WITHOUT_CATEGORY: "off" }. Schema issues (malformed input) cannot be re-mapped. valid is computed after re-mapping.

@openseat/core/src/validate.ts

interface

ValidationResult

interface ValidationResult

Members

MemberTypeDescription
validboolean
layoutLayoutDocument | null

The typed, default-filled document. Present only when valid is true.

errorsLayoutIssue[]
warningsLayoutIssue[]

Every member is readonly.

@openseat/core/src/validate.ts

interface

VertexEditResult

Result of a vertex edit. A rejected edit returns the original layout.

interface VertexEditResult

Members

MemberTypeDescription
layoutLayoutDocument
rejectedoptionalVertexEditRejection

Every member is readonly.

@openseat/core/src/section-ops.ts

interface

ZoneOnlyOptions

interface ZoneOnlyOptions

Members

MemberTypeDescription
sectionIdsoptionalreadonlyreadonly string[]

Only these sections become zones, and seats outside sections are left alone. Absent: every section with seats, after loose seats, rows and tables are wrapped into new sections.

@openseat/core/src/zone-ops.ts

interface

ZoneRect

A world-space rectangle: top-left corner and size.

interface ZoneRect

Members

MemberTypeDescription
xnumber
ynumber
widthnumber
heightnumber

Every member is readonly.

@openseat/core/src/zone-ops.ts

Types53

type

Accessibility

// Inferred from its zod schema: z.infer<typeof accessibilitySchema>
type Accessibility = {
  wheelchair: boolean;
  companionSeat: boolean;
  notes?: string;
};

Members

MemberTypeDescription
wheelchairboolean
companionSeatboolean
notesoptionalstring

@openseat/core/src/schema.ts

type

Aisle

// Inferred from its zod schema: z.infer<typeof aisleSchema>
type Aisle = {
  type: "aisle";
  points: Point[];
  width: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  name?: string;
};

Members

MemberTypeDescription
type"aisle"
pointsPoint[]
widthnumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
nameoptionalstring

@openseat/core/src/schema.ts

type

AlignEdge

type AlignEdge =
  "left" | "centerX" | "right" | "top" | "centerY" | "bottom";

@openseat/core/src/operations.ts

type

ArcSeating

// Inferred from its zod schema: z.infer<typeof arcSeatingSchema>
type ArcSeating = {
  seatSpacing: number;
  seatShape: SeatShape;
  seatLabeling: SeatLabeling;
  kind: "arc";
  center: Point;
  innerRadius: number;
  rows: number;
  rowSpacing: number;
  startAngle: number;
  endAngle: number;
  edgeMargin: number;
  rowLabelPosition?: "start" | "end" | "none" | "both";
  rowSeats?: number[];
};

Members

MemberTypeDescription
seatSpacingnumber
seatShapeSeatShape
seatLabelingSeatLabeling
kind"arc"
centerPoint
innerRadiusnumber
rowsnumber
rowSpacingnumber
startAnglenumber
endAnglenumber
edgeMarginnumber
rowLabelPositionoptional"start" | "end" | "none" | "both"
rowSeatsoptionalnumber[]

@openseat/core/src/schema.ts

type

ArenaFieldKind

type ArenaFieldKind = "rink" | "court" | "pitch" | "stage";

@openseat/core/src/generators/arena.ts

type

ArenaPreset

Arena options without placement, as returned by arenaPreset.

type ArenaPreset = Omit<ArenaOptions, "idPrefix" | "center">;

Members

MemberTypeDescription
venueoptional{ readonly margin: number; readonly shape?: "rect" | "ellipse"; }

Venue outline around the outermost tier. Defaults to a rounded rectangle 40 units out.

titleoptionalstring

Human-readable name, e.g. "Ice hockey arena"; createArenaLayout's default layout name.

seatLabelingoptionalSeatLabeling

How seats are numbered within each row. Defaults to 1, 2, 3… from each spectator's left.

numberingoptionalArenaNumbering
fieldArenaField
tiersreadonly ArenaTier[]

Tiers from the field outwards.

fieldKindoptional"stage" | "rink" | "court" | "pitch"

Defaults to "rink". Sets the field's default label, colours and markings.

Default "rink"

balanceSectionsoptionalboolean

Evens out the seats per section around each tier. The tier keeps its total section count (never more), but the sections are redistributed between the long sides, the short sides and the corners so the sections on every side and in every corner hold about the same number of seats: without it, a round-ended field gives huge corner fans next to thin side blocks. A side or corner left at 0 stays empty, and a side too short for any section gives its share to the others. Off by default, so existing options generate exactly what they did before.

Every member is readonly.

@openseat/core/src/generators/arena.ts

type

ArenaPresetName

type ArenaPresetName = (typeof ARENA_PRESET_NAMES)[number];

@openseat/core/src/generators/arena.ts

type

BlockSeating

// Inferred from its zod schema: z.infer<typeof blockSeatingSchema>
type BlockSeating = {
  seatSpacing: number;
  seatShape: SeatShape;
  seatLabeling: SeatLabeling;
  kind: "block";
  rows: number;
  seatsPerRow: number;
  rowSpacing: number;
  curvature: number;
  align: "center" | "left" | "right";
  rowLabelPosition?: "start" | "end" | "none" | "both";
  rowSeats?: number[];
  stagger?: number;
  aisles?: number[];
  aisleWidth?: number;
};

Members

MemberTypeDescription
seatSpacingnumber
seatShapeSeatShape
seatLabelingSeatLabeling
kind"block"
rowsnumber
seatsPerRownumber
rowSpacingnumber
curvaturenumber
align"center" | "left" | "right"
rowLabelPositionoptional"start" | "end" | "none" | "both"
rowSeatsoptionalnumber[]
staggeroptionalnumber
aislesoptionalnumber[]
aisleWidthoptionalnumber

@openseat/core/src/schema.ts

type

Booth

// Inferred from its zod schema: z.infer<typeof boothSchema>
type Booth = {
  type: "booth";
  label: string;
  width: number;
  height: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  categoryId?: string;
  inventoryId?: string;
  name?: string;
};

Members

MemberTypeDescription
type"booth"
labelstring
widthnumber
heightnumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
categoryIdoptionalstring
inventoryIdoptionalstring
nameoptionalstring

@openseat/core/src/schema.ts

type

Category

// Inferred from its zod schema: z.infer<typeof categorySchema>
type Category = {
  id: string;
  name: string;
  colour?: string;
};

Members

MemberTypeDescription
idstring
namestring
colouroptionalstring

@openseat/core/src/schema.ts

type

CustomPath

// Inferred from its zod schema: z.infer<typeof pathSchema>
type CustomPath = {
  type: "path";
  points: Point[];
  closed: boolean;
  strokeWidth: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  caption?: string;
  captionSize?: number;
  name?: string;
};

Members

MemberTypeDescription
type"path"
pointsPoint[]
closedboolean
strokeWidthnumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
captionoptionalstring
captionSizeoptionalnumber
nameoptionalstring

@openseat/core/src/schema.ts

type

Entrance

// Inferred from its zod schema: z.infer<typeof entranceSchema>
type Entrance = {
  type: "entrance";
  width: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  label?: string;
  name?: string;
};

Members

MemberTypeDescription
type"entrance"
widthnumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
labeloptionalstring
nameoptionalstring

@openseat/core/src/schema.ts

type

FillSeating

// Inferred from its zod schema: z.infer<typeof fillSeatingSchema>
type FillSeating = {
  seatSpacing: number;
  seatShape: SeatShape;
  seatLabeling: SeatLabeling;
  kind: "fill";
  rowSpacing: number;
  angle: number;
  margin: number;
  aisleEvery: number;
  minSeatsPerRow: number;
  reverse: boolean;
  rowLabelPosition?: "start" | "end" | "none" | "both";
  aisleWidth?: number;
};

Members

MemberTypeDescription
seatSpacingnumber
seatShapeSeatShape
seatLabelingSeatLabeling
kind"fill"
rowSpacingnumber
anglenumber
marginnumber
aisleEverynumber
minSeatsPerRownumber
reverseboolean
rowLabelPositionoptional"start" | "end" | "none" | "both"
aisleWidthoptionalnumber

@openseat/core/src/schema.ts

type

GaArea

// Inferred from its zod schema: z.infer<typeof gaAreaSchema>
type GaArea = {
  type: "ga";
  label: string;
  boundary: Point[];
  capacity: number;
  inventoryId: string;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  categoryId?: string;
  sectionId?: string;
  style?: { fill?: string | undefined; stroke?: string | undefined };
  seating?: "standing" | "seated";
  cornerRadius?: number;
  labelRotation?: number;
  name?: string;
};

Members

MemberTypeDescription
type"ga"
labelstring
boundaryPoint[]
capacitynumber
inventoryIdstring
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
categoryIdoptionalstring
sectionIdoptionalstring
styleoptional{ fill?: string | undefined; stroke?: string | undefined; }
seatingoptional"standing" | "seated"
cornerRadiusoptionalnumber
labelRotationoptionalnumber
nameoptionalstring

@openseat/core/src/schema.ts

type

GaSeating

Whether a GA zone is seated (buyers pick a quantity) or standing; absent means "standing".

type GaSeating = NonNullable<GaArea["seating"]>;

@openseat/core/src/schema.ts

type

HitShape

World-space hit geometry for a layout object. Renderers and editors share this so that what is drawn, what is clickable, and what is culled agree.

type HitShape =
  | {
      readonly kind: "circle";
      readonly center: Point;
      readonly radius: number;
    }
  | {
      readonly kind: "polygon";
      readonly points: readonly Point[];
    }
  | {
      readonly kind: "polyline";
      readonly points: readonly Point[];
      readonly halfWidth: number;
    }
  | {
      readonly kind: "none";
    };

Variants · 4

DiscriminantTypeDescription
kind: "circle"{ readonly kind: "circle"; readonly center: Point; readonly radius: number; }
kind: "polygon"{ readonly kind: "polygon"; readonly points: readonly Point[]; }
kind: "polyline"{ readonly kind: "polyline"; readonly points: readonly Point[]; readonly halfWidth: number; }
kind: "none"{ readonly kind: "none"; }

@openseat/core/src/object-geometry.ts

type

IssueRuleSetting

Severity override for one issue code; "off" drops the issue.

type IssueRuleSetting = "error" | "warning" | "off";

@openseat/core/src/validate.ts

type

Label

// Inferred from its zod schema: z.infer<typeof labelSchema>
type Label = {
  type: "label";
  text: string;
  fontSize: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  style?: LabelStyle;
  name?: string;
};

Members

MemberTypeDescription
type"label"
textstring
fontSizenumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
styleoptionalLabelStyle
nameoptionalstring

@openseat/core/src/schema.ts

type

LabelFormat

// Inferred from its zod schema: z.infer<typeof labelFormatSchema>
type LabelFormat = "numeric" | "alpha" | "alpha-lower" | "roman";

@openseat/core/src/schema.ts

type

LabelLod

Level of detail: "detail" when seats are drawn, "overview" when zoomed out (no seats drawn).

type LabelLod = "detail" | "overview";

@openseat/core/src/label-layout.ts

type

LabelStyle

type LabelStyle = NonNullable<Label["style"]>;

Members

MemberTypeDescription
colouroptionalstring
boldoptionalboolean
italicoptionalboolean
letterSpacingoptionalnumber

@openseat/core/src/schema.ts

type

LayoutDocument

A complete seating layout: the canvas, its ticket categories and every object on it (seats, rows, sections, tables, booths, stages, standing areas and more), plus a revision your backend increments on every save. It is plain JSON: store it as it is, create one with createLayout, and check one that came from outside with validateLayout.

// Inferred from its zod schema: z.infer<typeof layoutSchema>
type LayoutDocument = {
  schemaVersion: 1;
  id: string;
  name: string;
  revision: number;
  canvas: { width: number; height: number; gridSize: number };
  metadata: Record<string, unknown>;
  categories: Category[];
  objects: LayoutObject[];
  venue?: Venue;
  focalPoint?: Point;
  createdAt?: string;
  updatedAt?: string;
};

Members

MemberTypeDescription
schemaVersion1
idstring
namestring
revisionnumber
canvas{ width: number; height: number; gridSize: number; }
metadataRecord<string, unknown>
categoriesCategory[]
objectsLayoutObject[]
venueoptionalVenue
focalPointoptionalPoint
createdAtoptionalstring
updatedAtoptionalstring

@openseat/core/src/schema.ts

type

LayoutIssueCode

type LayoutIssueCode =
  | "INVALID_DOCUMENT"
  | "UNSUPPORTED_SCHEMA_VERSION"
  | "SCHEMA_VIOLATION"
  | "NON_FINITE_VALUE"
  | "INVALID_DIMENSION"
  | "MALFORMED_GEOMETRY"
  | "DUPLICATE_OBJECT_ID"
  | "DUPLICATE_SEAT_ID"
  | "DUPLICATE_CATEGORY_ID"
  | "UNRESOLVED_REFERENCE"
  | "CAPACITY_MISMATCH"
  | "SEAT_OUTSIDE_SECTION"
  | "OBJECT_OUTSIDE_CANVAS"
  | "DUPLICATE_SEAT_POSITION"
  | "SEAT_IN_MULTIPLE_GROUPS"
  | "DUPLICATE_GROUP_MEMBER"
  | "GROUP_SECTION_MISMATCH"
  | "ROW_LABEL_MISMATCH"
  | "DUPLICATE_ROW_LABEL"
  | "DUPLICATE_SEAT_LABEL"
  | "DUPLICATE_SECTION_LABEL"
  | "DUPLICATE_SEAT_TAG"
  | "EMPTY_ROW"
  | "SEAT_OVERLAP"
  | "OVERLAP_CHECK_SKIPPED"
  | "SEAT_WITHOUT_CATEGORY"
  | "SEATING_IN_STANDING_AREA"
  | "INVALID_ROW_LAYOUT"
  | "INVALID_ROW_ORDER"
  | "INVALID_SECTION_SEATING"
  | "DUPLICATE_INVENTORY_ID"
  | "LABEL_OVER_SEATS"
  | "ZONE_CAPACITY_ABOVE_SEATS";

@openseat/core/src/validate.ts

type

LayoutObject

One object on a layout's canvas. Its type tells the variants apart (listed below); narrow with obj.type === "seat" before reading variant fields.

// Inferred from its zod schema: z.infer<typeof layoutObjectSchema>
type LayoutObject =
  | Seat
  | Row
  | Section
  | Table
  | Booth
  | Stage
  | Aisle
  | Label
  | Polygon
  | CustomPath
  | Entrance
  | GaArea;

Variants · 12

DiscriminantTypeDescription
type: "seat"Seat
type: "row"Row
type: "section"Section
type: "table"Table
type: "booth"Booth
type: "stage"Stage
type: "aisle"Aisle
type: "label"Label
type: "polygon"Polygon
type: "path"CustomPath
type: "entrance"Entrance
type: "ga"GaArea

@openseat/core/src/schema.ts

type

LayoutObjectType

type LayoutObjectType = LayoutObject["type"];

@openseat/core/src/schema.ts

type

Polygon

// Inferred from its zod schema: z.infer<typeof polygonSchema>
type Polygon = {
  type: "polygon";
  points: Point[];
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  categoryId?: string;
  style?: { fill?: string | undefined; stroke?: string | undefined };
  name?: string;
};

Members

MemberTypeDescription
type"polygon"
pointsPoint[]
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
categoryIdoptionalstring
styleoptional{ fill?: string | undefined; stroke?: string | undefined; }
nameoptionalstring

@openseat/core/src/schema.ts

type

ReorderDirection

type ReorderDirection = "forward" | "backward" | "front" | "back";

@openseat/core/src/operations.ts

type

RoundedPathSegment

One piece of a rounded outline from roundedPolygonPath.

type RoundedPathSegment =
  | {
      readonly kind: "line";
      readonly from: Point;
      readonly to: Point;
    }
  | {
      readonly kind: "arc";
      readonly from: Point;
      readonly to: Point;
      readonly center: Point;
      readonly radius: number;
      readonly startAngle: number;
      readonly endAngle: number;
      readonly clockwise: boolean;
    };

Variants · 2

DiscriminantTypeDescription
kind: "line"{ readonly kind: "line"; readonly from: Point; readonly to: Point; }
kind: "arc"{ readonly kind: "arc"; readonly from: Point; readonly to: Point; readonly center: Point; readonly radius: number; readonly startAngle: number; readonly endAngle: number; readonly clockwise: boolean; }

@openseat/core/src/object-geometry.ts

type

Row

// Inferred from its zod schema: z.infer<typeof rowSchema>
type Row = {
  type: "row";
  rowLabel: string;
  seatObjectIds: string[];
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  sectionId?: string;
  layout?: RowLayout;
  labelPosition?: "start" | "end" | "none" | "both";
  name?: string;
};

Members

MemberTypeDescription
type"row"
rowLabelstring
seatObjectIdsstring[]
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
sectionIdoptionalstring
layoutoptionalRowLayout
labelPositionoptional"start" | "end" | "none" | "both"
nameoptionalstring

@openseat/core/src/schema.ts

type

RowGap

// Inferred from its zod schema: z.infer<typeof rowGapSchema>
type RowGap = {
  after: number;
  width: number;
};

Members

MemberTypeDescription
afternumber
widthnumber

@openseat/core/src/schema.ts

type

RowLabeling

// Inferred from its zod schema: z.infer<typeof rowLabelingSchema>
type RowLabeling = {
  format: LabelFormat;
  start: number;
  step: number;
  direction: "front-to-back" | "back-to-front";
  skip?: string[];
  prefix?: string;
  suffix?: string;
};

Members

MemberTypeDescription
formatLabelFormat
startnumber
stepnumber
direction"front-to-back" | "back-to-front"
skipoptionalstring[]
prefixoptionalstring
suffixoptionalstring

@openseat/core/src/schema.ts

type

RowLabelPosition

// Inferred from its zod schema: z.infer<typeof rowLabelPositionSchema>
type RowLabelPosition = "start" | "end" | "none" | "both";

@openseat/core/src/schema.ts

type

RowLayout

// Inferred from its zod schema: z.infer<typeof rowLayoutSchema>
type RowLayout = {
  seatSpacing: number;
  radius?: number;
  anchor?: "start" | "end" | "center";
  gaps?: RowGap[];
  holes?: number[];
  seatRotation?: "row" | "tangent" | "keep";
  labeling?: SeatLabeling;
};

Members

MemberTypeDescription
seatSpacingnumber
radiusoptionalnumber
anchoroptional"start" | "end" | "center"
gapsoptionalRowGap[]
holesoptionalnumber[]
seatRotationoptional"row" | "tangent" | "keep"
labelingoptionalSeatLabeling

@openseat/core/src/schema.ts

type

RowLayoutPatch

Changes for setRowLayout. radius: null straightens the row; seatCount counts real seats.

type RowLayoutPatch = Partial<Omit<RowLayout, "radius">> & {
  radius?: number | null;
  seatCount?: number;
  position?: Point;
  rotation?: number;
};

Members

MemberTypeDescription
seatSpacingoptionalnumber
anchoroptional"start" | "end" | "center"
gapsoptionalRowGap[]
holesoptionalnumber[]
seatRotationoptional"row" | "tangent" | "keep"
labelingoptionalSeatLabeling
radiusoptionalnumber | null
seatCountoptionalnumber
positionoptionalPoint
rotationoptionalnumber

@openseat/core/src/row-ops.ts

type

Seat

// Inferred from its zod schema: z.infer<typeof seatSchema>
type Seat = {
  type: "seat";
  seatId: string;
  label: string;
  shape: SeatShape;
  accessibility: Accessibility;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  rowLabel?: string;
  sectionId?: string;
  categoryId?: string;
  labelLocked?: boolean;
  tags?: string[];
  name?: string;
};

Members

MemberTypeDescription
type"seat"
seatIdstring
labelstring
shapeSeatShape
accessibilityAccessibility
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
rowLabeloptionalstring
sectionIdoptionalstring
categoryIdoptionalstring
labelLockedoptionalboolean
tagsoptionalstring[]
nameoptionalstring

@openseat/core/src/schema.ts

type

SeatLabeling

// Inferred from its zod schema: z.infer<typeof seatLabelingSchema>
type SeatLabeling = {
  format: LabelFormat;
  start: number;
  step: number;
  direction: "ltr" | "rtl";
  prefix?: string;
  suffix?: string;
};

Members

MemberTypeDescription
formatLabelFormat
startnumber
stepnumber
direction"ltr" | "rtl"
prefixoptionalstring
suffixoptionalstring

@openseat/core/src/schema.ts

type

SeatShape

// Inferred from its zod schema: z.infer<typeof seatShapeSchema>
type SeatShape =
  | { kind: "circle"; radius: number }
  | { kind: "rect"; width: number; height: number };

Variants · 2

DiscriminantTypeDescription
kind: "circle"{ kind: "circle"; radius: number; }
kind: "rect"{ kind: "rect"; width: number; height: number; }

@openseat/core/src/schema.ts

type

Section

// Inferred from its zod schema: z.infer<typeof sectionSchema>
type Section = {
  type: "section";
  label: string;
  boundary: Point[];
  style: { fill?: string | undefined; stroke?: string | undefined };
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  categoryId?: string;
  rowOrder?: string[];
  rowLabeling?: RowLabeling;
  seating?: BlockSeating | ArcSeating | FillSeating;
  outline?: "none" | "custom" | "auto";
  labelSize?: number;
  labelOffset?: Point;
  showSeats?: boolean;
  capacity?: number;
  cornerRadius?: number;
  labelRotation?: number;
  labelPlacement?: "hidden" | "left" | "right" | "auto" | "above" | "below";
  name?: string;
};

Members

MemberTypeDescription
type"section"
labelstring
boundaryPoint[]
style{ fill?: string | undefined; stroke?: string | undefined; }
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
categoryIdoptionalstring
rowOrderoptionalstring[]
rowLabelingoptionalRowLabeling
seatingoptionalBlockSeating | ArcSeating | FillSeating
outlineoptional"none" | "custom" | "auto"
labelSizeoptionalnumber
labelOffsetoptionalPoint
showSeatsoptionalboolean
capacityoptionalnumber
cornerRadiusoptionalnumber
labelRotationoptionalnumber
labelPlacementoptional"hidden" | "left" | "right" | "auto" | "above" | "below"
nameoptionalstring

@openseat/core/src/schema.ts

type

SectionLabelPlacement

Where a section's title goes when its seats are drawn; absent means "auto".

type SectionLabelPlacement = NonNullable<Section["labelPlacement"]>;

@openseat/core/src/schema.ts

type

Stage

// Inferred from its zod schema: z.infer<typeof stageSchema>
type Stage = {
  type: "stage";
  width: number;
  height: number;
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  label?: string;
  cornerRadius?: number;
  style?: StageStyle;
  markings?: "rink" | "court" | "pitch";
  shape?: "rect" | "round" | "thrust" | "semicircle";
  thrust?: StageThrust;
  name?: string;
};

Members

MemberTypeDescription
type"stage"
widthnumber
heightnumber
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
labeloptionalstring
cornerRadiusoptionalnumber
styleoptionalStageStyle
markingsoptional"rink" | "court" | "pitch"
shapeoptional"rect" | "round" | "thrust" | "semicircle"
thrustoptionalStageThrust
nameoptionalstring

@openseat/core/src/schema.ts

type

StageMarkings

type StageMarkings = NonNullable<Stage["markings"]>;

@openseat/core/src/schema.ts

type

StageShape

Outline shape of a stage; absent on a stage means "rect".

type StageShape = NonNullable<Stage["shape"]>;

@openseat/core/src/schema.ts

type

StageStyle

type StageStyle = NonNullable<Stage["style"]>;

Members

MemberTypeDescription
filloptionalstring
strokeoptionalstring
strokeWidthoptionalnumber

@openseat/core/src/schema.ts

type

StageThrust

Runway of a thrust stage.

type StageThrust = NonNullable<Stage["thrust"]>;

Members

MemberTypeDescription
widthoptionalnumber
depthoptionalnumber

@openseat/core/src/schema.ts

type

StructureRepairKind

type StructureRepairKind =
  | "seat-in-multiple-groups"
  | "duplicate-member"
  | "dangling-member"
  | "dangling-section"
  | "dangling-category"
  | "row-order"
  | "row-layout"
  | "capacity"
  | "seat-cache"
  | "empty-row";

@openseat/core/src/structure-checks.ts

type

Table

// Inferred from its zod schema: z.infer<typeof tableSchema>
type Table = {
  type: "table";
  label: string;
  shape: TableShape;
  capacity: number;
  seatObjectIds: string[];
  id: string;
  visible: boolean;
  locked: boolean;
  zIndex: number;
  position: Point;
  rotation: number;
  sectionId?: string;
  arrangement?:
    | { kind: "round"; seatDistance: number; startAngle: number }
    | {
        kind: "rect";
        seatsPerEdge: {
          top: number;
          right: number;
          bottom: number;
          left: number;
        };
        seatOffset: number;
      };
  bookAsWhole?: boolean;
  name?: string;
};

Members

MemberTypeDescription
type"table"
labelstring
shapeTableShape
capacitynumber
seatObjectIdsstring[]
idstring
visibleboolean
lockedboolean
zIndexnumber
positionPoint
rotationnumber
sectionIdoptionalstring
arrangementoptional{ kind: "round"; seatDistance: number; startAngle: number; } | { kind: "rect"; seatsPerEdge: { top: number; right: number; bottom: number; left: number; }; seatOffset: number; }
bookAsWholeoptionalboolean
nameoptionalstring

@openseat/core/src/schema.ts

type

TableArrangement

// Inferred from its zod schema: z.infer<typeof tableArrangementSchema>
type TableArrangement =
  | { kind: "round"; seatDistance: number; startAngle: number }
  | {
      kind: "rect";
      seatsPerEdge: {
        top: number;
        right: number;
        bottom: number;
        left: number;
      };
      seatOffset: number;
    };

Variants · 2

DiscriminantTypeDescription
kind: "round"{ kind: "round"; seatDistance: number; startAngle: number; }
kind: "rect"{ kind: "rect"; seatsPerEdge: { top: number; right: number; bottom: number; left: number; }; seatOffset: number; }

@openseat/core/src/schema.ts

type

TableRegenerationOptions

type TableRegenerationOptions = RetentionOptions &
  (
    | {
        readonly shape: {
          readonly kind: "round";
          readonly radius: number;
        };
        readonly seatCount: number;
        readonly seatDistance?: number;
      }
    | {
        readonly shape: {
          readonly kind: "rect";
          readonly width: number;
          readonly height: number;
        };
        readonly seatsPerEdge: RectTableSeatCounts;
        readonly seatOffset?: number;
      }
  ) & {
    readonly seatShape?: SeatShape;
  };

@openseat/core/src/regenerate.ts

type

TableShape

// Inferred from its zod schema: z.infer<typeof tableShapeSchema>
type TableShape =
  | { kind: "round"; radius: number }
  | { kind: "rect"; width: number; height: number };

Variants · 2

DiscriminantTypeDescription
kind: "round"{ kind: "round"; radius: number; }
kind: "rect"{ kind: "rect"; width: number; height: number; }

@openseat/core/src/schema.ts

type

TextBoxKind

What a piece of text belongs to. Seat numbers are not text boxes: they sit inside their seats by design.

type TextBoxKind =
  | "section-title"
  | "row-label"
  | "zone-label"
  | "stage-label"
  | "label"
  | "caption"
  | "table-label"
  | "booth-label";

@openseat/core/src/label-layout.ts

type

Venue

// Inferred from its zod schema: z.infer<typeof venueSchema>
type Venue = {
  shape: "rect" | "ellipse";
  position: Point;
  width: number;
  height: number;
  name?: string;
  showName?: boolean;
  cornerRadius?: number;
  style?: { fill?: string | undefined; stroke?: string | undefined };
};

Members

MemberTypeDescription
shape"rect" | "ellipse"
positionPoint
widthnumber
heightnumber
nameoptionalstring
showNameoptionalboolean
cornerRadiusoptionalnumber
styleoptional{ fill?: string | undefined; stroke?: string | undefined; }

@openseat/core/src/schema.ts

type

VertexEditRejection

type VertexEditRejection =
  "not-editable" | "too-few-points" | "self-intersecting" | "zero-area";

@openseat/core/src/section-ops.ts

Constants64

const

accessibilitySchema

const accessibilitySchema: z.ZodObject<
  {
    wheelchair: z.ZodDefault<z.ZodBoolean>;
    companionSeat: z.ZodDefault<z.ZodBoolean>;
    notes: z.ZodOptional<z.ZodString>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

aisleSchema

const aisleSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"aisle">;
    points: z.ZodArray<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    width: z.ZodNumber;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

arcSeatingSchema

Concentric rows on an arc between two angles.

const arcSeatingSchema: z.ZodObject<
  {
    seatSpacing: z.ZodNumber;
    seatShape: z.ZodDiscriminatedUnion<
      [
        z.ZodObject<
          {
            kind: z.ZodLiteral<"circle">;
            radius: z.ZodNumber;
          },
          z.core.$strict
        >,
        z.ZodObject<
          {
            kind: z.ZodLiteral<"rect">;
            width: z.ZodNumber;
            height: z.ZodNumber;
          },
          z.core.$strict
        >,
      ],
      "kind"
    >;
    seatLabeling: z.ZodObject<
      {
        format: z.ZodEnum<{
          numeric: "numeric";
          alpha: "alpha";
// … 40 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

ARENA_LIMITS

Bounds on ArenaOptions, enforced before anything is generated so a hostile or mistyped option cannot make the generator run for minutes.

const ARENA_LIMITS: {
  readonly maxTiers: 8;
  readonly maxRowsPerTier: 100;
  readonly maxSectionsPerSide: 50;
  readonly maxFieldSize: 100000;
  readonly maxSpacing: 10000;
  readonly maxSeatsPerRow: 2000;
  readonly maxSeats: 200000;
}

@openseat/core/src/generators/arena.ts

const

ARENA_PRESET_NAMES

Names accepted by arenaPreset.

const ARENA_PRESET_NAMES: readonly [
  "hockey",
  "basketball",
  "concert-in-round",
  "football",
]

@openseat/core/src/generators/arena.ts

const

ARENA_PRESET_TITLES

Display titles of the presets; createArenaLayout names a preset layout after its title.

const ARENA_PRESET_TITLES: Readonly<
  Record<ArenaPresetName, string>
>

@openseat/core/src/generators/arena.ts

const

blockSeatingSchema

A rectangular (optionally curved, ragged or staggered) block of rows.

const blockSeatingSchema: z.ZodObject<
  {
    seatSpacing: z.ZodNumber;
    seatShape: z.ZodDiscriminatedUnion<
      [
        z.ZodObject<
          {
            kind: z.ZodLiteral<"circle">;
            radius: z.ZodNumber;
          },
          z.core.$strict
        >,
        z.ZodObject<
          {
            kind: z.ZodLiteral<"rect">;
            width: z.ZodNumber;
            height: z.ZodNumber;
          },
          z.core.$strict
        >,
      ],
      "kind"
    >;
    seatLabeling: z.ZodObject<
      {
        format: z.ZodEnum<{
          numeric: "numeric";
          alpha: "alpha";
// … 39 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

boothSchema

const boothSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"booth">;
    label: z.ZodString;
    width: z.ZodNumber;
    height: z.ZodNumber;
    categoryId: z.ZodOptional<z.ZodString>;
    inventoryId: z.ZodOptional<z.ZodString>;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

builtinMigrations

Migrations registered for this build. Version 1 is the first published schema, so this list is empty. Add an entry here when schema version 2 ships.

Versioning policy: schema version 1 grows additively. New fields are optional and carry no Zod default, so every existing v1 document stays valid and re-serialises byte-for-byte without a migration step. Bump to version 2 (and register a migration here) only for a non-additive change (renaming, removing or re-typing a field, or changing what a stored value means) or when freezing the format for 1.0 before the first publish.

Structural corruption inside a valid v1 document (a seat in two groups, dangling references) is not a schema change; it is fixed by repairStructure in structure-checks.ts, not by a migration.

const builtinMigrations: readonly LayoutMigration[]

@openseat/core/src/migrate.ts

const

categorySchema

const categorySchema: z.ZodObject<
  {
    id: z.ZodString;
    name: z.ZodString;
    colour: z.ZodOptional<z.ZodString>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

DEFAULT_ROW_LABELING

Rows lettered A, B, C… from the front.

const DEFAULT_ROW_LABELING: RowLabeling

@openseat/core/src/labeling.ts

const

DEFAULT_SEAT_LABELING

Seats numbered 1, 2, 3… from the first slot.

const DEFAULT_SEAT_LABELING: SeatLabeling

@openseat/core/src/labeling.ts

const

DEFAULT_SEAT_SHAPE

Default seat shape used when a generator is not given one: a 10-unit radius circle.

const DEFAULT_SEAT_SHAPE: SeatShape

@openseat/core/src/generators/common.ts

const

DEFAULT_TABLE_SEAT_GAP

Clear space kept between neighbouring seats when fitting or growing a table.

const DEFAULT_TABLE_SEAT_GAP = 2

@openseat/core/src/table-ops.ts

const

DIVIDER_CAPTION_LETTER_SPACING

Letter spacing (em) of a divider caption.

const DIVIDER_CAPTION_LETTER_SPACING = 0.1

@openseat/core/src/object-geometry.ts

const

DIVIDER_CAPTION_SIZE

Default font size of a divider caption (a path's caption) when captionSize is absent.

const DIVIDER_CAPTION_SIZE = 9

@openseat/core/src/object-geometry.ts

const

ENTRANCE_DEPTH

Entrances are drawn as a bar width long and this thick.

const ENTRANCE_DEPTH = 8

@openseat/core/src/object-geometry.ts

const

entranceSchema

const entranceSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"entrance">;
    label: z.ZodOptional<z.ZodString>;
    width: z.ZodNumber;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

fillSeatingSchema

Rows that fill the section boundary at an angle.

const fillSeatingSchema: z.ZodObject<
  {
    seatSpacing: z.ZodNumber;
    seatShape: z.ZodDiscriminatedUnion<
      [
        z.ZodObject<
          {
            kind: z.ZodLiteral<"circle">;
            radius: z.ZodNumber;
          },
          z.core.$strict
        >,
        z.ZodObject<
          {
            kind: z.ZodLiteral<"rect">;
            width: z.ZodNumber;
            height: z.ZodNumber;
          },
          z.core.$strict
        >,
      ],
      "kind"
    >;
    seatLabeling: z.ZodObject<
      {
        format: z.ZodEnum<{
          numeric: "numeric";
          alpha: "alpha";
// … 33 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

FOOTNOTE_COLOUR

Default colour of a footnote made by createFootnote.

const FOOTNOTE_COLOUR = "#9e9e9e"

@openseat/core/src/zone-ops.ts

const

FOOTNOTE_FONT_SIZE

Font size of a footnote made by createFootnote.

const FOOTNOTE_FONT_SIZE = 12

@openseat/core/src/zone-ops.ts

const

FOOTNOTE_LETTER_SPACING

Letter spacing (em) of a footnote made by createFootnote.

const FOOTNOTE_LETTER_SPACING = 0.08

@openseat/core/src/zone-ops.ts

const

gaAreaSchema

A zone sold by quantity up to capacity rather than by seat: standing (general admission) or seated (seating: "seated").

const gaAreaSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"ga">;
    label: z.ZodString;
    boundary: z.ZodArray<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    capacity: z.ZodNumber;
    inventoryId: z.ZodString;
    categoryId: z.ZodOptional<z.ZodString>;
    sectionId: z.ZodOptional<z.ZodString>;
    style: z.ZodOptional<
      z.ZodObject<
        {
          fill: z.ZodOptional<z.ZodString>;
          stroke: z.ZodOptional<z.ZodString>;
        },
        z.core.$strict
      >
    >;
    seating: z.ZodOptional<
      z.ZodEnum<{
// … 24 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

labelFormatSchema

Label formats shared by seat and row labeling.

const labelFormatSchema: z.ZodEnum<{
  numeric: "numeric";
  alpha: "alpha";
  "alpha-lower": "alpha-lower";
  roman: "roman";
}>

@openseat/core/src/schema.ts

const

labelSchema

const labelSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"label">;
    text: z.ZodString;
    fontSize: z.ZodNumber;
    style: z.ZodOptional<
      z.ZodObject<
        {
          colour: z.ZodOptional<z.ZodString>;
          bold: z.ZodOptional<z.ZodBoolean>;
          italic: z.ZodOptional<z.ZodBoolean>;
          letterSpacing: z.ZodOptional<z.ZodNumber>;
        },
        z.core.$strict
      >
    >;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

LAYOUT_LIMITS

Hard size limits enforced by the schema. They bound the work validation, rendering and the generators can be made to do by an untrusted document, and sit well above anything a real venue needs (the largest stadiums have about 100,000 seats).

const LAYOUT_LIMITS: {
  readonly maxObjects: 250000;
  readonly maxPolygonPoints: 5000;
  readonly maxTotalShapePoints: 200000;
  readonly maxSectionSeats: 20000;
  readonly maxGroupSeats: 5000;
  readonly maxCategories: 1000;
  readonly maxTableCapacity: 500;
  readonly maxSeatsPerEdge: 500;
  readonly maxMetadataBytes: 65536;
  readonly maxMetadataDepth: 16;
  readonly maxCoordinate: 10000000;
  readonly maxDimension: 1000000;
  readonly maxFontSize: 10000;
}

@openseat/core/src/limits.ts

const

layoutObjectSchema

const layoutObjectSchema: z.ZodDiscriminatedUnion<
  [
    z.ZodObject<
      {
        type: z.ZodLiteral<"seat">;
        seatId: z.ZodString;
        label: z.ZodString;
        rowLabel: z.ZodOptional<z.ZodString>;
        sectionId: z.ZodOptional<z.ZodString>;
        categoryId: z.ZodOptional<z.ZodString>;
        shape: z.ZodDiscriminatedUnion<
          [
            z.ZodObject<
              {
                kind: z.ZodLiteral<"circle">;
                radius: z.ZodNumber;
              },
              z.core.$strict
            >,
            z.ZodObject<
              {
                kind: z.ZodLiteral<"rect">;
                width: z.ZodNumber;
                height: z.ZodNumber;
              },
              z.core.$strict
            >,
          ],
// … 797 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

layoutSchema

const layoutSchema: z.ZodObject<
  {
    schemaVersion: z.ZodLiteral<1>;
    id: z.ZodString;
    name: z.ZodString;
    revision: z.ZodDefault<z.ZodNumber>;
    canvas: z.ZodObject<
      {
        width: z.ZodNumber;
        height: z.ZodNumber;
        gridSize: z.ZodDefault<z.ZodNumber>;
      },
      z.core.$strict
    >;
    metadata: z.ZodDefault<
      z.ZodPipe<z.ZodUnknown, z.ZodRecord<z.ZodString, z.ZodUnknown>>
    >;
    categories: z.ZodDefault<
      z.ZodArray<
        z.ZodObject<
          {
            id: z.ZodString;
            name: z.ZodString;
            colour: z.ZodOptional<z.ZodString>;
          },
          z.core.$strict
        >
      >
// … 874 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

MAX_CELLS_PER_ENTRY

Most grid cells one entry (or one query) may touch. Entries that would cover more cells, or whose cell range is not a safe integer range (huge or non-finite coordinates), are kept in an "oversized" list that every query scans linearly. Without this cap a single 1e6 x 1e6 stage, or two seats at x = 1e9 with a 1e-300 radius, would make an insert loop for minutes and exhaust memory.

const MAX_CELLS_PER_ENTRY = 4096

@openseat/core/src/spatial-index.ts

const

MAX_FILL_ROWS

Most rows one fill may produce. Matches the block seating row limit.

const MAX_FILL_ROWS = 500

@openseat/core/src/generators/section.ts

const

MAX_FILL_SEATS_PER_SPAN

Most seats one scanline span may produce. Matches the per-row seat limit of block seating.

const MAX_FILL_SEATS_PER_SPAN = 2000

@openseat/core/src/generators/section.ts

const

MAX_LABEL_ROTATION

Largest |labelRotation| of a section or GA zone, in degrees.

const MAX_LABEL_ROTATION = 360

@openseat/core/src/limits.ts

const

MAX_SERIALIZE_DEPTH

Deepest nesting serializeLayout accepts. Valid documents nest far less (metadata is capped at 16).

const MAX_SERIALIZE_DEPTH = 256

@openseat/core/src/serialize.ts

const

MAX_ZONE_CAPACITY

Largest zone capacity: a GA zone's capacity and a zone section's capacity.

const MAX_ZONE_CAPACITY = 1000000

@openseat/core/src/limits.ts

const

MIN_OBJECT_LABEL_SIZE

Smallest size a table or booth label is shrunk to.

const MIN_OBJECT_LABEL_SIZE = 4

@openseat/core/src/label-layout.ts

const

OBJECT_LABEL_SIZE

Table and booth labels are drawn at least this size, shrunk to fit the table or booth. A larger table or booth gets a larger label, up to OBJECT_LABEL_SHARE of its shorter side.

const OBJECT_LABEL_SIZE = 12

@openseat/core/src/label-layout.ts

const

pathSchema

const pathSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"path">;
    points: z.ZodArray<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    closed: z.ZodDefault<z.ZodBoolean>;
    strokeWidth: z.ZodNumber;
    caption: z.ZodOptional<z.ZodString>;
    captionSize: z.ZodOptional<z.ZodNumber>;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

pointSchema

const pointSchema: z.ZodObject<
  {
    x: z.ZodNumber;
    y: z.ZodNumber;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

polygonSchema

const polygonSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"polygon">;
    points: z.ZodArray<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    categoryId: z.ZodOptional<z.ZodString>;
    style: z.ZodOptional<
      z.ZodObject<
        {
          fill: z.ZodOptional<z.ZodString>;
          stroke: z.ZodOptional<z.ZodString>;
        },
        z.core.$strict
      >
    >;
    id: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    visible: z.ZodDefault<z.ZodBoolean>;
    locked: z.ZodDefault<z.ZodBoolean>;
    zIndex: z.ZodDefault<z.ZodNumber>;
    position: z.ZodDefault<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    rotation: z.ZodDefault<z.ZodNumber>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

ROUNDED_ZONE_RADIUS_FRACTION

Corner radius of a "rounded" zone, as a fraction of its shorter side.

const ROUNDED_ZONE_RADIUS_FRACTION = 0.12

@openseat/core/src/zone-ops.ts

const

ROW_LABEL_LAYOUT

Row labels: font size, gap from the end seat's edge, push step (× font size) and most pushes.

const ROW_LABEL_LAYOUT: {
  readonly fontSize: 11;
  readonly gap: 8;
  readonly pushStep: 0.5;
  readonly maxPushes: 4;
  readonly bold: true;
}

@openseat/core/src/label-layout.ts

const

ROW_LAYOUT_FIT_TOLERANCE

Largest distance, in layout units, a fitted layout may deviate from the stored seats and still be written.

const ROW_LAYOUT_FIT_TOLERANCE = 0.5

@openseat/core/src/row-geometry.ts

const

rowGapSchema

Extra space after slot index after (an aisle inside a row).

const rowGapSchema: z.ZodObject<
  {
    after: z.ZodNumber;
    width: z.ZodNumber;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

rowLabelingSchema

How the rows of one section are labelled.

const rowLabelingSchema: z.ZodObject<
  {
    format: z.ZodEnum<{
      numeric: "numeric";
      alpha: "alpha";
      "alpha-lower": "alpha-lower";
      roman: "roman";
    }>;
    start: z.ZodNumber;
    step: z.ZodNumber;
    direction: z.ZodEnum<{
      "front-to-back": "front-to-back";
      "back-to-front": "back-to-front";
    }>;
    skip: z.ZodOptional<z.ZodArray<z.ZodString>>;
    prefix: z.ZodOptional<z.ZodString>;
    suffix: z.ZodOptional<z.ZodString>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

rowLabelPositionSchema

Where a row's label is drawn. Absent on a row means "start".

const rowLabelPositionSchema: z.ZodEnum<{
  start: "start";
  none: "none";
  end: "end";
  both: "both";
}>

@openseat/core/src/schema.ts

const

rowLayoutSchema

Parametric description of a row. Seat positions are derived from it by the row geometry helpers; the stored seat positions stay authoritative for rendering and booking.

const rowLayoutSchema: z.ZodObject<
  {
    seatSpacing: z.ZodNumber;
    radius: z.ZodOptional<z.ZodNumber>;
    anchor: z.ZodOptional<
      z.ZodEnum<{
        start: "start";
        end: "end";
        center: "center";
      }>
    >;
    gaps: z.ZodOptional<
      z.ZodArray<
        z.ZodObject<
          {
            after: z.ZodNumber;
            width: z.ZodNumber;
          },
          z.core.$strict
        >
      >
    >;
    holes: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
    seatRotation: z.ZodOptional<
      z.ZodEnum<{
        tangent: "tangent";
        row: "row";
        keep: "keep";
// … 26 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

rowSchema

const rowSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"row">;
    rowLabel: z.ZodString;
    sectionId: z.ZodOptional<z.ZodString>;
    seatObjectIds: z.ZodArray<z.ZodString>;
    layout: z.ZodOptional<
      z.ZodObject<
        {
          seatSpacing: z.ZodNumber;
          radius: z.ZodOptional<z.ZodNumber>;
          anchor: z.ZodOptional<
            z.ZodEnum<{
              start: "start";
              end: "end";
              center: "center";
            }>
          >;
          gaps: z.ZodOptional<
            z.ZodArray<
              z.ZodObject<
                {
                  after: z.ZodNumber;
                  width: z.ZodNumber;
                },
                z.core.$strict
              >
            >
// … 60 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

SCHEMA_VERSION

Plain constants of the layout schema. They are re-exported from schema.ts (and so from the package root) unchanged; they live here, free of zod, so that code needing only a constant (factories, generators, the renderer) does not keep the zod schemas in a bundle that never validates a layout.

const SCHEMA_VERSION = 1

@openseat/core/src/limits.ts

const

SEAT_TAG_MARKED

Seat tag that represents the reference editor's "marked" flag.

const SEAT_TAG_MARKED = "marked"

@openseat/core/src/limits.ts

const

seatLabelingSchema

How the seats of one row are numbered.

const seatLabelingSchema: z.ZodObject<
  {
    format: z.ZodEnum<{
      numeric: "numeric";
      alpha: "alpha";
      "alpha-lower": "alpha-lower";
      roman: "roman";
    }>;
    start: z.ZodNumber;
    step: z.ZodNumber;
    direction: z.ZodEnum<{
      ltr: "ltr";
      rtl: "rtl";
    }>;
    prefix: z.ZodOptional<z.ZodString>;
    suffix: z.ZodOptional<z.ZodString>;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts

const

seatSchema

const seatSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"seat">;
    seatId: z.ZodString;
    label: z.ZodString;
    rowLabel: z.ZodOptional<z.ZodString>;
    sectionId: z.ZodOptional<z.ZodString>;
    categoryId: z.ZodOptional<z.ZodString>;
    shape: z.ZodDiscriminatedUnion<
      [
        z.ZodObject<
          {
            kind: z.ZodLiteral<"circle">;
            radius: z.ZodNumber;
          },
          z.core.$strict
        >,
        z.ZodObject<
          {
            kind: z.ZodLiteral<"rect">;
            width: z.ZodNumber;
            height: z.ZodNumber;
          },
          z.core.$strict
        >,
      ],
      "kind"
    >;
// … 30 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

seatShapeSchema

const seatShapeSchema: z.ZodDiscriminatedUnion<
  [
    z.ZodObject<
      {
        kind: z.ZodLiteral<"circle">;
        radius: z.ZodNumber;
      },
      z.core.$strict
    >,
    z.ZodObject<
      {
        kind: z.ZodLiteral<"rect">;
        width: z.ZodNumber;
        height: z.ZodNumber;
      },
      z.core.$strict
    >,
  ],
  "kind"
>

@openseat/core/src/schema.ts

const

SECTION_TITLE_LAYOUT

Section titles: default and smallest size, band gap (× font size) and the fit factors.

const SECTION_TITLE_LAYOUT: {
  readonly defaultSize: 16;
  readonly minSize: 8;
  readonly gap: 0.5;
  readonly widthFit: 0.95;
  readonly pitchFit: 2;
  readonly insideShorterFit: 0.45;
  readonly insideWidthFit: 0.9;
}

@openseat/core/src/label-layout.ts

const

sectionSchema

const sectionSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"section">;
    label: z.ZodString;
    categoryId: z.ZodOptional<z.ZodString>;
    boundary: z.ZodArray<
      z.ZodObject<
        {
          x: z.ZodNumber;
          y: z.ZodNumber;
        },
        z.core.$strict
      >
    >;
    style: z.ZodDefault<
      z.ZodObject<
        {
          fill: z.ZodOptional<z.ZodString>;
          stroke: z.ZodOptional<z.ZodString>;
        },
        z.core.$strict
      >
    >;
    rowOrder: z.ZodOptional<z.ZodArray<z.ZodString>>;
    rowLabeling: z.ZodOptional<
      z.ZodObject<
        {
          format: z.ZodEnum<{
// … 270 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

sectionSeatingSchema

Parametric seating of a section, used to regenerate its rows.

const sectionSeatingSchema: z.ZodDiscriminatedUnion<
  [
    z.ZodObject<
      {
        seatSpacing: z.ZodNumber;
        seatShape: z.ZodDiscriminatedUnion<
          [
            z.ZodObject<
              {
                kind: z.ZodLiteral<"circle">;
                radius: z.ZodNumber;
              },
              z.core.$strict
            >,
            z.ZodObject<
              {
                kind: z.ZodLiteral<"rect">;
                width: z.ZodNumber;
                height: z.ZodNumber;
              },
              z.core.$strict
            >,
          ],
          "kind"
        >;
        seatLabeling: z.ZodObject<
          {
            format: z.ZodEnum<{
// … 173 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

STAGE_LABEL_LAYOUT

Stage labels: upper-case, letter-spaced, sized to 0.28 × the shorter side within [10, 36], at most 0.8 × the width.

const STAGE_LABEL_LAYOUT: {
  readonly sizeFactor: 0.28;
  readonly minSize: 10;
  readonly maxSize: 36;
  readonly widthFit: 0.8;
  readonly letterSpacing: 0.14;
}

@openseat/core/src/label-layout.ts

const

stageSchema

const stageSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"stage">;
    label: z.ZodOptional<z.ZodString>;
    width: z.ZodNumber;
    height: z.ZodNumber;
    cornerRadius: z.ZodOptional<z.ZodNumber>;
    style: z.ZodOptional<
      z.ZodObject<
        {
          fill: z.ZodOptional<z.ZodString>;
          stroke: z.ZodOptional<z.ZodString>;
          strokeWidth: z.ZodOptional<z.ZodNumber>;
        },
        z.core.$strict
      >
    >;
    markings: z.ZodOptional<
      z.ZodEnum<{
        rink: "rink";
        court: "court";
        pitch: "pitch";
      }>
    >;
    shape: z.ZodOptional<
      z.ZodEnum<{
        rect: "rect";
        round: "round";
// … 31 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

tableArrangementSchema

Parametric seat arrangement around a table.

const tableArrangementSchema: z.ZodDiscriminatedUnion<
  [
    z.ZodObject<
      {
        kind: z.ZodLiteral<"round">;
        seatDistance: z.ZodNumber;
        startAngle: z.ZodNumber;
      },
      z.core.$strict
    >,
    z.ZodObject<
      {
        kind: z.ZodLiteral<"rect">;
        seatsPerEdge: z.ZodObject<
          {
            top: z.ZodNumber;
            right: z.ZodNumber;
            bottom: z.ZodNumber;
            left: z.ZodNumber;
          },
          z.core.$strict
        >;
        seatOffset: z.ZodNumber;
      },
      z.core.$strict
    >,
  ],
  "kind"
>

@openseat/core/src/schema.ts

const

tableSchema

const tableSchema: z.ZodObject<
  {
    type: z.ZodLiteral<"table">;
    label: z.ZodString;
    shape: z.ZodDiscriminatedUnion<
      [
        z.ZodObject<
          {
            kind: z.ZodLiteral<"round">;
            radius: z.ZodNumber;
          },
          z.core.$strict
        >,
        z.ZodObject<
          {
            kind: z.ZodLiteral<"rect">;
            width: z.ZodNumber;
            height: z.ZodNumber;
          },
          z.core.$strict
        >,
      ],
      "kind"
    >;
    capacity: z.ZodNumber;
    sectionId: z.ZodOptional<z.ZodString>;
    seatObjectIds: z.ZodArray<z.ZodString>;
    arrangement: z.ZodOptional<
// … 49 more lines (type truncated)

This type is long; its declaration is shortened here.

@openseat/core/src/schema.ts

const

tableShapeSchema

const tableShapeSchema: z.ZodDiscriminatedUnion<
  [
    z.ZodObject<
      {
        kind: z.ZodLiteral<"round">;
        radius: z.ZodNumber;
      },
      z.core.$strict
    >,
    z.ZodObject<
      {
        kind: z.ZodLiteral<"rect">;
        width: z.ZodNumber;
        height: z.ZodNumber;
      },
      z.core.$strict
    >,
  ],
  "kind"
>

@openseat/core/src/schema.ts

const

THRUST_DEPTH_FRACTION

Default runway depth of a thrust stage, as a fraction of the stage height.

const THRUST_DEPTH_FRACTION = 0.45

@openseat/core/src/object-geometry.ts

const

THRUST_WIDTH_FRACTION

Default runway width of a thrust stage, as a fraction of the stage width.

const THRUST_WIDTH_FRACTION = 0.4

@openseat/core/src/object-geometry.ts

const

TRAPEZOID_INSET_FRACTION

How far a trapezoid zone's short edge is inset on each side, as a fraction of its width.

const TRAPEZOID_INSET_FRACTION = 0.15

@openseat/core/src/zone-ops.ts

const

venueSchema

Outline of the venue itself, drawn beneath every object.

const venueSchema: z.ZodObject<
  {
    name: z.ZodOptional<z.ZodString>;
    showName: z.ZodOptional<z.ZodBoolean>;
    shape: z.ZodEnum<{
      rect: "rect";
      ellipse: "ellipse";
    }>;
    position: z.ZodObject<
      {
        x: z.ZodNumber;
        y: z.ZodNumber;
      },
      z.core.$strict
    >;
    width: z.ZodNumber;
    height: z.ZodNumber;
    cornerRadius: z.ZodOptional<z.ZodNumber>;
    style: z.ZodOptional<
      z.ZodObject<
        {
          fill: z.ZodOptional<z.ZodString>;
          stroke: z.ZodOptional<z.ZodString>;
        },
        z.core.$strict
      >
    >;
  },
  z.core.$strict
>

@openseat/core/src/schema.ts