import _ from 'lodash'; type IClientRect = Omit; export function getAbsoluteBoundingClientRect( domNode: HTMLElement | null ): IClientRect { if (!domNode) { throw new Error('getAbsoluteBoundingClientRect called without a domNode'); } const elementRect: ClientRect = domNode && domNode.getBoundingClientRect(); return { bottom: elementRect.bottom + window.pageYOffset, top: elementRect.top + window.pageYOffset, left: elementRect.left + window.pageXOffset, right: elementRect.right + window.pageXOffset, height: elementRect.height, width: elementRect.width, }; } export function scrollParentTo( domNode: HTMLElement | null, additionalOffset: number = 0 ): void { if (domNode) { const parentElement = domNode.parentElement; if (parentElement) { if (parentElement.scrollTop > domNode.offsetTop - additionalOffset) { // if the top of the node is above the scroll line, // align to top parentElement.scrollTop = domNode.offsetTop - additionalOffset; } else if ( parentElement.scrollTop + parentElement.clientHeight < domNode.offsetTop + domNode.offsetHeight ) { // else if the bottom of the node is below the fold, // align to bottom parentElement.scrollTop = domNode.offsetHeight - (parentElement.clientHeight - domNode.offsetTop); } // else don't need to align anything } } } export function dispatchDOMEvent( node: EventTarget, eventName: string, assignedEventProps?: any ) { const event = document.createEvent('Event'); event.initEvent(eventName, true, true); node.dispatchEvent(_.assign(event, assignedEventProps)); return event; } /** * sharesAncestor * * Recursively looks at `node` and its parents for `nodeName` and makes * sure it contains `siblingNode`. * * @param {Node} node - dom node to check if any of its ancestors are a `