dash-core-components
Version:
Core component suite for Dash
153 lines (146 loc) • 6.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.setUndefined = exports.sanitizeMarks = exports.calcValue = exports.calcStep = exports.autoGenerateMarks = exports.applyD3Format = void 0;
var _ramda = require("ramda");
var _d3Format = require("d3-format");
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
/**
* Truncate marks if they are out of Slider interval
*/
var truncateMarks = (min, max, marks) => (0, _ramda.pickBy)((k, mark) => mark >= min && mark <= max, marks);
var truncateNumber = num => parseInt(num.toString().match(/^-?\d+(?:\.\d{0,0})?/)[0], 10);
var decimalCount = d => String(d).split('.').length > 1 ? String(d).split('.')[1].length : 0;
var alignIntValue = (v, d) => d < 10 ? v : parseInt((truncateNumber(v / d) * d).toFixed(decimalCount(d)), 10);
var alignDecimalValue = (v, d) => d < 10 ? parseFloat(v.toFixed(decimalCount(d))) : parseFloat(((v / d).toFixed(0) * d).toFixed(decimalCount(d)));
var alignValue = (v, d) => decimalCount(d) < 1 ? alignIntValue(v, d) : alignDecimalValue(v, d);
var log = v => Math.floor(Math.log10(v));
var getNearByStep = v => v < 10 ? [v] : [Math.pow(10, Math.floor(Math.log10(v))), Math.pow(10, Math.ceil(Math.log10(v))) / 2, alignValue(v, Math.pow(10, log(v))), Math.pow(10, Math.ceil(Math.log10(v)))].sort((a, b) => Math.abs(a - v) - Math.abs(b - v));
var estimateBestSteps = (minValue, maxValue, stepValue) => {
var desiredCountMin = 2 + (maxValue / stepValue <= 10 ? 3 : 3); // including start, end
var desiredCountMax = 2 + (maxValue / stepValue <= 10 ? 4 : 6);
var min = minValue / stepValue;
var max = maxValue / stepValue;
var rangeLength = max - min;
var leastMarksInterval = Math.max(Math.round(rangeLength / (desiredCountMin - 1)), 1);
var possibleValues = getNearByStep(leastMarksInterval);
var finalStep = possibleValues.find(step => {
var expectedSteps = Math.ceil(rangeLength / step) + 1;
return expectedSteps >= desiredCountMin - 1 && expectedSteps <= desiredCountMax + 1;
}) || possibleValues[0];
return [alignValue(min, finalStep) * stepValue, alignValue(finalStep * stepValue, stepValue), stepValue];
};
/**
* Calculate default step if not defined
*/
var calcStep = (min, max, step) => {
if (step) {
return step;
}
var diff = max > min ? max - min : min - max;
var v = (Math.abs(diff) + Number.EPSILON) / 100;
var N = Math.floor(Math.log10(v));
return [Number(Math.pow(10, N)), 2 * Math.pow(10, N), 5 * Math.pow(10, N)].sort((a, b) => Math.abs(a - v) - Math.abs(b - v))[0];
};
/**
* Set min and max if they are undefined and marks are defined
*/
exports.calcStep = calcStep;
var setUndefined = (min, max, marks) => {
var definedMarks = {
min_mark: min,
max_mark: max
};
if ((0, _ramda.isNil)(marks)) {
return definedMarks;
}
var marksObject = Object.keys(marks).map(Number);
if ((0, _ramda.isNil)(min)) {
definedMarks.min_mark = Math.min(...marksObject);
}
if ((0, _ramda.isNil)(max)) {
definedMarks.max_mark = Math.max(...marksObject);
}
return definedMarks;
};
exports.setUndefined = setUndefined;
var applyD3Format = (mark, min, max) => {
var mu_ten_factor = -3;
var k_ten_factor = 3;
var ten_factor = Math.log10(Math.abs(mark));
if (mark === 0 || ten_factor > mu_ten_factor && ten_factor < k_ten_factor) {
return String(mark);
}
var max_min_mean = (Math.abs(max) + Math.abs(min)) / 2;
var si_formatter = (0, _d3Format.formatPrefix)(',.0', max_min_mean);
return String(si_formatter(mark));
};
exports.applyD3Format = applyD3Format;
var autoGenerateMarks = (min, max, step) => {
var marks = [];
var _ref = step ? [min, step, step] : estimateBestSteps(min, max, calcStep(min, max, step)),
_ref2 = _slicedToArray(_ref, 3),
start = _ref2[0],
interval = _ref2[1],
chosenStep = _ref2[2];
var cursor = start + interval;
// make sure we don't step into infinite loop
if ((max - cursor) / interval > 0) {
do {
marks.push(alignValue(cursor, chosenStep));
cursor += interval;
} while (cursor < max);
// do some cosmetic
var discardThreshold = 1.5;
if (marks.length >= 2 && max - marks[marks.length - 2] <= interval * discardThreshold) {
marks.pop();
}
}
var marksObject = {};
marks.forEach(mark => {
marksObject[mark] = applyD3Format(mark, min, max);
});
marksObject[min] = applyD3Format(min, min, max);
marksObject[max] = applyD3Format(max, min, max);
return marksObject;
};
/**
* - Auto generate marks if not given,
* - Not generate anything at all when explicit null is given to marks
* - Then truncate marks so no out of range marks
*/
exports.autoGenerateMarks = autoGenerateMarks;
var sanitizeMarks = _ref3 => {
var min = _ref3.min,
max = _ref3.max,
marks = _ref3.marks,
step = _ref3.step;
if (marks === null) {
return undefined;
}
var _setUndefined = setUndefined(min, max, marks),
min_mark = _setUndefined.min_mark,
max_mark = _setUndefined.max_mark;
var truncated_marks = marks && (0, _ramda.isEmpty)(marks) === false ? truncateMarks(min_mark, max_mark, marks) : marks;
if (truncated_marks && (0, _ramda.isEmpty)(truncated_marks) === false) {
return truncated_marks;
}
return autoGenerateMarks(min_mark, max_mark, step);
};
/**
* Calculate default value if not defined
*/
exports.sanitizeMarks = sanitizeMarks;
var calcValue = (min, max, value) => {
if (value !== undefined) {
return value;
}
return [min, max];
};
exports.calcValue = calcValue;