Image plugin for Plate rich text editor that enables embedding, uploading, and managing images with advanced features like drag-and-drop, resizing, and captions.
—
React hooks for accessing image element data, managing captions, and integrating with the image store system.
Hook to access the current image element data within image component contexts.
/**
* Hook to get the current image element data
* Must be used within an image element component context
* @returns Current TImageElement with url, width, and caption properties
*/
function useImageElement(): TImageElement;Usage Examples:
import { useImageElement, TImageElement } from "@udecode/plate-image";
// Access image properties in component
function MyImageComponent() {
const element = useImageElement();
return (
<div>
<img src={element.url} style={{ width: element.width }} />
{element.caption && (
<figcaption>
Caption has {element.caption.length} nodes
</figcaption>
)}
</div>
);
}
// Conditional rendering based on image properties
function ConditionalImageRenderer() {
const element = useImageElement();
const hasCaption = element.caption && element.caption.length > 0;
const hasWidth = element.width && element.width > 0;
return (
<figure className={`image ${hasCaption ? 'with-caption' : ''}`}>
<img
src={element.url}
style={{
width: hasWidth ? `${element.width}px` : '100%',
maxWidth: '100%'
}}
draggable={true}
/>
{hasCaption && (
<figcaption>Image has caption content</figcaption>
)}
</figure>
);
}Hook to extract and memoize the caption text as a plain string from the image element.
/**
* Hook to get image caption as a plain string
* Extracts text content from caption descendant nodes and memoizes the result
* @returns String representation of the caption content (empty string if no caption)
*/
function useImageCaptionString(): string;Usage Examples:
import { useImageCaptionString } from "@udecode/plate-image";
// Use caption string for alt text
function AccessibleImage() {
const captionString = useImageCaptionString();
const element = useImageElement();
return (
<img
src={element.url}
alt={captionString || 'Image'}
title={captionString}
/>
);
}
// Conditional rendering based on caption content
function CaptionDisplay() {
const captionString = useImageCaptionString();
if (!captionString.length) {
return <div className="no-caption">No caption available</div>;
}
return (
<figcaption className="image-caption">
{captionString}
<span className="caption-length">({captionString.length} characters)</span>
</figcaption>
);
}
// Search and filtering based on caption content
function SearchableImageList({ searchTerm }: { searchTerm: string }) {
const captionString = useImageCaptionString();
const matchesSearch = captionString.toLowerCase().includes(
searchTerm.toLowerCase()
);
if (!matchesSearch) return null;
return (
<div className="search-result">
<Image.Img />
<div className="caption-match">
Caption: "{captionString}"
</div>
</div>
);
}Atom store for managing image-specific state like width during resize operations.
/**
* Atom store for image-specific state management
* Manages width property for individual image elements
*/
const imageStore: {
get: {
width(): CSSProperties['width'];
};
set: {
width(value: CSSProperties['width']): void;
};
};
/**
* Hook to access imageStore state
* Provides reactive access to image store properties
*/
function useImageStore(): {
get: {
width(): CSSProperties['width'];
};
set: {
width(value: CSSProperties['width']): void;
};
use: {
width(): [CSSProperties['width'], (value: CSSProperties['width']) => void];
};
};Usage Examples:
import { useImageStore } from "@udecode/plate-image";
// Access current width in resize component
function ResizeDisplayComponent() {
const imageStore = useImageStore();
const [width, setWidth] = imageStore.use.width();
return (
<div>
<div>Current width: {width}</div>
<button onClick={() => setWidth(300)}>
Set width to 300px
</button>
</div>
);
}
// Monitor width changes during resize
function ResizeMonitor() {
const imageStore = useImageStore();
const width = imageStore.get.width();
React.useEffect(() => {
console.log('Image width changed:', width);
}, [width]);
return <div>Width: {width}</div>;
}Global store for managing cross-image state like caption focus coordination.
/**
* Global store for cross-image state management
* Coordinates focus states across different image elements
*/
const imageGlobalStore: {
get: {
focusEndCaptionPath(): TPath | null;
focusStartCaptionPath(): TPath | null;
};
set: {
focusEndCaptionPath(path: TPath | null): void;
focusStartCaptionPath(path: TPath | null): void;
};
use: {
focusEndCaptionPath(): TPath | null;
focusStartCaptionPath(): TPath | null;
};
};Focus Management:
focusEndCaptionPath: Triggers focus to end of caption textarea for specified image pathfocusStartCaptionPath: Triggers focus to start of caption textarea for specified image pathUsage Examples:
import { imageGlobalStore } from "@udecode/plate-image";
import { findNodePath } from "@udecode/plate-core";
// Programmatically focus image caption
function FocusImageCaption() {
const element = useImageElement();
const editor = useEditorRef();
const focusCaption = () => {
const path = findNodePath(editor, element);
if (path) {
imageGlobalStore.set.focusEndCaptionPath(path);
}
};
return (
<button onClick={focusCaption}>
Focus Image Caption
</button>
);
}
// Monitor focus state changes
function FocusStateMonitor() {
const focusPath = imageGlobalStore.use.focusEndCaptionPath();
return (
<div>
{focusPath ? (
<div>Caption focus requested for path: {focusPath.join('.')}</div>
) : (
<div>No caption focus pending</div>
)}
</div>
);
}import {
useImageElement,
useImageCaptionString,
useImageStore
} from "@udecode/plate-image";
function CustomImageComponent() {
// Access image data
const element = useImageElement();
const captionString = useImageCaptionString();
const imageStore = useImageStore();
// Local state for interaction
const [isHovered, setIsHovered] = React.useState(false);
const [width] = imageStore.use.width();
return (
<figure
className="custom-image"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<img
src={element.url}
alt={captionString}
style={{
width: width || element.width || '100%',
opacity: isHovered ? 0.9 : 1,
transition: 'opacity 0.2s'
}}
/>
{captionString && (
<figcaption style={{ fontStyle: 'italic' }}>
{captionString}
</figcaption>
)}
{isHovered && (
<div className="image-info">
Dimensions: {width || element.width || 'auto'}
</div>
)}
</figure>
);
}// Custom hook combining multiple image hooks
function useImageInfo() {
const element = useImageElement();
const captionString = useImageCaptionString();
const imageStore = useImageStore();
return {
url: element.url,
width: element.width,
hasCaption: captionString.length > 0,
captionText: captionString,
storeWidth: imageStore.get.width(),
updateWidth: imageStore.set.width,
};
}
// Usage of custom hook
function ImageInfoDisplay() {
const info = useImageInfo();
return (
<div className="image-info">
<div>URL: {info.url}</div>
<div>Width: {info.width || 'auto'}</div>
<div>Store Width: {info.storeWidth}</div>
<div>Has Caption: {info.hasCaption ? 'Yes' : 'No'}</div>
{info.hasCaption && (
<div>Caption: "{info.captionText}"</div>
)}
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-udecode--plate-image