From 618b21485322aac61329a67478a47938732a1ed6 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sat, 30 Apr 2022 11:52:49 +0300 Subject: [PATCH] feat: InsertImageModal, img cmd in TextEditor, Make AddComment Controlled --- .../InsertImageModal.stories.tsx | 17 ++++ .../InsertImageModal/InsertImageModal.tsx | 78 +++++++++++++++++++ .../Inputs/TextEditor/TextEditor.stories.tsx | 2 + .../Inputs/TextEditor/TextEditor.tsx | 2 +- .../Inputs/TextEditor/Toolbar/ToolButton.tsx | 43 +++++++++- .../Inputs/TextEditor/Toolbar/Toolbar.tsx | 3 +- .../Comments/AddComment/AddComment.tsx | 32 +++++--- .../ContentEditor/ContentEditor.tsx | 2 +- .../Components/ContentEditor/Toolbar.tsx | 3 +- .../CreatePostPage/CreatePostPage.stories.tsx | 4 + src/redux/features/modals.slice.ts | 2 + src/utils/storybook/decorators.tsx | 9 ++- 12 files changed, 180 insertions(+), 17 deletions(-) create mode 100644 src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.stories.tsx create mode 100644 src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.tsx diff --git a/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.stories.tsx b/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.stories.tsx new file mode 100644 index 0000000..bae58db --- /dev/null +++ b/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.stories.tsx @@ -0,0 +1,17 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import InsertImageModal from './InsertImageModal'; + +import { ModalsDecorator } from 'src/utils/storybook/decorators'; + +export default { + title: 'Shared/TextEditor/Insert Image Modal', + component: InsertImageModal, + + decorators: [ModalsDecorator] +} as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const Default = Template.bind({}); + diff --git a/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.tsx b/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.tsx new file mode 100644 index 0000000..816766a --- /dev/null +++ b/src/Components/Inputs/TextEditor/InsertImageModal/InsertImageModal.tsx @@ -0,0 +1,78 @@ +import React, { FormEvent, useState } from 'react' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { motion } from 'framer-motion' +import { IoClose } from 'react-icons/io5' +import Button from 'src/Components/Button/Button' + +interface Props extends ModalCard { + onInsert: (img: { src: string, alt?: string }) => void +} + +export default function InsertImageModal({ onClose, direction, onInsert, ...props }: Props) { + + const [urlInput, setUrlInput] = useState("") + const [altInput, setAltInput] = useState("") + + const handleSubmit = (e: FormEvent) => { + e.preventDefault() + if (urlInput.length > 10) { + onInsert({ src: urlInput, alt: altInput }) + onClose?.(); + } + } + + return ( + + +

Add Image

+
+
+
+

+ Image URL +

+
+ setUrlInput(e.target.value)} + placeholder='https://images.com/my-image' + /> +
+
+
+

+ Alt Text +

+
+ setAltInput(e.target.value)} + placeholder='' + /> +
+
+
+
+ + +
+
+ +
+ ) +} diff --git a/src/Components/Inputs/TextEditor/TextEditor.stories.tsx b/src/Components/Inputs/TextEditor/TextEditor.stories.tsx index 0eeed5c..8294d7d 100644 --- a/src/Components/Inputs/TextEditor/TextEditor.stories.tsx +++ b/src/Components/Inputs/TextEditor/TextEditor.stories.tsx @@ -1,10 +1,12 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; +import { WithModals } from 'src/utils/storybook/decorators'; import TextEditor from './TextEditor'; export default { title: 'Shared/TextEditor', + decorators: [WithModals], component: TextEditor, } as ComponentMeta; diff --git a/src/Components/Inputs/TextEditor/TextEditor.tsx b/src/Components/Inputs/TextEditor/TextEditor.tsx index 7462a77..7c08432 100644 --- a/src/Components/Inputs/TextEditor/TextEditor.tsx +++ b/src/Components/Inputs/TextEditor/TextEditor.tsx @@ -67,7 +67,7 @@ export default function TextEditor({ placeholder, initialContent }: Props) { new CodeBlockExtension({ supportedLanguages: [javascript, typescript] }), - new ImageExtension({ enableResizing: true }), + new ImageExtension(), // new TrailingNodeExtension(), // new TableExtension(), new MarkdownExtension({ copyAsMarkdown: false }), diff --git a/src/Components/Inputs/TextEditor/Toolbar/ToolButton.tsx b/src/Components/Inputs/TextEditor/Toolbar/ToolButton.tsx index 4ec54b7..a1b98bd 100644 --- a/src/Components/Inputs/TextEditor/Toolbar/ToolButton.tsx +++ b/src/Components/Inputs/TextEditor/Toolbar/ToolButton.tsx @@ -1,6 +1,6 @@ import { useActive, useChainedCommands, useCommands } from '@remirror/react'; import { FiBold, FiItalic, FiType, FiUnderline, FiAlignCenter, FiAlignLeft, FiAlignRight, FiCode } from 'react-icons/fi' -import { FaListOl, FaListUl, FaUndo, FaRedo } from 'react-icons/fa' +import { FaListOl, FaListUl, FaUndo, FaRedo, FaImage } from 'react-icons/fa' import { Menu, @@ -10,6 +10,8 @@ import { import '@szhsin/react-menu/dist/index.css'; import '@szhsin/react-menu/dist/transitions/slide.css'; import { BiCodeCurly } from 'react-icons/bi'; +import { useAppDispatch } from 'src/utils/hooks'; +import { openModal } from 'src/redux/features/modals.slice'; interface Props { cmd: Command @@ -32,6 +34,7 @@ export default function ToolButton({ cmd: _cmd, classes }: Props) { const commands = useCommands(); const active = useActive(); + const dispatch = useAppDispatch() // const chain = useChainedCommands(); // commands.toggleCo @@ -71,6 +74,38 @@ export default function ToolButton({ cmd: _cmd, classes }: Props) { } + if (_cmd === 'img') { + const { activeCmd, cmd, tip, Icon } = cmdToBtn[_cmd]; + const onClick = () => { + dispatch(openModal({ + Modal: "InsertImageModal", + props: { + onInsert: ({ src, alt }) => { + commands.insertImage({ + src, + alt, + + }) + } + } + })) + } + + return ( + + ) + } if (isCommand(_cmd)) { const { activeCmd, cmd, tip, Icon } = cmdToBtn[_cmd] @@ -176,6 +211,12 @@ const cmdToBtn = { tip: "Code Block", Icon: BiCodeCurly, }, + img: { + cmd: 'insertImage', + activeCmd: 'image', + tip: "Insert Image", + Icon: FaImage, + }, } as const diff --git a/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx b/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx index 3860427..e8d56bc 100644 --- a/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx +++ b/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx @@ -11,7 +11,7 @@ export default function Toolbar() { return ( -
+
@@ -26,6 +26,7 @@ export default function Toolbar() { +
diff --git a/src/features/Posts/Components/Comments/AddComment/AddComment.tsx b/src/features/Posts/Components/Comments/AddComment/AddComment.tsx index 925cd3e..1c5870f 100644 --- a/src/features/Posts/Components/Comments/AddComment/AddComment.tsx +++ b/src/features/Posts/Components/Comments/AddComment/AddComment.tsx @@ -14,11 +14,12 @@ import { PlaceholderExtension, } from 'remirror/extensions'; import { EditorComponent, Remirror, useRemirror } from '@remirror/react'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import TextEditorComponents from 'src/Components/Inputs/TextEditor'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Toolbar from './Toolbar'; import Button from 'src/Components/Button/Button'; +import { debounce } from 'remirror'; interface Props { @@ -38,6 +39,8 @@ export default function AddComment({ initialContent, name }: Props) { return extension; }, []); + const valueRef = useRef(""); + const extensions = useCallback( () => [ @@ -60,33 +63,40 @@ export default function AddComment({ initialContent, name }: Props) { ); - const { manager } = useRemirror({ + const { manager, state, onChange, } = useRemirror({ extensions, stringHandler: 'markdown', + content: initialContent ?? '' }); + const submitComment = () => { + console.log(valueRef.current); + manager.view.updateState(manager.createState({ content: manager.createEmptyDoc() })) + } + + return (
{ + const markdown = e.helpers.getMarkdown(e.state) + valueRef.current = markdown; + onChange(e); + }} >
- {/*