UNPKG

@wordpress/components

Version:
179 lines (167 loc) 4.3 kB
/** * External dependencies */ import { some } from 'lodash'; import classnames from 'classnames'; /** * WordPress dependencies */ import { useRef, useReducer } from '@wordpress/element'; /** * Internal dependencies */ import ControlPoints from './control-points'; import { getHorizontalRelativeGradientPosition } from './utils'; import { INSERT_POINT_WIDTH, MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT, } from './constants'; function customGradientBarReducer( state, action ) { switch ( action.type ) { case 'MOVE_INSERTER': if ( state.id === 'IDLE' || state.id === 'MOVING_INSERTER' ) { return { id: 'MOVING_INSERTER', insertPosition: action.insertPosition, }; } break; case 'STOP_INSERTER_MOVE': if ( state.id === 'MOVING_INSERTER' ) { return { id: 'IDLE', }; } break; case 'OPEN_INSERTER': if ( state.id === 'MOVING_INSERTER' ) { return { id: 'INSERTING_CONTROL_POINT', insertPosition: state.insertPosition, }; } break; case 'CLOSE_INSERTER': if ( state.id === 'INSERTING_CONTROL_POINT' ) { return { id: 'IDLE', }; } break; case 'START_CONTROL_CHANGE': if ( state.id === 'IDLE' ) { return { id: 'MOVING_CONTROL_POINT', }; } break; case 'STOP_CONTROL_CHANGE': if ( state.id === 'MOVING_CONTROL_POINT' ) { return { id: 'IDLE', }; } break; } return state; } const customGradientBarReducerInitialState = { id: 'IDLE' }; export default function CustomGradientBar( { background, hasGradient, value: controlPoints, onChange, disableInserter = false, disableAlpha = false, } ) { const gradientPickerDomRef = useRef(); const [ gradientBarState, gradientBarStateDispatch ] = useReducer( customGradientBarReducer, customGradientBarReducerInitialState ); const onMouseEnterAndMove = ( event ) => { const insertPosition = getHorizontalRelativeGradientPosition( event.clientX, gradientPickerDomRef.current, INSERT_POINT_WIDTH ); // If the insert point is close to an existing control point don't show it. if ( some( controlPoints, ( { position } ) => { return ( Math.abs( insertPosition - position ) < MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT ); } ) ) { if ( gradientBarState.id === 'MOVING_INSERTER' ) { gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } ); } return; } gradientBarStateDispatch( { type: 'MOVE_INSERTER', insertPosition } ); }; const onMouseLeave = () => { gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } ); }; const isMovingInserter = gradientBarState.id === 'MOVING_INSERTER'; const isInsertingControlPoint = gradientBarState.id === 'INSERTING_CONTROL_POINT'; return ( <div ref={ gradientPickerDomRef } className={ classnames( 'components-custom-gradient-picker__gradient-bar', { 'has-gradient': hasGradient } ) } onMouseEnter={ onMouseEnterAndMove } onMouseMove={ onMouseEnterAndMove } style={ { background } } onMouseLeave={ onMouseLeave } > <div className="components-custom-gradient-picker__markers-container"> { ! disableInserter && ( isMovingInserter || isInsertingControlPoint ) && ( <ControlPoints.InsertPoint disableAlpha={ disableAlpha } insertPosition={ gradientBarState.insertPosition } value={ controlPoints } onChange={ onChange } onOpenInserter={ () => { gradientBarStateDispatch( { type: 'OPEN_INSERTER', } ); } } onCloseInserter={ () => { gradientBarStateDispatch( { type: 'CLOSE_INSERTER', } ); } } /> ) } <ControlPoints disableAlpha={ disableAlpha } disableRemove={ disableInserter } gradientPickerDomRef={ gradientPickerDomRef } ignoreMarkerPosition={ isInsertingControlPoint ? gradientBarState.insertPosition : undefined } value={ controlPoints } onChange={ onChange } onStartControlPointChange={ () => { gradientBarStateDispatch( { type: 'START_CONTROL_CHANGE', } ); } } onStopControlPointChange={ () => { gradientBarStateDispatch( { type: 'STOP_CONTROL_CHANGE', } ); } } /> </div> </div> ); }