Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 28 additions & 32 deletions packages/react-select/src/components/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ export interface MenuPlacementProps {
export interface MenuProps<
Option = unknown,
IsMulti extends boolean = boolean,
Group extends GroupBase<Option> = GroupBase<Option>
> extends CommonPropsAndClassName<Option, IsMulti, Group>,
MenuPlacementProps {
Group extends GroupBase<Option> = GroupBase<Option>,
>
extends CommonPropsAndClassName<Option, IsMulti, Group>, MenuPlacementProps {
/** Reference to the internal element, consumed by the MenuPlacer component */
innerRef: Ref<HTMLDivElement>;
innerProps: JSX.IntrinsicElements['div'];
Expand All @@ -262,9 +262,9 @@ interface ChildrenProps {
export interface MenuPlacerProps<
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
> extends CommonProps<Option, IsMulti, Group>,
MenuPlacementProps {
Group extends GroupBase<Option>,
>
extends CommonProps<Option, IsMulti, Group>, MenuPlacementProps {
/** The children to be rendered. */
children: (childrenProps: ChildrenProps) => ReactElement;
}
Expand All @@ -278,7 +278,7 @@ const coercePlacement = (p: MenuPlacement) => (p === 'auto' ? 'bottom' : p);
export const menuCSS = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
{
placement,
Expand All @@ -303,16 +303,15 @@ export const menuCSS = <
}),
});

const PortalPlacementContext =
createContext<{
setPortalPlacement: (placement: CoercedMenuPlacement) => void;
} | null>(null);
const PortalPlacementContext = createContext<{
setPortalPlacement: (placement: CoercedMenuPlacement) => void;
} | null>(null);

// NOTE: internal only
export const MenuPlacer = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
props: MenuPlacerProps<Option, IsMulti, Group>
) => {
Expand Down Expand Up @@ -397,7 +396,7 @@ export default Menu;
export interface MenuListProps<
Option = unknown,
IsMulti extends boolean = boolean,
Group extends GroupBase<Option> = GroupBase<Option>
Group extends GroupBase<Option> = GroupBase<Option>,
> extends CommonPropsAndClassName<Option, IsMulti, Group> {
/** Set the max height of the Menu component */
maxHeight: number;
Expand All @@ -413,7 +412,7 @@ export interface MenuListProps<
export const menuListCSS = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
{
maxHeight,
Expand All @@ -437,7 +436,7 @@ export const menuListCSS = <
export const MenuList = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
props: MenuListProps<Option, IsMulti, Group>
) => {
Expand All @@ -463,7 +462,7 @@ export const MenuList = <
const noticeCSS = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
{
theme: {
Expand All @@ -487,7 +486,7 @@ export const loadingMessageCSS = noticeCSS;
export interface NoticeProps<
Option = unknown,
IsMulti extends boolean = boolean,
Group extends GroupBase<Option> = GroupBase<Option>
Group extends GroupBase<Option> = GroupBase<Option>,
> extends CommonPropsAndClassName<Option, IsMulti, Group> {
/** The children to be rendered. */
children: ReactNode;
Expand All @@ -498,7 +497,7 @@ export interface NoticeProps<
export const NoOptionsMessage = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>({
children = 'No options',
innerProps,
Expand All @@ -524,7 +523,7 @@ export const NoOptionsMessage = <
export const LoadingMessage = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>({
children = 'Loading...',
innerProps,
Expand Down Expand Up @@ -554,7 +553,7 @@ export const LoadingMessage = <
export interface MenuPortalProps<
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
> extends CommonPropsAndClassName<Option, IsMulti, Group> {
appendTo: HTMLElement | undefined;
children: ReactNode; // ideally Menu<MenuProps>
Expand Down Expand Up @@ -590,7 +589,7 @@ interface ComputedPosition {
export const MenuPortal = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
Group extends GroupBase<Option>,
>(
props: MenuPortalProps<Option, IsMulti, Group>
) => {
Expand Down Expand Up @@ -618,27 +617,24 @@ export const MenuPortal = <
const [computedPosition, setComputedPosition] =
useState<ComputedPosition | null>(null);

const computedPositionRef = useRef(computedPosition);
computedPositionRef.current = computedPosition;

const updateComputedPosition = useCallback(() => {
if (!controlElement) return;

const rect = getBoundingClientObj(controlElement);
const scrollDistance = menuPosition === 'fixed' ? 0 : window.pageYOffset;
const offset = rect[placement] + scrollDistance;
const current = computedPositionRef.current;
if (
offset !== computedPosition?.offset ||
rect.left !== computedPosition?.rect.left ||
rect.width !== computedPosition?.rect.width
offset !== current?.offset ||
rect.left !== current?.rect.left ||
rect.width !== current?.rect.width
) {
setComputedPosition({ offset, rect });
}
}, [
controlElement,
menuPosition,
placement,
computedPosition?.offset,
computedPosition?.rect.left,
computedPosition?.rect.width,
]);
}, [controlElement, menuPosition, placement]);

useLayoutEffect(() => {
updateComputedPosition();
Expand Down