112 lines
2.5 KiB
TypeScript
112 lines
2.5 KiB
TypeScript
/**
|
|
* External dependencies
|
|
*/
|
|
import { useState } from 'react';
|
|
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { ENABLE_CLICK_CLASS } from './auto-block-preview-event-listener';
|
|
|
|
export enum PopoverStatus {
|
|
VISIBLE = 'VISIBLE',
|
|
HIDDEN = 'HIDDEN',
|
|
}
|
|
|
|
type VirtualElement = Pick< Element, 'getBoundingClientRect' >;
|
|
|
|
const generateGetBoundingClientRect = ( x = 0, y = 0 ) => {
|
|
return () => ( {
|
|
width: 0,
|
|
height: 0,
|
|
top: y,
|
|
right: x,
|
|
bottom: y,
|
|
left: x,
|
|
} );
|
|
};
|
|
|
|
let clickedClientId: string | null = null;
|
|
let hoveredClientId: string | null = null;
|
|
|
|
export const usePopoverHandler = () => {
|
|
const [ popoverStatus, setPopoverStatus ] = useState< PopoverStatus >(
|
|
PopoverStatus.HIDDEN
|
|
);
|
|
|
|
const defaultVirtualElement = {
|
|
getBoundingClientRect: generateGetBoundingClientRect(),
|
|
} as VirtualElement;
|
|
|
|
const [ virtualElement, setVirtualElement ] = useState< VirtualElement >(
|
|
defaultVirtualElement
|
|
);
|
|
|
|
const hidePopover = () => {
|
|
setPopoverStatus( PopoverStatus.HIDDEN );
|
|
clickedClientId = null;
|
|
hoveredClientId = null;
|
|
};
|
|
|
|
const updatePopoverPosition = ( {
|
|
event,
|
|
clickedBlockClientId,
|
|
hoveredBlockClientId,
|
|
}: {
|
|
event: MouseEvent;
|
|
clickedBlockClientId: string | null;
|
|
hoveredBlockClientId: string | null;
|
|
} ) => {
|
|
const iframe = window.document.querySelector(
|
|
'.woocommerce-customize-store-assembler > iframe[name="editor-canvas"]'
|
|
) as HTMLElement;
|
|
|
|
const target = event.target as HTMLElement;
|
|
|
|
// If the hover event is over elements with an ENABLE_CLICK_CLASS, hide the popover.
|
|
// This is because it's likely the "No Blocks" placeholder and we don't want the popover to show since its interactive.
|
|
if ( target.classList.contains( ENABLE_CLICK_CLASS ) ) {
|
|
hidePopover();
|
|
return;
|
|
}
|
|
|
|
clickedClientId =
|
|
clickedBlockClientId === null
|
|
? clickedClientId
|
|
: clickedBlockClientId;
|
|
hoveredClientId =
|
|
hoveredBlockClientId === null
|
|
? hoveredClientId
|
|
: hoveredBlockClientId;
|
|
|
|
if ( clickedClientId === hoveredClientId ) {
|
|
if ( popoverStatus === PopoverStatus.HIDDEN ) {
|
|
setPopoverStatus( PopoverStatus.VISIBLE );
|
|
}
|
|
|
|
const iframeRect = iframe.getBoundingClientRect();
|
|
|
|
const newElement = {
|
|
getBoundingClientRect: generateGetBoundingClientRect(
|
|
event.clientX + iframeRect.left,
|
|
event.clientY + iframeRect.top + 20
|
|
),
|
|
} as VirtualElement;
|
|
|
|
setVirtualElement( newElement );
|
|
return;
|
|
}
|
|
|
|
setPopoverStatus( PopoverStatus.HIDDEN );
|
|
clickedClientId = null;
|
|
};
|
|
|
|
return [
|
|
popoverStatus,
|
|
virtualElement,
|
|
updatePopoverPosition,
|
|
hidePopover,
|
|
setPopoverStatus,
|
|
] as const;
|
|
};
|