Skip to content

Commit

Permalink
popopover now correctly repositions on more prop changes
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkatz committed Sep 13, 2024
1 parent 7a6db49 commit 45c0f52
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 18 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-tiny-popover",
"version": "8.1.0",
"version": "8.1.1",
"description": "A simple and highly customizable popover react higher order component with no other dependencies!",
"keywords": [
"react",
Expand All @@ -20,7 +20,7 @@
],
"license": "MIT",
"author": "Alex Katz",
"main": "dist/Popover.js",
"main": "src/Popover.tsx",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc -p . && pnpm run copy-types",
Expand Down
43 changes: 28 additions & 15 deletions src/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PopoverPosition, PopoverProps, PopoverState } from '.';
import { EMPTY_RECT, rectsAreEqual } from './util';
import { usePopover } from './usePopover';
import { useMemoizedArray } from './useMemoizedArray';
import { useHandlePrevValues } from './useHandlePrevValues';
export { useArrowContainer } from './useArrowContainer';
export { ArrowContainer } from './ArrowContainer';
export { usePopover };
Expand Down Expand Up @@ -45,10 +46,14 @@ const PopoverInternal = forwardRef(
Array.isArray(externalPositions) ? externalPositions : [externalPositions],
);

// TODO: factor prevs out into a custom prevs hook
const prevIsOpen = useRef(false);
const prevPositions = useRef<PopoverPosition[] | undefined>();
const prevReposition = useRef(reposition);
const { prev, updatePrevValues } = useHandlePrevValues({
positions,
reposition,
transformMode,
transform,
boundaryElement,
boundaryInset,
});

const childRef = useRef<HTMLElement | undefined>();

Expand Down Expand Up @@ -102,26 +107,22 @@ const PopoverInternal = forwardRef(
popoverRect.height !== popoverState.popoverRect.height ||
popoverState.padding !== padding ||
popoverState.align !== align ||
positions !== prevPositions.current ||
reposition !== prevReposition.current)
positions !== prev.positions ||
reposition !== prev.reposition ||
transformMode !== prev.transformMode ||
transform !== prev.transform ||
boundaryElement !== prev.boundaryElement ||
boundaryInset !== prev.boundaryInset)
) {
positionPopover();
}

// TODO: factor prev checks out into the custom prevs hook
if (positions !== prevPositions.current) {
prevPositions.current = positions;
}
if (reposition !== prevReposition.current) {
prevReposition.current = reposition;
}
updatePrevValues();

if (shouldUpdate) {
window.requestAnimationFrame(updatePopover);
}
}

prevIsOpen.current = isOpen;
};

window.requestAnimationFrame(updatePopover);
Expand All @@ -131,6 +132,8 @@ const PopoverInternal = forwardRef(
};
}, [
align,
boundaryElement,
boundaryInset,
isOpen,
padding,
popoverRef,
Expand All @@ -141,7 +144,16 @@ const PopoverInternal = forwardRef(
popoverState.popoverRect.width,
positionPopover,
positions,
prev.boundaryElement,
prev.boundaryInset,
prev.positions,
prev.reposition,
prev.transform,
prev.transformMode,
reposition,
transform,
transformMode,
updatePrevValues,
]);

useEffect(() => {
Expand Down Expand Up @@ -183,6 +195,7 @@ const PopoverInternal = forwardRef(
body.addEventListener('click', handleOnClickOutside, clickOutsideCapture);
body.addEventListener('contextmenu', handleOnClickOutside, clickOutsideCapture);
body.addEventListener('resize', handleWindowResize);

return () => {
body.removeEventListener('click', handleOnClickOutside, clickOutsideCapture);
body.removeEventListener('contextmenu', handleOnClickOutside, clickOutsideCapture);
Expand Down
39 changes: 39 additions & 0 deletions src/useHandlePrevValues.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useCallback, useRef } from 'react';
import { PopoverProps } from '.';

export const useHandlePrevValues = (props: Partial<PopoverProps>) => {
const prevPositions = useRef(props.positions);
const prevReposition = useRef(props.reposition);
const prevTransformMode = useRef(props.transformMode);
const prevTransform = useRef(props.transform);
const prevBoundaryElement = useRef(props.boundaryElement);
const prevBoundaryInset = useRef(props.boundaryInset);

const updatePrevValues = useCallback(() => {
prevPositions.current = props.positions;
prevReposition.current = props.reposition;
prevTransformMode.current = props.transformMode;
prevTransform.current = props.transform;
prevBoundaryElement.current = props.boundaryElement;
prevBoundaryInset.current = props.boundaryInset;
}, [
props.boundaryElement,
props.boundaryInset,
props.positions,
props.reposition,
props.transform,
props.transformMode,
]);

return {
prev: {
positions: prevPositions.current,
reposition: prevReposition.current,
transformMode: prevTransformMode.current,
transform: prevTransform.current,
boundaryElement: prevBoundaryElement.current,
boundaryInset: prevBoundaryInset.current,
},
updatePrevValues,
};
};
4 changes: 3 additions & 1 deletion src/usePopover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export const usePopover = ({

const popoverRef = useElementRef({
containerClassName:
containerClassName != null
containerClassName != null &&
containerClassName.length > 0 &&
containerClassName !== 'react-tiny-popover-container'
? `react-tiny-popover-container ${containerClassName}`
: 'react-tiny-popover-container',
containerStyle: POPOVER_STYLE,
Expand Down

0 comments on commit 45c0f52

Please sign in to comment.