jobiqo-cl
Version:
[](https://circleci.com/gh/jobiqo/jobiqo-cl)
254 lines (207 loc) • 7.16 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var index = require('../../../prop-types/index.js');
var medium = require('./medium.js');
var index_es = require('../../../react-clientside-effect/lib/index.es.js');
var focusMerge = require('../../../focus-lock/dist/es2015/focusMerge.js');
var focusInside = require('../../../focus-lock/dist/es2015/focusInside.js');
var focusIsHidden = require('../../../focus-lock/dist/es2015/focusIsHidden.js');
var index$1 = require('../../../focus-lock/dist/es2015/index.js');
var util = require('./util.js');
var focusOnBody = function focusOnBody() {
return document && document.activeElement === document.body;
};
var isFreeFocus = function isFreeFocus() {
return focusOnBody() || focusIsHidden.default();
};
var lastActiveTrap = null;
var lastActiveFocus = null;
var lastPortaledElement = null;
var focusWasOutsideWindow = false;
var defaultWhitelist = function defaultWhitelist() {
return true;
};
var focusWhitelisted = function focusWhitelisted(activeElement) {
return (lastActiveTrap.whiteList || defaultWhitelist)(activeElement);
};
var recordPortal = function recordPortal(observerNode, portaledElement) {
lastPortaledElement = {
observerNode: observerNode,
portaledElement: portaledElement
};
};
var focusIsPortaledPair = function focusIsPortaledPair(element) {
return lastPortaledElement && lastPortaledElement.portaledElement === element;
};
function autoGuard(startIndex, end, step, allNodes) {
var lastGuard = null;
var i = startIndex;
do {
var item = allNodes[i];
if (item.guard) {
if (item.node.dataset.focusAutoGuard) {
lastGuard = item;
}
} else if (item.lockItem) {
if (i !== startIndex) {
// we will tab to the next element
return;
}
lastGuard = null;
} else {
break;
}
} while ((i += step) !== end);
if (lastGuard) {
lastGuard.node.tabIndex = 0;
}
}
var extractRef = function extractRef(ref) {
return ref && 'current' in ref ? ref.current : ref;
};
var activateTrap = function activateTrap() {
var result = false;
if (lastActiveTrap) {
var _lastActiveTrap = lastActiveTrap,
observed = _lastActiveTrap.observed,
persistentFocus = _lastActiveTrap.persistentFocus,
autoFocus = _lastActiveTrap.autoFocus,
shards = _lastActiveTrap.shards;
var workingNode = observed || lastPortaledElement && lastPortaledElement.portaledElement;
var activeElement = document && document.activeElement;
if (workingNode) {
var workingArea = [workingNode].concat(shards.map(extractRef).filter(Boolean));
if (!activeElement || focusWhitelisted(activeElement)) {
if (persistentFocus || focusWasOutsideWindow || !isFreeFocus() || !lastActiveFocus && autoFocus) {
if (workingNode && !(focusInside.default(workingArea) || focusIsPortaledPair(activeElement))) {
if (document && !lastActiveFocus && activeElement && !autoFocus) {
activeElement.blur();
document.body.focus();
} else {
result = index$1.default(workingArea, lastActiveFocus);
lastPortaledElement = {};
}
}
focusWasOutsideWindow = false;
lastActiveFocus = document && document.activeElement;
}
}
if (document) {
var newActiveElement = document && document.activeElement;
var allNodes = focusMerge.getFocusabledIn(workingArea);
var focusedItem = allNodes.find(function (_ref) {
var node = _ref.node;
return node === newActiveElement;
});
if (focusedItem) {
// remove old focus
allNodes.filter(function (_ref2) {
var guard = _ref2.guard,
node = _ref2.node;
return guard && node.dataset.focusAutoGuard;
}).forEach(function (_ref3) {
var node = _ref3.node;
return node.removeAttribute('tabIndex');
});
var focusedIndex = allNodes.indexOf(focusedItem);
autoGuard(focusedIndex, allNodes.length, +1, allNodes);
autoGuard(focusedIndex, -1, -1, allNodes);
}
}
}
}
return result;
};
var onTrap = function onTrap(event) {
if (activateTrap() && event) {
// prevent scroll jump
event.stopPropagation();
event.preventDefault();
}
};
var onBlur = function onBlur() {
return util.deferAction(activateTrap);
};
var onFocus = function onFocus(event) {
// detect portal
var source = event.target;
var currentNode = event.currentTarget;
if (!currentNode.contains(source)) {
recordPortal(currentNode, source);
}
};
var FocusWatcher = function FocusWatcher() {
return null;
};
var FocusTrap = function FocusTrap(_ref4) {
var children = _ref4.children;
return React__default.createElement("div", {
onBlur: onBlur,
onFocus: onFocus
}, children);
};
FocusTrap.propTypes = process.env.NODE_ENV !== "production" ? {
children: index.default.node.isRequired
} : {};
var onWindowBlur = function onWindowBlur() {
focusWasOutsideWindow = true;
};
var attachHandler = function attachHandler() {
document.addEventListener('focusin', onTrap, true);
document.addEventListener('focusout', onBlur);
window.addEventListener('blur', onWindowBlur);
};
var detachHandler = function detachHandler() {
document.removeEventListener('focusin', onTrap, true);
document.removeEventListener('focusout', onBlur);
window.removeEventListener('blur', onWindowBlur);
};
function reducePropsToState(propsList) {
return propsList.filter(function (_ref5) {
var disabled = _ref5.disabled;
return !disabled;
});
}
function handleStateChangeOnClient(traps) {
var trap = traps.slice(-1)[0];
if (trap && !lastActiveTrap) {
attachHandler();
}
var lastTrap = lastActiveTrap;
var sameTrap = lastTrap && trap && trap.id === lastTrap.id;
lastActiveTrap = trap;
if (lastTrap && !sameTrap) {
lastTrap.onDeactivation(); // return focus only of last trap was removed
if (!traps.filter(function (_ref6) {
var id = _ref6.id;
return id === lastTrap.id;
}).length) {
// allow defer is no other trap is awaiting restore
lastTrap.returnFocus(!trap);
}
}
if (trap) {
lastActiveFocus = null;
if (!sameTrap || lastTrap.observed !== trap.observed) {
trap.onActivation();
}
activateTrap();
util.deferAction(activateTrap);
} else {
detachHandler();
lastActiveFocus = null;
}
} // bind medium
medium.mediumFocus.assignSyncMedium(onFocus);
medium.mediumBlur.assignMedium(onBlur);
medium.mediumEffect.assignMedium(function (cb) {
return cb({
moveFocusInside: index$1.default,
focusInside: focusInside.default
});
});
var FocusTrap$1 = index_es.default(reducePropsToState, handleStateChangeOnClient)(FocusWatcher);
exports.default = FocusTrap$1;