Skip to main content

Overview

The ImageEditor component provides a powerful image editing interface with support for filters, effects, text, shapes, and more.

Import

'use client';

import dynamic from 'next/dynamic';

const ImageEditor = dynamic(
  () => import('@distralabs/media-editor').then(mod => ({ default: mod.ImageEditor })),
  { ssr: false }
);
Always use dynamic import with ssr: false to avoid server-side rendering issues.

Props

Required Props

licenseKey
string
required
Your SDK license key (JWT format). Contact your account manager to obtain a license key.
licenseKey="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
onClose
() => void
required
Callback function called when the user closes the editor.
onClose={() => setShowEditor(false)}

Optional Props

apiUrl
string
Override the default license validation API endpoint.Default: https://api.kloudleads.com/license/validate
apiUrl="https://localhost:3030/social"
The SDK appends /license/validate to this URL. If your endpoint is https://localhost:3030/social/license/validate, use apiUrl="https://localhost:3030/social".
files
File
Initial image file to load into the editor.
const [file, setFile] = useState<File | null>(null);

<ImageEditor
  files={file}
  // ...
/>
callback
(result: CallbackProps, extras?: EditorExtras) => void
Callback function called when the user exports the edited image.CallbackProps:
interface CallbackProps {
  base64: string;        // Data URL of exported image
  width: number;         // Canvas width
  height: number;        // Canvas height
  template?: any;        // Scene data if template used
}
EditorExtras:
interface EditorExtras {
  thumbnail?: string;    // Thumbnail preview
  format?: string;       // Image format (png, jpg, etc)
}
Example:
const handleExport = (result: CallbackProps, extras?: EditorExtras) => {
  // Download the image
  const link = document.createElement('a');
  link.href = result.base64;
  link.download = 'edited-image.png';
  link.click();

  // Or upload to server
  fetch('/api/upload', {
    method: 'POST',
    body: JSON.stringify({ image: result.base64 }),
  });
};
theme
Record<string, string>
Custom theme object to override default colors and styling.
const customTheme = {
  'background.primary': '#0f172a',
  'background.secondary': '#1e293b',
  'text.primary': '#ffffff',
  'accent.primary': '#3b82f6',
};

<ImageEditor theme={customTheme} />
See Theme Customization for all available keys.
showThemeCreator
boolean
default:"false"
Show theme customization UI to users. Set to false for production.
showThemeCreator={false}  // Hide theme UI
headless
boolean
default:"false"
Enable headless (programmatic) mode. The editor will execute predefined functions without showing the UI.
<ImageEditor
  headless={true}
  calls={[
    () => handleAddText(['Headline']),
    () => handleAddShape('rectangle'),
  ]}
/>
calls
CallItem[]
Array of functions to execute in headless mode.
calls={[
  () => handleAddText(['Text 1', 'Text 2']),
  () => handleAddShape('rectangle'),
  () => applyFilter('grayscale'),
]}
brands
BrandDetails[]
Array of brand presets for consistent styling.
interface BrandDetails {
  id: string;
  name: string;
  primaryColor?: string;
  secondaryColor?: string;
  fontFamily?: string;
  logo?: string;
}

const brands = [
  {
    id: 'brand-1',
    name: 'My Brand',
    primaryColor: '#3b82f6',
    fontFamily: 'Inter',
  },
];

<ImageEditor brands={brands} />
defaultTemplate
Template
Load a template on editor startup.
interface Template {
  id?: string;
  name?: string;
  sceneData: EditorItem[];
  width: number;
  height: number;
  thumbnail?: string;
  brandId?: string;
}

<ImageEditor defaultTemplate={myTemplate} />
onExport
(templateId: string, brandResults: any, updatedImage: string, thumbUri: string) => void
Advanced export callback with additional metadata.
const handleExport = (templateId, brandResults, updatedImage, thumbUri) => {
  console.log('Template ID:', templateId);
  console.log('Brand results:', brandResults);
  console.log('Image:', updatedImage);
  console.log('Thumbnail:', thumbUri);
};
onSaveTemplate
(props: { brandId: string; template: Template }) => Promise<void>
Callback when user saves a template.
const handleSaveTemplate = async ({ brandId, template }) => {
  await fetch('/api/templates', {
    method: 'POST',
    body: JSON.stringify({ brandId, template }),
  });
};
onGetTemplates
(brandIdList?: string[]) => Promise<{ success: { data: Template[] } }>
Callback to fetch templates for display.
const handleGetTemplates = async (brandIds) => {
  const response = await fetch('/api/templates?' + new URLSearchParams({
    brandIds: brandIds?.join(',') || ''
  }));
  return response.json();
};
createAutomatedContent
CreateAutomatedContent
AI-powered content creation function (advanced feature).

Complete Example

'use client';

import { useState, useCallback, useRef } from 'react';
import dynamic from 'next/dynamic';

const ImageEditor = dynamic(
  () => import('@distralabs/media-editor').then(mod => ({ default: mod.ImageEditor })),
  { ssr: false }
);

const customTheme = {
  'background.primary': '#0f172a',
  'background.secondary': '#1e293b',
  'text.primary': '#ffffff',
  'accent.primary': '#3b82f6',
};

export default function ImageStudioPage() {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [showEditor, setShowEditor] = useState(false);
  const [exportedImage, setExportedImage] = useState<string | null>(null);

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file && file.type.startsWith('image/')) {
      setSelectedFile(file);
      setShowEditor(true);
    }
  };

  const handleExport = useCallback((result: any) => {
    if (result.base64) {
      setExportedImage(result.base64);
      setShowEditor(false);

      // Download
      const link = document.createElement('a');
      link.href = result.base64;
      link.download = `edited-${Date.now()}.png`;
      link.click();
    }
  }, []);

  const handleClose = () => {
    setShowEditor(false);
    setSelectedFile(null);
  };

  return (
    <div className="min-h-screen p-6">
      {!showEditor && (
        <div>
          <h1 className="text-3xl font-bold mb-4">Image Studio</h1>
          <input
            ref={fileInputRef}
            type="file"
            accept="image/*"
            onChange={handleFileSelect}
            className="hidden"
          />
          <button
            onClick={() => fileInputRef.current?.click()}
            className="px-6 py-3 bg-blue-500 text-white rounded-lg"
          >
            Choose Image
          </button>
        </div>
      )}

      {showEditor && selectedFile && (
        <div className="fixed inset-0 z-50">
          <ImageEditor
            licenseKey={process.env.NEXT_PUBLIC_LICENSE_KEY || ''}
            apiUrl="https://localhost:3030/social"
            files={selectedFile}
            onClose={handleClose}
            callback={handleExport}
            theme={customTheme}
            showThemeCreator={false}
          />
        </div>
      )}
    </div>
  );
}

Features

Image Editing

  • Upload & Load: Support for JPG, PNG, GIF, WebP
  • Resize: Custom dimensions or preset aspect ratios
  • Crop: Freeform or ratio-locked cropping
  • Rotate: 90° increments or custom angles
  • Flip: Horizontal and vertical flipping

Effects & Filters

  • Color Filters: Grayscale, Sepia, Invert, Colorize
  • Adjustments: Brightness, Contrast, Saturation, Hue
  • Blur: Gaussian blur with adjustable radius
  • Artistic: Pixelate, Noise, Emboss, Posterize
  • Shadows: Drop shadows with offset, blur, color

Text

  • Rich Text: Multiple fonts, sizes, colors, weights
  • Google Fonts: Dynamic font loading
  • Formatting: Bold, italic, underline, alignment
  • Effects: Shadows, outlines, backgrounds

Shapes

  • Basic Shapes: Rectangle, Circle, Triangle, Star, Arrow
  • Customization: Fill color, stroke, stroke width
  • Advanced: Custom paths and SVG shapes

Layers

  • Multi-layer Support: Unlimited layers
  • Z-Index Control: Bring forward, send backward
  • Layer Management: Show/hide, lock, duplicate, delete

Background

  • Solid Colors: Any color picker
  • Gradients: Linear and radial gradients
  • Images: Background image with fit modes

Export

  • Formats: PNG, JPG, WebP
  • Quality: Adjustable compression
  • Dimensions: Original or custom size

Browser Support

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+
Mobile browsers have limited support. Desktop browsers recommended for best experience.

Next Steps