Skip to content

Commit

Permalink
Initial implementation of SlotFill for DimensionControls
Browse files Browse the repository at this point in the history
This will allow for ad hoc controls to be injected by blocks into the dimensions block support panel.
  • Loading branch information
aaronrobertshaw committed Aug 13, 2021
1 parent 65b18b9 commit ab8a037
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 25 deletions.
4 changes: 4 additions & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ _Returns_

Undocumented declaration.

### DimensionControls

Undocumented declaration.

### FontSizePicker

Undocumented declaration.
Expand Down
45 changes: 45 additions & 0 deletions packages/block-editor/src/components/dimension-controls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# DimensionControls

Dimension controls appear under the dimensions block support panel in post
settings sidebar when a block is being edited. `DimensionControls` allow for
blocks to group their own dimensions related controls along side those provided
via block supports.

The dimensions panel is built via the `ToolsPanel` component. Block's can also
add their controls to the `ToolsPanel` menu by wrapping them in a
`ToolsPanelItem` component and providing the required callbacks.

## Usage

```js
import { DimensionsControls } from '@wordpress/block-editor';
import {
TextControl,
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';

function MyBlockEdit( props ) {
const { attributes, setAttributes } = props;

return (
<DimensionControls>
<ToolsPanelItem
hasValue={ () => !! attributes.myValue }
label={ __( 'My dimension control' ) }
onDeselect={ () => setAttributes( { myValue: undefined } ) }
resetAllFilter={ ( newAttributes ) => ( {
...newAttributes,
myValue: undefined,
} ) }
isShownByDefault={ true }
>
<TextControl
label="My dimension"
value={ attributes.myValue }
onChange={ ( next ) => setAttributes( { myValue: next } ) ) }
/>
</ToolsPanelItem>
</DimensionControls>
);
}
```
18 changes: 18 additions & 0 deletions packages/block-editor/src/components/dimension-controls/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* WordPress dependencies
*/
import { createSlotFill } from '@wordpress/components';
/**
* Internal dependencies
*/
import useDisplayBlockControls from '../use-display-block-controls';

const { Fill, Slot } = createSlotFill( 'DimensionControls' );

function DimensionControls( { children } ) {
return useDisplayBlockControls() ? <Fill>{ children }</Fill> : null;
}

DimensionControls.Slot = Slot;

export default DimensionControls;
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export {
export { default as ColorPalette } from './color-palette';
export { default as ColorPaletteControl } from './color-palette/control';
export { default as ContrastChecker } from './contrast-checker';
export { default as DimensionControls } from './dimension-controls';
export { default as __experimentalDuotoneControl } from './duotone-control';
export { default as __experimentalFontAppearanceControl } from './font-appearance-control';
export { default as __experimentalFontFamilyControl } from './font-family';
Expand Down
74 changes: 50 additions & 24 deletions packages/block-editor/src/hooks/dimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getBlockSupport } from '@wordpress/blocks';
* Internal dependencies
*/
import InspectorControls from '../components/inspector-controls';
import DimensionControls from '../components/dimension-controls';
import {
MarginEdit,
hasMarginSupport,
Expand Down Expand Up @@ -56,19 +57,33 @@ export function DimensionsPanel( props ) {
] );

// Callback to reset all block support attributes controlled via this panel.
const resetAll = () => {
const resetAll = ( resetFilters = [] ) => {
const { style } = props.attributes;

props.setAttributes( {
style: cleanEmptyObject( {
let newAttributes = {
style: {
...style,
spacing: {
...style?.spacing,
margin: undefined,
padding: undefined,
},
} ),
},
};

// Injected controls can register additional functions to further adjust
// the attributes being reset.
resetFilters.forEach( ( resetFilter ) => {
newAttributes = resetFilter( newAttributes );
} );

// Enforce a cleaned style object.
newAttributes = {
...newAttributes,
style: cleanEmptyObject( newAttributes.style ),
};

props.setAttributes( newAttributes );
};

return (
Expand All @@ -78,26 +93,37 @@ export function DimensionsPanel( props ) {
header={ __( 'Dimensions' ) }
resetAll={ resetAll }
>
{ ! isPaddingDisabled && (
<ToolsPanelItem
hasValue={ () => hasPaddingValue( props ) }
label={ __( 'Padding' ) }
onDeselect={ () => resetPadding( props ) }
isShownByDefault={ defaultSpacingControls?.padding }
>
<PaddingEdit { ...props } />
</ToolsPanelItem>
) }
{ ! isMarginDisabled && (
<ToolsPanelItem
hasValue={ () => hasMarginValue( props ) }
label={ __( 'Margin' ) }
onDeselect={ () => resetMargin( props ) }
isShownByDefault={ defaultSpacingControls?.margin }
>
<MarginEdit { ...props } />
</ToolsPanelItem>
) }
<DimensionControls.Slot>
{ ( fills ) => (
<>
{ ! isPaddingDisabled && (
<ToolsPanelItem
hasValue={ () => hasPaddingValue( props ) }
label={ __( 'Padding' ) }
onDeselect={ () => resetPadding( props ) }
isShownByDefault={
defaultSpacingControls?.padding
}
>
<PaddingEdit { ...props } />
</ToolsPanelItem>
) }
{ ! isMarginDisabled && (
<ToolsPanelItem
hasValue={ () => hasMarginValue( props ) }
label={ __( 'Margin' ) }
onDeselect={ () => resetMargin( props ) }
isShownByDefault={
defaultSpacingControls?.margin
}
>
<MarginEdit { ...props } />
</ToolsPanelItem>
) }
{ fills }
</>
) }
</DimensionControls.Slot>
</ToolsPanel>
</InspectorControls>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/tools-panel/tools-panel-item/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function useToolsPanelItem( props ) {
hasValue,
isShownByDefault,
label,
resetAllFilter,
onDeselect = () => undefined,
onSelect = () => undefined,
...otherProps
Expand All @@ -37,6 +38,7 @@ export function useToolsPanelItem( props ) {
hasValue,
isShownByDefault,
label,
resetAllFilter,
} );
}, [] );

Expand Down
10 changes: 9 additions & 1 deletion packages/components/src/tools-panel/tools-panel/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@ export function useToolsPanel( props ) {

// Allow panel items to register themselves.
const [ panelItems, setPanelItems ] = useState( [] );
const [ panelResetAllFilters, setPanelResetAllFilters ] = useState( [] );

const registerPanelItem = ( item ) => {
setPanelItems( ( items ) => [ ...items, item ] );

if ( item.resetAllFilter ) {
setPanelResetAllFilters( ( filters ) => [
...filters,
item.resetAllFilter,
] );
}
};

// Manage and share display state of menu items representing child controls.
Expand Down Expand Up @@ -54,7 +62,7 @@ export function useToolsPanel( props ) {
// Resets display of children and executes resetAll callback if available.
const resetAllItems = () => {
if ( typeof resetAll === 'function' ) {
resetAll();
resetAll( panelResetAllFilters );
}

// Turn off display of all non-default items.
Expand Down

0 comments on commit ab8a037

Please sign in to comment.