buster/apps/web/src/components/ui/report/elements/MediaImageNode.tsx

78 lines
2.5 KiB
TypeScript

'use client';
import * as React from 'react';
import type { TImageElement } from 'platejs';
import type { PlateElementProps } from 'platejs/react';
import { useDraggable } from '@platejs/dnd';
import { Image, ImagePlugin, useMediaState } from '@platejs/media/react';
import { ResizableProvider, useResizableValue } from '@platejs/resizable';
import { PlateElement, withHOC } from 'platejs/react';
import { cn } from '@/lib/utils';
import { Caption, CaptionTextarea } from './CaptionNode';
import { MediaToolbar } from './MediaToolbar';
import { mediaResizeHandleVariants, Resizable, ResizeHandle } from './ResizeHandle';
export const ImageElement = withHOC(
ResizableProvider,
function ImageElement(props: PlateElementProps<TImageElement>) {
const { align = 'center', focused, readOnly, selected } = useMediaState();
const width = useResizableValue('width');
const { isDragging, handleRef } = useDraggable({
element: props.element
});
return (
<MediaToolbar plugin={ImagePlugin}>
<PlateElement {...props} className="py-2.5">
<figure className="group relative m-0" contentEditable={false}>
<Resizable
align={align}
options={{
align,
readOnly
}}>
<ResizeHandle
className={mediaResizeHandleVariants({ direction: 'left' })}
options={{ direction: 'left' }}
/>
<Image
ref={handleRef}
className={cn(
'bg-item-hover-active block w-full max-w-full cursor-pointer object-cover px-0',
'rounded-sm',
focused && selected && 'ring-ring ring-2 ring-offset-2',
isDragging && 'opacity-50'
)}
alt={(props.attributes as { alt?: string }).alt}
/>
<ResizeHandle
className={mediaResizeHandleVariants({
direction: 'right'
})}
options={{ direction: 'right' }}
/>
</Resizable>
<Caption style={{ width }} align={align}>
<CaptionTextarea
readOnly={readOnly}
onFocus={(e) => {
e.preventDefault();
}}
placeholder="Write a caption..."
/>
</Caption>
</figure>
{props.children}
</PlateElement>
</MediaToolbar>
);
}
);