Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more resizing handles #3023

Merged
merged 30 commits into from
Aug 21, 2019
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6539dc8
Make resizable-box styles more explicit
swissspidy Aug 13, 2019
4b8d90a
Enable all resizing handles for testing
swissspidy Aug 13, 2019
5ebb4ba
Update width/height calculation when resizing from top or left
swissspidy Aug 13, 2019
32c040d
Fix typo in docblock
swissspidy Aug 13, 2019
3f2a6ee
Merge branch 'develop' into add/more-rotation-handles
swissspidy Aug 13, 2019
666fd92
Move some resize helpers to separate file closer to the component
swissspidy Aug 14, 2019
3726456
Handle all edges when not rotated.
miina Aug 16, 2019
c4349a4
Start adding logic for handling rotation.
miina Aug 16, 2019
905d732
Merge branch 'develop' into add/more-rotation-handles
swissspidy Aug 16, 2019
31944ca
Resolve merge conflicts.
miina Aug 16, 2019
0d64be1
Merge branch 'add/more-rotation-handles' of github.com:ampproject/amp…
miina Aug 16, 2019
05d0795
Move constants to contsants.
miina Aug 16, 2019
9e30d6e
Fix style issues from merge.
miina Aug 16, 2019
46a1326
Adjust logic for topRight corner
miina Aug 19, 2019
fbdf271
Move blockPositioning helper to resizing helpers file.
miina Aug 19, 2019
5c3e7db
Add bottomLeft corner resizing logic.
miina Aug 19, 2019
45e91b4
Move position calculation logic to helpers file.
miina Aug 19, 2019
8045e5a
Improve styling for rotatable and resizable boxes
swissspidy Aug 19, 2019
0729544
Restrict block positioning when min height/width have been reached.
miina Aug 19, 2019
c64462c
Fix odd behavior when resizing small.
miina Aug 19, 2019
7f91e80
Start adding tests.
miina Aug 20, 2019
5b4fa2d
Add test for resizing to min width and height.
miina Aug 20, 2019
fd98b22
Add test for keeping the position when trying to resize with min width.
miina Aug 20, 2019
b6b17c7
Add test for resizing from topleft corner.
miina Aug 20, 2019
a831e1c
Add tests for rotated Text block.
miina Aug 20, 2019
1a68a61
Add a few tests for Author block, too.
miina Aug 20, 2019
680c731
Update tests and test config
swissspidy Aug 20, 2019
1a72f09
Don’t import from React
swissspidy Aug 20, 2019
d259361
Extract and rename test helpers
swissspidy Aug 20, 2019
38f1ead
Merge branch 'develop' into add/more-rotation-handles
swissspidy Aug 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions assets/src/stories-editor/blocks/amp-story-page/edit.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,18 @@
z-index: 100;
}

.block-editor-block-list__layout .block-editor-block-list__block.amp-page-inactive > .block-editor-block-list__block-edit::before {
.block-editor-block-list__block.amp-page-inactive > .block-editor-block-list__block-edit::before {
box-shadow: none;
border: 1px solid #e3e5e7;
}

.block-editor-block-list__layout .block-editor-block-list__block.amp-page-active > .block-editor-block-list__block-edit::before,
.block-editor-block-list__layout .block-editor-block-list__block.is-selected > .block-editor-block-list__block-edit::before {
/* todo: show border also when is-resizing */
.block-editor-block-list__block.amp-page-active > .block-editor-block-list__block-edit::before,
.block-editor-block-list__block.amp-page-active.is-selected > .block-editor-block-list__block-edit::before,
.block-editor-block-list__block.amp-page-active.has-child-selected > .block-editor-block-list__block-edit::before,
.block-editor-inner-blocks .wp-block:hover .block-editor-block-list__block-edit::before,
.block-editor-inner-blocks .wp-block.is-rotating .block-editor-block-list__block-edit::before,
.block-editor-inner-blocks .wp-block.is-selected .block-editor-block-list__block-edit::before {
box-shadow: none;
border: 1px solid rgba(66, 88, 99, .4);
}
Expand Down
29 changes: 0 additions & 29 deletions assets/src/stories-editor/blocks/amp-story-text/edit.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,10 @@
opacity: 0.62;
}

.wp-block[data-type="amp/amp-story-text"] .amp-story-resize-container .components-resizable-box__handle-right {
right: -13px;
}

.wp-block[data-type="amp/amp-story-text"] .amp-story-resize-container .components-resizable-box__handle-right::before {
margin: 0;
}

.wp-block[data-type="amp/amp-story-text"] .amp-story-resize-container .components-resizable-box__handle-bottom {
width: 50px;
left: calc(50% - 25px);
}

.amp-story-text__resize-container .components-resizable-box__handle-bottom::before {
margin: 0 auto;
}

.editor-styles-wrapper #amp-story-editor .wp-block .wp-block[data-type="amp/amp-story-text"] {
width: initial;
}

.wp-block[data-type="amp/amp-story-text"] .components-resizable-box__handle,
.wp-block.is-typing[data-type="amp/amp-story-text"] .components-resizable-box__handle {
display: block;
opacity: 0;
transition: opacity .3s;
}

.wp-block[data-type="amp/amp-story-text"]:hover .components-resizable-box__handle,
.wp-block[data-type="amp/amp-story-text"] .components-resizable-box__handle:hover {
opacity: 100;
}

.wp-block[data-type="amp/amp-story-text"] .block-editor-rich-text__editable,
div[data-type="amp/amp-story-page"] .block-editor-inner-blocks .block-editor-block-list__block-edit {
display: inline-block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ export default createHigherOrderComponent(
clientId,
name,
attributes,
isSelected,
isLast,
isFirst,
currentBlockPosition,
Expand Down Expand Up @@ -248,7 +247,6 @@ export default createHigherOrderComponent(
{ ( ! isMovableBlock ) && ( <BlockEdit { ...props } /> ) }
{ isMovableBlock && ! isEmptyImageBlock && needsResizing && (
<ResizableBox
isSelected={ isSelected }
width={ width }
height={ height }
angle={ rotationAngle }
Expand Down
58 changes: 29 additions & 29 deletions assets/src/stories-editor/components/resizable-box/edit.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
.amp-story-resize-container .components-resizable-box__handle-right {
right: -14px;
height: 50px;
top: calc(50% - 25px);
.amp-story-resize-container .components-resizable-box__handle {
display: block;
opacity: 0;
transition: opacity .3s;
}

.amp-story-resize-container .components-resizable-box__handle-right::before {
margin: 0;
.block-editor-inner-blocks .wp-block.is-typing .amp-story-resize-container .components-resizable-box__handle {
opacity: 0;
}

.block-editor-inner-blocks .wp-block:hover .amp-story-resize-container .components-resizable-box__handle,
.block-editor-inner-blocks .wp-block.is-selected .amp-story-resize-container .components-resizable-box__handle,
.block-editor-inner-blocks .wp-block .amp-story-resize-container.is-resizing .components-resizable-box__handle {
opacity: 1;
}

.amp-story-resize-container .components-resizable-box__handle-top {
top: -14px !important;
}

.amp-story-resize-container .components-resizable-box__handle-right {
right: -14px !important;
}

.amp-story-resize-container .components-resizable-box__handle-bottom {
bottom: -14px;
width: 50px;
left: calc(50% - 25px);
bottom: -14px !important;
}

.amp-story-resize-container .components-resizable-box__handle-left {
left: -14px !important;
}

.amp-story-editor__rotate-container .components-resizable-box__handle {
display: none !important;
}

.amp-story-resize-container .amp-story-editor__rotate-container {
height: 100%;
}

.wp-block-image .components-resizable-box__container img {
height: 100%;
object-fit: cover;
Expand All @@ -30,23 +50,3 @@
.block-editor-block-list__block[data-type="core/image"] img {
-webkit-user-drag: none;
}

.amp-story-resize-container .components-resizable-box__handle-bottom::before {
margin: 0 auto;
}

.amp-story-resize-container .amp-story-editor__rotate-container {
height: 100%;
}

.wp-block .components-resizable-box__handle,
.wp-block.is-typing .components-resizable-box__handle {
display: block;
opacity: 0;
transition: opacity .3s;
}

.wp-block.amp-page-active .wp-block:hover .components-resizable-box__handle,
.wp-block.amp-page-active .wp-block .components-resizable-box__handle:hover {
opacity: 1;
}
192 changes: 192 additions & 0 deletions assets/src/stories-editor/components/resizable-box/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/**
* Internal dependencies
*/
import {
BLOCKS_WITH_TEXT_SETTINGS,
REVERSE_WIDTH_CALCULATIONS,
REVERSE_HEIGHT_CALCULATIONS,
} from '../../constants';
import { getPixelsFromPercentage } from '../../helpers';

/**
* Get the distance between two points based on pythagorean.
*
* @param {number} deltaX Difference between X coordinates.
* @param {number} deltaY Difference between Y coordinates.
* @return {number} Difference between the two points.
*/
const getDelta = ( deltaX, deltaY ) => Math.sqrt( Math.pow( deltaX, 2 ) + Math.pow( deltaY, 2 ) );

/**
* Converts degrees to radian.
*
* @param {number} angle Angle.
* @return {number} Radian.
*/
export const getRadianFromDeg = ( angle ) => angle * Math.PI / 180;

/**
* Gets width and height delta values based on the original coordinates, rotation angle and mouse event.
*
* @param {Object} event MouseEvent.
* @param {number} angle Rotation angle.
* @param {number} lastSeenX Starting X coordinate.
* @param {number} lastSeenY Starting Y coordinate.
* @param {string} direction Direction of resizing.
* @return {Object} Width and height values.
*/
export const getResizedWidthAndHeight = ( event, angle, lastSeenX, lastSeenY, direction ) => {
const deltaY = event.clientY - lastSeenY;
const deltaX = event.clientX - lastSeenX;
const deltaL = getDelta( deltaX, deltaY );

// Get the angle between the two points.
const alpha = Math.atan2( deltaY, deltaX );
// Get the difference with rotation angle.
const beta = alpha - getRadianFromDeg( angle );

const resizedHorizontally = direction.toLowerCase().includes( 'left' ) || direction.toLowerCase().includes( 'right' );
const resizedVertically = direction.toLowerCase().includes( 'top' ) || direction.toLowerCase().includes( 'bottom' );
const deltaW = resizedHorizontally ? deltaL * Math.cos( beta ) : 0;
const deltaH = resizedVertically ? deltaL * Math.sin( beta ) : 0;

// When using left or top handles the size of the block is changing reversely to right and bottom.
return {
deltaW: REVERSE_WIDTH_CALCULATIONS.includes( direction ) ? -deltaW : deltaW,
deltaH: REVERSE_HEIGHT_CALCULATIONS.includes( direction ) ? -deltaH : deltaH,
};
};

/**
* Returns the block's inner text element.
*
* @param {string} blockName Block name.
* @param {HTMLElement} blockElement The block's `.wp-block` element.
* @return {?HTMLElement} Inner element if found, otherwise null.
*/
export const getBlockTextElement = ( blockName, blockElement ) => {
const isBlockWithText = BLOCKS_WITH_TEXT_SETTINGS.includes( blockName ) || 'core/code' === blockName;

if ( ! isBlockWithText ) {
return null;
}

switch ( blockName ) {
case 'amp/amp-story-text':
return blockElement.querySelector( '.block-editor-rich-text__editable.editor-rich-text__editable' );
case 'amp/amp-story-post-title':
return blockElement.querySelector( '.wp-block-amp-amp-story-post-title' );
case 'amp/amp-story-post-author':
return blockElement.querySelector( '.wp-block-amp-amp-story-post-author' );
case 'amp/amp-story-post-date':
return blockElement.querySelector( '.wp-block-amp-amp-story-post-date' );
case 'core/code':
return blockElement.querySelector( '.wp-block-code' );
default:
return null;
}
};

/**
* Get block positioning after resizing, not considering the rotation.
*
* @param {string} direction Resizing direction.
* @param {string} blockElementLeft Original left position before resizing.
* @param {string} blockElementTop Original top position before resizing.
* @param {number} deltaW Width change with resizing.
* @param {number} deltaH Height change with resizing.
* @return {{top: number, left: number}} Top and left positioning after resizing, not considering the rotation.
*/
export const getResizedBlockPosition = ( direction, blockElementLeft, blockElementTop, deltaW, deltaH ) => {
const baseLeftInPixels = getPixelsFromPercentage( 'x', parseFloat( blockElementLeft ) );
const baseTopInPixels = getPixelsFromPercentage( 'y', parseFloat( blockElementTop ) );
switch ( direction ) {
case 'topRight':
return {
left: baseLeftInPixels,
top: baseTopInPixels - deltaH,
};
case 'bottomLeft':
return {
left: baseLeftInPixels - deltaW,
top: baseTopInPixels,
};
case 'left':
case 'topLeft':
case 'top':
return {
left: baseLeftInPixels - deltaW,
top: baseTopInPixels - deltaH,
};
default:
return {
left: baseLeftInPixels,
top: baseTopInPixels,
};
}
};

/**
* Get block position after resizing, considering the rotation.
*
* @param {string} direction Resizing direction.
* @param {Object} originalPosition Original block position, considering the rotation.
* @param {Object} diff Block position difference after resizing.
* @return {{top: number, left: number}} Top and left params in pixels.
*/
export const getUpdatedBlockPosition = ( direction, originalPosition, diff ) => {
switch ( direction ) {
case 'topRight':
return {
left: originalPosition.left - diff.left,
top: originalPosition.top - diff.top,
};
case 'bottomLeft':
return {
left: originalPosition.left + diff.left,
top: originalPosition.top + diff.top,
};
case 'left':
case 'topLeft':
case 'top':
return {
left: originalPosition.left + diff.left,
top: originalPosition.top - diff.top,
};
default:
return {
left: originalPosition.left - diff.left,
top: originalPosition.top + diff.top,
};
}
};

/**
* Get block's left and top position based on width, height, and radian.
*
* @param {number} width Width.
* @param {number} height Height.
* @param {number} radian Radian.
* @param {string} direction Resizing direction.
* @return {{top: number, left: number}} Top and left positioning.
*/
export const getBlockPositioning = ( width, height, radian, direction ) => {
// The center point of the block.
const x = -width / 2;
const y = height / 2;

let rotatedX, rotatedY;
// Get the center point of the rotated block.
if ( 'topRight' === direction || 'bottomLeft' === direction ) {
rotatedX = ( y * -Math.sin( radian ) ) + ( x * Math.cos( radian ) );
rotatedY = ( y * Math.cos( radian ) ) - ( x * -Math.sin( radian ) );
} else {
rotatedX = ( y * Math.sin( radian ) ) + ( x * Math.cos( radian ) );
rotatedY = ( y * Math.cos( radian ) ) - ( x * Math.sin( radian ) );
}

return {
left: rotatedX - x,
top: rotatedY - y,
};
};
Loading