react-select
Version:
A Select control built with and for ReactJS
265 lines (217 loc) • 7 kB
JavaScript
;
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;
}
}