Designer API Reference
Complete API reference for the SeatSquirrel Designer
Constructor Options
new SeatSquirrel.Designer(options)
Shared Callbacks (Both Modes)
These options work in both standalone and iframe SDK modes.
| Option | Type | Required | Description |
|---|---|---|---|
permissions | DesignerPermissions | No | Restrict which features are enabled in the designer. Default: all features enabled. |
onReady | () => void | No | Called when designer is ready. |
onLayoutLoaded | () => void | No | Called when loadLayout() succeeds. Pure confirmation signal — no payload. |
onSave | (data: { layout: LayoutOutput }) => void | No | Called when user clicks Save. |
onLayoutChanged | (data: { hasChanges: boolean }) => void | No | Called when unsaved changes status changes. |
onPricingCategoriesChanged | (data: { hasChanges: boolean }) => void | No | Called when pricing changes; call getPricingCategories() for data. |
onError | (error: { message: string, code: string, details?: string }) => void | No | Called when an error occurs. |
iFrame SDK Only
These options only apply when using the iframe SDK. They are not available in standalone mode.
| Option | Type | Required | Description |
|---|---|---|---|
container | string | HTMLElement | Yes | CSS selector or DOM element for the iframe |
baseUrl | string | No | Location of the SeatSquirrel app (default: https://seatsquirrel.com) |
designerUrl | string | No | Full URL override for the designer page. Takes precedence over baseUrl. Useful for servers requiring .html extensions (e.g., https://example.com/designer.html) |
Restricting Designer Features
Use the permissions option to control which tools and features are available in the designer.
Disable pricing category management
When you supply pricing categories from your external system, you typically want to prevent users from creating or modifying them:
Standalone mode (window.SeatSquirrelConfig):
window.SeatSquirrelConfig = {
permissions: {
properties: {
pricingCategoriesCrud: false,
currencySettings: false
}
},
onReady: function () {
SeatSquirrel.designer.setPricingCategories({
mode: 'replace',
pricingCategories: [
{ id: 'vip', label: 'VIP', slug: 'vip', price: 15000, color: '#8b5cf6' },
{ id: 'standard', label: 'Standard', slug: 'standard', price: 5000, color: '#3b82f6' }
]
});
},
onSave: function (layout) {
console.log('Layout saved:', layout);
}
};iFrame SDK mode (new SeatSquirrel.Designer()):
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: {
properties: {
pricingCategoriesCrud: false,
currencySettings: false
}
},
onReady: () => {
designer.setPricingCategories({
mode: 'replace',
pricingCategories: [
{ id: 'vip', label: 'VIP', slug: 'vip', price: 15000, color: '#8b5cf6' },
{ id: 'standard', label: 'Standard', slug: 'standard', price: 5000, color: '#3b82f6' }
]
});
}
});Read-only preview mode
// Standalone
window.SeatSquirrelConfig = {
permissions: { readOnly: true }
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: { readOnly: true }
});Assignment-only mode
Allows pricing category assignment while blocking all structural and visual edits:
- Pricing category assignment remains enabled
- Creating, moving, resizing, and deleting objects is disabled
- Undo/redo, copy/paste, and destructive controls are hidden
- Settings tab and category CRUD are disabled
- Save and export remain available
- Selected elements show greyed-out (non-editable) properties below the pricing editor
- If both
readOnlyandassignmentOnlyaretrue,readOnlytakes precedence
// Standalone
window.SeatSquirrelConfig = {
permissions: { assignmentOnly: true }
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: { assignmentOnly: true }
});
// Hide greyed-out properties (restore previous behavior)
window.SeatSquirrelConfig = {
permissions: {
assignmentOnly: true,
properties: { showProperties: false }
}
};Limit available tools
// Only allow rows and areas (hide tables, shapes, text tools)
// Standalone
window.SeatSquirrelConfig = {
permissions: {
tools: {
table: false,
shape: false,
text: false,
traceImage: false
}
}
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: {
tools: {
table: false,
shape: false,
text: false,
traceImage: false
}
}
});Hide the Settings tab
// Standalone
window.SeatSquirrelConfig = {
permissions: {
properties: {
settingsTab: false
}
}
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: {
properties: {
settingsTab: false
}
}
});Suppress pricing category save warning
When pricing is managed externally and you don't want users to see warnings about missing pricing categories on save:
// Standalone
window.SeatSquirrelConfig = {
permissions: {
warnings: {
pricingCategoriesAssignmentSaveWarning: false
}
}
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: {
warnings: {
pricingCategoriesAssignmentSaveWarning: false
}
}
});Suppress pricing category panel warning
Hide the amber "Missing Pricing Categories" warning box shown in the properties panel when nothing is selected:
// Standalone
window.SeatSquirrelConfig = {
permissions: {
warnings: {
pricingCategoriesAssignmentPanelWarning: false
}
}
};
// iFrame SDK
const designer = new SeatSquirrel.Designer({
container: '#designer',
permissions: {
warnings: {
pricingCategoriesAssignmentPanelWarning: false
}
}
});Methods
Summary
| Method | Parameters | Returns |
|---|---|---|
loadLayout(layoutData) | layoutData: LayoutOutput | Standalone: { success: boolean } iFrame: Promise<{ success: boolean }> |
getLayout({ mode }) | { mode: 'current' | 'last-saved' } | Standalone: { layout: LayoutOutput | null } iFrame: Promise<{ layout: LayoutOutput | null }> |
hasChanges() | — | { hasChanges: boolean } |
setPermissions(permissions) | DesignerPermissions | { success: boolean } |
clearLayout() | — | { success: boolean } |
setPricingCategories({ mode, ... }) | { mode, pricingCategories } | Standalone: { success: boolean } iFrame: Promise<{ success: boolean }> |
getPricingCategories() | — | Standalone: { pricingCategories: PricingCategory[] } iFrame: Promise<{ pricingCategories: PricingCategory[] }> |
assignPricingCategories(input) | AssignPricingCategoriesInput | Standalone: { success, errors? } iFrame: Promise<{ success, errors? }> |
showToast(options) | ShowToastOptions | Standalone: { success: boolean } iFrame: Promise<{ actionClicked: boolean }> |
showAlertDialog(options) | ShowAlertDialogOptions | { success: boolean } |
isDesignerReady() | — | { designerReady: boolean } |
destroy() | — | void |
loadLayout(layoutData)
Description
Load an existing layout into the designer for editing.
Parameters
layoutData(LayoutOutput): The layout JSON from a previous export
Returns
{ success: boolean } — In standalone mode this is synchronous. In iframe SDK mode it returns a Promise<{ success: boolean }>.
Example
// Standalone mode (synchronous)
const { success } = SeatSquirrel.designer.loadLayout(savedLayout);
// Iframe SDK mode (async)
const { success } = await designer.loadLayout(savedLayout);
console.log('Layout loaded:', success);getLayout({ mode })
Description
Get layout data from the designer. The mode parameter controls which snapshot is returned:
'current'— Returns the real-time layout state including any unsaved changes.'last-saved'— Returns the last saved or loaded layout snapshot (not real-time). Returnsnullif no layout has been saved or loaded.
Note:
getLayout({ mode: 'current' })does not trigger theonSavecallback.onSaveonly fires when the user clicks the Save button in the UI.
Parameters
options(Object):
| Property | Type | Required | Description |
|---|---|---|---|
mode | 'current' | 'last-saved' | Yes | Which layout snapshot to return |
Returns
{ layout: LayoutOutput | null } — In standalone mode this is synchronous. In iframe SDK mode it returns a Promise<{ layout: LayoutOutput | null }>. When mode is 'current', layout is always present. When mode is 'last-saved', layout may be null.
Example
// Standalone mode (synchronous)
const { layout } = SeatSquirrel.designer.getLayout({ mode: 'current' });
// Iframe SDK mode (async)
const { layout } = await designer.getLayout({ mode: 'current' });
console.log(layout);
// Get the last saved snapshot
const { layout: savedLayout } = designer.getLayout({ mode: 'last-saved' });
if (savedLayout) {
console.log('Last saved:', savedLayout);
}setPermissions(permissions)
Description
Set designer permissions at runtime. Use this to dynamically enable/disable features such as read-only mode, tool restrictions, or properties panel controls.
This method goes through the same permissions system as the constructor permissions option, so all permission fields are supported.
Parameters
permissions(DesignerPermissions): Permissions object to apply
Returns
{ success: boolean }
Example
// Enable read-only mode
designer.setPermissions({ readOnly: true });
// Disable read-only mode
designer.setPermissions({ readOnly: false });
// Enable assignment-only mode (pricing assignment only)
designer.setPermissions({ assignmentOnly: true });
// Disable specific tools at runtime
designer.setPermissions({ tools: { row: false, table: false } });
// Lock down properties panel
designer.setPermissions({
properties: { pricingCategoriesCrud: false, currencySettings: false }
});clearLayout()
Description
Clear the current layout and start with a blank canvas.
Returns
{ success: boolean }
Example
designer.clearLayout();setPricingCategories({ mode, ... })
Description
Set or update pricing categories in the designer. The mode parameter controls how the categories are applied:
'replace'— Replace all pricing categories with the provided array. Marks them as "externally managed" — users can only modify colors in the designer UI.'update-by-id'— Partially update existing categories by ID. Merges provided fields into matching categories while leaving unmentioned categories untouched. All-or-nothing: if any ID doesn't match an existing category, the entire call fails with no changes applied.'update-by-slug'— Partially update existing categories by slug. Merges provided fields into matching categories while leaving unmentioned categories untouched. All-or-nothing: if any slug doesn't match an existing category, the entire call fails with no changes applied.
Note: When using
'replace'mode, the designer UI restricts users to only modifying category colors. They cannot add, delete, or change pricing details.
Note: When using
'update-by-slug'mode, theslugfield is used only for matching — it is not merged into the category. To change a category's slug, use'update-by-id'mode and passslugas an update field.
Parameters
options(Object):
| Property | Type | Required | Description |
|---|---|---|---|
mode | 'replace' | 'update-by-id' | 'update-by-slug' | Yes | How to apply the pricing categories |
pricingCategories | Array | Yes | Array of pricing category objects (shape depends on mode) |
Category Object Properties (mode: 'replace'):
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for the category |
label | string | Yes | Display label (e.g., "VIP", "Standard") |
slug | string | Yes | URL-friendly identifier |
price | number | Yes | Price in cents (e.g., 15000 for $150) |
color | string | Yes | Hex color code (e.g., "#8b5cf6") |
customerNotes | string | No | Optional notes visible to customers |
Update Object Properties (mode: 'update-by-id'):
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | ID of the category to update (must match an existing category) |
label | string | No | New display label |
slug | string | No | New slug |
price | number | No | New price in cents |
color | string | No | New hex color code |
customerNotes | string | No | New customer notes |
Update Object Properties (mode: 'update-by-slug'):
| Property | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Slug of the category to match (used for lookup only, not merged) |
label | string | No | New display label |
price | number | No | New price in cents |
color | string | No | New hex color code |
customerNotes | string | No | New customer notes |
Returns
{ success: boolean } — In standalone mode this is synchronous. In iframe SDK mode it returns a Promise<{ success: boolean }>.
Example
// Replace all categories (standalone, synchronous)
const result = SeatSquirrel.designer.setPricingCategories({
mode: 'replace',
pricingCategories: [
{ id: 'vip', label: 'VIP', slug: 'vip', price: 15000, color: '#8b5cf6' },
{ id: 'standard', label: 'Standard', slug: 'standard', price: 5000, color: '#3b82f6' },
]
});
console.log(result.success); // true
// Replace all categories (iframe SDK, async)
const result = await designer.setPricingCategories({
mode: 'replace',
pricingCategories: [
{ id: 'vip', label: 'VIP', slug: 'vip', price: 15000, color: '#8b5cf6' },
{ id: 'standard', label: 'Standard', slug: 'standard', price: 5000, color: '#3b82f6' },
{ id: 'economy', label: 'Economy', slug: 'economy', price: 2500, color: '#10b981' },
]
});
console.log('Pricing set:', result.success);
// Partially update by ID
const result = SeatSquirrel.designer.setPricingCategories({
mode: 'update-by-id',
pricingCategories: [
{ id: 'price_abc123', price: 7500, label: 'Standard (updated)' },
{ id: 'price_def456', color: '#10B981' },
]
});
// Partially update by slug
const result = await designer.setPricingCategories({
mode: 'update-by-slug',
pricingCategories: [
{ slug: 'standard', price: 7500, label: 'Standard (updated)' },
{ slug: 'vip', color: '#10B981' },
]
});getPricingCategories()
Description
Get the current pricing categories from the designer.
Returns
{ pricingCategories: PricingCategory[] } — In standalone mode this is synchronous. In iframe SDK mode it returns a Promise<{ pricingCategories: PricingCategory[] }>.
Example
// Standalone mode (synchronous)
const { pricingCategories } = SeatSquirrel.designer.getPricingCategories();
// Iframe SDK mode (async)
const { pricingCategories } = await designer.getPricingCategories();
console.log(pricingCategories);assignPricingCategories(input)
Description
Assign pricing categories to layout objects (rows, seats, areas, tables, table seats) programmatically. This is useful when pricing categories are managed externally and need to be mapped to layout objects after loading.
Atomic semantics: If any assignment fails validation, none are applied. All errors are returned in the errors array.
The mode parameter controls how objects and categories are identified:
'by-id'— Reference objects and categories by their internal UUIDs.'by-slug'— Reference objects and categories by their user-defined slugs. This is the recommended mode.'dangerously-by-labels'— Reference objects by human-readable labels (can be ambiguous across sections). Categories are always referenced by slug in this mode.
Parameters
input(AssignPricingCategoriesInput):
| Property | Type | Required | Description |
|---|---|---|---|
mode | 'by-id' | 'by-slug' | 'dangerously-by-labels' | Yes | How to identify objects and categories |
Additional properties for mode 'by-id' and 'by-slug':
Each property is a Record<key, categoryKeys[]> map (keys are IDs or slugs depending on mode).
| Property | Type | Required | Description |
|---|---|---|---|
rows | Record<string, string[]> | No | Row assignments |
rowSeats | Record<string, string[]> | No | Seat assignments |
areas | Record<string, string[]> | No | Area assignments |
tables | Record<string, string[]> | No | Table assignments |
tableSeats | Record<string, string[]> | No | Table seat assignments |
Additional properties for mode 'dangerously-by-labels': Each property is an array of label-based entries with pricingCategorySlugs.
Returns
AssignPricingCategoriesResult { success: boolean, errors?: string[] } — In standalone mode this is synchronous. In iframe SDK mode it returns a Promise.
Example
// Assign by slug (recommended)
const result = SeatSquirrel.designer.assignPricingCategories({
mode: 'by-slug',
rows: {
'row-a': ['vip', 'standard'],
'row-b': ['standard'],
},
areas: {
'vip-lounge': ['vip'],
},
});
// Assign by ID
const result = await designer.assignPricingCategories({
mode: 'by-id',
rows: {
'row-uuid-1': ['cat-uuid-1', 'cat-uuid-2'],
'row-uuid-2': ['cat-uuid-2'],
},
});
if (!result.success) {
console.error('Assignment errors:', result.errors);
}showToast(options)
Description
Show a toast notification inside the designer UI.
Parameters
options(Object):
| Property | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Main toast message |
type | string | No | 'success', 'info', 'warning', 'error', or 'default' (default: 'default') |
description | string | No | Secondary description text |
action | Object | No | Action button: { label: string, onClick?: function } |
Returns
- Standalone mode:
{ success: boolean } - iFrame SDK mode:
Promise<{ actionClicked: boolean }>— resolves when the toast is dismissed or the action button is clicked
Example
designer.showToast({ title: 'Layout saved successfully', type: 'success' });
// Per-toast action callback (works in both modes)
const { actionClicked } = await designer.showToast({
title: 'External changes detected',
type: 'info',
description: 'Pricing was updated in your ticketing system.',
action: {
label: 'Reload pricing',
onClick: function () {
fetchLatestPricing().then(categories => designer.setPricingCategories({ mode: 'replace', pricingCategories: categories }));
},
},
});
console.log('User clicked action:', actionClicked);Action handling by mode:
- Standalone mode —
action.onClickruns directly when the button is clicked. - iFrame SDK mode —
action.onClickis called via correlation IDs when the action button is clicked. The returned Promise resolves with{ actionClicked: true }if the action was clicked, or{ actionClicked: false }if the toast was dismissed.
showAlertDialog(options)
Description
Show a modal alert dialog inside the designer UI. The dialog blocks interaction and requires the user to explicitly confirm or cancel.
Note: Only one alert dialog can be shown at a time. Calling
showAlertDialog()while a dialog is open cancels the previous one. In both modes,onConfirmandonCancelwork the same way. In iframe mode, the SDK matches callbacks via internal correlation IDs transparently.
Parameters
options(Object):
| Property | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Dialog title text |
description | string | No | Dialog body/description text |
confirmText | string | No | Confirm button label (default: 'OK') |
cancelText | string | No | Cancel button label (default: 'Cancel') |
variant | string | No | 'default' or 'danger' — danger shows a red AlertTriangle icon (default: 'default') |
mode | string | No | 'alert' (OK button only) or 'confirm' (OK/Cancel buttons) (default: 'alert') |
onConfirm | function | No | Called when the user clicks the confirm button |
onCancel | function | No | Called when the user clicks the cancel button |
Returns
{ success: boolean }
Example
designer.showAlertDialog({
title: 'Unsaved changes',
description: 'You have unsaved changes that will be lost. Continue?',
variant: 'danger',
confirmText: 'Discard changes',
cancelText: 'Go back',
onConfirm: function () {
navigateAway();
},
});
designer.showAlertDialog({
title: 'Layout published',
description: 'Your layout is now live and available for booking.',
mode: 'alert',
});hasChanges()
Description
Check if there are unsaved changes.
Returns
{ hasChanges: boolean } — Whether there are unsaved changes
isDesignerReady()
Description
Check if the designer is ready to receive commands.
Returns
{ designerReady: boolean } — Whether the designer is ready
destroy()
iFrame SDK only. Not available in standalone mode — standalone cleanup is handled automatically by the page lifecycle.
Description
Destroy the designer instance. Removes the iframe from the DOM, detaches the PostMessage event listener, and clears all internal state (pending requests, cached layouts, callback maps). Call this when you no longer need the designer — for example, when a modal closes or the user navigates away in a SPA.
Returns
void
Example
designer.destroy();Next Steps
- Standalone Quick Start — Direct JavaScript API without iFrame
- iFrame Quick Start — Embed via SDK
- Picker API Reference — Picker SDK documentation
- Types Reference — All shared data structures