vivid--compose-layers-preview
v1.2.1
Published
Isolated React + TypeScript component for previewing composed image layers with status handling.
Downloads
46
Maintainers
Readme
ComposeLayersPreview
Universal React component for previewing composite image layers with support for different states (loading, success, error, empty).
Works in two ways:
- As a normal NPM package in React apps
- As a standalone CDN script on regular HTML pages (no React required)
Installation
NPM/Yarn
npm install vivid--compose-layers-preview
# or
yarn add vivid--compose-layers-previewCDN (no installation required)
<!-- Standalone build: React included inside -->
<link rel="stylesheet" href="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/style.css" />
<script src="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/standalone.min.js"></script>Usage
The component displays a stack of rendered image layers from a layers configuration. It handles different states (loading, success, error, empty) and allows users to preview how multiple layers combine into a final composite image. The layers are typically fetched from a render API endpoint and contain configuration data.
Important: The container element must have fixed dimensions (width and height) for the component to display correctly. The component will fill the entire container space and layer images will be positioned absolutely within it.
API Integration: This component is designed to work with configuration layer data returned by the render API endpoint
https://renderapi-dev.vivid3d.tech/2d/renderConfigurationLayers. The component automatically processes the layer ordering and composites them into a visual preview based on thelayerOrderproperty of each layer's options.
1) React applications (NPM)
import { useState, useEffect } from "react";
import {
ComposeLayersPreview,
type ComposeLayersArrT,
type ComposeLayerI,
JOB_STATUSES
} from "vivid--compose-layers-preview";
const exampleLayersData: ComposeLayersArrT = [
{
id: 5929,
productId: 41,
projectId: 2,
type: "layer",
status: "success",
config: {
stage: {
id: 28,
name: "M_TubyAnime",
paramString: "",
resourceUrl: "https://example.com/stage.pak",
},
camera: {
id: 43,
fov: 12,
name: "Dimension",
enabled: true,
rotationType: "Disabled",
nearClipPlane: 10,
// ... other camera properties
},
products: [
{
id: 41,
name: "Product 1",
type: "layer",
options: [
{
val: 19,
name: "Switch",
type: "geometry",
layerOrder: 1,
optionId: 8,
// ... other option properties
},
],
projectId: 2,
paramString: "",
resourceUrl: "https://example.com/product.pak",
},
],
configurationHash: "11ffd93f00f849c7d2669c6d04a6a7a40f6fe163fb473e9e20c75a43eaf18cf8",
},
imageUrl: "https://example.com/render.png",
thumbnailUrl: "https://example.com/thumbnail.webp",
annotationUrl: null,
configHash: "11ffd93f00f849c7d2669c6d04a6a7a40f6fe163fb473e9e20c75a43eaf18cf8",
relationHash: null,
massrenderJobId: 93,
errorMessage: null,
createdAt: "2025-10-03T09:30:12.762Z",
updatedAt: "2025-10-03T09:31:45.972Z",
},
// Additional layers with different layerOrder values...
];
export default function MyComponent() {
const [layers, setLayers] = useState<ComposeLayersArrT>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const fetchLayers = async () => {
setLoading(true);
try {
const res = await fetch("https://renderapi-dev.vivid3d.tech/2d/renderConfigurationLayers");
const data = await res.json();
setLayers(data);
setError(null);
} catch (e) {
setError("Failed to load layers");
} finally {
setLoading(false);
}
};
const refreshLayers = async () => {
fetchLayers();
};
useEffect(() => {
fetchLayers();
}, []);
return (
<div style={{ width: '800px', height: '600px' }}>
<ComposeLayersPreview
composeLayersArr={layers}
refresh={refreshLayers}
loading={loading}
error={error}
className="my-preview"
/>
</div>
);
}TypeScript Types (NPM only)
When using the NPM package in TypeScript projects, you can import all the necessary types:
import {
ComposeLayersPreview,
type ComposeLayersArrT,
type ComposeLayerI,
type ConfigI,
type ProductI,
type OptionI,
type CameraI,
type StageI,
type TransformI,
type PositionI,
type RotationI,
JOB_STATUSES
} from "vivid--compose-layers-preview";2) Regular websites (CDN)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ComposeLayersPreview Demo</title>
<link rel="stylesheet" href="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/style.css" />
<script src="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/standalone.min.js"></script>
</head>
<body>
<div id="preview" style="width:400px;height:300px"></div>
<button onclick="fetchLayers()">Load Layers</button>
<button onclick="refreshLayers()">Refresh</button>
<script>
let previewContainer = document.getElementById("preview");
let currentLayers = [];
let isLoading = false;
let currentError = null;
// Render component with current state
function renderPreview() {
ComposeLayersPreview.render(previewContainer, {
composeLayersArr: currentLayers,
refresh: refreshLayers,
loading: isLoading,
error: currentError,
className: "my-preview",
});
}
// Fetch layers from API
async function fetchLayers() {
isLoading = true;
currentError = null;
renderPreview();
try {
const response = await fetch("https://renderapi-dev.vivid3d.tech/2d/renderConfigurationLayers");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
currentLayers = data;
currentError = null;
} catch (error) {
console.error("Failed to fetch layers:", error);
currentError = "Failed to load layers: " + error.message;
currentLayers = [];
} finally {
isLoading = false;
renderPreview();
}
}
// Refresh function called by the component
function refreshLayers() {
fetchLayers();
}
// Initial render with empty state
renderPreview();
// Auto-load layers on page load
fetchLayers();
</script>
</body>
</html>Props
| Prop | Type | Required | Description | | ---------------- | ----------------- | -------- | --------------------------------- | | composeLayersArr | ComposeLayersArrT | Yes | Array of layer objects to display | | refresh | () => void | Yes | Trigger reloading/data fetch | | loading | boolean | No | Shows loading state | | error | string or null | No | Error text to display | | className | string | No | Extra CSS class on root |
Standalone (CDN) API
// Render component into a container element
ComposeLayersPreview.render(containerElement, props);
// Create React element (advanced)
ComposeLayersPreview.createElement(props);
// Direct access to React component
ComposeLayersPreview.ComposeLayersPreview;Styling
This component uses CSS Modules. The safest way to customize appearance is via CSS variables on a parent element or globally:
Supported variables:
- --content-main-color – main text color (default: #343a40)
- --link-color – link color for the refresh action (default: #2a8efa)
- --warning-color – error text color (default: #ff4b4b)
Example:
<div id="preview" style="--content-main-color:#222; --link-color:#0b74ff; --warning-color:#e11d48"></div>Development
git clone https://github.com/Elementals-technical/compose-layers-preview.git
cd compose-layers-preview
npm install
npm run devTesting CDN Usage Locally
To test the CDN (standalone) version locally during development:
Build the standalone version:
npm run build:standaloneTest with local files - Create an HTML file and use local paths:
<!-- Use local build files --> <link rel="stylesheet" href="./dist/standalone/style.css" /> <script src="./dist/standalone/standalone.min.js"></script>Test with CDN - Use the published CDN version:
<!-- Use published CDN --> <link rel="stylesheet" href="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/style.css" /> <script src="https://unpkg.com/vivid--compose-layers-preview/dist/standalone/standalone.min.js"></script>Included test file - The repository includes
standalone-test.htmlwhich demonstrates CDN usage with interactive examples.To run the test file locally:
# Option 1: Using npx serve (recommended) npx serve . # Then open http://localhost:3000/standalone-test.html # Option 2: Using Python (if installed) python -m http.server 8000 # Then open http://localhost:8000/standalone-test.html # Option 3: Using VS Code Live Server extension # Right-click on standalone-test.html → "Open with Live Server"
Note: When testing locally with file:// protocol, some browsers may block loading local files. Use a local server (like
npx serve .or VS Code Live Server extension) for testing.
