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

Visual editor: remove 4 wrapper divs #27035

Merged
merged 8 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef } from '@wordpress/element';

function useBlockSelectionClearer() {
export function useBlockSelectionClearer( ref ) {
const hasSelection = useSelect( ( select ) => {
const { hasSelectedBlock, hasMultiSelection } = select(
'core/block-editor'
Expand All @@ -13,14 +14,25 @@ function useBlockSelectionClearer() {
} );
const { clearSelectedBlock } = useDispatch( 'core/block-editor' );

return ( event ) => {
if ( event.target === event.currentTarget && hasSelection ) {
useEffect( () => {
if ( ! hasSelection ) {
return;
}

function onFocus() {
clearSelectedBlock();
}
};

ref.current.addEventListener( 'focus', onFocus );

return () => {
ref.current.removeEventListener( 'focus', onFocus );
};
}, [ hasSelection, clearSelectedBlock ] );
}

export default function BlockSelectionClearer( props ) {
const onFocus = useBlockSelectionClearer();
return <div tabIndex={ -1 } onFocus={ onFocus } { ...props } />;
const ref = useRef();
useBlockSelectionClearer( ref );
return <div tabIndex={ -1 } ref={ ref } { ...props } />;
}
144 changes: 73 additions & 71 deletions packages/block-editor/src/components/copy-handler/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { useCallback, useRef } from '@wordpress/element';
import { useCallback, useEffect, useRef } from '@wordpress/element';
import { serialize, pasteHandler } from '@wordpress/blocks';
import {
documentHasSelection,
Expand Down Expand Up @@ -71,97 +71,99 @@ export function useNotifyCopy() {
}, [] );
}

function CopyHandler( { children } ) {
const containerRef = useRef();

export function useClipboardHandler( ref ) {
const {
getBlocksByClientId,
getSelectedBlockClientIds,
hasMultiSelection,
getSettings,
} = useSelect( ( select ) => select( 'core/block-editor' ), [] );

const { flashBlock, removeBlocks, replaceBlocks } = useDispatch(
'core/block-editor'
);

const notifyCopy = useNotifyCopy();

const {
__experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML,
} = getSettings();
useEffect( () => {
function handler( event ) {
const selectedBlockClientIds = getSelectedBlockClientIds();

const handler = ( event ) => {
const selectedBlockClientIds = getSelectedBlockClientIds();
if ( selectedBlockClientIds.length === 0 ) {
return;
}

if ( selectedBlockClientIds.length === 0 ) {
return;
}
// Always handle multiple selected blocks.
if ( ! hasMultiSelection() ) {
const { target } = event;
const { ownerDocument } = target;
// If copying, only consider actual text selection as selection.
// Otherwise, any focus on an input field is considered.
const hasSelection =
event.type === 'copy' || event.type === 'cut'
? documentHasUncollapsedSelection( ownerDocument )
: documentHasSelection( ownerDocument );

// Let native copy behaviour take over in input fields.
if ( hasSelection ) {
return;
}
}

// Always handle multiple selected blocks.
if ( ! hasMultiSelection() ) {
const { target } = event;
const { ownerDocument } = target;
// If copying, only consider actual text selection as selection.
// Otherwise, any focus on an input field is considered.
const hasSelection =
event.type === 'copy' || event.type === 'cut'
? documentHasUncollapsedSelection( ownerDocument )
: documentHasSelection( ownerDocument );

// Let native copy behaviour take over in input fields.
if ( hasSelection ) {
if ( ! ref.current.contains( event.target ) ) {
return;
}
}
event.preventDefault();

if ( event.type === 'copy' || event.type === 'cut' ) {
if ( selectedBlockClientIds.length === 1 ) {
flashBlock( selectedBlockClientIds[ 0 ] );
}
notifyCopy( event.type, selectedBlockClientIds );
const blocks = getBlocksByClientId( selectedBlockClientIds );
const serialized = serialize( blocks );

event.clipboardData.setData( 'text/plain', serialized );
event.clipboardData.setData( 'text/html', serialized );
}

if ( ! containerRef.current.contains( event.target ) ) {
return;
if ( event.type === 'cut' ) {
removeBlocks( selectedBlockClientIds );
} else if ( event.type === 'paste' ) {
const {
__experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML,
} = getSettings();
const { plainText, html } = getPasteEventData( event );
const blocks = pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML,
} );

replaceBlocks(
selectedBlockClientIds,
blocks,
blocks.length - 1,
-1
);
}
}
event.preventDefault();

if ( event.type === 'copy' || event.type === 'cut' ) {
if ( selectedBlockClientIds.length === 1 ) {
flashBlock( selectedBlockClientIds[ 0 ] );
}
notifyCopy( event.type, selectedBlockClientIds );
const blocks = getBlocksByClientId( selectedBlockClientIds );
const serialized = serialize( blocks );
ref.current.addEventListener( 'copy', handler );
ref.current.addEventListener( 'cut', handler );
ref.current.addEventListener( 'paste', handler );

event.clipboardData.setData( 'text/plain', serialized );
event.clipboardData.setData( 'text/html', serialized );
}
return () => {
ref.current.removeEventListener( 'copy', handler );
ref.current.removeEventListener( 'cut', handler );
ref.current.removeEventListener( 'paste', handler );
};
}, [] );
}

if ( event.type === 'cut' ) {
removeBlocks( selectedBlockClientIds );
} else if ( event.type === 'paste' ) {
const { plainText, html } = getPasteEventData( event );
const blocks = pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML,
} );

replaceBlocks(
selectedBlockClientIds,
blocks,
blocks.length - 1,
-1
);
}
};

return (
<div
ref={ containerRef }
onCopy={ handler }
onCut={ handler }
onPaste={ handler }
>
{ children }
</div>
);
function CopyHandler( { children } ) {
const ref = useRef();
useClipboardHandler( ref );
return <div ref={ ref }>{ children }</div>;
}

export default CopyHandler;
25 changes: 20 additions & 5 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,39 @@ export {
} from './block-list/block-wrapper';
export { default as BlockMover } from './block-mover';
export { default as BlockPreview } from './block-preview';
export { default as BlockSelectionClearer } from './block-selection-clearer';
export {
default as BlockSelectionClearer,
useBlockSelectionClearer as __unstableUseBlockSelectionClearer,
} from './block-selection-clearer';
export { default as BlockSettingsMenu } from './block-settings-menu';
export { default as BlockSettingsMenuControls } from './block-settings-menu-controls';
export { default as BlockTitle } from './block-title';
export { default as BlockToolbar } from './block-toolbar';
export { default as CopyHandler } from './copy-handler';
export {
default as CopyHandler,
useClipboardHandler as __unstableUseClipboardHandler,
} from './copy-handler';
export { default as DefaultBlockAppender } from './default-block-appender';
export { default as __unstableEditorStyles } from './editor-styles';
export { default as Inserter } from './inserter';
export { default as __experimentalLibrary } from './inserter/library';
export { default as __experimentalSearchForm } from './inserter/search-form';
export { default as BlockEditorKeyboardShortcuts } from './keyboard-shortcuts';
export { default as MultiSelectScrollIntoView } from './multi-select-scroll-into-view';
export {
default as MultiSelectScrollIntoView,
useScrollMultiSelectionIntoView as __unstableUseScrollMultiSelectionIntoView,
} from './multi-select-scroll-into-view';
export { default as NavigableToolbar } from './navigable-toolbar';
export { default as ObserveTyping } from './observe-typing';
export {
default as ObserveTyping,
useTypingObserver as __unstableUseTypingObserver,
} from './observe-typing';
export { default as PreserveScrollInReorder } from './preserve-scroll-in-reorder';
export { default as SkipToSelectedBlock } from './skip-to-selected-block';
export { default as Typewriter } from './typewriter';
export {
default as Typewriter,
useTypewriter as __unstableUseTypewriter,
} from './typewriter';
export { default as Warning } from './warning';
export { default as WritingFlow } from './writing-flow';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,29 @@ import { getScrollContainer } from '@wordpress/dom';
*/
import { getBlockDOMNode } from '../../utils/dom';

/**
* Scrolls the multi block selection end into view if not in view already. This
* is important to do after selection by keyboard.
*/
export default function MultiSelectScrollIntoView() {
const selector = ( select ) => {
export function useScrollMultiSelectionIntoView( ref ) {
const selectionEnd = useSelect( ( select ) => {
const {
getBlockSelectionEnd,
hasMultiSelection,
isMultiSelecting,
} = select( 'core/block-editor' );

return {
selectionEnd: getBlockSelectionEnd(),
isMultiSelection: hasMultiSelection(),
isMultiSelecting: isMultiSelecting(),
};
};
const { isMultiSelection, selectionEnd, isMultiSelecting } = useSelect(
selector,
[]
);
const ref = useRef();
const blockSelectionEnd = getBlockSelectionEnd();

if (
! blockSelectionEnd ||
isMultiSelecting() ||
! hasMultiSelection()
) {
return;
}

return blockSelectionEnd;
}, [] );

useEffect( () => {
if ( ! selectionEnd || isMultiSelecting || ! isMultiSelection ) {
if ( ! selectionEnd ) {
return;
}

Expand All @@ -62,7 +59,15 @@ export default function MultiSelectScrollIntoView() {
scrollIntoView( extentNode, scrollContainer, {
onlyScrollIfNeeded: true,
} );
}, [ isMultiSelection, selectionEnd, isMultiSelecting ] );
}, [ selectionEnd ] );
}

/**
* Scrolls the multi block selection end into view if not in view already. This
* is important to do after selection by keyboard.
*/
export default function MultiSelectScrollIntoView() {
const ref = useRef();
useScrollMultiSelectionIntoView( ref );
return <div ref={ ref } />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function isKeyDownEligibleForStartTyping( event ) {
return ! shiftKey && KEY_DOWN_ELIGIBLE_KEY_CODES.has( keyCode );
}

function useTypingObserver( ref ) {
export function useTypingObserver( ref ) {
const isTyping = useSelect( ( select ) =>
select( 'core/block-editor' ).isTyping()
);
Expand Down
7 changes: 5 additions & 2 deletions packages/block-editor/src/components/typewriter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ const isIE = window.navigator.userAgent.indexOf( 'Trident' ) !== -1;
const arrowKeyCodes = new Set( [ UP, DOWN, LEFT, RIGHT ] );
const initialTriggerPercentage = 0.75;

function Typewriter( { children } ) {
const ref = useRef();
export function useTypewriter( ref ) {
const hasSelectedBlock = useSelect( ( select ) =>
select( 'core/block-editor' ).hasSelectedBlock()
);
Expand Down Expand Up @@ -242,7 +241,11 @@ function Typewriter( { children } ) {
defaultView.cancelAnimationFrame( onKeyDownRafId );
};
}, [ hasSelectedBlock ] );
}

function Typewriter( { children } ) {
const ref = useRef();
useTypewriter( ref );
return (
<div ref={ ref } className="block-editor__typewriter">
{ children }
Expand Down
5 changes: 3 additions & 2 deletions packages/block-editor/src/components/writing-flow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ export default function WritingFlow( { children } ) {
// bubbling events from children to determine focus transition intents.
/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<div className={ className }>
<>
<FocusCapture
ref={ focusCaptureBeforeRef }
selectedClientId={ selectedBlockClientId }
Expand All @@ -719,6 +719,7 @@ export default function WritingFlow( { children } ) {
/>
<div
ref={ container }
className={ className }
onKeyDown={ onKeyDown }
onMouseDown={ onMouseDown }
>
Expand Down Expand Up @@ -751,7 +752,7 @@ export default function WritingFlow( { children } ) {
onClick={ focusLastTextField }
className="block-editor-writing-flow__click-redirect"
/>
</div>
</>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
}
Loading