Skip to content

Commit

Permalink
Remove unused is-hovered class (#19390)
Browse files Browse the repository at this point in the history
* Remove unused is-hovered class

* Revert 0d0c8e0d55849529227df3540ad35ff3edf5be5b
  • Loading branch information
ellatrix authored Jan 3, 2020
1 parent d8f6d64 commit 431f76c
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 112 deletions.
69 changes: 1 addition & 68 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,59 +125,6 @@ function BlockListBlock( {

const breadcrumb = useRef();

// Keep track of touchstart to disable hover on iOS
const hadTouchStart = useRef( false );
const onTouchStart = () => {
hadTouchStart.current = true;
};
const onTouchStop = () => {
// Clear touchstart detection
// Browser will try to emulate mouse events also see https://www.html5rocks.com/en/mobile/touchandmouse/
hadTouchStart.current = false;
};

// Handling isHovered
const [ isBlockHovered, setBlockHoveredState ] = useState( false );

/**
* Sets the block state as unhovered if currently hovering. There are cases
* where mouseleave may occur but the block is not hovered (multi-select),
* so to avoid unnecesary renders, the state is only set if hovered.
*/
const hideHoverEffects = () => {
if ( isBlockHovered ) {
setBlockHoveredState( false );
}
};
/**
* A mouseover event handler to apply hover effect when a pointer device is
* placed within the bounds of the block. The mouseover event is preferred
* over mouseenter because it may be the case that a previous mouseenter
* event was blocked from being handled by a IgnoreNestedEvents component,
* therefore transitioning out of a nested block to the bounds of the block
* would otherwise not trigger a hover effect.
*
* @see https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter
*/
const maybeHover = () => {
if (
isBlockHovered ||
isPartOfMultiSelection ||
isSelected ||
hadTouchStart.current
) {
return;
}
setBlockHoveredState( true );
};

// Set hover to false once we start typing or select the block.
useEffect( () => {
if ( isTypingWithinBlock || isSelected ) {
hideHoverEffects();
}
} );

// Handling the error state
const [ hasError, setErrorState ] = useState( false );
const onBlockError = () => setErrorState( true );
Expand Down Expand Up @@ -389,8 +336,6 @@ function BlockListBlock( {
if ( isSelected && ( buttons || which ) === 1 ) {
onSelectionStart( clientId );
}

hideHoverEffects();
};

const selectOnOpen = ( open ) => {
Expand All @@ -413,7 +358,6 @@ function BlockListBlock( {
);

// Rendering the output
const isHovered = isBlockHovered && ! isPartOfMultiSelection;
const blockType = getBlockType( name );
// translators: %s: Type of block (i.e. Text, Image etc)
const blockLabel = sprintf( __( 'Block: %s' ), blockType.title );
Expand All @@ -424,17 +368,12 @@ function BlockListBlock( {

// If the block is selected and we're typing the block should not appear.
// Empty paragraph blocks should always show up as unselected.
const showEmptyBlockSideInserter = ! isNavigationMode && ( isSelected || isHovered || isLast ) && isEmptyDefaultBlock && isValid;
const showEmptyBlockSideInserter = ! isNavigationMode && ( isSelected || isLast ) && isEmptyDefaultBlock && isValid;
const shouldAppearSelected =
! isFocusMode &&
! showEmptyBlockSideInserter &&
isSelected &&
! isTypingWithinBlock;
const shouldAppearHovered =
! isFocusMode &&
! hasFixedToolbar &&
isHovered &&
! isEmptyDefaultBlock;
const shouldShowBreadcrumb = isNavigationMode && isSelected;
const shouldShowContextualToolbar =
! isNavigationMode &&
Expand Down Expand Up @@ -467,7 +406,6 @@ function BlockListBlock( {
'is-selected': shouldAppearSelected && hasSelectedUI,
'is-navigate-mode': isNavigationMode,
'is-multi-selected': isMultiSelected,
'is-hovered': shouldAppearHovered,
'is-reusable': isReusableBlock( blockType ),
'is-dragging': isDragging,
'is-typing': isTypingWithinBlock,
Expand Down Expand Up @@ -534,14 +472,9 @@ function BlockListBlock( {
<IgnoreNestedEvents
id={ blockElementId }
ref={ wrapper }
onMouseOver={ maybeHover }
onMouseOverHandled={ hideHoverEffects }
onMouseLeave={ hideHoverEffects }
className={ wrapperClassName }
data-type={ name }
onTouchStart={ onTouchStart }
onFocus={ onFocus }
onClick={ onTouchStop }
onKeyDown={ onKeyDown }
tabIndex="0"
aria-label={ blockLabel }
Expand Down
27 changes: 8 additions & 19 deletions packages/block-editor/src/components/ignore-nested-events/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ export class IgnoreNestedEvents extends Component {
* @param {Event} event Event object.
*/
proxyEvent( event ) {
const isHandled = !! event.nativeEvent._blockHandled;
// Skip if already handled (i.e. assume nested block)
if ( event.nativeEvent._blockHandled ) {
return;
}

// Assign into the native event, since React will reuse their synthetic
// event objects and this property assignment could otherwise leak.
Expand All @@ -50,13 +53,7 @@ export class IgnoreNestedEvents extends Component {
event.nativeEvent._blockHandled = true;

// Invoke original prop handler
let propKey = this.eventMap[ event.type ];

// If already handled (i.e. assume nested block), only invoke a
// corresponding "Handled"-suffixed prop callback.
if ( isHandled ) {
propKey += 'Handled';
}
const propKey = this.eventMap[ event.type ];

if ( this.props[ propKey ] ) {
this.props[ propKey ]( event );
Expand All @@ -71,24 +68,16 @@ export class IgnoreNestedEvents extends Component {
...Object.keys( props ),
], ( result, key ) => {
// Try to match prop key as event handler
const match = key.match( /^on([A-Z][a-zA-Z]+?)(Handled)?$/ );
const match = key.match( /^on([A-Z][a-zA-Z]+)$/ );
if ( match ) {
const isHandledProp = !! match[ 2 ];
if ( isHandledProp ) {
// Avoid assigning through the invalid prop key. This
// assumes mutation of shallow clone by above spread.
delete props[ key ];
}

// Re-map the prop to the local proxy handler to check whether
// the event has already been handled.
const proxiedPropName = 'on' + match[ 1 ];
result[ proxiedPropName ] = this.proxyEvent;
result[ key ] = this.proxyEvent;

// Assign event -> propName into an instance variable, so as to
// avoid re-renders which could be incurred either by setState
// or in mapping values to a newly created function.
this.eventMap[ match[ 1 ].toLowerCase() ] = proxiedPropName;
this.eventMap[ match[ 1 ].toLowerCase() ] = key;
}

return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { mount } from 'enzyme';
import { shallow } from 'enzyme';

/**
* Internal dependencies
Expand All @@ -10,24 +10,24 @@ import { IgnoreNestedEvents } from '../';

describe( 'IgnoreNestedEvents', () => {
it( 'passes props to its rendered div', () => {
const wrapper = mount(
const wrapper = shallow(
<IgnoreNestedEvents className="foo" />
);

expect( wrapper.find( 'div' ) ).toHaveLength( 1 );
expect( wrapper.type() ).toBe( 'div' );
expect( wrapper.prop( 'className' ) ).toBe( 'foo' );
} );

it( 'stops propagation of events to ancestor IgnoreNestedEvents', () => {
const spyOuter = jest.fn();
const spyInner = jest.fn();
const wrapper = mount(
const wrapper = shallow(
<IgnoreNestedEvents onClick={ spyOuter }>
<IgnoreNestedEvents onClick={ spyInner } />
</IgnoreNestedEvents>
);

wrapper.find( 'div' ).last().simulate( 'click' );
wrapper.childAt( 0 ).simulate( 'click' );

expect( spyInner ).toHaveBeenCalled();
expect( spyOuter ).not.toHaveBeenCalled();
Expand All @@ -36,7 +36,7 @@ describe( 'IgnoreNestedEvents', () => {
it( 'stops propagation of child handled events', () => {
const spyOuter = jest.fn();
const spyInner = jest.fn();
const wrapper = mount(
const wrapper = shallow(
<IgnoreNestedEvents onClick={ spyOuter }>
<IgnoreNestedEvents childHandledEvents={ [ 'onClick' ] }>
<div />
Expand All @@ -51,23 +51,4 @@ describe( 'IgnoreNestedEvents', () => {
expect( spyInner ).not.toHaveBeenCalled();
expect( spyOuter ).not.toHaveBeenCalled();
} );

it( 'invokes callback of Handled-suffixed prop if handled', () => {
const spyOuter = jest.fn();
const spyInner = jest.fn();
const wrapper = mount(
<IgnoreNestedEvents onClickHandled={ spyOuter }>
<IgnoreNestedEvents childHandledEvents={ [ 'onClick' ] }>
<div />
<IgnoreNestedEvents onClick={ spyInner } />
</IgnoreNestedEvents>
</IgnoreNestedEvents>
);

const div = wrapper.childAt( 0 ).childAt( 0 );
div.simulate( 'click' );

expect( spyInner ).not.toHaveBeenCalled();
expect( spyOuter ).toHaveBeenCalled();
} );
} );

0 comments on commit 431f76c

Please sign in to comment.