Skip to content

Commit

Permalink
Hover hook: use ref callback (#29089)
Browse files Browse the repository at this point in the history
* Hover hook: use ref callback

* Lint
  • Loading branch information
ellatrix committed Feb 18, 2021
1 parent 39382dd commit cf03bb1
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,13 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
index
);

const isHovered = useIsHovered( ref );
const blockMovingModeClassNames = useBlockMovingModeClassNames( clientId );
const htmlSuffix = mode === 'html' && ! __unstableIsHtml ? '-visual' : '';
const mergedRefs = useMergeRefs( [ ref, useEventHandlers( clientId ) ] );
const mergedRefs = useMergeRefs( [
ref,
useEventHandlers( clientId ),
useIsHovered(),
] );

return {
...wrapperProps,
Expand All @@ -123,8 +126,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
className,
props.className,
wrapperProps.className,
blockMovingModeClassNames,
{ 'is-hovered': isHovered }
blockMovingModeClassNames
),
style: { ...wrapperProps.style, ...props.style },
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,73 +1,50 @@
/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { useRefEffect } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../../store';

/** @typedef {import('@wordpress/element').RefObject} RefObject */

/**
* Returns true when the block is hovered and in navigation or outline mode, false if not.
*
* @param {RefObject} ref React ref with the block element.
*
* @return {boolean} Hovered state.
*/
export function useIsHovered( ref ) {
const [ isHovered, setHovered ] = useState( false );

const { isNavigationMode, isOutlineMode } = useSelect( ( select ) => {
const {
isNavigationMode: selectIsNavigationMode,
getSettings,
} = select( blockEditorStore );

return {
isNavigationMode: selectIsNavigationMode(),
isOutlineMode: getSettings().outlineMode,
};
}, [] );

function addHoverListener( eventType, value ) {
function listener( event ) {
if ( event.defaultPrevented ) {
return;
}

event.preventDefault();
setHovered( value );
}

ref.current.addEventListener( eventType, listener );
return [ eventType, listener ];
function listener( event ) {
if ( event.defaultPrevented ) {
return;
}

function addHoverListeners() {
const hoverListeners = [];

hoverListeners.push( addHoverListener( 'mouseout', false ) );
const action = event.type === 'mouseover' ? 'add' : 'remove';

if ( isOutlineMode || isNavigationMode ) {
hoverListeners.push( addHoverListener( 'mouseover', true ) );
}
event.preventDefault();
event.currentTarget.classList[ action ]( 'is-hovered' );
}

return hoverListeners;
}
/**
* Adds `is-hovered` class when the block is hovered and in navigation or
* outline mode.
*/
export function useIsHovered() {
const isEnabled = useSelect( ( select ) => {
const { isNavigationMode, getSettings } = select( blockEditorStore );
return isNavigationMode() || getSettings().outlineMode;
}, [] );

useEffect( () => {
const hoverListeners = addHoverListeners();
return useRefEffect(
( node ) => {
if ( isEnabled ) {
node.addEventListener( 'mouseout', listener );
node.addEventListener( 'mouseover', listener );

return () => {
hoverListeners.forEach( ( [ eventType, listener ] ) =>
ref.current.removeEventListener( eventType, listener )
);
};
}, [ isOutlineMode, isNavigationMode ] );
return () => {
node.removeEventListener( 'mouseout', listener );
node.removeEventListener( 'mouseover', listener );

return isHovered;
// Remove class in case it lingers.
node.classList.remove( 'is-hovered' );
};
}
},
[ isEnabled ]
);
}

0 comments on commit cf03bb1

Please sign in to comment.