<commit_before>/**
 * External dependencies
 */
import PropTypes from 'prop-types';

/**
 * WordPress dependencies
 */
import { useCallback, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Context from './context';

function DropZoneProvider( { children } ) {
	const [ dropZones, setDropZones ] = useState( [] );
	const [ hoveredDropZone, setHoveredDropZone ] = useState( null );

	const registerDropZone = useCallback(
		( dropZone ) => {
			// If dropZone isn't registered yet.
			if ( dropZone && ! dropZones.some( ( { node } ) => node === dropZone.node ) ) {
				setDropZones( ( oldDropZones ) => ( [ ...oldDropZones, dropZone ] ) );
			}
		}, [ dropZones ] );

	// Unregisters dropzones which node's don't exist.
	const unregisterDropZone = useCallback(
		( dropZone ) => {
			// If dropZone needs unregistering.
			if ( dropZones.some( ( dz ) => dz === dropZone ) ) {
				setDropZones( ( oldDropZones ) => oldDropZones.filter( ( dz ) => dz !== dropZone ) );
			}
		}, [ dropZones ] );

	const isWithinElementBounds = ( element, x, y ) => {
		const rect = element.getBoundingClientRect();
		if ( rect.bottom === rect.top || rect.left === rect.right ) {
			return false;
		}
		return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
	};

	const resetHoverState = () => {
		setHoveredDropZone( null );
	};

	const onDragOver = ( evt ) => {
		evt.preventDefault();
		// Get the hovered dropzone. // @todo Consider dropzone inside dropzone, will we need this?
		const foundDropZones = dropZones.filter( ( dropZone ) => {
			return isWithinElementBounds( dropZone.node, evt.clientX, evt.clientY );
		} );

		// If there was a dropzone before and nothing was found now, reset.
		if ( hoveredDropZone && ! foundDropZones.length ) {
			resetHoverState();
			return;
		}
		const foundDropZone = foundDropZones[ 0 ];
		// If dropzone not found, do nothing.
		if ( ! foundDropZone || ! foundDropZone.node ) {
			return;
		}
		const rect = foundDropZone.node.getBoundingClientRect();

		const position = {
			x: evt.clientX - rect.left < rect.right - evt.clientX ? 'left' : 'right',
			y: evt.clientY - rect.top < rect.bottom - evt.clientY ? 'top' : 'bottom',
		};

		setHoveredDropZone( {
			node: foundDropZone.node,
			position,
		} );
	};

	const state = {
		state: {
			hoveredDropZone,
			dropZones,
		},
		actions: {
			registerDropZone,
			unregisterDropZone,
			resetHoverState,
		},
	};
	return (
		<div onDragOver={ onDragOver }>
			<Context.Provider value={ state }>
				{ children }
			</Context.Provider>
		</div>
	);
}

DropZoneProvider.propTypes = {
	children: PropTypes.oneOfType( [
		PropTypes.arrayOf( PropTypes.node ),
		PropTypes.node,
	] ).isRequired,
};

export default DropZoneProvider;<commit_msg>Fix: Add height to dropzoneprovider div. (#4165)<commit_after>/**
 * External dependencies
 */
import PropTypes from 'prop-types';
import styled from 'styled-components';

/**
 * WordPress dependencies
 */
import { useCallback, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Context from './context';

const DropZoneWrapper = styled.div`
	height: 100%;
`;

function DropZoneProvider( { children } ) {
	const [ dropZones, setDropZones ] = useState( [] );
	const [ hoveredDropZone, setHoveredDropZone ] = useState( null );

	const registerDropZone = useCallback(
		( dropZone ) => {
			// If dropZone isn't registered yet.
			if ( dropZone && ! dropZones.some( ( { node } ) => node === dropZone.node ) ) {
				setDropZones( ( oldDropZones ) => ( [ ...oldDropZones, dropZone ] ) );
			}
		}, [ dropZones ] );

	// Unregisters dropzones which node's don't exist.
	const unregisterDropZone = useCallback(
		( dropZone ) => {
			// If dropZone needs unregistering.
			if ( dropZones.some( ( dz ) => dz === dropZone ) ) {
				setDropZones( ( oldDropZones ) => oldDropZones.filter( ( dz ) => dz !== dropZone ) );
			}
		}, [ dropZones ] );

	const isWithinElementBounds = ( element, x, y ) => {
		const rect = element.getBoundingClientRect();
		if ( rect.bottom === rect.top || rect.left === rect.right ) {
			return false;
		}
		return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
	};

	const resetHoverState = () => {
		setHoveredDropZone( null );
	};

	const onDragOver = ( evt ) => {
		evt.preventDefault();
		// Get the hovered dropzone. // @todo Consider dropzone inside dropzone, will we need this?
		const foundDropZones = dropZones.filter( ( dropZone ) => {
			return isWithinElementBounds( dropZone.node, evt.clientX, evt.clientY );
		} );

		// If there was a dropzone before and nothing was found now, reset.
		if ( hoveredDropZone && ! foundDropZones.length ) {
			resetHoverState();
			return;
		}
		const foundDropZone = foundDropZones[ 0 ];
		// If dropzone not found, do nothing.
		if ( ! foundDropZone || ! foundDropZone.node ) {
			return;
		}
		const rect = foundDropZone.node.getBoundingClientRect();

		const position = {
			x: evt.clientX - rect.left < rect.right - evt.clientX ? 'left' : 'right',
			y: evt.clientY - rect.top < rect.bottom - evt.clientY ? 'top' : 'bottom',
		};

		setHoveredDropZone( {
			node: foundDropZone.node,
			position,
		} );
	};

	const state = {
		state: {
			hoveredDropZone,
			dropZones,
		},
		actions: {
			registerDropZone,
			unregisterDropZone,
			resetHoverState,
		},
	};
	return (
		<DropZoneWrapper onDragOver={ onDragOver }>
			<Context.Provider value={ state }>
				{ children }
			</Context.Provider>
		</DropZoneWrapper>
	);
}

DropZoneProvider.propTypes = {
	children: PropTypes.oneOfType( [
		PropTypes.arrayOf( PropTypes.node ),
		PropTypes.node,
	] ).isRequired,
};

export default DropZoneProvider;
{'fraction_non_alphanumeric': 0.1466971187631764, 'fraction_numerical': 0.0015811665495432186, 'mean_word_length': 3.2836719337848006, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4228664', 'n_tokens_mistral': 2070, 'n_tokens_neox': 1881, 'n_words': 444}