UNPKG

dash-core-components

Version:

Core component suite for Dash

153 lines (146 loc) 6.94 kB
"use strict"; 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;