/* 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 { withHistory } from 'slate-history'; import { BlockType } from './types'; import { 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, BlockType.Command].includes( element.type ) || isInline(element); return editor; }; const withVoid = (editor: Editor): Editor => { const { isVoid } = editor; editor.isVoid = (element) => [BlockType.Mention, BlockType.Emoticon, BlockType.Command].includes(element.type) || isVoid(element); return editor; }; export const useEditor = (): Editor => { const [editor] = useState(() => withInline(withVoid(withReact(withHistory(createEditor()))))); return editor; }; export type EditorChangeHandler = (value: Descendant[]) => void; type CustomEditorProps = { editableName?: string; top?: ReactNode; bottom?: ReactNode; before?: ReactNode; after?: ReactNode; maxHeight?: string; editor: Editor; placeholder?: string; onKeyDown?: KeyboardEventHandler; onKeyUp?: KeyboardEventHandler; onChange?: EditorChangeHandler; onPaste?: ClipboardEventHandler; }; export const CustomEditor = forwardRef( ( { editableName, top, bottom, before, after, maxHeight = '50vh', editor, placeholder, onKeyDown, onKeyUp, 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}
); } );