react-avatar
Version:
Universal React avatar component makes it possible to generate avatars based on user information.
142 lines (134 loc) • 4.54 kB
JavaScript
;
import retina from 'is-retina';
const IS_RETINA = retina();
export function fetch(url, successCb, errorCb) {
const request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
const data = JSON.parse(request.responseText);
successCb(data);
} else {
errorCb(request.status);
}
}
};
request.open('GET', url, true);
request.send();
}
export function fetchJSONP(url, successCb, errorCb) {
const callbackName = 'jsonp_cb_' + Math.round(100000 * Math.random());
const script = document.createElement('script');
script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
document.body.appendChild(script);
script.onerror = function () {
errorCb();
};
window[callbackName] = function (data) {
delete window[callbackName];
document.body.removeChild(script);
successCb(data);
};
}
// https://webaim.org/resources/contrastchecker/
export const defaultColors = ['#A62A21', '#7e3794', '#0B51C1', '#3A6024', '#A81563', '#B3003C'];
// https://regex101.com/r/YEsPER/1
// https://developer.mozilla.org/en-US/docs/Web/CSS/length
const reSize = /^([-+]?(?:\d+(?:\.\d+)?|\.\d+))([a-z]{2,4}|%)?$/;
// https://en.wikipedia.org/wiki/Linear_congruential_generator
function _stringAsciiPRNG(value, m) {
// Xn+1 = (a * Xn + c) % m
// 0 < a < m
// 0 <= c < m
// 0 <= X0 < m
const charCodes = [...value].map(letter => letter.charCodeAt(0));
const len = charCodes.length;
const a = len % (m - 1) + 1;
const c = charCodes.reduce((current, next) => current + next) % m;
let random = charCodes[0] % m;
for (let i = 0; i < len; i++) random = (a * random + c) % m;
return random;
}
export function getRandomColor(value) {
let colors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultColors;
// if no value is passed, always return transparent color otherwise
// a rerender would show a new color which would will
// give strange effects when an interface is loading
// and gets rerendered a few consequent times
if (!value) return 'transparent';
// value based random color index
// the reason we don't just use a random number is to make sure that
// a certain value will always get the same color assigned given
// a fixed set of colors
const colorIndex = _stringAsciiPRNG(value, colors.length);
return colors[colorIndex];
}
export function parseSize(size) {
size = '' + size;
const [, value = 0, unit = 'px'] = reSize.exec(size) || [];
return {
value: parseFloat(value),
str: value + unit,
unit
};
}
/**
* Calculate absolute size in pixels we want for the images
* that get requested from the various sources. They don't
* understand relative sizes like `em` or `vww`. We select
* a fixed size of 512px when we can't detect the true pixel size.
*/
export function getImageSize(size) {
size = parseSize(size);
if (isNaN(size.value))
// invalid size, use fallback
size = 512;else if (size.unit === 'px')
// px are good, use them
size = size.value;else if (size.value === 0)
// relative 0 === absolute 0
size = 0;else
// anything else is unknown, use fallback
size = 512;
if (IS_RETINA) size = size * 2;
return size;
}
export function defaultInitials(name, _ref) {
let {
maxInitials
} = _ref;
return name.split(/\s/).map(part => part.substring(0, 1).toUpperCase()).filter(v => !!v).slice(0, maxInitials).join('').toUpperCase();
}
/**
* Grouped timeouts reduce the amount of timeouts trigged
* by grouping multiple handlers into a single setTimeout call.
*
* This reduces accuracy of the timeout but will be less expensive
* when multiple avatar have been loaded into view.
*/
const timeoutGroups = {};
export function setGroupedTimeout(fn, ttl) {
if (timeoutGroups[ttl]) {
timeoutGroups[ttl].push(fn);
return;
}
const callbacks = timeoutGroups[ttl] = [fn];
setTimeout(() => {
delete timeoutGroups[ttl];
callbacks.forEach(cb => cb());
}, ttl);
}
export function getNullableText() {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
for (const arg of args) {
if (arg || arg === '') return arg;
if (arg === false || arg === null) return null;
}
return;
}
export function calculateBorderRadius(round) {
if (round === true) return '100%';
if (round === false) return;
return round;
}