From 00826407aab16fbef71b2676e731ed1e9aed0a8e Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Sun, 1 Dec 2019 17:56:56 -0500 Subject: [PATCH] expose render prop types, refactor default renderers --- .../slate-react/src/components/children.tsx | 14 +-- .../slate-react/src/components/custom.tsx | 106 ------------------ .../slate-react/src/components/editable.tsx | 58 ++++++++-- .../slate-react/src/components/element.tsx | 32 ++++-- packages/slate-react/src/components/leaf.tsx | 67 ++++++++--- packages/slate-react/src/components/text.tsx | 6 +- packages/slate-react/src/index.ts | 2 + 7 files changed, 138 insertions(+), 147 deletions(-) delete mode 100644 packages/slate-react/src/components/custom.tsx diff --git a/packages/slate-react/src/components/children.tsx b/packages/slate-react/src/components/children.tsx index 046902f74..1bfb963de 100644 --- a/packages/slate-react/src/components/children.tsx +++ b/packages/slate-react/src/components/children.tsx @@ -7,10 +7,10 @@ import { ReactEditor } from '..' import { useEditor } from '../hooks/use-editor' import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps' import { - CustomDecorationProps, - CustomElementProps, - CustomMarkProps, -} from './custom' + RenderDecorationProps, + RenderElementProps, + RenderMarkProps, +} from './editable' /** * Children. @@ -20,9 +20,9 @@ const Children = (props: { decorate: (entry: NodeEntry) => Range[] decorations: Range[] node: Ancestor - renderDecoration?: (props: CustomDecorationProps) => JSX.Element - renderElement?: (props: CustomElementProps) => JSX.Element - renderMark?: (props: CustomMarkProps) => JSX.Element + renderDecoration?: (props: RenderDecorationProps) => JSX.Element + renderElement?: (props: RenderElementProps) => JSX.Element + renderMark?: (props: RenderMarkProps) => JSX.Element selection: Range | null }) => { const { diff --git a/packages/slate-react/src/components/custom.tsx b/packages/slate-react/src/components/custom.tsx deleted file mode 100644 index f7ea642d5..000000000 --- a/packages/slate-react/src/components/custom.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react' -import { Element, Range, Mark, Text } from 'slate' - -import { useEditor } from '../hooks/use-editor' -import { Leaf } from '../utils/leaf' - -export interface CustomDecorationProps { - children: any - decoration: Range - leaf: Leaf - text: Text - attributes: { - 'data-slate-decoration': true - } -} - -/** - * The default custom decoration renderer. - */ - -export const CustomDecoration = (props: CustomDecorationProps) => { - const { attributes, children } = props - return {children} -} - -/** - * `CustomElementProps` are passed to the `renderElement` handler. - */ - -export interface CustomElementProps { - children: any - element: Element - attributes: { - 'data-slate-inline'?: true - 'data-slate-node': 'element' - 'data-slate-void'?: true - dir?: 'rtl' - ref: any - } -} - -/** - * The default element renderer. - */ - -export const CustomElement = (props: CustomElementProps) => { - const { attributes, children, element } = props - const editor = useEditor() - const Tag = editor.isInline(element) ? 'span' : 'div' - return ( - - {children} - - ) -} - -/** - * `CustomMarkProps` are passed to the `renderMark` handler. - */ - -export interface CustomMarkProps { - children: any - mark: Mark - leaf: Leaf - text: Text - attributes: { - 'data-slate-mark': true - } -} - -/** - * The default custom mark renderer. - */ - -export const CustomMark = (props: CustomMarkProps) => { - const { attributes, children } = props - return {children} -} - -/** - * A custom decoration for the default placeholder behavior. - */ - -export const PlaceholderDecoration = (props: CustomDecorationProps) => { - const { decoration, attributes, children } = props - const { placeholder } = decoration - return ( - - - {placeholder} - - {children} - - ) -} diff --git a/packages/slate-react/src/components/editable.tsx b/packages/slate-react/src/components/editable.tsx index 98414bbe1..8d0383905 100644 --- a/packages/slate-react/src/components/editable.tsx +++ b/packages/slate-react/src/components/editable.tsx @@ -1,5 +1,5 @@ import React, { useLayoutEffect, useRef, useMemo, useCallback } from 'react' -import { Editor, Element, NodeEntry, Node, Range } from 'slate' +import { Editor, Element, NodeEntry, Node, Range, Text, Mark } from 'slate' import debounce from 'debounce' import scrollIntoView from 'scroll-into-view-if-needed' @@ -9,6 +9,7 @@ import { IS_FIREFOX, IS_SAFARI } from '../utils/environment' import { ReactEditor } from '..' import { ReadOnlyContext } from '../hooks/use-read-only' import { useSlate } from '../hooks/use-slate' +import { Leaf } from '../utils/leaf' import { DOMElement, DOMNode, @@ -26,11 +27,50 @@ import { IS_FOCUSED, PLACEHOLDER_SYMBOL, } from '../utils/weak-maps' -import { - CustomDecorationProps, - CustomElementProps, - CustomMarkProps, -} from './custom' + +/** + * `RenderDecorationProps` are passed to the `renderDecoration` handler. + */ + +export interface RenderDecorationProps { + children: any + decoration: Range + leaf: Leaf + text: Text + attributes: { + 'data-slate-decoration': true + } +} + +/** + * `RenderElementProps` are passed to the `renderElement` handler. + */ + +export interface RenderElementProps { + children: any + element: Element + attributes: { + 'data-slate-inline'?: true + 'data-slate-node': 'element' + 'data-slate-void'?: true + dir?: 'rtl' + ref: any + } +} + +/** + * `RenderMarkProps` are passed to the `renderMark` handler. + */ + +export interface RenderMarkProps { + children: any + mark: Mark + leaf: Leaf + text: Text + attributes: { + 'data-slate-mark': true + } +} /** * Editable. @@ -44,9 +84,9 @@ export const Editable = ( readOnly?: boolean role?: string style?: React.CSSProperties - renderDecoration?: (props: CustomDecorationProps) => JSX.Element - renderElement?: (props: CustomElementProps) => JSX.Element - renderMark?: (props: CustomMarkProps) => JSX.Element + renderDecoration?: (props: RenderDecorationProps) => JSX.Element + renderElement?: (props: RenderElementProps) => JSX.Element + renderMark?: (props: RenderMarkProps) => JSX.Element } & React.TextareaHTMLAttributes ) => { const { diff --git a/packages/slate-react/src/components/element.tsx b/packages/slate-react/src/components/element.tsx index 5dae126e6..1c5d97313 100644 --- a/packages/slate-react/src/components/element.tsx +++ b/packages/slate-react/src/components/element.tsx @@ -14,11 +14,10 @@ import { KEY_TO_ELEMENT, } from '../utils/weak-maps' import { - CustomDecorationProps, - CustomElement, - CustomElementProps, - CustomMarkProps, -} from './custom' + RenderDecorationProps, + RenderElementProps, + RenderMarkProps, +} from './editable' import { isRangeListEqual } from '../utils/leaf' /** @@ -29,9 +28,9 @@ const Element = (props: { decorate: (entry: NodeEntry) => Range[] decorations: Range[] element: SlateElement - renderDecoration?: (props: CustomDecorationProps) => JSX.Element - renderElement?: (props: CustomElementProps) => JSX.Element - renderMark?: (props: CustomMarkProps) => JSX.Element + renderDecoration?: (props: RenderDecorationProps) => JSX.Element + renderElement?: (props: RenderElementProps) => JSX.Element + renderMark?: (props: RenderMarkProps) => JSX.Element selection: Range | null }) => { const { @@ -39,7 +38,7 @@ const Element = (props: { decorations, element, renderDecoration, - renderElement = (p: CustomElementProps) => , + renderElement = (p: RenderElementProps) => , renderMark, selection, } = props @@ -153,4 +152,19 @@ const MemoizedElement = React.memo(Element, (prev, next) => { ) }) +/** + * The default element renderer. + */ + +export const DefaultElement = (props: RenderElementProps) => { + const { attributes, children, element } = props + const editor = useEditor() + const Tag = editor.isInline(element) ? 'span' : 'div' + return ( + + {children} + + ) +} + export default MemoizedElement diff --git a/packages/slate-react/src/components/leaf.tsx b/packages/slate-react/src/components/leaf.tsx index 5a763fc86..1c8907daa 100644 --- a/packages/slate-react/src/components/leaf.tsx +++ b/packages/slate-react/src/components/leaf.tsx @@ -1,15 +1,10 @@ import React from 'react' import { Text, Element } from 'slate' + import String from './string' -import { - CustomDecoration, - CustomDecorationProps, - CustomMark, - CustomMarkProps, - PlaceholderDecoration, -} from './custom' -import { PLACEHOLDER_SYMBOL } from '../utils/weak-maps' import { Leaf as SlateLeaf } from '../utils/leaf' +import { PLACEHOLDER_SYMBOL } from '../utils/weak-maps' +import { RenderDecorationProps, RenderMarkProps } from './editable' /** * Individual leaves in a text node with unique formatting. @@ -19,8 +14,8 @@ const Leaf = (props: { isLast: boolean leaf: SlateLeaf parent: Element - renderDecoration?: (props: CustomDecorationProps) => JSX.Element - renderMark?: (props: CustomMarkProps) => JSX.Element + renderDecoration?: (props: RenderDecorationProps) => JSX.Element + renderMark?: (props: RenderMarkProps) => JSX.Element text: Text }) => { const { @@ -28,10 +23,10 @@ const Leaf = (props: { isLast, text, parent, - renderDecoration = (props: CustomDecorationProps) => ( - + renderDecoration = (props: RenderDecorationProps) => ( + ), - renderMark = (props: CustomMarkProps) => , + renderMark = (props: RenderMarkProps) => , } = props let children = ( @@ -95,4 +90,50 @@ const MemoizedLeaf = React.memo(Leaf, (prev, next) => { ) }) +/** + * The default custom decoration renderer. + */ + +export const DefaultDecoration = (props: RenderDecorationProps) => { + const { attributes, children } = props + return {children} +} + +/** + * The default custom mark renderer. + */ + +export const DefaultMark = (props: RenderMarkProps) => { + const { attributes, children } = props + return {children} +} + +/** + * A custom decoration for the default placeholder behavior. + */ + +const PlaceholderDecoration = (props: RenderDecorationProps) => { + const { decoration, attributes, children } = props + const { placeholder } = decoration + return ( + + + {placeholder} + + {children} + + ) +} + export default MemoizedLeaf diff --git a/packages/slate-react/src/components/text.tsx b/packages/slate-react/src/components/text.tsx index 4d489e0c8..fd06ea476 100644 --- a/packages/slate-react/src/components/text.tsx +++ b/packages/slate-react/src/components/text.tsx @@ -4,12 +4,12 @@ import { Range, Element, Text as SlateText } from 'slate' import Leaf from './leaf' import { Leaf as SlateLeaf } from '../utils/leaf' import { ReactEditor, useEditor } from '..' +import { RenderDecorationProps, RenderMarkProps } from './editable' import { KEY_TO_ELEMENT, NODE_TO_ELEMENT, ELEMENT_TO_NODE, } from '../utils/weak-maps' -import { CustomDecorationProps, CustomMarkProps } from './custom' /** * Text. @@ -19,8 +19,8 @@ const Text = (props: { decorations: Range[] isLast: boolean parent: Element - renderDecoration?: (props: CustomDecorationProps) => JSX.Element - renderMark?: (props: CustomMarkProps) => JSX.Element + renderDecoration?: (props: RenderDecorationProps) => JSX.Element + renderMark?: (props: RenderMarkProps) => JSX.Element text: SlateText }) => { const { diff --git a/packages/slate-react/src/index.ts b/packages/slate-react/src/index.ts index 702b81c12..96afb3f55 100644 --- a/packages/slate-react/src/index.ts +++ b/packages/slate-react/src/index.ts @@ -1,4 +1,6 @@ export * from './components/editable' +export { DefaultElement } from './components/element' +export { DefaultMark, DefaultDecoration } from './components/leaf' export * from './hooks/use-editor' export * from './hooks/use-focused' export * from './hooks/use-read-only'