Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
vcanales committed Feb 11, 2021
1 parent 4200a9d commit ea9c9c4
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 51 deletions.
25 changes: 16 additions & 9 deletions packages/block-library/src/navigation/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import mergeRefs from 'react-merge-refs';
/**
* WordPress dependencies
*/
import { useCallback, useRef, useState } from '@wordpress/element';
import { useCallback, useMemo, useRef, useState } from '@wordpress/element';
import {
InnerBlocks,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
Expand All @@ -31,6 +31,7 @@ import {
justifySpaceBetween,
} from '@wordpress/icons';
import useAutohide from './use-autohide';
import useMaxHeight from './use-max-height';
import NavigationPlaceholder from './placeholder';
import PlaceholderPreview from './placeholder-preview';

Expand All @@ -40,6 +41,7 @@ function Navigation( {
setAttributes,
clientId,
hasExistingNavItems,
innerBlocks,
isImmediateParentOfSelectedBlock,
isSelected,
updateInnerBlocks,
Expand All @@ -60,18 +62,26 @@ function Navigation( {
);

const navElement = useRef( null );
const wrappedElementsContainer = useRef( null );
const navItemsElement = useRef( null );

const { selectBlock } = useDispatch( 'core/block-editor' );

const [ isWrapping ] = useAutohide( navElement, wrappedElementsContainer );
const containerHeight = useMaxHeight( navItemsElement );
const { isWrapping } = useAutohide(
clientId,
innerBlocks,
navItemsElement
);

const blockProps = useBlockProps( {
className: classnames( className, {
[ `items-justified-${ attributes.itemsJustification }` ]: attributes.itemsJustification,
'is-vertical': attributes.orientation === 'vertical',
wrapping: isWrapping,
} ),
style: {
height: containerHeight || 'auto',
},
} );

const { navigatorToolbarButton, navigatorModal } = useBlockNavigator(
Expand Down Expand Up @@ -114,8 +124,8 @@ function Navigation( {
[ blockProps.ref, navElement ]
);
const mergedInnerBlocksRefs = useCallback(
mergeRefs( [ innerBlocksProps.ref, wrappedElementsContainer ] ),
[ innerBlocksProps.ref, wrappedElementsContainer ]
mergeRefs( [ innerBlocksProps.ref, navItemsElement ] ),
[ innerBlocksProps.ref, navItemsElement ]
);

if ( isPlaceholderShown ) {
Expand Down Expand Up @@ -224,10 +234,6 @@ function Navigation( {
type="checkbox"
/>
<ul { ...innerBlocksProps } ref={ mergedInnerBlocksRefs } />
<ul
ref={ wrappedElementsContainer }
className="nav-wrapped-items"
/>
<label htmlFor="nav-toggle" className="nav-button">
More
</label>
Expand All @@ -253,6 +259,7 @@ export default compose( [
selectedBlockId,
] )?.length;
return {
innerBlocks,
isImmediateParentOfSelectedBlock,
selectedBlockHasDescendants,
hasExistingNavItems: !! innerBlocks.length,
Expand Down
1 change: 0 additions & 1 deletion packages/block-library/src/navigation/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

.wp-block-navigation__container {
display: flex;
height: 61.6px;
overflow: hidden;
background-color: rgba( 0, 255, 0, 0.2 );
flex-grow: 1;
Expand Down
101 changes: 60 additions & 41 deletions packages/block-library/src/navigation/use-autohide.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,80 @@
/**
* External dependencies
*/
import { debounce } from 'lodash';
/**
* WordPress dependencies
*/
import { useDispatch } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';

export default function useAutohide( navElement, wrappedElementsContainer ) {
const [ isWrapping, setIsWrapping ] = useState( false );
export default function useAutohide( clientId, innerBlocks, ref ) {
const [ state, setState ] = useState( {
isWrapping: false,
visibilityMap: [],
} );

useEffect( () => {
if ( navElement && wrappedElementsContainer ) {
let timeout;
const handleResize = debounce( ( nav ) => {
const { bottom } = nav.getBoundingClientRect();

const { bottom } = navElement.current.getBoundingClientRect();
const items = Array.from( nav.childNodes );
const visibilityMap = items.reduce( ( result, el ) => {
const isHidden = el.getBoundingClientRect().y >= bottom;
const [ , blockId ] = el.id.split( 'block-' );

function handleResize() {
if ( timeout ) {
window.cancelAnimationFrame( timeout );
}
return {
...result,
[ blockId ]: isHidden,
};
}, {} );
const hasWrappedElements = Object.values( visibilityMap ).some(
( item ) => item.isHidden
);

timeout = window.requestAnimationFrame( () => {
const items = Array.from( navElement.current.childNodes ); // i need to work in terms of react component
// Using the rendered DOM nodes does not allow me to alter props.
// I would also like to use react in order to move the components around.
// I can do this by storing arrays of elements.
// Moving the elements from the main container to the wrapped elements container is actually easier with react. cool.
setState( {
isWrapping: hasWrappedElements,
visibilityMap,
} );
}, 100 );

const hasWrappedElements = items.some( ( el ) => {
const isBelowBottom =
el.getBoundingClientRect().y >= bottom;
useEffect( () => {
const element = ref.current;

// @todo: move this side effect elsewhere.
el.classList.toggle( 'wrapped', isBelowBottom );
if ( ! element ) {
return;
}

const elementCopy = el.cloneNode( true );
const { ownerDocument } = element;

if ( isBelowBottom ) {
wrappedElementsContainer.append( elementCopy );
}
window.addEventListener(
'resize',
() => handleResize( element ),
false
);

return isBelowBottom;
} );
handleResize( element );

setIsWrapping( hasWrappedElements );
} );
}
return () => {
window.removeEventListener( 'resize', () =>
handleResize( element )
);
};
}, [ innerBlocks ] );

window.addEventListener( 'resize', handleResize, false );
const updatedBlocks = innerBlocks.map( ( block ) => ( {
...block,
isHidden: state.visibilityMap[ block.clientId ],
} ) );

handleResize();
console.log( updatedBlocks );

return () => {
// remove resize listener
if ( navElement ) {
window.removeEventListener( 'resize', handleResize );
}
};
}
}, [ navElement, wrappedElementsContainer ] );
useDispatch( ( dispatch ) =>
dispatch( 'core/block-editor' ).replaceInnerBlocks(
clientId,
updatedBlocks,
true
)
);

return [ isWrapping ];
return state;
}
9 changes: 9 additions & 0 deletions packages/block-library/src/navigation/use-max-height.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function ( navItemsElement ) {
if ( navItemsElement && null !== navItemsElement.current ) {
const items = Array.from( navItemsElement.current.childNodes );

return window.getComputedStyle( items[ 0 ] ).height;
}

return 0;
}

0 comments on commit ea9c9c4

Please sign in to comment.