azure-devops-ui
Version:
React components for building web UI in Azure DevOps
1 lines • 4.61 kB
JavaScript
import"../../CommonImports";import"../../Core/core.css";import*as React from"react";import{FocusGroup}from"../../FocusGroup";import{ElementRelationship,getRelationship,KeyCode,shimRef}from"../../Util";import{FocusZoneDirection,FocusZoneKeyStroke}from"./FocusZone.Props";const FocusZoneContext=React.createContext({direction:void 0,focuszoneId:void 0});let ignoreEvent=!1,focuszoneId=1;class FocusZone extends React.Component{constructor(e){super(e),this.rootElements=[],this.state={focuszoneId:"focuszone-"+focuszoneId++}}render(){let e=React.createElement(FocusZoneContext.Consumer,null,l=>React.createElement(FocusZoneContext.Provider,{value:{direction:this.props.direction,focuszoneId:this.state.focuszoneId}},React.Children.map(this.props.children,(e,t)=>{if(null===e||"string"==typeof e||"number"==typeof e)return e;if("string"!=typeof e.type)throw Error("Children of a focus zone MUST be DOM elements");const o=e.props.onKeyDown,s=e.props.onFocus;return this.rootElements[t]=shimRef(e),React.cloneElement(e,Object.assign(Object.assign({key:t},e.props),{ref:this.rootElements[t],onFocus:t=>{s&&s(t);var o=document.activeElement;for(let e=0;e<this.rootElements.length;e++){var r=null==(r=this.rootElements[e])?void 0:r.current;r&&(r.contains(o)||r===o)&&(this.lastFocusElement=t.target)}},onKeyDown:r=>{let e=FocusZoneKeyStroke.IgnoreNone;if(o&&o(r),!(ignoreEvent=!ignoreEvent&&this.props.preprocessKeyStroke&&(e=this.props.preprocessKeyStroke(r))===FocusZoneKeyStroke.IgnoreAll?!0:ignoreEvent)&&!r.defaultPrevented&&!this.props.disabled){var s=r.target.nodeName;let e,t,o;if("INPUT"===s||"TEXTAREA"===s){var n=r.target;try{t="number"==typeof n.selectionStart?n.selectionStart:void 0}catch(e){}o=n.value.length}var i=void 0===t||0===t&&this.props.allowArrowOutOfInputs,c=void 0===t||void 0===o||t===o&&this.props.allowArrowOutOfInputs;switch(r.which){case KeyCode.upArrow:"TEXTAREA"!==s&&this.props.direction===FocusZoneDirection.Vertical&&(e=-1);break;case KeyCode.downArrow:"TEXTAREA"!==s&&this.props.direction===FocusZoneDirection.Vertical&&(e=1);break;case KeyCode.rightArrow:c&&this.props.direction===FocusZoneDirection.Horizontal&&(e=1);break;case KeyCode.leftArrow:i&&this.props.direction===FocusZoneDirection.Horizontal&&(e=-1);break;case KeyCode.tab:this.props.handleTabKey&&(e=r.shiftKey?-1:1);break;case KeyCode.enter:this.props.activateOnEnter&&r.target.click()}e&&this.focusNextElement(r,e)&&r.preventDefault()}!(ignoreEvent=e===FocusZoneKeyStroke.IgnoreParents?!0:ignoreEvent)&&this.props.postprocessKeyStroke&&this.props.postprocessKeyStroke(r)===FocusZoneKeyStroke.IgnoreParents&&(ignoreEvent=!0),l.focuszoneId||(ignoreEvent=!1)}}))})));return e=this.props.focusGroupProps?React.createElement(FocusGroup,Object.assign({},this.props.focusGroupProps),e):e}componentDidMount(){let e;var t;(e=this.props.focusOnMount&&(t=this.props["defaultActiveElement"],0<(t=this.getFocusElements("function"==typeof t?t():t)).length)?t[0]:e)&&e.focus({preventScroll:this.props.preventScrollOnFocus})}focusNextElement(o,r){var s=this.getFocusElements();if(0<s.length){var n=document.activeElement,i=this.rootElements;let t=s.indexOf(n);if(-1===t){let e=0;for(e=0;e<i.length;e++){var c=i[e];if(c.current&&c.current.contains(o.target))break}if(e===this.rootElements.length&&this.lastFocusElement)t=s.indexOf(this.lastFocusElement);else for(e=0;e<s.length;e++){var l=getRelationship(n,s[e]);if(l===ElementRelationship.Before){t=e-(0<r?1:0);break}if(l===ElementRelationship.Child){t=e;break}l===ElementRelationship.After&&e===s.length-1&&(t=s.length)}}if(t+=r,this.props.circularNavigation&&(t<0?t=s.length-1:t>=s.length&&(t=0)),-1<t&&t<s.length)return s[t].focus(),this.props.selectInputTextOnFocus&&s[t]instanceof HTMLInputElement&&s[t].select(),!0}return!1}getFocusElements(t){var o=[];let e=t;e||(e="[data-focuszone~="+this.state.focuszoneId+"]",this.props.includeDefaults&&(e+=",a[href],button,iframe,input,select,textarea,[tabIndex]"));for(const n of this.rootElements)if(n.current){var r=n.current.querySelectorAll(e);n.current.matches(e)&&this.isFocusElement(n.current,t)&&o.push(n.current);for(let e=0;e<r.length;e++){var s=r[e];this.isFocusElement(s,t)&&o.push(s)}}return o}isFocusElement(e,t){if(e.hasAttribute("disabled"))return!1;if(!t){if(!this.props.skipHiddenCheck){t=window.getComputedStyle(e);if("hidden"===t.visibility||"none"===t.display||!(e.offsetWidth||e.offsetHeight||e.getClientRects().length))return!1}t=e.getAttribute("tabindex");if(t&&parseInt(t)<0){t=e.getAttribute("data-focuszone");if(!t||t.indexOf(this.state.focuszoneId)<0)return!1}}return!0}}export{FocusZoneContext,FocusZone};