@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 +83 -0
- package/es/index.js +4 -0
- package/es/src/format.js +14 -0
- package/es/src/formatAbbreviate.js +77 -0
- package/es/src/formatDate.js +108 -0
- package/es/src/formatDefaultLocale.js +12 -0
- package/package.json +42 -0
- package/umd/d3plus-format.full.js +1745 -0
- package/umd/d3plus-format.full.js.map +1 -0
- package/umd/d3plus-format.full.min.js +126 -0
- package/umd/d3plus-format.js +260 -0
- package/umd/d3plus-format.js.map +1 -0
- package/umd/d3plus-format.min.js +53 -0
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
package/es/src/format.js
ADDED
|
@@ -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
|
+
}
|