diff --git a/packages/dom/README.md b/packages/dom/README.md index d52e47552f342..12a3eb3f49d2c 100644 --- a/packages/dom/README.md +++ b/packages/dom/README.md @@ -52,7 +52,7 @@ _Parameters_ _Returns_ -- `?Node`: Offset parent. +- `(Element|null)`: Offset parent. # **getRectangleFromRange** @@ -68,15 +68,15 @@ _Returns_ # **getScrollContainer** -Given a DOM node, finds the closest scrollable container node. +Given a DOM element, finds the closest scrollable container element. _Parameters_ -- _node_ `Element`: Node from which to start. +- _element_ `Element`: Element from which to start. _Returns_ -- `?Element`: Scrollable container node, if found. +- `(Element|undefined)`: Scrollable container node, if found. # **insertAfter** @@ -85,12 +85,8 @@ the latter. _Parameters_ -- _newNode_ `Element`: Node to be inserted. -- _referenceNode_ `Element`: Node after which to perform the insertion. - -_Returns_ - -- `void`: +- _newNode_ `Node`: Node to be inserted. +- _referenceNode_ `Node`: Node after which to perform the insertion. # **isEntirelySelected** @@ -99,7 +95,7 @@ Returns true if there is no possibility of selection. _Parameters_ -- _element_ `Element`: The element to check. +- _element_ `HTMLElement`: The element to check. _Returns_ @@ -111,7 +107,7 @@ Check whether the selection is horizontally at the edge of the container. _Parameters_ -- _container_ `Element`: Focusable element. +- _container_ `HTMLElement`: Focusable element. - _isReverse_ `boolean`: Set to true to check left, false for right. _Returns_ @@ -139,7 +135,7 @@ Check whether the selection is vertically at the edge of the container. _Parameters_ -- _container_ `Element`: Focusable element. +- _container_ `HTMLElement`: Focusable element. - _isReverse_ `boolean`: Set to true to check top, false for bottom. _Returns_ @@ -152,7 +148,7 @@ Places the caret at start or end of a given element. _Parameters_ -- _container_ `Element`: Focusable element. +- _container_ `(HTMLElement|undefined)`: Focusable element. - _isReverse_ `boolean`: True for end, false for start. # **placeCaretAtVerticalEdge** @@ -161,7 +157,7 @@ Places the caret at the top or bottom of a given element. _Parameters_ -- _container_ `Element`: Focusable element. +- _container_ `(HTMLElement|undefined)`: Focusable element. - _isReverse_ `boolean`: True for bottom, false for top. - _rect_ `[DOMRect]`: The rectangle to position the caret with. - _mayUseScroll_ `[boolean]`: True to allow scrolling, false to disallow. @@ -172,11 +168,7 @@ Given a DOM node, removes it from the DOM. _Parameters_ -- _node_ `Element`: Node to be removed. - -_Returns_ - -- `void`: +- _node_ `Node`: Node to be removed. # **replace** @@ -184,12 +176,8 @@ Given two DOM nodes, replaces the former with the latter in the DOM. _Parameters_ -- _processedNode_ `Element`: Node to be removed. -- _newNode_ `Element`: Node to be inserted in its place. - -_Returns_ - -- `void`: +- _processedNode_ `Node`: Node to be removed. +- _newNode_ `Node`: Node to be inserted in its place. # **replaceTag** @@ -197,12 +185,12 @@ Replaces the given node with a new node with the given tag name. _Parameters_ -- _node_ `Element`: The node to replace -- _tagName_ `string`: The new tag name. +- _node_ `Node`: The node to replace. +- _tagName_ `T`: The new tag name. _Returns_ -- `Element`: The new node. +- `null`: The new node. # **unwrap** @@ -212,18 +200,14 @@ _Parameters_ - _node_ `Node`: The node to unwrap. -_Returns_ - -- `void`: - # **wrap** Wraps the given node with a new node with the given tag name. _Parameters_ -- _newNode_ `Element`: The node to insert. -- _referenceNode_ `Element`: The node to wrap. +- _newNode_ `Node`: The node to insert. +- _referenceNode_ `Node`: The node to wrap. diff --git a/packages/dom/src/dom.js b/packages/dom/src/dom.js index 64fb97534f60a..901d2405c8622 100644 --- a/packages/dom/src/dom.js +++ b/packages/dom/src/dom.js @@ -64,9 +64,9 @@ function isSelectionForward( selection ) { * horizontal position by default. Set `onlyVertical` to true to check only * vertically. * - * @param {Element} container Focusable element. - * @param {boolean} isReverse Set to true to check left, false to check right. - * @param {boolean} onlyVertical Set to true to check only vertical position. + * @param {HTMLElement} container Focusable element. + * @param {boolean} isReverse Set to true to check left, false to check right. + * @param {boolean} onlyVertical Set to true to check only vertical position. * * @return {boolean} True if at the edge, false if not. */ @@ -169,8 +169,8 @@ function isEdge( container, isReverse, onlyVertical ) { /** * Check whether the selection is horizontally at the edge of the container. * - * @param {Element} container Focusable element. - * @param {boolean} isReverse Set to true to check left, false for right. + * @param {HTMLElement} container Focusable element. + * @param {boolean} isReverse Set to true to check left, false for right. * * @return {boolean} True if at the horizontal edge, false if not. */ @@ -181,7 +181,7 @@ export function isHorizontalEdge( container, isReverse ) { /** * Check whether the selection is vertically at the edge of the container. * - * @param {Element} container Focusable element. + * @param {HTMLElement} container Focusable element. * @param {boolean} isReverse Set to true to check top, false for bottom. * * @return {boolean} True if at the vertical edge, false if not. @@ -255,8 +255,8 @@ export function computeCaretRect() { /** * Places the caret at start or end of a given element. * - * @param {Element} container Focusable element. - * @param {boolean} isReverse True for end, false for start. + * @param {HTMLElement|undefined} container Focusable element. + * @param {boolean} isReverse True for end, false for start. */ export function placeCaretAtHorizontalEdge( container, isReverse ) { if ( ! container ) { @@ -364,10 +364,10 @@ function hiddenCaretRangeFromPoint( doc, x, y, container ) { /** * Places the caret at the top or bottom of a given element. * - * @param {Element} container Focusable element. - * @param {boolean} isReverse True for bottom, false for top. - * @param {DOMRect} [rect] The rectangle to position the caret with. - * @param {boolean} [mayUseScroll=true] True to allow scrolling, false to disallow. + * @param {HTMLElement|undefined} container Focusable element. + * @param {boolean} isReverse True for bottom, false for top. + * @param {DOMRect} [rect] The rectangle to position the caret with. + * @param {boolean} [mayUseScroll=true] True to allow scrolling, false to disallow. */ export function placeCaretAtVerticalEdge( container, isReverse, rect, mayUseScroll = true ) { if ( ! container ) { @@ -484,7 +484,7 @@ export function documentHasSelection() { * Check whether the contents of the element have been entirely selected. * Returns true if there is no possibility of selection. * - * @param {Element} element The element to check. + * @param {HTMLElement} element The element to check. * * @return {boolean} True if entirely selected, false if not. */ @@ -529,28 +529,28 @@ export function isEntirelySelected( element ) { } /** - * Given a DOM node, finds the closest scrollable container node. + * Given a DOM element, finds the closest scrollable container element. * - * @param {Element} node Node from which to start. + * @param {Element} element Element from which to start. * - * @return {?Element} Scrollable container node, if found. + * @return {Element|undefined} Scrollable container node, if found. */ -export function getScrollContainer( node ) { - if ( ! node ) { +export function getScrollContainer( element ) { + if ( ! element ) { return; } // Scrollable if scrollable height exceeds displayed... - if ( node.scrollHeight > node.clientHeight ) { + if ( element.scrollHeight > element.clientHeight ) { // ...except when overflow is defined to be hidden or visible - const { overflowY } = window.getComputedStyle( node ); + const { overflowY } = window.getComputedStyle( element ); if ( /(auto|scroll)/.test( overflowY ) ) { - return node; + return element; } } // Continue traversing - return getScrollContainer( node.parentNode ); + return getScrollContainer( element.parentElement ); } /** @@ -562,7 +562,7 @@ export function getScrollContainer( node ) { * * @param {Node} node Node from which to find offset parent. * - * @return {?Node} Offset parent. + * @return {Element|null} Offset parent. */ export function getOffsetParent( node ) { // Cannot retrieve computed style or offset parent only anything other than @@ -590,9 +590,8 @@ export function getOffsetParent( node ) { /** * Given two DOM nodes, replaces the former with the latter in the DOM. * - * @param {Element} processedNode Node to be removed. - * @param {Element} newNode Node to be inserted in its place. - * @return {void} + * @param {Node} processedNode Node to be removed. + * @param {Node} newNode Node to be inserted in its place. */ export function replace( processedNode, newNode ) { insertAfter( newNode, processedNode.parentNode ); @@ -602,8 +601,7 @@ export function replace( processedNode, newNode ) { /** * Given a DOM node, removes it from the DOM. * - * @param {Element} node Node to be removed. - * @return {void} + * @param {Node} node Node to be removed. */ export function remove( node ) { node.parentNode.removeChild( node ); @@ -613,9 +611,8 @@ export function remove( node ) { * Given two DOM nodes, inserts the former in the DOM as the next sibling of * the latter. * - * @param {Element} newNode Node to be inserted. - * @param {Element} referenceNode Node after which to perform the insertion. - * @return {void} + * @param {Node} newNode Node to be inserted. + * @param {Node} referenceNode Node after which to perform the insertion. */ export function insertAfter( newNode, referenceNode ) { referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling ); @@ -625,8 +622,6 @@ export function insertAfter( newNode, referenceNode ) { * Unwrap the given node. This means any child nodes are moved to the parent. * * @param {Node} node The node to unwrap. - * - * @return {void} */ export function unwrap( node ) { const parent = node.parentNode; @@ -638,13 +633,15 @@ export function unwrap( node ) { parent.removeChild( node ); } +// eslint-disable-next-line valid-jsdoc /** * Replaces the given node with a new node with the given tag name. * - * @param {Element} node The node to replace - * @param {string} tagName The new tag name. + * @template {keyof HTMLElementTagNameMap} T + * @param {Node} node The node to replace. + * @param {T} tagName The new tag name. * - * @return {Element} The new node. + * @return {HTMLElementTagNameMap[T]} The new node. */ export function replaceTag( node, tagName ) { const newNode = node.ownerDocument.createElement( tagName ); @@ -661,8 +658,8 @@ export function replaceTag( node, tagName ) { /** * Wraps the given node with a new node with the given tag name. * - * @param {Element} newNode The node to insert. - * @param {Element} referenceNode The node to wrap. + * @param {Node} newNode The node to insert. + * @param {Node} referenceNode The node to wrap. */ export function wrap( newNode, referenceNode ) { referenceNode.parentNode.insertBefore( newNode, referenceNode ); diff --git a/packages/dom/src/focusable.js b/packages/dom/src/focusable.js index 133b89d366974..0491741c1b231 100644 --- a/packages/dom/src/focusable.js +++ b/packages/dom/src/focusable.js @@ -35,7 +35,7 @@ const SELECTOR = [ * Returns true if the specified element is visible (i.e. neither display: none * nor visibility: hidden). * - * @param {Element} element DOM element to test. + * @param {HTMLElement} element DOM element to test. * * @return {boolean} Whether element is visible. */ @@ -69,7 +69,7 @@ function isValidFocusableArea( element ) { /** * Returns all focusable elements within a given context. * - * @param {Element} context Element in which to search. + * @param {ParentNode} context Element in which to search. * * @return {Element[]} Focusable elements. */ diff --git a/packages/dom/src/tabbable.js b/packages/dom/src/tabbable.js index 315a98b8b2a8e..8cac26ac5178e 100644 --- a/packages/dom/src/tabbable.js +++ b/packages/dom/src/tabbable.js @@ -8,6 +8,12 @@ import { without } from 'lodash'; */ import { find as findFocusable } from './focusable'; +/** + * @typedef {Object} ObjectTabbable + * @prop {Element} element Element to be indexed. + * @prop {number} index Index of the element. + */ + /** * Returns the tab index of the given element. In contrast with the tabIndex * property, this normalizes the default (0) to avoid browser inconsistencies, @@ -86,7 +92,7 @@ function createStatefulCollapseRadioGroup() { * @param {Element} element Element. * @param {number} index Array index of element. * - * @return {Object} Mapped object with element, index. + * @return {ObjectTabbable} Mapped object with element, index. */ function mapElementToObjectTabbable( element, index ) { return { element, index }; @@ -96,7 +102,7 @@ function mapElementToObjectTabbable( element, index ) { * An array map callback, returning an element of the given mapped object's * element value. * - * @param {Object} object Mapped object with index. + * @param {ObjectTabbable} object Mapped object with index. * * @return {Element} Mapped object element. */ @@ -109,8 +115,8 @@ function mapObjectTabbableToElement( object ) { * * @see mapElementToObjectTabbable * - * @param {Object} a First object to compare. - * @param {Object} b Second object to compare. + * @param {ObjectTabbable} a First object to compare. + * @param {ObjectTabbable} b Second object to compare. * * @return {number} Comparator result. */ @@ -125,6 +131,15 @@ function compareObjectTabbables( a, b ) { return aTabIndex - bTabIndex; } +/** + * Returns a filtered array of tabbable elements, where at most one radio + * input is selected for a given name, giving priority to checked input, + * falling back to the first encountered. + * + * @param {ParentNode} context Element in which to search. + * + * @return {Element[]} Tabbable elements. + */ export function find( context ) { return findFocusable( context ) .filter( isTabbableIndex )