/* eslint-disable react/display-name */ import React, { useMemo } from 'react'; import { cn, withRef } from '@udecode/cn'; import { isType } from '@udecode/plate'; import { BlockquotePlugin } from '@udecode/plate-block-quote/react'; import { CodeBlockPlugin } from '@udecode/plate-code-block/react'; import { useDraggable, useDropLine } from '@udecode/plate-dnd'; import { ExcalidrawPlugin } from '@udecode/plate-excalidraw/react'; import { HEADING_KEYS } from '@udecode/plate-heading'; import { ColumnItemPlugin, ColumnPlugin } from '@udecode/plate-layout/react'; import { ImagePlugin, MediaEmbedPlugin, PlaceholderPlugin, } from '@udecode/plate-media/react'; import { BlockSelectionPlugin } from '@udecode/plate-selection/react'; import { TableCellPlugin, TablePlugin, TableRowPlugin, } from '@udecode/plate-table/react'; import { TogglePlugin } from '@udecode/plate-toggle/react'; import { type PlateRenderElementProps, type RenderNodeWrapper, MemoizedChildren, ParagraphPlugin, useEditorRef, useElement, usePath, usePluginOption, } from '@udecode/plate/react'; import { useReadOnly, useSelected } from '@udecode/plate/react'; import { GripVertical } from 'lucide-react'; import { STRUCTURAL_TYPES } from '../editor/transforms'; import { TooltipButton } from './tooltip'; const UNDRAGGABLE_KEYS = [ ColumnItemPlugin.key, TableRowPlugin.key, TableCellPlugin.key, ]; export const DraggableAboveNodes: RenderNodeWrapper = (props) => { const { editor, element, path } = props; const readOnly = useReadOnly(); const enabled = useMemo(() => { if (readOnly) return false; if (path.length === 1 && !isType(editor, element, UNDRAGGABLE_KEYS)) { return true; } if (path.length === 3 && !isType(editor, element, UNDRAGGABLE_KEYS)) { const block = editor.api.some({ at: path, match: { type: editor.getType(ColumnPlugin), }, }); if (block) { return true; } } if (path.length === 4 && !isType(editor, element, UNDRAGGABLE_KEYS)) { const block = editor.api.some({ at: path, match: { type: editor.getType(TablePlugin), }, }); if (block) { return true; } } return false; }, [editor, element, path, readOnly]); if (!enabled) return; return (props) => ; }; export const Draggable = withRef<'div', PlateRenderElementProps>( ({ className, ...props }, ref) => { const { children, editor, element, path } = props; const blockSelectionApi = editor.getApi(BlockSelectionPlugin).blockSelection; const { isDragging, previewRef, handleRef } = useDraggable({ element, onDropHandler: (_, { dragItem }) => { const id = (dragItem as any).id; if (blockSelectionApi && id) { blockSelectionApi.set(id); } }, }); const isInColumn = path.length === 3; const isInTable = path.length === 4; return (
{!isInTable && (
)}
{children}
); }, ); const Gutter = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ children, className, ...props }, ref) => { const editor = useEditorRef(); const element = useElement(); const path = usePath(); const isSelectionAreaVisible = usePluginOption( BlockSelectionPlugin, 'isSelectionAreaVisible', ); const selected = useSelected(); const isNodeType = (keys: string[] | string) => isType(editor, element, keys); const isInColumn = path.length === 3; return (
{children}
); }); const DragHandle = React.memo(() => { const editor = useEditorRef(); const element = useElement(); return ( { editor .getApi(BlockSelectionPlugin) .blockSelection.set(element.id as string); }} data-plate-prevent-deselect tooltip="Drag to move" > ); }); const DropLine = React.memo( React.forwardRef>( // eslint-disable-next-line react/prop-types ({ className, ...props }, ref) => { const { dropLine } = useDropLine(); if (!dropLine) return null; return (
); }, ), );