From fc0a4b1165af225d360c524a0e3232dfbbe78bc0 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 6 Jul 2023 01:53:42 -0700 Subject: [PATCH] Add extensions and implement ToolbarButton --- components/common/Editor/index.module.scss | 58 ++++-- components/common/Editor/index.tsx | 205 ++++++++++++++------- 2 files changed, 177 insertions(+), 86 deletions(-) diff --git a/components/common/Editor/index.module.scss b/components/common/Editor/index.module.scss index faebbf51..6be160ed 100644 --- a/components/common/Editor/index.module.scss +++ b/components/common/Editor/index.module.scss @@ -61,6 +61,44 @@ font-style: italic; } + ul { + padding: 0 $unit-2x; + list-style-type: disc; + } + + ol { + padding: 0 $unit-2x; + list-style-type: decimal; + } + + h1 { + font-size: $font-xlarge; + font-weight: $medium; + margin: $unit 0; + text-align: left; + } + + h2 { + font-size: $font-large; + font-weight: $medium; + margin: $unit 0; + text-align: left; + } + + h3 { + font-size: $font-regular; + font-weight: $medium; + margin: $unit 0; + text-align: left; + } + + mark { + border-radius: $item-corner-small; + background: var(--highlight-bg); + color: var(--highlight-text); + padding: 1px $unit-fourth; + } + iframe { background: var(--input-bound-bg); border-radius: $card-corner; @@ -180,26 +218,6 @@ padding: $unit; z-index: 10; - button { - background: var(--toolbar-item-bg); - border-radius: $bubble-menu-item-corner; - color: var(--toolbar-item-text); - font-weight: $medium; - font-size: $font-small; - padding: $unit-half $unit; - - &:hover { - background: var(--toolbar-item-bg-hover); - color: var(--toolbar-item-text-hover); - cursor: pointer; - } - - &.active { - background: var(--toolbar-item-bg-active); - color: var(--toolbar-item-text-active); - } - } - .divider { background: var(--toolbar-divider-bg); border-radius: $full-corner; diff --git a/components/common/Editor/index.tsx b/components/common/Editor/index.tsx index 29414555..f948614c 100644 --- a/components/common/Editor/index.tsx +++ b/components/common/Editor/index.tsx @@ -1,15 +1,29 @@ -import { ComponentProps, useCallback, useEffect, useState } from 'react' +import { ComponentProps, useCallback, useEffect } from 'react' import { useRouter } from 'next/router' -import { useEditor, Editor as TiptapEditor, EditorContent } from '@tiptap/react' +import { useEditor, EditorContent } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import Link from '@tiptap/extension-link' +import Highlight from '@tiptap/extension-highlight' +import Typography from '@tiptap/extension-typography' import Youtube from '@tiptap/extension-youtube' import CustomMention from '~extensions/CustomMention' import classNames from 'classnames' import { mentionSuggestionOptions } from '~utils/mentionSuggestions' import type { JSONContent } from '@tiptap/core' +import ToolbarButton from '~components/common/ToolbarButton' +import BoldIcon from 'remixicon-react/BoldIcon' +import ItalicIcon from 'remixicon-react/ItalicIcon' +import StrikethroughIcon from 'remixicon-react/StrikethroughIcon' +import UnorderedListIcon from 'remixicon-react/ListUnorderedIcon' +import OrderedListIcon from '~public/icons/remix/list-ordered-2.svg' +import PaintbrushIcon from 'remixicon-react/PaintbrushLineIcon' +import H1Icon from 'remixicon-react/H1Icon' +import H2Icon from 'remixicon-react/H2Icon' +import H3Icon from 'remixicon-react/H3Icon' +import LinkIcon from 'remixicon-react/LinkIcon' +import YoutubeIcon from 'remixicon-react/YoutubeLineIcon' import styles from './index.module.scss' interface Props extends ComponentProps<'div'> { @@ -30,7 +44,7 @@ const Editor = ({ const router = useRouter() const locale = router.locale || 'en' - const [editor, setEditor] = useState(undefined) + // const [editor, setEditor] = useState(undefined) function isJSON(content?: string) { if (!content) return false @@ -44,50 +58,57 @@ const Editor = ({ } useEffect(() => { - editor?.destroy() - const newEditor: TiptapEditor = new TiptapEditor({ - content: formatContent(content), - editable: editable, - editorProps: { - attributes: { - class: classNames( - { - [styles.editor]: true, - [styles.bound]: bound, - }, - className?.split(' ').map((c) => styles[c]) - ), - }, - }, - extensions: [ - StarterKit, - Link, - CustomMention.configure({ - renderLabel({ options, node }) { - return `${node.attrs.id.name[locale] ?? node.attrs.id.granblue_en}` - }, - suggestion: mentionSuggestionOptions, - HTMLAttributes: { - class: classNames({ - [styles.mention]: true, - }), - }, - }), - Youtube.configure({ - inline: false, - modestBranding: true, - interfaceLanguage: locale, - }), - ], - onUpdate: ({ editor }) => { - const json = editor.getJSON() - if (onUpdate) onUpdate(json) - }, - }) - - setEditor(newEditor) + // console.log('Recreating editor...') + // editor?.destroy() + // setEditor(newEditor) }, [content]) + const editor = useEditor({ + content: formatContent(content), + editable: editable, + editorProps: { + attributes: { + class: classNames( + { + [styles.editor]: true, + [styles.bound]: bound, + }, + className?.split(' ').map((c) => styles[c]) + ), + }, + }, + extensions: [ + StarterKit.configure({ + heading: { + levels: [1, 2, 3], + }, + }), + Link, + Highlight, + Typography, + CustomMention.configure({ + renderLabel({ options, node }) { + return `${node.attrs.id.name[locale] ?? node.attrs.id.granblue_en}` + }, + suggestion: mentionSuggestionOptions, + HTMLAttributes: { + class: classNames({ + [styles.mention]: true, + }), + }, + }), + Youtube.configure({ + inline: false, + modestBranding: true, + interfaceLanguage: locale, + }), + ], + onUpdate: ({ editor }) => { + const json = editor.getJSON() + if (onUpdate) onUpdate(json) + }, + }) + function formatContent(content?: string) { if (!content) return '' if (isJSON(content)) return JSON.parse(content) @@ -146,32 +167,84 @@ const Editor = ({
{editor && editable === true && ( )}