The Actions API provides a centralized way to manage and customize actions for various user interactions in CE.SDK.
Two Layers of Actions#
CE.SDK exposes actions through two related registries:
cesdk.actions— the host actions (saveScene,exportDesign,uploadFile, and the rest documented below). These are convenience actions registered by the prebuilt editor.- The engine action registry — every editor command the engine ships (undo, delete, group, text formatting, zoom, pan, and many more) lives here as a named, overridable action, available wherever the engine runs (including headless via
@cesdk/engine).cesdk.actionswrites to this same underlying registry.
Because both write to one registry, re-registering an id from either side overrides whatever was there before.
The Action Registry#
An action is a named function stored under a string id, such as history.undo, text.toggleBold, or zoom. You run actions by id, override what a built-in id does, add your own, or list what is available.
Running an Action#
Call run(id, ...args) to execute an action. It returns a Promise that resolves to the action’s result — most engine defaults resolve to true or false (changed or no-change), a few to null.
// Undo the last change.await cesdk.actions.run('history.undo');
// Nudge the current selection 10px to the right.await cesdk.actions.run('nudge', { dx: 10, dy: 0 });
// Set the fill color of the selected blocks.await cesdk.actions.run('fill.color', { color: { r: 1, g: 0, b: 0, a: 1 } });Selection verbs act on the current selection (cesdk.engine.block.findAllSelected()); explicitly targeted actions take ids in their arguments.
Registering and Overriding#
Call register(id, fn) to add a new action or replace an existing one. Re-registering a default id overrides its behavior everywhere that id is used — including toolbar buttons, keyboard shortcuts, and the engine’s own dispatches.
// Add your own command.cesdk.actions.register('myCompany.report', async (payload) => { await sendAnalytics(payload); return { ok: true };});
// Override a built-in: confirm before deleting.cesdk.actions.register('selection.delete', async () => { if (await confirmDialog('Delete the selection?')) { cesdk.engine.block .findAllSelected() .forEach((id) => cesdk.engine.block.destroy(id)); }});On the web, an action you register runs directly in JavaScript, so arguments and results pass by reference — non-serializable values such as File, Blob, or callbacks work. The engine’s own dispatches and any cross-thread calls go through a JSON boundary, so values that cross it must be JSON-serializable.
Listing and Inspecting#
Call list(options?) to discover registered actions. It returns an array of { id, enabled, argSchema } objects. Pass a matcher glob to filter by id.
// Every registered action.const all = cesdk.actions.list();
// Just the engine defaults under the `text.` namespace.const textActions = cesdk.actions.list({ matcher: 'text.*' });// => [{ id: 'text.toggleBold', enabled: true, argSchema: '…' }, …]Use has(id) to test for an action, unregister(id) to remove a custom action or revert an overridden built-in to its default, and — on the web — get(id) to read back a function you registered so you can call it synchronously (it returns undefined for engine-default native actions; use run for those).
cesdk.actions.has('zoom'); // trueconst report = cesdk.actions.get('myCompany.report'); // the raw fn, web onlyAPI Methods#
The Actions API provides four methods:
register(actionId, handler)- Register an action function for a specific eventget(actionId)- Retrieve a registered action functionrun(actionId, ...args)- Execute a registered action with the provided arguments (throws if not registered)list(matcher)- Lists registered action IDs, optionally filtered by wildcard pattern
Getting Started#
Register actions after initializing the editor:
import CreativeEditorSDK from '@cesdk/cesdk-js';
const cesdk = await CreativeEditorSDK.create(container, { // license: 'YOUR_CESDK_LICENSE_KEY',});
// Register an actioncesdk.actions.register('actionType', async (...args) => { // Your custom implementation return result;});
// Execute a registered actionawait cesdk.actions.run('actionType', arg1, arg2);
// Or retrieve an action to call it laterconst action = cesdk.actions.get('actionType');
// List all registered actionsconst allActions = cesdk.actions.list();
// List actions matching a patternconst exportActions = cesdk.actions.list({ matcher: 'export*' });Default Actions#
In the prebuilt editor, both the host actions and every engine-default action are available — the engine runs inside the editor, so its full command vocabulary is registered too. The sections below document each default action.
Scene Creation#
scene.create#
Creates a new scene with configurable mode, layout and page sizes. Returns the scene block ID.
// Create a sceneawait cesdk.actions.run('scene.create');Options:
| Option | Type | Default | Description |
|---|---|---|---|
layout | SceneLayout | 'VerticalStack' | The scene layout. |
page | PageSpec | — | A single page specification. Cannot be used together with pages. |
pageCount | number | 1 | Number of pages to create from the single page spec. Ignored when pages is used. |
pages | PageSpec[] | — | An array of page specifications, one page per entry. Cannot be used together with page. |
Page Specification#
Pages can be specified in three ways:
1. Direct dimensions
Specify width, height, and unit directly:
await cesdk.actions.run('scene.create', { page: { width: 1080, height: 1920, unit: 'Pixel' }});
// With fixed orientation (prevents rotation from swapping dimensions)await cesdk.actions.run('scene.create', { page: { width: 1080, height: 1920, unit: 'Pixel', fixedOrientation: true }});2. Asset source reference
Reference a page preset from an asset source by its source and asset IDs:
// Use an Instagram Story presetawait cesdk.actions.run('scene.create', { page: { sourceId: 'ly.img.page.presets', assetId: 'ly.img.page.presets.instagram.story' }});3. Asset object
Pass an asset object directly, for example one returned by engine.asset.findAssets():
const result = await cesdk.engine.asset.findAssets('ly.img.page.presets', { query: ''});await cesdk.actions.run('scene.create', { page: result.assets[0]});Multiple Pages#
Create scenes with multiple pages:
// Multiple pages with different sizesawait cesdk.actions.run('scene.create', { pages: [ { width: 1080, height: 1920, unit: 'Pixel' }, { width: 1920, height: 1080, unit: 'Pixel' } ]});
// Multiple identical pages using pageCountawait cesdk.actions.run('scene.create', { page: { width: 1080, height: 1080, unit: 'Pixel' }, pageCount: 3});Scene Management Actions#
saveScene#
Handles saving the current scene. Default implementation downloads the scene file.
// Basic implementationcesdk.actions.register('saveScene', async () => { const scene = await cesdk.engine.scene.saveToString(); console.log('Scene saved:', scene.length, 'characters');
// Production: // await yourAPI.saveScene(scene);
cesdk.ui.showNotification('Scene saved successfully');});
// With loading dialogcesdk.actions.register('saveScene', async () => { const dialogController = cesdk.utils.showLoadingDialog({ title: 'Saving Scene', message: 'Please wait...', progress: 'indeterminate', });
try { const scene = await cesdk.engine.scene.saveToString(); console.log('Scene saved:', scene.length, 'characters');
// Production: // await yourAPI.saveScene(scene);
dialogController.showSuccess({ title: 'Saved', message: 'Scene saved successfully', }); } catch (error) { dialogController.showError({ title: 'Save Failed', message: 'Could not save the scene', }); throw error; }});shareScene#
Handles scene sharing. No default implementation.
// Register share functionalitycesdk.actions.register('shareScene', async () => { const scene = await cesdk.engine.scene.saveToString(); const shareUrl = 'https://example.com/shared-scene-placeholder'; console.log('Scene ready to share:', scene.length, 'characters');
// Production: // const shareUrl = await yourAPI.createShareableLink(scene);
await navigator.share({ url: shareUrl });});importScene and exportScene#
Handle scene import/export operations with support for both scene files and archives.
// Import scene or archivecesdk.actions.register('importScene', async ({ format }) => { if (format === 'archive') { console.log('Archive import requested');
// Production: // const archive = await yourAPI.loadArchive(); // await cesdk.engine.scene.loadFromArchiveURL(archive); } else { console.log('Scene import requested');
// Production: // const scene = await yourAPI.loadScene(); // await cesdk.engine.scene.loadFromString(scene); }});
// Export scene or archivecesdk.actions.register('exportScene', async ({ format }) => { if (format === 'archive') { const archive = await cesdk.engine.scene.saveToArchive(); console.log('Archive ready for export:', archive.length, 'bytes');
// Production: // await yourAPI.uploadArchive(archive); } else { const scene = await cesdk.engine.scene.saveToString(); console.log('Scene ready for export:', scene.length, 'characters');
// Production: // await yourAPI.uploadScene(scene); }});Export Operations#
exportDesign#
Handles all export operations (images, PDFs, videos). Default implementation downloads the exported file.
// Basic implementationcesdk.actions.register('exportDesign', async options => { // Use the utils API to perform the export with loading dialog const { blobs, options: exportOptions } = await cesdk.utils.export(options); console.log('Exported', blobs.length, 'files'); blobs.forEach((blob, i) => console.log(`File ${i + 1}:`, blob.size, 'bytes'));
// Production: // await Promise.all(blobs.map(blob => yourCDN.upload(blob)));
cesdk.ui.showNotification('Export completed successfully');});
// Direct engine export with custom loading dialog (bypassing utils)cesdk.actions.register('exportDesign', async options => { const dialogController = cesdk.utils.showLoadingDialog({ title: 'Exporting', message: 'Processing your export...', });
try { const page = cesdk.engine.scene.getCurrentPage(); if (page === null) { throw new Error('No page selected for export'); } let result;
if (options?.mimeType?.startsWith('video/')) { // Video export with progress result = await cesdk.engine.block.exportVideo(page, { ...options, onProgress: (rendered, encoded, total) => { dialogController.updateProgress({ value: rendered, max: total, }); }, }); } else { // Static export (image/PDF) result = await cesdk.engine.block.export(page, options); }
console.log('File ready for export:', result.size, 'bytes');
// Production: // await yourCDN.upload(result);
dialogController.showSuccess({ title: 'Export Complete', message: 'Files uploaded successfully', }); } catch (error) { dialogController.showError({ title: 'Export Failed', message: 'Could not complete the export', }); throw error; }});File Upload Action#
uploadFile#
Handles file uploads to asset sources. Default implementation uses local upload for development.
// Register production upload handlercesdk.actions.register('uploadFile', async (file, onProgress, context) => { console.log('Uploading file:', file.name, file.size, 'bytes'); onProgress(50); // Simulate progress await new Promise(resolve => setTimeout(resolve, 500)); onProgress(100);
// Production: // const asset = await yourStorageService.upload(file, { // onProgress: (percent) => onProgress(percent), // context // });
// Return AssetDefinition return { id: 'local-' + Date.now(), label: { en: file.name }, meta: { uri: URL.createObjectURL(file), thumbUri: URL.createObjectURL(file), kind: 'image', width: 1920, height: 1080, // Production: // uri: asset.url, // thumbUri: asset.thumbnailUrl, // width: asset.width, // height: asset.height }, };});You can control which file types users can upload by setting the upload/supportedMimeTypes setting:
// Example 1: Only allow imagescesdk.engine.editor.setSettingString( 'upload/supportedMimeTypes', 'image/png,image/jpeg,image/gif,image/svg+xml',);
// Example 2: Allow images and videoscesdk.engine.editor.setSettingString( 'upload/supportedMimeTypes', 'image/png,image/jpeg,image/gif,video/mp4,video/quicktime',);
// Example 3: Allow specific document typescesdk.engine.editor.setSettingString( 'upload/supportedMimeTypes', 'application/pdf,image/png,image/jpeg',);Asset Library Actions#
asset.delete#
Invoked when the user deletes an asset from an asset source via the asset library card. The default implementation opens a confirmation dialog and, on confirm, removes the asset from its source. Register a custom implementation to replace the dialog content, swap in your own dialog, or change the deletion behavior entirely.
The handler receives the source id and the full AssetResult, so you can derive per-asset context such as metadata or a page number for your custom UI.
cesdk.actions.register('asset.delete', async ({ sourceId, asset }) => { const pageNumber = asset.meta?.pageNumber;
cesdk.ui.showDialog({ type: 'error', content: { title: `Delete page ${pageNumber}?`, message: 'This will also remove the page from your design.', }, actions: [ { color: 'danger', label: 'Delete', onClick: ({ id }) => { cesdk.engine.asset.removeAssetFromSource(sourceId, asset.id); cesdk.engine.asset.assetSourceContentsChanged(sourceId); cesdk.ui.closeDialog(id); }, }, ], cancel: { variant: 'plain', label: 'Cancel', onClick: ({ id }) => cesdk.ui.closeDialog(id), }, });});Unsupported Browser Action#
onUnsupportedBrowser#
Handles unsupported browser detection. No default implementation is provided.
// Register handler for unsupported browserscesdk.actions.register('onUnsupportedBrowser', () => { // Redirect to a custom compatibility page window.location.href = '/browser-not-supported';});Video Support Actions#
CE.SDK provides actions to detect video capabilities at runtime. These actions help you handle browsers and platforms that lack required video codecs, particularly Linux browsers and Firefox.
video.decode.checkSupport#
Checks if the browser supports video decoding and playback via the WebCodecs API. If unsupported, displays a blocking error dialog that users cannot dismiss.
Returns true if video decoding is supported, false otherwise.
// Check video decode support before loading video contentconst isSupported = cesdk.actions.run('video.decode.checkSupport');
if (!isSupported) { // A blocking error dialog is shown automatically // The user cannot proceed with video editing return;}
// Safe to proceed with video contentawait cesdk.engine.scene.loadFromURL(videoSceneUrl);
// You can also disable the dialog and handle feedback yourself:const supportedSilently = cesdk.actions.run('video.decode.checkSupport', { dialog: false});Options:
| Option | Type | Default | Description |
|---|---|---|---|
dialog | boolean | { show: boolean; backdrop?: 'transparent' | 'opaque' } | true (backdrop: 'opaque') | Controls dialog display. Use false to disable, or an object for fine-grained control. |
video.encode.checkSupport#
Checks if the browser supports video encoding/export (H.264 video and AAC audio encoding). If unsupported, displays a warning dialog that users can dismiss to continue editing.
Returns a Promise<boolean> - true if video encoding is supported, false otherwise.
// Check video encode support before attempting exportconst canExport = await cesdk.actions.run('video.encode.checkSupport');
if (!canExport) { // A warning dialog is shown automatically // User can dismiss and continue editing // Consider offering server-side export as alternative console.log('Video export unavailable - consider server-side rendering');}
// You can also disable the dialog and handle feedback yourself:const canExportSilently = await cesdk.actions.run('video.encode.checkSupport', { dialog: false});Options:
| Option | Type | Default | Description |
|---|---|---|---|
dialog | boolean | { show: boolean; backdrop?: 'transparent' | 'opaque' } | true (backdrop: 'transparent') | Controls dialog display. Use false to disable, or an object for fine-grained control. |
Platform Support#
| Platform | Video Import | Video Export |
|---|---|---|
| Chrome/Edge (Windows, macOS) | ✅ | ✅ |
| Safari (macOS) | ✅ | ✅ |
| Chrome (Linux) | ❌ | ❌ |
| Firefox (all platforms) | ❌ | ❌ |
Zoom Actions#
CE.SDK provides built-in zoom actions for controlling the viewport zoom level and focus. These actions are automatically registered and can be customized or called programmatically.
zoom.toBlock#
Zooms the viewport to fit a specific block.
// Zoom to a block with default settingsawait cesdk.actions.run('zoom.toBlock', blockId);
// Zoom with custom padding and animationawait cesdk.actions.run('zoom.toBlock', blockId, { padding: 50, // Uniform padding on all sides animate: true, autoFit: false});
// Different padding for each sideawait cesdk.actions.run('zoom.toBlock', blockId, { padding: { top: 20, bottom: 20, left: 40, right: 40 }, animate: { duration: 0.3, easing: 'EaseInOut' }});zoom.toPage#
Zooms to the current page or a specified page. If no options are provided, defaults to the current page.
// Zoom to current page with auto-fitawait cesdk.actions.run('zoom.toPage', { autoFit: true, animate: false});
// Zoom with custom paddingawait cesdk.actions.run('zoom.toPage', { padding: { x: 40, y: 80 }, animate: true});zoom.toSelection#
Zooms to fit all currently selected blocks in the viewport.
// Zoom to selection with animationawait cesdk.actions.run('zoom.toSelection', { padding: 40, animate: true});
// Auto-fit to selectionawait cesdk.actions.run('zoom.toSelection', { autoFit: true, padding: { x: 20, y: 20 }});zoom.in and zoom.out#
Step-based zoom controls with configurable limits.
// Zoom in with default settingsawait cesdk.actions.run('zoom.in');
// Zoom in with custom maximumawait cesdk.actions.run('zoom.in', { maxZoom: 4, // Maximum zoom level animate: true});
// Zoom out with custom minimumawait cesdk.actions.run('zoom.out', { minZoom: 0.25, // Minimum zoom level animate: { duration: 0.2, easing: 'EaseOut' }});zoom.toLevel#
Sets the zoom to a specific level.
// Set zoom to 100%await cesdk.actions.run('zoom.toLevel', 1.0);
// Set zoom to 200% with animationawait cesdk.actions.run('zoom.toLevel', 2.0, { animate: true, minZoom: 0.125, maxZoom: 32});
// Fit to width (50% zoom)await cesdk.actions.run('zoom.toLevel', 0.5, { animate: { duration: 0.3, easing: 'EaseInOut' }});Padding Options#
Padding can be specified in multiple ways:
// Uniform padding on all sides{ padding: 20 }
// Different horizontal and vertical padding{ padding: { x: 40, y: 20 } }
// Individual padding for each side{ padding: { top: 10, bottom: 20, left: 30, right: 40 } }Animation Options#
Animation can be a boolean or an object with detailed settings:
// Simple animation toggle{ animate: true } // Uses default duration and easing{ animate: false } // No animation
// Detailed animation configuration{ animate: { duration: 0.3, // Duration in seconds easing: 'EaseInOut', // 'Linear', 'EaseIn', 'EaseOut', or 'EaseInOut' interruptible: true // Whether the animation can be interrupted }}Auto-Fit Mode#
The autoFit option enables automatic zoom adjustment when the viewport resizes:
// Enable auto-fit to maintain proper framingawait cesdk.actions.run('zoom.toPage', { autoFit: true, padding: { x: 40, y: 80 }});When auto-fit is enabled, the zoom level will automatically adjust to keep the target properly framed when the viewport size changes.
Custom Zoom Action Example#
You can override the default zoom actions with custom implementations:
// Custom zoom to page with analyticscesdk.actions.register('zoom.toPage', async (options) => { // Track zoom event console.log('User zoomed to page');
// Get current page const currentPage = cesdk.engine.scene.getCurrentPage(); if (!currentPage) return;
// Apply custom zoom logic await cesdk.engine.scene.zoomToBlock(currentPage, { padding: options?.padding ?? { x: 50, y: 100 }, animate: options?.animate ?? true });
// Custom post-zoom behavior cesdk.ui.showNotification('Zoomed to page');});Video Timeline Zoom Actions#
The video timeline has its own set of zoom controls for managing the timeline view. These actions are registered when the video timeline component is active and provide instant zoom without animation.
timeline.zoom.in#
Zooms in the video timeline by one step (multiplies current zoom level by 1.25).
// Zoom in the timelineawait cesdk.actions.run('timeline.zoom.in');timeline.zoom.out#
Zooms out the video timeline by one step (divides current zoom level by 1.25).
// Zoom out the timelineawait cesdk.actions.run('timeline.zoom.out');timeline.zoom.fit#
Automatically adjusts the timeline zoom to fit all content in the visible area.
// Fit timeline to show all contentawait cesdk.actions.run('timeline.zoom.fit');timeline.zoom.toLevel#
Sets the timeline zoom to a specific level.
// Set timeline zoom to 100%await cesdk.actions.run('timeline.zoom.toLevel', 1.0);
// Set timeline zoom to 150%await cesdk.actions.run('timeline.zoom.toLevel', 1.5);
// Set timeline zoom to 50%await cesdk.actions.run('timeline.zoom.toLevel', 0.5);timeline.zoom.reset#
Resets the timeline zoom to the default level (1.0 or 100%).
// Reset timeline zoom to defaultawait cesdk.actions.run('timeline.zoom.reset');Scroll Actions#
CE.SDK provides a scroll action for panning the viewport to different pages without changing the zoom level. This is useful for multi-page navigation where you want to maintain the current zoom.
scroll.toPage#
Scrolls the viewport to center on a specific page without changing the zoom level.
// Scroll to current page without animationawait cesdk.actions.run('scroll.toPage');
// Scroll to current page with smooth animationawait cesdk.actions.run('scroll.toPage', { animate: true});
// Scroll to a specific pageawait cesdk.actions.run('scroll.toPage', { pageId: myPageId, animate: true});Parameters#
The scroll.toPage action accepts an optional options object:
pageId(optional): The ID of the page to scroll to. If not provided, scrolls to the current page.animate(optional): Whether to animate the scroll transition. Default isfalse.
Scroll vs Zoom#
The key difference between scroll.toPage and zoom.toPage:
scroll.toPage: Pans the viewport to center on the page while maintaining the current zoom levelzoom.toPage: Adjusts the zoom level to fit the page within the viewport with padding
Use scroll.toPage when you want to navigate between pages in a multi-page document while keeping the same zoom level. Use zoom.toPage when you want to frame a page properly within the viewport.
Clipboard Actions#
copy- Copy the current selectioncut- Copy the current selection, then delete itpaste- Paste the clipboard contents
Selection & Navigation Actions#
selection.parentOrDeselect- Select the parent group, or deselect if nonegroup.enterOrExit- Enter the selected group, or exit the current groupvectorPath.deleteNodeOrPoint- Delete the selected vector node or control point
Movement Actions#
selection.nudgeUp/selection.nudgeDown/selection.nudgeLeft/selection.nudgeRight- Nudge the selection by one stepselection.nudgeUpExtended/selection.nudgeDownExtended/selection.nudgeLeftExtended/selection.nudgeRightExtended- Nudge the selection by a larger step
Text Formatting Actions#
text.toggleBold- Toggle bold on the selected texttext.toggleItalic- Toggle italic on the selected texttext.toggleUnderline- Toggle underline on the selected texttext.toggleStrikethrough- Toggle strikethrough on the selected text
Editor & UI Actions#
toggleUserInterfaceVisibility- Show or hide the editor UIzoom.toFit- Zoom to fit the current pagescroll.toBlock- Scroll the viewport to center on a blockeditor.checkBrowserSupport- Check whether the current browser is supportedtimeline.collapse- Collapse the video timelinetimeline.expand- Expand the video timeline
History#
history.undo- Undo the last changehistory.redo- Redo the last undone change
Lifecycle / selection#
selection.delete- Delete the selected blocksselection.duplicate- Duplicate the selected blocksselection.group- Group the selected blocksselection.ungroup- Ungroup the selected groupgroup.enter- Enter the selected group for editinggroup.exit- Exit the current groupselect- Select blocks by id (dispatched by the engine on click)selection.all- Select all blocks on the current pageselect.byType- Select all blocks of a given typeselection.parentOrDeselect- Select the parent group, or deselect if nonerename- Rename the selected blocklock.toggle- Toggle the lock state of the selected blocks
Transform / arrange#
nudge- Move the selection by a pixel delta ({ dx, dy })transform- Apply position/size/rotation to blocksresize- Resize the selection by a delta or scalescale- Scale the selection around an anchorrotate- Rotate the selection by degrees (absolute or relative)flip.horizontal- Flip the selection horizontallyflip.vertical- Flip the selection verticallyalign.horizontal- Align the selection horizontally (left/center/right)align.vertical- Align the selection vertically (top/center/bottom)distribute.horizontal- Distribute the selection horizontallydistribute.vertical- Distribute the selection verticallymatchSize- Match the size of the selection to a reference blockbringToFront- Bring the selection to the frontbringForward- Bring the selection forward one stepsendBackward- Send the selection backward one stepsendToBack- Send the selection to the backreorder.moveToIndex- Move the selection to a specific layer indexreparent- Move the selection under a new parent
Appearance#
opacity- Set the opacity of the selectionvisibility.toggle- Toggle visibility of the selectionblendMode- Set the blend mode of the selectionfill.color- Set the solid fill colorfill.toggle- Toggle the fill on or offcontentFillMode- Set the content fill mode (crop/cover/contain)stroke.toggle- Toggle the stroke on or offstroke.color- Set the stroke colorstroke.width- Set the stroke widthdropShadow.toggle- Toggle the drop shadow on or offdropShadow.color- Set the drop shadow colordropShadow.offset- Set the drop shadow offsetdropShadow.blur- Set the drop shadow blurblur.toggle- Toggle the block blur on or offblur.set- Set the block blur typeeffect.append- Append an effect to the selectioneffect.remove- Remove an effect by indexeffect.clear- Remove all effects from the selection
Crop / edit mode#
crop.enter- Enter crop mode (dispatched by the engine on double-click)crop.reset- Reset the crop to its defaultcrop.fillFrame- Fill the frame with the cropped contenteditmode.exit- Exit the current edit modetext.edit- Enter text editing (dispatched by the engine on double-click)
Text#
text.toggleBold- Toggle bold on the selected texttext.toggleItalic- Toggle italic on the selected texttext.fontSize- Set the font sizetext.align- Set the text alignment (left/center/right)text.case- Set the text case (normal/upper/lower/title)text.color- Set the text colortext.lineHeight- Set the line heighttext.letterSpacing- Set the letter spacingtext.list- Set the list style (none/unordered/ordered)text.typeface- Set the typeface
Pages#
page.add- Add a new pagepage.selectNext- Scroll to the next pagepage.selectPrevious- Scroll to the previous pagepage.remove- Remove a pagepage.duplicate- Duplicate a pagepage.size- Set a page’s sizepage.background.toggle- Toggle a page’s background fillpage.title.edit- Edit a page’s title (dispatched by the engine)
Scene / view#
scene.layout- Set the scene layout (free/stacks)scene.size- Set the scene sizezoom- Set the zoom level/factor around a pivotzoom.autoFit.toggle- Toggle auto-fit zoom on an axispan- Pan the viewport by a delta
Video / timeline / playback#
selection.split- Split the selected clip at the playheadaddClip- Add a clip to the timelinevideo.playPause- Toggle playback of the current pageplayback.seek- Seek playback to a timeduration- Set the duration of the selectiontrim.offset- Set the trim offset of the selectiontrim.length- Set the trim length of the selectionplaybackSpeed- Set the playback speed of the selectionvolume- Set the volume of the selectionmute.toggle- Toggle mute on the selectionloop.toggle- Toggle looping on the selectiontimeOffset- Set the time offset of the selectionanimation.in/animation.in.remove- Set or remove the in animationanimation.out/animation.out.remove- Set or remove the out animationanimation.loop/animation.loop.remove- Set or remove the loop animation
Canvas interaction primitives#
drag.begin- Begin a drag gesture on blocksdrag.end- End a drag gesture on blockssecondaryAction- The secondary (context) action at a position
Register actions after initializing the headless engine:
import CreativeEngine from '@cesdk/engine';
const engine = await CreativeEngine.init({ // license: 'YOUR_CESDK_LICENSE_KEY',});
// Register an actionengine.actions.register('actionType', async (...args) => { // Your custom implementation return result;});
// Execute a registered actionawait engine.actions.run('actionType', arg1, arg2);
// Or retrieve an action to call it laterconst action = engine.actions.get('actionType');
// List all registered actionsconst allActions = engine.actions.list();
// List actions matching a patternconst exportActions = engine.actions.list({ matcher: 'text.*' });Engine-Default Actions#
The engine seeds its registry with the editor’s command vocabulary. These run wherever the engine runs, including headless mode via @cesdk/engine. Run any of them by id, override them, or bind them to a keyboard shortcut. The full set is discoverable at runtime:
History#
history.undo- Undo the last changehistory.redo- Redo the last undone change
Lifecycle / selection#
selection.delete- Delete the selected blocksselection.duplicate- Duplicate the selected blocksselection.group- Group the selected blocksselection.ungroup- Ungroup the selected groupgroup.enter- Enter the selected group for editinggroup.exit- Exit the current groupselect- Select blocks by id (dispatched by the engine on click)selection.all- Select all blocks on the current pageselect.byType- Select all blocks of a given typeselection.parentOrDeselect- Select the parent group, or deselect if nonerename- Rename the selected blocklock.toggle- Toggle the lock state of the selected blocks
Transform / arrange#
nudge- Move the selection by a pixel delta ({ dx, dy })transform- Apply position/size/rotation to blocksresize- Resize the selection by a delta or scalescale- Scale the selection around an anchorrotate- Rotate the selection by degrees (absolute or relative)flip.horizontal- Flip the selection horizontallyflip.vertical- Flip the selection verticallyalign.horizontal- Align the selection horizontally (left/center/right)align.vertical- Align the selection vertically (top/center/bottom)distribute.horizontal- Distribute the selection horizontallydistribute.vertical- Distribute the selection verticallymatchSize- Match the size of the selection to a reference blockbringToFront- Bring the selection to the frontbringForward- Bring the selection forward one stepsendBackward- Send the selection backward one stepsendToBack- Send the selection to the backreorder.moveToIndex- Move the selection to a specific layer indexreparent- Move the selection under a new parent
Appearance#
opacity- Set the opacity of the selectionvisibility.toggle- Toggle visibility of the selectionblendMode- Set the blend mode of the selectionfill.color- Set the solid fill colorfill.toggle- Toggle the fill on or offcontentFillMode- Set the content fill mode (crop/cover/contain)stroke.toggle- Toggle the stroke on or offstroke.color- Set the stroke colorstroke.width- Set the stroke widthdropShadow.toggle- Toggle the drop shadow on or offdropShadow.color- Set the drop shadow colordropShadow.offset- Set the drop shadow offsetdropShadow.blur- Set the drop shadow blurblur.toggle- Toggle the block blur on or offblur.set- Set the block blur typeeffect.append- Append an effect to the selectioneffect.remove- Remove an effect by indexeffect.clear- Remove all effects from the selection
Crop / edit mode#
crop.enter- Enter crop mode (dispatched by the engine on double-click)crop.reset- Reset the crop to its defaultcrop.fillFrame- Fill the frame with the cropped contenteditmode.exit- Exit the current edit modetext.edit- Enter text editing (dispatched by the engine on double-click)
Text#
text.toggleBold- Toggle bold on the selected texttext.toggleItalic- Toggle italic on the selected texttext.fontSize- Set the font sizetext.align- Set the text alignment (left/center/right)text.case- Set the text case (normal/upper/lower/title)text.color- Set the text colortext.lineHeight- Set the line heighttext.letterSpacing- Set the letter spacingtext.list- Set the list style (none/unordered/ordered)text.typeface- Set the typeface
Pages#
page.add- Add a new pagepage.selectNext- Scroll to the next pagepage.selectPrevious- Scroll to the previous pagepage.remove- Remove a pagepage.duplicate- Duplicate a pagepage.size- Set a page’s sizepage.background.toggle- Toggle a page’s background fillpage.title.edit- Edit a page’s title (dispatched by the engine)
Scene / view#
scene.layout- Set the scene layout (free/stacks)scene.size- Set the scene sizezoom- Set the zoom level/factor around a pivotzoom.autoFit.toggle- Toggle auto-fit zoom on an axispan- Pan the viewport by a delta
Video / timeline / playback#
selection.split- Split the selected clip at the playheadaddClip- Add a clip to the timelinevideo.playPause- Toggle playback of the current pageplayback.seek- Seek playback to a timeduration- Set the duration of the selectiontrim.offset- Set the trim offset of the selectiontrim.length- Set the trim length of the selectionplaybackSpeed- Set the playback speed of the selectionvolume- Set the volume of the selectionmute.toggle- Toggle mute on the selectionloop.toggle- Toggle looping on the selectiontimeOffset- Set the time offset of the selectionanimation.in/animation.in.remove- Set or remove the in animationanimation.out/animation.out.remove- Set or remove the out animationanimation.loop/animation.loop.remove- Set or remove the loop animation
Canvas interaction primitives#
drag.begin- Begin a drag gesture on blocksdrag.end- End a drag gesture on blockssecondaryAction- The secondary (context) action at a position
Overriding Engine Defaults Safely#
Some actions are dispatched by the engine itself in response to user input — for example select (on click), crop.enter and text.edit (on double-click), and page.title.edit. The engine reads the result of these within the same update, so an override of one of them must apply its effect synchronously.
// Synchronous override — runs in the same tick, so the engine sees the result.cesdk.actions.register('select', ({ ids }) => { applyMySelection(ids);});Utils API#
CE.SDK provides a Utils API with utility functions for common operations. These utilities are available through cesdk.utils:
Loading Dialogs#
// Create and manage loading dialogsconst dialogController = cesdk.utils.showLoadingDialog({ title: 'Processing...', message: 'Please wait', // Can also be an array of strings progress: 0, // Initial progress value or 'indeterminate' cancelLabel: 'Cancel', abortTitle: 'Abort Operation?', abortMessage: 'Are you sure you want to abort?', abortLabel: 'Abort', size: 'large', // 'regular' or 'large' clickOutsideToClose: false, onAbort: () => console.log('User cancelled'), onDone: () => console.log('Dialog closed'),});
// Update progressdialogController.updateProgress({ value: 50, max: 100 });
// Show success or errordialogController.showSuccess({ title: 'Done!', message: 'Operation completed',});dialogController.showError({ title: 'Error', message: 'Something went wrong' });
// Close dialogdialogController.close();Export Utility#
The export utility automatically handles both static (images, PDFs) and video exports:
// Export image or PDFconst { blobs, options } = await cesdk.utils.export({ mimeType: 'image/png', pngCompressionLevel: 7,});
// Export video (automatically detected by MIME type)const { blobs, options } = await cesdk.utils.export({ mimeType: 'video/mp4', onProgress: (rendered, encoded, total) => { console.log(`Progress: ${rendered}/${total} frames`); },});File Operations#
// Load file from userconst file = await cesdk.utils.loadFile({ accept: 'image/*', returnType: 'File', // 'dataURL', 'objectURL', 'text', 'blob', 'arrayBuffer', or 'File'});
// Download file to user's deviceawait cesdk.utils.downloadFile(blob, 'image/png');
// Local upload (development only)const asset = await cesdk.utils.localUpload(file, context);Video Support Detection#
Check browser video capabilities before working with video content:
// Check if video decoding/playback is supportedif (cesdk.utils.supportsVideoDecode()) { // Safe to load and play video content await cesdk.engine.scene.loadFromURL(videoSceneUrl);} else { // Show fallback UI or message console.log('Video playback not available in this browser');}
// Check if video encoding/export is supported (async)if (await cesdk.utils.supportsVideoEncode()) { // Video export is available const blob = await cesdk.engine.block.exportVideo(page);} else { // Suggest server-side rendering alternative console.log('Video export not available - consider using CE.SDK Renderer');}These utilities provide the same checks as the video.decode.checkSupport and video.encode.checkSupport actions, but without showing dialogs. Use them when you want to check support silently and handle the UI yourself.
Implementation Examples#
Environment-Based Upload Strategy#
// Use local upload in development, CDN in productioncesdk.actions.register('uploadFile', async (file, onProgress, context) => { if (process.env.NODE_ENV === 'development') { // Use utils for local upload return await cesdk.utils.localUpload(file, context); } else { console.log('Production upload for:', file.name); onProgress(100);
// Production: // const asset = await yourCDNService.upload(file, { // onProgress: onProgress // });
return { id: 'prod-' + Date.now(), label: { en: file.name }, meta: { uri: URL.createObjectURL(file), thumbUri: URL.createObjectURL(file), // Production: // uri: asset.url, // thumbUri: asset.thumbnailUrl }, }; }});Combining Utils with Custom Logic#
// Use utils for heavy lifting, add custom business logiccesdk.actions.register('exportDesign', async options => { console.log('Export started:', { format: options?.mimeType });
// Production: // analytics.track('export_started', { format: options?.mimeType });
// Use utils to handle the export with loading dialog const { blobs, options: exportOptions } = await cesdk.utils.export(options);
// Custom post-processing if (exportOptions.mimeType === 'application/pdf') { console.log('PDF ready for watermarking:', blobs[0].size, 'bytes');
// Production: // const watermarkedBlob = await addWatermark(blobs[0]); // await cesdk.utils.downloadFile(watermarkedBlob, 'application/pdf');
await cesdk.utils.downloadFile(blobs[0], 'application/pdf'); } else { // Direct download for other formats await cesdk.utils.downloadFile(blobs[0], exportOptions.mimeType); }
console.log('Export completed:', { format: exportOptions.mimeType });
// Production: // analytics.track('export_completed', { format: exportOptions.mimeType });});Registering Custom Actions with Custom IDs#
Beyond the predefined action types, you can register actions with custom IDs for your own application-specific needs:
// Register a custom actioncesdk.actions.register('myCustomAction', async data => { console.log('Custom action triggered with:', data); return { success: true, processedData: data };});
// Execute the custom action using runconst result = await cesdk.actions.run('myCustomAction', { someData: 'value' });
// Or retrieve it for conditional executionconst customAction = cesdk.actions.get('myCustomAction');if (customAction) { const result = await customAction({ someData: 'value' });}Discovering Registered Actions#
Use list() to get all registered action IDs or find actions matching a pattern:
// Get all registered action IDsconst registeredActions = cesdk.actions.list();console.log('Available actions:', registeredActions);
// Find actions matching a patternconst exportActions = cesdk.actions.list({ matcher: 'export*' });console.log('Export actions:', exportActions);Using Actions with Navigation Actions#
The navigation bar actions in CE.SDK automatically use the registered actions:
Default Navigation Bar Actions#
The default navigation bar actions map to actions:
- Save action →
saveSceneaction - Share action →
shareSceneaction - Export actions →
exportDesignaction - Import scene/archive →
importSceneaction - Export scene/archive →
exportSceneaction