UNPKG

@wordpress/block-editor

Version:
8 lines (7 loc) 7.5 kB
{ "version": 3, "sources": ["../../../src/components/block-toolbar/utils.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { useState, useRef, useEffect } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\nconst { clearTimeout, setTimeout } = window;\nconst DEBOUNCE_TIMEOUT = 200;\n\n/**\n * Hook that creates debounced callbacks when the node is hovered or focused.\n *\n * @param {Object} props Component props.\n * @param {Object} props.ref Element reference.\n * @param {boolean} props.isFocused Whether the component has current focus.\n * @param {number} props.highlightParent Whether to highlight the parent block. It defaults in highlighting the selected block.\n * @param {number} [props.debounceTimeout=250] Debounce timeout in milliseconds.\n */\nfunction useDebouncedShowGestures( {\n\tref,\n\tisFocused,\n\thighlightParent,\n\tdebounceTimeout = DEBOUNCE_TIMEOUT,\n} ) {\n\tconst { getSelectedBlockClientId, getBlockRootClientId } =\n\t\tuseSelect( blockEditorStore );\n\tconst { toggleBlockHighlight } = useDispatch( blockEditorStore );\n\tconst timeoutRef = useRef();\n\tconst isDistractionFree = useSelect(\n\t\t( select ) =>\n\t\t\tselect( blockEditorStore ).getSettings().isDistractionFree,\n\t\t[]\n\t);\n\tconst handleOnChange = ( nextIsFocused ) => {\n\t\tif ( nextIsFocused && isDistractionFree ) {\n\t\t\treturn;\n\t\t}\n\t\tconst selectedBlockClientId = getSelectedBlockClientId();\n\t\tconst clientId = highlightParent\n\t\t\t? getBlockRootClientId( selectedBlockClientId )\n\t\t\t: selectedBlockClientId;\n\t\ttoggleBlockHighlight( clientId, nextIsFocused );\n\t};\n\n\tconst getIsHovered = () => {\n\t\treturn ref?.current && ref.current.matches( ':hover' );\n\t};\n\n\tconst shouldHideGestures = () => {\n\t\tconst isHovered = getIsHovered();\n\t\treturn ! isFocused && ! isHovered;\n\t};\n\n\tconst clearTimeoutRef = () => {\n\t\tconst timeout = timeoutRef.current;\n\n\t\tif ( timeout && clearTimeout ) {\n\t\t\tclearTimeout( timeout );\n\t\t}\n\t};\n\n\tconst debouncedShowGestures = ( event ) => {\n\t\tif ( event ) {\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\tclearTimeoutRef();\n\t\thandleOnChange( true );\n\t};\n\n\tconst debouncedHideGestures = ( event ) => {\n\t\tif ( event ) {\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\tclearTimeoutRef();\n\n\t\ttimeoutRef.current = setTimeout( () => {\n\t\t\tif ( shouldHideGestures() ) {\n\t\t\t\thandleOnChange( false );\n\t\t\t}\n\t\t}, debounceTimeout );\n\t};\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\t/**\n\t\t\t * We need to call the change handler with `isFocused`\n\t\t\t * set to false on unmount because we also clear the\n\t\t\t * timeout that would handle that.\n\t\t\t */\n\t\t\thandleOnChange( false );\n\t\t\tclearTimeoutRef();\n\t\t},\n\t\t[]\n\t);\n\n\treturn {\n\t\tdebouncedShowGestures,\n\t\tdebouncedHideGestures,\n\t};\n}\n\n/**\n * Hook that provides gesture events for DOM elements\n * that interact with the isFocused state.\n *\n * @param {Object} props Component props.\n * @param {Object} props.ref Element reference.\n * @param {number} [props.highlightParent=false] Whether to highlight the parent block. It defaults to highlighting the selected block.\n * @param {number} [props.debounceTimeout=250] Debounce timeout in milliseconds.\n */\nexport function useShowHoveredOrFocusedGestures( {\n\tref,\n\thighlightParent = false,\n\tdebounceTimeout = DEBOUNCE_TIMEOUT,\n} ) {\n\tconst [ isFocused, setIsFocused ] = useState( false );\n\tconst { debouncedShowGestures, debouncedHideGestures } =\n\t\tuseDebouncedShowGestures( {\n\t\t\tref,\n\t\t\tdebounceTimeout,\n\t\t\tisFocused,\n\t\t\thighlightParent,\n\t\t} );\n\n\tconst registerRef = useRef( false );\n\n\tconst isFocusedWithin = () => {\n\t\treturn (\n\t\t\tref?.current &&\n\t\t\tref.current.contains( ref.current.ownerDocument.activeElement )\n\t\t);\n\t};\n\n\tuseEffect( () => {\n\t\tconst node = ref.current;\n\n\t\tconst handleOnFocus = () => {\n\t\t\tif ( isFocusedWithin() ) {\n\t\t\t\tsetIsFocused( true );\n\t\t\t\tdebouncedShowGestures();\n\t\t\t}\n\t\t};\n\n\t\tconst handleOnBlur = () => {\n\t\t\tif ( ! isFocusedWithin() ) {\n\t\t\t\tsetIsFocused( false );\n\t\t\t\tdebouncedHideGestures();\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Events are added via DOM events (vs. React synthetic events),\n\t\t * as the child React components swallow mouse events.\n\t\t */\n\t\tif ( node && ! registerRef.current ) {\n\t\t\tnode.addEventListener( 'focus', handleOnFocus, true );\n\t\t\tnode.addEventListener( 'blur', handleOnBlur, true );\n\t\t\tregisterRef.current = true;\n\t\t}\n\n\t\treturn () => {\n\t\t\tif ( node ) {\n\t\t\t\tnode.removeEventListener( 'focus', handleOnFocus );\n\t\t\t\tnode.removeEventListener( 'blur', handleOnBlur );\n\t\t\t}\n\t\t};\n\t}, [\n\t\tref,\n\t\tregisterRef,\n\t\tsetIsFocused,\n\t\tdebouncedShowGestures,\n\t\tdebouncedHideGestures,\n\t] );\n\n\treturn {\n\t\tonMouseMove: debouncedShowGestures,\n\t\tonMouseLeave: debouncedHideGestures,\n\t};\n}\n"], "mappings": "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", "names": ["blockEditorStore"] }