UNPKG

@wordpress/block-editor

Version:
8 lines (7 loc) 7.21 kB
{ "version": 3, "sources": ["../../../src/components/writing-flow/use-drag-selection.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { useRefEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\n/**\n * Sets the `contenteditable` wrapper element to `value`.\n *\n * @param {HTMLElement} node Block element.\n * @param {boolean} value `contentEditable` value (true or false)\n */\nfunction setContentEditableWrapper( node, value ) {\n\tnode.contentEditable = value;\n\t// Firefox doesn't automatically move focus.\n\tif ( value ) {\n\t\tnode.focus();\n\t}\n}\n\n/**\n * Sets a multi-selection based on the native selection across blocks.\n */\nexport default function useDragSelection() {\n\tconst { startMultiSelect, stopMultiSelect } =\n\t\tuseDispatch( blockEditorStore );\n\tconst {\n\t\tisSelectionEnabled,\n\t\thasSelectedBlock,\n\t\tisDraggingBlocks,\n\t\tisMultiSelecting,\n\t} = useSelect( blockEditorStore );\n\treturn useRefEffect(\n\t\t( node ) => {\n\t\t\tconst { ownerDocument } = node;\n\t\t\tconst { defaultView } = ownerDocument;\n\n\t\t\tlet anchorElement;\n\t\t\tlet rafId;\n\n\t\t\tfunction onMouseUp() {\n\t\t\t\tstopMultiSelect();\n\t\t\t\t// Equivalent to attaching the listener once.\n\t\t\t\tdefaultView.removeEventListener( 'mouseup', onMouseUp );\n\t\t\t\t// The browser selection won't have updated yet at this point,\n\t\t\t\t// so wait until the next animation frame to get the browser\n\t\t\t\t// selection.\n\t\t\t\trafId = defaultView.requestAnimationFrame( () => {\n\t\t\t\t\tif ( ! hasSelectedBlock() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the selection is complete (on mouse up), and no\n\t\t\t\t\t// multiple blocks have been selected, set focus back to the\n\t\t\t\t\t// anchor element. if the anchor element contains the\n\t\t\t\t\t// selection. Additionally, the contentEditable wrapper can\n\t\t\t\t\t// now be disabled again.\n\t\t\t\t\tsetContentEditableWrapper( node, false );\n\n\t\t\t\t\tconst selection = defaultView.getSelection();\n\n\t\t\t\t\tif ( selection.rangeCount ) {\n\t\t\t\t\t\tconst range = selection.getRangeAt( 0 );\n\t\t\t\t\t\tconst { commonAncestorContainer } = range;\n\t\t\t\t\t\tconst clonedRange = range.cloneRange();\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tanchorElement.contains( commonAncestorContainer )\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tanchorElement.focus();\n\t\t\t\t\t\t\tselection.removeAllRanges();\n\t\t\t\t\t\t\tselection.addRange( clonedRange );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet lastMouseDownTarget;\n\n\t\t\tfunction onMouseDown( { target } ) {\n\t\t\t\tlastMouseDownTarget = target;\n\t\t\t}\n\n\t\t\tfunction onMouseLeave( { buttons, target, relatedTarget } ) {\n\t\t\t\tif ( ! target.contains( lastMouseDownTarget ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If we're moving into a child element, ignore. We're tracking\n\t\t\t\t// the mouse leaving the element to a parent, no a child.\n\t\t\t\tif ( target.contains( relatedTarget ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Avoid triggering a multi-selection if the user is already\n\t\t\t\t// dragging blocks.\n\t\t\t\tif ( isDraggingBlocks() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// The primary button must be pressed to initiate selection.\n\t\t\t\t// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons\n\t\t\t\tif ( buttons !== 1 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Abort if we are already multi-selecting.\n\t\t\t\tif ( isMultiSelecting() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Abort if selection is leaving writing flow.\n\t\t\t\tif ( node === target ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Check the attribute, not the contentEditable attribute. All\n\t\t\t\t// child elements of the content editable wrapper are editable\n\t\t\t\t// and return true for this property. We only want to start\n\t\t\t\t// multi selecting when the mouse leaves the wrapper.\n\t\t\t\tif ( target.getAttribute( 'contenteditable' ) !== 'true' ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( ! isSelectionEnabled() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Do not rely on the active element because it may change after\n\t\t\t\t// the mouse leaves for the first time. See\n\t\t\t\t// https://github.com/WordPress/gutenberg/issues/48747.\n\t\t\t\tanchorElement = target;\n\n\t\t\t\tstartMultiSelect();\n\n\t\t\t\t// `onSelectionStart` is called after `mousedown` and\n\t\t\t\t// `mouseleave` (from a block). The selection ends when\n\t\t\t\t// `mouseup` happens anywhere in the window.\n\t\t\t\tdefaultView.addEventListener( 'mouseup', onMouseUp );\n\n\t\t\t\t// Allow cross contentEditable selection by temporarily making\n\t\t\t\t// all content editable. We can't rely on using the store and\n\t\t\t\t// React because re-rending happens too slowly. We need to be\n\t\t\t\t// able to select across instances immediately.\n\t\t\t\tsetContentEditableWrapper( node, true );\n\t\t\t}\n\n\t\t\tnode.addEventListener( 'mouseout', onMouseLeave );\n\t\t\tnode.addEventListener( 'mousedown', onMouseDown );\n\n\t\t\treturn () => {\n\t\t\t\tnode.removeEventListener( 'mouseout', onMouseLeave );\n\t\t\t\tdefaultView.removeEventListener( 'mouseup', onMouseUp );\n\t\t\t\tdefaultView.cancelAnimationFrame( rafId );\n\t\t\t};\n\t\t},\n\t\t[\n\t\t\tstartMultiSelect,\n\t\t\tstopMultiSelect,\n\t\t\tisSelectionEnabled,\n\t\t\thasSelectedBlock,\n\t\t]\n\t);\n}\n"], "mappings": ";AAGA,SAAS,WAAW,mBAAmB;AACvC,SAAS,oBAAoB;AAK7B,SAAS,SAAS,wBAAwB;AAQ1C,SAAS,0BAA2B,MAAM,OAAQ;AACjD,OAAK,kBAAkB;AAEvB,MAAK,OAAQ;AACZ,SAAK,MAAM;AAAA,EACZ;AACD;AAKe,SAAR,mBAAoC;AAC1C,QAAM,EAAE,kBAAkB,gBAAgB,IACzC,YAAa,gBAAiB;AAC/B,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,UAAW,gBAAiB;AAChC,SAAO;AAAA,IACN,CAAE,SAAU;AACX,YAAM,EAAE,cAAc,IAAI;AAC1B,YAAM,EAAE,YAAY,IAAI;AAExB,UAAI;AACJ,UAAI;AAEJ,eAAS,YAAY;AACpB,wBAAgB;AAEhB,oBAAY,oBAAqB,WAAW,SAAU;AAItD,gBAAQ,YAAY,sBAAuB,MAAM;AAChD,cAAK,CAAE,iBAAiB,GAAI;AAC3B;AAAA,UACD;AAOA,oCAA2B,MAAM,KAAM;AAEvC,gBAAM,YAAY,YAAY,aAAa;AAE3C,cAAK,UAAU,YAAa;AAC3B,kBAAM,QAAQ,UAAU,WAAY,CAAE;AACtC,kBAAM,EAAE,wBAAwB,IAAI;AACpC,kBAAM,cAAc,MAAM,WAAW;AAErC,gBACC,cAAc,SAAU,uBAAwB,GAC/C;AACD,4BAAc,MAAM;AACpB,wBAAU,gBAAgB;AAC1B,wBAAU,SAAU,WAAY;AAAA,YACjC;AAAA,UACD;AAAA,QACD,CAAE;AAAA,MACH;AAEA,UAAI;AAEJ,eAAS,YAAa,EAAE,OAAO,GAAI;AAClC,8BAAsB;AAAA,MACvB;AAEA,eAAS,aAAc,EAAE,SAAS,QAAQ,cAAc,GAAI;AAC3D,YAAK,CAAE,OAAO,SAAU,mBAAoB,GAAI;AAC/C;AAAA,QACD;AAIA,YAAK,OAAO,SAAU,aAAc,GAAI;AACvC;AAAA,QACD;AAIA,YAAK,iBAAiB,GAAI;AACzB;AAAA,QACD;AAIA,YAAK,YAAY,GAAI;AACpB;AAAA,QACD;AAGA,YAAK,iBAAiB,GAAI;AACzB;AAAA,QACD;AAGA,YAAK,SAAS,QAAS;AACtB;AAAA,QACD;AAMA,YAAK,OAAO,aAAc,iBAAkB,MAAM,QAAS;AAC1D;AAAA,QACD;AAEA,YAAK,CAAE,mBAAmB,GAAI;AAC7B;AAAA,QACD;AAKA,wBAAgB;AAEhB,yBAAiB;AAKjB,oBAAY,iBAAkB,WAAW,SAAU;AAMnD,kCAA2B,MAAM,IAAK;AAAA,MACvC;AAEA,WAAK,iBAAkB,YAAY,YAAa;AAChD,WAAK,iBAAkB,aAAa,WAAY;AAEhD,aAAO,MAAM;AACZ,aAAK,oBAAqB,YAAY,YAAa;AACnD,oBAAY,oBAAqB,WAAW,SAAU;AACtD,oBAAY,qBAAsB,KAAM;AAAA,MACzC;AAAA,IACD;AAAA,IACA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;", "names": [] }