Booking Client (Renderer) API Changes - v1.61.0

Release: v1.61.0 Package: @seatmap.pro/renderer Date: 2026-04-06


Summary

Backward Compatible: YES New Features: 3 (error messages, constrained GPU mode, unified section API) Behavior Changes: 1 (image format WebP) Deprecations: 6 (legacy *SvgSections* methods, SVGSectionManipulator) Bug Fixes: 4 (detail texture artifacts, premultiplied alpha, filter state reset, outline label alignment)

Migration Required: NO - all existing integrations continue to work unchanged


New Features

Error Messages API

Status: New

Description: The renderer now shows contextual error overlays when event loading fails. Error messages are customizable via loader.errorTexts in renderer settings. A new ApiError class is thrown by the API client, preserving the HTTP status code and backend error code.

API:

interface IErrorMessage {
  title: string;
  subtitle?: string;
}

interface ILoaderSettings {
  enabled: boolean;
  style?: 'overlay' | 'top-bar';
  theme?: ILoaderTheme;
  showText?: boolean;
  texts?: {
    schema?: string;
    prices?: string;
    rows?: string;
    backgroundBlurred?: string;
    backgroundPreview?: string;
    backgroundFull?: string;
    processing?: string;
  };
  /**
   * Customizable error messages shown when event loading fails.
   * Each key corresponds to a backend error code.
   */
  errorTexts?: {
    /** Shown when the event has been archived (HTTP 410). */
    eventArchived?: IErrorMessage;
    /** Shown when the event is not published (HTTP 422). */
    eventNotPublished?: IErrorMessage;
    /** Shown when the event does not exist (HTTP 404). */
    eventNotFound?: IErrorMessage;
    /** Shown for any other API error. */
    genericError?: IErrorMessage;
  };
}

Default error messages:

Error Code HTTP Status Default Title Default Subtitle
EVENT_ARCHIVED 410 Event is no longer available This event has been archived
EVENT_NOT_PUBLISHED 422 Event is not available This event has not been published yet
ENTITY_NOT_FOUND 404 Event not found The requested event does not exist
(other) any Failed to load event Error {status}

Example:

const renderer = new SeatmapBookingRenderer(container, {
  publicKey: 'your-key',
  loader: {
    enabled: true,
    style: 'overlay',
    errorTexts: {
      eventArchived: {
        title: 'This event has ended',
        subtitle: 'Check out our upcoming events',
      },
      eventNotPublished: {
        title: 'Coming soon',
        subtitle: 'Tickets will be available shortly',
      },
    },
  },
});

Behavior:

  • Error overlay replaces the loading progress bar/text
  • Inherits loader theme settings (overlayColor, overlayOpacity, textColor, fontSize)
  • Both overlay and top-bar styles display errors as a centered overlay
  • If loader.enabled: false, errors are thrown but not displayed visually

ApiError class (exported from booking-api-client):

class ApiError extends Error {
  readonly status: number;        // HTTP status code
  readonly errorCode: string | undefined;  // Backend error code
}

Performance Impact: NONE - error handling only activates on failed requests

Related Files:

  • src/layers/LoaderLayer.ts - Error overlay rendering
  • src/booking-api-client/BookingApiClient.ts - ApiError class
  • src/booking-renderer/SeatmapBookingRenderer.ts - Error message resolution
  • src/models.ts - IErrorMessage, ILoaderSettings.errorTexts

Constrained GPU Mode (SEAT-831)

Status: New (automatic, internal)

Description: The renderer now auto-detects GPU capabilities and adapts its rendering strategy for memory-limited devices. This prevents GPU memory exhaustion crashes on iPhones and low-end Android devices when rendering large venues with high-resolution backgrounds.

API:

interface IRendererSettings {
  /**
   * Force the GPU capability tier instead of auto-detecting.
   * 'constrained' enables the two-layer texture system and caps
   * canvas dimensions to 2048px.
   * Also settable via URL parameter ?gpuTier=constrained.
   * @hidden
   */
  gpuTier?: 'high' | 'constrained';
}

Detection logic (automatic, no consumer action needed):

  1. Screen-based: DPR >= 3 or total screen pixels > 8M -> constrained
  2. GL-based: maxTextureSize <= 8192 -> constrained
  3. Benchmark: GPU texture upload >30ms for 10MB throughput -> constrained

Constrained mode behavior:

  • Canvas dimensions capped to 2048px (reduced GPU texture memory)
  • Full-resolution background kept in JS heap (not uploaded to GPU)
  • On zoom, a detail crop is extracted from JS heap and uploaded as a smaller texture
  • Stale detail crops are discarded on viewport changes
  • Blur smoothing skipped (avoids overdraw on constrained GPU)

Override: Set gpuTier: 'constrained' in settings or add ?gpuTier=constrained to URL.

For host apps: No API changes needed. This is an internal optimization. The gpuTier setting is @hidden in TypeDoc and intended for debugging/testing only.

Performance Impact: Positive – prevents crashes, reduces GPU memory by 60-80% on constrained devices. No impact on high-tier devices.

Related Files:

  • src/tools/deviceCapabilities.ts - GPU probe and benchmark
  • src/layers/webgl/DetailTextureManager.ts - Two-layer texture system
  • src/Renderer.ts - Constrained mode integration

Unified Section API (SEAT-892)

Status: New

Description: Section disable, enable, and filter operations now work consistently across all outline types – SVG background sections, editor-created shapes, auto-generated outlines, and fallback outlines.

New API methods:

New Method Replaces (deprecated) Description
disableSections(ids, options?) disableSvgSectionsByIds() Disable sections by numeric ID
enableSections(ids) enableSvgSectionsByIds() Enable previously disabled sections
filterSections(ids, options?) filterSvgSectionsByIds() Show only specified sections
removeFilterSections(ids?) removeFilterSvgSectionsByIds() Remove section filter
disableSectionsByNames(names, options?) disableSvgSectionsByNames() Disable sections by name
enableSectionsByNames(names) enableSvgSectionsByNames() Enable sections by name

Themeable opacity:

const renderer = new SeatmapBookingRenderer(container, {
  svgSectionStyles: {
    unavailable: {
      opacity: 0.4,   // Default: 0.5
      cursor: 'not-allowed',
    },
    filtered: {
      opacity: 0.2,   // Default: 0.3
    },
    default: {
      bgColor: '#f0f0f0',  // Base fill for all sections
    },
  },
});

Bug fix: filterSections({ resetAll: true }) now correctly clears filtered state.

Internal: All operations route through OutlineStateManager. SVGSectionManipulator is deprecated.

For host apps: No changes needed. Existing *SvgSections* calls continue to work. Migrate names when convenient.

Documentation: Section States & Styling

Playground: Load the unifiedSectionStates preset.


Behavior Changes

Image Format: WebP (SEAT-897)

Status: Changed (transparent)

Description: The converter service now generates WebP images instead of PNG for venue backgrounds. The renderer handles both formats automatically.

Impact: NONE for consumers – the format change is handled internally. WebP provides 30-50% smaller payloads and better progressive loading quality.

Related Changes:

  • Sharp palette: true removed for PNGs with alpha channels (was causing black fills)
  • Blur re-enabled in converter for progressive loading smoothing
  • WebGL context now uses premultipliedAlpha: false to match texture loading

Deprecations

Legacy Section Methods

The following methods are deprecated in favor of the unified section API. They continue to work and will be maintained for backward compatibility.

Deprecated Method Replacement
disableSvgSectionsByIds() disableSections()
enableSvgSectionsByIds() enableSvgSectionsByIds()
filterSvgSectionsByIds() filterSections()
removeFilterSvgSectionsByIds() removeFilterSections()
disableSvgSectionsByNames() disableSectionsByNames()
enableSvgSectionsByNames() enableSectionsByNames()

SVGSectionManipulator

The internal SVGSectionManipulator class is deprecated. All section state operations now route through OutlineStateManager.


Bug Fixes

Detail Texture Artifacts (SEAT-809, SEAT-831)

Status: Fixed

Description: Zoom and pan operations could produce visual artifacts (white stripes, stale crops) in the detail texture pipeline. Fixed by:

  • Discarding stale detail texture crops on viewport changes
  • Replacing createImageBitmap crop with canvas-based cropping for Safari/iOS compatibility
  • Aligning WebGL premultipliedAlpha between context creation and texture upload

Filter State Reset

Status: Fixed

Description: filterSections({ resetAll: true }) (and the deprecated filterSvgSectionsByIds) now correctly clears previous filtered state. Previously it called the wrong internal method, leaving data-filtered attributes in the DOM.

Outline Label Alignment

Status: Fixed

Description: WebGL section label vertical position now matches Canvas2D baseline rendering. Previously the WebGL path had a slight vertical offset.

GA Label Preservation

Status: Fixed

Description: Background-bound GA labels are now preserved across outline rebuilds. Previously, outline re-rendering could drop GA labels from the SVG overlay.


Configuration Changes

Constructor Options

New Options

interface IRendererSettings {
  // Error message customization (via loader settings)
  loader?: {
    errorTexts?: {
      eventArchived?: IErrorMessage;
      eventNotPublished?: IErrorMessage;
      eventNotFound?: IErrorMessage;
      genericError?: IErrorMessage;
    };
  };

  // GPU tier override (hidden, for debugging)
  gpuTier?: 'high' | 'constrained';
}

No removed or deprecated options.


Migration Guide

No API Incompatibilities

All existing integrations work without modification.

Optional migrations:

  1. Rename section methods: Replace *SvgSections* method names with the new unified names when convenient
  2. Customize error texts: Add loader.errorTexts to provide branded error messages for your users
  3. Remove workarounds: If you had code to work around shape sections not responding to disable/filter, you can remove it


Support

Questions or Issues?