Put SquiggleChart into playground

This commit is contained in:
Sam Nolan 2022-02-15 17:27:23 +11:00
parent 7c8e76173b
commit fa116227cf
27 changed files with 2396 additions and 1888 deletions

1
packages/components/dist/lib.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export { SquiggleChart } from './stories/SquiggleChart';

13
packages/components/dist/lib.js vendored Normal file
View File

@ -0,0 +1,13 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
exports.__esModule = true;
exports.SquiggleChart = void 0;
var SquiggleChart_1 = require("./stories/SquiggleChart");
__createBinding(exports, SquiggleChart_1, "SquiggleChart");
//# sourceMappingURL=lib.js.map

1
packages/components/dist/lib.js.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,yDAAuD;AAA9C,2DAAa"}

View File

@ -0,0 +1,25 @@
import * as PropTypes from 'prop-types';
export declare const SquiggleChart: {
({ squiggleString }: {
squiggleString: string;
}): JSX.Element;
propTypes: {
squiggleString: PropTypes.Requireable<string>;
};
defaultProps: {
squggleString: string;
};
};
export declare function numberShow(number: number, precision?: number): {
value: string;
power?: undefined;
symbol?: undefined;
} | {
value: string;
power: number;
symbol?: undefined;
} | {
value: string;
symbol: string;
power?: undefined;
};

View File

@ -0,0 +1,302 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
exports.__esModule = true;
exports.numberShow = exports.SquiggleChart = void 0;
var React = require("react");
var PropTypes = require("prop-types");
var _ = require("lodash");
var squiggle_lang_1 = require("@squiggle/squiggle-lang");
var react_vega_1 = require("react-vega");
var chartSpecification = require("./spec-distributions.json");
var percentilesSpec = require("./spec-pertentiles.json");
var SquiggleVegaChart = (0, react_vega_1.createClassFromSpec)({ 'spec': chartSpecification });
var SquigglePercentilesChart = (0, react_vega_1.createClassFromSpec)({ 'spec': percentilesSpec });
var SquiggleChart = function (_a) {
var squiggleString = _a.squiggleString;
var result = (0, squiggle_lang_1.run)(squiggleString);
console.log(result);
if (result.tag === "Ok") {
var chartResults = result.value.map(function (chartResult) {
console.log(chartResult);
if (chartResult["NAME"] === "Float") {
return React.createElement(MakeNumberShower, { precision: 3, number: chartResult["VAL"] });
}
else if (chartResult["NAME"] === "DistPlus") {
var shape = chartResult.VAL.shape;
if (shape.tag === "Continuous") {
var xyShape = shape.value.xyShape;
var totalY_1 = xyShape.ys.reduce(function (a, b) { return a + b; });
var total_1 = 0;
var cdf = xyShape.ys.map(function (y) {
total_1 += y;
return total_1 / totalY_1;
});
var values = _.zip(cdf, xyShape.xs, xyShape.ys).map(function (_a) {
var c = _a[0], x = _a[1], y = _a[2];
return ({ cdf: (c * 100).toFixed(2) + "%", x: x, y: y });
});
return (React.createElement(SquiggleVegaChart, { data: { "con": values } }));
}
else if (shape.tag === "Discrete") {
var xyShape = shape.value.xyShape;
var totalY_2 = xyShape.ys.reduce(function (a, b) { return a + b; });
var total_2 = 0;
var cdf = xyShape.ys.map(function (y) {
total_2 += y;
return total_2 / totalY_2;
});
var values = _.zip(cdf, xyShape.xs, xyShape.ys).map(function (_a) {
var c = _a[0], x = _a[1], y = _a[2];
return ({ cdf: (c * 100).toFixed(2) + "%", x: x, y: y });
});
return (React.createElement(SquiggleVegaChart, { data: { "dis": values } }));
}
else if (shape.tag === "Mixed") {
var discreteShape = shape.value.discrete.xyShape;
var totalDiscrete = discreteShape.ys.reduce(function (a, b) { return a + b; });
var discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
var continuousShape = shape.value.continuous.xyShape;
var continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
;
var markedDisPoints = discretePoints.map(function (_a) {
var x = _a[0], y = _a[1];
return ({ x: x, y: y, type: "discrete" });
});
var markedConPoints = continuousPoints.map(function (_a) {
var x = _a[0], y = _a[1];
return ({ x: x, y: y, type: "continuous" });
});
var sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), 'x');
var totalContinuous_1 = 1 - totalDiscrete;
var totalY_3 = continuousShape.ys.reduce(function (a, b) { return a + b; });
var total_3 = 0;
var cdf = sortedPoints.map(function (point) {
if (point.type == "discrete") {
total_3 += point.y;
return total_3;
}
else if (point.type == "continuous") {
total_3 += point.y / totalY_3 * totalContinuous_1;
return total_3;
}
});
var cdfLabeledPoint = _.zipWith(cdf, sortedPoints, function (c, point) { return (__assign(__assign({}, point), { cdf: (c * 100).toFixed(2) + "%" })); });
var continuousValues = cdfLabeledPoint.filter(function (x) { return x.type == "continuous"; });
var discreteValues = cdfLabeledPoint.filter(function (x) { return x.type == "discrete"; });
return (React.createElement(SquiggleVegaChart, { data: { "con": continuousValues, "dis": discreteValues } }));
}
}
else if (chartResult.NAME === "Function") {
var data = _.range(0, 10, 0.1).map(function (_, i) {
var x = i / 10;
if (chartResult.NAME == "Function") {
var result_1 = chartResult.VAL(x);
if (result_1.tag == "Ok") {
var percentileArray = [
0.01,
0.05,
0.1,
0.2,
0.3,
0.4,
0.5,
0.6,
0.7,
0.8,
0.9,
0.95,
0.99
];
var percentiles = getPercentiles(percentileArray, result_1.value);
return {
"x": x,
"p1": percentiles[0],
"p5": percentiles[1],
"p10": percentiles[2],
"p20": percentiles[3],
"p30": percentiles[4],
"p40": percentiles[5],
"p50": percentiles[6],
"p60": percentiles[7],
"p70": percentiles[8],
"p80": percentiles[9],
"p90": percentiles[10],
"p95": percentiles[11],
"p99": percentiles[12]
};
}
}
return 0;
});
return React.createElement(SquigglePercentilesChart, { data: { "facet": data } });
}
});
return React.createElement(React.Fragment, null, chartResults);
}
else if (result.tag == "Error") {
return (React.createElement("p", null, "Error parsing Squiggle: " + result.value));
}
return (React.createElement("p", null, "Invalid Response"));
};
exports.SquiggleChart = SquiggleChart;
function getPercentiles(percentiles, t) {
if (t.shape.tag == "Discrete") {
var total_4 = 0;
var maxX_1 = _.max(t.shape.value.xyShape.xs);
var bounds_1 = percentiles.map(function (_) { return maxX_1; });
_.zipWith(t.shape.value.xyShape.xs, t.shape.value.xyShape.ys, function (x, y) {
total_4 += y;
percentiles.forEach(function (v, i) {
if (total_4 > v && bounds_1[i] == maxX_1) {
bounds_1[i] = x;
}
});
});
return bounds_1;
}
else if (t.shape.tag == "Continuous") {
var total_5 = 0;
var maxX_2 = _.max(t.shape.value.xyShape.xs);
var totalY_4 = _.sum(t.shape.value.xyShape.ys);
var bounds_2 = percentiles.map(function (_) { return maxX_2; });
_.zipWith(t.shape.value.xyShape.xs, t.shape.value.xyShape.ys, function (x, y) {
total_5 += y / totalY_4;
percentiles.forEach(function (v, i) {
if (total_5 > v && bounds_2[i] == maxX_2) {
bounds_2[i] = x;
}
});
});
return bounds_2;
}
else if (t.shape.tag == "Mixed") {
var discreteShape = t.shape.value.discrete.xyShape;
var totalDiscrete = discreteShape.ys.reduce(function (a, b) { return a + b; });
var discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
var continuousShape = t.shape.value.continuous.xyShape;
var continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
;
var markedDisPoints = discretePoints.map(function (_a) {
var x = _a[0], y = _a[1];
return ({ x: x, y: y, type: "discrete" });
});
var markedConPoints = continuousPoints.map(function (_a) {
var x = _a[0], y = _a[1];
return ({ x: x, y: y, type: "continuous" });
});
var sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), 'x');
var totalContinuous_2 = 1 - totalDiscrete;
var totalY_5 = continuousShape.ys.reduce(function (a, b) { return a + b; });
var total_6 = 0;
var maxX_3 = _.max(sortedPoints.map(function (x) { return x.x; }));
var bounds_3 = percentiles.map(function (_) { return maxX_3; });
sortedPoints.map(function (point) {
if (point.type == "discrete") {
total_6 += point.y;
}
else if (point.type == "continuous") {
total_6 += point.y / totalY_5 * totalContinuous_2;
}
percentiles.forEach(function (v, i) {
if (total_6 > v && bounds_3[i] == maxX_3) {
bounds_3[i] = total_6;
}
});
return total_6;
});
return bounds_3;
}
}
exports.SquiggleChart.propTypes = {
squiggleString: PropTypes.string
};
exports.SquiggleChart.defaultProps = {
squggleString: "normal(5, 2)"
};
function MakeNumberShower(props) {
var numberWithPresentation = numberShow(props.number, props.precision);
return (React.createElement("span", null,
numberWithPresentation.value,
numberWithPresentation.symbol,
numberWithPresentation.power ?
React.createElement("span", null,
'\u00b710',
React.createElement("span", { style: { fontSize: "0.6em", verticalAlign: "super" } }, numberWithPresentation.power))
: React.createElement(React.Fragment, null)));
}
var orderOfMagnitudeNum = function (n) {
return Math.pow(10, n);
};
var orderOfMagnitude = function (n) {
return Math.floor(Math.log(n) / Math.LN10 + 0.000000001);
};
function withXSigFigs(number, sigFigs) {
var withPrecision = number.toPrecision(sigFigs);
var formatted = Number(withPrecision);
return "".concat(formatted);
}
var NumberShower = (function () {
function NumberShower(number, precision) {
if (precision === void 0) { precision = 2; }
this.number = number;
this.precision = precision;
}
NumberShower.prototype.convert = function () {
var number = Math.abs(this.number);
var response = this.evaluate(number);
if (this.number < 0) {
response.value = '-' + response.value;
}
return response;
};
NumberShower.prototype.metricSystem = function (number, order) {
var newNumber = number / orderOfMagnitudeNum(order);
var precision = this.precision;
return "".concat(withXSigFigs(newNumber, precision));
};
NumberShower.prototype.evaluate = function (number) {
if (number === 0) {
return { value: this.metricSystem(0, 0) };
}
var order = orderOfMagnitude(number);
if (order < -2) {
return { value: this.metricSystem(number, order), power: order };
}
else if (order < 4) {
return { value: this.metricSystem(number, 0) };
}
else if (order < 6) {
return { value: this.metricSystem(number, 3), symbol: 'K' };
}
else if (order < 9) {
return { value: this.metricSystem(number, 6), symbol: 'M' };
}
else if (order < 12) {
return { value: this.metricSystem(number, 9), symbol: 'B' };
}
else if (order < 15) {
return { value: this.metricSystem(number, 12), symbol: 'T' };
}
else {
return { value: this.metricSystem(number, order), power: order };
}
};
return NumberShower;
}());
function numberShow(number, precision) {
if (precision === void 0) { precision = 2; }
var ns = new NumberShower(number, precision);
return ns.convert();
}
exports.numberShow = numberShow;
//# sourceMappingURL=SquiggleChart.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,16 @@
declare const _default: {
title: string;
component: {
({ squiggleString }: {
squiggleString: string;
}): JSX.Element;
propTypes: {
squiggleString: import("prop-types").Requireable<string>;
};
defaultProps: {
squggleString: string;
};
};
};
export default _default;
export declare const Default: any;

View File

@ -0,0 +1,18 @@
"use strict";
exports.__esModule = true;
exports.Default = void 0;
var React = require("react");
var SquiggleChart_1 = require("./SquiggleChart");
exports["default"] = {
title: 'Example/SquiggleChart',
component: SquiggleChart_1.SquiggleChart
};
var Template = function (_a) {
var squiggleString = _a.squiggleString;
return React.createElement(SquiggleChart_1.SquiggleChart, { squiggleString: squiggleString });
};
exports.Default = Template.bind({});
exports.Default.args = {
squiggleString: "normal(5, 2)"
};
//# sourceMappingURL=SquiggleChart.stories.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"SquiggleChart.stories.js","sourceRoot":"","sources":["../../src/stories/SquiggleChart.stories.tsx"],"names":[],"mappings":";;;AAAA,6BAA8B;AAC9B,iDAA+C;AAG/C,qBAAe;IACb,KAAK,EAAE,uBAAuB;IAC9B,SAAS,EAAE,6BAAa;CACzB,CAAA;AAED,IAAM,QAAQ,GAAG,UAAC,EAAgB;QAAf,cAAc,oBAAA;IAAM,OAAA,oBAAC,6BAAa,IAAC,cAAc,EAAE,cAAc,GAAI;AAAjD,CAAiD,CAAA;AAE3E,QAAA,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACxC,eAAO,CAAC,IAAI,GAAG;IACb,cAAc,EAAE,cAAc;CAC/B,CAAC"}

View File

@ -0,0 +1,118 @@
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic area chart example.",
"width": 500,
"height": 200,
"padding": 5,
"data": [{ "name": "con" }, { "name": "dis" }],
"signals": [
{
"name": "mousex",
"description": "x position of mouse",
"update": "0",
"on": [{ "events": "mousemove", "update": "1-x()/width" }]
},
{
"name": "xscale",
"description": "The transform of the x scale",
"value": 1.0,
"bind": {
"input": "range",
"min": 0.1,
"max": 1
}
},
{
"name": "yscale",
"description": "The transform of the y scale",
"value": 1.0,
"bind": {
"input": "range",
"min": 0.1,
"max": 1
}
}
],
"scales": [{
"name": "xscale",
"type": "pow",
"exponent": { "signal": "xscale" },
"range": "width",
"zero": false,
"nice": false,
"domain": {
"fields": [
{ "data": "con", "field": "x" },
{ "data": "dis", "field": "x" }
]
}
}, {
"name": "yscale",
"type": "pow",
"exponent": { "signal": "yscale" },
"range": "height",
"nice": true,
"zero": true,
"domain": {
"fields": [
{ "data": "con", "field": "y" },
{ "data": "dis", "field": "y" }
]
}
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale", "tickCount": 20 },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "area",
"from": { "data": "con" },
"encode": {
"enter": {
"tooltip": { "signal": "datum.cdf" }
},
"update": {
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "y" },
"y2": { "scale": "yscale", "value": 0 },
"fill": {
"signal": "{gradient: 'linear', x1: 1, y1: 1, x2: 0, y2: 1, stops: [ {offset: 0.0, color: 'steelblue'}, {offset: clamp(mousex, 0, 1), color: 'steelblue'}, {offset: clamp(mousex, 0, 1), color: 'blue'}, {offset: 1.0, color: 'blue'} ] }"
},
"interpolate": { "value": "monotone" },
"fillOpacity": { "value": 1 }
}
}
},
{
"type": "rect",
"from": { "data": "dis" },
"encode": {
"enter": {
"y2": { "scale": "yscale", "value": 0 },
"width": { "value": 1 }
},
"update": {
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "y" }
}
}
},
{
"type": "symbol",
"from": { "data": "dis" },
"encode": {
"enter": {
"shape": { "value": "circle" },
"width": { "value": 5 },
"tooltip": { "signal": "datum.y" }
},
"update": {
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "y" }
}
}
}
]
}

View File

@ -0,0 +1,208 @@
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 500,
"height": 400,
"padding": 5,
"data": [
{
"name": "facet",
"values": [],
"format": { "type": "json", "parse": { "timestamp": "date" } }
},
{
"name": "table",
"source": "facet",
"transform": [
{
"type": "aggregate",
"groupby": ["x"],
"ops": [
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean"
],
"fields": [
"p1",
"p5",
"p10",
"p20",
"p30",
"p40",
"p50",
"p60",
"p70",
"p80",
"p90",
"p95",
"p99"
],
"as": [
"p1",
"p5",
"p10",
"p20",
"p30",
"p40",
"p50",
"p60",
"p70",
"p80",
"p90",
"p95",
"p99"
]
}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"nice": true,
"domain": { "data": "facet", "field": "x" },
"range": "width"
},
{
"name": "yscale",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain": { "data": "facet", "field": "p99" }
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"grid": false,
"tickSize": 2,
"encode": {
"grid": { "enter": { "stroke": { "value": "#ccc" } } },
"ticks": { "enter": { "stroke": { "value": "#ccc" } } }
}
},
{
"orient": "left",
"scale": "yscale",
"grid": false,
"domain": false,
"tickSize": 2,
"encode": {
"grid": { "enter": { "stroke": { "value": "#ccc" } } },
"ticks": { "enter": { "stroke": { "value": "#ccc" } } }
}
}
],
"marks": [
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p1" },
"y2": { "scale": "yscale", "field": "p99" },
"opacity": { "value": 0.05 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p5" },
"y2": { "scale": "yscale", "field": "p95" },
"opacity": { "value": 0.1 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p10" },
"y2": { "scale": "yscale", "field": "p90" },
"opacity": { "value": 0.15 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p20" },
"y2": { "scale": "yscale", "field": "p80" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p30" },
"y2": { "scale": "yscale", "field": "p70" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p40" },
"y2": { "scale": "yscale", "field": "p60" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "line",
"from": { "data": "table" },
"encode": {
"update": {
"interpolate": { "value": "monotone" },
"stroke": { "value": "#4C78A8" },
"strokeWidth": { "value": 2 },
"opacity": { "value": 0.8 },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p50" }
}
}
}
]
}

View File

@ -39,7 +39,7 @@
"@rescript/react",
"bs-css",
"bs-css-emotion",
"@foretold-app/squiggle",
"@squiggle/squiggle-lang",
"rationale",
"bs-moment",
"reschema"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "@foretold-app/squiggle-playground",
"name": "@squiggle/playground",
"version": "0.1.0",
"homepage": "https://foretold-app.github.io/estiband/",
"scripts": {
@ -30,6 +30,13 @@
"@glennsl/bs-json": "^5.0.2",
"@rescript/react": "^0.10.3",
"@rescriptbr/reform": "^11.0.1",
"@squiggle/components": "^0.1.0",
"@squiggle/squiggle-lang": "^0.1.9",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.178",
"@types/node": "^17.0.16",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"ace-builds": "^1.4.12",
"antd": "^4.18.5",
"autoprefixer": "9.8.8",
@ -40,6 +47,7 @@
"bs-css-emotion": "^4.1.0",
"bs-moment": "0.6.0",
"bsb-js": "1.1.7",
"cross-env": "^7.0.3",
"css-loader": "^6.6.0",
"d3": "7.3.0",
"gh-pages": "2.2.0",
@ -47,7 +55,7 @@
"jstat": "1.9.2",
"lenses-ppx": "5.1.0",
"less": "3.10.3",
"lodash": "4.17.15",
"lodash": "^4.17.21",
"mathjs": "5.10.3",
"moduleserve": "0.9.1",
"moment": "2.24.0",
@ -61,11 +69,13 @@
"react-vega": "^7.4.4",
"reschema": "^2.2.0",
"rescript": "^9.1.4",
"@foretold-app/squiggle": "^0.1.9",
"tailwindcss": "1.2.0",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.5.5",
"vega": "*",
"vega-embed": "6.6.0",
"vega-lite": "*"
"vega-lite": "*",
"webpack-cli": "^4.9.2"
},
"devDependencies": {
"@glennsl/bs-jest": "^0.5.1",

View File

@ -94,79 +94,13 @@ let groupB = style(. [ selector(. ".antInputNumberInput", [ backgroundColor(hex(
}
module DemoDist = {
@react.component
let make = (~squiggleString: string, ~options) =>
<Antd.Card title={"Distribution"}>
<div>
{switch options {
| Some(options) =>
let inputs1 = ForetoldAppSquiggle.ProgramEvaluator.Inputs.make(
~samplingInputs={
sampleCount: Some(options.sampleCount),
outputXYPoints: Some(options.outputXYPoints),
kernelWidth: options.kernelWidth,
shapeLength: Some(options.downsampleTo |> E.O.default(1000)),
},
~squiggleString,
~environment=[
("K", #SymbolicDist(#Float(1000.0))),
("M", #SymbolicDist(#Float(1000000.0))),
("B", #SymbolicDist(#Float(1000000000.0))),
("T", #SymbolicDist(#Float(1000000000000.0))),
]->Belt.Map.String.fromArray,
(),
)
let distributionList = ForetoldAppSquiggle.ProgramEvaluator.evaluateProgram(inputs1)
type props
let renderExpression = response1 =>
switch response1 {
| #DistPlus(distPlus1) => <DistPlusPlot distPlus={ForetoldAppSquiggle.DistPlus.T.normalize(distPlus1)} />
| #Float(f) => <NumberShower number=f precision=3 />
| #Function((f, a), env) =>
// Problem: When it gets the function, it doesn't save state about previous commands
let foo: ForetoldAppSquiggle.ProgramEvaluator.Inputs.inputs = {
squiggleString: squiggleString,
samplingInputs: inputs1.samplingInputs,
environment: env,
}
let results =
E.A.Floats.range(options.diagramStart, options.diagramStop, options.diagramCount)
|> E.A.fmap(r =>
ForetoldAppSquiggle.ProgramEvaluator.evaluateFunction(
foo,
(f, a),
[#SymbolicDist(#Float(r))],
) |> E.R.bind(_, a =>
switch a {
| #DistPlus(d) => Ok((r, ForetoldAppSquiggle.DistPlus.T.normalize(d)))
| n =>
Js.log2("Error here", n)
Error("wrong type")
}
)
)
|> E.A.R.firstErrorOrOpen
switch results {
| Ok(dists) => <PercentilesChart dists />
| Error(r) => r |> R.ste
}
}
@obj external makeProps : (~squiggleString: string,unit) => props = ""
// Render the list of distributions given by the
switch distributionList {
| Ok(xs) =>
let childrenElements = List.map(renderExpression, xs)
Js.Console.log(childrenElements)
<ul>
{Belt.List.toArray(Belt.List.mapWithIndex(childrenElements, (i, child) => <li key={Belt.Int.toString(i)}>child</li>))->React.array}
</ul>
| Error(r) => r |> R.ste
}
| _ => "Nothing to show. Try to change the distribution description." |> R.ste
}}
</div>
</Antd.Card>
@module("@squiggle/components")
external make : props => React.element = "SquiggleChart"
}
@react.component
@ -196,6 +130,7 @@ let make = () => {
}
let squiggleString = reform.state.values.squiggleString
/*
let sampleCount = reform.state.values.sampleCount |> Js.Float.fromString
let outputXYPoints = reform.state.values.outputXYPoints |> Js.Float.fromString
let downsampleTo = reform.state.values.downsampleTo |> Js.Float.fromString
@ -220,21 +155,10 @@ let make = () => {
})
| _ => None
}
*/
let demoDist = React.useMemo1(
() => <DemoDist squiggleString options />,
[
reform.state.values.squiggleString,
reform.state.values.sampleCount,
reform.state.values.outputXYPoints,
reform.state.values.downsampleTo,
reform.state.values.kernelWidth,
reform.state.values.diagramStart,
reform.state.values.diagramStop,
reform.state.values.diagramCount,
reloader |> string_of_int,
],
)
let demoDist =
<DemoDist squiggleString=squiggleString />
let onReload = _ => setReloader(_ => reloader + 1)

View File

@ -1,306 +0,0 @@
open DistPlusPlotReducer
let plotBlue = #hex("1860ad")
let showAsForm = (distPlus: ForetoldAppSquiggle.DistTypes.distPlus) =>
<div> <Antd.Input value={distPlus.squiggleString |> E.O.default("")} /> </div>
let showFloat = (~precision=3, number) => <NumberShower number precision />
let table = (distPlus, x) =>
<div>
<table className="table-auto text-sm">
<thead>
<tr>
<td className="px-4 py-2 "> {"X Point" |> React.string} </td>
<td className="px-4 py-2"> {"Discrete Value" |> React.string} </td>
<td className="px-4 py-2"> {"Continuous Value" |> React.string} </td>
<td className="px-4 py-2"> {"Y Integral to Point" |> React.string} </td>
<td className="px-4 py-2"> {"Y Integral Total" |> React.string} </td>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border"> {x |> E.Float.toString |> React.string} </td>
<td className="px-4 py-2 border ">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.xToY(x)
|> ForetoldAppSquiggle.DistTypes.MixedPoint.toDiscreteValue
|> Js.Float.toPrecisionWithPrecision(_, ~digits=7)
|> React.string}
</td>
<td className="px-4 py-2 border ">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.xToY(x)
|> ForetoldAppSquiggle.DistTypes.MixedPoint.toContinuousValue
|> Js.Float.toPrecisionWithPrecision(_, ~digits=7)
|> React.string}
</td>
<td className="px-4 py-2 border ">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.Integral.xToY(x)
|> E.Float.with2DigitsPrecision
|> React.string}
</td>
<td className="px-4 py-2 border ">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.Integral.sum
|> E.Float.with2DigitsPrecision
|> React.string}
</td>
</tr>
</tbody>
</table>
<table className="table-auto text-sm">
<thead>
<tr>
<td className="px-4 py-2"> {"Continuous Total" |> React.string} </td>
<td className="px-4 py-2"> {"Discrete Total" |> React.string} </td>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.toContinuous
|> E.O.fmap(ForetoldAppSquiggle.Continuous.T.Integral.sum)
|> E.O.fmap(E.Float.with2DigitsPrecision)
|> E.O.default("")
|> React.string}
</td>
<td className="px-4 py-2 border ">
{distPlus
|> ForetoldAppSquiggle.DistPlus.T.toDiscrete
|> E.O.fmap(ForetoldAppSquiggle.Discrete.T.Integral.sum)
|> E.O.fmap(E.Float.with2DigitsPrecision)
|> E.O.default("")
|> React.string}
</td>
</tr>
</tbody>
</table>
</div>
let percentiles = distPlus =>
<div>
<table className="table-auto text-sm">
<thead>
<tr>
<td className="px-4 py-2"> {"1" |> React.string} </td>
<td className="px-4 py-2"> {"5" |> React.string} </td>
<td className="px-4 py-2"> {"25" |> React.string} </td>
<td className="px-4 py-2"> {"50" |> React.string} </td>
<td className="px-4 py-2"> {"75" |> React.string} </td>
<td className="px-4 py-2"> {"95" |> React.string} </td>
<td className="px-4 py-2"> {"99" |> React.string} </td>
<td className="px-4 py-2"> {"99.999" |> React.string} </td>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.01) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.05) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.25) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.5) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.75) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.95) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.99) |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.99999) |> showFloat}
</td>
</tr>
</tbody>
</table>
<table className="table-auto text-sm">
<thead>
<tr>
<td className="px-4 py-2"> {"mean" |> React.string} </td>
<td className="px-4 py-2"> {"standard deviation" |> React.string} </td>
<td className="px-4 py-2"> {"variance" |> React.string} </td>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border"> {distPlus |> ForetoldAppSquiggle.DistPlus.T.mean |> showFloat} </td>
<td className="px-4 py-2 border">
{distPlus |> ForetoldAppSquiggle.DistPlus.T.variance |> (r => r ** 0.5) |> showFloat}
</td>
<td className="px-4 py-2 border"> {distPlus |> ForetoldAppSquiggle.DistPlus.T.variance |> showFloat} </td>
</tr>
</tbody>
</table>
</div>
let adjustBoth = discreteProbabilityMassFraction => {
let yMaxDiscreteDomainFactor = discreteProbabilityMassFraction
let yMaxContinuousDomainFactor = 1.0 -. discreteProbabilityMassFraction
// use the bigger proportion, such that whichever is the bigger proportion, the yMax is 1.
let yMax = yMaxDiscreteDomainFactor > 0.5 ? yMaxDiscreteDomainFactor : yMaxContinuousDomainFactor
(yMax /. yMaxDiscreteDomainFactor, yMax /. yMaxContinuousDomainFactor)
}
module DistPlusChart = {
@react.component
let make = (~distPlus: ForetoldAppSquiggle.DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
open ForetoldAppSquiggle.DistPlus
let discrete = distPlus |> T.toDiscrete |> E.O.fmap(ForetoldAppSquiggle.Discrete.getShape)
let continuous = distPlus |> T.toContinuous |> E.O.fmap(ForetoldAppSquiggle.Continuous.getShape)
// // We subtract a bit from the range to make sure that it fits. Maybe this should be done in d3 instead.
// let minX =
// switch (
// distPlus
// |> DistPlus.T.Integral.yToX(0.0001),
// range,
// ) {
// | (min, Some(range)) => Some(min -. range *. 0.001)
// | _ => None
// };
let minX = distPlus |> T.Integral.yToX(0.00001)
let maxX = distPlus |> T.Integral.yToX(0.99999)
let timeScale = distPlus.unit |> ForetoldAppSquiggle.DistTypes.DistributionUnit.toJson
let discreteProbabilityMassFraction = distPlus |> T.toDiscreteProbabilityMassFraction
let (yMaxDiscreteDomainFactor, yMaxContinuousDomainFactor) = adjustBoth(
discreteProbabilityMassFraction,
)
<DistributionPlot
xScale={config.xLog ? "log" : "linear"}
yScale={config.yLog ? "log" : "linear"}
height={DistPlusPlotReducer.heightToPix(config.height)}
minX
maxX
yMaxDiscreteDomainFactor
yMaxContinuousDomainFactor
?discrete
?continuous
color=plotBlue
onHover
timeScale
/>
}
}
module IntegralChart = {
@react.component
let make = (~distPlus: ForetoldAppSquiggle.DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
let integral = distPlus.integralCache
let continuous = integral |> ForetoldAppSquiggle.Continuous.toLinear |> E.O.fmap(ForetoldAppSquiggle.Continuous.getShape)
let minX = distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.00001)
let maxX = distPlus |> ForetoldAppSquiggle.DistPlus.T.Integral.yToX(0.99999)
let timeScale = distPlus.unit |> ForetoldAppSquiggle.DistTypes.DistributionUnit.toJson
<DistributionPlot
xScale={config.xLog ? "log" : "linear"}
yScale={config.yLog ? "log" : "linear"}
height={DistPlusPlotReducer.heightToPix(config.height)}
minX
maxX
?continuous
color=plotBlue
timeScale
onHover
/>
}
}
module Chart = {
@react.component
let make = (~distPlus: ForetoldAppSquiggle.DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
let chart = React.useMemo2(
() =>
config.isCumulative
? <IntegralChart distPlus config onHover />
: <DistPlusChart distPlus config onHover />,
(distPlus, config),
)
<div
className={
open CssJs
style(. [ minHeight(#px(DistPlusPlotReducer.heightToPix(config.height))) ])
}>
chart
</div>
}
}
let button = "bg-gray-300 hover:bg-gray-500 text-grey-darkest text-xs px-4 py-1"
@react.component
let make = (~distPlus: ForetoldAppSquiggle.DistTypes.distPlus) => {
let (x, setX) = React.useState(() => 0.)
let (state, dispatch) = React.useReducer(DistPlusPlotReducer.reducer, DistPlusPlotReducer.init)
<div>
{state.distributions
|> E.L.fmapi((index, config) =>
<div className="flex" key={string_of_int(index)}>
<div className="w-4/5"> <Chart distPlus config onHover={r => setX(_ => r)} /> </div>
<div className="w-1/5">
<div className="opacity-50 hover:opacity-100">
<button className=button onClick={_ => dispatch(CHANGE_X_LOG(index))}>
{(config.xLog ? "x-log" : "x-linear") |> React.string}
</button>
<button className=button onClick={_ => dispatch(CHANGE_Y_LOG(index))}>
{(config.yLog ? "y-log" : "y-linear") |> React.string}
</button>
<button
className=button
onClick={_ => dispatch(CHANGE_IS_CUMULATIVE(index, !config.isCumulative))}>
{(config.isCumulative ? "cdf" : "pdf") |> React.string}
</button>
<button className=button onClick={_ => dispatch(HEIGHT_INCREMENT(index))}>
{"expand" |> React.string}
</button>
<button className=button onClick={_ => dispatch(HEIGHT_DECREMENT(index))}>
{"shrink" |> React.string}
</button>
{index != 0
? <button className=button onClick={_ => dispatch(REMOVE_DIST(index))}>
{"remove" |> React.string}
</button>
: React.null}
</div>
</div>
</div>
)
|> E.L.toArray
|> React.array}
<div className="inline-flex opacity-50 hover:opacity-100">
<button className=button onClick={_ => dispatch(CHANGE_SHOW_PERCENTILES)}>
{"Percentiles" |> React.string}
</button>
<button className=button onClick={_ => dispatch(CHANGE_SHOW_STATS)}>
{"Debug Stats" |> React.string}
</button>
<button className=button onClick={_ => dispatch(CHANGE_SHOW_PARAMS)}>
{"Params" |> React.string}
</button>
<button className=button onClick={_ => dispatch(ADD_DIST)}>
{"Add" |> React.string}
</button>
</div>
{state.showParams ? showAsForm(distPlus) : React.null}
{state.showStats ? table(distPlus, x) : React.null}
{state.showPercentiles ? percentiles(distPlus) : React.null}
</div>
}

View File

@ -1,112 +0,0 @@
type chartConfig = {
xLog: bool,
yLog: bool,
isCumulative: bool,
height: int,
};
type state = {
showStats: bool,
showPercentiles: bool,
showParams: bool,
distributions: list(chartConfig),
};
type action =
| CHANGE_SHOW_STATS
| CHANGE_SHOW_PARAMS
| CHANGE_SHOW_PERCENTILES
| REMOVE_DIST(int)
| ADD_DIST
| CHANGE_X_LOG(int)
| CHANGE_Y_LOG(int)
| CHANGE_IS_CUMULATIVE(int, bool)
| HEIGHT_INCREMENT(int)
| HEIGHT_DECREMENT(int);
let changeHeight = (currentHeight, foo: [ | `increment | `decrement]) =>
switch (currentHeight, foo) {
| (1, `decrement) => 1
| (2, `decrement) => 1
| (3, `decrement) => 2
| (4, `decrement) => 3
| (5, `decrement) => 4
| (1, `increment) => 2
| (2, `increment) => 3
| (3, `increment) => 4
| (4, `increment) => 5
| (5, `increment) => 5
| _ => 1
};
let heightToPix =
fun
| 1 => 80
| 2 => 140
| 3 => 240
| 4 => 340
| 5 => 440
| _ => 140;
let distributionReducer = (index, state: list(chartConfig), action) => {
switch (action, E.L.get(state, index)) {
| (HEIGHT_INCREMENT(_), Some(dist)) =>
E.L.update(
{...dist, height: changeHeight(dist.height, `increment)},
index,
state,
)
| (HEIGHT_DECREMENT(_), Some(dist)) =>
E.L.update(
{...dist, height: changeHeight(dist.height, `decrement)},
index,
state,
)
| (CHANGE_IS_CUMULATIVE(_, isCumulative), Some(dist)) =>
E.L.update({...dist, isCumulative}, index, state)
| (CHANGE_X_LOG(_), Some(dist)) =>
E.L.update({...dist, xLog: !dist.xLog}, index, state)
| (CHANGE_Y_LOG(_), Some(dist)) =>
E.L.update({...dist, yLog: !dist.yLog}, index, state)
| (REMOVE_DIST(_), Some(_)) => E.L.remove(index, 1, state)
| (ADD_DIST, Some(_)) =>
E.L.append(
state,
[{yLog: false, xLog: false, isCumulative: false, height: 4}],
)
| _ => state
};
};
let reducer = (state: state, action: action) =>
switch (action) {
| CHANGE_X_LOG(i)
| CHANGE_Y_LOG(i)
| CHANGE_IS_CUMULATIVE(i, _)
| HEIGHT_DECREMENT(i)
| REMOVE_DIST(i)
| HEIGHT_INCREMENT(i) => {
...state,
distributions: distributionReducer(i, state.distributions, action),
}
| ADD_DIST => {
...state,
distributions: distributionReducer(0, state.distributions, action),
}
| CHANGE_SHOW_STATS => {...state, showStats: !state.showStats}
| CHANGE_SHOW_PARAMS => {...state, showParams: !state.showParams}
| CHANGE_SHOW_PERCENTILES => {
...state,
showPercentiles: !state.showPercentiles,
}
};
let init = {
showStats: false,
showParams: false,
showPercentiles: false,
distributions: [
{yLog: false, xLog: false, isCumulative: false, height: 4},
{yLog: false, xLog: false, isCumulative: true, height: 1},
],
};

View File

@ -1,108 +0,0 @@
module RawPlot = {
type primaryDistribution = option<{"xs": array<float>, "ys": array<float>}>
type discrete = option<{"xs": array<float>, "ys": array<float>}>
type props
type makeType = props => React.element
@obj external makeProps: (
~height: int=?,
~marginBottom: int=?,
~marginTop: int=?,
~maxX: float=?,
~minX: float=?,
~yMaxContinuousDomainFactor: float=?,
~yMaxDiscreteDomainFactor: float=?,
~onHover: float => (),
~continuous: option<{"xs": array<float>, "ys": array<float>}>=?,
~discrete: option<{"xs": array<float>, "ys": array<float>}>=?,
~xScale: string=?,
~yScale: string=?,
~showDistributionLines: bool=?,
~showDistributionYAxis: bool=?,
~showVerticalLine: bool=?,
~timeScale:Js.Null.t<{"unit": string, "zero": MomentRe.Moment.t}>=?,
~verticalLine: int=?,
~children: array<React.element>=?,
unit // This unit is a quirk of the type system. Apparently it must exist to have optional arguments in a type
) => props = ""
@module("./distPlotReact.js")
external make : makeType = "default"
}
module Styles = {
open CssJs
let textOverlay = style(. [position(#absolute)])
let mainText = style(. [ fontSize(#em(1.1))])
let secondaryText = style(. [fontSize(#em(0.9))])
let graph = chartColor =>
style(. [
position(#relative),
selector(. ".xAxis", [fontSize(#px(9))]),
selector(. ".xAxis .domain", [ display(#none) ]),
selector(. ".xAxis .tick line", [ display(#none) ]),
selector(. ".xAxis .tick text", [ color(#hex("7a8998")) ]),
selector(. ".chart .areaPath", [ SVG.fill(chartColor) ]),
selector(. ".lollipopsLine", [ SVG.stroke(#hex("bfcad4")) ]),
selector(. ".lollipopsCircle", [ SVG.stroke(#hex("bfcad4")), SVG.fill(#hex("bfcad4")) ]),
selector(. ".lollipopsXAxis .domain", [ display(#none) ]),
selector(. ".lollipopsXAxis .tick line", [ display(#none) ]),
selector(. ".lollipopsXAxis .tick text", [ display(#none) ]),
selector(.
".lollipopsTooltip",
[ position(#absolute),
textAlign(#center),
padding(px(2)),
backgroundColor(hex("bfcad4")),
borderRadius(px(3)),
],
),
selector(.
".lollipopsCircleMouseover",
[ SVG.fill(hex("ffa500")), SVG.stroke(#hex("fff")) ],
),
selector(. ".lollipopsLineMouseover", [ SVG.stroke(#hex("ffa500")) ]),
])
}
@react.component
let make = (
~color=#hex("111"),
~discrete=?,
~height=200,
~maxX=?,
~minX=?,
~yMaxDiscreteDomainFactor=?,
~yMaxContinuousDomainFactor=?,
~onHover: float => unit=_ => (),
~continuous=?,
~xScale=?,
~yScale=?,
~showDistributionLines=false,
~showDistributionYAxis=false,
~showVerticalLine=false,
~timeScale=?,
) =>
<div className={Styles.graph(color)}>
<RawPlot
?maxX
?minX
?yMaxDiscreteDomainFactor
?yMaxContinuousDomainFactor
?xScale
?yScale
?timeScale
discrete={discrete |> E.O.fmap(ForetoldAppSquiggle.XYShape.T.toJs)}
height
marginBottom=50
marginTop=0
onHover
continuous={continuous |> E.O.fmap(ForetoldAppSquiggle.XYShape.T.toJs)}
showDistributionLines
showDistributionYAxis
showVerticalLine
/>
</div>

View File

@ -1,10 +0,0 @@
import * as _ from "lodash";
import { createClassFromSpec } from "react-vega";
import spec from "./spec-percentiles";
const PercentilesChart = createClassFromSpec({
spec,
style: "width: 100%",
});
export { PercentilesChart };

View File

@ -1,55 +0,0 @@
open ForetoldAppSquiggle
@module("./PercentilesChart.js")
external percentilesChart: React.element = "PercentilesChart"
module Internal = {
type props
type makeType = props => React.element
type dataType = { "facet": array<
{
"p1": float,
"p10": float,
"p20": float,
"p30": float,
"p40": float,
"p5": float,
"p50": float,
"p60": float,
"p70": float,
"p80": float,
"p90": float,
"p95": float,
"p99": float,
"x": float,
}>}
@obj external makeProps: (~data: dataType, ~signalListeners: list<string>,~children:React.element, unit) => props = ""
@module("./PercentilesChart.js")
external make : makeType = "PercentilesChart"
}
@react.component
@module("./PercentilesChart.js")
let make = (~dists: array<(float, DistTypes.distPlus)>, ~children=React.null) => {
let data = dists -> Belt.Array.map(((x, r)) =>
{
"x": x,
"p1": r |> DistPlus.T.Integral.yToX(0.01),
"p5": r |> DistPlus.T.Integral.yToX(0.05),
"p10": r |> DistPlus.T.Integral.yToX(0.1),
"p20": r |> DistPlus.T.Integral.yToX(0.2),
"p30": r |> DistPlus.T.Integral.yToX(0.3),
"p40": r |> DistPlus.T.Integral.yToX(0.4),
"p50": r |> DistPlus.T.Integral.yToX(0.5),
"p60": r |> DistPlus.T.Integral.yToX(0.6),
"p70": r |> DistPlus.T.Integral.yToX(0.7),
"p80": r |> DistPlus.T.Integral.yToX(0.8),
"p90": r |> DistPlus.T.Integral.yToX(0.9),
"p95": r |> DistPlus.T.Integral.yToX(0.95),
"p99": r |> DistPlus.T.Integral.yToX(0.99),
}
)
Js.log3("Data", dists, data)
let da = {"facet": data}
<Internal data=da signalListeners=list{}>children</Internal>
}

View File

@ -1,658 +0,0 @@
const _ = require('lodash');
const d3 = require('d3');
const moment = require('moment');
require('./styles.css');
/**
* @param arr
* @returns {*}
*/
function exists(arr) {
return arr.find(num => _.isFinite(num));
}
export class DistPlotD3 {
constructor() {
this.attrs = {
svgWidth: 400,
svgHeight: 400,
marginTop: 5,
marginBottom: 5,
marginRight: 50,
marginLeft: 5,
container: null,
// X
minX: null,
maxX: null,
xScaleType: 'linear',
xScaleTimeOptions: null,
xScaleLogBase: 10,
// Y
minY: null,
maxY: null,
yScaleType: 'linear',
yScaleTimeOptions: null,
yScaleLogBase: 10,
xMinContinuousDomainFactor: 1,
xMaxContinuousDomainFactor: 1,
yMaxContinuousDomainFactor: 1,
yMaxDiscreteDomainFactor: 1,
showDistributionYAxis: false,
showDistributionLines: true,
areaColors: ['#E1E5EC', '#E1E5EC'],
verticalLine: 110,
showVerticalLine: true,
data: {
continuous: null,
discrete: null,
},
onHover: (e) => {
},
};
this.calc = {
chartLeftMargin: null,
chartTopMargin: null,
chartWidth: null,
chartHeight: null,
};
this.chart = null;
this.svg = null;
this._container = null;
this.formatDates = this.formatDates.bind(this);
}
/**
* @param {string} name
* @param value
* @returns {DistPlotD3}
*/
set(name, value) {
_.set(this.attrs, [name], value);
return this;
}
/**
* @param data
* @returns {DistPlotD3}
*/
data(data) {
const continuousXs = _.get(data, 'continuous.xs', []);
const continuousYs = _.get(data, 'continuous.ys', []);
const discreteXs = _.get(data, 'discrete.xs', []);
const discreteYs = _.get(data, 'discrete.ys', []);
this.attrs.data = data;
this.attrs.data.continuous = {
xs: continuousXs,
ys: continuousYs,
};
this.attrs.data.discrete = {
xs: discreteXs,
ys: discreteYs,
};
return this;
}
render() {
this._container = d3.select(this.attrs.container);
if (this._container.node() === null) {
throw new Error('Container for D3 is not defined.');
}
if (!['log', 'linear'].includes(this.attrs.xScaleType)) {
throw new Error('X-scale type should be either "log" or "linear".');
}
if (!['log', 'linear'].includes(this.attrs.yScaleType)) {
throw new Error('Y-scale type should be either "log" or "linear".');
}
// Log Scale.
if (this.attrs.xScaleType === 'log') {
this.logFilter('continuous', (x, y) => x > 0);
this.logFilter('discrete', (x, y) => x > 0);
}
if (this.attrs.yScaleType === 'log') {
this.logFilter('continuous', (x, y) => y > 0);
this.logFilter('discrete', (x, y) => y > 0);
}
if (
this.attrs.xScaleType === 'log'
&& this.attrs.minX !== null
&& this.attrs.minX < 0
) {
console.warn('minX should be positive.');
this.attrs.minX = undefined;
}
if (
this.attrs.yScaleType === 'log'
&& this.attrs.minY !== null
&& this.attrs.minY < 0
) {
console.warn('minY should be positive.');
this.attrs.minY = undefined;
}
// Fields.
const fields = [
'marginLeft', 'marginRight',
'marginTop', 'marginBottom',
'svgWidth', 'svgHeight',
'yMaxContinuousDomainFactor',
'yMaxDiscreteDomainFactor',
'xScaleLogBase', 'yScaleLogBase',
];
for (const field of fields) {
if (!_.isNumber(this.attrs[field])) {
throw new Error(`${field} should be a number.`);
}
}
// Sets the width from the DOM element.
const containerRect = this._container.node().getBoundingClientRect();
if (containerRect.width > 0) {
this.attrs.svgWidth = containerRect.width;
}
// Calculated properties.
this.calc.chartLeftMargin = this.attrs.marginLeft;
this.calc.chartTopMargin = this.attrs.marginTop;
this.calc.chartWidth = this.attrs.svgWidth
- this.attrs.marginRight
- this.attrs.marginLeft;
this.calc.chartHeight = this.attrs.svgHeight
- this.attrs.marginBottom
- this.attrs.marginTop;
// Add svg.
this.svg = this._container
.createObject({ tag: 'svg', selector: 'svg-chart-container' })
.attr('width', '100%')
.attr('height', this.attrs.svgHeight)
.attr('pointer-events', 'none');
// Add container 'g' (empty) element.
this.chart = this.svg
.createObject({ tag: 'g', selector: 'chart' })
.attr(
'transform',
`translate(${this.calc.chartLeftMargin}, ${this.calc.chartTopMargin})`,
);
try {
const common = this.getCommonThings();
if (this.hasDate('continuous')) {
this.addDistributionChart(common);
}
if (this.hasDate('discrete')) {
this.addLollipopsChart(common);
}
} catch (e) {
this._container.selectAll("*").remove();
throw e;
}
return this;
}
/**
* @returns {*}
*/
getCommonThings() {
// Boundaries.
const xMin = exists([
this.attrs.minX,
d3.min(this.attrs.data.continuous.xs),
d3.min(this.attrs.data.discrete.xs),
]);
const xMax = exists([
this.attrs.maxX,
d3.max(this.attrs.data.continuous.xs),
d3.max(this.attrs.data.discrete.xs),
]);
const yMin = exists([
this.attrs.minY,
d3.min(this.attrs.data.continuous.ys),
d3.min(this.attrs.data.discrete.ys),
]);
const yMax = exists([
this.attrs.maxY,
d3.max(this.attrs.data.continuous.ys),
d3.max(this.attrs.data.discrete.ys),
]);
// Errors.
if (!_.isFinite(xMin)) throw new Error('xMin is undefined');
if (!_.isFinite(xMax)) throw new Error('xMax is undefined');
if (!_.isFinite(yMin)) throw new Error('yMin is undefined');
if (!_.isFinite(yMax)) throw new Error('yMax is undefined');
// X-domains.
const xMinDomainFactor = _.get(this.attrs, 'xMinContinuousDomainFactor', 1);
const xMaxDomainFactor = _.get(this.attrs, 'xMaxContinuousDomainFactor', 1);
const yMinDomainFactor = _.get(this.attrs, 'yMinContinuousDomainFactor', 1);
const yMaxDomainFactor = _.get(this.attrs, 'yMaxContinuousDomainFactor', 1);
const xMinDomain = xMin * xMinDomainFactor;
const xMaxDomain = xMax * xMaxDomainFactor;
const yMinDomain = yMin * yMinDomainFactor;
const yMaxDomain = yMax * yMaxDomainFactor;
// X-scale.
const xScale = this.attrs.xScaleType === 'linear'
? d3.scaleLinear()
.domain([xMinDomain, xMaxDomain])
.range([0, this.calc.chartWidth])
: d3.scaleLog()
.base(this.attrs.xScaleLogBase)
.domain([xMinDomain, xMaxDomain])
.range([0, this.calc.chartWidth]);
// Y-scale.
const yScale = this.attrs.yScaleType === 'linear'
? d3.scaleLinear()
.domain([yMinDomain, yMaxDomain])
.range([this.calc.chartHeight, 0])
: d3.scaleLog()
.base(this.attrs.yScaleLogBase)
.domain([yMinDomain, yMaxDomain])
.range([this.calc.chartHeight, 0]);
return {
xMin, xMax,
xScale, yScale,
};
}
/**
* @param common
*/
addDistributionChart(common) {
const areaColorRange = d3.scaleOrdinal().range(this.attrs.areaColors);
const dataPoints = [this.getDataPoints('continuous')];
const { xMin, xMax, xScale, yScale } = common;
// X-axis.
let xAxis = null;
if (!!this.attrs.xScaleTimeOptions) {
// Calculates the projection on X-axis.
const zero = _.get(this.attrs, 'xScaleTimeOptions.zero', moment());
const unit = _.get(this.attrs, 'xScaleTimeOptions.unit', 'years');
const diff = Math.abs(xMax - xMin);
const left = zero.clone().add(xMin, unit);
const right = left.clone().add(diff, unit);
// X-time-scale.
const xScaleTime = d3.scaleTime()
.domain([left.toDate(), right.toDate()])
.nice()
.range([0, this.calc.chartWidth]);
xAxis = d3.axisBottom()
.scale(xScaleTime)
.ticks(this.getTimeTicksByStr(unit))
.tickFormat(this.formatDates);
} else {
xAxis = d3.axisBottom(xScale)
.ticks(3)
.tickFormat(d => {
if (Math.abs(d) < 1) {
return d3.format('.2')(d);
} else if (xMin > 1000 && xMax < 3000) {
// Condition which identifies years; 2019, 2020, 2021.
return d3.format('.0')(d);
} else {
const prefix = d3.formatPrefix('.0', d);
return prefix(d).replace('G', 'B');
}
});
}
// Y-axis.
const yAxis = d3.axisRight(yScale);
// Add axis.
this.chart
.createObject({ tag: 'g', selector: 'x-axis' })
.attr('transform', `translate(0, ${this.calc.chartHeight})`)
.call(xAxis);
if (this.attrs.showDistributionYAxis) {
this.chart
.createObject({ tag: 'g', selector: 'y-axis' })
.call(yAxis);
}
// Draw area.
const area = d3.area()
.x(d => xScale(d.x))
.y1(d => yScale(d.y))
.y0(this.calc.chartHeight);
this.chart
.createObjectsWithData({
tag: 'path',
selector: 'area-path',
data: dataPoints,
})
.attr('d', area)
.attr('fill', (d, i) => areaColorRange(i))
.attr('opacity', (d, i) => i === 0 ? 0.7 : 0.5);
// Draw line.
if (this.attrs.showDistributionLines) {
const line = d3.line()
.x(d => xScale(d.x))
.y(d => yScale(d.y));
this.chart
.createObjectsWithData({
tag: 'path',
selector: 'line-path',
data: dataPoints,
})
.attr('d', line)
.attr('id', (d, i) => 'line-' + (i + 1))
.attr('opacity', (d, i) => i === 0 ? 0.7 : 1)
.attr('fill', 'none');
}
if (this.attrs.showVerticalLine) {
this.chart
.createObject({ tag: 'line', selector: 'v-line' })
.attr('x1', xScale(this.attrs.verticalLine))
.attr('x2', xScale(this.attrs.verticalLine))
.attr('y1', 0)
.attr('y2', this.calc.chartHeight)
.attr('stroke-width', 1.5)
.attr('stroke-dasharray', '6 6')
.attr('stroke', 'steelblue');
}
const hoverLine = this.chart
.createObject({ tag: 'line', selector: 'hover-line' })
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', this.calc.chartHeight)
.attr('opacity', 0)
.attr('stroke-width', 1.5)
.attr('stroke-dasharray', '6 6')
.attr('stroke', '#22313F');
// Add drawing rectangle.
{
const context = this;
function mouseover() {
const mouse = d3.mouse(this);
hoverLine
.attr('opacity', 1)
.attr('x1', mouse[0])
.attr('x2', mouse[0]);
const xValue = xScale.invert(mouse[0]);
context.attrs.onHover(xValue);
}
function mouseout() {
hoverLine.attr('opacity', 0);
}
this.chart
.createObject({ tag: 'rect', selector: 'mouse-rect' })
.attr('width', this.calc.chartWidth)
.attr('height', this.calc.chartHeight)
.attr('fill', 'transparent')
.attr('pointer-events', 'all')
.on('mouseover', mouseover)
.on('mousemove', mouseover)
.on('mouseout', mouseout);
}
}
/**
* @param {object} common
* @param {object} common.xScale
* @param {object} common.yScale
*/
addLollipopsChart(common) {
const data = this.getDataPoints('discrete');
const yMin = 0.;
const yMax = d3.max(this.attrs.data.discrete.ys);
// X axis.
this.chart.append('g')
.attr('class', 'lollipops-x-axis')
.attr('transform', `translate(0, ${this.calc.chartHeight})`)
.call(d3.axisBottom(common.xScale));
// Y-domain.
const yMinDomainFactor = _.get(this.attrs, 'yMinDiscreteDomainFactor', 1);
const yMaxDomainFactor = _.get(this.attrs, 'yMaxDiscreteDomainFactor', 1);
const yMinDomain = yMin * yMinDomainFactor;
const yMaxDomain = yMax * yMaxDomainFactor;
// Y-scale.
const yScale = this.attrs.yScaleType === 'linear'
? d3.scaleLinear()
.domain([yMinDomain, yMaxDomain])
.range([this.calc.chartHeight, 0])
: d3.scaleLog()
.base(this.attrs.yScaleLogBase)
.domain([yMinDomain, yMaxDomain])
.range([this.calc.chartHeight, 0]);
//
const yTicks = Math.floor(this.calc.chartHeight / 20);
const yAxis = d3.axisLeft(yScale).ticks(yTicks);
// Adds 'g' for an y-axis.
this.chart.append('g')
.attr('class', 'lollipops-y-axis')
.attr('transform', `translate(${this.calc.chartWidth}, 0)`)
.call(yAxis);
const thi$ = this;
function showTooltip(d) {
thi$.chart.select('.lollipops-line-' + d.id)
.classed('lollipops-line-mouseover', true);
thi$.chart.select('.lollipops-circle-' + d.id)
.classed('lollipops-circle-mouseover', true)
.attr('r', 6);
tooltip.transition()
.style('opacity', .9);
tooltip.html(`x: ${d.x}, y: ${(d.y * 100).toFixed(1)}%`)
.style('left', (common.xScale(d.x) + 60) + 'px')
.style('top', yScale(d.y) + 'px');
}
function hideTooltip(d) {
thi$.chart.select('.lollipops-line-' + d.id)
.classed('lollipops-line-mouseover', false);
thi$.chart.select('.lollipops-circle-' + d.id)
.classed('lollipops-circle-mouseover', false)
.attr('r', 4);
tooltip.transition()
.style('opacity', 0);
}
// Lines.
this.chart.selectAll('lollipops-line')
.data(data)
.enter()
.append('line')
.attr('class', 'lollipops-line')
.attr('class', d => 'lollipops-line lollipops-line-' + d.id)
.attr('x1', d => common.xScale(d.x))
.attr('x2', d => common.xScale(d.x))
.attr('y1', d => yScale(d.y))
.attr('y2', yScale(yMin));
// Define the div for the tooltip
const tooltip = this._container.append('div')
.attr('class', 'lollipop-tooltip')
.style('opacity', 0);
// Circles.
this.chart.selectAll('lollipops-circle')
.data(data)
.enter()
.append('circle')
.attr('class', d => 'lollipops-circle lollipops-circle-' + d.id)
.attr('cx', d => common.xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', '4');
// Rectangles.
this.chart.selectAll('lollipops-rectangle')
.data(data)
.enter()
.append('rect')
.attr('width', 30)
.attr('height', d => this.calc.chartHeight - yScale(d.y) + 10)
.attr('x', d => common.xScale(d.x) - 15)
.attr('y', d => yScale(d.y) - 10)
.attr('opacity', 0)
.attr('pointer-events', 'all')
.on('mouseover', showTooltip)
.on('mouseout', hideTooltip)
;
}
/**
* @param ts
* @returns {string}
*/
formatDates(ts) {
return moment(ts).format('MMMM Do YYYY');
}
/**
* @param {string} unit
* @returns {*}
*/
getTimeTicksByStr(unit) {
switch (unit) {
case 'months':
return d3.timeMonth.every(4);
case 'quarters':
// It is temporary solution, but it works
// if the difference between edge dates is not
// much more than 10 units.
return d3.timeMonth.every(12);
case 'hours':
return d3.timeHour.every(10);
case 'days':
return d3.timeDay.every(7);
case 'seconds':
return d3.timeSecond.every(10);
case 'years':
return d3.timeYear.every(10);
case 'minutes':
return d3.timeMinute.every(10);
case 'weeks':
return d3.timeWeek.every(10);
case 'milliseconds':
return d3.timeMillisecond.every(10);
default:
return d3.timeYear.every(10);
}
}
/**
* @param {string} key
* @returns {{x: number[], y: number[]}}
*/
getDataPoints(key) {
const dt = [];
const emptyShape = { xs: [], ys: [] };
const data = _.get(this.attrs.data, key, emptyShape);
const len = data.xs.length;
for (let i = 0; i < len; i++) {
const x = data.xs[i];
const y = data.ys[i];
const id = i;
dt.push({ x, y, id });
}
return dt;
}
/**
* @param {string} key
* @param {function} pred
* @returns {{x: number[], y: number[]}}
*/
logFilter(key, pred) {
const xs = [];
const ys = [];
const emptyShape = { xs: [], ys: [] };
const data = _.get(this.attrs.data, key, emptyShape);
for (let i = 0, len = data.xs.length; i < len; i++) {
const x = data.xs[i];
const y = data.ys[i];
if (pred(x, y)) {
xs.push(x);
ys.push(y);
}
}
_.set(this.attrs.data, [key, 'xs'], xs);
_.set(this.attrs.data, [key, 'ys'], ys);
}
/**
* @param {string} key
* @returns {boolean}
*/
hasDate(key) {
const xs = _.get(this.attrs, ['data', key, 'xs']);
return !!_.size(xs);
}
}
/**
* @docs: https://github.com/d3/d3-selection
* @param {object} params
* @param {string} params.selector
* @param {string} params.tag
* @returns {*}
*/
d3.selection.prototype.createObject = function createObject(params) {
const selector = params.selector;
const tag = params.tag;
return this.insert(tag).attr('class', selector);
};
/**
* @docs: https://github.com/d3/d3-selection
* @param {object} params
* @param {string} params.selector
* @param {string} params.tag
* @param {*[]} params.data
* @returns {*}
*/
d3.selection.prototype.createObjectsWithData = function createObjectsWithData(params) {
const selector = params.selector;
const tag = params.tag;
const data = params.data;
return this.selectAll('.' + selector)
.data(data)
.enter()
.insert(tag)
.attr('class', selector);
};

View File

@ -1,81 +0,0 @@
import React, { useEffect } from 'react';
import { useSize } from 'react-use';
import { DistPlotD3 } from './distPlotD3';
/**
* @param min
* @param max
* @returns {number}
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* @param props
* @returns {*}
* @constructor
*/
function DistPlotReact(props) {
const containerRef = React.createRef();
const key = "cdf-chart-react-" + getRandomInt(0, 1000);
const style = !!props.width ? { width: props.width + "px" } : {};
const [sized, { width }] = useSize(() => {
return React.createElement("div", {
key: "resizable-div",
});
}, {
width: props.width,
});
useEffect(() => {
try {
new DistPlotD3()
.set('svgWidth', width)
.set('svgHeight', props.height)
.set('maxX', props.maxX)
.set('minX', props.minX)
.set('onHover', props.onHover)
.set('marginBottom', props.marginBottom || 15)
.set('marginLeft', 30)
.set('marginRight', 30)
.set('marginTop', 5)
.set('showDistributionLines', props.showDistributionLines)
.set('showDistributionYAxis', props.showDistributionYAxis)
.set('verticalLine', props.verticalLine || 110)
.set('showVerticalLine', props.showVerticalLine)
.set('container', containerRef.current)
.set('xScaleType', props.xScale || 'linear')
.set('yScaleType', props.yScale || 'linear')
.set('xScaleTimeOptions', props.timeScale)
.set('yMaxContinuousDomainFactor', props.yMaxContinuousDomainFactor || 1)
.set('yMaxDiscreteDomainFactor', props.yMaxDiscreteDomainFactor || 1)
.data({
continuous: props.continuous,
discrete: props.discrete,
})
.render();
} catch (e) {
console.error("distPlotD3 Error: ", e)
}
});
return React.createElement("div", {
style: {
paddingLeft: "10px",
paddingRight: "10px",
},
}, [
sized,
React.createElement("div", {
key,
style,
ref: containerRef,
}),
]);
}
export default DistPlotReact;

View File

@ -1,208 +0,0 @@
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 500,
"height": 400,
"padding": 5,
"data": [
{
"name": "facet",
"values": [],
"format": { "type": "json", "parse": { "timestamp": "date" } }
},
{
"name": "table",
"source": "facet",
"transform": [
{
"type": "aggregate",
"groupby": ["x"],
"ops": [
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean",
"mean"
],
"fields": [
"p1",
"p5",
"p10",
"p20",
"p30",
"p40",
"p50",
"p60",
"p70",
"p80",
"p90",
"p95",
"p99"
],
"as": [
"p1",
"p5",
"p10",
"p20",
"p30",
"p40",
"p50",
"p60",
"p70",
"p80",
"p90",
"p95",
"p99"
]
}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"nice": true,
"domain": { "data": "facet", "field": "x" },
"range": "width"
},
{
"name": "yscale",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain": { "data": "facet", "field": "p99" }
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"grid": false,
"tickSize": 2,
"encode": {
"grid": { "enter": { "stroke": { "value": "#ccc" } } },
"ticks": { "enter": { "stroke": { "value": "#ccc" } } }
}
},
{
"orient": "left",
"scale": "yscale",
"grid": false,
"domain": false,
"tickSize": 2,
"encode": {
"grid": { "enter": { "stroke": { "value": "#ccc" } } },
"ticks": { "enter": { "stroke": { "value": "#ccc" } } }
}
}
],
"marks": [
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p1" },
"y2": { "scale": "yscale", "field": "p99" },
"opacity": { "value": 0.05 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p5" },
"y2": { "scale": "yscale", "field": "p95" },
"opacity": { "value": 0.1 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p10" },
"y2": { "scale": "yscale", "field": "p90" },
"opacity": { "value": 0.15 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p20" },
"y2": { "scale": "yscale", "field": "p80" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p30" },
"y2": { "scale": "yscale", "field": "p70" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "area",
"from": { "data": "table" },
"encode": {
"enter": { "fill": { "value": "#4C78A8" } },
"update": {
"interpolate": { "value": "monotone" },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p40" },
"y2": { "scale": "yscale", "field": "p60" },
"opacity": { "value": 0.2 }
}
}
},
{
"type": "line",
"from": { "data": "table" },
"encode": {
"update": {
"interpolate": { "value": "monotone" },
"stroke": { "value": "#4C78A8" },
"strokeWidth": { "value": 2 },
"opacity": { "value": 0.8 },
"x": { "scale": "xscale", "field": "x" },
"y": { "scale": "yscale", "field": "p50" }
}
}
}
]
}

View File

@ -1,10 +0,0 @@
.lollipops-line-mouseover {
stroke-dasharray: 4;
animation: dash 2s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: 1000;
}
}

View File

@ -1,31 +0,0 @@
module JS = {
@deriving(abstract)
type numberPresentation = {
value: string,
power: option<float>,
symbol: option<string>,
}
@module("./numberShower.js")
external numberShow: (float, int) => numberPresentation = "numberShow"
}
let sup = {
open CssJs
style(. [ fontSize(#em(0.6)), verticalAlign(#super) ])
}
@react.component
let make = (~number, ~precision) => {
let numberWithPresentation = JS.numberShow(number, precision)
<span>
{JS.valueGet(numberWithPresentation) |> React.string}
{JS.symbolGet(numberWithPresentation) |> R.O.fmapOrNull(React.string)}
{JS.powerGet(numberWithPresentation) |> R.O.fmapOrNull(e =>
<span>
{j`\\u00b710` |> React.string}
<span className=sup> {e |> E.Float.toString |> React.string} </span>
</span>
)}
</span>
}

View File

@ -1,65 +0,0 @@
// 105 -> 3
const orderOfMagnitudeNum = (n) => {
return Math.pow(10, n);
};
// 105 -> 3
const orderOfMagnitude = (n) => {
return Math.floor(Math.log(n) / Math.LN10 + 0.000000001);
};
function withXSigFigs(number, sigFigs) {
const withPrecision = number.toPrecision(sigFigs);
const formatted = Number(withPrecision);
return `${formatted}`;
}
class NumberShower {
constructor(number, precision = 2) {
this.number = number;
this.precision = precision;
}
convert() {
const number = Math.abs(this.number);
const response = this.evaluate(number);
if (this.number < 0) {
response.value = '-' + response.value;
}
return response
}
metricSystem(number, order) {
const newNumber = number / orderOfMagnitudeNum(order);
const precision = this.precision;
return `${withXSigFigs(newNumber, precision)}`;
}
evaluate(number) {
if (number === 0) {
return { value: this.metricSystem(0, 0) }
}
const order = orderOfMagnitude(number);
if (order < -2) {
return { value: this.metricSystem(number, order), power: order };
} else if (order < 4) {
return { value: this.metricSystem(number, 0) };
} else if (order < 6) {
return { value: this.metricSystem(number, 3), symbol: 'K' };
} else if (order < 9) {
return { value: this.metricSystem(number, 6), symbol: 'M' };
} else if (order < 12) {
return { value: this.metricSystem(number, 9), symbol: 'B' };
} else if (order < 15) {
return { value: this.metricSystem(number, 12), symbol: 'T' };
} else {
return { value: this.metricSystem(number, order), power: order };
}
}
}
export function numberShow(number, precision = 2) {
const ns = new NumberShower(number, precision);
return ns.convert();
}

View File

@ -539,7 +539,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-syntax-jsx@^7.16.7":
"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.16.7":
"integrity" "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q=="
"resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz"
"version" "7.16.7"
@ -962,7 +962,7 @@
"@babel/types" "^7.4.4"
"esutils" "^2.0.2"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.4.4", "@babel/runtime@^7.8.4":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.4.4", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
"integrity" "sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ=="
"resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.0.tgz"
"version" "7.17.0"
@ -1020,6 +1020,92 @@
"resolved" "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz"
"version" "3.4.0"
"@discoveryjs/json-ext@^0.5.0":
"integrity" "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA=="
"resolved" "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz"
"version" "0.5.6"
"@emotion/babel-plugin@^11.7.1":
"integrity" "sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ=="
"resolved" "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz"
"version" "11.7.2"
dependencies:
"@babel/helper-module-imports" "^7.12.13"
"@babel/plugin-syntax-jsx" "^7.12.13"
"@babel/runtime" "^7.13.10"
"@emotion/hash" "^0.8.0"
"@emotion/memoize" "^0.7.5"
"@emotion/serialize" "^1.0.2"
"babel-plugin-macros" "^2.6.1"
"convert-source-map" "^1.5.0"
"escape-string-regexp" "^4.0.0"
"find-root" "^1.1.0"
"source-map" "^0.5.7"
"stylis" "4.0.13"
"@emotion/cache@^11.0.0", "@emotion/cache@^11.7.1":
"integrity" "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A=="
"resolved" "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz"
"version" "11.7.1"
dependencies:
"@emotion/memoize" "^0.7.4"
"@emotion/sheet" "^1.1.0"
"@emotion/utils" "^1.0.0"
"@emotion/weak-memoize" "^0.2.5"
"stylis" "4.0.13"
"@emotion/css@^11.0.0":
"integrity" "sha512-RUUgPlMZunlc7SE5A6Hg+VWRzb2cU6O9xlV78KCFgcnl25s7Qz/20oQg71iKudpLqk7xj0vhbJlwcJJMT0BOZg=="
"resolved" "https://registry.npmjs.org/@emotion/css/-/css-11.7.1.tgz"
"version" "11.7.1"
dependencies:
"@emotion/babel-plugin" "^11.7.1"
"@emotion/cache" "^11.7.1"
"@emotion/serialize" "^1.0.0"
"@emotion/sheet" "^1.0.3"
"@emotion/utils" "^1.0.0"
"@emotion/hash@^0.8.0":
"integrity" "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
"resolved" "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz"
"version" "0.8.0"
"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5":
"integrity" "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
"resolved" "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz"
"version" "0.7.5"
"@emotion/serialize@^1.0.0", "@emotion/serialize@^1.0.2":
"integrity" "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A=="
"resolved" "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz"
"version" "1.0.2"
dependencies:
"@emotion/hash" "^0.8.0"
"@emotion/memoize" "^0.7.4"
"@emotion/unitless" "^0.7.5"
"@emotion/utils" "^1.0.0"
"csstype" "^3.0.2"
"@emotion/sheet@^1.0.3", "@emotion/sheet@^1.1.0":
"integrity" "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
"resolved" "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz"
"version" "1.1.0"
"@emotion/unitless@^0.7.5":
"integrity" "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
"resolved" "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz"
"version" "0.7.5"
"@emotion/utils@^1.0.0":
"integrity" "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA=="
"resolved" "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz"
"version" "1.0.0"
"@emotion/weak-memoize@^0.2.5":
"integrity" "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
"resolved" "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz"
"version" "0.2.5"
"@glennsl/bs-jest@^0.5.1":
"integrity" "sha512-+yhWn6uxFt+k61xcWz/xnLC3ticZR5m2d2++a7vXIq2qxiktegBc3ZD/5nvKU8ciFnsHEOoyIzBzoZH2oRGdkw=="
"resolved" "https://registry.npmjs.org/@glennsl/bs-jest/-/bs-jest-0.5.1.tgz"
@ -1319,7 +1405,7 @@
"@parcel/utils" "^1.11.0"
"physical-cpu-count" "^2.0.0"
"@rescript/react@^0.10.0", "@rescript/react@^0.10.1", "@rescript/react@^0.10.3":
"@rescript/react@^0.10.1", "@rescript/react@^0.10.3":
"integrity" "sha512-Lf9rzrR3bQPKJjOK3PBRa/B3xrJ7CqQ1HYr9VHPVxJidarIJJFZBhj0Dg1uZURX+Wg/xiP0PHFxXmdj2bK8Vxw=="
"resolved" "https://registry.npmjs.org/@rescript/react/-/react-0.10.3.tgz"
"version" "0.10.3"
@ -1433,6 +1519,14 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/jest@^27.4.0":
"integrity" "sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ=="
"resolved" "https://registry.npmjs.org/@types/jest/-/jest-27.4.0.tgz"
"version" "27.4.0"
dependencies:
"jest-diff" "^27.0.0"
"pretty-format" "^27.0.0"
"@types/js-cookie@^2.2.6":
"integrity" "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
"resolved" "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz"
@ -1443,7 +1537,17 @@
"resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz"
"version" "7.0.9"
"@types/node@*":
"@types/json5@^0.0.29":
"integrity" "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
"resolved" "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
"version" "0.0.29"
"@types/lodash@^4.14.178":
"integrity" "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
"resolved" "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz"
"version" "4.14.178"
"@types/node@*", "@types/node@^17.0.16":
"integrity" "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA=="
"resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz"
"version" "17.0.16"
@ -1453,6 +1557,11 @@
"resolved" "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz"
"version" "2.4.1"
"@types/parse-json@^4.0.0":
"integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
"resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz"
"version" "4.0.0"
"@types/prettier@^1.19.0":
"integrity" "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ=="
"resolved" "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz"
@ -1468,6 +1577,13 @@
"resolved" "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz"
"version" "1.5.5"
"@types/react-dom@^17.0.11":
"integrity" "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q=="
"resolved" "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz"
"version" "17.0.11"
dependencies:
"@types/react" "*"
"@types/react-slick@^0.23.3":
"integrity" "sha512-SfzSg++/3uyftVZaCgHpW+2fnJFsyJEQ/YdsuqfOWQ5lqUYV/gY/UwAnkw4qksCj5jalto/T5rKXJ8zeFldQeA=="
"resolved" "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.8.tgz"
@ -1475,7 +1591,16 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.9.19":
"@types/react@*", "@types/react@^17.0.39":
"integrity" "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug=="
"resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz"
"version" "17.0.39"
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
"csstype" "^3.0.2"
"@types/react@^16.9.19":
"integrity" "sha512-WngBZLuSkP4IAgPi0HOsGCHo6dn3CcuLQnCfC17VbA7YBgipZiZoTOhObwl/93DsFW0Y2a/ZXeonpW4DxirEJg=="
"resolved" "https://registry.npmjs.org/@types/react/-/react-16.14.23.tgz"
"version" "16.14.23"
@ -1627,6 +1752,23 @@
"@webassemblyjs/ast" "1.11.1"
"@xtuc/long" "4.2.2"
"@webpack-cli/configtest@^1.1.1":
"integrity" "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg=="
"resolved" "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz"
"version" "1.1.1"
"@webpack-cli/info@^1.4.1":
"integrity" "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA=="
"resolved" "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz"
"version" "1.4.1"
dependencies:
"envinfo" "^7.7.3"
"@webpack-cli/serve@^1.6.1":
"integrity" "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw=="
"resolved" "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz"
"version" "1.6.1"
"@xobotyi/scrollbar-width@^1.9.5":
"integrity" "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
"resolved" "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz"
@ -1794,6 +1936,11 @@
dependencies:
"color-convert" "^2.0.1"
"ansi-styles@^5.0.0":
"integrity" "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="
"resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz"
"version" "5.2.0"
"ansi-to-html@^0.6.4":
"integrity" "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ=="
"resolved" "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz"
@ -2151,6 +2298,15 @@
"@babel/types" "^7.3.3"
"@types/babel__traverse" "^7.0.6"
"babel-plugin-macros@^2.6.1":
"integrity" "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg=="
"resolved" "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz"
"version" "2.8.0"
dependencies:
"@babel/runtime" "^7.7.2"
"cosmiconfig" "^6.0.0"
"resolve" "^1.12.0"
"babel-plugin-polyfill-corejs2@^0.3.0":
"integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w=="
"resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz"
@ -2494,11 +2650,13 @@
"bs-moment" "^0.4.4"
"re-classnames" "^4.0.0"
"bs-css-dom@^3.1.0":
"integrity" "sha512-l7jBEsqRnjl2QzW0qW5Nh6n6+R1vjGyOUYCB87ESxkKVD/O4TcDyZH+hN8bTsajxrA7ft+iztu0+kCYzLH7zvA=="
"resolved" "https://registry.npmjs.org/bs-css-dom/-/bs-css-dom-3.1.0.tgz"
"version" "3.1.0"
"bs-css-emotion@^4.1.0":
"integrity" "sha512-1wuxYkvifv5CwF/8cFnSLr9xAFJnqjkRbZPIKbAcR982KJRhmUmiK8XaRQtv1VUEtxDCa5UaXUtEk2Ey8Ce2Tg=="
"resolved" "https://registry.npmjs.org/bs-css-emotion/-/bs-css-emotion-4.1.0.tgz"
"version" "4.1.0"
dependencies:
"@emotion/cache" "^11.0.0"
"@emotion/css" "^11.0.0"
"bs-css" "15.1.0"
"bs-css@^15.1.0", "bs-css@15.1.0":
@ -2734,6 +2892,22 @@
"ansi-styles" "^4.1.0"
"supports-color" "^7.1.0"
"chalk@^4.0.0":
"integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
"resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
"version" "4.1.2"
dependencies:
"ansi-styles" "^4.1.0"
"supports-color" "^7.1.0"
"chalk@^4.1.0":
"integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
"resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
"version" "4.1.2"
dependencies:
"ansi-styles" "^4.1.0"
"supports-color" "^7.1.0"
"chokidar@^2.1.5":
"integrity" "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg=="
"resolved" "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz"
@ -2845,6 +3019,15 @@
"strip-ansi" "^6.0.0"
"wrap-ansi" "^7.0.0"
"clone-deep@^4.0.1":
"integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ=="
"resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz"
"version" "4.0.1"
dependencies:
"is-plain-object" "^2.0.4"
"kind-of" "^6.0.2"
"shallow-clone" "^3.0.0"
"clone@^1.0.2":
"integrity" "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
"resolved" "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz"
@ -2927,6 +3110,11 @@
"color-convert" "^1.9.3"
"color-string" "^1.6.0"
"colorette@^2.0.14":
"integrity" "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g=="
"resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz"
"version" "2.0.16"
"combined-stream@^1.0.6", "combined-stream@~1.0.6":
"integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="
"resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
@ -2964,16 +3152,16 @@
"resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz"
"version" "5.1.0"
"commander@^7.0.0", "commander@7":
"integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
"resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz"
"version" "7.2.0"
"commander@2":
"integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
"resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
"version" "2.20.3"
"commander@7":
"integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
"resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz"
"version" "7.2.0"
"complex.js@2.0.11":
"integrity" "sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw=="
"resolved" "https://registry.npmjs.org/complex.js/-/complex.js-2.0.11.tgz"
@ -3026,7 +3214,7 @@
"resolved" "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz"
"version" "1.0.0"
"convert-source-map@^1.4.0", "convert-source-map@^1.5.1", "convert-source-map@^1.6.0", "convert-source-map@^1.7.0":
"convert-source-map@^1.4.0", "convert-source-map@^1.5.0", "convert-source-map@^1.5.1", "convert-source-map@^1.6.0", "convert-source-map@^1.7.0":
"integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA=="
"resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz"
"version" "1.8.0"
@ -3083,6 +3271,17 @@
"js-yaml" "^3.13.1"
"parse-json" "^4.0.0"
"cosmiconfig@^6.0.0":
"integrity" "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg=="
"resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz"
"version" "6.0.0"
dependencies:
"@types/parse-json" "^4.0.0"
"import-fresh" "^3.1.0"
"parse-json" "^5.0.0"
"path-type" "^4.0.0"
"yaml" "^1.7.2"
"create-ecdh@^4.0.0":
"integrity" "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A=="
"resolved" "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz"
@ -3122,6 +3321,13 @@
"loose-envify" "^1.3.1"
"object-assign" "^4.1.1"
"cross-env@^7.0.3":
"integrity" "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="
"resolved" "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz"
"version" "7.0.3"
dependencies:
"cross-spawn" "^7.0.1"
"cross-spawn@^6.0.0":
"integrity" "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ=="
"resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz"
@ -3144,7 +3350,7 @@
"shebang-command" "^1.2.0"
"which" "^1.2.9"
"cross-spawn@^7.0.0":
"cross-spawn@^7.0.0", "cross-spawn@^7.0.1", "cross-spawn@^7.0.3":
"integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="
"resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
"version" "7.0.3"
@ -3976,6 +4182,11 @@
"resolved" "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz"
"version" "25.2.6"
"diff-sequences@^27.5.1":
"integrity" "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ=="
"resolved" "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz"
"version" "27.5.1"
"diffie-hellman@^5.0.0":
"integrity" "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg=="
"resolved" "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz"
@ -4210,7 +4421,7 @@
dependencies:
"once" "^1.4.0"
"enhanced-resolve@^5.8.3":
"enhanced-resolve@^5.7.0", "enhanced-resolve@^5.8.3":
"integrity" "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA=="
"resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz"
"version" "5.8.3"
@ -4233,7 +4444,7 @@
"resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz"
"version" "2.2.0"
"envinfo@^7.3.1":
"envinfo@^7.3.1", "envinfo@^7.7.3":
"integrity" "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw=="
"resolved" "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz"
"version" "7.8.1"
@ -4324,6 +4535,11 @@
"resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz"
"version" "2.0.0"
"escape-string-regexp@^4.0.0":
"integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
"resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
"version" "4.0.0"
"escodegen@^1.11.0", "escodegen@^1.11.1":
"integrity" "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw=="
"resolved" "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz"
@ -4445,6 +4661,21 @@
"signal-exit" "^3.0.2"
"strip-final-newline" "^2.0.0"
"execa@^5.0.0":
"integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="
"resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
"version" "5.1.1"
dependencies:
"cross-spawn" "^7.0.3"
"get-stream" "^6.0.0"
"human-signals" "^2.1.0"
"is-stream" "^2.0.0"
"merge-stream" "^2.0.0"
"npm-run-path" "^4.0.1"
"onetime" "^5.1.2"
"signal-exit" "^3.0.3"
"strip-final-newline" "^2.0.0"
"exit@^0.1.2":
"integrity" "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
"resolved" "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz"
@ -4580,6 +4811,11 @@
"resolved" "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz"
"version" "1.0.0"
"fastest-levenshtein@^1.0.12":
"integrity" "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow=="
"resolved" "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz"
"version" "1.0.12"
"fastest-stable-stringify@^2.0.2":
"integrity" "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
"resolved" "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz"
@ -4666,6 +4902,11 @@
dependencies:
"to-regex-range" "^5.0.1"
"find-root@^1.1.0":
"integrity" "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
"resolved" "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz"
"version" "1.1.0"
"find-up@^2.1.0":
"integrity" "sha1-RdG35QbHF93UgndaK3eSCjwMV6c="
"resolved" "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz"
@ -4745,19 +4986,6 @@
"resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
"version" "1.0.0"
"fsevents@^1.2.7":
"integrity" "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw=="
"resolved" "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz"
"version" "1.2.13"
dependencies:
"bindings" "^1.5.0"
"nan" "^2.12.1"
"fsevents@^2.1.2", "fsevents@~2.3.2":
"integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="
"resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
"version" "2.3.2"
"function-bind@^1.1.1":
"integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
@ -4816,6 +5044,11 @@
dependencies:
"pump" "^3.0.0"
"get-stream@^6.0.0":
"integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
"resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz"
"version" "6.0.1"
"get-symbol-description@^1.0.0":
"integrity" "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw=="
"resolved" "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz"
@ -5186,6 +5419,11 @@
"resolved" "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz"
"version" "1.1.1"
"human-signals@^2.1.0":
"integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
"resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz"
"version" "2.1.0"
"humanize-url@^1.0.0":
"integrity" "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8="
"resolved" "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz"
@ -5258,6 +5496,14 @@
"caller-path" "^2.0.0"
"resolve-from" "^3.0.0"
"import-fresh@^3.1.0":
"integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="
"resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
"version" "3.3.0"
dependencies:
"parent-module" "^1.0.0"
"resolve-from" "^4.0.0"
"import-local@^3.0.2":
"integrity" "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg=="
"resolved" "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz"
@ -5325,6 +5571,11 @@
"resolved" "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz"
"version" "2.0.3"
"interpret@^2.2.0":
"integrity" "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw=="
"resolved" "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz"
"version" "2.2.0"
"invariant@^2.2.2":
"integrity" "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="
"resolved" "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
@ -5842,6 +6093,16 @@
"jest-get-type" "^25.2.6"
"pretty-format" "^25.5.0"
"jest-diff@^27.0.0":
"integrity" "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw=="
"resolved" "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz"
"version" "27.5.1"
dependencies:
"chalk" "^4.0.0"
"diff-sequences" "^27.5.1"
"jest-get-type" "^27.5.1"
"pretty-format" "^27.5.1"
"jest-docblock@^25.3.0":
"integrity" "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg=="
"resolved" "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz"
@ -5889,6 +6150,11 @@
"resolved" "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz"
"version" "25.2.6"
"jest-get-type@^27.5.1":
"integrity" "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw=="
"resolved" "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz"
"version" "27.5.1"
"jest-haste-map@^25.5.1":
"integrity" "sha512-dddgh9UZjV7SCDQUrQ+5t9yy8iEgKc1AKqZR9YDww8xsVOtzPQSMVLDChc21+g29oTRexb9/B0bIlZL+sWmvAQ=="
"resolved" "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.5.1.tgz"
@ -6494,17 +6760,7 @@
"resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz"
"version" "4.5.0"
"lodash@^4.16.5", "lodash@^4.17.11", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.4", "lodash@^4.17.5", "lodash@4.17.15":
"integrity" "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz"
"version" "4.17.15"
"lodash@^4.17.19":
"integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
"version" "4.17.21"
"lodash@^4.17.21":
"lodash@^4.16.5", "lodash@^4.17.11", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.19", "lodash@^4.17.21", "lodash@^4.17.4", "lodash@^4.17.5":
"integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
"version" "4.17.21"
@ -6841,11 +7097,6 @@
"resolved" "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.7.tgz"
"version" "0.3.7"
"nan@^2.12.1":
"integrity" "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
"resolved" "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz"
"version" "2.15.0"
"nano-css@^5.3.1":
"integrity" "sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg=="
"resolved" "https://registry.npmjs.org/nano-css/-/nano-css-5.3.4.tgz"
@ -7033,7 +7284,7 @@
dependencies:
"path-key" "^2.0.0"
"npm-run-path@^4.0.0":
"npm-run-path@^4.0.0", "npm-run-path@^4.0.1":
"integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="
"resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz"
"version" "4.0.1"
@ -7171,7 +7422,7 @@
dependencies:
"mimic-fn" "^1.0.0"
"onetime@^5.1.0":
"onetime@^5.1.0", "onetime@^5.1.2":
"integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="
"resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
"version" "5.1.2"
@ -7382,6 +7633,13 @@
dependencies:
"parcel-bundler" "^1.12.3"
"parent-module@^1.0.0":
"integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="
"resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
"version" "1.0.1"
dependencies:
"callsites" "^3.0.0"
"parse-asn1@^5.0.0", "parse-asn1@^5.1.5":
"integrity" "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw=="
"resolved" "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz"
@ -8114,6 +8372,15 @@
"ansi-styles" "^4.0.0"
"react-is" "^16.12.0"
"pretty-format@^27.0.0", "pretty-format@^27.5.1":
"integrity" "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="
"resolved" "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz"
"version" "27.5.1"
dependencies:
"ansi-regex" "^5.0.1"
"ansi-styles" "^5.0.0"
"react-is" "^17.0.1"
"pretty-hrtime@^1.0.3":
"integrity" "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="
"resolved" "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz"
@ -9076,7 +9343,7 @@
"lodash.isequal" "^4.5.0"
"prop-types" "^15.7.2"
"react-dom@*", "react-dom@^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0", "react-dom@^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.0", "react-dom@^17.0.2", "react-dom@>= 16.9.0", "react-dom@>=15.0.0", "react-dom@>=16.0.0", "react-dom@>=16.8.1", "react-dom@>=16.9.0":
"react-dom@*", "react-dom@^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0", "react-dom@^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.2", "react-dom@>= 16.9.0", "react-dom@>=15.0.0", "react-dom@>=16.0.0", "react-dom@>=16.8.1", "react-dom@>=16.9.0":
"integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA=="
"resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
"version" "17.0.2"
@ -9100,6 +9367,11 @@
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
"version" "16.13.1"
"react-is@^17.0.1":
"integrity" "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
"resolved" "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
"version" "17.0.2"
"react-lazy-load@^3.0.13":
"integrity" "sha512-eAVNUn3vhNj79Iv04NOCwy/sCLyqDEhL3j9aJKV7VJuRBDg6rCiB+BIWHuG7VXJGCgb//6nX/soR8PTyWRhFvQ=="
"resolved" "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.1.13.tgz"
@ -9160,7 +9432,7 @@
"fast-deep-equal" "^3.1.1"
"vega-embed" "^6.5.1"
"react@*", "react@^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0", "react@^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0", "react@^16 || ^17", "react@^16.8.0 || ^17.0.0", "react@^16.8.0 || ^17.0.0", "react@^17.0.0", "react@>= 16.9.0", "react@>=15.0.0", "react@>=16.0.0", "react@>=16.8.1", "react@>=16.9.0", "react@17.0.2":
"react@*", "react@^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0", "react@^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0", "react@^16 || ^17", "react@^16.8.0 || ^17.0.0", "react@^16.8.0 || ^17.0.0", "react@>= 16.9.0", "react@>=15.0.0", "react@>=16.0.0", "react@>=16.8.1", "react@>=16.9.0", "react@17.0.2":
"integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="
"resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
"version" "17.0.2"
@ -9255,6 +9527,13 @@
"resolved" "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz"
"version" "2.0.0"
"rechoir@^0.7.0":
"integrity" "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg=="
"resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz"
"version" "0.7.1"
dependencies:
"resolve" "^1.9.0"
"reduce-css-calc@^2.1.6":
"integrity" "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg=="
"resolved" "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz"
@ -9433,6 +9712,11 @@
"resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz"
"version" "3.0.0"
"resolve-from@^4.0.0":
"integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
"resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
"version" "4.0.0"
"resolve-from@^5.0.0":
"integrity" "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
"resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz"
@ -9443,7 +9727,7 @@
"resolved" "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz"
"version" "0.2.1"
"resolve@^1.1.10", "resolve@^1.1.5", "resolve@^1.10.0", "resolve@^1.14.2", "resolve@^1.17.0", "resolve@^1.4.0":
"resolve@^1.1.10", "resolve@^1.1.5", "resolve@^1.10.0", "resolve@^1.12.0", "resolve@^1.14.2", "resolve@^1.17.0", "resolve@^1.4.0", "resolve@^1.9.0":
"integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw=="
"resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz"
"version" "1.22.0"
@ -9761,6 +10045,13 @@
"inherits" "^2.0.1"
"safe-buffer" "^5.0.1"
"shallow-clone@^3.0.0":
"integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA=="
"resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz"
"version" "3.0.1"
dependencies:
"kind-of" "^6.0.2"
"shallow-copy@~0.0.1":
"integrity" "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA="
"resolved" "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz"
@ -9814,7 +10105,7 @@
"get-intrinsic" "^1.0.2"
"object-inspect" "^1.9.0"
"signal-exit@^3.0.0", "signal-exit@^3.0.2":
"signal-exit@^3.0.0", "signal-exit@^3.0.2", "signal-exit@^3.0.3":
"integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
"resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"
"version" "3.0.7"
@ -9917,6 +10208,11 @@
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
"version" "0.5.7"
"source-map@^0.5.7":
"integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
"version" "0.5.7"
"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@~0.6.1", "source-map@0.6.1":
"integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
@ -10214,6 +10510,11 @@
dependencies:
"ansi-regex" "^5.0.1"
"strip-bom@^3.0.0":
"integrity" "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
"resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
"version" "3.0.0"
"strip-bom@^4.0.0":
"integrity" "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="
"resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz"
@ -10257,7 +10558,7 @@
"postcss" "^7.0.0"
"postcss-selector-parser" "^3.0.0"
"stylis@^4.0.6":
"stylis@^4.0.6", "stylis@4.0.13":
"integrity" "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
"resolved" "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz"
"version" "4.0.13"
@ -10609,6 +10910,25 @@
"resolved" "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz"
"version" "0.2.0"
"tsconfig-paths-webpack-plugin@^3.5.2":
"integrity" "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw=="
"resolved" "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz"
"version" "3.5.2"
dependencies:
"chalk" "^4.1.0"
"enhanced-resolve" "^5.7.0"
"tsconfig-paths" "^3.9.0"
"tsconfig-paths@^3.9.0":
"integrity" "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg=="
"resolved" "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz"
"version" "3.12.0"
dependencies:
"@types/json5" "^0.0.29"
"json5" "^1.0.1"
"minimist" "^1.2.0"
"strip-bom" "^3.0.0"
"tslib@*", "tslib@^2.1.0", "tslib@~2.3.1":
"integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
"resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz"
@ -10680,6 +11000,11 @@
"resolved" "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
"version" "0.0.6"
"typescript@^4.5.5":
"integrity" "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA=="
"resolved" "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz"
"version" "4.5.5"
"ua-parser-js@^0.7.30":
"integrity" "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ=="
"resolved" "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz"
@ -11320,12 +11645,38 @@
"resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz"
"version" "4.0.2"
"webpack-cli@^4.9.2", "webpack-cli@4.x.x":
"integrity" "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ=="
"resolved" "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz"
"version" "4.9.2"
dependencies:
"@discoveryjs/json-ext" "^0.5.0"
"@webpack-cli/configtest" "^1.1.1"
"@webpack-cli/info" "^1.4.1"
"@webpack-cli/serve" "^1.6.1"
"colorette" "^2.0.14"
"commander" "^7.0.0"
"execa" "^5.0.0"
"fastest-levenshtein" "^1.0.12"
"import-local" "^3.0.2"
"interpret" "^2.2.0"
"rechoir" "^0.7.0"
"webpack-merge" "^5.7.3"
"webpack-merge@^5.7.3":
"integrity" "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q=="
"resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz"
"version" "5.8.0"
dependencies:
"clone-deep" "^4.0.1"
"wildcard" "^2.0.0"
"webpack-sources@^3.2.3":
"integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w=="
"resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz"
"version" "3.2.3"
"webpack@^5.0.0", "webpack@^5.1.0":
"webpack@^5.0.0", "webpack@^5.1.0", "webpack@4.x.x || 5.x.x":
"integrity" "sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g=="
"resolved" "https://registry.npmjs.org/webpack/-/webpack-5.68.0.tgz"
"version" "5.68.0"
@ -11426,6 +11777,11 @@
dependencies:
"isexe" "^2.0.0"
"wildcard@^2.0.0":
"integrity" "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw=="
"resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz"
"version" "2.0.0"
"word-wrap@~1.2.3":
"integrity" "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
"resolved" "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
@ -11526,7 +11882,7 @@
"resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
"version" "4.0.0"
"yaml@^1.10.2":
"yaml@^1.10.2", "yaml@^1.7.2":
"integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
"resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
"version" "1.10.2"