This commit is contained in:
bniwredyc 2023-05-04 19:38:50 +02:00
parent 0c849a99e9
commit 382da58af2
8 changed files with 45 additions and 25 deletions

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 11.01L1 11V13H23V11.01Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19 3H5V9H19V3ZM17 5H7V7H17V5Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19 15H5V21H19V15ZM17 17H7V19H17V17Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 375 B

View File

@ -39,7 +39,6 @@ import { TextBubbleMenu } from './TextBubbleMenu'
import { ImageBubbleMenu } from './ImageBubbleMenu' import { ImageBubbleMenu } from './ImageBubbleMenu'
import { EditorFloatingMenu } from './EditorFloatingMenu' import { EditorFloatingMenu } from './EditorFloatingMenu'
import { useEditorContext } from '../../context/editor' import { useEditorContext } from '../../context/editor'
import { isTextSelection } from '@tiptap/core'
type EditorProps = { type EditorProps = {
shoutId: number shoutId: number
@ -105,7 +104,11 @@ export const Editor = (props: EditorProps) => {
Bold, Bold,
Italic, Italic,
Strike, Strike,
HorizontalRule, HorizontalRule.configure({
HTMLAttributes: {
class: 'horizontalRule'
}
}),
Underline, Underline,
Link.configure({ Link.configure({
openOnClick: false openOnClick: false
@ -144,25 +147,17 @@ export const Editor = (props: EditorProps) => {
CharacterCount, CharacterCount,
BubbleMenu.configure({ BubbleMenu.configure({
pluginKey: 'textBubbleMenu', pluginKey: 'textBubbleMenu',
element: textBubbleMenuRef.current, element: textBubbleMenuRef.current
shouldShow: ({ editor: e, view, state, oldState, from, to }) => { // shouldShow: ({ editor: e, view, state, oldState, from, to }) => {
const { doc, selection } = state // console.log('!!! e:', view)
const { empty } = selection // return !e.isActive('image')
// }
const isEmptyTextBlock = doc.textBetween(from, to).length === 0 && isTextSelection(selection)
if (!view.hasFocus() || empty || isEmptyTextBlock || e.isActive('image')) {
return false
}
return true
}
}), }),
BubbleMenu.configure({ BubbleMenu.configure({
pluginKey: 'imageBubbleMenu', pluginKey: 'imageBubbleMenu',
element: imageBubbleMenuRef.current, element: imageBubbleMenuRef.current,
shouldShow: ({ editor: e, view, state, oldState, from, to }) => { shouldShow: ({ editor: e, view, state, oldState, from, to }) => {
return view.hasFocus() && e.isActive('image') return e.isFocused && e.isActive('image')
} }
}), }),
FloatingMenu.configure({ FloatingMenu.configure({

View File

@ -12,10 +12,10 @@
opacity: 1; opacity: 1;
} }
} }
.menuHolder { .menuHolder {
background: #fff; background: #fff;
left: calc(100% + 1rem); left: calc(100% + 1rem);
box-shadow: 0 4px 10px rgba(#000, 0.25);
position: absolute; position: absolute;
top: -0.8rem; top: -0.8rem;
min-width: 64vw; min-width: 64vw;

View File

@ -7,6 +7,7 @@ import HTMLParser from 'html-to-json-parser'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { Modal } from '../../Nav/Modal' import { Modal } from '../../Nav/Modal'
import { Menu } from './Menu' import { Menu } from './Menu'
import type { MenuItem } from './Menu/Menu'
import { showModal } from '../../../stores/ui' import { showModal } from '../../../stores/ui'
import { UploadModalContent } from '../UploadModal' import { UploadModalContent } from '../UploadModal'
@ -31,7 +32,7 @@ const validateEmbed = async (value) => {
export const EditorFloatingMenu = (props: FloatingMenuProps) => { export const EditorFloatingMenu = (props: FloatingMenuProps) => {
const { t } = useLocalize() const { t } = useLocalize()
const [selectedMenuItem, setSelectedMenuItem] = createSignal<string | null>(null) const [selectedMenuItem, setSelectedMenuItem] = createSignal<MenuItem | null>(null)
const [menuOpen, setMenuOpen] = createSignal<boolean>(false) const [menuOpen, setMenuOpen] = createSignal<boolean>(false)
const handleEmbedFormSubmit = async (value: string) => { const handleEmbedFormSubmit = async (value: string) => {
// TODO: add support instagram embed (blockquote) // TODO: add support instagram embed (blockquote)
@ -40,8 +41,15 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => {
} }
createEffect(() => { createEffect(() => {
if (selectedMenuItem() === 'image') { switch (selectedMenuItem()) {
case 'image': {
showModal('uploadImage') showModal('uploadImage')
return
}
case 'horizontal-rule': {
props.editor.chain().focus().setHorizontalRule().run()
return
}
} }
}) })
const closeUploadModalHandler = () => { const closeUploadModalHandler = () => {
@ -58,7 +66,7 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => {
<Show when={menuOpen()}> <Show when={menuOpen()}>
<div class={styles.menuHolder}> <div class={styles.menuHolder}>
<Show when={!selectedMenuItem()}> <Show when={!selectedMenuItem()}>
<Menu selectedItem={(value) => setSelectedMenuItem(value)} /> <Menu selectedItem={(value: MenuItem) => setSelectedMenuItem(value)} />
</Show> </Show>
<Show when={selectedMenuItem() === 'embed'}> <Show when={selectedMenuItem() === 'embed'}>
<InlineForm <InlineForm

View File

@ -1,19 +1,27 @@
import styles from './Menu.module.scss' import styles from './Menu.module.scss'
import { Icon } from '../../../_shared/Icon' import { Icon } from '../../../_shared/Icon'
export type MenuItem = 'image' | 'embed' | 'horizontal-rule'
type Props = { type Props = {
selectedItem: (value: string) => void selectedItem: (value: string) => void
} }
export const Menu = (props: Props) => { export const Menu = (props: Props) => {
const setSelectedMenuItem = (value: MenuItem) => {
props.selectedItem(value)
}
return ( return (
<div class={styles.Menu}> <div class={styles.Menu}>
<button type="button" onClick={() => props.selectedItem('image')}> <button type="button" onClick={() => setSelectedMenuItem('image')}>
<Icon class={styles.icon} name="editor-image" /> <Icon class={styles.icon} name="editor-image" />
</button> </button>
<button type="button" onClick={() => props.selectedItem('embed')}> <button type="button" onClick={() => setSelectedMenuItem('embed')}>
<Icon class={styles.icon} name="editor-embed" /> <Icon class={styles.icon} name="editor-embed" />
</button> </button>
<button type="button" onClick={() => setSelectedMenuItem('horizontal-rule')}>
<Icon class={styles.icon} name="editor-horizontal-rule" />
</button>
</div> </div>
) )
} }

View File

@ -68,3 +68,7 @@
display: block; display: block;
width: unset !important; width: unset !important;
} }
.horizontalRule {
border-top: 2px solid #000;
}

View File

@ -29,7 +29,7 @@ export const UploadModalContent = (props: Props) => {
.chain() .chain()
.focus() .focus()
.extendMarkRange('link') .extendMarkRange('link')
.setImage({ src: `/api/image?url=${src}` }) .setImage({ src: `https://new.discours.io/api/image?url=${src}` })
.run() .run()
hideModal() hideModal()
} }

View File

@ -677,7 +677,7 @@ figcaption {
.main-content { .main-content {
flex: 1 100%; flex: 1 100%;
min-height: 300px; min-height: 90vh;
padding-top: 120px; padding-top: 120px;
position: relative; position: relative;
} }