The Actions API provides a centralized way to manage and customize actions for various user interactions in CE.SDK.
API Methods#
The Actions API provides four methods:
- register(actionId, handler)- Register an action function for a specific event
- get(actionId)- Retrieve a registered action function
- run(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 CE.SDK:
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#
CE.SDK automatically registers the following default actions:
Action Handlers#
- saveScene- Saves the current scene (default: downloads scene file)
- shareScene- Shares the current scene (no default implementation)
- exportDesign- Exports design in various formats (default: downloads the exported file)
- importScene- Imports scene or archive files (default: opens file picker)
- exportScene- Exports scene or archive (default: downloads the file)
- uploadFile- Uploads files to asset sources (default: local upload for development)
- onUnsupportedBrowser- Handles unsupported browsers (no default implementation)
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',);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';});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', '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);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