Add side panels, task selection, graph animation, and project docs

- Foldable left panel (user profile) and right panel (task details)
- Clicking a task in the list or graph node selects it and shows details
- Both views (task list + graph) always mounted via absolute inset-0 for
  correct canvas dimensions; tabs toggle visibility with opacity
- Graph node selection animation: other nodes repel outward (charge -600),
  then selected node smoothly slides to center (500ms cubic ease-out),
  then charge restores to -120 and graph stabilizes
- Graph re-fits on tab switch and panel resize via ResizeObserver
- Fix UUID string IDs throughout (backend returns UUIDs, not integers)
- Add TaskDetailPanel, UserPanel components
- Add CLAUDE.md project documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alvis
2026-04-08 11:23:06 +00:00
parent 5c7edd4bbc
commit f1d51b8cc8
23998 changed files with 3242708 additions and 0 deletions

13
frontend/node_modules/d3-format/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2010-2026 Mike Bostock
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

12
frontend/node_modules/d3-format/README.md generated vendored Normal file
View File

@@ -0,0 +1,12 @@
# d3-format
<a href="https://d3js.org"><img src="https://github.com/d3/d3/raw/main/docs/public/logo.svg" width="256" height="256"></a>
This module formats numbers for human consumption, with a consistent output allowing comparison. Grouped digits, currencies, scientific notation…
## Resources
- [Documentation](https://d3js.org/d3-format)
- [Examples](https://observablehq.com/@d3/d3-format)
- [Releases](https://github.com/d3/d3-format/releases)
- [Getting help](https://d3js.org/community)

342
frontend/node_modules/d3-format/dist/d3-format.js generated vendored Normal file
View File

@@ -0,0 +1,342 @@
// https://d3js.org/d3-format/ v3.1.2 Copyright 2010-2026 Mike Bostock
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}));
})(this, (function (exports) { 'use strict';
function formatDecimal(x) {
return Math.abs(x = Math.round(x)) >= 1e21
? x.toLocaleString("en").replace(/,/g, "")
: x.toString(10);
}
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimalParts(1.23) returns ["123", 0].
function formatDecimalParts(x, p) {
if (!isFinite(x) || x === 0) return null; // NaN, ±Infinity, ±0
var i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e"), coefficient = x.slice(0, i);
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+x.slice(i + 1)
];
}
function exponent(x) {
return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
}
function formatGroup(grouping, thousands) {
return function(value, width) {
var i = value.length,
t = [],
j = 0,
g = grouping[0],
length = 0;
while (i > 0 && g > 0) {
if (length + g + 1 > width) g = Math.max(1, width - length);
t.push(value.substring(i -= g, i + g));
if ((length += g + 1) > width) break;
g = grouping[j = (j + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
}
function formatNumerals(numerals) {
return function(value) {
return value.replace(/[0-9]/g, function(i) {
return numerals[+i];
});
};
}
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
function formatSpecifier(specifier) {
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
var match;
return new FormatSpecifier({
fill: match[1],
align: match[2],
sign: match[3],
symbol: match[4],
zero: match[5],
width: match[6],
comma: match[7],
precision: match[8] && match[8].slice(1),
trim: match[9],
type: match[10]
});
}
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
function FormatSpecifier(specifier) {
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
this.align = specifier.align === undefined ? ">" : specifier.align + "";
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
this.zero = !!specifier.zero;
this.width = specifier.width === undefined ? undefined : +specifier.width;
this.comma = !!specifier.comma;
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
this.trim = !!specifier.trim;
this.type = specifier.type === undefined ? "" : specifier.type + "";
}
FormatSpecifier.prototype.toString = function() {
return this.fill
+ this.align
+ this.sign
+ this.symbol
+ (this.zero ? "0" : "")
+ (this.width === undefined ? "" : Math.max(1, this.width | 0))
+ (this.comma ? "," : "")
+ (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
+ (this.trim ? "~" : "")
+ this.type;
};
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
function formatTrim(s) {
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
switch (s[i]) {
case ".": i0 = i1 = i; break;
case "0": if (i0 === 0) i0 = i; i1 = i; break;
default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
}
}
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}
var prefixExponent;
function formatPrefixAuto(x, p) {
var d = formatDecimalParts(x, p);
if (!d) return prefixExponent = undefined, x.toPrecision(p);
var coefficient = d[0],
exponent = d[1],
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
n = coefficient.length;
return i === n ? coefficient
: i > n ? coefficient + new Array(i - n + 1).join("0")
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
: "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
}
function formatRounded(x, p) {
var d = formatDecimalParts(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1];
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
: coefficient + new Array(exponent - coefficient.length + 2).join("0");
}
var formatTypes = {
"%": (x, p) => (x * 100).toFixed(p),
"b": (x) => Math.round(x).toString(2),
"c": (x) => x + "",
"d": formatDecimal,
"e": (x, p) => x.toExponential(p),
"f": (x, p) => x.toFixed(p),
"g": (x, p) => x.toPrecision(p),
"o": (x) => Math.round(x).toString(8),
"p": (x, p) => formatRounded(x * 100, p),
"r": formatRounded,
"s": formatPrefixAuto,
"X": (x) => Math.round(x).toString(16).toUpperCase(),
"x": (x) => Math.round(x).toString(16)
};
function identity(x) {
return x;
}
var map = Array.prototype.map,
prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
function formatLocale(locale) {
var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
numerals = locale.numerals === undefined ? identity : formatNumerals(map.call(locale.numerals, String)),
percent = locale.percent === undefined ? "%" : locale.percent + "",
minus = locale.minus === undefined ? "" : locale.minus + "",
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
function newFormat(specifier, options) {
specifier = formatSpecifier(specifier);
var fill = specifier.fill,
align = specifier.align,
sign = specifier.sign,
symbol = specifier.symbol,
zero = specifier.zero,
width = specifier.width,
comma = specifier.comma,
precision = specifier.precision,
trim = specifier.trim,
type = specifier.type;
// The "n" type is an alias for ",g".
if (type === "n") comma = true, type = "g";
// The "" type, and any invalid type, is an alias for ".12~g".
else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
// If zero fill is specified, padding goes after sign and before digits.
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
// Compute the prefix and suffix.
// For SI-prefix, the suffix is lazily computed.
var prefix = (options && options.prefix !== undefined ? options.prefix : "") + (symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : ""),
suffix = (symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "") + (options && options.suffix !== undefined ? options.suffix : "");
// What format function should we use?
// Is this an integer type?
// Can this type generate exponential notation?
var formatType = formatTypes[type],
maybeSuffix = /[defgprs%]/.test(type);
// Set the default precision if not specified,
// or clamp the specified precision to the supported range.
// For significant precision, it must be in [1, 21].
// For fixed precision, it must be in [0, 20].
precision = precision === undefined ? 6
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
: Math.max(0, Math.min(20, precision));
function format(value) {
var valuePrefix = prefix,
valueSuffix = suffix,
i, n, c;
if (type === "c") {
valueSuffix = formatType(value) + valueSuffix;
value = "";
} else {
value = +value;
// Determine the sign. -0 is not less than 0, but 1 / -0 is!
var valueNegative = value < 0 || 1 / value < 0;
// Perform the initial formatting.
value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
// Trim insignificant zeros.
if (trim) value = formatTrim(value);
// If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;
// Compute the prefix and suffix.
valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
valueSuffix = (type === "s" && !isNaN(value) && prefixExponent !== undefined ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
// Break the formatted value into the integer “value” part that can be
// grouped, and fractional or exponential “suffix” part that is not.
if (maybeSuffix) {
i = -1, n = value.length;
while (++i < n) {
if (c = value.charCodeAt(i), 48 > c || c > 57) {
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
value = value.slice(0, i);
break;
}
}
}
}
// If the fill character is not "0", grouping is applied before padding.
if (comma && !zero) value = group(value, Infinity);
// Compute the padding.
var length = valuePrefix.length + value.length + valueSuffix.length,
padding = length < width ? new Array(width - length + 1).join(fill) : "";
// If the fill character is "0", grouping is applied after padding.
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
// Reconstruct the final output based on the desired alignment.
switch (align) {
case "<": value = valuePrefix + value + valueSuffix + padding; break;
case "=": value = valuePrefix + padding + value + valueSuffix; break;
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
default: value = padding + valuePrefix + value + valueSuffix; break;
}
return numerals(value);
}
format.toString = function() {
return specifier + "";
};
return format;
}
function formatPrefix(specifier, value) {
var e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
k = Math.pow(10, -e),
f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier), {suffix: prefixes[8 + e / 3]});
return function(value) {
return f(k * value);
};
}
return {
format: newFormat,
formatPrefix: formatPrefix
};
}
var locale;
exports.format = void 0;
exports.formatPrefix = void 0;
defaultLocale({
thousands: ",",
grouping: [3],
currency: ["$", ""]
});
function defaultLocale(definition) {
locale = formatLocale(definition);
exports.format = locale.format;
exports.formatPrefix = locale.formatPrefix;
return locale;
}
function precisionFixed(step) {
return Math.max(0, -exponent(Math.abs(step)));
}
function precisionPrefix(step, value) {
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
}
function precisionRound(step, max) {
step = Math.abs(step), max = Math.abs(max) - step;
return Math.max(0, exponent(max) - exponent(step)) + 1;
}
exports.FormatSpecifier = FormatSpecifier;
exports.formatDefaultLocale = defaultLocale;
exports.formatLocale = formatLocale;
exports.formatSpecifier = formatSpecifier;
exports.precisionFixed = precisionFixed;
exports.precisionPrefix = precisionPrefix;
exports.precisionRound = precisionRound;
}));

File diff suppressed because one or more lines are too long

7
frontend/node_modules/d3-format/locale/ar-001.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-AE.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062f\u002e\u0625\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-BH.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062f\u002e\u0628\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-DJ.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u200f\u0046\u0064\u006a ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

6
frontend/node_modules/d3-format/locale/ar-DZ.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": "\u002c",
"thousands": "\u002e",
"grouping": [3],
"currency": ["\u062f\u002e\u062c\u002e ", ""]
}

7
frontend/node_modules/d3-format/locale/ar-EG.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062c\u002e\u0645\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

6
frontend/node_modules/d3-format/locale/ar-EH.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": "\u002e",
"thousands": "\u002c",
"grouping": [3],
"currency": ["\u062f\u002e\u0645\u002e ", ""]
}

7
frontend/node_modules/d3-format/locale/ar-ER.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u004e\u0066\u006b ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-IL.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u20aa ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-IQ.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062f\u002e\u0639\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-JO.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062f\u002e\u0623\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-KM.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0641\u002e\u062c\u002e\u0642\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-KW.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062f\u002e\u0643\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-LB.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0644\u002e\u0644\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

6
frontend/node_modules/d3-format/locale/ar-LY.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": "\u002c",
"thousands": "\u002e",
"grouping": [3],
"currency": ["\u062f\u002e\u0644\u002e ", ""]
}

6
frontend/node_modules/d3-format/locale/ar-MA.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": "\u002c",
"thousands": "\u002e",
"grouping": [3],
"currency": ["\u062f\u002e\u0645\u002e ", ""]
}

7
frontend/node_modules/d3-format/locale/ar-MR.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0623\u002e\u0645\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-OM.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0631\u002e\u0639\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-PS.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u20aa ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-QA.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0631\u002e\u0642\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-SA.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0631\u002e\u0633\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-SD.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u062c\u002e\u0633\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-SO.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u200f\u0053 ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-SS.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u00a3 ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-SY.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0644\u002e\u0633\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

7
frontend/node_modules/d3-format/locale/ar-TD.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["\u200f\u0046\u0043\u0046\u0041 ", ""],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

6
frontend/node_modules/d3-format/locale/ar-TN.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": "\u002c",
"thousands": "\u002e",
"grouping": [3],
"currency": ["\u062f\u002e\u062a\u002e ", ""]
}

7
frontend/node_modules/d3-format/locale/ar-YE.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": "\u066b",
"thousands": "\u066c",
"grouping": [3],
"currency": ["", " \u0631\u002e\u0649\u002e"],
"numerals" : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
}

6
frontend/node_modules/d3-format/locale/ca-ES.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/cs-CZ.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0Kč"]
}

6
frontend/node_modules/d3-format/locale/da-DK.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", " kr"]
}

6
frontend/node_modules/d3-format/locale/de-CH.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "'",
"grouping": [3],
"currency": ["", "\u00a0CHF"]
}

6
frontend/node_modules/d3-format/locale/de-DE.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/en-CA.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["$", ""]
}

6
frontend/node_modules/d3-format/locale/en-GB.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["£", ""]
}

6
frontend/node_modules/d3-format/locale/en-IE.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["€", ""]
}

6
frontend/node_modules/d3-format/locale/en-IN.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3, 2, 2, 2, 2, 2, 2, 2, 2, 2],
"currency": ["₹", ""]
}

6
frontend/node_modules/d3-format/locale/en-US.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["$", ""]
}

7
frontend/node_modules/d3-format/locale/es-BO.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["Bs\u00a0", ""],
"percent": "\u202f%"
}

6
frontend/node_modules/d3-format/locale/es-ES.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/es-MX.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["$", ""]
}

6
frontend/node_modules/d3-format/locale/fi-FI.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/fr-CA.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "$"]
}

7
frontend/node_modules/d3-format/locale/fr-FR.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0€"],
"percent": "\u202f%"
}

6
frontend/node_modules/d3-format/locale/he-IL.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["₪", ""]
}

6
frontend/node_modules/d3-format/locale/hu-HU.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0Ft"]
}

6
frontend/node_modules/d3-format/locale/it-IT.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["€", ""]
}

6
frontend/node_modules/d3-format/locale/ja-JP.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["", "円"]
}

6
frontend/node_modules/d3-format/locale/ko-KR.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["₩", ""]
}

6
frontend/node_modules/d3-format/locale/mk-MK.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "\u00a0ден."]
}

6
frontend/node_modules/d3-format/locale/nl-NL.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["€\u00a0", ""]
}

6
frontend/node_modules/d3-format/locale/pl-PL.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "zł"]
}

6
frontend/node_modules/d3-format/locale/pt-BR.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["R$", ""]
}

6
frontend/node_modules/d3-format/locale/pt-PT.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/ru-RU.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0\u20bd"]
}

6
frontend/node_modules/d3-format/locale/sl-SI.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": ".",
"grouping": [3],
"currency": ["", "\u00a0€"]
}

6
frontend/node_modules/d3-format/locale/sv-SE.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", " kr"]
}

6
frontend/node_modules/d3-format/locale/uk-UA.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0₴."]
}

6
frontend/node_modules/d3-format/locale/zh-CN.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["¥", ""]
}

56
frontend/node_modules/d3-format/package.json generated vendored Normal file
View File

@@ -0,0 +1,56 @@
{
"name": "d3-format",
"version": "3.1.2",
"description": "Format numbers for human consumption.",
"homepage": "https://d3js.org/d3-format/",
"repository": {
"type": "git",
"url": "https://github.com/d3/d3-format.git"
},
"keywords": [
"d3",
"d3-module",
"format",
"localization"
],
"license": "ISC",
"author": {
"name": "Mike Bostock",
"url": "http://bost.ocks.org/mike"
},
"type": "module",
"files": [
"dist/**/*.js",
"src/**/*.js",
"locale/*.json"
],
"module": "src/index.js",
"main": "src/index.js",
"jsdelivr": "dist/d3-format.min.js",
"unpkg": "dist/d3-format.min.js",
"exports": {
".": {
"umd": "./dist/d3-format.min.js",
"default": "./src/index.js"
},
"./locale/*": "./locale/*.json"
},
"sideEffects": [
"./src/defaultLocale.js"
],
"devDependencies": {
"@rollup/plugin-terser": "^0.4.4",
"eslint": "^9.39.2",
"globals": "^17.0.0",
"rollup": "^4.55.1",
"vitest": "^4.0.17"
},
"scripts": {
"test": "vitest",
"lint": "eslint src test",
"prepublishOnly": "rm -rf dist && rollup -c"
},
"engines": {
"node": ">=12"
}
}

18
frontend/node_modules/d3-format/src/defaultLocale.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
import formatLocale from "./locale.js";
var locale;
export var format;
export var formatPrefix;
defaultLocale({
thousands: ",",
grouping: [3],
currency: ["$", ""]
});
export default function defaultLocale(definition) {
locale = formatLocale(definition);
format = locale.format;
formatPrefix = locale.formatPrefix;
return locale;
}

5
frontend/node_modules/d3-format/src/exponent.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import {formatDecimalParts} from "./formatDecimal.js";
export default function(x) {
return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
}

20
frontend/node_modules/d3-format/src/formatDecimal.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
export default function(x) {
return Math.abs(x = Math.round(x)) >= 1e21
? x.toLocaleString("en").replace(/,/g, "")
: x.toString(10);
}
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimalParts(1.23) returns ["123", 0].
export function formatDecimalParts(x, p) {
if (!isFinite(x) || x === 0) return null; // NaN, ±Infinity, ±0
var i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e"), coefficient = x.slice(0, i);
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+x.slice(i + 1)
];
}

18
frontend/node_modules/d3-format/src/formatGroup.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
export default function(grouping, thousands) {
return function(value, width) {
var i = value.length,
t = [],
j = 0,
g = grouping[0],
length = 0;
while (i > 0 && g > 0) {
if (length + g + 1 > width) g = Math.max(1, width - length);
t.push(value.substring(i -= g, i + g));
if ((length += g + 1) > width) break;
g = grouping[j = (j + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
}

View File

@@ -0,0 +1,7 @@
export default function(numerals) {
return function(value) {
return value.replace(/[0-9]/g, function(i) {
return numerals[+i];
});
};
}

View File

@@ -0,0 +1,16 @@
import {formatDecimalParts} from "./formatDecimal.js";
export var prefixExponent;
export default function(x, p) {
var d = formatDecimalParts(x, p);
if (!d) return prefixExponent = undefined, x.toPrecision(p);
var coefficient = d[0],
exponent = d[1],
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
n = coefficient.length;
return i === n ? coefficient
: i > n ? coefficient + new Array(i - n + 1).join("0")
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
: "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
}

11
frontend/node_modules/d3-format/src/formatRounded.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import {formatDecimalParts} from "./formatDecimal.js";
export default function(x, p) {
var d = formatDecimalParts(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1];
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
: coefficient + new Array(exponent - coefficient.length + 2).join("0");
}

47
frontend/node_modules/d3-format/src/formatSpecifier.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
export default function formatSpecifier(specifier) {
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
var match;
return new FormatSpecifier({
fill: match[1],
align: match[2],
sign: match[3],
symbol: match[4],
zero: match[5],
width: match[6],
comma: match[7],
precision: match[8] && match[8].slice(1),
trim: match[9],
type: match[10]
});
}
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
export function FormatSpecifier(specifier) {
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
this.align = specifier.align === undefined ? ">" : specifier.align + "";
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
this.zero = !!specifier.zero;
this.width = specifier.width === undefined ? undefined : +specifier.width;
this.comma = !!specifier.comma;
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
this.trim = !!specifier.trim;
this.type = specifier.type === undefined ? "" : specifier.type + "";
}
FormatSpecifier.prototype.toString = function() {
return this.fill
+ this.align
+ this.sign
+ this.symbol
+ (this.zero ? "0" : "")
+ (this.width === undefined ? "" : Math.max(1, this.width | 0))
+ (this.comma ? "," : "")
+ (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
+ (this.trim ? "~" : "")
+ this.type;
};

11
frontend/node_modules/d3-format/src/formatTrim.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
export default function(s) {
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
switch (s[i]) {
case ".": i0 = i1 = i; break;
case "0": if (i0 === 0) i0 = i; i1 = i; break;
default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
}
}
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}

19
frontend/node_modules/d3-format/src/formatTypes.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import formatDecimal from "./formatDecimal.js";
import formatPrefixAuto from "./formatPrefixAuto.js";
import formatRounded from "./formatRounded.js";
export default {
"%": (x, p) => (x * 100).toFixed(p),
"b": (x) => Math.round(x).toString(2),
"c": (x) => x + "",
"d": formatDecimal,
"e": (x, p) => x.toExponential(p),
"f": (x, p) => x.toFixed(p),
"g": (x, p) => x.toPrecision(p),
"o": (x) => Math.round(x).toString(8),
"p": (x, p) => formatRounded(x * 100, p),
"r": formatRounded,
"s": formatPrefixAuto,
"X": (x) => Math.round(x).toString(16).toUpperCase(),
"x": (x) => Math.round(x).toString(16)
};

3
frontend/node_modules/d3-format/src/identity.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export default function(x) {
return x;
}

6
frontend/node_modules/d3-format/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export {default as formatDefaultLocale, format, formatPrefix} from "./defaultLocale.js";
export {default as formatLocale} from "./locale.js";
export {default as formatSpecifier, FormatSpecifier} from "./formatSpecifier.js";
export {default as precisionFixed} from "./precisionFixed.js";
export {default as precisionPrefix} from "./precisionPrefix.js";
export {default as precisionRound} from "./precisionRound.js";

147
frontend/node_modules/d3-format/src/locale.js generated vendored Normal file
View File

@@ -0,0 +1,147 @@
import exponent from "./exponent.js";
import formatGroup from "./formatGroup.js";
import formatNumerals from "./formatNumerals.js";
import formatSpecifier from "./formatSpecifier.js";
import formatTrim from "./formatTrim.js";
import formatTypes from "./formatTypes.js";
import {prefixExponent} from "./formatPrefixAuto.js";
import identity from "./identity.js";
var map = Array.prototype.map,
prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
export default function(locale) {
var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
numerals = locale.numerals === undefined ? identity : formatNumerals(map.call(locale.numerals, String)),
percent = locale.percent === undefined ? "%" : locale.percent + "",
minus = locale.minus === undefined ? "" : locale.minus + "",
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
function newFormat(specifier, options) {
specifier = formatSpecifier(specifier);
var fill = specifier.fill,
align = specifier.align,
sign = specifier.sign,
symbol = specifier.symbol,
zero = specifier.zero,
width = specifier.width,
comma = specifier.comma,
precision = specifier.precision,
trim = specifier.trim,
type = specifier.type;
// The "n" type is an alias for ",g".
if (type === "n") comma = true, type = "g";
// The "" type, and any invalid type, is an alias for ".12~g".
else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
// If zero fill is specified, padding goes after sign and before digits.
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
// Compute the prefix and suffix.
// For SI-prefix, the suffix is lazily computed.
var prefix = (options && options.prefix !== undefined ? options.prefix : "") + (symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : ""),
suffix = (symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "") + (options && options.suffix !== undefined ? options.suffix : "");
// What format function should we use?
// Is this an integer type?
// Can this type generate exponential notation?
var formatType = formatTypes[type],
maybeSuffix = /[defgprs%]/.test(type);
// Set the default precision if not specified,
// or clamp the specified precision to the supported range.
// For significant precision, it must be in [1, 21].
// For fixed precision, it must be in [0, 20].
precision = precision === undefined ? 6
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
: Math.max(0, Math.min(20, precision));
function format(value) {
var valuePrefix = prefix,
valueSuffix = suffix,
i, n, c;
if (type === "c") {
valueSuffix = formatType(value) + valueSuffix;
value = "";
} else {
value = +value;
// Determine the sign. -0 is not less than 0, but 1 / -0 is!
var valueNegative = value < 0 || 1 / value < 0;
// Perform the initial formatting.
value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
// Trim insignificant zeros.
if (trim) value = formatTrim(value);
// If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;
// Compute the prefix and suffix.
valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
valueSuffix = (type === "s" && !isNaN(value) && prefixExponent !== undefined ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
// Break the formatted value into the integer “value” part that can be
// grouped, and fractional or exponential “suffix” part that is not.
if (maybeSuffix) {
i = -1, n = value.length;
while (++i < n) {
if (c = value.charCodeAt(i), 48 > c || c > 57) {
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
value = value.slice(0, i);
break;
}
}
}
}
// If the fill character is not "0", grouping is applied before padding.
if (comma && !zero) value = group(value, Infinity);
// Compute the padding.
var length = valuePrefix.length + value.length + valueSuffix.length,
padding = length < width ? new Array(width - length + 1).join(fill) : "";
// If the fill character is "0", grouping is applied after padding.
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
// Reconstruct the final output based on the desired alignment.
switch (align) {
case "<": value = valuePrefix + value + valueSuffix + padding; break;
case "=": value = valuePrefix + padding + value + valueSuffix; break;
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
default: value = padding + valuePrefix + value + valueSuffix; break;
}
return numerals(value);
}
format.toString = function() {
return specifier + "";
};
return format;
}
function formatPrefix(specifier, value) {
var e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
k = Math.pow(10, -e),
f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier), {suffix: prefixes[8 + e / 3]});
return function(value) {
return f(k * value);
};
}
return {
format: newFormat,
formatPrefix: formatPrefix
};
}

View File

@@ -0,0 +1,5 @@
import exponent from "./exponent.js";
export default function(step) {
return Math.max(0, -exponent(Math.abs(step)));
}

View File

@@ -0,0 +1,5 @@
import exponent from "./exponent.js";
export default function(step, value) {
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
}

View File

@@ -0,0 +1,6 @@
import exponent from "./exponent.js";
export default function(step, max) {
step = Math.abs(step), max = Math.abs(max) - step;
return Math.max(0, exponent(max) - exponent(step)) + 1;
}