chore: fix issue with link editor position on iOS
This commit is contained in:
@@ -12,7 +12,6 @@ import { classNames } from '@standardnotes/snjs'
|
|||||||
import Icon from '@/Components/Icon/Icon'
|
import Icon from '@/Components/Icon/Icon'
|
||||||
import StyledTooltip from '@/Components/StyledTooltip/StyledTooltip'
|
import StyledTooltip from '@/Components/StyledTooltip/StyledTooltip'
|
||||||
import { TOGGLE_LINK_COMMAND } from '@lexical/link'
|
import { TOGGLE_LINK_COMMAND } from '@lexical/link'
|
||||||
import Portal from '@/Components/Portal/Portal'
|
|
||||||
import { mergeRegister } from '@lexical/utils'
|
import { mergeRegister } from '@lexical/utils'
|
||||||
import { KeyboardKey } from '@standardnotes/ui-services'
|
import { KeyboardKey } from '@standardnotes/ui-services'
|
||||||
import Button from '@/Components/Button/Button'
|
import Button from '@/Components/Button/Button'
|
||||||
@@ -20,6 +19,9 @@ import { sanitizeUrl } from '../../Lexical/Utils/sanitizeUrl'
|
|||||||
import { getSelectedNode } from '../../Lexical/Utils/getSelectedNode'
|
import { getSelectedNode } from '../../Lexical/Utils/getSelectedNode'
|
||||||
import { $isLinkTextNode } from './ToolbarLinkTextEditor'
|
import { $isLinkTextNode } from './ToolbarLinkTextEditor'
|
||||||
import { useElementResize } from '@/Hooks/useElementRect'
|
import { useElementResize } from '@/Hooks/useElementRect'
|
||||||
|
import { createPortal } from 'react-dom'
|
||||||
|
import { ElementIds } from '@/Constants/ElementIDs'
|
||||||
|
import { getAdjustedStylesForNonPortalPopover } from '@/Components/Popover/Utils/getAdjustedStylesForNonPortal'
|
||||||
|
|
||||||
const FloatingLinkEditor = ({
|
const FloatingLinkEditor = ({
|
||||||
linkUrl,
|
linkUrl,
|
||||||
@@ -90,7 +92,8 @@ const FloatingLinkEditor = ({
|
|||||||
maxHeightFunction: () => 'none',
|
maxHeightFunction: () => 'none',
|
||||||
})
|
})
|
||||||
if (calculatedStyles) {
|
if (calculatedStyles) {
|
||||||
Object.entries(calculatedStyles).forEach(([key, value]) => {
|
const adjustedStyles = getAdjustedStylesForNonPortalPopover(linkEditorElement, calculatedStyles)
|
||||||
|
Object.entries(adjustedStyles).forEach(([key, value]) => {
|
||||||
linkEditorElement.style.setProperty(key, value)
|
linkEditorElement.style.setProperty(key, value)
|
||||||
})
|
})
|
||||||
linkEditorElement.style.opacity = '1'
|
linkEditorElement.style.opacity = '1'
|
||||||
@@ -145,50 +148,28 @@ const FloatingLinkEditor = ({
|
|||||||
setTimeout(updateLinkEditorPosition)
|
setTimeout(updateLinkEditorPosition)
|
||||||
}, [isEditMode, updateLinkEditorPosition])
|
}, [isEditMode, updateLinkEditorPosition])
|
||||||
|
|
||||||
return (
|
return createPortal(
|
||||||
<Portal>
|
<div
|
||||||
<div
|
id="super-link-editor"
|
||||||
id="super-link-editor"
|
className="absolute bottom-12 left-1/2 z-modal w-[calc(100%_-_1rem)] -translate-x-1/2 rounded-lg border border-border bg-contrast px-2 py-1 shadow-sm shadow-contrast translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)] md:bottom-[unset] md:left-0 md:top-0 md:w-auto md:translate-x-0 md:opacity-0"
|
||||||
className="absolute bottom-12 left-1/2 z-modal w-[calc(100%_-_1rem)] -translate-x-1/2 rounded-lg border border-border bg-contrast px-2 py-1 shadow-sm shadow-contrast translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)] md:bottom-[unset] md:left-0 md:top-0 md:w-auto md:translate-x-0 md:opacity-0"
|
ref={linkEditorRef}
|
||||||
ref={linkEditorRef}
|
>
|
||||||
>
|
{isEditMode ? (
|
||||||
{isEditMode ? (
|
<div
|
||||||
<div
|
className="flex flex-col gap-2 py-1"
|
||||||
className="flex flex-col gap-2 py-1"
|
onBlur={(event) => {
|
||||||
onBlur={(event) => {
|
if (!linkEditorRef.current?.contains(event.relatedTarget as Node)) {
|
||||||
if (!linkEditorRef.current?.contains(event.relatedTarget as Node)) {
|
setEditMode(false)
|
||||||
setEditMode(false)
|
}
|
||||||
}
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{isLinkText && (
|
||||||
{isLinkText && (
|
|
||||||
<div className="flex items-center gap-1.5">
|
|
||||||
<Icon type="plain-text" className="flex-shrink-0" />
|
|
||||||
<input
|
|
||||||
value={editedLinkText}
|
|
||||||
onChange={(event) => {
|
|
||||||
setEditedLinkText(event.target.value)
|
|
||||||
}}
|
|
||||||
onKeyDown={(event) => {
|
|
||||||
if (event.key === KeyboardKey.Enter) {
|
|
||||||
event.preventDefault()
|
|
||||||
handleSubmission()
|
|
||||||
} else if (event.key === KeyboardKey.Escape) {
|
|
||||||
event.preventDefault()
|
|
||||||
setEditMode(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[20ch]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<Icon type="link" className="flex-shrink-0" />
|
<Icon type="plain-text" className="flex-shrink-0" />
|
||||||
<input
|
<input
|
||||||
ref={focusInput}
|
value={editedLinkText}
|
||||||
value={editedLinkUrl}
|
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setEditedLinkUrl(event.target.value)
|
setEditedLinkText(event.target.value)
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
if (event.key === KeyboardKey.Enter) {
|
if (event.key === KeyboardKey.Enter) {
|
||||||
@@ -199,84 +180,105 @@ const FloatingLinkEditor = ({
|
|||||||
setEditMode(false)
|
setEditMode(false)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[40ch]"
|
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[20ch]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-end gap-1.5">
|
)}
|
||||||
<StyledTooltip showOnMobile showOnHover label="Cancel editing">
|
<div className="flex items-center gap-1.5">
|
||||||
<Button
|
<Icon type="link" className="flex-shrink-0" />
|
||||||
onClick={() => {
|
<input
|
||||||
setEditMode(false)
|
ref={focusInput}
|
||||||
editor.focus()
|
value={editedLinkUrl}
|
||||||
}}
|
onChange={(event) => {
|
||||||
onMouseDown={(event) => event.preventDefault()}
|
setEditedLinkUrl(event.target.value)
|
||||||
>
|
}}
|
||||||
Cancel
|
onKeyDown={(event) => {
|
||||||
</Button>
|
if (event.key === KeyboardKey.Enter) {
|
||||||
</StyledTooltip>
|
event.preventDefault()
|
||||||
<StyledTooltip showOnMobile showOnHover label="Save link">
|
handleSubmission()
|
||||||
<Button primary onClick={handleSubmission} onMouseDown={(event) => event.preventDefault()}>
|
} else if (event.key === KeyboardKey.Escape) {
|
||||||
Apply
|
event.preventDefault()
|
||||||
</Button>
|
setEditMode(false)
|
||||||
</StyledTooltip>
|
}
|
||||||
</div>
|
}}
|
||||||
|
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[40ch]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
<div className="flex items-center justify-end gap-1.5">
|
||||||
<div className="flex items-center gap-1">
|
<StyledTooltip showOnMobile showOnHover label="Cancel editing">
|
||||||
<a
|
<Button
|
||||||
className={classNames(
|
|
||||||
'mr-1 flex flex-grow items-center gap-2 overflow-hidden whitespace-nowrap underline',
|
|
||||||
isAutoLink && 'py-2.5',
|
|
||||||
)}
|
|
||||||
href={linkUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Icon type="open-in" className="ml-1 flex-shrink-0" />
|
|
||||||
<div className="max-w-[35ch] overflow-hidden text-ellipsis">{linkUrl}</div>
|
|
||||||
</a>
|
|
||||||
<StyledTooltip showOnMobile showOnHover label="Copy link">
|
|
||||||
<button
|
|
||||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigator.clipboard.writeText(linkUrl).catch(console.error)
|
setEditMode(false)
|
||||||
|
editor.focus()
|
||||||
}}
|
}}
|
||||||
onMouseDown={(event) => event.preventDefault()}
|
onMouseDown={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<Icon type="copy" size="medium" />
|
Cancel
|
||||||
</button>
|
</Button>
|
||||||
|
</StyledTooltip>
|
||||||
|
<StyledTooltip showOnMobile showOnHover label="Save link">
|
||||||
|
<Button primary onClick={handleSubmission} onMouseDown={(event) => event.preventDefault()}>
|
||||||
|
Apply
|
||||||
|
</Button>
|
||||||
</StyledTooltip>
|
</StyledTooltip>
|
||||||
{!isAutoLink && (
|
|
||||||
<>
|
|
||||||
<StyledTooltip showOnMobile showOnHover label="Edit link">
|
|
||||||
<button
|
|
||||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
|
||||||
onClick={() => {
|
|
||||||
setEditedLinkUrl(linkUrl)
|
|
||||||
setEditMode(true)
|
|
||||||
}}
|
|
||||||
onMouseDown={(event) => event.preventDefault()}
|
|
||||||
>
|
|
||||||
<Icon type="pencil-filled" size="medium" />
|
|
||||||
</button>
|
|
||||||
</StyledTooltip>
|
|
||||||
<StyledTooltip showOnMobile showOnHover label="Remove link">
|
|
||||||
<button
|
|
||||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
|
||||||
onClick={() => {
|
|
||||||
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
|
|
||||||
}}
|
|
||||||
onMouseDown={(event) => event.preventDefault()}
|
|
||||||
>
|
|
||||||
<Icon type="trash-filled" size="medium" />
|
|
||||||
</button>
|
|
||||||
</StyledTooltip>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
</Portal>
|
<div className="flex items-center gap-1">
|
||||||
|
<a
|
||||||
|
className={classNames(
|
||||||
|
'mr-1 flex flex-grow items-center gap-2 overflow-hidden whitespace-nowrap underline',
|
||||||
|
isAutoLink && 'py-2.5',
|
||||||
|
)}
|
||||||
|
href={linkUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Icon type="open-in" className="ml-1 flex-shrink-0" />
|
||||||
|
<div className="max-w-[35ch] overflow-hidden text-ellipsis">{linkUrl}</div>
|
||||||
|
</a>
|
||||||
|
<StyledTooltip showOnMobile showOnHover label="Copy link">
|
||||||
|
<button
|
||||||
|
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(linkUrl).catch(console.error)
|
||||||
|
}}
|
||||||
|
onMouseDown={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<Icon type="copy" size="medium" />
|
||||||
|
</button>
|
||||||
|
</StyledTooltip>
|
||||||
|
{!isAutoLink && (
|
||||||
|
<>
|
||||||
|
<StyledTooltip showOnMobile showOnHover label="Edit link">
|
||||||
|
<button
|
||||||
|
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||||
|
onClick={() => {
|
||||||
|
setEditedLinkUrl(linkUrl)
|
||||||
|
setEditMode(true)
|
||||||
|
}}
|
||||||
|
onMouseDown={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<Icon type="pencil-filled" size="medium" />
|
||||||
|
</button>
|
||||||
|
</StyledTooltip>
|
||||||
|
<StyledTooltip showOnMobile showOnHover label="Remove link">
|
||||||
|
<button
|
||||||
|
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||||
|
onClick={() => {
|
||||||
|
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
|
||||||
|
}}
|
||||||
|
onMouseDown={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<Icon type="trash-filled" size="medium" />
|
||||||
|
</button>
|
||||||
|
</StyledTooltip>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>,
|
||||||
|
document.getElementById(ElementIds.SuperEditor) ?? document.body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user