-
+
Link text:
{linkText}
-
+
+
+
)
}
diff --git a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/MobileToolbarPlugin.tsx b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx
similarity index 57%
rename from packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/MobileToolbarPlugin.tsx
rename to packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx
index 11396e8b906..9279de287bc 100644
--- a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/MobileToolbarPlugin.tsx
+++ b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/ToolbarPlugin.tsx
@@ -18,8 +18,8 @@ import {
UNDO_COMMAND,
} from 'lexical'
import { mergeRegister } from '@lexical/utils'
-import { $isLinkNode, $isAutoLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link'
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link'
+import { ComponentPropsWithoutRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { GetAlignmentBlocks } from '../Blocks/Alignment'
import { GetBulletedListBlock } from '../Blocks/BulletedList'
import { GetChecklistBlock } from '../Blocks/Checklist'
@@ -37,25 +37,65 @@ import { GetQuoteBlock } from '../Blocks/Quote'
import { GetTableBlock } from '../Blocks/Table'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { classNames } from '@standardnotes/snjs'
-import { SUPER_TOGGLE_SEARCH } from '@standardnotes/ui-services'
+import { SUPER_TOGGLE_SEARCH, SUPER_TOGGLE_TOOLBAR } from '@standardnotes/ui-services'
import { useApplication } from '@/Components/ApplicationProvider'
import { GetRemoteImageBlock } from '../Blocks/RemoteImage'
import { InsertRemoteImageDialog } from '../RemoteImagePlugin/RemoteImagePlugin'
-import LinkEditor from '../LinkEditor/LinkEditor'
+import LinkEditor from './ToolbarLinkEditor'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants'
import { useSelectedTextFormatInfo } from './useSelectedTextFormatInfo'
import StyledTooltip from '@/Components/StyledTooltip/StyledTooltip'
+import LinkTextEditor, { $isLinkTextNode } from './ToolbarLinkTextEditor'
+import { Toolbar, ToolbarItem, useToolbarStore } from '@ariakit/react'
-const MobileToolbarPlugin = () => {
+interface ToolbarButtonProps extends ComponentPropsWithoutRef<'button'> {
+ name: string
+ active?: boolean
+ iconName: string
+ onSelect: () => void
+}
+
+const ToolbarButton = ({ name, active, iconName, onSelect, disabled, ...props }: ToolbarButtonProps) => {
+ const [editor] = useLexicalComposerContext()
+
+ return (
+
+ {
+ event.preventDefault()
+ onSelect()
+ }}
+ onContextMenu={(event) => {
+ editor.focus()
+ event.preventDefault()
+ }}
+ disabled={disabled}
+ {...props}
+ >
+
+
+
+
+
+ )
+}
+
+const ToolbarPlugin = () => {
const application = useApplication()
const [editor] = useLexicalComposerContext()
const [modal, showModal] = useModal()
const [isInEditor, setIsInEditor] = useState(false)
- const [isInLinkEditor, setIsInLinkEditor] = useState(false)
const [isInToolbar, setIsInToolbar] = useState(false)
const isMobile = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
+ const containerRef = useRef
(null)
const toolbarRef = useRef(null)
const linkEditorRef = useRef(null)
const backspaceButtonRef = useRef(null)
@@ -77,9 +117,19 @@ const MobileToolbarPlugin = () => {
}
}, [editor])
- const { isBold, isItalic, isUnderline, isSubscript, isSuperscript, isStrikethrough, blockType, isHighlighted } =
- useSelectedTextFormatInfo()
- const [isSelectionLink, setIsSelectionLink] = useState(false)
+ const {
+ isBold,
+ isItalic,
+ isUnderline,
+ isSubscript,
+ isSuperscript,
+ isStrikethrough,
+ blockType,
+ isHighlighted,
+ isLink,
+ isLinkText,
+ isAutoLink,
+ } = useSelectedTextFormatInfo()
const [canUndo, setCanUndo] = useState(false)
const [canRedo, setCanRedo] = useState(false)
@@ -193,7 +243,7 @@ const MobileToolbarPlugin = () => {
insertLink()
})
},
- active: isSelectionLink,
+ active: isLink,
},
{
name: 'Search',
@@ -205,6 +255,7 @@ const MobileToolbarPlugin = () => {
GetParagraphBlock(editor),
...GetHeadingsBlocks(editor),
...GetIndentOutdentBlocks(editor),
+ ...GetAlignmentBlocks(editor),
GetTableBlock(() =>
showModal('Insert Table', (onClose) => ),
),
@@ -218,7 +269,6 @@ const MobileToolbarPlugin = () => {
GetCodeBlock(editor),
GetDividerBlock(editor),
...GetDatetimeBlocks(editor),
- ...GetAlignmentBlocks(editor),
...[GetPasswordBlock(editor)],
GetCollapsibleBlock(editor),
...GetEmbedsBlocks(editor),
@@ -233,7 +283,7 @@ const MobileToolbarPlugin = () => {
isBold,
isHighlighted,
isItalic,
- isSelectionLink,
+ isLink,
isStrikethrough,
isSubscript,
isSuperscript,
@@ -243,41 +293,14 @@ const MobileToolbarPlugin = () => {
)
useEffect(() => {
+ const container = containerRef.current
const rootElement = editor.getRootElement()
if (!rootElement) {
return
}
- const handleFocus = () => setIsInEditor(true)
- const handleBlur = (event: FocusEvent) => {
- const elementToBeFocused = event.relatedTarget as Node
- const toolbarContainsElementToFocus = toolbarRef.current && toolbarRef.current.contains(elementToBeFocused)
- const linkEditorContainsElementToFocus =
- linkEditorRef.current &&
- (linkEditorRef.current.contains(elementToBeFocused) || elementToBeFocused === linkEditorRef.current)
- const willFocusBackspaceButton = backspaceButtonRef.current && elementToBeFocused === backspaceButtonRef.current
- if (toolbarContainsElementToFocus || linkEditorContainsElementToFocus || willFocusBackspaceButton) {
- return
- }
- setIsInEditor(false)
- }
-
- rootElement.addEventListener('focus', handleFocus)
- rootElement.addEventListener('blur', handleBlur)
-
- return () => {
- rootElement.removeEventListener('focus', handleFocus)
- rootElement.removeEventListener('blur', handleBlur)
- }
- }, [editor])
-
- useEffect(() => {
- const toolbar = toolbarRef.current
- const linkEditor = linkEditorRef.current
-
const handleToolbarFocus = () => setIsInToolbar(true)
- const handleLinkEditorFocus = () => setIsInLinkEditor(true)
const handleToolbarBlur = (event: FocusEvent) => {
const elementToBeFocused = event.relatedTarget as Node
if (elementToBeFocused === backspaceButtonRef.current) {
@@ -285,34 +308,42 @@ const MobileToolbarPlugin = () => {
}
setIsInToolbar(false)
}
- const handleLinkEditorBlur = (event: FocusEvent) => {
+
+ const handleRootFocus = () => setIsInEditor(true)
+ const handleRootBlur = (event: FocusEvent) => {
const elementToBeFocused = event.relatedTarget as Node
- if (elementToBeFocused === backspaceButtonRef.current) {
+
+ const containerContainsElementToFocus = container?.contains(elementToBeFocused)
+
+ const willFocusBackspaceButton = backspaceButtonRef.current && elementToBeFocused === backspaceButtonRef.current
+
+ if (containerContainsElementToFocus || willFocusBackspaceButton) {
return
}
- setIsInLinkEditor(false)
- }
- if (toolbar) {
- toolbar.addEventListener('focus', handleToolbarFocus)
- toolbar.addEventListener('blur', handleToolbarBlur)
+ setIsInEditor(false)
}
- if (linkEditor) {
- linkEditor.addEventListener('focus', handleLinkEditorFocus)
- linkEditor.addEventListener('blur', handleLinkEditorBlur)
+ rootElement.addEventListener('focus', handleRootFocus)
+ rootElement.addEventListener('blur', handleRootBlur)
+
+ if (container) {
+ container.addEventListener('focus', handleToolbarFocus)
+ container.addEventListener('blur', handleToolbarBlur)
}
return () => {
- toolbar?.removeEventListener('focus', handleToolbarFocus)
- toolbar?.removeEventListener('blur', handleToolbarBlur)
- linkEditor?.removeEventListener('focus', handleLinkEditorFocus)
- linkEditor?.removeEventListener('blur', handleLinkEditorBlur)
+ rootElement.removeEventListener('focus', handleRootFocus)
+ rootElement.removeEventListener('blur', handleRootBlur)
+ container?.removeEventListener('focus', handleToolbarFocus)
+ container?.removeEventListener('blur', handleToolbarBlur)
}
- }, [])
- const [isSelectionAutoLink, setIsSelectionAutoLink] = useState(false)
+ }, [editor])
+
const [linkUrl, setLinkUrl] = useState('')
+ const [linkText, setLinkText] = useState('')
const [isLinkEditMode, setIsLinkEditMode] = useState(false)
+ const [isLinkTextEditMode, setIsLinkTextEditMode] = useState(false)
const [lastSelection, setLastSelection] = useState(null)
const updateEditorSelection = useCallback(() => {
@@ -329,18 +360,6 @@ const MobileToolbarPlugin = () => {
const node = getSelectedNode(selection)
const parent = node.getParent()
- if ($isLinkNode(parent) || $isLinkNode(node)) {
- setIsSelectionLink(true)
- } else {
- setIsSelectionLink(false)
- }
-
- if ($isAutoLinkNode(parent) || $isAutoLinkNode(node)) {
- setIsSelectionAutoLink(true)
- } else {
- setIsSelectionAutoLink(false)
- }
-
if ($isLinkNode(parent)) {
setLinkUrl(parent.getURL())
} else if ($isLinkNode(node)) {
@@ -348,6 +367,11 @@ const MobileToolbarPlugin = () => {
} else {
setLinkUrl('')
}
+ if ($isLinkTextNode(node, selection)) {
+ setLinkText(node.getTextContent())
+ } else {
+ setLinkText('')
+ }
if (
selection !== null &&
@@ -380,76 +404,147 @@ const MobileToolbarPlugin = () => {
)
}, [editor, updateEditorSelection])
- const isFocusInEditorOrToolbar = isInEditor || isInToolbar || isInLinkEditor
+ useEffect(() => {
+ const container = containerRef.current
+ const rootElement = editor.getRootElement()
+
+ if (!container || !rootElement) {
+ return
+ }
+
+ const resizeObserver = new ResizeObserver(() => {
+ if (isMobile) {
+ return
+ }
+
+ const containerHeight = container.offsetHeight
+
+ rootElement.style.paddingBottom = containerHeight ? `${containerHeight + 16 * 2}px` : ''
+ })
+
+ resizeObserver.observe(container)
+
+ return () => {
+ resizeObserver.disconnect()
+ }
+ }, [editor, isMobile])
+
+ const isFocusInEditorOrToolbar = isInEditor || isInToolbar
+ const [isToolbarVisible, setIsToolbarVisible] = useState(true)
+ const canShowToolbar = isMobile ? isFocusInEditorOrToolbar : isToolbarVisible
+
+ const toolbarStore = useToolbarStore()
+
+ useEffect(() => {
+ return application.keyboardService.addCommandHandler({
+ command: SUPER_TOGGLE_TOOLBAR,
+ onKeyDown: (event) => {
+ if (isMobile) {
+ return
+ }
+
+ event.preventDefault()
+
+ const isFocusInContainer = containerRef.current?.contains(document.activeElement)
+
+ if (!isToolbarVisible) {
+ setIsToolbarVisible(true)
+ toolbarStore.move(toolbarStore.first())
+ return
+ }
+
+ if (isFocusInContainer) {
+ setIsToolbarVisible(false)
+ editor.focus()
+ } else {
+ toolbarStore.move(toolbarStore.first())
+ }
+ },
+ })
+ }, [application.keyboardService, editor, isMobile, isToolbarVisible, toolbarStore])
return (
<>
{modal}
>
)
}
-export default MobileToolbarPlugin
+export default ToolbarPlugin
diff --git a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/useSelectedTextFormatInfo.ts b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/useSelectedTextFormatInfo.ts
similarity index 98%
rename from packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/useSelectedTextFormatInfo.ts
rename to packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/useSelectedTextFormatInfo.ts
index e209a4da9e8..a541b215bc6 100644
--- a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/useSelectedTextFormatInfo.ts
+++ b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugin/useSelectedTextFormatInfo.ts
@@ -14,7 +14,7 @@ import { $isHeadingNode } from '@lexical/rich-text'
import { $isListNode, ListNode } from '@lexical/list'
import { useCallback, useEffect, useState } from 'react'
import { getSelectedNode } from '../../Lexical/Utils/getSelectedNode'
-import { $isLinkTextNode } from '../LinkEditor/LinkTextEditor'
+import { $isLinkTextNode } from './ToolbarLinkTextEditor'
const blockTypeToBlockName = {
bullet: 'Bulleted List',
diff --git a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/FloatingTextFormatToolbarPlugin.tsx b/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/FloatingTextFormatToolbarPlugin.tsx
deleted file mode 100644
index 723a394a362..00000000000
--- a/packages/web/src/javascripts/Components/SuperEditor/Plugins/ToolbarPlugins/FloatingTextFormatToolbarPlugin.tsx
+++ /dev/null
@@ -1,535 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- */
-
-import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link'
-import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
-import { mergeRegister } from '@lexical/utils'
-import {
- $getSelection,
- $isRangeSelection,
- FORMAT_TEXT_COMMAND,
- LexicalEditor,
- SELECTION_CHANGE_COMMAND,
- COMMAND_PRIORITY_LOW,
- RangeSelection,
- GridSelection,
- NodeSelection,
- KEY_MODIFIER_COMMAND,
- COMMAND_PRIORITY_NORMAL,
- createCommand,
-} from 'lexical'
-import { INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND } from '@lexical/list'
-import { ComponentPropsWithoutRef, useCallback, useEffect, useRef, useState } from 'react'
-import { createPortal } from 'react-dom'
-import { getSelectedNode } from '../../Lexical/Utils/getSelectedNode'
-import {
- BoldIcon,
- ItalicIcon,
- UnderlineIcon,
- StrikethroughIcon,
- CodeIcon,
- LinkIcon,
- SuperscriptIcon,
- SubscriptIcon,
- ListBulleted,
- ListNumbered,
- DrawIcon,
-} from '@standardnotes/icons'
-import { IconComponent } from '../../Lexical/Theme/IconComponent'
-import { classNames } from '@standardnotes/snjs'
-import { getDOMRangeRect } from '../../Lexical/Utils/getDOMRangeRect'
-import { getPositionedPopoverStyles } from '@/Components/Popover/GetPositionedPopoverStyles'
-import { getAdjustedStylesForNonPortalPopover } from '@/Components/Popover/Utils/getAdjustedStylesForNonPortal'
-import LinkEditor from '../LinkEditor/LinkEditor'
-import LinkTextEditor, { $isLinkTextNode } from '../LinkEditor/LinkTextEditor'
-import { URL_REGEX } from '@/Constants/Constants'
-import { useSelectedTextFormatInfo } from './useSelectedTextFormatInfo'
-import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
-import StyledTooltip from '@/Components/StyledTooltip/StyledTooltip'
-
-const IconSize = 15
-
-const TOGGLE_LINK_AND_EDIT_COMMAND = createCommand('TOGGLE_LINK_AND_EDIT_COMMAND')
-
-const ToolbarButton = ({ active, ...props }: { active?: boolean } & ComponentPropsWithoutRef<'button'>) => {
- return (
-
- )
-}
-
-function TextFormatFloatingToolbar({
- editor,
- anchorElem,
- isText,
- isLink,
- isLinkText,
- isAutoLink,
- isBold,
- isItalic,
- isUnderline,
- isCode,
- isStrikethrough,
- isSubscript,
- isSuperscript,
- isBulletedList,
- isNumberedList,
- isHighlighted,
-}: {
- editor: LexicalEditor
- anchorElem: HTMLElement
- isText: boolean
- isBold: boolean
- isCode: boolean
- isItalic: boolean
- isLink: boolean
- isLinkText: boolean
- isAutoLink: boolean
- isStrikethrough: boolean
- isSubscript: boolean
- isSuperscript: boolean
- isUnderline: boolean
- isBulletedList: boolean
- isNumberedList: boolean
- isHighlighted: boolean
-}) {
- const toolbarRef = useRef(null)
-
- const [linkUrl, setLinkUrl] = useState('')
- const [linkText, setLinkText] = useState('')
- const [isLinkEditMode, setIsLinkEditMode] = useState(false)
- const [lastSelection, setLastSelection] = useState(null)
-
- useEffect(() => {
- return editor.registerCommand(
- TOGGLE_LINK_AND_EDIT_COMMAND,
- (payload) => {
- if (payload === null) {
- return editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
- } else if (typeof payload === 'string') {
- const dispatched = editor.dispatchCommand(TOGGLE_LINK_COMMAND, payload)
- setLinkUrl(payload)
- setIsLinkEditMode(true)
- return dispatched
- }
- return false
- },
- COMMAND_PRIORITY_LOW,
- )
- }, [editor])
-
- const insertLink = useCallback(() => {
- if (!isLink) {
- editor.update(() => {
- editor.dispatchCommand(TOGGLE_LINK_AND_EDIT_COMMAND, '')
- })
- } else {
- editor.dispatchCommand(TOGGLE_LINK_AND_EDIT_COMMAND, null)
- }
- }, [editor, isLink])
-
- const formatBulletList = useCallback(() => {
- if (!isBulletedList) {
- editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined)
- } else {
- editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined)
- }
- }, [editor, isBulletedList])
-
- const formatNumberedList = useCallback(() => {
- if (!isNumberedList) {
- editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined)
- } else {
- editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined)
- }
- }, [editor, isNumberedList])
-
- const updateToolbar = useCallback(() => {
- const selection = $getSelection()
- if ($isRangeSelection(selection)) {
- const node = getSelectedNode(selection)
- const parent = node.getParent()
- if ($isLinkNode(parent)) {
- setLinkUrl(parent.getURL())
- } else if ($isLinkNode(node)) {
- setLinkUrl(node.getURL())
- } else {
- setLinkUrl('')
- }
- if ($isLinkTextNode(node, selection)) {
- setLinkText(node.getTextContent())
- } else {
- setLinkText('')
- }
- }
-
- const toolbarElement = toolbarRef.current
-
- if (!toolbarElement) {
- return
- }
-
- const nativeSelection = window.getSelection()
- const activeElement = document.activeElement
- const rootElement = editor.getRootElement()
-
- if (
- selection !== null &&
- nativeSelection !== null &&
- rootElement !== null &&
- rootElement.contains(nativeSelection.anchorNode)
- ) {
- setLastSelection(selection)
-
- const rangeRect = getDOMRangeRect(nativeSelection, rootElement)
- const toolbarRect = toolbarElement.getBoundingClientRect()
- const rootElementRect = rootElement.getBoundingClientRect()
-
- const calculatedStyles = getPositionedPopoverStyles({
- align: 'start',
- side: 'top',
- anchorRect: rangeRect,
- popoverRect: toolbarRect,
- documentRect: rootElementRect,
- offset: 12,
- maxHeightFunction: () => 'none',
- })
- if (calculatedStyles) {
- toolbarElement.style.setProperty('--offset', calculatedStyles['--offset'])
- }
-
- if (calculatedStyles) {
- Object.assign(toolbarElement.style, calculatedStyles)
- const adjustedStyles = getAdjustedStylesForNonPortalPopover(toolbarElement, calculatedStyles, rootElement)
- toolbarElement.style.setProperty('--translate-x', adjustedStyles['--translate-x'])
- toolbarElement.style.setProperty('--translate-y', adjustedStyles['--translate-y'])
- }
- } else if (!activeElement || activeElement.id !== 'link-input') {
- setLastSelection(null)
- setIsLinkEditMode(false)
- setLinkUrl('')
- }
-
- return true
- }, [editor])
-
- useEffect(() => {
- const scrollerElem = editor.getRootElement()
-
- const update = () => {
- editor.getEditorState().read(() => {
- updateToolbar()
- })
- }
-
- window.addEventListener('resize', update)
- if (scrollerElem) {
- scrollerElem.addEventListener('scroll', update)
- }
-
- return () => {
- window.removeEventListener('resize', update)
- if (scrollerElem) {
- scrollerElem.removeEventListener('scroll', update)
- }
- }
- }, [editor, anchorElem, updateToolbar])
-
- useEffect(() => {
- editor.getEditorState().read(() => {
- updateToolbar()
- })
- return mergeRegister(
- editor.registerUpdateListener(({ editorState }) => {
- editorState.read(() => {
- updateToolbar()
- })
- }),
-
- editor.registerCommand(
- SELECTION_CHANGE_COMMAND,
- () => {
- updateToolbar()
- return false
- },
- COMMAND_PRIORITY_LOW,
- ),
- )
- }, [editor, updateToolbar])
-
- useEffect(() => {
- return editor.registerCommand(
- KEY_MODIFIER_COMMAND,
- (payload) => {
- const event: KeyboardEvent = payload
- const { code, ctrlKey, metaKey } = event
-
- if (code === 'KeyK' && (ctrlKey || metaKey)) {
- event.preventDefault()
- if ('readText' in navigator.clipboard) {
- navigator.clipboard
- .readText()
- .then((text) => {
- if (URL_REGEX.test(text)) {
- editor.dispatchCommand(TOGGLE_LINK_COMMAND, text)
- } else {
- throw new Error('Not a valid URL')
- }
- })
- .catch((error) => {
- console.error(error)
- editor.dispatchCommand(TOGGLE_LINK_AND_EDIT_COMMAND, '')
- setIsLinkEditMode(true)
- })
- } else {
- editor.dispatchCommand(TOGGLE_LINK_AND_EDIT_COMMAND, '')
- setIsLinkEditMode(true)
- }
- return true
- }
- return false
- },
- COMMAND_PRIORITY_NORMAL,
- )
- }, [editor])
-
- useEffect(() => {
- editor.getEditorState().read(() => updateToolbar())
- }, [editor, isLink, isText, updateToolbar])
-
- if (!editor.isEditable()) {
- return null
- }
-
- return (
-
- {isLinkText && !isAutoLink && (
- <>
-
-
- >
- )}
- {isLink && (
-
- )}
- {isText && isLink && (
-
- )}
- {isText && (
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold')
- }}
- aria-label="Format text as bold"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic')
- }}
- active={isItalic}
- aria-label="Format text as italics"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline')
- }}
- active={isUnderline}
- aria-label="Format text to underlined"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough')
- }}
- active={isStrikethrough}
- aria-label="Format text with a strikethrough"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'subscript')
- }}
- active={isSubscript}
- title="Subscript"
- aria-label="Format Subscript"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'superscript')
- }}
- active={isSuperscript}
- title="Superscript"
- aria-label="Format Superscript"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code')
- }}
- active={isCode}
- aria-label="Insert code block"
- >
-
-
-
-
-
-
- {
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'highlight')
- }}
- active={isHighlighted}
- aria-label="Highlight text"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- )
-}
-
-function useFloatingTextFormatToolbar(editor: LexicalEditor, anchorElem: HTMLElement): JSX.Element | null {
- const {
- isText,
- isLink,
- isLinkText,
- isAutoLink,
- isBold,
- isItalic,
- isStrikethrough,
- isSubscript,
- isSuperscript,
- isUnderline,
- isCode,
- isHighlighted,
- blockType,
- } = useSelectedTextFormatInfo()
-
- const isMobile = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
-
- if (isMobile) {
- return null
- }
-
- if (!isText && !isLink) {
- return null
- }
-
- return createPortal(
- ,
- anchorElem,
- )
-}
-
-export default function FloatingTextFormatToolbarPlugin({
- anchorElem = document.body,
-}: {
- anchorElem?: HTMLElement
-}): JSX.Element | null {
- const [editor] = useLexicalComposerContext()
- return useFloatingTextFormatToolbar(editor, anchorElem)
-}
diff --git a/packages/web/src/javascripts/Components/SuperEditor/SuperEditor.tsx b/packages/web/src/javascripts/Components/SuperEditor/SuperEditor.tsx
index c21d4d82776..a90f4f1f41e 100644
--- a/packages/web/src/javascripts/Components/SuperEditor/SuperEditor.tsx
+++ b/packages/web/src/javascripts/Components/SuperEditor/SuperEditor.tsx
@@ -44,7 +44,7 @@ import ReadonlyPlugin from './Plugins/ReadonlyPlugin/ReadonlyPlugin'
import { SuperSearchContextProvider } from './Plugins/SearchPlugin/Context'
import { SearchPlugin } from './Plugins/SearchPlugin/SearchPlugin'
import ModalOverlay from '@/Components/Modal/ModalOverlay'
-import MobileToolbarPlugin from './Plugins/ToolbarPlugins/MobileToolbarPlugin'
+import ToolbarPlugin from './Plugins/ToolbarPlugin/ToolbarPlugin'
import CodeOptionsPlugin from './Plugins/CodeOptionsPlugin/CodeOptions'
import RemoteImagePlugin from './Plugins/RemoteImagePlugin/RemoteImagePlugin'
import NotEntitledBanner from '../ComponentView/NotEntitledBanner'
@@ -250,7 +250,7 @@ export const SuperEditor: FunctionComponent = ({
-
+