Skip to content

Commit 96e5dc7

Browse files
authored
Refactor dropzone for unmodified default blocks with useBlockDropZone and InsertionPoint (#44647)
* Try integrating block-popover-drop-zone with insertion-point * Fix changelog * Fix animation and add e2e tests * Remove fake html draggable once the drag starts * Address minor reviews * Add back deleted tests * Merge getNearestBlockIndex and getDropTargetIndexAndOperation * Add comment for insertion point
1 parent fc081cc commit 96e5dc7

File tree

24 files changed

+1053
-403
lines changed

24 files changed

+1053
-403
lines changed

docs/reference-guides/data/data-core-block-editor.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1510,12 +1510,17 @@ _Parameters_
15101510

15111511
- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
15121512
- _index_ `?number`: Index at which block should be inserted.
1513-
- _\_\_unstableOptions_ `Object`: Whether or not to show an inserter button.
1513+
- _\_\_unstableOptions_ `?Object`: Additional options.
15141514

15151515
_Returns_
15161516

15171517
- `Object`: Action object.
15181518

1519+
_Properties_
1520+
1521+
- _\_\_unstableWithInserter_ `boolean`: Whether or not to show an inserter button.
1522+
- _operation_ `WPDropOperation`: The operation to perform when applied, either 'insert' or 'replace' for now.
1523+
15191524
### startDraggingBlocks
15201525

15211526
Returns an action object used in signalling that the user has begun to drag blocks.

packages/block-editor/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
- `FontSizePicker`: Update fluid utils so that only string, floats and integers are treated as valid font sizes for the purposes of fluid typography ([#44847](https://github.com/WordPress/gutenberg/pull/44847))
88
- `getTypographyClassesAndStyles()`: Ensure that font sizes are transformed into fluid values if fluid typography is activated ([#44852](https://github.com/WordPress/gutenberg/pull/44852))
99

10+
### New features
11+
12+
- You can now drop files/blocks/HTML on unmodified default blocks to transform them into corresponding blocks ([#44647](https://github.com/WordPress/gutenberg/pull/44647)).
13+
1014
## 10.2.0 (2022-10-05)
1115

1216
## 10.1.0 (2022-09-21)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { useSelect } from '@wordpress/data';
5+
import { useReducedMotion } from '@wordpress/compose';
6+
import { __unstableMotion as motion } from '@wordpress/components';
7+
8+
/**
9+
* Internal dependencies
10+
*/
11+
import { store as blockEditorStore } from '../../store';
12+
import BlockPopover from './index';
13+
14+
const animateVariants = {
15+
hide: { opacity: 0, scaleY: 0.75 },
16+
show: { opacity: 1, scaleY: 1 },
17+
exit: { opacity: 0, scaleY: 0.9 },
18+
};
19+
20+
function BlockDropZonePopover( {
21+
__unstablePopoverSlot,
22+
__unstableContentRef,
23+
} ) {
24+
const { clientId } = useSelect( ( select ) => {
25+
const { getBlockOrder, getBlockInsertionPoint } =
26+
select( blockEditorStore );
27+
const insertionPoint = getBlockInsertionPoint();
28+
const order = getBlockOrder( insertionPoint.rootClientId );
29+
30+
if ( ! order.length ) {
31+
return {};
32+
}
33+
34+
return {
35+
clientId: order[ insertionPoint.index ],
36+
};
37+
}, [] );
38+
const reducedMotion = useReducedMotion();
39+
40+
return (
41+
<BlockPopover
42+
clientId={ clientId }
43+
__unstableCoverTarget
44+
__unstablePopoverSlot={ __unstablePopoverSlot }
45+
__unstableContentRef={ __unstableContentRef }
46+
className="block-editor-block-popover__drop-zone"
47+
>
48+
<motion.div
49+
data-testid="block-popover-drop-zone"
50+
initial={
51+
reducedMotion ? animateVariants.show : animateVariants.hide
52+
}
53+
animate={ animateVariants.show }
54+
exit={
55+
reducedMotion ? animateVariants.show : animateVariants.exit
56+
}
57+
className="block-editor-block-popover__drop-zone-foreground"
58+
/>
59+
</BlockPopover>
60+
);
61+
}
62+
63+
export default BlockDropZonePopover;

packages/block-editor/src/components/block-popover/style.scss

+17-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
}
2222

2323
// Enable pointer events for the toolbar's content.
24-
&:not(.block-editor-block-popover__inbetween) .components-popover__content {
24+
&:not(.block-editor-block-popover__inbetween, .block-editor-block-popover__drop-zone) .components-popover__content {
2525
* {
2626
pointer-events: all;
2727
}
@@ -48,3 +48,19 @@
4848
}
4949
}
5050
}
51+
52+
53+
.components-popover.block-editor-block-popover__drop-zone {
54+
// Disable pointer events for dragging and dropping.
55+
// This drop zone is fully presentational, the actual DnD implementation is handled elsewhere.
56+
* {
57+
pointer-events: none;
58+
}
59+
60+
.block-editor-block-popover__drop-zone-foreground {
61+
position: absolute;
62+
inset: 0;
63+
background-color: var(--wp-admin-theme-color);
64+
border-radius: 2px;
65+
}
66+
}

packages/block-editor/src/components/block-tools/insertion-point.js

+26-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ import { useReducedMotion } from '@wordpress/compose';
1717
import Inserter from '../inserter';
1818
import { store as blockEditorStore } from '../../store';
1919
import BlockPopoverInbetween from '../block-popover/inbetween';
20+
import BlockDropZonePopover from '../block-popover/drop-zone';
2021

2122
export const InsertionPointOpenRef = createContext();
2223

23-
function InsertionPointPopover( {
24+
function InbetweenInsertionPointPopover( {
2425
__unstablePopoverSlot,
2526
__unstableContentRef,
2627
} ) {
@@ -232,9 +233,30 @@ function InsertionPointPopover( {
232233
}
233234

234235
export default function InsertionPoint( props ) {
235-
const isVisible = useSelect( ( select ) => {
236-
return select( blockEditorStore ).isBlockInsertionPointVisible();
236+
const { insertionPoint, isVisible } = useSelect( ( select ) => {
237+
const { getBlockInsertionPoint, isBlockInsertionPointVisible } =
238+
select( blockEditorStore );
239+
return {
240+
insertionPoint: getBlockInsertionPoint(),
241+
isVisible: isBlockInsertionPointVisible(),
242+
};
237243
}, [] );
238244

239-
return isVisible && <InsertionPointPopover { ...props } />;
245+
if ( ! isVisible ) {
246+
return null;
247+
}
248+
249+
/**
250+
* Render a popover that overlays the block when the desired operation is to replace it.
251+
* Otherwise, render a popover in between blocks for the indication of inserting between them.
252+
*/
253+
return insertionPoint.operation === 'replace' ? (
254+
<BlockDropZonePopover
255+
// Force remount to trigger the animation.
256+
key={ `${ insertionPoint.rootClientId }-${ insertionPoint.index }` }
257+
{ ...props }
258+
/>
259+
) : (
260+
<InbetweenInsertionPointPopover { ...props } />
261+
);
240262
}

packages/block-editor/src/components/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ export {
155155
export { default as __experimentalBlockPatternsList } from './block-patterns-list';
156156
export { default as __experimentalPublishDateTimePicker } from './publish-date-time-picker';
157157
export { default as __experimentalInspectorPopoverHeader } from './inspector-popover-header';
158-
export { default as __experimentalUseOnBlockDrop } from './use-on-block-drop';
159158

160159
/*
161160
* State Related Components

packages/block-editor/src/components/list-view/use-list-view-drop-zone.js

+4-18
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {
1111
/**
1212
* Internal dependencies
1313
*/
14-
import { getDistanceToNearestEdge } from '../../utils/math';
14+
import {
15+
getDistanceToNearestEdge,
16+
isPointContainedByRect,
17+
} from '../../utils/math';
1518
import useOnBlockDrop from '../use-on-block-drop';
1619
import { store as blockEditorStore } from '../../store';
1720

@@ -48,23 +51,6 @@ import { store as blockEditorStore } from '../../store';
4851
* 'inside' refers to nesting as an inner block.
4952
*/
5053

51-
/**
52-
* Is the point contained by the rectangle.
53-
*
54-
* @param {WPPoint} point The point.
55-
* @param {DOMRect} rect The rectangle.
56-
*
57-
* @return {boolean} True if the point is contained by the rectangle, false otherwise.
58-
*/
59-
function isPointContainedByRect( point, rect ) {
60-
return (
61-
rect.left <= point.x &&
62-
rect.right >= point.x &&
63-
rect.top <= point.y &&
64-
rect.bottom >= point.y
65-
);
66-
}
67-
6854
/**
6955
* Determines whether the user positioning the dragged block to nest as an
7056
* inner block.

0 commit comments

Comments
 (0)