Skip to content

Image Assets

Elucim supports direct image URLs and host-managed asset references. Direct URLs are easiest for standalone documents; asset references are better when your app owns the image library, permissions, signed URLs, or CDN transforms.

FieldPurpose
srcDirect URL/data URI, or fallback preview URL when a ref is used.
ref / imageRefOpaque asset reference stored in the document.
displayNameHuman-readable asset label shown by the editor.
width / heightInitial sizing when the picker knows natural dimensions.
altAccessibility metadata preserved by the editor picker result.

Either src or an asset reference is required.

Provide onBrowseImage to let the inspector open your app’s asset picker:

import { ElucimEditor, type BrowseImageResult } from '@elucim/editor';
async function handleBrowseImage(): Promise<BrowseImageResult | null> {
const asset = await myAssetPicker.open();
if (!asset) return null;
return {
ref: asset.id,
displayName: asset.name,
src: asset.thumbnailUrl,
width: asset.width,
height: asset.height,
alt: asset.alt,
};
}
<ElucimEditor onBrowseImage={handleBrowseImage} />;

When onBrowseImage is set, image fields show a browse button next to the URL/reference controls. The picker may return a direct URL, an opaque ref, or both.

Provide imageResolver so ref-based images render in the editor canvas:

<ElucimEditor
initialDocument={doc}
onBrowseImage={handleBrowseImage}
imageResolver={(ref) => `/api/assets/${ref}/url`}
/>

Resolvers can return a string or Promise<string>:

const resolver = async (ref: string) => {
const response = await fetch(`/api/assets/${ref}/signed-url`);
if (!response.ok) throw new Error(`Could not resolve image ${ref}`);
return response.text();
};

While async resolution is pending, the renderer can use src as a fallback when it is present.

Use the same resolver when rendering the normalized document outside the editor:

import { DslRenderer, type ImageResolverFn } from '@elucim/dsl/react';
const imageResolver: ImageResolverFn = ref => `/api/assets/${ref}/url`;
<DslRenderer dsl={document} imageResolver={imageResolver} />;

Or wrap a subtree with the resolver provider:

import { DslRenderer, ImageResolverProvider } from '@elucim/dsl/react';
<ImageResolverProvider resolver={imageResolver}>
<DslRenderer dsl={document} />
</ImageResolverProvider>;

In Elucim Documents, image data lives in the element props object:

{
"version": "2.0",
"scene": {
"type": "player",
"width": 1280,
"height": 720,
"children": ["hero-image"]
},
"elements": {
"hero-image": {
"id": "hero-image",
"type": "image",
"props": {
"type": "image",
"ref": "asset-abc-123",
"displayName": "Hero Banner",
"src": "https://example.com/fallback.png",
"x": 80,
"y": 96,
"width": 640,
"height": 360
}
}
}
}
type ImageResolverFn = (ref: string) => string | Promise<string>;
interface BrowseImageResult {
src?: string;
ref?: string;
displayName?: string;
width?: number;
height?: number;
alt?: string;
}
type BrowseImageFn = () => Promise<BrowseImageResult | null>;