Skip to content

Commit

Permalink
Bring back min and max height calculation and reposition the dropdown…
Browse files Browse the repository at this point in the history
… in a smarter way
  • Loading branch information
kudlajz committed Nov 1, 2024
1 parent 9262c9c commit 5223c32
Showing 1 changed file with 37 additions and 20 deletions.
57 changes: 37 additions & 20 deletions packages/slate-editor/src/components/SearchInput/Suggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { FlipModifier } from '@popperjs/core/lib/modifiers/flip';
import type { PreventOverflowModifier } from '@popperjs/core/lib/modifiers/preventOverflow';
import classNames from 'classnames';
import type { HTMLAttributes, ReactNode } from 'react';
import React, { useEffect, useRef, useState } from 'react';
Expand All @@ -16,6 +15,7 @@ import type { Suggestion } from './types';
export interface Props<T> extends HTMLAttributes<HTMLDivElement> {
activeElement: HTMLElement | undefined;
footer?: ReactNode;
minHeight?: number;
maxHeight?: number;
origin: HTMLElement | null;
query: string;
Expand All @@ -27,13 +27,15 @@ export function Suggestions<T>({
children,
className,
footer,
maxHeight = 500,
minHeight = 200,
maxHeight = 400,
origin,
query,
suggestions,
...attributes
}: Props<T>) {
const [height, setHeight] = useState<number>();
const [calculatedMaxHeight, setMaxHeight] = useState<number>();
const container = useRef<HTMLDivElement | null>(null);
const childrenContainer = useRef<HTMLDivElement | null>(null);
const [scrollarea, setScrollarea] = useState<FancyScrollbars | null>(null);
Expand All @@ -44,42 +46,51 @@ export function Suggestions<T>({
name: 'flip',
enabled: true,
options: {
fallbackPlacements: ['top'],
fallbackPlacements: ['top-end'],
},
} satisfies Partial<FlipModifier>,
{
name: 'preventOverflow',
enabled: true,
options: {
altAxis: true,
mainAxis: true,
},
} satisfies Partial<PreventOverflowModifier>,
],
placement: 'bottom',
placement: 'bottom-end',
});

const updatePanelSizeAndPosition = useFunction(() => {
setHeight(childrenContainer.current?.getBoundingClientRect().height);

if (container.current) {
const viewport = document.body.getBoundingClientRect();
const rect = container.current.getBoundingClientRect();
setMaxHeight(clamp(viewport.height - rect.top - 4, minHeight, maxHeight));
} else {
setMaxHeight(undefined);
}
});

useEffect(updatePanelSizeAndPosition, [query, suggestions, maxHeight]);
useEffect(updatePanelSizeAndPosition, [
query,
suggestions,
calculatedMaxHeight,
minHeight,
maxHeight,
]);

useEffect(() => {
if (activeElement) {
scrollarea?.ensureVisible(activeElement);
async function repositionPopper() {
await popper.update?.();
updatePanelSizeAndPosition();

if (activeElement) {
scrollarea?.ensureVisible(activeElement);
}
}
}, [scrollarea, activeElement]);

useEffect(() => {
popper.update?.();
}, [height]);
repositionPopper();
}, [activeElement, calculatedMaxHeight]);

return (
<Panel
{...attributes}
{...popper.attributes.popper}
style={{ maxHeight, ...attributes.style, ...popper.styles.popper }}
style={{ maxHeight: calculatedMaxHeight, ...attributes.style, ...popper.styles.popper }}
ref={container}
className={classNames(className, styles.Suggestions)}
footer={footer}
Expand All @@ -91,3 +102,9 @@ export function Suggestions<T>({
</Panel>
);
}

function clamp(num: number, min: number, max: number) {
if (num < min) return min;
if (num > max) return max;
return num;
}

0 comments on commit 5223c32

Please sign in to comment.