-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement the G2 Mover interactions (#20056)
Co-authored-by: Joen Asmussen <joen@automattic.com> Co-authored-by: Riad Benguella <benguella@gmail.com>
- Loading branch information
1 parent
819989b
commit e986412
Showing
7 changed files
with
236 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
packages/block-editor/src/components/block-toolbar/utils.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState, useRef, useEffect, useCallback } from '@wordpress/element'; | ||
|
||
const { clearTimeout, setTimeout } = window; | ||
|
||
/** | ||
* Hook that creates a showMover state, as well as debounced show/hide callbacks | ||
*/ | ||
export function useDebouncedShowMovers( { | ||
ref, | ||
isFocused, | ||
debounceTimeout = 500, | ||
} ) { | ||
const [ showMovers, setShowMovers ] = useState( false ); | ||
const timeoutRef = useRef(); | ||
|
||
const getIsHovered = () => { | ||
return ref?.current && ref.current.matches( ':hover' ); | ||
}; | ||
|
||
const shouldHideMovers = () => { | ||
const isHovered = getIsHovered(); | ||
|
||
return ! isFocused && ! isHovered; | ||
}; | ||
|
||
const debouncedShowMovers = useCallback( | ||
( event ) => { | ||
if ( event ) { | ||
event.stopPropagation(); | ||
} | ||
|
||
const timeout = timeoutRef.current; | ||
|
||
if ( timeout && clearTimeout ) { | ||
clearTimeout( timeout ); | ||
} | ||
if ( ! showMovers ) { | ||
setShowMovers( true ); | ||
} | ||
}, | ||
[ showMovers ] | ||
); | ||
|
||
const debouncedHideMovers = useCallback( | ||
( event ) => { | ||
if ( event ) { | ||
event.stopPropagation(); | ||
} | ||
|
||
timeoutRef.current = setTimeout( () => { | ||
if ( shouldHideMovers() ) { | ||
setShowMovers( false ); | ||
} | ||
}, debounceTimeout ); | ||
}, | ||
[ isFocused ] | ||
); | ||
|
||
return { | ||
showMovers, | ||
debouncedShowMovers, | ||
debouncedHideMovers, | ||
}; | ||
} | ||
|
||
/** | ||
* Hook that provides a showMovers state and gesture events for DOM elements | ||
* that interact with the showMovers state. | ||
*/ | ||
export function useShowMoversGestures( { ref, debounceTimeout = 500 } ) { | ||
const [ isFocused, setIsFocused ] = useState( false ); | ||
const { | ||
showMovers, | ||
debouncedShowMovers, | ||
debouncedHideMovers, | ||
} = useDebouncedShowMovers( { ref, debounceTimeout, isFocused } ); | ||
|
||
const registerRef = useRef( false ); | ||
|
||
const isFocusedWithin = () => { | ||
return ref && ref.current.contains( document.activeElement ); | ||
}; | ||
|
||
useEffect( () => { | ||
const node = ref.current; | ||
|
||
const handleOnFocus = () => { | ||
if ( isFocusedWithin() ) { | ||
setIsFocused( true ); | ||
debouncedShowMovers(); | ||
} | ||
}; | ||
|
||
const handleOnBlur = () => { | ||
if ( ! isFocusedWithin() ) { | ||
setIsFocused( false ); | ||
debouncedHideMovers(); | ||
} | ||
}; | ||
|
||
/** | ||
* Events are added via DOM events (vs. React synthetic events), | ||
* as the child React components swallow mouse events. | ||
*/ | ||
if ( node && ! registerRef.current ) { | ||
node.addEventListener( 'focus', handleOnFocus, true ); | ||
node.addEventListener( 'blur', handleOnBlur, true ); | ||
registerRef.current = true; | ||
} | ||
|
||
return () => { | ||
if ( node ) { | ||
node.removeEventListener( 'focus', handleOnFocus ); | ||
node.removeEventListener( 'blur', handleOnBlur ); | ||
} | ||
}; | ||
}, [ | ||
ref, | ||
registerRef, | ||
setIsFocused, | ||
debouncedShowMovers, | ||
debouncedHideMovers, | ||
] ); | ||
|
||
return { | ||
showMovers, | ||
gestures: { | ||
onMouseMove: debouncedShowMovers, | ||
onMouseLeave: debouncedHideMovers, | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters