diff --git a/public/icons/editor-horizontal-rule.svg b/public/icons/editor-horizontal-rule.svg new file mode 100644 index 00000000..3349d421 --- /dev/null +++ b/public/icons/editor-horizontal-rule.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index 23e012ae..6c05cf40 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -39,7 +39,6 @@ import { TextBubbleMenu } from './TextBubbleMenu' import { ImageBubbleMenu } from './ImageBubbleMenu' import { EditorFloatingMenu } from './EditorFloatingMenu' import { useEditorContext } from '../../context/editor' -import { isTextSelection } from '@tiptap/core' type EditorProps = { shoutId: number @@ -105,7 +104,11 @@ export const Editor = (props: EditorProps) => { Bold, Italic, Strike, - HorizontalRule, + HorizontalRule.configure({ + HTMLAttributes: { + class: 'horizontalRule' + } + }), Underline, Link.configure({ openOnClick: false @@ -144,25 +147,17 @@ export const Editor = (props: EditorProps) => { CharacterCount, BubbleMenu.configure({ pluginKey: 'textBubbleMenu', - element: textBubbleMenuRef.current, - shouldShow: ({ editor: e, view, state, oldState, from, to }) => { - const { doc, selection } = state - const { empty } = selection - - const isEmptyTextBlock = doc.textBetween(from, to).length === 0 && isTextSelection(selection) - - if (!view.hasFocus() || empty || isEmptyTextBlock || e.isActive('image')) { - return false - } - - return true - } + element: textBubbleMenuRef.current + // shouldShow: ({ editor: e, view, state, oldState, from, to }) => { + // console.log('!!! e:', view) + // return !e.isActive('image') + // } }), BubbleMenu.configure({ pluginKey: 'imageBubbleMenu', element: imageBubbleMenuRef.current, shouldShow: ({ editor: e, view, state, oldState, from, to }) => { - return view.hasFocus() && e.isActive('image') + return e.isFocused && e.isActive('image') } }), FloatingMenu.configure({ diff --git a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.module.scss b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.module.scss index e6078156..83d6bdbd 100644 --- a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.module.scss +++ b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.module.scss @@ -12,10 +12,10 @@ opacity: 1; } } + .menuHolder { background: #fff; left: calc(100% + 1rem); - box-shadow: 0 4px 10px rgba(#000, 0.25); position: absolute; top: -0.8rem; min-width: 64vw; diff --git a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx index 23f916b9..30d91a07 100644 --- a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx +++ b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx @@ -7,6 +7,7 @@ import HTMLParser from 'html-to-json-parser' import { useLocalize } from '../../../context/localize' import { Modal } from '../../Nav/Modal' import { Menu } from './Menu' +import type { MenuItem } from './Menu/Menu' import { showModal } from '../../../stores/ui' import { UploadModalContent } from '../UploadModal' @@ -31,7 +32,7 @@ const validateEmbed = async (value) => { export const EditorFloatingMenu = (props: FloatingMenuProps) => { const { t } = useLocalize() - const [selectedMenuItem, setSelectedMenuItem] = createSignal(null) + const [selectedMenuItem, setSelectedMenuItem] = createSignal(null) const [menuOpen, setMenuOpen] = createSignal(false) const handleEmbedFormSubmit = async (value: string) => { // TODO: add support instagram embed (blockquote) @@ -40,8 +41,15 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => { } createEffect(() => { - if (selectedMenuItem() === 'image') { - showModal('uploadImage') + switch (selectedMenuItem()) { + case 'image': { + showModal('uploadImage') + return + } + case 'horizontal-rule': { + props.editor.chain().focus().setHorizontalRule().run() + return + } } }) const closeUploadModalHandler = () => { @@ -58,7 +66,7 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => {
- setSelectedMenuItem(value)} /> + setSelectedMenuItem(value)} /> void } export const Menu = (props: Props) => { + const setSelectedMenuItem = (value: MenuItem) => { + props.selectedItem(value) + } + return (
- - +
) } diff --git a/src/components/Editor/Prosemirror.scss b/src/components/Editor/Prosemirror.scss index 28885985..535d96f4 100644 --- a/src/components/Editor/Prosemirror.scss +++ b/src/components/Editor/Prosemirror.scss @@ -68,3 +68,7 @@ display: block; width: unset !important; } + +.horizontalRule { + border-top: 2px solid #000; +} diff --git a/src/components/Editor/UploadModal/UploadModalContent.tsx b/src/components/Editor/UploadModal/UploadModalContent.tsx index 7abd8424..8f2156fe 100644 --- a/src/components/Editor/UploadModal/UploadModalContent.tsx +++ b/src/components/Editor/UploadModal/UploadModalContent.tsx @@ -29,7 +29,7 @@ export const UploadModalContent = (props: Props) => { .chain() .focus() .extendMarkRange('link') - .setImage({ src: `/api/image?url=${src}` }) + .setImage({ src: `https://new.discours.io/api/image?url=${src}` }) .run() hideModal() } diff --git a/src/styles/app.scss b/src/styles/app.scss index 9a22667e..ee5b68f0 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -677,7 +677,7 @@ figcaption { .main-content { flex: 1 100%; - min-height: 300px; + min-height: 90vh; padding-top: 120px; position: relative; }