UNPKG

grommet

Version:

The most advanced UX framework for enterprise applications.

211 lines (184 loc) 6.21 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); exports.findScrollParents = findScrollParents; exports.isDescendant = isDescendant; exports.findAncestor = findAncestor; exports.filterByFocusable = filterByFocusable; exports.getBestFirstFocusable = getBestFirstFocusable; exports.isFormElement = isFormElement; exports.generateId = generateId; exports.generateUUID = generateUUID; exports.checkDarkBackground = checkDarkBackground; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP var COLOR_RGB_REGEXP = /rgb\((\d+), (\d+), (\d+)\)/; var COLOR_RGBA_REGEXP = /rgba\((\d+), (\d+), (\d+), ([\d\.]+)\)/; var LIGHT_HINT_REGEXP = /^light/; function hash(input) { var hash = 0, i, chr, len; if (input.length === 0) return hash; for (i = 0, len = input.length; i < len; i++) { chr = input.charCodeAt(i); hash = (hash << 5) - hash + chr; hash = hash & hash; // Convert to 32bit integer } return hash; }; function findScrollParents(element, horizontal) { var result = []; var parent = element.parentNode; while (parent && parent.getBoundingClientRect) { var rect = parent.getBoundingClientRect(); // 10px is to account for borders and scrollbars in a lazy way if (horizontal) { if (rect.width && parent.scrollWidth > rect.width + 10) { result.push(parent); } } else { if (rect.height && parent.scrollHeight > rect.height + 10) { result.push(parent); } } parent = parent.parentNode; } if (result.length === 0) { result.push(document); } return result; } function isDescendant(parent, child) { var node = child.parentNode; while (node != null) { if (node == parent) { return true; } node = node.parentNode; } return false; } function findAncestor(element, className) { var node = element.parentNode; while (node != null) { if (node.classList && node.classList.contains(className)) { break; } node = node.parentNode; } return node; } function filterByFocusable(elements) { return Array.prototype.filter.call(elements || [], function (element) { var currentTag = element.tagName.toLowerCase(); var validTags = /(svg|a|area|input|select|textarea|button|iframe|div)$/; var isValidTag = currentTag.match(validTags) && element.focus; if (currentTag === 'a') { return isValidTag && element.childNodes.length > 0 && element.getAttribute('href'); } else if (currentTag === 'svg' || currentTag === 'div') { return isValidTag && element.hasAttribute('tabindex'); } return isValidTag; }); } function getBestFirstFocusable(elements) { var bestFirstFocusable; Array.prototype.some.call(elements || [], function (element) { var currentTag = element.tagName.toLowerCase(); var isValidTag = currentTag.match(/(input|select|textarea)$/); return isValidTag ? (bestFirstFocusable = element, true) : false; }); if (!bestFirstFocusable) { bestFirstFocusable = this.filterByFocusable(elements)[0]; } return bestFirstFocusable; } function isFormElement(element) { var elementType = element ? element.tagName.toLowerCase() : undefined; return elementType && (elementType === 'input' || elementType === 'textarea'); } function generateId(element) { if (element) { var id = void 0; var elementId = element.getAttribute('id'); if (!elementId) { // IE11 fix: check for parentNode instead of parentElement var parentElement = element.parentElement || element.parentNode; if (parentElement) { id = hash(parentElement.innerHTML); element.setAttribute('id', id); } } else { id = elementId; } return id; } } function generateUUID() { function S4() { return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1); } var uuid = '' + S4() + S4() + ('-' + S4() + '-4' + S4().substr(0, 3)) + ('-' + S4() + '-' + S4() + S4() + S4()).toLowerCase(); return uuid; } var CHECK_DARK_BACKGROUND_BACKOFFS = [0, 20, 80, 200]; function hasDarkBackground(element) { var result = false; var color = window.getComputedStyle(element).backgroundColor; var match = color.match(COLOR_RGB_REGEXP) || color.match(COLOR_RGBA_REGEXP); if (match) { var _match$slice$map = match.slice(1).map(function (n) { return parseInt(n, 10); }), _match$slice$map2 = (0, _slicedToArray3.default)(_match$slice$map, 3), red = _match$slice$map2[0], green = _match$slice$map2[1], blue = _match$slice$map2[2]; // http://www.had2know.com/technology/ // color-contrast-calculator-web-design.html var brightness = (299 * red + 587 * green + 114 * blue) / 1000; if (0 === brightness) { // Browsers return 0,0,0 when they don't know yet. result = undefined; } else if (brightness < 125) { result = true; } } return result; } function checkDarkBackgroundBackoff(element, handler, backoffDurations) { return setTimeout(function () { var dark = hasDarkBackground(element); if (undefined === dark && backoffDurations.length > 0) { checkDarkBackgroundBackoff(element, handler, backoffDurations); } else { handler(dark); } }, backoffDurations.shift()); } function checkDarkBackground(colorIndex, element, handler) { var timer = void 0; if (colorIndex) { if ('dark' === colorIndex) { // caller knows handler(true); } else if (LIGHT_HINT_REGEXP.test(colorIndex)) { // skip if this is a 'light-*' color index handler(false); } else { // Measure the actual background color brightness to determine whether // to set a dark or light context. if (element && window.getComputedStyle) { timer = checkDarkBackgroundBackoff(element, handler, CHECK_DARK_BACKGROUND_BACKOFFS); } } } return { stop: function stop() { return clearTimeout(timer); } }; }