šŸ“ Sign Up | šŸ” Log In

← Root | ↑ Up

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ šŸ“„ shadcn/directory/udecode/plate/(plugins)/(elements)/media │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

╔══════════════════════════════════════════════════════════════════════════════════════════════╗
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘

title: Media docs:

  • route: https://pro.platejs.org/docs/examples/media title: Plus
  • route: /docs/components/media-image-node title: Image Element
  • route: /docs/components/media-video-node title: Video Element
  • route: /docs/components/media-audio-node title: Audio Element
  • route: /docs/components/media-file-node title: File Element
  • route: /docs/components/media-embed-node title: Media Embed Element
  • route: /docs/components/media-toolbar title: Media Popover
  • route: /docs/components/media-placeholder-node title: Media Placeholder Element
  • route: /docs/components/media-upload-toast title: Media Upload Toast
  • route: /docs/components/media-toolbar-button title: Media Toolbar Button

<ComponentPreview name="media-demo" /> <PackageInfo>

Features

Media Support

  • File types:
    • Image
    • Video
    • Audio
    • Others (PDF, Word, etc.)
  • Video providers:
    • Local video files
    • YouTube, Vimeo, Dailymotion, Youku, Coub
  • Embed providers:
    • Tweets

Media Features

  • Editable captions
  • Resizable elements

Upload

  • Multiple upload methods:
    • Toolbar button with file picker
    • Drag and drop from file system
    • Paste from clipboard (images)
    • URL embedding for external media
  • Upload experience:
    • Real-time progress tracking
    • Preview during upload
    • Automatically converts the placeholder to the appropriate media element (image, video, audio, file) once the upload or embed is submitted
    • Error handling
    • File size validation
    • Type validation
</PackageInfo>

Kit Usage

<Steps>

Installation

The fastest way to add comprehensive media support is with the MediaKit, which includes pre-configured ImagePlugin, VideoPlugin, AudioPlugin, FilePlugin, MediaEmbedPlugin, PlaceholderPlugin, and CaptionPlugin with their Plate UI components.

<ComponentSource name="media-kit" />

Add Kit

Add the kit to your plugins:

import { createPlateEditor } from 'platejs/react';
import { MediaKit } from '@/components/editor/plugins/media-kit';

const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    ...MediaKit,
  ],
});

Add API Routes

<ComponentInstallation name="media-uploadthing-api" inline />

Environment Setup

Get your secret key from UploadThing and add it to .env:

UPLOADTHING_TOKEN=xxx
</Steps>

Manual Usage

<Steps>

Installation

npm install @platejs/media

Add Plugins

Include the media plugins in your Plate plugins array when creating the editor.

import {
  AudioPlugin,
  FilePlugin,
  ImagePlugin,
  MediaEmbedPlugin,
  PlaceholderPlugin,
  VideoPlugin,
} from '@platejs/media/react';
import { createPlateEditor } from 'platejs/react';

const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    ImagePlugin,
    VideoPlugin,
    AudioPlugin,
    FilePlugin,
    MediaEmbedPlugin,
    PlaceholderPlugin,
  ],
});

Configure Plugins

Configure the plugins with custom components and upload settings.

import {
  AudioPlugin,
  FilePlugin,
  ImagePlugin,
  MediaEmbedPlugin,
  PlaceholderPlugin,
  VideoPlugin,
} from '@platejs/media/react';
import { KEYS } from 'platejs';
import { createPlateEditor } from 'platejs/react';
import { 
  AudioElement, 
  FileElement, 
  ImageElement, 
  MediaEmbedElement, 
  PlaceholderElement, 
  VideoElement 
} from '@/components/ui/media-nodes';
import { MediaUploadToast } from '@/components/ui/media-upload-toast';

const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    ImagePlugin.withComponent(ImageElement),
    VideoPlugin.withComponent(VideoElement),
    AudioPlugin.withComponent(AudioElement),
    FilePlugin.withComponent(FileElement),
    MediaEmbedPlugin.withComponent(MediaEmbedElement),
    PlaceholderPlugin.configure({
      options: { disableEmptyPlaceholder: true },
      render: { afterEditable: MediaUploadToast, node: PlaceholderElement },
    }),
  ],
});
  • withComponent: Assigns custom components to render each media type.
  • options.disableEmptyPlaceholder: Prevents showing placeholder when no file is uploading.
  • render.afterEditable: Renders upload progress toast outside the editor.

Caption Support

To enable media captions, add the Caption Plugin:

import { CaptionPlugin } from '@platejs/caption/react';

const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    // ...media plugins,
    CaptionPlugin.configure({
      options: {
        query: {
          allow: [KEYS.img, KEYS.video, KEYS.audio, KEYS.file, KEYS.mediaEmbed],
        },
      },
    }),
  ],
});

Custom Upload Implementation

For custom upload implementations, create an upload hook that matches this interface:

interface UseUploadFileProps {
  onUploadComplete?: (file: UploadedFile) => void;
  onUploadError?: (error: unknown) => void;
  headers?: Record<string, string>;
  onUploadBegin?: (fileName: string) => void;
  onUploadProgress?: (progress: { progress: number }) => void;
  skipPolling?: boolean;
}

interface UploadedFile {
  key: string;    // Unique identifier
  url: string;    // Public URL of the uploaded file
  name: string;   // Original filename
  size: number;   // File size in bytes
  type: string;   // MIME type
}

Example implementation with S3 presigned URLs:

export function useUploadFile({ 
  onUploadComplete, 
  onUploadError, 
  onUploadProgress 
}: UseUploadFileProps = {}) {
  const [uploadedFile, setUploadedFile] = useState<UploadedFile>();
  const [uploadingFile, setUploadingFile] = useState<File>();
  const [progress, setProgress] = useState(0);
  const [isUploading, setIsUploading] = useState(false);

  async function uploadFile(file: File) {
    setIsUploading(true);
    setUploadingFile(file);

    try {
      // Get presigned URL and final URL from your backend
      const { presignedUrl, fileUrl, fileKey } = await fetch('/api/upload', {
        method: 'POST',
        body: JSON.stringify({
          filename: file.name,
          contentType: file.type,
        }),
      }).then(r => r.json());

      // Upload to S3 using presigned URL
      await axios.put(presignedUrl, file, {
        headers: { 'Content-Type': file.type },
        onUploadProgress: (progressEvent) => {
          const progress = (progressEvent.loaded / progressEvent.total) * 100;
          setProgress(progress);
          onUploadProgress?.({ progress });
        },
      });

      const uploadedFile = {
        key: fileKey,
        url: fileUrl,
        name: file.name,
        size: file.size,
        type: file.type,
      };

      setUploadedFile(uploadedFile);
      onUploadComplete?.(uploadedFile);
      
      return uploadedFile;
    } catch (error) {
      onUploadError?.(error);
      throw error;
    } finally {
      setProgress(0);
      setIsUploading(false);
      setUploadingFile(undefined);
    }
  }

  return {
    isUploading,
    progress,
    uploadFile,
    uploadedFile,
    uploadingFile,
  };
}

Then integrate your custom upload hook with the media components:

import { useUploadFile } from '@/hooks/use-upload-file'; // Your custom hook

// In your PlaceholderElement component
export function PlaceholderElement({ className, children, element, ...props }) {
  const { uploadFile, isUploading, progress } = useUploadFile({
    onUploadComplete: (uploadedFile) => {
      // Replace placeholder with actual media element
      const { url, type } = uploadedFile;
      
      // Transform placeholder to appropriate media type
      editor.tf.replace.placeholder({
        id: element.id,
        url,
        type: getMediaType(type), // image, video, audio, file
      });
    },
    onUploadError: (error) => {
      console.error('Upload failed:', error);
      // Handle upload error, maybe show toast
    },
  });

  // Use uploadFile when files are dropped or selected
  // This integrates with the PlaceholderPlugin's file handling
}

Add Toolbar Button

You can add MediaToolbarButton to your Toolbar to upload and insert media.

Insert Toolbar Button

You can add these items to the Insert Toolbar Button to insert media elements:

{
  icon: <ImageIcon />,
  label: 'Image',
  value: KEYS.img,
}
</Steps>

Plate Plus

<ComponentPreviewPro name="media-pro" />

Plugins

ImagePlugin

Plugin for void image elements.

<API name="ImagePlugin"> <APIOptions type="ImagePluginOptions"> <APIItem name="uploadImage" type="(dataUrl: string | ArrayBuffer) => Promise<string | ArrayBuffer> | string | ArrayBuffer" optional> Function to upload image to a server. Receives: - Data URL (string) from `FileReader.readAsDataURL` - ArrayBuffer from clipboard data Returns: - URL string to uploaded image - Original data URL/ArrayBuffer if no upload needed - **Default:** Returns original input </APIItem> <APIItem name="disableUploadInsert" type="boolean" optional> Disables file upload on data insertion. - **Default:** `false` </APIItem> <APIItem name="disableEmbedInsert" type="boolean" optional> Disables URL embed on data insertion. - **Default:** `false` </APIItem> <APIItem name="isUrl" type="function" optional> A function to check whether a text string is a URL. </APIItem> <APIItem name="transformUrl" type="function" optional> A function to transform the URL. </APIItem> </APIOptions> </API>

VideoPlugin

Plugin for void video elements. Extends MediaPluginOptions.

AudioPlugin

Plugin for void audio elements. Extends MediaPluginOptions.

FilePlugin

Plugin for void file elements. Extends MediaPluginOptions.

MediaEmbedPlugin

Plugin for void media embed elements. Extends MediaPluginOptions.

PlaceholderPlugin

Plugin for managing media placeholders during upload. Handles file uploads, drag & drop, and clipboard paste events.

<API name="PlaceholderPlugin"> <APIOptions type="object"> <APIItem name="uploadConfig" type="Partial<Record<AllowedFileType, MediaItemConfig>>" optional> Configuration for different file types. Default configuration: ```ts { audio: { maxFileCount: 1, maxFileSize: '8MB', mediaType: KEYS.audio, minFileCount: 1, }, blob: { maxFileCount: 1, maxFileSize: '8MB', mediaType: KEYS.file, minFileCount: 1, }, image: { maxFileCount: 3, maxFileSize: '4MB', mediaType: KEYS.image, minFileCount: 1, }, pdf: { maxFileCount: 1, maxFileSize: '4MB', mediaType: KEYS.file, minFileCount: 1, }, text: { maxFileCount: 1, maxFileSize: '64KB', mediaType: KEYS.file, minFileCount: 1, }, video: { maxFileCount: 1, maxFileSize: '16MB', mediaType: KEYS.video, minFileCount: 1, }, } ``` Supported file types: `'image' | 'video' | 'audio' | 'pdf' | 'text' | 'blob'` <APISubList> <APISubListItem parent="uploadConfig" name="mediaType" type="MediaKeys"> The media plugin keys that this config is for: `'audio' | 'file' | 'image' | 'video'` </APISubListItem> <APISubListItem parent="uploadConfig" name="maxFileCount" type="number" optional> The maximum number of files of this type that can be uploaded. </APISubListItem> <APISubListItem parent="uploadConfig" name="maxFileSize" type="FileSize" optional> The maximum file size for a file of this type. Format: `${1|2|4|8|16|32|64|128|256|512|1024}${B|KB|MB|GB}` </APISubListItem> <APISubListItem parent="uploadConfig" name="minFileCount" type="number" optional> The minimum number of files of this type that must be uploaded. </APISubListItem> </APISubList> </APIItem> <APIItem name="disableEmptyPlaceholder" type="boolean" optional> Disable empty placeholder when no file is uploading. - **Default:** `false` </APIItem> <APIItem name="disableFileDrop" type="boolean" optional> Disable drag and drop file upload functionality. - **Default:** `false` </APIItem> <APIItem name="maxFileCount" type="number" optional> Maximum number of files that can be uploaded at once, if not specified by `uploadConfig`. - **Default:** `5` </APIItem> <APIItem name="multiple" type="boolean" optional> Allow multiple files of the same type to be uploaded. - **Default:** `true` </APIItem> </APIOptions> </API>

API

api.placeholder.addUploadingFile

Tracks a file that is currently being uploaded.

<API name="addUploadingFile"> <APIParameters> <APIItem name="id" type="string"> Unique identifier for the placeholder element. </APIItem> <APIItem name="file" type="File"> The file being uploaded. </APIItem> </APIParameters> </API>

api.placeholder.getUploadingFile

Gets a file that is currently being uploaded.

<API name="getUploadingFile"> <APIParameters> <APIItem name="id" type="string"> Unique identifier for the placeholder element. </APIItem> </APIParameters> <APIReturns> <APIItem type="File | undefined"> The uploading file if found, undefined otherwise. </APIItem> </APIReturns> </API>

api.placeholder.removeUploadingFile

Removes a file from the uploading tracking state after upload completes or fails.

<API name="removeUploadingFile"> <APIParameters> <APIItem name="id" type="string"> Unique identifier for the placeholder element to remove. </APIItem> </APIParameters> </API>

Transforms

tf.insert.media

Inserts media files into the editor with upload placeholders.

<API name="insertMedia"> <APIParameters> <APIItem name="files" type="FileList"> Files to upload. Validates against configured file types and limits. </APIItem> <APIItem name="options" type="object" optional> Options for the insert nodes transform. </APIItem> </APIParameters> <APIOptions type="object"> <APIItem name="at" type="Path" optional> Location to insert the media. Defaults to current selection. </APIItem> <APIItem name="nextBlock" type="boolean" optional> Whether to insert a new block after the media. - **Default:** `true` </APIItem> </APIOptions> </API>

Validates files against configured limits (size, count, type), creates placeholder elements for each file, handles multiple file uploads sequentially, maintains upload history for undo/redo operations, and triggers error handling if validation fails.

Error codes:

enum UploadErrorCode {
  INVALID_FILE_TYPE = 400,
  TOO_MANY_FILES = 402,
  INVALID_FILE_SIZE = 403,
  TOO_LESS_FILES = 405,
  TOO_LARGE = 413,
}

tf.insert.imagePlaceholder

Inserts a placeholder that converts to an image element when completed.

tf.insert.videoPlaceholder

Inserts a placeholder that converts to a video element when completed.

tf.insert.audioPlaceholder

Inserts a placeholder that converts to an audio element when completed.

tf.insert.filePlaceholder

Inserts a placeholder that converts to a file element when completed.

tf.insert.image

Inserts an image element into the editor.

<API name="insertImage"> <APIParameters> <APIItem name="url" type="string | ArrayBuffer"> The URL or ArrayBuffer of the image. </APIItem> <APIItem name="options" type="InsertNodesOptions" optional> Additional options for inserting the image element. </APIItem> </APIParameters> <APIOptions type="InsertImageOptions"> <APIItem name="nextBlock" type="boolean" optional> If true, the image will be inserted in the next block. </APIItem> </APIOptions> </API>

tf.insert.mediaEmbed

Inserts a media embed element at the current selection.

<API name="insertMediaEmbed"> <APIOptions type="InsertMediaEmbedOptions"> <APIItem name="url" type="string" optional> The URL of the media embed. - **Default:** `''` </APIItem> <APIItem name="key" type="string" optional> The key of the media embed element. - **Default:** `KEYS.mediaEmbed` </APIItem> <APIItem name="insertNodesOptions" type="InsertNodesOptions" optional> Additional options for inserting nodes. </APIItem> </APIOptions> </API>

Hooks

useResizable

Handles the resizable properties of a media element.

<API name="useResizable"> <APIState> <APIItem name="align" type="'left' | 'center' | 'right'"> The alignment of the content within the resizable element. </APIItem> <APIItem name="minWidth" type="ResizeLength"> The minimum width that the resizable element can be adjusted to. </APIItem> <APIItem name="maxWidth" type="ResizeLength"> The maximum width that the resizable element can be adjusted to. </APIItem> <APIItem name="setNodeWidth" type="(width: number | string) => void"> Function to set the width of the node when resizing. </APIItem> <APIItem name="setWidth" type="(width: number | string) => void"> Function to set the width of the resizable element directly. </APIItem> <APIItem name="width" type="Property.Width<string | number> | undefined"> The current width of the resizable element (percentage, 'auto', or pixels). </APIItem> </APIState> <APIReturns type="object"> <APIItem name="wrapperRef" type="React.RefObject<HTMLDivElement>"> React reference to the outermost wrapper div. </APIItem> <APIItem name="wrapperProps.style" type="CSSProperties"> CSS styles for the wrapper div. </APIItem> <APIItem name="props.style" type="CSSProperties"> CSS styles for the resizable element. </APIItem> <APIItem name="context.onResize" type="() => void"> Callback function called when the element is resized. </APIItem> </APIReturns> </API>

useMediaState

A state hook for a media element.

<API name="useMediaState"> <APIParameters> <APIItem name="options.urlParsers" type="EmbedUrlParser[]" optional> Array of URL parsers to parse the media element URL.
- **`EmbedUrlParser`:** `(url: string) => EmbedUrlData | undefined`
</APIItem> </APIParameters> <APIReturns type="object"> <APIItem name="align" type="string"> The alignment of the media element. </APIItem> <APIItem name="focus" type="boolean"> Whether the media element is currently focused. </APIItem> <APIItem name="selected" type="boolean"> Whether the media element is currently selected. </APIItem> <APIItem name="readOnly" type="boolean"> Whether the editor is in read-only mode. </APIItem> <APIItem name="embed" type="EmbedUrlData"> The parsed embed data of the media element. </APIItem> <APIItem name="isTweet" type="boolean"> Whether the media element is a tweet. </APIItem> <APIItem name="isVideo" type="boolean"> Whether the media element is a video. </APIItem> <APIItem name="isYoutube" type="boolean"> Whether the media element is a YouTube video. </APIItem> </APIReturns> </API>

useMediaToolbarButton

A behavior hook for a media toolbar button.

<API name="useMediaToolbarButton"> <APIParameters> <APIItem name="options.nodeType" type="string" optional> The type of media node to insert. </APIItem> </APIParameters> <APIReturns type="object"> <APIItem name="props.onClick" type="() => void"> Callback function that inserts the media node and focuses the editor. </APIItem> </APIReturns> </API>

useFloatingMediaEditButton

Handles the floating media edit button.

<API name="useFloatingMediaEditButton"> <APIReturns type="object"> <APIItem name="props.onClick" type="() => void"> Callback function to handle the button click. </APIItem> </APIReturns> </API>

useFloatingMediaUrlInput

Handles the URL input field for media elements.

<API name="useFloatingMediaUrlInput"> <APIProps> <APIItem name="defaultValue" type="string"> The default value for the URL input field. </APIItem> </APIProps> <APIReturns type="object"> <APIItem name="props.onChange" type="() => void"> Callback function to handle input changes. </APIItem> <APIItem name="props.autoFocus" type="boolean"> Whether the URL input field should be focused on mount. </APIItem> <APIItem name="props.defaultValue" type="string"> The default value for the URL input field. </APIItem> </APIReturns> </API>

useImage

A hook for image elements.

<API name="useImage"> <APIReturns type="object"> <APIItem name="props.src" type="string"> The URL of the media element. </APIItem> <APIItem name="props.alt" type="string"> The caption string for the image. </APIItem> <APIItem name="props.draggable" type="boolean"> Whether the image is draggable. </APIItem> </APIReturns> </API>

Utilities

parseMediaUrl

Parses a media URL for plugin-specific handling.

<API name="parseMediaUrl"> <APIParameters> <APIItem name="options.pluginKey" type="string"> The key of the media plugin. </APIItem> <APIItem name="options.url" type="string" optional> The URL of the media to be parsed. </APIItem> </APIParameters> </API>

parseVideoUrl

Parses a video URL and extracts the video ID and provider-specific embed URL.

<API name="parseVideoUrl"> <APIParameters> <APIItem name="url" type="string"> The video URL to parse. </APIItem> </APIParameters> <APIReturns type="EmbedUrlData | undefined"> An object containing the video ID and provider if parsing is successful, undefined if URL is invalid or unsupported. </APIReturns> </API>

parseTwitterUrl

Parses a Twitter URL and extracts the tweet ID.

<API name="parseTwitterUrl"> <APIParameters> <APIItem name="url" type="string"> The Twitter URL. </APIItem> </APIParameters> <APIReturns> <APIItem type="EmbedUrlData | undefined"> An object containing the tweet ID and provider if the parsing is successful. Returns undefined if the URL is not valid or does not match any supported video providers. </APIItem> </APIReturns> </API>

parseIframeUrl

Parses the URL of an iframe embed.

<API name="parseIframeUrl"> <APIParameters> <APIItem name="url" type="string"> The URL or embed code of the iframe. </APIItem> </APIParameters> </API>

isImageUrl

Checks if a URL is a valid image URL.

<API name="isImageUrl"> <APIParameters> <APIItem name="url" type="string"> The URL to check. </APIItem> </APIParameters> <APIReturns type="boolean"> Whether the URL is a valid image URL. </APIReturns> </API>

submitFloatingMedia

Submits a floating media element.

<API name="submitFloatingMedia"> <APIParameters> <APIItem name="options.element" type="TMediaElement"> The floating media element to be submitted. </APIItem> <APIItem name="options.pluginKey" type="string" optional> The key of the media plugin. </APIItem> </APIParameters> </API>

withImageUpload

Enhances the editor instance with image upload functionality.

<API name="withImageUpload"> <APIParameters> <APIItem name="plugin" type="PlatePlugin"> The plate plugin. </APIItem> </APIParameters> </API>

withImageEmbed

Enhances the editor instance with image-related functionality.

<API name="withImageEmbed"> <APIParameters> <APIItem name="plugin" type="PlatePlugin"> The plate plugin. </APIItem> </APIParameters> </API>

Types

TMediaElement

export interface TMediaElement extends TElement {
  url: string;
  id?: string;
  align?: 'center' | 'left' | 'right';
  isUpload?: boolean;
  name?: string;
  placeholderId?: string;
}

TPlaceholderElement

export interface TPlaceholderElement extends TElement {
  mediaType: string;
}

EmbedUrlData

export interface EmbedUrlData {
  url?: string;
  provider?: string;
  id?: string;
  component?: React.FC<EmbedUrlData>;
}
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•

← Root | ↑ Up