Image plugin for Plate rich text editor that enables embedding, uploading, and managing images with advanced features like drag-and-drop, resizing, and captions.
—
TypeScript interfaces and types for image elements and plugin configuration.
The core interface defining the structure of image elements in the Plate editor.
/**
* Image element interface extending Plate's base element type
* Represents an image node in the editor's document structure
*/
interface TImageElement extends TElement {
/** Image URL (can be data URL, blob URL, or remote URL) */
url: string;
/** Optional width for image sizing (CSS-compatible value) */
width?: number;
/** Optional caption content as descendant nodes */
caption?: TDescendant[];
}Usage Examples:
import { TImageElement } from "@udecode/plate-image";
// Create image element data
const imageElement: TImageElement = {
type: 'img',
url: 'https://example.com/image.jpg',
width: 400,
caption: [{ text: 'Sample image caption' }],
children: [{ text: '' }] // Required by TElement
};
// Type-safe access to image properties
function processImageElement(element: TImageElement) {
console.log(`Image URL: ${element.url}`);
if (element.width) {
console.log(`Width: ${element.width}px`);
}
if (element.caption) {
console.log(`Has caption with ${element.caption.length} nodes`);
}
}Interface defining the configuration options for the image plugin.
/**
* Configuration interface for the image plugin
* All properties are optional with sensible defaults
*/
interface ImagePlugin {
/**
* Custom image upload function
* Called when user pastes/drops image files
* @param dataUrl - Base64 data URL or ArrayBuffer of the image
* @returns Promise resolving to uploaded image URL or synchronous URL
*/
uploadImage?: (
dataUrl: string | ArrayBuffer
) => Promise<string | ArrayBuffer> | string | ArrayBuffer;
/**
* Disable automatic file upload on paste/drop operations
* When true, image files won't be processed automatically
* @default false
*/
disableUploadInsert?: boolean;
/**
* Disable automatic URL embedding when pasting image URLs
* When true, image URLs will be treated as regular text
* @default false
*/
disableEmbedInsert?: boolean;
}Usage Examples:
import { ImagePlugin } from "@udecode/plate-image";
// Minimal configuration
const basicConfig: ImagePlugin = {};
// Configuration with custom upload
const uploadConfig: ImagePlugin = {
uploadImage: async (dataUrl) => {
try {
const response = await fetch('/api/images', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ imageData: dataUrl })
});
const result = await response.json();
return result.imageUrl;
} catch (error) {
console.error('Upload failed:', error);
throw error;
}
}
};
// Configuration with disabled features
const restrictedConfig: ImagePlugin = {
disableUploadInsert: true, // No file uploads
disableEmbedInsert: false, // Still allow URL embedding
};
// Complete configuration example
const fullConfig: ImagePlugin = {
async uploadImage(dataUrl) {
// Handle both string and ArrayBuffer inputs
const imageData = typeof dataUrl === 'string' ? dataUrl : dataUrl;
// Custom upload logic with error handling
try {
const uploadResult = await uploadToCloudinary(imageData);
return uploadResult.secure_url;
} catch (error) {
// Fallback to data URL if upload fails
return dataUrl;
}
},
disableUploadInsert: false,
disableEmbedInsert: false,
};import { TImageElement, useImageElement } from "@udecode/plate-image";
import { setNodes, findNodePath } from "@udecode/plate-core";
// Hook usage in components
function MyImageComponent() {
const element = useImageElement(); // Returns TImageElement
// Type-safe property access
const imageUrl = element.url;
const imageWidth = element.width || '100%';
const hasCaption = element.caption && element.caption.length > 0;
return (
<img
src={imageUrl}
style={{ width: imageWidth }}
alt={hasCaption ? 'Image with caption' : 'Image'}
/>
);
}
// Programmatic element manipulation
function updateImageWidth(editor: PlateEditor, newWidth: number) {
const element = useImageElement();
const path = findNodePath(editor, element);
if (path) {
setNodes<TImageElement>(
editor,
{ width: newWidth },
{ at: path }
);
}
}import { createImagePlugin, ImagePlugin } from "@udecode/plate-image";
// Factory function for creating configured plugins
function createCustomImagePlugin(uploadEndpoint: string): ImagePlugin {
return {
uploadImage: async (dataUrl) => {
const response = await fetch(uploadEndpoint, {
method: 'POST',
body: JSON.stringify({ image: dataUrl }),
headers: { 'Content-Type': 'application/json' }
});
return response.json().then(data => data.url);
}
};
}
// Conditional configuration
function createImagePluginForEnvironment(isDevelopment: boolean): ImagePlugin {
if (isDevelopment) {
return {
// In development, just use data URLs
uploadImage: (dataUrl) => Promise.resolve(dataUrl)
};
}
return {
uploadImage: async (dataUrl) => {
// Production upload logic
return await uploadToProduction(dataUrl);
}
};
}Install with Tessl CLI
npx tessl i tessl/npm-udecode--plate-image