/* eslint-disable no-param-reassign */ import React, { ClipboardEventHandler, KeyboardEventHandler, ReactNode, forwardRef, useCallback, useState, } from 'react'; import { Box, Scroll, Text } from 'folds'; import { Descendant, Editor, createEditor } from 'slate'; import { Slate, Editable, withReact, RenderLeafProps, RenderElementProps, RenderPlaceholderProps, } from 'slate-react'; import { BlockType, RenderElement, RenderLeaf } from './Elements'; import { CustomElement } from './slate'; import * as css from './Editor.css'; import { toggleKeyboardShortcut } from './keyboard'; const initialValue: CustomElement[] = [ { type: BlockType.Paragraph, children: [{ text: '' }], }, ]; const withInline = (editor: Editor): Editor => { const { isInline } = editor; editor.isInline = (element) => [BlockType.Mention, BlockType.Emoticon, BlockType.Link].includes(element.type) || isInline(element); return editor; }; const withVoid = (editor: Editor): Editor => { const { isVoid } = editor; editor.isVoid = (element) => [BlockType.Mention, BlockType.Emoticon].includes(element.type) || isVoid(element); return editor; }; export const useEditor = (): Editor => { const [editor] = useState(withInline(withVoid(withReact(createEditor())))); return editor; }; export type EditorChangeHandler = ((value: Descendant[]) => void) | undefined; type CustomEditorProps = { top?: ReactNode; bottom?: ReactNode; before?: ReactNode; after?: ReactNode; maxHeight?: string; editor: Editor; placeholder?: string; onKeyDown?: KeyboardEventHandler; onChange?: EditorChangeHandler; onPaste?: ClipboardEventHandler; }; export const CustomEditor = forwardRef( ( { top, bottom, before, after, maxHeight = '50vh', editor, placeholder, onKeyDown, onChange, onPaste, }, ref ) => { const renderElement = useCallback( (props: RenderElementProps) => , [] ); const renderLeaf = useCallback((props: RenderLeafProps) => , []); const handleKeydown: KeyboardEventHandler = useCallback( (evt) => { onKeyDown?.(evt); const shortcutToggled = toggleKeyboardShortcut(editor, evt); if (shortcutToggled) evt.preventDefault(); }, [editor, onKeyDown] ); const renderPlaceholder = useCallback(({ attributes, children }: RenderPlaceholderProps) => { // drop style attribute as we use our custom placeholder css. // eslint-disable-next-line @typescript-eslint/no-unused-vars const { style, ...props } = attributes; return ( {children} ); }, []); return (
{top} {before && ( {before} )} {after && ( {after} )} {bottom}
); } );