@d3plus/format 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @d3plus/format
2
+
3
+ JavaScript formatters for localized numbers and dates.
4
+
5
+ ## Installing
6
+
7
+ If using npm, `npm install @d3plus/format`. Otherwise, you can download the [latest release from GitHub](https://github.com/d3plus/d3plus/releases/latest) or load from a [CDN](https://cdn.jsdelivr.net/npm/@d3plus/format@3.0.0-alpha.0/+esm).
8
+
9
+ ```js
10
+ import modules from "@d3plus/format";
11
+ ```
12
+
13
+ In vanilla JavaScript, a `d3plus` global is exported from the pre-bundled version:
14
+
15
+ ```html
16
+ <script src="https://cdn.jsdelivr.net/npm/@d3plus/format@3.0.0-alpha.0"></script>
17
+ <script>
18
+ console.log(d3plus);
19
+ </script>
20
+ ```
21
+
22
+ ## Examples
23
+
24
+ Live examples can be found on [d3plus.org](https://d3plus.org/), which includes a collection of example visualizations using @d3plus/react.
25
+
26
+ ## API Reference
27
+
28
+ #####
29
+ * [format](#format) - An extension to d3's [format](https://github.com/d3/d3-format#api-reference) function that adds more string formatting types and localizations.
30
+
31
+ The new specifier strings added by d3plus-format are:
32
+ - `.3~a` - abbreviated decimal notation with a numeric suffix (ie. "k", "M", "B", etc). This is an alias of the `formatAbbreviate` function.
33
+ * [formatAbbreviate](#formatAbbreviate) - Formats a number to an appropriate number of decimal places and rounding, adding suffixes if applicable (ie. `1200000` to `"1.2M"`).
34
+ * [formatDate](#formatDate) - A default set of date formatters, which takes into account both the interval in between in each data point but also the start/end data points.
35
+ * [formatDefaultLocale](#formatDefaultLocale) - An extension to d3's [formatDefaultLocale](https://github.com/d3/d3-format#api-reference) function that allows setting the locale globally for formatters.
36
+
37
+ ---
38
+
39
+ <a name="format"></a>
40
+ #### d3plus.**format**(specifier) [<>](https://github.com/d3plus/d3plus/blob/main/packages/format/src/format.js#L4)
41
+
42
+ An extension to d3's [format](https://github.com/d3/d3-format#api-reference) function that adds more string formatting types and localizations.
43
+
44
+ The new specifier strings added by d3plus-format are:
45
+ - `.3~a` - abbreviated decimal notation with a numeric suffix (ie. "k", "M", "B", etc). This is an alias of the `formatAbbreviate` function.
46
+
47
+
48
+ This is a global function
49
+
50
+ ---
51
+
52
+ <a name="formatAbbreviate"></a>
53
+ #### d3plus.**formatAbbreviate**(n, locale) [<>](https://github.com/d3plus/d3plus/blob/main/packages/format/src/formatAbbreviate.js#L38)
54
+
55
+ Formats a number to an appropriate number of decimal places and rounding, adding suffixes if applicable (ie. `1200000` to `"1.2M"`).
56
+
57
+
58
+ This is a global function
59
+
60
+ ---
61
+
62
+ <a name="formatDate"></a>
63
+ #### d3plus.**formatDate**(d, dataArray, [formatter]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/format/src/formatDate.js#L4)
64
+
65
+ A default set of date formatters, which takes into account both the interval in between in each data point but also the start/end data points.
66
+
67
+
68
+ This is a global function
69
+
70
+ ---
71
+
72
+ <a name="formatDefaultLocale"></a>
73
+ #### d3plus.**formatDefaultLocale**(definition) [<>](https://github.com/d3plus/d3plus/blob/main/packages/format/src/formatDefaultLocale.js#L4)
74
+
75
+ An extension to d3's [formatDefaultLocale](https://github.com/d3/d3-format#api-reference) function that allows setting the locale globally for formatters.
76
+
77
+
78
+ This is a global function
79
+
80
+ ---
81
+
82
+
83
+ ###### <sub>Documentation generated on Thu, 13 Mar 2025 19:58:29 GMT</sub>
package/es/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default as format } from "./src/format.js";
2
+ export { default as formatDefaultLocale } from "./src/formatDefaultLocale.js";
3
+ export { default as formatAbbreviate } from "./src/formatAbbreviate.js";
4
+ export { default as formatDate } from "./src/formatDate.js";
@@ -0,0 +1,14 @@
1
+ import abbreviate from "./formatAbbreviate.js";
2
+ import { format } from "d3-format";
3
+ /**
4
+ @function format
5
+ @desc An extension to d3's [format](https://github.com/d3/d3-format#api-reference) function that adds more string formatting types and localizations.
6
+
7
+ The new specifier strings added by d3plus-format are:
8
+ - `.3~a` - abbreviated decimal notation with a numeric suffix (ie. "k", "M", "B", etc). This is an alias of the `formatAbbreviate` function.
9
+ @param {String} specifier The string specifier used by the format function.
10
+ @returns {Function}
11
+ */ export default function(specifier) {
12
+ if (specifier === ".3~a") return abbreviate;
13
+ return format(specifier);
14
+ };
@@ -0,0 +1,77 @@
1
+ function _type_of(obj) {
2
+ "@swc/helpers - typeof";
3
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
4
+ }
5
+ import { formatLocale } from "d3-format";
6
+ import { formatLocale as defaultLocale } from "@d3plus/locales";
7
+ var round = function(x, n) {
8
+ return parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);
9
+ };
10
+ /**
11
+ * @private
12
+ */ function formatSuffix(str, precision, suffixes) {
13
+ var i = 0;
14
+ var value = parseFloat(str.replace("−", "-"), 10);
15
+ if (value) {
16
+ if (value < 0) value *= -1;
17
+ i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
18
+ i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
19
+ }
20
+ var d = suffixes[8 + i / 3];
21
+ return {
22
+ number: round(d.scale(value), precision),
23
+ symbol: d.symbol
24
+ };
25
+ }
26
+ /**
27
+ * @private
28
+ */ function parseSuffixes(d, i) {
29
+ var k = Math.pow(10, Math.abs(8 - i) * 3);
30
+ return {
31
+ scale: i > 8 ? function(d) {
32
+ return d / k;
33
+ } : function(d) {
34
+ return d * k;
35
+ },
36
+ symbol: d
37
+ };
38
+ }
39
+ /**
40
+ @function formatAbbreviate
41
+ @desc Formats a number to an appropriate number of decimal places and rounding, adding suffixes if applicable (ie. `1200000` to `"1.2M"`).
42
+ @param {Number|String} n The number to be formatted.
43
+ @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.
44
+ @returns {String}
45
+ */ export default function(n) {
46
+ var locale = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "en-US", precision = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : undefined;
47
+ if (isFinite(n)) n *= 1;
48
+ else return "N/A";
49
+ var negative = n < 0;
50
+ 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);
51
+ var decimal = localeConfig.delimiters.decimal || ".", separator = localeConfig.separator || "", thousands = localeConfig.delimiters.thousands || ",";
52
+ var d3plusFormatLocale = formatLocale({
53
+ currency: localeConfig.currency || [
54
+ "$",
55
+ ""
56
+ ],
57
+ decimal: decimal,
58
+ grouping: localeConfig.grouping || [
59
+ 3
60
+ ],
61
+ thousands: thousands
62
+ });
63
+ var val;
64
+ if (precision) val = d3plusFormatLocale.format(precision)(n);
65
+ else if (n === 0) val = "0";
66
+ else if (length >= 3) {
67
+ var f = formatSuffix(d3plusFormatLocale.format(".3r")(n), 2, suffixes);
68
+ var num = parseFloat(f.number).toString().replace(".", decimal);
69
+ var char = f.symbol;
70
+ val = "".concat(num).concat(separator).concat(char);
71
+ } else if (length === 3) val = d3plusFormatLocale.format(",f")(n);
72
+ else if (n < 1 && n > -1) val = d3plusFormatLocale.format(".2g")(n);
73
+ else val = d3plusFormatLocale.format(".3g")(n);
74
+ return "".concat(negative && val.charAt(0) !== "−" ? "−" : "").concat(val).replace(/−/g, "-") // replace new d3 default minus sign (−) to hyphen-minus (-)
75
+ .replace(/(\.[0]*[1-9]*)[0]*$/g, "$1") // removes any trailing zeros
76
+ .replace(/\.[0]*$/g, ""); // removes any trailing decimal point
77
+ }
@@ -0,0 +1,108 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _iterable_to_array_limit(arr, i) {
10
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
11
+ if (_i == null) return;
12
+ var _arr = [];
13
+ var _n = true;
14
+ var _d = false;
15
+ var _s, _e;
16
+ try {
17
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
18
+ _arr.push(_s.value);
19
+ if (i && _arr.length === i) break;
20
+ }
21
+ } catch (err) {
22
+ _d = true;
23
+ _e = err;
24
+ } finally{
25
+ try {
26
+ if (!_n && _i["return"] != null) _i["return"]();
27
+ } finally{
28
+ if (_d) throw _e;
29
+ }
30
+ }
31
+ return _arr;
32
+ }
33
+ function _non_iterable_rest() {
34
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
35
+ }
36
+ function _sliced_to_array(arr, i) {
37
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
38
+ }
39
+ function _unsupported_iterable_to_array(o, minLen) {
40
+ if (!o) return;
41
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
42
+ var n = Object.prototype.toString.call(o).slice(8, -1);
43
+ if (n === "Object" && o.constructor) n = o.constructor.name;
44
+ if (n === "Map" || n === "Set") return Array.from(n);
45
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
+ }
47
+ import { timeYear, timeMonth, timeHour, timeMinute, timeSecond } from "d3-time";
48
+ import { timeFormat } from "d3-time-format";
49
+ /**
50
+ @function formatDate
51
+ @desc A default set of date formatters, which takes into account both the interval in between in each data point but also the start/end data points.
52
+ @param {Date} d The date string to be formatted.
53
+ @param {Array} dataArray The full array of ordered Date Objects.
54
+ @param {Function} [formatter = d3.timeFormat] An optional instance of d3.timeFormat to be used for localization.
55
+ @returns {String}
56
+ */ export default function(d, dataArray) {
57
+ var formatter = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : timeFormat;
58
+ var formatHour = formatter("%I %p"), formatMillisecond = formatter(".%L"), formatMinute = formatter("%I:%M"), formatMonth = formatter("%b"), formatMonthDay = formatter("%b %-d"), formatMonthDayYear = formatter("%b %-d, %Y"), formatMonthYear = formatter("%b %Y"), formatQuarter = formatter("Q%q"), formatQuarterYear = formatter("Q%q %Y"), formatSecond = formatter(":%S"), formatYear = formatter("%Y");
59
+ var labelIndex = dataArray.findIndex(function(a) {
60
+ return +a === +d;
61
+ });
62
+ var firstOrLast = labelIndex === 0 || labelIndex === dataArray.length - 1;
63
+ var smallArray = dataArray.length <= 5;
64
+ var _dataArray_reduce = _sliced_to_array(dataArray.reduce(function(arr, d, i) {
65
+ if (i) {
66
+ arr[0].push(d.getFullYear() - dataArray[i - 1].getFullYear());
67
+ arr[1].push(monthDiff(dataArray[i - 1], d));
68
+ arr[2].push(Math.round((d - dataArray[i - 1]) / (1000 * 60 * 60 * 24)));
69
+ arr[3].push(Math.round((d - dataArray[i - 1]) / (1000 * 60 * 60)));
70
+ }
71
+ return arr;
72
+ }, [
73
+ [],
74
+ [],
75
+ [],
76
+ []
77
+ ]), 4), yearlySteps = _dataArray_reduce[0], monthlySteps = _dataArray_reduce[1], dailySteps = _dataArray_reduce[2], hourlySteps = _dataArray_reduce[3];
78
+ return (yearlySteps.every(function(s) {
79
+ return s >= 1 && !(s % 1);
80
+ }) // Yearly Data
81
+ ? formatYear : monthlySteps.every(function(s) {
82
+ return s >= 3 && !(s % 3);
83
+ }) // Quarterly Data
84
+ ? +timeYear(d) === d || firstOrLast || smallArray ? formatQuarterYear : formatQuarter : monthlySteps.every(function(s) {
85
+ return s >= 1 && !(s % 1);
86
+ }) // Monthly Data
87
+ ? +timeYear(d) === d || firstOrLast || smallArray ? formatMonthYear : formatMonth : dailySteps.every(function(s) {
88
+ return s >= 1 && !(s % 1);
89
+ }) // Daily Data
90
+ ? +timeYear(d) === d || firstOrLast || smallArray ? formatMonthDayYear : formatMonthDay : hourlySteps.every(function(s) {
91
+ return s >= 1 && !(s % 1);
92
+ }) // Hourly Data
93
+ ? firstOrLast || smallArray ? formatMonthDayYear : +timeMonth(d) === d ? formatMonthDay : formatHour : timeSecond(d) < d ? formatMillisecond : timeMinute(d) < d ? formatSecond : timeHour(d) < d ? formatMinute : d)(d);
94
+ }
95
+ /**
96
+ @function monthDiff
97
+ @desc Returns the number of months between two Date objects
98
+ @param {*} d1
99
+ @param {*} d2
100
+ @returns {Number} the number of months between the two Date objects
101
+ @private
102
+ */ function monthDiff(d1, d2) {
103
+ var months;
104
+ months = (d2.getFullYear() - d1.getFullYear()) * 12;
105
+ months -= d1.getMonth();
106
+ months += d2.getMonth();
107
+ return months <= 0 ? 0 : months;
108
+ }
@@ -0,0 +1,12 @@
1
+ import format from "./format.js";
2
+ import { formatDefaultLocale } from "d3-format";
3
+ /**
4
+ @function formatDefaultLocale
5
+ @desc An extension to d3's [formatDefaultLocale](https://github.com/d3/d3-format#api-reference) function that allows setting the locale globally for formatters.
6
+ @param {Object} definition The localization definition.
7
+ @returns {Object}
8
+ */ export default function(definition) {
9
+ var locale = formatDefaultLocale(definition);
10
+ locale.format = format;
11
+ return locale;
12
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@d3plus/format",
3
+ "version": "3.0.0-alpha.0",
4
+ "description": "JavaScript formatters for localized numbers and dates.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": "./es/index.js",
8
+ "browser": "./umd/d3plus-format.full.js",
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "sideEffects": false,
13
+ "files": [
14
+ "umd",
15
+ "es"
16
+ ],
17
+ "homepage": "https://d3plus.org",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/d3plus/d3plus.git",
21
+ "directory": "packages/format"
22
+ },
23
+ "keywords": [
24
+ "format",
25
+ "d3",
26
+ "d3plus",
27
+ "data",
28
+ "visualization"
29
+ ],
30
+ "scripts": {
31
+ "build:esm": "node ../../scripts/build-esm.js",
32
+ "build:umd": "node ../../scripts/build-umd.js",
33
+ "dev": "node ../../scripts/dev.js",
34
+ "test": "eslint index.js src/**/*.js && eslint --global=it test && mocha 'test/**/*-test.js'"
35
+ },
36
+ "dependencies": {
37
+ "@d3plus/locales": "3.0.0-alpha.0",
38
+ "d3-format": "^3.1.0",
39
+ "d3-time": "^3.1.0",
40
+ "d3-time-format": "^4.1.0"
41
+ }
42
+ }