From c31f360d4b1a043c52a1ea2665483ad4fb99fd1b Mon Sep 17 00:00:00 2001 From: Rajendrasinh Parmar Date: Fri, 18 Mar 2022 18:41:57 +0530 Subject: [PATCH] Add slate editor with read only support --- .../components/TextEditor/BlockButton.tsx | 83 +++++++++++ .../TextEditor/ContainerElement.tsx | 29 ++++ .../components/TextEditor/EditorMenu.tsx | 16 +++ .../components/TextEditor/EditorToolbar.tsx | 16 +++ .../components/TextEditor/LeafElement.tsx | 25 ++++ .../components/TextEditor/MarkButton.tsx | 57 ++++++++ .../components/TextEditor/TextEditor.tsx | 131 ++++++++++++++++++ .../components/TextEditor/index.tsx | 2 + .../TextEditor/menuItems/BulletedList.tsx | 19 +++ .../TextEditor/menuItems/NumberedList.tsx | 19 +++ .../TextEditor/menuItems/TextBlockQuote.tsx | 19 +++ .../TextEditor/menuItems/TextBold.tsx | 19 +++ .../TextEditor/menuItems/TextCode.tsx | 19 +++ .../TextEditor/menuItems/TextHeader1.tsx | 19 +++ .../TextEditor/menuItems/TextHeader2.tsx | 19 +++ .../TextEditor/menuItems/TextHeader3.tsx | 19 +++ .../TextEditor/menuItems/TextItalic.tsx | 19 +++ .../TextEditor/menuItems/TextUnderline.tsx | 19 +++ .../components/TextEditor/menuItems/index.tsx | 10 ++ .../components/TextEditor/menuItems/style.ts | 20 +++ .../components/TextEditor/style.ts | 39 ++++++ packages/orca-frontend/package.json | 4 + yarn.lock | 77 +++++++++- 23 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 packages/orca-frontend/components/TextEditor/BlockButton.tsx create mode 100644 packages/orca-frontend/components/TextEditor/ContainerElement.tsx create mode 100644 packages/orca-frontend/components/TextEditor/EditorMenu.tsx create mode 100644 packages/orca-frontend/components/TextEditor/EditorToolbar.tsx create mode 100644 packages/orca-frontend/components/TextEditor/LeafElement.tsx create mode 100644 packages/orca-frontend/components/TextEditor/MarkButton.tsx create mode 100644 packages/orca-frontend/components/TextEditor/TextEditor.tsx create mode 100644 packages/orca-frontend/components/TextEditor/index.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/BulletedList.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/NumberedList.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextBlockQuote.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextBold.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextCode.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextHeader1.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextHeader2.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextHeader3.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextItalic.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/TextUnderline.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/index.tsx create mode 100644 packages/orca-frontend/components/TextEditor/menuItems/style.ts create mode 100644 packages/orca-frontend/components/TextEditor/style.ts diff --git a/packages/orca-frontend/components/TextEditor/BlockButton.tsx b/packages/orca-frontend/components/TextEditor/BlockButton.tsx new file mode 100644 index 00000000..9fa2510d --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/BlockButton.tsx @@ -0,0 +1,83 @@ +import { FC } from 'react'; +import { Editor, Element as SlateElement, Transforms } from 'slate'; +import { useSlate } from 'slate-react'; +import { BulletedList, NumberedList, TextBlockQuote, TextHeader1, TextHeader2, TextHeader3 } from './menuItems'; +import { StyledEditorButton } from './style'; + +interface BlockButtonProps { + format: string; +} + +const LIST_TYPES = ['numbered-list', 'bulleted-list']; + +const isBlockActive = (editor: Editor, format: string) => { + const { selection } = editor; + if (!selection) return false; + + const [match] = Array.from( + Editor.nodes(editor, { + at: Editor.unhangRange(editor, selection), + match: (n) => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === format, + }) + ); + + return !!match; +}; + +const toggleBlock = (editor, format) => { + const isActive = isBlockActive(editor, format); + const isList = LIST_TYPES.includes(format); + + Transforms.unwrapNodes(editor, { + match: (n) => !Editor.isEditor(n) && SlateElement.isElement(n) && LIST_TYPES.includes(n.type), + split: true, + }); + const newProperties: Partial = { + type: isActive ? 'paragraph' : isList ? 'list-item' : format, + }; + Transforms.setNodes(editor, newProperties); + + if (!isActive && isList) { + const block = { type: format, children: [] }; + Transforms.wrapNodes(editor, block); + } +}; + +const BlockButton: FC = ({ format }) => { + const editor = useSlate(); + + let MenuItemComponent; + switch (format) { + case 'heading-one': + MenuItemComponent = TextHeader1; + break; + case 'heading-two': + MenuItemComponent = TextHeader2; + break; + case 'heading-three': + MenuItemComponent = TextHeader3; + break; + case 'block-quote': + MenuItemComponent = TextBlockQuote; + break; + case 'bulleted-list': + MenuItemComponent = BulletedList; + break; + case 'numbered-list': + MenuItemComponent = NumberedList; + break; + } + + return ( + { + event.preventDefault(); + toggleBlock(editor, format); + }} + > + + + ); +}; + +export default BlockButton; diff --git a/packages/orca-frontend/components/TextEditor/ContainerElement.tsx b/packages/orca-frontend/components/TextEditor/ContainerElement.tsx new file mode 100644 index 00000000..bc41d1c3 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/ContainerElement.tsx @@ -0,0 +1,29 @@ +import { FC } from 'react'; +import { RenderElementProps } from 'slate-react'; +import Linkify from '../Linkify'; +import { StyledBlockQuote } from './style'; + +export const ContainerElement: FC = ({ attributes, children, element }) => { + switch (element.type) { + case 'block-quote': + return ( + + {children} + + ); + case 'bulleted-list': + return
    {children}
; + case 'heading-one': + return

{children}

; + case 'heading-two': + return

{children}

; + case 'heading-three': + return

{children}

; + case 'list-item': + return
  • {children}
  • ; + case 'numbered-list': + return
      {children}
    ; + default: + return

    {children}

    ; + } +}; diff --git a/packages/orca-frontend/components/TextEditor/EditorMenu.tsx b/packages/orca-frontend/components/TextEditor/EditorMenu.tsx new file mode 100644 index 00000000..81c6d313 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/EditorMenu.tsx @@ -0,0 +1,16 @@ +import React, { ForwardRefRenderFunction, forwardRef } from 'react'; +import { StyledEditorMenu } from './style'; + +interface EditorMenuProps { + children: React.ReactNode; +} + +const EditorMenu: ForwardRefRenderFunction = ({ children, ...props }, ref) => { + return ( + + {children} + + ); +}; + +export default forwardRef(EditorMenu); diff --git a/packages/orca-frontend/components/TextEditor/EditorToolbar.tsx b/packages/orca-frontend/components/TextEditor/EditorToolbar.tsx new file mode 100644 index 00000000..05846de9 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/EditorToolbar.tsx @@ -0,0 +1,16 @@ +import React, { ForwardRefRenderFunction, forwardRef } from 'react'; +import EditorMenu from './EditorMenu'; + +interface EditorToolbarProps { + children: React.ReactNode; +} + +const EditorToolbar: ForwardRefRenderFunction = ({ children, ...props }, ref) => { + return ( + + {children} + + ); +}; + +export default forwardRef(EditorToolbar); diff --git a/packages/orca-frontend/components/TextEditor/LeafElement.tsx b/packages/orca-frontend/components/TextEditor/LeafElement.tsx new file mode 100644 index 00000000..0c9cb92f --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/LeafElement.tsx @@ -0,0 +1,25 @@ +import { FC } from 'react'; +import { StyledCodeBlock } from './style'; +import { CustomRenderLeafProps } from './TextEditor'; + +const LeafElement: FC = ({ attributes, children, leaf }) => { + if (leaf.bold) { + children = {children}; + } + + if (leaf.code) { + children = {children}; + } + + if (leaf.italic) { + children = {children}; + } + + if (leaf.underline) { + children = {children}; + } + + return {children}; +}; + +export default LeafElement; diff --git a/packages/orca-frontend/components/TextEditor/MarkButton.tsx b/packages/orca-frontend/components/TextEditor/MarkButton.tsx new file mode 100644 index 00000000..96e8799f --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/MarkButton.tsx @@ -0,0 +1,57 @@ +import { FC } from 'react'; +import { Editor } from 'slate'; +import { useSlate } from 'slate-react'; +import { TextBold, TextCode, TextItalic, TextUnderline } from './menuItems'; +import { StyledEditorButton } from './style'; + +interface MarkButtonProps { + format: string; +} + +const isMarkActive = (editor: Editor, format: string) => { + const marks = Editor.marks(editor); + return marks ? marks[format] === true : false; +}; + +export const toggleMark = (editor: Editor, format: string) => { + const isActive = isMarkActive(editor, format); + + if (isActive) { + Editor.removeMark(editor, format); + } else { + Editor.addMark(editor, format, true); + } +}; + +const MarkButton: FC = ({ format }) => { + const editor = useSlate(); + + let MenuItemComponent; + switch (format) { + case 'bold': + MenuItemComponent = TextBold; + break; + case 'italic': + MenuItemComponent = TextItalic; + break; + case 'underline': + MenuItemComponent = TextUnderline; + break; + case 'code': + MenuItemComponent = TextCode; + break; + } + + return ( + { + event.preventDefault(); + toggleMark(editor, format); + }} + > + + + ); +}; + +export default MarkButton; diff --git a/packages/orca-frontend/components/TextEditor/TextEditor.tsx b/packages/orca-frontend/components/TextEditor/TextEditor.tsx new file mode 100644 index 00000000..92b88fea --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/TextEditor.tsx @@ -0,0 +1,131 @@ +import React, { useCallback, useMemo, useState, FC } from 'react'; +import { Editable, withReact, Slate, ReactEditor } from 'slate-react'; +import isHotkey from 'is-hotkey'; +import { createEditor, Descendant, BaseEditor, Editor } from 'slate'; +import EditorToolbar from './EditorToolbar'; +import { StyledDivider } from './style'; +import BlockButton from './BlockButton'; +import MarkButton, { toggleMark } from './MarkButton'; +import { ContainerElement } from './ContainerElement'; +import LeafElement from './LeafElement'; + +declare module 'slate' { + interface CustomTypes { + Editor: BaseEditor & ReactEditor; + Element: CustomElement; + Text: CustomText; + } +} + +const HOTKEYS = { + 'mod+b': 'bold', + 'mod+i': 'italic', + 'mod+u': 'underline', + 'mod+`': 'code', +}; + +type CustomElementTypes = + | 'paragraph' + | 'block-quote' + | 'bulleted-list' + | 'heading-one' + | 'heading-two' + | 'heading-three' + | 'list-item' + | 'numbered-list'; +type CustomText = { + text?: string; + bold?: boolean; + code?: boolean; + italic?: boolean; + underline?: boolean; + type?: CustomElementTypes; + children?: CustomText[]; +}; + +export type CustomElement = { type: CustomElementTypes; children: CustomText[] }; + +export interface CustomRenderLeafProps { + children: any; + leaf: CustomText; + text: Text; + attributes: { + 'data-slate-leaf': true; + }; +} + +interface TextEditorProps { + isReadOnly?: boolean; + placeholderText?: string; + name?: string; + post?: CustomElement[]; + [x: string]: any; +} + +const initialValue: CustomElement[] = [ + { + type: 'paragraph', + children: [{ text: '' }], + }, +]; + +const TextEditor: FC = ({ isReadOnly, placeholderText, post, name, onChange }) => { + const [value, setValue] = useState(post); + const renderElement = useCallback((props) => , []); + const renderLeaf = useCallback((props) => , []); + const editor = useMemo(() => withReact(createEditor()), []); + + const handleChange = (value) => { + console.log(Editor.hasTexts(editor, initialValue[0])); + setValue(value); + if (onChange) { + onChange(name, value); + } + }; + + return ( + !isReadOnly && handleChange(value)}> + {!isReadOnly && ( + + + + + + + + + + + + + + + )} + { + for (const hotkey in HOTKEYS) { + if (isHotkey(hotkey, event as any)) { + event.preventDefault(); + const mark = HOTKEYS[hotkey]; + toggleMark(editor, mark); + } + } + }} + /> + + ); +}; + +TextEditor.defaultProps = { + isReadOnly: false, + post: initialValue, + name: 'post', +}; + +export default TextEditor; diff --git a/packages/orca-frontend/components/TextEditor/index.tsx b/packages/orca-frontend/components/TextEditor/index.tsx new file mode 100644 index 00000000..64e7fb0b --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/index.tsx @@ -0,0 +1,2 @@ +export { default } from './TextEditor'; +export type { CustomElement } from './TextEditor'; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/BulletedList.tsx b/packages/orca-frontend/components/TextEditor/menuItems/BulletedList.tsx new file mode 100644 index 00000000..71f1baa0 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/BulletedList.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface BulletedListProps { + width?: string; + active?: boolean; +} + +const BulletedList: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default BulletedList; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/NumberedList.tsx b/packages/orca-frontend/components/TextEditor/menuItems/NumberedList.tsx new file mode 100644 index 00000000..3d1f7a74 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/NumberedList.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface NumberedListProps { + width?: string; + active?: boolean; +} + +const NumberedList: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default NumberedList; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextBlockQuote.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextBlockQuote.tsx new file mode 100644 index 00000000..64410e5f --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextBlockQuote.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextBlockQuoteProps { + width?: string; + active?: boolean; +} + +const TextBlockQuote: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextBlockQuote; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextBold.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextBold.tsx new file mode 100644 index 00000000..5f91db7b --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextBold.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextBoldProps { + width?: string; + active?: boolean; +} + +const TextBold: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextBold; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextCode.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextCode.tsx new file mode 100644 index 00000000..dc9d3241 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextCode.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextCodeProps { + width?: string; + active?: boolean; +} + +const TextCode: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextCode; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextHeader1.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader1.tsx new file mode 100644 index 00000000..4a5713c7 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader1.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextHeader1Props { + width?: string; + active?: boolean; +} + +const TextHeader1: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextHeader1; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextHeader2.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader2.tsx new file mode 100644 index 00000000..acffd181 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader2.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextHeader2Props { + width?: string; + active?: boolean; +} + +const TextHeader2: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextHeader2; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextHeader3.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader3.tsx new file mode 100644 index 00000000..7afb83f5 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextHeader3.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextHeader3Props { + width?: string; + active?: boolean; +} + +const TextHeader3: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextHeader3; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextItalic.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextItalic.tsx new file mode 100644 index 00000000..bfc7240d --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextItalic.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextItalicProps { + width?: string; + active?: boolean; +} + +const TextItalic: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextItalic; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/TextUnderline.tsx b/packages/orca-frontend/components/TextEditor/menuItems/TextUnderline.tsx new file mode 100644 index 00000000..c8da80df --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/TextUnderline.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { StyledMenuItem } from './style'; + +interface TextUnderlineProps { + width?: string; + active?: boolean; +} + +const TextUnderline: FC = ({ width, active }) => { + const DEFAULT_WIDTH = '20'; + + return ( + + + + ); +}; + +export default TextUnderline; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/index.tsx b/packages/orca-frontend/components/TextEditor/menuItems/index.tsx new file mode 100644 index 00000000..97189581 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/index.tsx @@ -0,0 +1,10 @@ +export { default as TextHeader1 } from './TextHeader1'; +export { default as TextHeader2 } from './TextHeader2'; +export { default as TextHeader3 } from './TextHeader3'; +export { default as TextBlockQuote } from './TextBlockQuote'; +export { default as TextBold } from './TextBold'; +export { default as TextItalic } from './TextItalic'; +export { default as TextUnderline } from './TextUnderline'; +export { default as TextCode } from './TextCode'; +export { default as NumberedList } from './NumberedList'; +export { default as BulletedList } from './BulletedList'; diff --git a/packages/orca-frontend/components/TextEditor/menuItems/style.ts b/packages/orca-frontend/components/TextEditor/menuItems/style.ts new file mode 100644 index 00000000..4ed3c032 --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/menuItems/style.ts @@ -0,0 +1,20 @@ +import styled from 'styled-components'; + +interface StyledMenuItemProps { + active: boolean; + width: number; +} + +export const StyledMenuItem = styled.svg.attrs((props: StyledMenuItemProps) => ({ + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + xmlnsXlink: 'http://www.w3.org/1999/xlink', + viewBox: '0 0 24 24', + 'aria-hidden': true, + role: 'img', + preserveAspectRatio: 'xMidYMid meet', + active: props.active ? props.active : false, +}))` + width: ${(p) => p.width}px; + fill: ${(p) => (p.active ? p.theme.colors.general.primary : p.theme.colors.grey[50])}; +`; diff --git a/packages/orca-frontend/components/TextEditor/style.ts b/packages/orca-frontend/components/TextEditor/style.ts new file mode 100644 index 00000000..39a84a4f --- /dev/null +++ b/packages/orca-frontend/components/TextEditor/style.ts @@ -0,0 +1,39 @@ +import styled from 'styled-components'; + +export const StyledEditorButton = styled.span` + cursor: pointer; + display: inline-block; + width: 28px; + height: 28px; + padding: 4px; +`; + +export const StyledEditorMenu = styled.div` + position: relative; + padding: ${(p) => p.theme.spacing.xxs}; + border-bottom: 2px solid ${(p) => p.theme.colors.border.light}; + margin-bottom: ${(p) => p.theme.spacing.sm}; +`; + +export const StyledBlockQuote = styled.blockquote` + border-left: 2px solid #ddd; + margin-left: 0; + margin-right: 0; + padding-left: 10px; + color: #aaa; + font-style: italic; +`; + +export const StyledCodeBlock = styled.code` + font-family: monospace; + background-color: #eee; + padding: 3px; +`; + +export const StyledDivider = styled.span` + display: inline-block; + width: 2px; + background-color: ${(p) => p.theme.colors.grey[40]}; + margin: 0 10px; + height: 24px; +`; diff --git a/packages/orca-frontend/package.json b/packages/orca-frontend/package.json index ef119281..4251a6b9 100644 --- a/packages/orca-frontend/package.json +++ b/packages/orca-frontend/package.json @@ -18,6 +18,7 @@ "dependencies": { "axios": "^0.21.1", "deepmerge": "^4.2.2", + "is-hotkey": "^0.2.0", "linkify-it": "^3.0.3", "next": "^11.0.1", "nprogress": "^0.2.0", @@ -29,11 +30,14 @@ "react-redux": "^7.2.2", "react-share": "^4.4.0", "redux": "^4.0.5", + "slate": "^0.72.8", + "slate-react": "^0.72.9", "socket.io-client": "^3.1.1", "styled-components": "^5.3.0", "uuid": "^8.3.2" }, "devDependencies": { + "@types/is-hotkey": "^0.1.7", "@types/linkify-it": "^3.0.2", "@types/lodash": "^4.14.166", "@types/node": "^14.14.36", diff --git a/yarn.lock b/yarn.lock index 9f753ed5..b7047777 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1322,6 +1322,11 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/is-hotkey@^0.1.1", "@types/is-hotkey@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@types/is-hotkey/-/is-hotkey-0.1.7.tgz#30ec6d4234895230b576728ef77e70a52962f3b3" + integrity sha512-yB5C7zcOM7idwYZZ1wKQ3pTfjA9BbvFqRWvKB46GFddxnJtHwi/b9y84ykQtxQPg5qhdpg4Q/kWU3EGoCTmLzQ== + "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1337,6 +1342,11 @@ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9" integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA== +"@types/lodash@^4.14.149": + version "4.14.178" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" + integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== + "@types/lodash@^4.14.166": version "4.14.175" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.175.tgz#b78dfa959192b01fae0ad90e166478769b215f45" @@ -2770,6 +2780,11 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" +compute-scroll-into-view@^1.0.17: + version "1.0.17" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" + integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3397,6 +3412,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +direction@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/direction/-/direction-1.0.4.tgz#2b86fb686967e987088caf8b89059370d4837442" + integrity sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ== + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -4956,6 +4976,11 @@ image-size@1.0.0: dependencies: queue "6.0.2" +immer@^9.0.6: + version "9.0.12" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" + integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -5274,6 +5299,16 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hotkey@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/is-hotkey/-/is-hotkey-0.1.8.tgz#6b1f4b2d0e5639934e20c05ed24d623a21d36d25" + integrity sha512-qs3NZ1INIS+H+yeo7cD9pDfwYV/jqRh1JG9S9zYrNudkoUQg7OL7ziXqRKu+InFjUIDoP2o6HIkLYMh1pcWgyQ== + +is-hotkey@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-hotkey/-/is-hotkey-0.2.0.tgz#1835a68171a91e5c9460869d96336947c8340cef" + integrity sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + is-nan@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" @@ -5906,7 +5941,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8368,6 +8403,13 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +scroll-into-view-if-needed@^2.2.20: + version "2.2.29" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" + integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== + dependencies: + compute-scroll-into-view "^1.0.17" + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -8522,6 +8564,29 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slate-react@^0.72.9: + version "0.72.9" + resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.72.9.tgz#b05dd533bd29dd2d4796b614a8d8e01f214bb714" + integrity sha512-FEsqB+D1R/h+w1eCtHH367Krw2X7vju2GjMRL/d0bUiCRXlV50J9I9TJizvi7aaZyqBY8BypCuIiq9nNmsulCA== + dependencies: + "@types/is-hotkey" "^0.1.1" + "@types/lodash" "^4.14.149" + direction "^1.0.3" + is-hotkey "^0.1.6" + is-plain-object "^5.0.0" + lodash "^4.17.4" + scroll-into-view-if-needed "^2.2.20" + tiny-invariant "1.0.6" + +slate@^0.72.8: + version "0.72.8" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.72.8.tgz#5a018edf24e45448655293a68bfbcf563aa5ba81" + integrity sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + dependencies: + immer "^9.0.6" + is-plain-object "^5.0.0" + tiny-warning "^1.0.3" + slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -9274,6 +9339,16 @@ timers-browserify@2.0.12, timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-invariant@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" + integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"