UNPKG

tweak-tools

Version:

Tweak your React projects until awesomeness

105 lines (104 loc) 4.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.evaluate = exports.getUid = exports.invertedRange = exports.range = exports.getStep = exports.parseNumber = exports.ceil = exports.pad = exports.clamp = void 0; const clamp = (x, min, max) => (x > max ? max : x < min ? min : x); exports.clamp = clamp; const pad = (x, pad) => String(x).padStart(pad, '0'); exports.pad = pad; const ceil = (v) => Math.sign(v) * Math.ceil(Math.abs(v)); exports.ceil = ceil; const parseNumber = (v) => { if (v === '' || typeof v === 'number') return v; try { const _v = evaluate(v); if (!isNaN(_v)) return _v; } catch (_a) { } return parseFloat(v); }; exports.parseNumber = parseNumber; const log10 = Math.log(10); function getStep(number) { let n = Math.abs(+String(number).replace('.', '')); //remove decimal and make positive if (n === 0) return 0.01; while (n !== 0 && n % 10 === 0) n /= 10; //kill the 0s at the end of n const significantDigits = Math.floor(Math.log(n) / log10) + 1; const numberLog = Math.floor(Math.log10(Math.abs(number))); const step = Math.pow(10, numberLog - significantDigits); return Math.max(step, 0.001); } exports.getStep = getStep; const range = (v, min, max) => { if (max === min) return 0; const _v = (0, exports.clamp)(v, min, max); return (_v - min) / (max - min); }; exports.range = range; const invertedRange = (p, min, max) => p * (max - min) + min; exports.invertedRange = invertedRange; // from https://gist.github.com/gordonbrander/2230317 const getUid = () => '_' + Math.random().toString(36).substr(2, 9); exports.getUid = getUid; const parens = /\(([0-9+\-*/^ .]+)\)/; // Regex for identifying parenthetical expressions const exp = /(\d+(?:\.\d+)?) ?\^ ?(\d+(?:\.\d+)?)/; // Regex for identifying exponentials (x ^ y) const mul = /(\d+(?:\.\d+)?) ?\* ?(\d+(?:\.\d+)?)/; // Regex for identifying multiplication (x * y) const div = /(\d+(?:\.\d+)?) ?\/ ?(\d+(?:\.\d+)?)/; // Regex for identifying division (x / y) const add = /(\d+(?:\.\d+)?) ?\+ ?(\d+(?:\.\d+)?)/; // Regex for identifying addition (x + y) const sub = /(\d+(?:\.\d+)?) ?- ?(\d+(?:\.\d+)?)/; // Regex for identifying subtraction (x - y) /** * Copyright: copied from here: https://stackoverflow.com/a/63105543 * by @aanrudolph2 https://github.com/aanrudolph2 * * Evaluates a numerical expression as a string and returns a Number * Follows standard PEMDAS operation ordering * @param {String} expr Numerical expression input * @returns {Number} Result of expression */ function evaluate(expr) { if (isNaN(Number(expr))) { if (parens.test(expr)) { const newExpr = expr.replace(parens, (match, subExpr) => String(evaluate(subExpr))); return evaluate(newExpr); } else if (exp.test(expr)) { const newExpr = expr.replace(exp, (match, base, pow) => String(Math.pow(Number(base), Number(pow)))); return evaluate(newExpr); } else if (mul.test(expr)) { const newExpr = expr.replace(mul, (match, a, b) => String(Number(a) * Number(b))); return evaluate(newExpr); } else if (div.test(expr)) { const newExpr = expr.replace(div, (match, a, b) => { // b can equal either 0 or "0" this is on purpose // eslint-disable-next-line eqeqeq if (b != 0) return String(Number(a) / Number(b)); else throw new Error('Division by zero'); }); return evaluate(newExpr); } else if (add.test(expr)) { const newExpr = expr.replace(add, (match, a, b) => String(Number(a) + Number(b))); return evaluate(newExpr); } else if (sub.test(expr)) { const newExpr = expr.replace(sub, (match, a, b) => String(Number(a) - Number(b))); return evaluate(newExpr); } else { return Number(expr); } } return Number(expr); } exports.evaluate = evaluate; // Example usage //console.log(evaluate("2 + 4*(30/5) - 34 + 45/2"));