UNPKG

@d3plus/format

Version:

JavaScript formatters for localized numbers and dates.

78 lines (77 loc) 3.46 kB
function _type_of(obj) { "@swc/helpers - typeof"; return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; } import { formatLocale } from "d3-format"; import { formatLocale as defaultLocale } from "@d3plus/locales"; var round = function(x, n) { return parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n); }; /** * @private */ function formatSuffix(str, precision, suffixes) { var i = 0; var value = parseFloat(str.replace("−", "-"), 10); if (value) { if (value < 0) value *= -1; i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); } var d = suffixes[8 + i / 3]; return { number: round(d.scale(value), precision), symbol: d.symbol }; } /** * @private */ function parseSuffixes(d, i) { var k = Math.pow(10, Math.abs(8 - i) * 3); return { scale: i > 8 ? function(d) { return d / k; } : function(d) { return d * k; }, symbol: d }; } /** @function formatAbbreviate @desc Formats a number to an appropriate number of decimal places and rounding, adding suffixes if applicable (ie. `1200000` to `"1.2M"`). @param {Number|String} n The number to be formatted. @param {Object|String} locale The locale config to be used. If *value* is an object, the function will format the numbers according the object. The object must include `suffixes`, `delimiter` and `currency` properties. @returns {String} */ export default function(n) { var locale = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "en-US", precision = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : undefined; if (isFinite(n)) n *= 1; else return "N/A"; var negative = n < 0; var length = n.toString().split(".")[0].replace("-", "").length, localeConfig = (typeof locale === "undefined" ? "undefined" : _type_of(locale)) === "object" ? locale : defaultLocale[locale] || defaultLocale["en-US"], suffixes = localeConfig.suffixes.map(parseSuffixes); var decimal = localeConfig.delimiters.decimal || ".", separator = localeConfig.separator || "", thousands = localeConfig.delimiters.thousands || ","; var d3plusFormatLocale = formatLocale({ currency: localeConfig.currency || [ "$", "" ], decimal: decimal, grouping: localeConfig.grouping || [ 3 ], thousands: thousands }); var val; if (precision) val = d3plusFormatLocale.format(precision)(n); else if (n === 0) val = "0"; else if (length >= 3) { var f = formatSuffix(d3plusFormatLocale.format(".3r")(n), 2, suffixes); var num = parseFloat(f.number).toString().replace(".", decimal); var char = f.symbol; val = "".concat(num).concat(separator).concat(char); } else if (length === 3) val = d3plusFormatLocale.format(",f")(n); else if (n < 1 && n > -1) val = d3plusFormatLocale.format(".2g")(n); else val = d3plusFormatLocale.format(".3g")(n); return "".concat(negative && val.charAt(0) !== "−" ? "−" : "").concat(val).replace(/−/g, "-") // replace new d3 default minus sign (−) to hyphen-minus (-) .replace(/(\.[0]*[1-9]*)[0]*$/g, "$1") // removes any trailing zeros .replace(/\.[0]*$/g, ""); // removes any trailing decimal point }