Skip to content

Commit

Permalink
Visual editor: remove 4 wrapper divs (#27035)
Browse files Browse the repository at this point in the history
* typing observer

* clipboard and selection clearer

* Collapse divs

* Fix selector

* Popover needs relative container

* Fix keyboard nav test

* Fix click redirect

* Remove useless check
  • Loading branch information
ellatrix authored Nov 17, 2020
1 parent a57cc16 commit bcd4775
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 140 deletions.
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

0 comments on commit bcd4775

Please sign in to comment.