UNPKG

react-select

Version:

A Select control built with and for ReactJS

204 lines (170 loc) 5.48 kB
// ============================== // NO OP // ============================== var noop = function noop() {}; // 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, state, className) { var arr = [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 = function cleanValue(value) { if (Array.isArray(value)) return value.filter(Boolean); if (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 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, duration, callback) { if (duration === void 0) { duration = 200; } if (callback === void 0) { callback = 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) { window.requestAnimationFrame(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 }; } // 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; } } export { getScrollParent as a, getScrollTop as b, animatedScrollTo as c, isMobileDevice as d, cleanValue as e, scrollIntoView as f, getBoundingClientObj as g, classNames as h, isTouchCapable as i, isDocumentElement as j, handleInputChange as k, noop as n, scrollTo as s };