UNPKG

@wordpress/block-editor

Version:
8 lines (7 loc) 3.93 kB
{ "version": 3, "sources": ["../../../../src/components/block-list/use-block-props/use-focus-first-element.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useEffect, useRef } from '@wordpress/element';\nimport {\n\tfocus,\n\tisFormElement,\n\tisTextField,\n\tplaceCaretAtHorizontalEdge,\n} from '@wordpress/dom';\nimport { useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { isInsideRootBlock } from '../../../utils/dom';\nimport { store as blockEditorStore } from '../../../store';\nimport { unlock } from '../../../lock-unlock';\n\n/** @typedef {import('@wordpress/element').RefObject} RefObject */\n\n/**\n * Transitions focus to the block or inner tabbable when the block becomes\n * selected and an initial position is set.\n *\n * @param {string} clientId Block client ID.\n *\n * @return {RefObject} React ref with the block element.\n */\nexport function useFocusFirstElement( { clientId, initialPosition } ) {\n\tconst ref = useRef();\n\tconst { isBlockSelected, isMultiSelecting, isZoomOut } = unlock(\n\t\tuseSelect( blockEditorStore )\n\t);\n\n\tuseEffect( () => {\n\t\t// Check if the block is still selected at the time this effect runs.\n\t\tif (\n\t\t\t! isBlockSelected( clientId ) ||\n\t\t\tisMultiSelecting() ||\n\t\t\tisZoomOut()\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( initialPosition === undefined || initialPosition === null ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! ref.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { ownerDocument } = ref.current;\n\n\t\t// Do not focus the block if it already contains the active element.\n\t\tif ( isInsideRootBlock( ref.current, ownerDocument.activeElement ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find all tabbables within node.\n\t\tconst textInputs = focus.tabbable\n\t\t\t.find( ref.current )\n\t\t\t.filter( ( node ) => isTextField( node ) );\n\n\t\t// If reversed (e.g. merge via backspace), use the last in the set of\n\t\t// tabbables.\n\t\tconst isReverse = -1 === initialPosition;\n\t\tconst target =\n\t\t\ttextInputs[ isReverse ? textInputs.length - 1 : 0 ] || ref.current;\n\n\t\tif ( ! isInsideRootBlock( ref.current, target ) ) {\n\t\t\tref.current.focus();\n\t\t\treturn;\n\t\t}\n\n\t\t// Check to see if element is focussable before a generic caret insert.\n\t\tif ( ! ref.current.getAttribute( 'contenteditable' ) ) {\n\t\t\tconst focusElement = focus.tabbable.findNext( ref.current );\n\t\t\t// Make sure focusElement is valid, contained in the same block, and a form field.\n\t\t\tif (\n\t\t\t\tfocusElement &&\n\t\t\t\tisInsideRootBlock( ref.current, focusElement ) &&\n\t\t\t\tisFormElement( focusElement )\n\t\t\t) {\n\t\t\t\tfocusElement.focus();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tplaceCaretAtHorizontalEdge( target, isReverse );\n\t}, [ initialPosition, clientId ] );\n\n\treturn ref;\n}\n"], "mappings": ";AAGA,SAAS,WAAW,cAAc;AAClC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB;AAK1B,SAAS,yBAAyB;AAClC,SAAS,SAAS,wBAAwB;AAC1C,SAAS,cAAc;AAYhB,SAAS,qBAAsB,EAAE,UAAU,gBAAgB,GAAI;AACrE,QAAM,MAAM,OAAO;AACnB,QAAM,EAAE,iBAAiB,kBAAkB,UAAU,IAAI;AAAA,IACxD,UAAW,gBAAiB;AAAA,EAC7B;AAEA,YAAW,MAAM;AAEhB,QACC,CAAE,gBAAiB,QAAS,KAC5B,iBAAiB,KACjB,UAAU,GACT;AACD;AAAA,IACD;AAEA,QAAK,oBAAoB,UAAa,oBAAoB,MAAO;AAChE;AAAA,IACD;AAEA,QAAK,CAAE,IAAI,SAAU;AACpB;AAAA,IACD;AAEA,UAAM,EAAE,cAAc,IAAI,IAAI;AAG9B,QAAK,kBAAmB,IAAI,SAAS,cAAc,aAAc,GAAI;AACpE;AAAA,IACD;AAGA,UAAM,aAAa,MAAM,SACvB,KAAM,IAAI,OAAQ,EAClB,OAAQ,CAAE,SAAU,YAAa,IAAK,CAAE;AAI1C,UAAM,YAAY,OAAO;AACzB,UAAM,SACL,WAAY,YAAY,WAAW,SAAS,IAAI,CAAE,KAAK,IAAI;AAE5D,QAAK,CAAE,kBAAmB,IAAI,SAAS,MAAO,GAAI;AACjD,UAAI,QAAQ,MAAM;AAClB;AAAA,IACD;AAGA,QAAK,CAAE,IAAI,QAAQ,aAAc,iBAAkB,GAAI;AACtD,YAAM,eAAe,MAAM,SAAS,SAAU,IAAI,OAAQ;AAE1D,UACC,gBACA,kBAAmB,IAAI,SAAS,YAAa,KAC7C,cAAe,YAAa,GAC3B;AACD,qBAAa,MAAM;AACnB;AAAA,MACD;AAAA,IACD;AACA,+BAA4B,QAAQ,SAAU;AAAA,EAC/C,GAAG,CAAE,iBAAiB,QAAS,CAAE;AAEjC,SAAO;AACR;", "names": [] }