CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-udecode--plate-media

Comprehensive media handling capabilities for the Plate rich text editor framework, supporting images, videos, audio files, and embeddable content

Pending
Overview
Eval results
Files

react-components.mddocs/

React Components

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.

Capabilities

React Plugin Wrappers

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
  ]
});

Media State Management

Comprehensive state management for media elements with React integration.

Media Store

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>
  );
};

Media Element State

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>
  );
};

Media Controller Components

UI components for controlling media elements with dropdown menus and toolbars.

Media Controller

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;
};

Media Toolbar Button

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 Media Components

Floating UI components for in-place media editing with URL input and validation.

Floating Media Store

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;

Floating Media Components

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;

Floating Media Hooks

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;
};

Floating Media Functions

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>
);

Image Preview System (React)

Advanced image preview system with React components and state management.

Image Preview Access

/**
 * Hook to access ImagePreviewStore values
 * @returns Current preview store state
 */
function useImagePreviewValue(): ImagePreviewStoreState;

Image Preview Functions

/**
 * 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;

Image Components (React)

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:

  1. Plugin Integration: Seamless integration with Plate editor plugins
  2. State Management: Comprehensive state management with Zustand and Atom stores
  3. UI Components: Pre-built components for common media interactions
  4. Upload System: Advanced file upload with validation and progress tracking
  5. Preview System: Full-featured image preview with zoom and navigation
  6. Floating Editors: In-place editing capabilities for media URLs
  7. Toolbar Integration: Ready-to-use toolbar buttons and controls

Install with Tessl CLI

npx tessl i tessl/npm-udecode--plate-media

docs

base-plugins.md

image.md

index.md

media-embeds.md

react-components.md

upload-system.md

tile.json