Update MediaEmbedNode.tsx

This commit is contained in:
Nate Kelley 2025-08-02 12:49:36 -06:00
parent ce7ecbe4bb
commit 3b4394874e
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
1 changed files with 55 additions and 10 deletions

View File

@ -6,12 +6,19 @@ import LiteYouTubeEmbed from 'react-lite-youtube-embed';
import type { TMediaEmbedElement } from 'platejs';
import type { PlateElementProps } from 'platejs/react';
import { parseTwitterUrl, parseVideoUrl } from '@platejs/media';
import {
parseTwitterUrl,
parseVideoUrl,
parseIframeUrl,
parseMediaUrl,
type EmbedUrlParser
} from '@platejs/media';
import { MediaEmbedPlugin, useMediaState } from '@platejs/media/react';
import { ResizableProvider, useResizableValue } from '@platejs/resizable';
import {
PlateElement,
useEditorRef,
useElement,
useFocused,
useReadOnly,
useSelected,
@ -25,17 +32,27 @@ import { MediaToolbar } from './MediaToolbar';
import { mediaResizeHandleVariants, Resizable, ResizeHandle } from './ResizeHandle';
import { Code3 } from '../../icons';
import { PopoverAnchor, PopoverBase, PopoverContent } from '../../popover';
import { Title, Text } from '../../typography';
import { Text } from '../../typography';
import { Input } from '../../inputs';
import { Button } from '../../buttons';
import { Separator } from '../../separator';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { useEffect } from 'react';
import { useMount } from '@/hooks';
import { useClickAway } from '@/hooks/useClickAway';
const parseGenericUrl: EmbedUrlParser = (url: string) => {
return {
url,
provider: 'generic'
};
};
const urlParsers: EmbedUrlParser[] = [parseTwitterUrl, parseVideoUrl, parseGenericUrl];
export const MediaEmbedElement = withHOC(
ResizableProvider,
function MediaEmbedElement(props: PlateElementProps<TMediaEmbedElement>) {
const url = props.element.url;
const {
align = 'center',
embed,
@ -44,13 +61,14 @@ export const MediaEmbedElement = withHOC(
isVideo,
isYoutube,
readOnly,
selected
selected,
...rest
} = useMediaState({
urlParsers: [parseTwitterUrl, parseVideoUrl]
urlParsers
});
const width = useResizableValue('width');
const provider = embed?.provider;
const hasElement = !!embed?.url;
const hasElement = !!url;
if (!hasElement) {
return <MediaEmbedPlaceholder {...props} />;
@ -115,7 +133,19 @@ export const MediaEmbedElement = withHOC(
/>
</div>
)
) : null}
) : (
<div className="bg-gray-light/30 h-full min-h-16 w-full overflow-hidden rounded">
<iframe
className={cn(
'absolute top-0 left-0 size-full min-h-16 rounded-sm',
focused && selected && 'ring-ring ring-2 ring-offset-2'
)}
title="embed"
src={embed?.url ?? url}
allowFullScreen
/>
</div>
)}
<ResizeHandle
className={mediaResizeHandleVariants({ direction: 'right' })}
@ -141,8 +171,11 @@ export const MediaEmbedPlaceholder = (props: PlateElementProps<TMediaEmbedElemen
const focused = useFocused();
const editor = useEditorRef();
const inputRef = React.useRef<HTMLInputElement>(null);
const popoverRef = React.useRef<HTMLDivElement>(null);
const anchorRef = React.useRef<HTMLDivElement>(null);
const { openInfoMessage } = useBusterNotifications();
const [forceOpen, setForceOpen] = React.useState(false);
const element = useElement();
const isFocused = focused && selected && !readOnly;
@ -153,6 +186,9 @@ export const MediaEmbedPlaceholder = (props: PlateElementProps<TMediaEmbedElemen
return;
}
// Update the current node with the URL
editor.tf.setNodes({ url }, { at: editor.api.findPath(props.element) });
setForceOpen(false);
};
@ -162,11 +198,21 @@ export const MediaEmbedPlaceholder = (props: PlateElementProps<TMediaEmbedElemen
}
}, [isFocused]);
useClickAway(
(e) => {
setForceOpen(false);
e.preventDefault();
e.stopPropagation();
},
[popoverRef, anchorRef]
);
return (
<PlateElement className="media-embed py-2.5" {...props}>
<PopoverBase open={forceOpen} onOpenChange={setForceOpen}>
<PopoverBase open={forceOpen}>
<PopoverAnchor>
<div
ref={anchorRef}
className={cn(
'bg-muted hover:bg-primary/10 flex cursor-pointer items-center rounded-sm p-3 pr-9 select-none'
)}
@ -181,13 +227,12 @@ export const MediaEmbedPlaceholder = (props: PlateElementProps<TMediaEmbedElemen
</PopoverAnchor>
<PopoverContent
ref={popoverRef}
className="flex w-[300px] flex-col px-0 py-2"
onOpenAutoFocus={(e) => {
console.log('onOpenAutoFocus', e);
e.preventDefault();
}}
onCloseAutoFocus={(e) => {
console.log('onCloseAutoFocus', e);
e.preventDefault();
}}>
<div className="px-3">