@d3plus/format
Version:
JavaScript formatters for localized numbers and dates.
78 lines (77 loc) • 3.46 kB
JavaScript
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
}