Comprehensive media handling capabilities for the Plate rich text editor framework, supporting images, videos, audio files, and embeddable content
—
React integration providing UI components, hooks, and state management for media interactions. Includes plugin wrappers, specialized components for media control, and comprehensive state management systems.
React-wrapped versions of the base plugins with enhanced UI integration.
/**
* React-wrapped image plugin with UI components and hooks
*/
const ImagePlugin: TPlatePlugin<ImageConfig>;
/**
* React-wrapped media embed plugin with UI integration
*/
const MediaEmbedPlugin: TPlatePlugin<MediaEmbedConfig>;
/**
* React-wrapped audio plugin
*/
const AudioPlugin: TPlatePlugin<AudioConfig>;
/**
* React-wrapped file plugin
*/
const FilePlugin: TPlatePlugin<FileConfig>;
/**
* React-wrapped video plugin
*/
const VideoPlugin: TPlatePlugin<VideoConfig>;Usage Example:
import {
ImagePlugin,
MediaEmbedPlugin,
AudioPlugin
} from "@udecode/plate-media/react";
import { createPlateEditor } from "@udecode/plate";
const editor = createPlateEditor({
plugins: [
ImagePlugin.configure({
options: {
uploadImage: async (file) => {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
return data.url;
}
}
}),
MediaEmbedPlugin,
AudioPlugin,
VideoPlugin,
FilePlugin
]
});Comprehensive state management for media elements with React integration.
Global state management for media element visibility and captions.
/**
* Atom store for media state management
*/
interface MediaStore {
/** Whether captions are visible */
showCaption: boolean;
}
/**
* Provider component for media store context
*/
const MediaProvider: React.ComponentType<{ children: React.ReactNode }>;
/**
* Hook to access the entire media store
*/
function useMediaStore(): MediaStore;
/**
* Hook to access specific media store values
*/
function useMediaValue<T>(selector: (store: MediaStore) => T): T;
/**
* Hook to update media store values
*/
function useMediaSet(): (updates: Partial<MediaStore>) => void;Usage Example:
import {
MediaProvider,
useMediaValue,
useMediaSet
} from "@udecode/plate-media/react";
const MediaApp = () => {
return (
<MediaProvider>
<MediaControls />
<MediaContent />
</MediaProvider>
);
};
const MediaControls = () => {
const showCaption = useMediaValue(store => store.showCaption);
const setMediaState = useMediaSet();
return (
<button
onClick={() => setMediaState({ showCaption: !showCaption })}
>
{showCaption ? 'Hide' : 'Show'} Captions
</button>
);
};Comprehensive state hook for individual media elements.
/**
* Provides comprehensive media element state including embed data and provider info
* @param options - Configuration with URL parsers
* @returns Complete media element state
*/
function useMediaState(options?: {
urlParsers?: EmbedUrlParser[]
}): MediaStateResult;
interface MediaStateResult {
// Element properties
id: string;
url: string;
align: string;
focused: boolean;
selected: boolean;
// Parsed embed data
embed: EmbedUrlData | null;
// Provider detection
isTweet: boolean;
isVideo: boolean;
isYoutube: boolean;
isVimeo: boolean;
// UI state
caption: string;
showCaption: boolean;
// Dimensions
width: number;
height: number;
aspectRatio: number;
}Usage Example:
import {
useMediaState,
parseVideoUrl,
parseTwitterUrl
} from "@udecode/plate-media/react";
const MediaElement = () => {
const mediaState = useMediaState({
urlParsers: [parseVideoUrl, parseTwitterUrl]
});
return (
<div className={`media-element ${mediaState.focused ? 'focused' : ''}`}>
{mediaState.isYoutube && (
<div>YouTube Video: {mediaState.embed?.id}</div>
)}
{mediaState.isTweet && (
<div>Tweet ID: {mediaState.embed?.id}</div>
)}
{mediaState.showCaption && (
<div className="caption">{mediaState.caption}</div>
)}
<div>
Dimensions: {mediaState.width}x{mediaState.height}
(Aspect Ratio: {mediaState.aspectRatio})
</div>
</div>
);
};UI components for controlling media elements with dropdown menus and toolbars.
State management for media control dropdowns and interactions.
/**
* Provides media control dropdown state management
* @returns Controller state and handlers
*/
function useMediaController(): {
isOpen: boolean;
open: () => void;
close: () => void;
toggle: () => void;
};
/**
* Controller state management hook
* @returns Detailed controller state
*/
function useMediaControllerState(): {
activeId: string | null;
isOpen: boolean;
setActiveId: (id: string | null) => void;
};
/**
* Dropdown menu state for media controller
* @returns Menu state and handlers
*/
function useMediaControllerDropDownMenu(): {
isOpen: boolean;
onOpenChange: (open: boolean) => void;
};Toolbar integration for media insertion buttons.
/**
* Provides toolbar button props for media insertion
* @param options - Configuration options
* @returns Button props and handlers
*/
function useMediaToolbarButton(options?: {
nodeType?: string
}): {
pressed: boolean;
onClick: () => void;
disabled: boolean;
};Usage Example:
import {
useMediaToolbarButton,
useMediaController
} from "@udecode/plate-media/react";
const MediaToolbar = () => {
const imageButton = useMediaToolbarButton({ nodeType: 'image' });
const videoButton = useMediaToolbarButton({ nodeType: 'video' });
const controller = useMediaController();
return (
<div className="media-toolbar">
<button
{...imageButton}
className={imageButton.pressed ? 'active' : ''}
>
Insert Image
</button>
<button
{...videoButton}
className={videoButton.pressed ? 'active' : ''}
>
Insert Video
</button>
<div className="media-controller">
<button onClick={controller.toggle}>
Media Options
</button>
{controller.isOpen && (
<div className="dropdown">
<button onClick={() => {/* handle action */}}>
Edit Media
</button>
<button onClick={() => {/* handle action */}}>
Remove Media
</button>
</div>
)}
</div>
</div>
);
};Floating UI components for in-place media editing with URL input and validation.
State management for floating media editing operations.
/**
* Zustand store for floating media editing state
*/
interface FloatingMediaStore {
/** Whether editing mode is active */
isEditing: boolean;
/** Current URL being edited */
url: string;
/** Reset editing state */
reset(): void;
}
/**
* Hook to access floating media state
*/
function useFloatingMediaState(): FloatingMediaStore;
/**
* Hook to access floating media values
*/
function useFloatingMediaValue<T>(
selector: (store: FloatingMediaStore) => T
): T;React components for floating media editing interface.
/**
* Container component with edit button and URL input
*/
const FloatingMedia: {
EditButton: React.ComponentType;
UrlInput: React.ComponentType;
};
/**
* Primitive edit button component
* Sets store to editing mode when clicked
*/
const FloatingMediaEditButton: React.ComponentType;
/**
* Primitive URL input component with validation
* Handles auto-focus and keyboard interactions
*/
const FloatingMediaUrlInput: React.ComponentType;Specialized hooks for floating media functionality.
/**
* Hook for edit button functionality
* @returns Click handler that activates editing mode
*/
function useFloatingMediaEditButton(): {
onClick: () => void;
};
/**
* Hook for URL input state management
* @param options - Configuration options
* @returns Keyboard handling and state management
*/
function useFloatingMediaUrlInputState(options: {
plugin: any
}): {
onKeyDown: (event: KeyboardEvent) => void;
onEscape: () => void;
onEnter: () => void;
};
/**
* Hook for URL input props
* @param options - Configuration options
* @returns Input props and handlers
*/
function useFloatingMediaUrlInput(options: {
defaultValue?: string
}): {
value: string;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
onBlur: () => void;
autoFocus: boolean;
};Utility functions for floating media operations.
/**
* Validates and updates media element URL
* @param editor - Slate editor instance
* @param options - Element and plugin configuration
* @returns Success status
*/
function submitFloatingMedia(
editor: SlateEditor,
options: {
element: TMediaElement;
plugin: any
}
): boolean;Usage Example:
import {
FloatingMedia,
useFloatingMediaState,
submitFloatingMedia,
useFloatingMediaUrlInput
} from "@udecode/plate-media/react";
const FloatingMediaEditor = ({ element, plugin }) => {
const { isEditing } = useFloatingMediaState();
const urlInput = useFloatingMediaUrlInput({
defaultValue: element.url
});
const handleSubmit = () => {
const success = submitFloatingMedia(editor, { element, plugin });
if (success) {
// Handle successful update
}
};
return (
<div className="floating-media">
{!isEditing ? (
<FloatingMedia.EditButton />
) : (
<div className="url-editor">
<input
{...urlInput}
placeholder="Enter media URL..."
/>
<button onClick={handleSubmit}>
Update
</button>
</div>
)}
</div>
);
};
// Using the compound component approach
const SimpleFloatingMedia = () => (
<FloatingMedia>
<FloatingMedia.EditButton />
<FloatingMedia.UrlInput />
</FloatingMedia>
);Advanced image preview system with React components and state management.
/**
* Hook to access ImagePreviewStore values
* @returns Current preview store state
*/
function useImagePreviewValue(): ImagePreviewStoreState;/**
* Opens image preview overlay for the specified image element
* @param editor - Slate editor instance
* @param element - Media element to preview
*/
function openImagePreview(editor: SlateEditor, element: TMediaElement): void;Specialized React components for image rendering and preview functionality.
/**
* Primitive image component with drag and preview functionality
* Provides double-click to open preview and draggable behavior
*/
const Image: React.ComponentType;
/**
* Hook providing image component props and handlers
* @returns Props for image element including drag and preview handlers
*/
function useImage(): {
onDoubleClick: () => void;
draggable: boolean;
onDragStart: (event: DragEvent) => void;
};
/**
* Primitive component for preview overlay image
* Handles click-to-zoom and transform styles
*/
const PreviewImage: React.ComponentType;
/**
* Hook providing preview image props with zoom and transform functionality
* @returns Props for preview image including click handlers and styles
*/
function usePreviewImage(): {
onClick: () => void;
style: CSSProperties;
cursor: string;
};Complete React Integration Example:
import {
ImagePlugin,
MediaEmbedPlugin,
PlaceholderPlugin,
MediaProvider,
useMediaState,
useImagePreview,
openImagePreview,
Image,
PreviewImage
} from "@udecode/plate-media/react";
const MediaRichEditor = () => {
const editor = createPlateEditor({
plugins: [
ImagePlugin.configure({
options: {
uploadImage: async (file) => {
// Upload implementation
return await uploadToServer(file);
}
}
}),
MediaEmbedPlugin,
PlaceholderPlugin.configure({
options: {
uploadConfig: {
image: { mediaType: 'image', maxFileSize: '5MB' },
video: { mediaType: 'video', maxFileSize: '50MB' }
}
}
})
]
});
return (
<MediaProvider>
<PlateProvider editor={editor}>
<Plate>
<PlateContent />
<ImagePreviewOverlay />
</Plate>
</PlateProvider>
</MediaProvider>
);
};
const ImagePreviewOverlay = () => {
const previewControls = useImagePreview({ scrollSpeed: 0.1 });
return (
<div
className="image-preview-overlay"
onKeyDown={previewControls.onKeyDown}
onWheel={previewControls.onWheel}
tabIndex={0}
>
<PreviewImage />
<div className="preview-controls">
<button onClick={previewControls.zoomIn}>
Zoom In
</button>
<button onClick={previewControls.zoomOut}>
Zoom Out
</button>
<button onClick={previewControls.goPrevious}>
Previous
</button>
<button onClick={previewControls.goNext}>
Next
</button>
</div>
</div>
);
};This React integration provides a complete media handling solution with:
Install with Tessl CLI
npx tessl i tessl/npm-udecode--plate-media