fix(mobile): super editor autocomplete dropdowns (#2019)
This commit is contained in:
@@ -21,6 +21,7 @@ import { GetDynamicTableBlocks, GetTableBlock } from './Blocks/Table'
|
||||
import Popover from '@/Components/Popover/Popover'
|
||||
import { PopoverClassNames } from '../ClassNames'
|
||||
import { GetDatetimeBlocks } from './Blocks/DateTime'
|
||||
import { isMobileScreen } from '@/Utils'
|
||||
|
||||
export default function BlockPickerMenuPlugin(): JSX.Element {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
@@ -109,12 +110,14 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
|
||||
align="start"
|
||||
anchorPoint={{
|
||||
x: anchorElementRef.current.offsetLeft,
|
||||
y: anchorElementRef.current.offsetTop + anchorElementRef.current.offsetHeight,
|
||||
y: anchorElementRef.current.offsetTop + (!isMobileScreen() ? anchorElementRef.current.offsetHeight : 0),
|
||||
}}
|
||||
open={popoverOpen}
|
||||
togglePopover={() => {
|
||||
setPopoverOpen((prevValue) => !prevValue)
|
||||
}}
|
||||
disableMobileFullscreenTakeover={true}
|
||||
side={isMobileScreen() ? 'top' : 'bottom'}
|
||||
>
|
||||
<div className={PopoverClassNames}>
|
||||
<ul>
|
||||
|
||||
@@ -11,6 +11,7 @@ import Popover from '@/Components/Popover/Popover'
|
||||
import { INSERT_BUBBLE_COMMAND, INSERT_FILE_COMMAND } from '../Commands'
|
||||
import { useLinkingController } from '../../../../../Controllers/LinkingControllerProvider'
|
||||
import { PopoverClassNames } from '../ClassNames'
|
||||
import { isMobileScreen } from '@/Utils'
|
||||
|
||||
type Props = {
|
||||
currentNote: SNNote
|
||||
@@ -106,12 +107,14 @@ export const ItemSelectionPlugin: FunctionComponent<Props> = ({ currentNote }) =
|
||||
align="start"
|
||||
anchorPoint={{
|
||||
x: anchorElementRef.current.offsetLeft,
|
||||
y: anchorElementRef.current.offsetTop + anchorElementRef.current.offsetHeight,
|
||||
y: anchorElementRef.current.offsetTop + (!isMobileScreen() ? anchorElementRef.current.offsetHeight : 0),
|
||||
}}
|
||||
open={popoverOpen}
|
||||
togglePopover={() => {
|
||||
setPopoverOpen((prevValue) => !prevValue)
|
||||
}}
|
||||
disableMobileFullscreenTakeover={true}
|
||||
side={isMobileScreen() ? 'top' : 'bottom'}
|
||||
>
|
||||
<div className={PopoverClassNames}>
|
||||
<ul>
|
||||
|
||||
@@ -102,7 +102,7 @@ export const SuperEditor: FunctionComponent<Props> = ({
|
||||
<BlocksEditor
|
||||
onChange={handleChange}
|
||||
ignoreFirstChange={true}
|
||||
className="relative relative h-full resize-none text-base focus:shadow-none focus:outline-none"
|
||||
className="relative h-full resize-none text-base focus:shadow-none focus:outline-none"
|
||||
previewLength={NotePreviewCharLimit}
|
||||
spellcheck={spellcheck}
|
||||
>
|
||||
|
||||
@@ -4,10 +4,15 @@ import { PopoverAlignment, PopoverSide } from './Types'
|
||||
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
|
||||
import { getPositionedPopoverRect } from './Utils/Rect'
|
||||
|
||||
const getStylesFromRect = (rect: DOMRect): CSSProperties => {
|
||||
const getStylesFromRect = (rect: DOMRect, disableMobileFullscreenTakeover?: boolean): CSSProperties => {
|
||||
return {
|
||||
willChange: 'transform',
|
||||
transform: `translate(${rect.x}px, ${rect.y}px)`,
|
||||
...(disableMobileFullscreenTakeover
|
||||
? {
|
||||
maxWidth: `${window.innerWidth - rect.x * 2}px`,
|
||||
}
|
||||
: {}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +22,7 @@ type Options = {
|
||||
documentRect: DOMRect
|
||||
popoverRect?: DOMRect
|
||||
side: PopoverSide
|
||||
disableMobileFullscreenTakeover?: boolean
|
||||
}
|
||||
|
||||
export const getPositionedPopoverStyles = ({
|
||||
@@ -25,6 +31,7 @@ export const getPositionedPopoverStyles = ({
|
||||
documentRect,
|
||||
popoverRect,
|
||||
side,
|
||||
disableMobileFullscreenTakeover,
|
||||
}: Options): [CSSProperties | null, PopoverSide, PopoverAlignment] => {
|
||||
if (!popoverRect || !anchorRect) {
|
||||
return [null, side, align]
|
||||
@@ -32,7 +39,7 @@ export const getPositionedPopoverStyles = ({
|
||||
|
||||
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
if (!matchesMediumBreakpoint && !disableMobileFullscreenTakeover) {
|
||||
return [null, side, align]
|
||||
}
|
||||
|
||||
@@ -51,5 +58,5 @@ export const getPositionedPopoverStyles = ({
|
||||
})
|
||||
const finalPositionedRect = getPositionedPopoverRect(popoverRect, anchorRect, finalSide, finalAlignment)
|
||||
|
||||
return [getStylesFromRect(finalPositionedRect), finalSide, finalAlignment]
|
||||
return [getStylesFromRect(finalPositionedRect, disableMobileFullscreenTakeover), finalSide, finalAlignment]
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ const useRegisterPopoverToParent = (popoverId: string) => {
|
||||
|
||||
type Props = PopoverProps & {
|
||||
open: boolean
|
||||
disableClickOutside?: boolean
|
||||
}
|
||||
|
||||
const Popover = ({
|
||||
@@ -41,6 +40,7 @@ const Popover = ({
|
||||
side,
|
||||
togglePopover,
|
||||
disableClickOutside,
|
||||
disableMobileFullscreenTakeover,
|
||||
}: Props) => {
|
||||
const popoverId = useRef(UuidGenerator.GenerateUuid())
|
||||
|
||||
@@ -99,6 +99,7 @@ const Popover = ({
|
||||
side={side}
|
||||
togglePopover={togglePopover}
|
||||
disableClickOutside={disableClickOutside}
|
||||
disableMobileFullscreenTakeover={disableMobileFullscreenTakeover}
|
||||
>
|
||||
{children}
|
||||
</PositionedPopoverContent>
|
||||
|
||||
@@ -24,6 +24,7 @@ const PositionedPopoverContent = ({
|
||||
side = 'bottom',
|
||||
togglePopover,
|
||||
disableClickOutside,
|
||||
disableMobileFullscreenTakeover,
|
||||
}: PopoverContentProps) => {
|
||||
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
|
||||
const popoverRect = useAutoElementRect(popoverElement)
|
||||
@@ -44,6 +45,7 @@ const PositionedPopoverContent = ({
|
||||
documentRect,
|
||||
popoverRect: popoverRect ?? popoverElement?.getBoundingClientRect(),
|
||||
side,
|
||||
disableMobileFullscreenTakeover: disableMobileFullscreenTakeover,
|
||||
})
|
||||
|
||||
usePopoverCloseOnClickOutside({
|
||||
@@ -72,23 +74,30 @@ const PositionedPopoverContent = ({
|
||||
<Portal>
|
||||
<div
|
||||
className={classNames(
|
||||
'absolute top-0 left-0 flex h-full w-full min-w-80 cursor-auto flex-col',
|
||||
'absolute top-0 left-0 flex w-full min-w-80 cursor-auto flex-col',
|
||||
'overflow-y-auto rounded bg-default shadow-main md:h-auto md:max-w-xs',
|
||||
!disableMobileFullscreenTakeover && 'h-full',
|
||||
overrideZIndex ? overrideZIndex : 'z-dropdown-menu',
|
||||
!isDesktopScreen ? 'pt-safe-top pb-safe-bottom' : '',
|
||||
!isDesktopScreen && !disableMobileFullscreenTakeover ? 'pt-safe-top pb-safe-bottom' : '',
|
||||
!styles && 'md:invisible',
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
maxHeight: styles
|
||||
? getPopoverMaxHeight(getAppRect(documentRect), anchorRect, positionedSide, positionedAlignment)
|
||||
? getPopoverMaxHeight(
|
||||
getAppRect(documentRect),
|
||||
anchorRect,
|
||||
positionedSide,
|
||||
positionedAlignment,
|
||||
disableMobileFullscreenTakeover,
|
||||
)
|
||||
: '',
|
||||
top: !isDesktopScreen ? `${document.documentElement.scrollTop}px` : '',
|
||||
}}
|
||||
ref={setPopoverElement}
|
||||
data-popover={id}
|
||||
>
|
||||
<div className="md:hidden">
|
||||
<div className={classNames(disableMobileFullscreenTakeover && 'hidden', 'md:hidden')}>
|
||||
<div className="flex items-center justify-end px-3 pt-2">
|
||||
<button className="rounded-full border border-border p-1" onClick={togglePopover}>
|
||||
<Icon type="close" className="h-6 w-6" />
|
||||
|
||||
@@ -37,6 +37,8 @@ type CommonPopoverProps = {
|
||||
overrideZIndex?: string
|
||||
togglePopover: () => void
|
||||
className?: string
|
||||
disableClickOutside?: boolean
|
||||
disableMobileFullscreenTakeover?: boolean
|
||||
}
|
||||
|
||||
export type PopoverContentProps = CommonPopoverProps & {
|
||||
@@ -44,7 +46,6 @@ export type PopoverContentProps = CommonPopoverProps & {
|
||||
anchorPoint?: Point
|
||||
childPopovers: Set<string>
|
||||
id: string
|
||||
disableClickOutside?: boolean
|
||||
}
|
||||
|
||||
export type PopoverProps =
|
||||
|
||||
@@ -6,14 +6,18 @@ export const getPopoverMaxHeight = (
|
||||
buttonRect: DOMRect | undefined,
|
||||
side: PopoverSide,
|
||||
alignment: PopoverAlignment,
|
||||
disableMobileFullscreenTakeover?: boolean,
|
||||
): number | 'none' => {
|
||||
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
if (!matchesMediumBreakpoint && !disableMobileFullscreenTakeover) {
|
||||
return 'none'
|
||||
}
|
||||
|
||||
const MarginFromAppBorderInPX = 10
|
||||
const topSafeAreaInset = parseInt(
|
||||
getComputedStyle(document.documentElement).getPropertyValue('--safe-area-inset-top'),
|
||||
)
|
||||
|
||||
let constraint = 0
|
||||
|
||||
@@ -21,6 +25,9 @@ export const getPopoverMaxHeight = (
|
||||
switch (side) {
|
||||
case 'top':
|
||||
constraint = appRect.height - buttonRect.top
|
||||
if (topSafeAreaInset > 0) {
|
||||
constraint += topSafeAreaInset
|
||||
}
|
||||
break
|
||||
case 'bottom':
|
||||
constraint = buttonRect.bottom
|
||||
|
||||
Reference in New Issue
Block a user