UNPKG

react-select

Version:

A Select control built with and for ReactJS

265 lines (217 loc) 7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.cleanValue = exports.emptyString = exports.noop = undefined; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports.classNames = classNames; exports.handleInputChange = handleInputChange; exports.isDocumentElement = isDocumentElement; exports.normalizedHeight = normalizedHeight; exports.getScrollTop = getScrollTop; exports.scrollTo = scrollTo; exports.getScrollParent = getScrollParent; exports.animatedScrollTo = animatedScrollTo; exports.scrollIntoView = scrollIntoView; exports.getBoundingClientObj = getBoundingClientObj; exports.toKey = toKey; exports.isTouchCapable = isTouchCapable; exports.isMobileDevice = isMobileDevice; var _raf = require('raf'); var _raf2 = _interopRequireDefault(_raf); require('react'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // ============================== // NO OP // ============================== var noop = exports.noop = function noop() {}; var emptyString = exports.emptyString = function emptyString() { return ''; }; // ============================== // Class Name Prefixer // ============================== /** String representation of component state for styling with class names. Expects an array of strings OR a string/object pair: - className(['comp', 'comp-arg', 'comp-arg-2']) @returns 'react-select__comp react-select__comp-arg react-select__comp-arg-2' - className('comp', { some: true, state: false }) @returns 'react-select__comp react-select__comp--some' */ function applyPrefixToName(prefix, name) { if (!name) { return prefix; } else if (name[0] === '-') { return prefix + name; } else { return prefix + '__' + name; } } function classNames(prefix, cssKey, state, className) { var arr = [cssKey, className]; if (state && prefix) { for (var key in state) { if (state.hasOwnProperty(key) && state[key]) { arr.push('' + applyPrefixToName(prefix, key)); } } } return arr.filter(function (i) { return i; }).map(function (i) { return String(i).trim(); }).join(' '); } // ============================== // Clean Value // ============================== var cleanValue = exports.cleanValue = function cleanValue(value) { if (Array.isArray(value)) return value.filter(Boolean); if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value !== null) return [value]; return []; }; // ============================== // Handle Input Change // ============================== function handleInputChange(inputValue, actionMeta, onInputChange) { if (onInputChange) { var newValue = onInputChange(inputValue, actionMeta); if (typeof newValue === 'string') return newValue; } return inputValue; } // ============================== // Scroll Helpers // ============================== function isDocumentElement(el) { return [document.documentElement, document.body, window].indexOf(el) > -1; } // Normalized Scroll Top // ------------------------------ function normalizedHeight(el) { if (isDocumentElement(el)) { return window.innerHeight; } return el.clientHeight; } // Normalized scrollTo & scrollTop // ------------------------------ function getScrollTop(el) { if (isDocumentElement(el)) { return window.pageYOffset; } return el.scrollTop; } function scrollTo(el, top) { // with a scroll distance, we perform scroll on the element if (isDocumentElement(el)) { window.scrollTo(0, top); return; } el.scrollTop = top; } // Get Scroll Parent // ------------------------------ function getScrollParent(element) { var style = getComputedStyle(element); var excludeStaticParent = style.position === 'absolute'; var overflowRx = /(auto|scroll)/; var docEl = document.documentElement; // suck it, flow... if (style.position === 'fixed') return docEl; for (var parent = element; parent = parent.parentElement;) { style = getComputedStyle(parent); if (excludeStaticParent && style.position === 'static') { continue; } if (overflowRx.test(style.overflow + style.overflowY + style.overflowX)) { return parent; } } return docEl; } // Animated Scroll To // ------------------------------ /** @param t: time (elapsed) @param b: initial value @param c: amount of change @param d: duration */ function easeOutCubic(t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; } function animatedScrollTo(element, to) { var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 200; var callback = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : noop; var start = getScrollTop(element); var change = to - start; var increment = 10; var currentTime = 0; function animateScroll() { currentTime += increment; var val = easeOutCubic(currentTime, start, change, duration); scrollTo(element, val); if (currentTime < duration) { (0, _raf2.default)(animateScroll); } else { callback(element); } } animateScroll(); } // Scroll Into View // ------------------------------ function scrollIntoView(menuEl, focusedEl) { var menuRect = menuEl.getBoundingClientRect(); var focusedRect = focusedEl.getBoundingClientRect(); var overScroll = focusedEl.offsetHeight / 3; if (focusedRect.bottom + overScroll > menuRect.bottom) { scrollTo(menuEl, Math.min(focusedEl.offsetTop + focusedEl.clientHeight - menuEl.offsetHeight + overScroll, menuEl.scrollHeight)); } else if (focusedRect.top - overScroll < menuRect.top) { scrollTo(menuEl, Math.max(focusedEl.offsetTop - overScroll, 0)); } } // ============================== // Get bounding client object // ============================== // cannot get keys using array notation with DOMRect function getBoundingClientObj(element) { var rect = element.getBoundingClientRect(); return { bottom: rect.bottom, height: rect.height, left: rect.left, right: rect.right, top: rect.top, width: rect.width }; } // ============================== // String to Key (kebabify) // ============================== function toKey(str) { return str.replace(/\W/g, '-'); } // ============================== // Touch Capability Detector // ============================== function isTouchCapable() { try { document.createEvent('TouchEvent'); return true; } catch (e) { return false; } } // ============================== // Mobile Device Detector // ============================== function isMobileDevice() { try { return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ); } catch (e) { return false; } }