'use client'; import React, { useCallback, useState } from 'react'; import type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; import { PopoverAnchor } from '@radix-ui/react-popover'; import { cn, withRef } from '@udecode/cn'; import { BlockSelectionPlugin } from '@udecode/plate-selection/react'; import { type TTableElement, setCellBackground } from '@udecode/plate-table'; import { TablePlugin, TableProvider, useTableBordersDropdownMenuContentState, useTableElement, useTableMergeState, } from '@udecode/plate-table/react'; import { PlateElement, useEditorPlugin, useEditorRef, useEditorSelector, useElement, usePluginOption, useReadOnly, useRemoveNodeButton, useSelected, withHOC, } from '@udecode/plate/react'; import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, CombineIcon, EraserIcon, Grid2X2Icon, PaintBucketIcon, SquareSplitHorizontalIcon, Trash2Icon, XIcon, } from 'lucide-react'; import { DEFAULT_COLORS } from './color-constants'; import { ColorDropdownMenuItems } from './color-dropdown-menu-items'; import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuTrigger, } from './dropdown-menu'; import { Popover, PopoverContent } from './popover'; import { BorderAll, BorderBottom, BorderLeft, BorderNone, BorderRight, BorderTop, } from './table-icons'; import { Toolbar, ToolbarButton, ToolbarGroup } from './toolbar'; export const TableElement = withHOC( TableProvider, withRef(({ children, className, ...props }, ref) => { const readOnly = useReadOnly(); const isSelectionAreaVisible = usePluginOption( BlockSelectionPlugin, 'isSelectionAreaVisible', ); const hasControls = !readOnly && !isSelectionAreaVisible; const selected = useSelected(); const { isSelectingCell, marginLeft, props: tableProps, } = useTableElement(); const content = (
{children}
); if (readOnly || !selected) { return content; } return {content}; }), ); export const TableFloatingToolbar = withRef( ({ children, ...props }, ref) => { const { tf } = useEditorPlugin(TablePlugin); const element = useElement(); const { props: buttonProps } = useRemoveNodeButton({ element }); const collapsed = useEditorSelector( (editor) => !editor.api.isExpanded(), [], ); const { canMerge, canSplit } = useTableMergeState(); return ( {children} e.preventDefault()} contentEditable={false} {...props} > {canMerge && ( tf.table.merge()} onMouseDown={(e) => e.preventDefault()} tooltip="Merge cells" > )} {canSplit && ( tf.table.split()} onMouseDown={(e) => e.preventDefault()} tooltip="Split cell" > )} {collapsed && ( )} {collapsed && ( { tf.insert.tableRow({ before: true }); }} onMouseDown={(e) => e.preventDefault()} tooltip="Insert row before" > { tf.insert.tableRow(); }} onMouseDown={(e) => e.preventDefault()} tooltip="Insert row after" > { tf.remove.tableRow(); }} onMouseDown={(e) => e.preventDefault()} tooltip="Delete row" > )} {collapsed && ( { tf.insert.tableColumn({ before: true }); }} onMouseDown={(e) => e.preventDefault()} tooltip="Insert column before" > { tf.insert.tableColumn(); }} onMouseDown={(e) => e.preventDefault()} tooltip="Insert column after" > { tf.remove.tableColumn(); }} onMouseDown={(e) => e.preventDefault()} tooltip="Delete column" > )} ); }, ); export const TableBordersDropdownMenuContent = withRef< typeof DropdownMenuPrimitive.Content >((props, ref) => { const editor = useEditorRef(); const { getOnSelectTableBorder, hasBottomBorder, hasLeftBorder, hasNoBorders, hasOuterBorders, hasRightBorder, hasTopBorder, } = useTableBordersDropdownMenuContentState(); return ( { e.preventDefault(); editor.tf.focus(); }} align="start" side="right" sideOffset={0} {...props} >
Top Border
Right Border
Bottom Border
Left Border
No Border
Outside Borders
); }); type ColorDropdownMenuProps = { children: React.ReactNode; tooltip: string; }; function ColorDropdownMenu({ children, tooltip }: ColorDropdownMenuProps) { const [open, setOpen] = useState(false); const editor = useEditorRef(); const selectedCells = usePluginOption(TablePlugin, 'selectedCells'); const onUpdateColor = useCallback( (color: string) => { setOpen(false); setCellBackground(editor, { color, selectedCells: selectedCells ?? [] }); }, [selectedCells, editor], ); const onClearColor = useCallback(() => { setOpen(false); setCellBackground(editor, { color: null, selectedCells: selectedCells ?? [], }); }, [selectedCells, editor]); return ( {children} Clear ); }