Skip to content

Commit

Permalink
Merge branch 'trunk' into rnmobile/add-media-inserter-to-toolbar
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/react-native-editor/CHANGELOG.md
  • Loading branch information
Gerardo committed Jul 6, 2023
2 parents 7f5a35f + bc663f6 commit 28fbc2f
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 64 deletions.
14 changes: 7 additions & 7 deletions docs/explanations/architecture/styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,7 @@ The global styles UI in the site editor has a screen for per-block styles. The l

In addition to styles at the individual block level and in global styles, there is the concept of layout styles that are output for both blocks-based and classic themes.

The layout block support is an experimental approach for outputting common layout styles that are shared between blocks that are used for creating layouts. Layout styles are useful for providing common styling for any block that is a container for other blocks. Examples of blocks that depend on these layout styles include Group, Row, Columns, Buttons, and Social Icons.

While the feature is part of WordPress core, it is still flagged as experimental in the sense that the features and output are still undergoing active development. It is therefore not yet a stable feature from the perspective of 3rd party blocks, as the API is likely to change. The feature is enabled in core blocks via the `layout` setting under `supports` in a block's `block.json` file.
The layout block support outputs common layout styles that are shared between blocks used for creating layouts. Layout styles are useful for providing common styling for any block that is a container for other blocks. Examples of blocks that depend on these layout styles include Group, Row, Columns, Buttons, and Social Icons. The feature is enabled in core blocks via the `layout` setting under `supports` in a block's `block.json` file.

There are two primary places where Layout styles are output:

Expand All @@ -523,30 +521,31 @@ Base layout styles are those styles that are common to all blocks that opt in to

Base layout styles are output from within [the main PHP class](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/class-wp-theme-json.php) that handles global styles, and form part of the global styles stylesheet. In order to provide support for core blocks in classic themes, these styles are always output, irrespective of whether the theme provides its own `theme.json` file.

Common layout definitions are stored in [the core `theme.json` file](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/theme.json), but are not intended to be extended or overridden by themes.
Common layout definitions are stored in [the core layout block support file](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-supports/layout.php).

#### Individual layout styles

When a block that opts in to the experimental layout support is rendered, two things are processed and added to the output via [`layout.php`](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-supports/layout.php):
When a block that opts in to layout support is rendered, two things are processed and added to the output via [`layout.php`](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-supports/layout.php):

- Semantic class names are added to the block markup to indicate which layout settings are in use. For example, `is-layout-flow` is for blocks (such as Group) that use the default/flow layout, and `is-content-justification-right` is added when a user sets a block to use right justification.
- Individual styles are generated for non-default layout values that are set on the individual block being rendered. These styles are attached to the block via a container class name using the form `wp-container-$id` where the `$id` is a [unique number](https://developer.wordpress.org/reference/functions/wp_unique_id/).

#### Available layout types

There are currently three layout types in use:
There are currently four layout types in use:

- Default/Flow: Items are stacked vertically. The parent container block is set to `display: flow` and the spacing between children is handled via vertical margins.
- Constrained: Items are stacked vertically, using the same spacing logic as the Flow layout. Features constrained widths for child content, outputting widths for standard content size and wide size. Defaults to using global `contentSize` and `wideSize` values set in `settings.layout` in the `theme.json`.
- Flex: Items are displayed using a Flexbox layout. Defaults to a horizontal orientation. Spacing between children is handled via the `gap` CSS property.
- Grid: Items are displayed using a Grid layout. Defaults to an `auto-fill` approach to column generation but can also be set to a fixed number of columns. Spacing between children is handled via the `gap` CSS property.

For controlling spacing between blocks, and enabling block spacing controls see: [What is blockGap and how can I use it?](https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/#what-is-blockgap-and-how-can-i-use-it).

#### Targeting layout or container blocks from themes

The layout block support is designed to enable control over layout features from within the block and site editors. Where possible, try to use the features of the blocks to determine particular layout requirements rather than relying upon additional stylesheets.

For themes that wish to target container blocks in order to add or adjust particular styles, the block's class name is often the best class name to use. Class names such as `wp-block-group` or `wp-block-columns` are usually reliable class names for targeting a particular block.
For themes that wish to target container blocks in order to add or adjust particular styles, the block's class name is often the best class name to use. Class names such as `wp-block-group` or `wp-block-columns` are usually reliable class names for targeting a particular block. In addition to block and layout classnames, there is also a classname composed of block and layout together: for example, for a Group block with a constrained layout it will be `wp-block-group-is-layout-constrained`.

For targeting a block that uses a particular layout type, avoid targeting `wp-container-` as container classes may not always be present in the rendered markup.

Expand All @@ -559,6 +558,7 @@ The current semantic class names that can be output by the Layout block support
- `is-layout-flow`: Blocks that use the Default/Flow layout type.
- `is-layout-constrained`: Blocks that use the Constrained layout type.
- `is-layout-flex`: Blocks that use the Flex layout type.
- `is-layout-grid`: Blocks that used the Grid layout type.
- `wp-container-$id`: Where `$id` is a semi-random number. A container class that only exists when the block contains non-default Layout values. This class should not be used directly for any CSS targeting as it may or may not be present.
- `is-horizontal`: When a block explicitly sets `orientation` to `horizontal`.
- `is-vertical`: When a block explicitly sets `orientation` to `vertical`.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 89 additions & 0 deletions packages/block-editor/src/components/block-controls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# BlockControls

When the user selects a particular block, a toolbar positioned above the selected block displays a set of control buttons. Certain block-level controls are automatically included in the toolbar under specific circumstances. For example, there is a control for converting the block into a different type or when the focused element is a RichText component.

With `BlockControls`, you can customize the toolbar to include controls specific to your block type. If the return value of your block type's `edit` function includes a `BlockControls` element, the controls nested inside it will be shown in the selected block's toolbar.

![Screenshot of the block controls of a Paragraph block inside the block editor](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/toolbar-text.png)

## Usage

```jsx
/**
* WordPress dependencies
*/
import {
BlockControls,
__experimentalBlockAlignmentMatrixControl as BlockAlignmentMatrixControl,
useBlockProps,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

export default function MyBlockEdit( { attributes, setAttributes } ) {
const blockProps = useBlockProps( {
className: 'my-block__custom-class',
} );
const { contentPosition } = attributes;

return (
<div { ...blockProps }>
{
<BlockControls>
<BlockAlignmentMatrixControl
label={ __( 'Change content position' ) }
value={ contentPosition }
onChange={ ( nextPosition ) =>
setAttributes( {
contentPosition: nextPosition,
} )
}
/>
</BlockControls>
}
</div>
);
}

/// ...

<MyBlockEdit />;
```

See [this custom block tutorial page](/docs/how-to-guides/block-tutorial/block-controls-toolbar-and-sidebar.md) for more information and block controls examples.

Furthermore, the READMEs of various components inside the block editor package and the components package include examples that also utilize `BlockControls` and can be a good reference.

### Props

The component accepts the following props:

### `group`

Group of the block controls. Allows you to create and render multiple groups of block controls.

- Type: `string`
- Default: `default`
- Required: No

### `controls`

Allows overriding the default `controls` if the `default` group is used.

See [this custom block tutorial page](/docs/how-to-guides/block-tutorial/block-controls-toolbar-and-sidebar.md) for more details and examples with block controls.

- Type: `array`

### `children`

Additional control components to be rendered.

- Type: `Element`
- Required: No.


### `__experimentalShareWithChildBlocks`

Whether the additional block controls should be added to the block toolbars of child blocks.

- Type: `boolean`
- Default: `false`
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,12 @@ const BlockDraggableWrapper = ( { children, isRTL } ) => {
draggingScrollHandler( event );
};

const { onBlockDragOver, onBlockDragEnd, onBlockDrop, targetBlockIndex } =
useBlockDropZone();
const {
onBlockDragOverWorklet,
onBlockDragEnd,
onBlockDrop,
targetBlockIndex,
} = useBlockDropZone();

// Stop dragging blocks if the block draggable is unmounted.
useEffect( () => {
Expand Down Expand Up @@ -184,7 +188,7 @@ const BlockDraggableWrapper = ( { children, isRTL } ) => {
chip.y.value = dragPosition.y;
currentYPosition.value = dragPosition.y;

runOnJS( onBlockDragOver )( { x, y: y + scroll.offsetY.value } );
onBlockDragOverWorklet( { x, y: y + scroll.offsetY.value } );

// Update scrolling velocity
scrollOnDragOver( dragPosition.y );
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/**
* External dependencies
*/
import { useSharedValue } from 'react-native-reanimated';
import {
runOnJS,
useDerivedValue,
useSharedValue,
} from 'react-native-reanimated';

/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { useThrottle } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -18,6 +21,8 @@ import { useBlockListContext } from '../block-list/block-list-context';
import { getDistanceToNearestEdge } from '../../utils/math';
import useOnBlockDrop from '../use-on-block-drop';

const UPDATE_TARGET_BLOCK_INDEX_THRESHOLD = 20; // In pixels

/** @typedef {import('../../utils/math').WPPoint} WPPoint */

/**
Expand Down Expand Up @@ -111,50 +116,82 @@ export default function useBlockDropZone( {
rootClientId: targetRootClientId = '',
} = {} ) {
const targetBlockIndex = useSharedValue( null );
const dragPosition = {
x: useSharedValue( 0 ),
y: useSharedValue( 0 ),
};
const prevDragPosition = {
x: useSharedValue( 0 ),
y: useSharedValue( 0 ),
};

const { getBlockListSettings, getSettings } = useSelect( blockEditorStore );
const { blocksLayouts, getBlockLayoutsOrderedByYCoord } =
useBlockListContext();

const getSortedBlocksLayouts = useCallback( () => {
return getBlockLayoutsOrderedByYCoord( blocksLayouts.current );
// We use the value of `blocksLayouts` as the dependency.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ blocksLayouts.current ] );

const isRTL = getSettings().isRTL;

const onBlockDrop = useOnBlockDrop();

const throttled = useThrottle(
useCallback(
( event ) => {
const sortedBlockLayouts = getSortedBlocksLayouts();

const targetIndex = getNearestBlockIndex(
sortedBlockLayouts,
{ x: event.x, y: event.y },
getBlockListSettings( targetRootClientId )?.orientation,
isRTL
);
if ( targetIndex !== null ) {
targetBlockIndex.value = targetIndex ?? 0;
}
},
[
getSortedBlocksLayouts,
getNearestBlockIndex,
getBlockListSettings,
targetBlockIndex,
]
),
200
const updateTargetBlockIndex = useCallback(
( event ) => {
const sortedBlockLayouts = getSortedBlocksLayouts();

const targetIndex = getNearestBlockIndex(
sortedBlockLayouts,
{ x: event.x, y: event.y },
getBlockListSettings( targetRootClientId )?.orientation,
isRTL
);
if ( targetIndex !== null ) {
targetBlockIndex.value = targetIndex ?? 0;
}
},
[
getSortedBlocksLayouts,
getBlockListSettings,
targetRootClientId,
isRTL,
targetBlockIndex,
]
);

useDerivedValue( () => {
const x = dragPosition.x.value;
const y = dragPosition.y.value;
const prevX = prevDragPosition.x.value;
const prevY = prevDragPosition.y.value;
// `updateTargetBlockIndex` performs expensive calculations, so we throttle
// the call using a offset threshold based on the dragging position.
if (
Math.abs( x - prevX ) >= UPDATE_TARGET_BLOCK_INDEX_THRESHOLD ||
Math.abs( y - prevY ) >= UPDATE_TARGET_BLOCK_INDEX_THRESHOLD
) {
runOnJS( updateTargetBlockIndex )( { x, y } );
prevDragPosition.x.value = x;
prevDragPosition.y.value = y;
return true;
}
return false;
} );

return {
onBlockDragOver( event ) {
throttled( event );
onBlockDragOver( { x, y } ) {
dragPosition.x.value = x;
dragPosition.y.value = y;
},
onBlockDragOverWorklet( { x, y } ) {
'worklet';
dragPosition.x.value = x;
dragPosition.y.value = y;
},
onBlockDragEnd() {
throttled.cancel();
targetBlockIndex.value = null;
},
onBlockDrop: ( event ) => {
Expand Down
31 changes: 17 additions & 14 deletions packages/block-library/src/query-pagination/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,23 @@ export default function QueryPaginationEdit( {
setAttributes,
clientId,
} ) {
const hasNextPreviousBlocks = useSelect( ( select ) => {
const { getBlocks } = select( blockEditorStore );
const innerBlocks = getBlocks( clientId );
/**
* Show the `paginationArrow` and `showLabel` controls only if a
* `QueryPaginationNext/Previous` block exists.
*/
return innerBlocks?.find( ( innerBlock ) => {
return [
'core/query-pagination-next',
'core/query-pagination-previous',
].includes( innerBlock.name );
} );
}, [] );
const hasNextPreviousBlocks = useSelect(
( select ) => {
const { getBlocks } = select( blockEditorStore );
const innerBlocks = getBlocks( clientId );
/**
* Show the `paginationArrow` and `showLabel` controls only if a
* `QueryPaginationNext/Previous` block exists.
*/
return innerBlocks?.find( ( innerBlock ) => {
return [
'core/query-pagination-next',
'core/query-pagination-previous',
].includes( innerBlock.name );
} );
},
[ clientId ]
);
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps, {
template: TEMPLATE,
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/template-part/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function TemplatePartEdit( {
area: _area,
};
},
[ templatePartId, clientId ]
[ templatePartId, attributes.area, clientId ]
);
const { templateParts } = useAlternativeTemplateParts(
area,
Expand Down
4 changes: 4 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Bug Fix

- `Popover`: Pin `react-dropdown-menu` version to avoid breaking changes in dependency updates. ([52356](https://github.com/WordPress/gutenberg/pull/52356)).

## 25.3.0 (2023-07-05)

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@emotion/styled": "^11.6.0",
"@emotion/utils": "^1.0.0",
"@floating-ui/react-dom": "1.0.0",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-dropdown-menu": "2.0.4",
"@use-gesture/react": "^10.2.24",
"@wordpress/a11y": "file:../a11y",
"@wordpress/compose": "file:../compose",
Expand Down
Loading

0 comments on commit 28fbc2f

Please sign in to comment.