diff --git a/package.json b/package.json index 5bbccb8..3ede266 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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", diff --git a/src/Popover.tsx b/src/Popover.tsx index 89f893d..0a45a2a 100644 --- a/src/Popover.tsx +++ b/src/Popover.tsx @@ -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 }; @@ -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(); - const prevReposition = useRef(reposition); + const { prev, updatePrevValues } = useHandlePrevValues({ + positions, + reposition, + transformMode, + transform, + boundaryElement, + boundaryInset, + }); const childRef = useRef(); @@ -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); @@ -131,6 +132,8 @@ const PopoverInternal = forwardRef( }; }, [ align, + boundaryElement, + boundaryInset, isOpen, padding, popoverRef, @@ -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(() => { @@ -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); diff --git a/src/useHandlePrevValues.ts b/src/useHandlePrevValues.ts new file mode 100644 index 0000000..df3d412 --- /dev/null +++ b/src/useHandlePrevValues.ts @@ -0,0 +1,39 @@ +import { useCallback, useRef } from 'react'; +import { PopoverProps } from '.'; + +export const useHandlePrevValues = (props: Partial) => { + 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, + }; +}; diff --git a/src/usePopover.ts b/src/usePopover.ts index ce1b31c..3b7c0d5 100644 --- a/src/usePopover.ts +++ b/src/usePopover.ts @@ -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,