Skip to content

Commit

Permalink
BoxControl: Allow configurable sides (#30606)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw authored Apr 19, 2021
1 parent 7d4b8a7 commit be7ae06
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 65 deletions.
9 changes: 5 additions & 4 deletions packages/components/src/box-control/all-input-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default function AllInputControl( {
onHoverOn = noop,
onHoverOff = noop,
values,
sides,
...props
} ) {
const allValue = getAllValue( values );
Expand All @@ -28,11 +29,11 @@ export default function AllInputControl( {

const handleOnChange = ( next ) => {
const nextValues = { ...values };
const selectedSides = sides?.length
? sides
: [ 'top', 'right', 'bottom', 'left' ];

nextValues.top = next;
nextValues.bottom = next;
nextValues.left = next;
nextValues.right = next;
selectedSides.forEach( ( side ) => ( nextValues[ side ] = next ) );

onChange( nextValues );
};
Expand Down
24 changes: 16 additions & 8 deletions packages/components/src/box-control/icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@ const BASE_ICON_SIZE = 24;
export default function BoxControlIcon( {
size = 24,
side = 'all',
sides,
...props
} ) {
const top = getSide( side, 'top' );
const right = getSide( side, 'right' );
const bottom = getSide( side, 'bottom' );
const left = getSide( side, 'left' );
const isSideDisabled = ( value ) =>
sides?.length && ! sides.includes( value );

const getSide = ( value ) => {
if ( isSideDisabled( value ) ) {
return false;
}

return side === 'all' || side === value;
};

const top = getSide( 'top' );
const right = getSide( 'right' );
const bottom = getSide( 'bottom' );
const left = getSide( 'left' );

// Simulates SVG Icon scaling
const scale = size / BASE_ICON_SIZE;
Expand All @@ -36,7 +48,3 @@ export default function BoxControlIcon( {
</Root>
);
}

function getSide( side, value ) {
return side === 'all' || side === value;
}
28 changes: 16 additions & 12 deletions packages/components/src/box-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,19 @@ export default function BoxControl( {
label = __( 'Box Control' ),
values: valuesProp,
units,
sides,
resetValues = DEFAULT_VALUES,
} ) {
const [ values, setValues ] = useControlledState( valuesProp, {
fallback: DEFAULT_VALUES,
} );
const inputValues = values || DEFAULT_VALUES;
const hasInitialValue = isValuesDefined( valuesProp );
const hasOneSide = sides?.length === 1;

const [ isDirty, setIsDirty ] = useState( hasInitialValue );
const [ isLinked, setIsLinked ] = useState(
! hasInitialValue || ! isValuesMixed( inputValues )
! hasInitialValue || ! isValuesMixed( inputValues ) || hasOneSide
);

const [ side, setSide ] = useState( isLinked ? 'all' : 'top' );
Expand Down Expand Up @@ -92,10 +95,8 @@ export default function BoxControl( {
};

const handleOnReset = () => {
const initialValues = DEFAULT_VALUES;

onChange( initialValues );
setValues( initialValues );
onChange( resetValues );
setValues( resetValues );
setIsDirty( false );
};

Expand All @@ -107,6 +108,7 @@ export default function BoxControl( {
onHoverOff: handleOnHoverOff,
isLinked,
units,
sides,
values: inputValues,
};

Expand Down Expand Up @@ -135,7 +137,7 @@ export default function BoxControl( {
</Header>
<HeaderControlWrapper className="component-box-control__header-control-wrapper">
<FlexItem>
<BoxControlIcon side={ side } />
<BoxControlIcon side={ side } sides={ sides } />
</FlexItem>
{ isLinked && (
<FlexBlock>
Expand All @@ -145,12 +147,14 @@ export default function BoxControl( {
/>
</FlexBlock>
) }
<FlexItem>
<LinkedButton
onClick={ toggleLinked }
isLinked={ isLinked }
/>
</FlexItem>
{ ! hasOneSide && (
<FlexItem>
<LinkedButton
onClick={ toggleLinked }
isLinked={ isLinked }
/>
</FlexItem>
) }
</HeaderControlWrapper>
{ ! isLinked && <InputControls { ...inputControlProps } /> }
</Root>
Expand Down
67 changes: 27 additions & 40 deletions packages/components/src/box-control/input-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import UnitControl from './unit-control';
import { LABELS } from './utils';
import { LayoutContainer, Layout } from './styles/box-control-styles';

const allSides = [ 'top', 'right', 'bottom', 'left' ];

export default function BoxInputControls( {
onChange = noop,
onFocus = noop,
onHoverOn = noop,
onHoverOff = noop,
values,
sides,
...props
} ) {
const createHandleOnFocus = ( side ) => ( event ) => {
Expand All @@ -34,8 +37,6 @@ export default function BoxInputControls( {
onChange( nextValues );
};

const { top, right, bottom, left } = values;

const createHandleOnChange = ( side ) => ( next, { event } ) => {
const { altKey } = event;
const nextValues = { ...values };
Expand Down Expand Up @@ -66,51 +67,37 @@ export default function BoxInputControls( {
handleOnChange( nextValues );
};

// Filter sides if custom configuration provided, maintaining default order.
const filteredSides = sides?.length
? allSides.filter( ( side ) => sides.includes( side ) )
: allSides;

const first = filteredSides[ 0 ];
const last = filteredSides[ filteredSides.length - 1 ];
const only = first === last && first;

return (
<LayoutContainer className="component-box-control__input-controls-wrapper">
<Layout
gap={ 0 }
align="top"
className="component-box-control__input-controls"
>
<UnitControl
{ ...props }
isFirst
value={ top }
onChange={ createHandleOnChange( 'top' ) }
onFocus={ createHandleOnFocus( 'top' ) }
onHoverOn={ createHandleOnHoverOn( 'top' ) }
onHoverOff={ createHandleOnHoverOff( 'top' ) }
label={ LABELS.top }
/>
<UnitControl
{ ...props }
value={ right }
onChange={ createHandleOnChange( 'right' ) }
onFocus={ createHandleOnFocus( 'right' ) }
onHoverOn={ createHandleOnHoverOn( 'right' ) }
onHoverOff={ createHandleOnHoverOff( 'right' ) }
label={ LABELS.right }
/>
<UnitControl
{ ...props }
value={ bottom }
onChange={ createHandleOnChange( 'bottom' ) }
onFocus={ createHandleOnFocus( 'bottom' ) }
onHoverOn={ createHandleOnHoverOn( 'bottom' ) }
onHoverOff={ createHandleOnHoverOff( 'bottom' ) }
label={ LABELS.bottom }
/>
<UnitControl
{ ...props }
isLast
value={ left }
onChange={ createHandleOnChange( 'left' ) }
onFocus={ createHandleOnFocus( 'left' ) }
onHoverOn={ createHandleOnHoverOn( 'left' ) }
onHoverOff={ createHandleOnHoverOff( 'left' ) }
label={ LABELS.left }
/>
{ filteredSides.map( ( side ) => (
<UnitControl
{ ...props }
isFirst={ first === side }
isLast={ last === side }
isOnly={ only === side }
value={ values[ side ] }
onChange={ createHandleOnChange( side ) }
onFocus={ createHandleOnFocus( side ) }
onHoverOn={ createHandleOnHoverOn( side ) }
onHoverOff={ createHandleOnHoverOff( side ) }
label={ LABELS.top }
key={ `box-control-${ side }` }
/>
) ) }
</Layout>
</LayoutContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const Layout = styled( Flex )`
position: relative;
height: 100%;
width: 100%;
justify-content: flex-start;
`;

const unitControlBorderRadiusStyles = ( { isFirst, isLast, isOnly } ) => {
Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/input-control/input-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function InputField(
const dragCursor = useDragCursor( isDragging, dragDirection );

/*
* Handles syncronization of external and internal value state.
* Handles synchronization of external and internal value state.
* If not focused and did not hold a dirty value[1] on blur
* updates the value from the props. Otherwise if not holding
* a dirty value[1] propagates the value and event through onChange.
Expand Down Expand Up @@ -155,6 +155,9 @@ function InputField(
const dragGestureProps = useDrag(
( dragProps ) => {
const { distance, dragging, event } = dragProps;
// The event is persisted to prevent errors in components using this
// to check if a modifier key was held while dragging.
event.persist();

if ( ! distance ) return;
event.stopPropagation();
Expand Down

0 comments on commit be7ae06

Please sign in to comment.