parent
ed85b75cc8
commit
8b114ea75f
|
@ -0,0 +1,4 @@
|
||||||
|
.LinkBubbleMenu {
|
||||||
|
background: var(--editor-bubble-menu-background);
|
||||||
|
box-shadow: 0 4px 10px rgba(#000, 0.25);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { Editor } from '@tiptap/core'
|
||||||
|
|
||||||
|
import { InsertLinkForm } from '../InsertLinkForm'
|
||||||
|
|
||||||
|
import styles from './LinkBubbleMenu.module.scss'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
editor: Editor
|
||||||
|
ref: (el: HTMLDivElement) => void
|
||||||
|
shouldShow: boolean
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LinkBubbleMenuModule = (props: Props) => {
|
||||||
|
return (
|
||||||
|
<div ref={props.ref} class={styles.LinkBubbleMenu}>
|
||||||
|
<InsertLinkForm editor={props.editor} onClose={props.onClose} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
1
src/components/Editor/LinkBubbleMenu/index.ts
Normal file
1
src/components/Editor/LinkBubbleMenu/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { LinkBubbleMenuModule } from './LinkBubbleMenu.module'
|
|
@ -31,7 +31,7 @@ import { Modal } from '../Nav/Modal'
|
||||||
|
|
||||||
import { Figcaption } from './extensions/Figcaption'
|
import { Figcaption } from './extensions/Figcaption'
|
||||||
import { Figure } from './extensions/Figure'
|
import { Figure } from './extensions/Figure'
|
||||||
import { InsertLinkForm } from './InsertLinkForm'
|
import { LinkBubbleMenuModule } from './LinkBubbleMenu'
|
||||||
import { TextBubbleMenu } from './TextBubbleMenu'
|
import { TextBubbleMenu } from './TextBubbleMenu'
|
||||||
import { UploadModalContent } from './UploadModalContent'
|
import { UploadModalContent } from './UploadModalContent'
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ export const MAX_DESCRIPTION_LIMIT = 400
|
||||||
const SimplifiedEditor = (props: Props) => {
|
const SimplifiedEditor = (props: Props) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const [counter, setCounter] = createSignal<number>()
|
const [counter, setCounter] = createSignal<number>()
|
||||||
|
const [shouldShowLinkBubbleMenu, setShouldShowLinkBubbleMenu] = createSignal(false)
|
||||||
const isCancelButtonVisible = createMemo(() => props.isCancelButtonVisible !== false)
|
const isCancelButtonVisible = createMemo(() => props.isCancelButtonVisible !== false)
|
||||||
const wrapperEditorElRef: {
|
const wrapperEditorElRef: {
|
||||||
current: HTMLElement
|
current: HTMLElement
|
||||||
|
@ -84,6 +84,12 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
current: null,
|
current: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const linkBubbleMenuRef: {
|
||||||
|
current: HTMLDivElement
|
||||||
|
} = {
|
||||||
|
current: null,
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
actions: { setEditor },
|
actions: { setEditor },
|
||||||
} = useEditorContext()
|
} = useEditorContext()
|
||||||
|
@ -129,6 +135,15 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
return view.hasFocus() && !empty
|
return view.hasFocus() && !empty
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
BubbleMenu.configure({
|
||||||
|
pluginKey: 'linkBubbleMenu',
|
||||||
|
element: linkBubbleMenuRef.current,
|
||||||
|
shouldShow: ({ state }) => {
|
||||||
|
const { selection } = state
|
||||||
|
const { empty } = selection
|
||||||
|
return !empty && shouldShowLinkBubbleMenu()
|
||||||
|
},
|
||||||
|
}),
|
||||||
ImageFigure,
|
ImageFigure,
|
||||||
Image,
|
Image,
|
||||||
Figcaption,
|
Figcaption,
|
||||||
|
@ -213,7 +228,7 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
|
|
||||||
if (event.code === 'KeyK' && (event.metaKey || event.ctrlKey) && !editor().state.selection.empty) {
|
if (event.code === 'KeyK' && (event.metaKey || event.ctrlKey) && !editor().state.selection.empty) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
showModal('simplifiedEditorInsertLink')
|
setShouldShowLinkBubbleMenu(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,8 +246,6 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleInsertLink = () => !editor().state.selection.empty && showModal('simplifiedEditorInsertLink')
|
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (html()) {
|
if (html()) {
|
||||||
setCounter(editor().storage.characterCount.characters())
|
setCounter(editor().storage.characterCount.characters())
|
||||||
|
@ -244,6 +257,10 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
'max-height': `${props.maxHeight}px`,
|
'max-height': `${props.maxHeight}px`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleShowLinkBubble = () => {
|
||||||
|
editor().chain().focus().run()
|
||||||
|
setShouldShowLinkBubbleMenu(true)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={(el) => (wrapperEditorElRef.current = el)}
|
ref={(el) => (wrapperEditorElRef.current = el)}
|
||||||
|
@ -294,7 +311,7 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
<button
|
<button
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleInsertLink}
|
onClick={handleShowLinkBubble}
|
||||||
class={clsx(styles.actionButton, { [styles.active]: isLink() })}
|
class={clsx(styles.actionButton, { [styles.active]: isLink() })}
|
||||||
>
|
>
|
||||||
<Icon name="editor-link" />
|
<Icon name="editor-link" />
|
||||||
|
@ -345,11 +362,6 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<Portal>
|
|
||||||
<Modal variant="narrow" name="simplifiedEditorInsertLink">
|
|
||||||
<InsertLinkForm editor={editor()} onClose={() => hideModal()} />
|
|
||||||
</Modal>
|
|
||||||
</Portal>
|
|
||||||
<Show when={props.imageEnabled}>
|
<Show when={props.imageEnabled}>
|
||||||
<Portal>
|
<Portal>
|
||||||
<Modal variant="narrow" name="simplifiedEditorUploadImage">
|
<Modal variant="narrow" name="simplifiedEditorUploadImage">
|
||||||
|
@ -369,6 +381,12 @@ const SimplifiedEditor = (props: Props) => {
|
||||||
ref={(el) => (textBubbleMenuRef.current = el)}
|
ref={(el) => (textBubbleMenuRef.current = el)}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
<LinkBubbleMenuModule
|
||||||
|
shouldShow={shouldShowLinkBubbleMenu()}
|
||||||
|
editor={editor()}
|
||||||
|
ref={(el) => (linkBubbleMenuRef.current = el)}
|
||||||
|
onClose={() => setShouldShowLinkBubbleMenu(false)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ export type ModalType =
|
||||||
| 'simplifiedEditorUploadImage'
|
| 'simplifiedEditorUploadImage'
|
||||||
| 'uploadCoverImage'
|
| 'uploadCoverImage'
|
||||||
| 'editorInsertLink'
|
| 'editorInsertLink'
|
||||||
| 'simplifiedEditorInsertLink'
|
|
||||||
| 'followers'
|
| 'followers'
|
||||||
| 'following'
|
| 'following'
|
||||||
|
|
||||||
|
@ -37,7 +36,6 @@ export const MODALS: Record<ModalType, ModalType> = {
|
||||||
simplifiedEditorUploadImage: 'simplifiedEditorUploadImage',
|
simplifiedEditorUploadImage: 'simplifiedEditorUploadImage',
|
||||||
uploadCoverImage: 'uploadCoverImage',
|
uploadCoverImage: 'uploadCoverImage',
|
||||||
editorInsertLink: 'editorInsertLink',
|
editorInsertLink: 'editorInsertLink',
|
||||||
simplifiedEditorInsertLink: 'simplifiedEditorInsertLink',
|
|
||||||
followers: 'followers',
|
followers: 'followers',
|
||||||
following: 'following',
|
following: 'following',
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user