@3dsource/metabox-modular-configurator-api
Version:
API for Metabox MODULAR configurator
1,106 lines (831 loc) • 30.9 kB
Markdown
# Metabox Modular Configurator API
A powerful TypeScript API for integrating and controlling the Metabox Modular Configurator in web
applications. This package provides seamless communication with 3D configurators, allowing you to control environments,
components, component types, materials, and capture screenshots or PDFs.
## Table of Contents
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
- [Core Integration](#core-integration)
- [Type Definitions](#type-definitions)
- [Command Classes](#command-classes)
- [Examples](#examples)
- [Event Handling](#event-handling)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
## Features
- 🚀 Easy integration with any web framework (Angular, React, Vue, etc.)
- 📱 Responsive design support
- 🎨 Full control over materials, environments, and components
- 📸 Screenshot and PDF generation
- 🎬 Showcase management
- 📦 TypeScript support with full type definitions
- 🌐 CDN support for quick prototyping
## Prerequisites
- Modern web browser with ES6 module support
- HTTPS connection (required for unreal engine)
- Valid Metabox modular configurator URL
## Installation
### NPM Installation (Recommended)
For use with modern frameworks like Angular, React, Vue, etc.:
```bash
npm install @3dsource/metabox-modular-configurator-api --save
```
### CDN Installation
For direct browser usage without a build system:
```javascript
import { integrateMetabox, Communicator, SetEnvironment, SetComponent } from 'https://cdn.jsdelivr.net/npm/@3dsource/metabox-modular-configurator-api';
```
Alternative CDN options:
- **jsDelivr**: `https://cdn.jsdelivr.net/npm/@3dsource/metabox-modular-configurator-api@0.0.3/+esm`
## Quick Start
### 1. HTML Setup
Ensure your HTML page has the following structure, where the Metabox Configurator will be integrated.
You **MUST** control CSS style of `embed3DSource` element to make the configurator responsive and fit your needs on your
own.
Create a container element where the configurator will be embedded:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Metabox Configurator</title>
<style>
#embed3DSource {
width: 100%;
height: 600px;
border: 1px solid #ccc;
border-radius: 8px;
}
</style>
</head>
<body>
<div id="embed3DSource">
<!-- Configurator iframe will be embedded here -->
</div>
</body>
</html>
```
### 2. Basic Integration
#### JavaScript (ES6 Modules)
```html
<script type="module">
import { GetPdf, GetScreenshot, integrateMetabox, saveImage, SetComponent, SetComponentMaterial, SetEnvironment, SetEnvironmentMaterial, ShowEmbeddedMenu, ShowOverlayInterface } from 'https://cdn.jsdelivr.net/npm/@3dsource/metabox-modular-configurator-api';
// Replace it with your actual configurator URL
const configuratorUrl = 'https://metabox.3dsource.com/metabox-configurator/modular/your-configurator-id';
integrateMetabox(configuratorUrl, 'embed3DSource', (api) => {
console.log('Configurator API ready!');
// Listen for configurator data updates
api.addEventListener('configuratorDataUpdated', (data) => {
console.log('Configurator data:', data);
});
// Listen for screenshot events
api.addEventListener('screenshotReady', (data) => {
saveImage(data, 'configurator-screenshot.png');
});
// Set initial configuration
api.sendCommandToMetaBox(new SetComponent('componentId', 'typeId', true));
api.sendCommandToMetaBox(new SetEnvironment('environmentId'));
api.sendCommandToMetaBox(new SetComponentMaterial('slotId', 'materialId'));
api.sendCommandToMetaBox(new SetEnvironmentMaterial('slotId', 'materialId'));
api.sendCommandToMetaBox(new ShowEmbeddedMenu(false));
api.sendCommandToMetaBox(new ShowOverlayInterface(false));
api.sendCommandToMetaBox(new GetPdf());
api.sendCommandToMetaBox(new GetScreenshot('image/png', { x: 1024, y: 1024 }));
});
</script>
```
#### TypeScript/Angular/React
```typescript
import { integrateMetabox, Communicator, ModularConfiguratorEnvelope, SetEnvironment, ShowOverlayInterface, GetScreenshot, saveImage, SetComponent, SetComponentMaterial, type MimeType, ShowEmbeddedMenu } from '@3dsource/metabox-modular-configurator-api';
class ConfiguratorIntegration {
private api: Communicator | null = null;
private readonly configuratorUrl: string;
constructor(configuratorUrl: string) {
this.configuratorUrl = configuratorUrl;
this.initialize();
}
private initialize(): void {
integrateMetabox(this.configuratorUrl, 'embed3DSource', (api: Communicator) => {
this.api = api;
this.setupEventListeners();
this.setupInitialState();
});
}
private setupEventListeners(): void {
if (!this.api) return;
// Listen for configuration data changes
this.api.addEventListener('configuratorDataUpdated', (data: ModularConfiguratorEnvelope) => {
console.log('Configurator data updated:', data);
this.handleConfiguratorData(data);
});
// Handle screenshot events
this.api.addEventListener('screenshotReady', (imageData: string | null) => {
saveImage(imageData ?? '', 'configurator-render.png');
});
// Handle viewport ready events
this.api.addEventListener('viewportReady', (isReady: boolean) => {
console.log('Viewport ready:', isReady);
});
// Handle status messages
this.api.addEventListener('statusMessageChanged', (message: string | null) => {
console.log('Status message:', message);
});
}
private setupInitialState(): void {
if (!this.api) return;
// Configure initial environment and components
this.api.sendCommandToMetaBox(new SetEnvironment('default-environment'));
this.api.sendCommandToMetaBox(new SetComponent('main-product', 'chair', true));
this.api.sendCommandToMetaBox(new ShowOverlayInterface(true));
this.api.sendCommandToMetaBox(new ShowEmbeddedMenu(true));
}
private handleConfiguratorData(data: ModularConfiguratorEnvelope): void {
// Access typed data properties according to actual interface
console.log('Configurator:', data.configurator);
console.log('Configuration tree:', data.configurationTree);
console.log('Components by type:', data.componentsByComponentType);
console.log('Component materials:', data.componentMaterialsIds);
console.log('Environment ID:', data.environmentId);
console.log('Environment materials:', data.environmentMaterialsIds);
// Process configurator data according to your needs
this.updateUI(data);
}
private updateUI(data: ModularConfiguratorEnvelope): void {
// Update your application UI based on configurator state
// This method would contain your specific UI update logic
}
// Public API methods
public takeScreenshot(format: MimeType = 'image/png', size?: { x: number; y: number }): void {
if (this.api) {
this.api.sendCommandToMetaBox(new GetScreenshot(format, size));
}
}
public changeMaterial(slotId: string, materialId: string): void {
if (this.api) {
this.api.sendCommandToMetaBox(new SetComponentMaterialById(slotId, materialId));
}
}
public changeEnvironment(environmentId: string): void {
if (this.api) {
this.api.sendCommandToMetaBox(new SetEnvironment(environmentId));
}
}
public destroy(): void {
// Clean up resources when component is destroyed
this.api = null;
}
}
// Usage example
const configurator = new ConfiguratorIntegration('https://metabox.3dsource.com/metabox-configurator/modular/your-configurator-id');
// Take a high-resolution screenshot
configurator.takeScreenshot('image/png', { x: 1920, y: 1080 });
// Change material
configurator.changeMaterial('seat-fabric', 'leather-brown');
```
## API Reference
### Core Integration
#### `integrateMetabox(configuratorUrl, containerId, apiReadyCallback)`
Integrates the Metabox modular configurator into the specified container.
**Parameters:**
- `configuratorUrl` (`string`): The URL of your Metabox configurator
- `containerId` (`string`): The ID of the HTML element where the configurator will be embedded
- `apiReadyCallback` (`(api: Communicator) => void`): Callback function that receives the API communicator instance
**TypeScript Signature:**
```typescript
declare function integrateMetabox(configuratorUrl: string, containerId: string, apiReadyCallback: (api: Communicator) => void): void;
```
**Example:**
```typescript
integrateMetabox('https://metabox.3dsource.com/metabox-configurator/modular/your-id', 'embed3DSource', (api) => {
console.log('API ready!', api);
});
```
### Type Definitions
The API provides comprehensive TypeScript support with the following key interfaces and types:
#### Core Types
##### `Communicator`
The main API interface for sending commands and listening to events.
```typescript
interface Communicator {
sendCommandToMetaBox<T extends keyof ToMetaboxMessagePayloads>(command: CommandBase<T>): void;
addEventListener<K extends keyof FromMetaboxMessagePayloads>(eventType: K, listener: (data: FromMetaboxMessagePayloads[K]) => void): void;
removeEventListener<K extends keyof FromMetaboxMessagePayloads>(eventType: K, listener: (data: FromMetaboxMessagePayloads[K]) => void): void;
}
```
##### `ModularConfiguratorEnvelope`
The main data structure contains the complete configurator state.
```typescript
interface ModularConfiguratorEnvelope {
/** Represents the modular configurator api with its components, component types, and environments */
configurator: InitialModularConfigurator;
/** The unique tree of components and parent and component type id */
configurationTree: ComponentWithParent[];
/** A record mapping all components by current component type */
componentsByComponentType: Record<string, string>;
/** A record mapping component material selection */
componentMaterialsIds: SelectedIds;
/** The unique environment identifier */
environmentId: string;
/** A record mapping environment material selections */
environmentMaterialsIds: SelectedIds;
}
```
##### `ModularConfiguratorComponent`
Represents a component in the configurator.
```typescript
interface ModularConfiguratorComponent {
/** The id unique identifier. */
id: string;
/** The modular configurator component type identifier. */
componentType: ModularConfiguratorComponentType;
/** Display the name for the product. */
name: string;
/** Position index of the product. */
position: number;
/** The detailed product information. */
product: Product;
/** Connectors between connectors and virtual sockets. */
virtualSocketToConnectorsMap?: ModularConfiguratorVirtualSocketToConnector[];
/** GraphQL typename for the component. */
__typename: 'ModularConfiguratorComponent';
}
```
##### `Material`
Represents a material that can be applied to components or environments.
```typescript
interface Material {
/** Unique identifier for the material. */
id: string;
/** Title or name of the material. */
title: string;
/** Unique external id for the material. */
externalId: string;
/** List of thumbnails for the material. */
thumbnailList: Thumbnail[];
/** GraphQL typename for the material. */
__typename: 'Material';
}
```
##### `Environment`
Represents an environment/scene configuration.
```typescript
interface Environment {
/** Unique identifier for the environment. */
id: string;
/** Title or name of the environment. */
title: string;
/** Flag indicating if UDS is enabled. */
udsEnabled: boolean;
/** The north yaw of the sun in the environment. */
sunNorthYaw: number;
/** The UDS hour setting for the environment. */
udsHour: number;
/** List of thumbnails for the environment (optional). */
thumbnailList: Thumbnail[];
/** List of slots for the environment (optional). */
slots: Slot[];
/** GraphQL typename for the environment. */
__typename: 'Environment';
}
```
#### Command Payload Types
All commands use strongly typed payloads defined in `ToMetaboxMessagePayloads`:
```typescript
interface ToMetaboxMessagePayloads {
setEnvironment: { id: string };
setEnvironmentMaterialById: { slotId: string; materialId: string };
setComponent: { id: string; typeId: string; isRoot: boolean };
setComponentType: { typeId: string };
setComponentMaterialById: { slotId: string; materialId: string };
getScreenshot: { format: MimeType; size?: { x: number; y: number } };
getPdf: void;
showEmbeddedMenu: { visible: boolean };
showOverlayInterface: { visible: boolean };
forceSetDeviceType: { deviceType: ApplicationDeviceTypes };
resetCamera: void;
applyZoom: { zoom: number };
initShowcase: { productId: string };
playShowcase: void;
pauseShowcase: void;
stopShowcase: void;
sendCommandToUnreal: object;
}
```
#### Utility Types
##### `MimeType`
Supported image formats for screenshots.
```typescript
type MimeType = 'image/png' | 'image/jpeg' | 'image/webp';
```
##### `ApplicationDeviceTypes`
Device type options for responsive behavior.
```typescript
type ApplicationDeviceTypes = 'desktop' | 'tablet' | 'mobile';
```
##### `Position` and `Rotation`
3D coordinate and rotation structures.
```typescript
interface Position {
x: number;
y: number;
z: number;
}
interface Rotation {
x: number;
y: number;
z: number;
}
```
### Command Classes
### Environment & Scene Control
#### `SetEnvironment(environmentId)`
Sets the active environment/scene in the configurator.
**Parameters:**
- `environmentId` (string): The ID of the environment to activate
**Example:**
```typescript
api.sendCommandToMetaBox(new SetEnvironment('environment-001'));
```
#### `SetEnvironmentMaterial(slotId, materialId)`
Changes the material of an environment element.
**Parameters:**
- `slotId` (string): The slot identifier for the environment element
- `materialId` (string): The ID of the material to apply
**Example:**
```typescript
api.sendCommandToMetaBox(new SetEnvironmentMaterial('floor-slot', 'wood-material'));
```
### Component Management
#### `SetComponent(id, typeId, isRoot)`
Adds or updates a component in the configurator.
**Parameters:**
- `id` (string): Unique identifier for the component
- `typeId` (string): The type/category of the component
- `isRoot` (boolean): Whether this is a root component
**Example:**
```typescript
api.sendCommandToMetaBox(new SetComponent('chair-001', 'furniture', true));
```
#### `SetComponentType(componentId, typeId)`
Changes the type of the existing component.
**Parameters:**
- `componentId` (string): The ID of the component to modify
- `typeId` (string): The new type ID to assign
**Example:**
```typescript
api.sendCommandToMetaBox(new SetComponentType('chair-001', 'office-chair'));
```
#### `SetComponentMaterial(slotId, materialId)`
Applies a material to a component's material slot.
**Parameters:**
- `slotId` (string): The material slot identifier
- `materialId` (string): The ID of the material to apply
**Example:**
```typescript
api.sendCommandToMetaBox(new SetComponentMaterial('chair-fabric', 'leather-brown'));
```
### UI Control
#### `ShowEmbeddedMenu(visible)`
Controls the visibility of the embedded configurator menu.
**Parameters:**
- `visible` (boolean): Whether to show or hide the menu
**Example:**
```typescript
api.sendCommandToMetaBox(new ShowEmbeddedMenu(false)); // Hide menu
```
#### `ShowOverlayInterface(visible)`
Controls the visibility of the overlay interface.
**Parameters:**
- `visible` (boolean): Whether to show or hide the overlay
**Example:**
```typescript
api.sendCommandToMetaBox(new ShowOverlayInterface(true)); // Show overlay
```
### Camera Control
#### `ResetCamera()`
Resets the camera to its default position and rotation.
**Example:**
```typescript
api.sendCommandToMetaBox(new ResetCamera());
```
#### `ApplyZoom(zoom)`
Applies zoom to the camera view.
**Parameters:**
- `zoom` (number): Zoom level (typically between 0.1 and 3.0)
**Example:**
```typescript
api.sendCommandToMetaBox(new ApplyZoom(1.5)); // 150% zoom
```
### Export & Capture
#### `GetScreenshot(mimeType, size?)`
Captures a screenshot of the current configurator view.
**Parameters:**
- `mimeType` (`string`): Image format ('image/png', 'image/jpeg')
- `size` (`{ x: number; y: number }`, optional): Screenshot dimensions in pixels
**TypeScript Interface:**
```typescript
interface ScreenshotSize {
x: number; // Width in pixels
y: number; // Height in pixels
}
```
**Example:**
```typescript
api.sendCommandToMetaBox(new GetScreenshot('image/png', { x: 1920, y: 1080 }));
```
#### `GetPdf()`
Generates a PDF document of the current configuration.
**Example:**
```typescript
api.sendCommandToMetaBox(new GetPdf());
```
#### `saveImage(renderData, fileName)`
Utility function to save image data to a file.
**Parameters:**
- `renderData` (string): Base64 image data
- `fileName` (string): Name for the downloaded file
**Example:**
```typescript
saveImage(data, 'my-configuration.png');
```
### Showcase Control
#### `InitShowcase(showcaseId)`
Initializes a showcase animation sequence.
**Parameters:**
- `showcaseId` (string): The ID of the showcase to initialize
**Example:**
```typescript
api.sendCommandToMetaBox(new InitShowcase('product-tour-001'));
```
#### `PlayShowcase()` / `PauseShowcase()` / `StopShowcase()`
Controls showcase playback.
**Examples:**
```typescript
api.sendCommandToMetaBox(new PlayShowcase()); // Start playback
api.sendCommandToMetaBox(new PauseShowcase()); // Pause playback
api.sendCommandToMetaBox(new StopShowcase()); // Stop and reset
```
### Advanced Features
#### `UnrealCommand(command)`
Sends custom commands directly to the Unreal Engine.
**Parameters:**
- `command` (string): Custom Unreal Engine command
**Example:**
```typescript
api.sendCommandToMetaBox(new UnrealCommand('SetLightIntensity 2.5'));
```
## Examples
### Complete Product Configurator
```typescript
import { integrateMetabox, Communicator, ModularConfiguratorEnvelope, SetEnvironment, SetComponent, SetComponentMaterial, ShowOverlayInterface, GetScreenshot, ResetCamera } from '@3dsource/metabox-modular-configurator-api';
class ProductConfigurator {
private api: Communicator | null = null;
private currentConfig: ModularConfiguratorEnvelope | null = null;
constructor(configuratorUrl: string) {
integrateMetabox(configuratorUrl, 'embed3DSource', (api) => {
this.api = api;
this.setupEventListeners();
this.initializeProduct();
});
}
private setupEventListeners(): void {
if (!this.api) return;
this.api.addEventListener('configuratorData', (data: ModularConfiguratorEnvelope) => {
this.currentConfig = data;
this.onConfigurationChange(data);
});
this.api.addEventListener('screenshot', (imageData: string) => {
this.onScreenshotReady(imageData);
});
}
private initializeProduct(): void {
if (!this.api) return;
// Set up the initial environment
this.api.sendCommandToMetaBox(new SetEnvironment('showroom-001'));
// Add main product component
this.api.sendCommandToMetaBox(new SetComponent('product-main', 'chair', true));
// Configure UI
this.api.sendCommandToMetaBox(new ShowOverlayInterface(true));
// Reset camera to default position
this.api.sendCommandToMetaBox(new ResetCamera());
}
public changeMaterial(slotId: string, materialId: string): void {
if (this.api) {
this.api.sendCommandToMetaBox(new SetComponentMaterial(slotId, materialId));
}
}
public takeProductPhoto(): void {
if (this.api) {
this.api.sendCommandToMetaBox(new GetScreenshot('image/png', { x: 1920, y: 1080 }));
}
}
private onConfigurationChange(data: ModularConfiguratorEnvelope): void {
console.log('Configuration updated:', data);
// Update your UI, save state, etc.
}
private onScreenshotReady(imageData: string): void {
// Create download link or display image
const link = document.createElement('a');
link.download = 'product-configuration.png';
link.href = imageData;
link.click();
}
}
```
### React Hook Example
```typescript
import { useCallback, useEffect, useRef, useState } from 'react';
import {
Communicator,
GetScreenshot,
integrateMetabox,
ModularConfiguratorEnvelope,
SetComponent,
SetComponentMaterial,
SetEnvironment,
} from '@3dsource/metabox-modular-configurator-api';
interface UseMetaboxConfiguratorOptions {
configuratorUrl: string;
autoInitialize?: boolean;
}
interface UseMetaboxConfiguratorReturn {
containerRef: React.RefObject<HTMLDivElement>;
api: Communicator | null;
isReady: boolean;
configData: ModularConfiguratorEnvelope | null;
isLoading: boolean;
error: string | null;
// Actions
changeEnvironment: (environmentId: string) => void;
takeScreenshot: (format?: MimeType, size?: { x: number; y: number }) => void;
changeMaterial: (slotId: string, materialId: string) => void;
addComponent: (id: string, typeId: string, isRoot?: boolean) => void;
initialize: () => void;
destroy: () => void;
}
export const useMetaboxConfigurator = ({
configuratorUrl,
autoInitialize = true,
}: UseMetaboxConfiguratorOptions): UseMetaboxConfiguratorReturn => {
const [api, setApi] = useState<Communicator | null>(null);
const [isReady, setIsReady] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [configData, setConfigData] = useState<ModularConfiguratorEnvelope | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
const initialize = useCallback(() => {
if (!containerRef.current || !configuratorUrl || isLoading) return;
setIsLoading(true);
setError(null);
try {
const containerId = 'metabox-container-' + Date.now();
containerRef.current.id = containerId;
integrateMetabox(configuratorUrl, containerId, (apiInstance: Communicator) => {
setApi(apiInstance);
setIsReady(true);
setIsLoading(false);
// Set up event listeners
apiInstance.addEventListener('configuratorData', (data: ModularConfiguratorEnvelope) => {
setConfigData(data);
});
apiInstance.addEventListener('screenshot', (imageData: string) => {
// Handle screenshot data - could emit custom event or callback
console.log('Screenshot ready:', imageData);
});
apiInstance.addEventListener('pdf', (pdfData: string) => {
// Handle PDF data
console.log('PDF ready:', pdfData);
});
});
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to initialize configurator');
setIsLoading(false);
}
}, [configuratorUrl, isLoading]);
const destroy = useCallback(() => {
setApi(null);
setIsReady(false);
setIsLoading(false);
setConfigData(null);
setError(null);
}, []);
useEffect(() => {
if (autoInitialize) {
initialize();
}
return destroy;
}, [initialize, destroy, autoInitialize]);
// Action methods
const changeEnvironment = useCallback((environmentId: string) => {
if (api && isReady) {
api.sendCommandToMetaBox(new SetEnvironment(environmentId));
}
}, [api, isReady]);
const takeScreenshot = useCallback((
format: MimeType = 'image/png',
size?: { x: number; y: number },
) => {
if (api && isReady) {
api.sendCommandToMetaBox(new GetScreenshot(format, size));
}
}, [api, isReady]);
const changeMaterial = useCallback((slotId: string, materialId: string) => {
if (api && isReady) {
api.sendCommandToMetaBox(new SetComponentMaterial(slotId, materialId));
}
}, [api, isReady]);
const addComponent = useCallback((id: string, typeId: string, isRoot: boolean = false) => {
if (api && isReady) {
api.sendCommandToMetaBox(new SetComponent(id, typeId, isRoot));
}
}, [api, isReady]);
return {
containerRef,
api,
isReady,
configData,
isLoading,
error,
changeEnvironment,
takeScreenshot,
changeMaterial,
addComponent,
initialize,
destroy,
};
};
// Usage example in a React component
const ConfiguratorComponent: React.FC = () => {
const {
containerRef,
isReady,
isLoading,
error,
configData,
changeEnvironment,
takeScreenshot,
changeMaterial,
} = useMetaboxConfigurator({
configuratorUrl: 'https://metabox.3dsource.com/metabox-configurator/modular/your-id',
});
const handleEnvironmentChange = (envId: string) => {
changeEnvironment(envId);
};
const handleTakeScreenshot = () => {
takeScreenshot('image/png', { x: 1920, y: 1080 });
};
if (error) {
return <div className="error">Error loading configurator: {error}</div>;
}
return (
<div className="configurator-wrapper">
{isLoading && <div className="loading">Loading configurator...</div>}
<div ref={containerRef} className="configurator-container" />
{isReady && (
<div className="controls">
<button onClick={() => handleEnvironmentChange('showroom-1')}>
Showroom Environment
</button>
<button onClick={() => changeMaterial('seat', 'leather-brown')}>
Brown Leather
</button>
<button onClick={handleTakeScreenshot}>
Take Screenshot
</button>
</div>
)}
{configData && (
<div className="config-info">
<p>Components: {configData.componentsByComponentType ? Object.keys(configData.componentsByComponentType).length : 0}</p>
<p>Environment: {configData.environmentId}</p>
</div>
)}
</div>
);
};
```
## Event Handling
The API provides several events that you can listen to for real-time updates:
### Available Events
| Event Name | Description | Data Type |
| ------------------------- | ------------------------------------- | ----------------------------- |
| `configuratorDataUpdated` | Fired when configuration data changes | `ModularConfiguratorEnvelope` |
| `screenshotReady` | Fired when a screenshot is ready | `string` (base64 image data) |
| `showcaseStatusChanged` | Fired when showcase status changes | `ShowCaseStatus` |
| `viewportReady` | Fired when viewport is ready | `boolean` |
| `statusMessageChanged` | Fired when status message changes | `string \| null` |
### Event Listener Examples
```typescript
// Listen for configuration changes
api.addEventListener('configuratorDataUpdated', (data: ModularConfiguratorEnvelope) => {
console.log('Configuration updated:', data);
// Access specific data
console.log('Configurator:', data.configurator);
console.log('Configuration tree:', data.configurationTree);
console.log('Components by type:', data.componentsByComponentType);
console.log('Environment ID:', data.environmentId);
});
// Handle screenshot events
api.addEventListener('screenshotReady', (imageData: string) => {
// imageData is a base64 encoded image
const img = document.createElement('img');
img.src = imageData;
document.body.appendChild(img);
});
// Monitor showcase playback
api.addEventListener('showcaseStatusChanged', (status: ShowCaseStatus) => {
console.log('Showcase status:', status);
// Handle play/pause/stop states
});
// Handle viewport ready events
api.addEventListener('viewportReady', (isReady: boolean) => {
console.log('Viewport ready:', isReady);
});
// Handle status messages
api.addEventListener('statusMessageChanged', (message: string | null) => {
console.log('Status message:', message);
});
```
## Troubleshooting
### Common Issues
#### Configurator Not Loading
**Problem**: The configurator iframe doesn't appear or loads indefinitely.
**Solutions**:
1. Verify the configurator URL is correct and accessible
2. Check that the container element exists in the DOM
3. Ensure the container has proper dimensions (width/height)
4. Check the browser console for CORS or network errors
```typescript
// Add error handling
integrateMetabox(
configuratorUrl,
'embed3DSource',
(api) => {
console.log('API ready!');
},
(error) => {
console.error('Failed to load configurator:', error);
},
);
```
#### Commands Not Working
**Problem**: API commands are sent but don't affect the configurator.
**Solutions**:
1. Ensure the API is ready before sending commands
2. Verify component/environment IDs are correct
3. Check that the configurator supports the specific command
```typescript
// Wait for API to be ready
integrateMetabox(url, containerId, (api) => {
// Only send commands after this callback
api.sendCommandToMetaBox(new SetEnvironment('env-001'));
});
```
#### TypeScript Errors
**Problem**: TypeScript compilation errors with API types.
**Solutions**:
1. Ensure you're importing types correctly:
```typescript
import type { Communicator, ModularConfiguratorEnvelope } from '@3dsource/metabox-modular-configurator-api';
```
2. Update your `tsconfig.json` to include proper module resolution:
```json
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true
}
}
```
### Performance Tips
1. **Debounce rapid commands**: Avoid sending too many commands in quick succession
2. **Optimize screenshot size**: Use appropriate dimensions for your use case
3. **Clean up event listeners**: Remove listeners when components unmount
```typescript
// Debounce example
let timeoutId: NodeJS.Timeout;
const debouncedMaterialChange = (slotId: string, materialId: string) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
api.sendCommandToMetaBox(new SetComponentMaterial(slotId, materialId));
}, 300);
};
```
### Browser Compatibility
- **Modern browsers**: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
- **ES6 modules**: Required for CDN usage
- **HTTPS**: Required for production deployments
## Contributing
We welcome contributions to improve the Metabox Modular Configurator API!
### Development Setup
1. Clone the repository
2. Install dependencies: `npm install`
3. Build the library: `npm run build`
4. Run tests: `npm test`
---
For more examples and advanced usage, visit
our [documentation site](https://preview.3dsource.com/front-libraries/master/modular-configurator-api-doc/).