{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "media-docs",
  "title": "Media",
  "description": "Documentation for Media",
  "files": [
    {
      "path": "../../content/docs/(plugins)/(elements)/media.mdx",
      "content": "---\ntitle: Media\ndocs:\n  - route: https://pro.platejs.org/docs/examples/media\n    title: Plus\n  - route: /docs/components/media-image-node\n    title: Image Element\n  - route: /docs/components/media-video-node\n    title: Video Element\n  - route: /docs/components/media-audio-node\n    title: Audio Element\n  - route: /docs/components/media-file-node\n    title: File Element\n  - route: /docs/components/media-embed-node\n    title: Media Embed Element\n  - route: /docs/components/media-toolbar\n    title: Media Popover\n  - route: /docs/components/media-placeholder-node\n    title: Media Placeholder Element\n  - route: /docs/components/media-upload-toast\n    title: Media Upload Toast\n  - route: /docs/components/media-toolbar-button\n    title: Media Toolbar Button\n---\n\n<ComponentPreview name=\"media-demo\" />\n\n<PackageInfo>\n\n## Features\n\n### Media Support\n- **File types**: \n  - Image\n  - Video\n  - Audio\n  - Others (PDF, Word, etc.)\n- **Video providers**:\n  - Local video files\n  - YouTube, Vimeo, Dailymotion, Youku, Coub\n- **Embed providers**: \n  - Tweets\n\n### Media Features\n- Editable captions\n- Resizable elements\n- Embed URLs are normalized into `url`, `provider`, and `id` props, with an optional `sourceUrl` preserved for reversible editing.\n\n### Upload\n- **Multiple upload methods**:\n  - Toolbar button with file picker\n  - Drag and drop from file system\n  - Paste from clipboard (images)\n  - URL embedding for external media\n- **Upload experience**:\n  - Real-time progress tracking\n  - Preview during upload\n  - Automatically converts the placeholder to the appropriate media element (image, video, audio, file) once the upload or embed is submitted\n  - Error handling\n  - File size validation\n  - Type validation\n\n</PackageInfo>\n\n## Kit Usage\n\n<Steps>\n\n### Installation\n\nThe 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](/docs/installation/plate-ui) components.\n\n<ComponentSource name=\"media-kit\" />\n\n- [`ImageElement`](/docs/components/media-image-node): Renders image elements.\n- [`VideoElement`](/docs/components/media-video-node): Renders video elements.\n- [`AudioElement`](/docs/components/media-audio-node): Renders audio elements.\n- [`FileElement`](/docs/components/media-file-node): Renders file elements.\n- [`MediaEmbedElement`](/docs/components/media-embed-node): Renders embedded media.\n- [`PlaceholderElement`](/docs/components/media-placeholder-node): Renders upload placeholders.\n- [`MediaUploadToast`](/docs/components/media-upload-toast): Shows upload progress notifications.\n- [`MediaPreviewDialog`](/docs/components/media-preview-dialog): Provides media preview functionality.\n\n### Add Kit\n\nAdd the kit to your plugins:\n\n```tsx\nimport { createPlateEditor } from 'platejs/react';\nimport { MediaKit } from '@/components/editor/plugins/media-kit';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ...MediaKit,\n  ],\n});\n```\n\n### Add API Routes\n\n<ComponentInstallation name=\"media-uploadthing-api\" inline />\n\n### Environment Setup\n\nGet your secret key from [UploadThing](https://uploadthing.com/dashboard/settings) and add it to `.env`:\n\n```bash title=\".env\"\nUPLOADTHING_TOKEN=xxx\n```\n\n</Steps>\n\n## Manual Usage\n\n<Steps>\n\n### Installation\n\n```bash\nnpm install @platejs/media\n```\n\n### Add Plugins\n\nInclude the media plugins in your Plate plugins array when creating the editor.\n\n```tsx\nimport {\n  AudioPlugin,\n  FilePlugin,\n  ImagePlugin,\n  MediaEmbedPlugin,\n  PlaceholderPlugin,\n  VideoPlugin,\n} from '@platejs/media/react';\nimport { createPlateEditor } from 'platejs/react';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ImagePlugin,\n    VideoPlugin,\n    AudioPlugin,\n    FilePlugin,\n    MediaEmbedPlugin,\n    PlaceholderPlugin,\n  ],\n});\n```\n\n### Configure Plugins\n\nConfigure the plugins with custom components and upload settings.\n\n```tsx\nimport {\n  AudioPlugin,\n  FilePlugin,\n  ImagePlugin,\n  MediaEmbedPlugin,\n  PlaceholderPlugin,\n  VideoPlugin,\n} from '@platejs/media/react';\nimport { KEYS } from 'platejs';\nimport { createPlateEditor } from 'platejs/react';\nimport { \n  AudioElement, \n  FileElement, \n  ImageElement, \n  MediaEmbedElement, \n  PlaceholderElement, \n  VideoElement \n} from '@/components/ui/media-nodes';\nimport { MediaUploadToast } from '@/components/ui/media-upload-toast';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ImagePlugin.withComponent(ImageElement),\n    VideoPlugin.withComponent(VideoElement),\n    AudioPlugin.withComponent(AudioElement),\n    FilePlugin.withComponent(FileElement),\n    MediaEmbedPlugin.withComponent(MediaEmbedElement),\n    PlaceholderPlugin.configure({\n      options: { disableEmptyPlaceholder: true },\n      render: { afterEditable: MediaUploadToast, node: PlaceholderElement },\n    }),\n  ],\n});\n```\n\n- `withComponent`: Assigns custom components to render each media type.\n- `options.disableEmptyPlaceholder`: Prevents showing placeholder when no file is uploading.\n- `render.afterEditable`: Renders upload progress toast outside the editor.\n\n<Callout type=\"info\">\n  **Note:** When serialized to Markdown or MDX, embeds persist the canonical `url`, `provider`, and `id`, plus an optional `sourceUrl` so edits remain reversible. Allowlisted provider snippets (e.g. YouTube, Tweet) are reduced to canonical URLs on paste. Raw `<script>` or custom embed chrome is out of scope — add your own rules if you need to preserve it.\n</Callout>\n\n### Caption Support\n\nTo enable media captions, add the [Caption Plugin](/docs/caption):\n\n```tsx\nimport { CaptionPlugin } from '@platejs/caption/react';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    // ...media plugins,\n    CaptionPlugin.configure({\n      options: {\n        query: {\n          allow: [KEYS.img, KEYS.video, KEYS.audio, KEYS.file, KEYS.mediaEmbed],\n        },\n      },\n    }),\n  ],\n});\n```\n\n### Custom Upload Implementation\n\nFor custom upload implementations, create an upload hook that matches this interface:\n\n```ts\ninterface UseUploadFileProps {\n  onUploadComplete?: (file: UploadedFile) => void;\n  onUploadError?: (error: unknown) => void;\n  headers?: Record<string, string>;\n  onUploadBegin?: (fileName: string) => void;\n  onUploadProgress?: (progress: { progress: number }) => void;\n  skipPolling?: boolean;\n}\n\ninterface UploadedFile {\n  key: string;    // Unique identifier\n  url: string;    // Public URL of the uploaded file\n  name: string;   // Original filename\n  size: number;   // File size in bytes\n  type: string;   // MIME type\n}\n```\n\nExample implementation with S3 presigned URLs:\n\n```ts\nexport function useUploadFile({ \n  onUploadComplete, \n  onUploadError, \n  onUploadProgress \n}: UseUploadFileProps = {}) {\n  const [uploadedFile, setUploadedFile] = useState<UploadedFile>();\n  const [uploadingFile, setUploadingFile] = useState<File>();\n  const [progress, setProgress] = useState(0);\n  const [isUploading, setIsUploading] = useState(false);\n\n  async function uploadFile(file: File) {\n    setIsUploading(true);\n    setUploadingFile(file);\n\n    try {\n      // Get presigned URL and final URL from your backend\n      const { presignedUrl, fileUrl, fileKey } = await fetch('/api/upload', {\n        method: 'POST',\n        body: JSON.stringify({\n          filename: file.name,\n          contentType: file.type,\n        }),\n      }).then(r => r.json());\n\n      // Upload to S3 using presigned URL\n      await axios.put(presignedUrl, file, {\n        headers: { 'Content-Type': file.type },\n        onUploadProgress: (progressEvent) => {\n          const progress = (progressEvent.loaded / progressEvent.total) * 100;\n          setProgress(progress);\n          onUploadProgress?.({ progress });\n        },\n      });\n\n      const uploadedFile = {\n        key: fileKey,\n        url: fileUrl,\n        name: file.name,\n        size: file.size,\n        type: file.type,\n      };\n\n      setUploadedFile(uploadedFile);\n      onUploadComplete?.(uploadedFile);\n      \n      return uploadedFile;\n    } catch (error) {\n      onUploadError?.(error);\n      throw error;\n    } finally {\n      setProgress(0);\n      setIsUploading(false);\n      setUploadingFile(undefined);\n    }\n  }\n\n  return {\n    isUploading,\n    progress,\n    uploadFile,\n    uploadedFile,\n    uploadingFile,\n  };\n}\n```\n\nThen integrate your custom upload hook with the media components:\n\n```tsx\nimport { useUploadFile } from '@/hooks/use-upload-file'; // Your custom hook\n\n// In your PlaceholderElement component\nexport function PlaceholderElement({ className, children, element, ...props }) {\n  const { uploadFile, isUploading, progress } = useUploadFile({\n    onUploadComplete: (uploadedFile) => {\n      // Replace placeholder with actual media element\n      const { url, type } = uploadedFile;\n      \n      // Transform placeholder to appropriate media type\n      editor.tf.replace.placeholder({\n        id: element.id,\n        url,\n        type: getMediaType(type), // image, video, audio, file\n      });\n    },\n    onUploadError: (error) => {\n      console.error('Upload failed:', error);\n      // Handle upload error, maybe show toast\n    },\n  });\n\n  // Use uploadFile when files are dropped or selected\n  // This integrates with the PlaceholderPlugin's file handling\n}\n```\n\n### Add Toolbar Button\n\nYou can add [`MediaToolbarButton`](/docs/components/media-toolbar-button) to your [Toolbar](/docs/toolbar) to upload and insert media.\n\n### Insert Toolbar Button\n\nYou can add these items to the [Insert Toolbar Button](/docs/toolbar#insert-toolbar-button) to insert media elements:\n\n```tsx\n{\n  icon: <ImageIcon />,\n  label: 'Image',\n  value: KEYS.img,\n}\n```\n\n</Steps>\n\n## Plate Plus\n\n<ComponentPreviewPro name=\"media-pro\" />\n\n## Plugins\n\n### `ImagePlugin`\n\nPlugin for void image elements.\n\n<API name=\"ImagePlugin\">\n<APIOptions type=\"ImagePluginOptions\">\n  <APIItem name=\"uploadImage\" type=\"(dataUrl: string | ArrayBuffer) => Promise<string | ArrayBuffer> | string | ArrayBuffer\" optional>\n    Function to upload image to a server. Receives:\n    - Data URL (string) from `FileReader.readAsDataURL`\n    - ArrayBuffer from clipboard data\n    Returns:\n    - URL string to uploaded image\n    - Original data URL/ArrayBuffer if no upload needed\n    - **Default:** Returns original input\n  </APIItem>\n  <APIItem name=\"disableUploadInsert\" type=\"boolean\" optional>\n    Disables file upload on data insertion.\n    - **Default:** `false`\n  </APIItem>\n  <APIItem name=\"disableEmbedInsert\" type=\"boolean\" optional>\n    Disables URL embed on data insertion.\n    - **Default:** `false`\n  </APIItem>\n  <APIItem name=\"isUrl\" type=\"function\" optional>\n    A function to check whether a text string is a URL.\n  </APIItem>\n  <APIItem name=\"transformUrl\" type=\"function\" optional>\n    A function to transform the URL.\n  </APIItem>\n</APIOptions>\n</API>\n\n### `VideoPlugin`\n\nPlugin for void video elements. Extends `MediaPluginOptions`.\n\n### `AudioPlugin`\n\nPlugin for void audio elements. Extends `MediaPluginOptions`.\n\n### `FilePlugin`\n\nPlugin for void file elements. Extends `MediaPluginOptions`.\n\n### `MediaEmbedPlugin`\n\nPlugin for void media embed elements. Extends `MediaPluginOptions`.\n\n### `PlaceholderPlugin`\n\nPlugin for managing media placeholders during upload. Handles file uploads, drag & drop, and clipboard paste events.\n\n<API name=\"PlaceholderPlugin\">\n<APIOptions type=\"object\">\n  <APIItem name=\"uploadConfig\" type=\"Partial<Record<AllowedFileType, MediaItemConfig>>\" optional>\nConfiguration for different file types. Default configuration:\n```ts\n{\n  audio: {\n    maxFileCount: 1,\n    maxFileSize: '8MB',\n    mediaType: KEYS.audio,\n    minFileCount: 1,\n  },\n  blob: {\n    maxFileCount: 1,\n    maxFileSize: '8MB',\n    mediaType: KEYS.file,\n    minFileCount: 1,\n  },\n  image: {\n    maxFileCount: 3,\n    maxFileSize: '4MB',\n    mediaType: KEYS.image,\n    minFileCount: 1,\n  },\n  pdf: {\n    maxFileCount: 1,\n    maxFileSize: '4MB',\n    mediaType: KEYS.file,\n    minFileCount: 1,\n  },\n  text: {\n    maxFileCount: 1,\n    maxFileSize: '64KB',\n    mediaType: KEYS.file,\n    minFileCount: 1,\n  },\n  video: {\n    maxFileCount: 1,\n    maxFileSize: '16MB',\n    mediaType: KEYS.video,\n    minFileCount: 1,\n  },\n}\n```\nSupported file types: `'image' | 'video' | 'audio' | 'pdf' | 'text' | 'blob'`\n<APISubList>\n  <APISubListItem parent=\"uploadConfig\" name=\"mediaType\" type=\"MediaKeys\">\n    The media plugin keys that this config is for: `'audio' | 'file' | 'image' | 'video'`\n  </APISubListItem>\n  <APISubListItem parent=\"uploadConfig\" name=\"maxFileCount\" type=\"number\" optional>\n    The maximum number of files of this type that can be uploaded.\n  </APISubListItem>\n  <APISubListItem parent=\"uploadConfig\" name=\"maxFileSize\" type=\"FileSize\" optional>\n    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}`\n  </APISubListItem>\n  <APISubListItem parent=\"uploadConfig\" name=\"minFileCount\" type=\"number\" optional>\n    The minimum number of files of this type that must be uploaded.\n  </APISubListItem>\n</APISubList>\n</APIItem>\n<APIItem name=\"disableEmptyPlaceholder\" type=\"boolean\" optional>\nDisable empty placeholder when no file is uploading.\n- **Default:** `false`\n</APIItem>\n<APIItem name=\"disableFileDrop\" type=\"boolean\" optional>\nDisable drag and drop file upload functionality.\n- **Default:** `false`\n</APIItem>\n<APIItem name=\"maxFileCount\" type=\"number\" optional>\nMaximum number of files that can be uploaded at once, if not specified by `uploadConfig`.\n- **Default:** `5`\n</APIItem>\n<APIItem name=\"multiple\" type=\"boolean\" optional>\nAllow multiple files of the same type to be uploaded.\n- **Default:** `true`\n</APIItem>\n</APIOptions>\n</API>\n\n## API\n\n### `api.placeholder.addUploadingFile`\n\nTracks a file that is currently being uploaded.\n\n<API name=\"addUploadingFile\">\n<APIParameters>\n  <APIItem name=\"id\" type=\"string\">\n    Unique identifier for the placeholder element.\n  </APIItem>\n  <APIItem name=\"file\" type=\"File\">\n    The file being uploaded.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `api.placeholder.getUploadingFile`\n\nGets a file that is currently being uploaded.\n\n<API name=\"getUploadingFile\">\n<APIParameters>\n  <APIItem name=\"id\" type=\"string\">\n    Unique identifier for the placeholder element.\n  </APIItem>\n</APIParameters>\n\n<APIReturns>\n  <APIItem type=\"File | undefined\">\n    The uploading file if found, undefined otherwise.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `api.placeholder.removeUploadingFile`\n\nRemoves a file from the uploading tracking state after upload completes or fails.\n\n<API name=\"removeUploadingFile\">\n<APIParameters>\n  <APIItem name=\"id\" type=\"string\">\n    Unique identifier for the placeholder element to remove.\n  </APIItem>\n</APIParameters>\n</API>\n\n## Transforms\n\n### `tf.insert.media`\n\nInserts media files into the editor with upload placeholders.\n\n<API name=\"insertMedia\">\n<APIParameters>\n  <APIItem name=\"files\" type=\"FileList\">\n    Files to upload. Validates against configured file types and limits.\n  </APIItem>\n  <APIItem name=\"options\" type=\"object\" optional>\n    Options for the insert nodes transform.\n  </APIItem>\n</APIParameters>\n\n<APIOptions type=\"object\">\n  <APIItem name=\"at\" type=\"Path\" optional>\n    Location to insert the media. Defaults to current selection.\n  </APIItem>\n  <APIItem name=\"nextBlock\" type=\"boolean\" optional>\n    Whether to insert a new block after the media.\n    - **Default:** `true`\n  </APIItem>\n</APIOptions>\n</API>\n\nValidates 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.\n\nError codes:\n```ts\nenum UploadErrorCode {\n  INVALID_FILE_TYPE = 400,\n  TOO_MANY_FILES = 402,\n  INVALID_FILE_SIZE = 403,\n  TOO_LESS_FILES = 405,\n  TOO_LARGE = 413,\n}\n```\n\n### `tf.insert.imagePlaceholder`\n\nInserts a placeholder that converts to an image element when completed.\n\n### `tf.insert.videoPlaceholder`\n\nInserts a placeholder that converts to a video element when completed.\n\n### `tf.insert.audioPlaceholder`\n\nInserts a placeholder that converts to an audio element when completed.\n\n### `tf.insert.filePlaceholder`\n\nInserts a placeholder that converts to a file element when completed.\n\n### `tf.insert.image`\n\nInserts an image element into the editor.\n\n<API name=\"insertImage\">\n<APIParameters>\n  <APIItem name=\"url\" type=\"string | ArrayBuffer\">\n    The URL or ArrayBuffer of the image.\n  </APIItem>\n  <APIItem name=\"options\" type=\"InsertNodesOptions\" optional>\n    Additional options for inserting the image element.\n  </APIItem>\n</APIParameters>\n\n<APIOptions type=\"InsertImageOptions\">\n  <APIItem name=\"nextBlock\" type=\"boolean\" optional>\n    If true, the image will be inserted in the next block.\n  </APIItem>\n</APIOptions>\n</API>\n\n### `tf.insert.mediaEmbed`\n\nInserts a media embed element at the current selection.\n\n<API name=\"insertMediaEmbed\">\n<APIOptions type=\"InsertMediaEmbedOptions\">\n  <APIItem name=\"url\" type=\"string\" optional>\n    The URL of the media embed.\n    - **Default:** `''`\n  </APIItem>\n  <APIItem name=\"key\" type=\"string\" optional>\n    The key of the media embed element.\n    - **Default:** `KEYS.mediaEmbed`\n  </APIItem>\n  <APIItem name=\"insertNodesOptions\" type=\"InsertNodesOptions\" optional>\n    Additional options for inserting nodes.\n  </APIItem>\n</APIOptions>\n</API>\n\n## Hooks\n\n### `useResizable`\n\nHandles the resizable properties of a media element.\n\n<API name=\"useResizable\">\n<APIState>\n  <APIItem name=\"align\" type=\"'left' | 'center' | 'right'\">\n    The alignment of the content within the resizable element.\n  </APIItem>\n  <APIItem name=\"minWidth\" type=\"ResizeLength\">\n    The minimum width that the resizable element can be adjusted to.\n  </APIItem>\n  <APIItem name=\"maxWidth\" type=\"ResizeLength\">\n    The maximum width that the resizable element can be adjusted to.\n  </APIItem>\n  <APIItem name=\"setNodeWidth\" type=\"(width: number | string) => void\">\n    Function to set the width of the node when resizing.\n  </APIItem>\n  <APIItem name=\"setWidth\" type=\"(width: number | string) => void\">\n    Function to set the width of the resizable element directly.\n  </APIItem>\n  <APIItem name=\"width\" type=\"Property.Width<string | number> | undefined\">\n    The current width of the resizable element (percentage, 'auto', or pixels).\n  </APIItem>\n</APIState>\n\n<APIReturns type=\"object\">\n  <APIItem name=\"wrapperRef\" type=\"React.RefObject<HTMLDivElement>\">\n    React reference to the outermost wrapper div.\n  </APIItem>\n  <APIItem name=\"wrapperProps.style\" type=\"CSSProperties\">\n    CSS styles for the wrapper div.\n  </APIItem>\n  <APIItem name=\"props.style\" type=\"CSSProperties\">\n    CSS styles for the resizable element.\n  </APIItem>\n  <APIItem name=\"context.onResize\" type=\"() => void\">\n    Callback function called when the element is resized.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `useMediaState`\n\nA state hook for a media element.\n\n<API name=\"useMediaState\">\n<APIParameters>\n  <APIItem name=\"options.urlParsers\" type=\"EmbedUrlParser[]\" optional>\n    Array of URL parsers to parse the media element URL.\n  \n    - **`EmbedUrlParser`:** `(url: string) => EmbedUrlData | undefined`\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"object\">\n  <APIItem name=\"align\" type=\"string\">\n    The alignment of the media element.\n  </APIItem>\n  <APIItem name=\"focus\" type=\"boolean\">\n    Whether the media element is currently focused.\n  </APIItem>\n  <APIItem name=\"selected\" type=\"boolean\">\n    Whether the media element is currently selected.\n  </APIItem>\n  <APIItem name=\"readOnly\" type=\"boolean\">\n    Whether the editor is in read-only mode.\n  </APIItem>\n  <APIItem name=\"embed\" type=\"EmbedUrlData\">\n    The parsed embed data of the media element.\n  </APIItem>\n  <APIItem name=\"isTweet\" type=\"boolean\">\n    Whether the media element is a tweet.\n  </APIItem>\n  <APIItem name=\"isVideo\" type=\"boolean\">\n    Whether the media element is a video.\n  </APIItem>\n  <APIItem name=\"isYoutube\" type=\"boolean\">\n    Whether the media element is a YouTube video.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `useMediaToolbarButton`\n\nA behavior hook for a media toolbar button.\n\n<API name=\"useMediaToolbarButton\">\n<APIParameters>\n  <APIItem name=\"options.nodeType\" type=\"string\" optional>\n    The type of media node to insert.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"object\">\n  <APIItem name=\"props.onClick\" type=\"() => void\">\n    Callback function that inserts the media node and focuses the editor.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `useFloatingMediaEditButton`\n\nHandles the floating media edit button.\n\n<API name=\"useFloatingMediaEditButton\">\n<APIReturns type=\"object\">\n  <APIItem name=\"props.onClick\" type=\"() => void\">\n    Callback function to handle the button click.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `useFloatingMediaUrlInput`\n\nHandles the URL input field for media elements.\n\n<API name=\"useFloatingMediaUrlInput\">\n<APIProps>\n  <APIItem name=\"defaultValue\" type=\"string\">\n    The default value for the URL input field.\n  </APIItem>\n</APIProps>\n\n<APIReturns type=\"object\">\n  <APIItem name=\"props.onChange\" type=\"() => void\">\n    Callback function to handle input changes.\n  </APIItem>\n  <APIItem name=\"props.autoFocus\" type=\"boolean\">\n    Whether the URL input field should be focused on mount.\n  </APIItem>\n  <APIItem name=\"props.defaultValue\" type=\"string\">\n    The default value for the URL input field.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `useImage`\n\nA hook for image elements.\n\n<API name=\"useImage\">\n<APIReturns type=\"object\">\n  <APIItem name=\"props.src\" type=\"string\">\n    The URL of the media element.\n  </APIItem>\n  <APIItem name=\"props.alt\" type=\"string\">\n    The caption string for the image.\n  </APIItem>\n  <APIItem name=\"props.draggable\" type=\"boolean\">\n    Whether the image is draggable.\n  </APIItem>\n</APIReturns>\n</API>\n\n## Utilities\n\n### `parseMediaUrl`\n\nParses a media URL for plugin-specific handling.\n\n<API name=\"parseMediaUrl\">\n<APIParameters>\n  <APIItem name=\"options.pluginKey\" type=\"string\">\n    The key of the media plugin.\n  </APIItem>\n  <APIItem name=\"options.url\" type=\"string\" optional>\n    The URL of the media to be parsed.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `parseVideoUrl`\n\nParses a video URL and extracts the video ID and provider-specific embed URL.\n\n<API name=\"parseVideoUrl\">\n<APIParameters>\n  <APIItem name=\"url\" type=\"string\">\n    The video URL to parse.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"EmbedUrlData | undefined\">\n  An object containing the video ID and provider if parsing is successful, undefined if URL is invalid or unsupported.\n</APIReturns>\n</API>\n\n### `parseTwitterUrl`\n\nParses a Twitter URL and extracts the tweet ID.\n\n<API name=\"parseTwitterUrl\">\n<APIParameters>\n  <APIItem name=\"url\" type=\"string\">\n    The Twitter URL.\n  </APIItem>\n</APIParameters>\n\n<APIReturns>\n  <APIItem type=\"EmbedUrlData | undefined\">\n    An object containing the tweet ID and provider if the parsing is successful.\n    Returns undefined if the URL is not valid or does not match any supported video providers.\n  </APIItem>\n</APIReturns>\n</API>\n\n### `parseIframeUrl`\n\nParses the URL of an iframe embed.\n\n<API name=\"parseIframeUrl\">\n<APIParameters>\n  <APIItem name=\"url\" type=\"string\">\n    The URL or embed code of the iframe.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `isImageUrl`\n\nChecks if a URL is a valid image URL.\n\n<API name=\"isImageUrl\">\n<APIParameters>\n  <APIItem name=\"url\" type=\"string\">\n    The URL to check.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"boolean\">\n  Whether the URL is a valid image URL.\n</APIReturns>\n</API>\n\n### `submitFloatingMedia`\n\nSubmits a floating media element.\n\n<API name=\"submitFloatingMedia\">\n<APIParameters>\n  <APIItem name=\"options.element\" type=\"TMediaElement\">\n    The floating media element to be submitted.\n  </APIItem>\n  <APIItem name=\"options.pluginKey\" type=\"string\" optional>\n    The key of the media plugin.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `withImageUpload`\n\nEnhances the editor instance with image upload functionality.\n\n<API name=\"withImageUpload\">\n<APIParameters>\n  <APIItem name=\"plugin\" type=\"PlatePlugin\">\n    The plate plugin.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `withImageEmbed`\n\nEnhances the editor instance with image-related functionality.\n\n<API name=\"withImageEmbed\">\n<APIParameters>\n  <APIItem name=\"plugin\" type=\"PlatePlugin\">\n    The plate plugin.\n  </APIItem>\n</APIParameters>\n</API>\n\n## Types\n\n### `TMediaElement`\n\n```tsx\nexport interface TMediaElement extends TElement {\n  url: string;\n  id?: string;\n  align?: 'center' | 'left' | 'right';\n  isUpload?: boolean;\n  name?: string;\n  placeholderId?: string;\n}\n```\n\n### `TPlaceholderElement`\n\n```tsx\nexport interface TPlaceholderElement extends TElement {\n  mediaType: string;\n}\n```\n\n### `EmbedUrlData`\n\n```tsx\nexport interface EmbedUrlData {\n  url?: string;\n  provider?: string;\n  id?: string;\n  component?: React.FC<EmbedUrlData>;\n}\n```\n",
      "type": "registry:file",
      "target": "content/docs/plate/(plugins)/(elements)/media.mdx"
    }
  ],
  "type": "registry:file"
}