Add prettier and format
This commit is contained in:
parent
f122b5fd7f
commit
15c9fbd13b
5
packages/components/.prettierignore
Normal file
5
packages/components/.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
|||
dist
|
||||
build
|
||||
node_modules
|
||||
storybook-static
|
||||
.storybook
|
1
packages/components/.prettierrc.json
Normal file
1
packages/components/.prettierrc.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
57037
packages/components/package-lock.json
generated
57037
packages/components/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -69,6 +69,7 @@
|
|||
"@storybook/preset-create-react-app": "^4.0.0",
|
||||
"@storybook/react": "^6.4.18",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"prettier": "^2.6.0",
|
||||
"react-codejar": "^1.1.2",
|
||||
"ts-loader": "^9.2.8",
|
||||
"webpack": "^5.70.0",
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Squiggle components"
|
||||
/>
|
||||
<meta name="description" content="Squiggle components" />
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<title>Squiggle Components</title>
|
||||
</head>
|
||||
|
|
|
@ -1,92 +1,96 @@
|
|||
import * as React from 'react';
|
||||
import _ from 'lodash';
|
||||
import type { Spec } from 'vega';
|
||||
import { run } from '@quri/squiggle-lang';
|
||||
import type { DistPlus, SamplingInputs, exportEnv, exportDistribution } from '@quri/squiggle-lang';
|
||||
import { createClassFromSpec } from 'react-vega';
|
||||
import * as chartSpecification from './spec-distributions.json'
|
||||
import * as percentilesSpec from './spec-pertentiles.json'
|
||||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import type { Spec } from "vega";
|
||||
import { run } from "@quri/squiggle-lang";
|
||||
import type {
|
||||
DistPlus,
|
||||
SamplingInputs,
|
||||
exportEnv,
|
||||
exportDistribution,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { createClassFromSpec } from "react-vega";
|
||||
import * as chartSpecification from "./spec-distributions.json";
|
||||
import * as percentilesSpec from "./spec-pertentiles.json";
|
||||
|
||||
let SquiggleVegaChart = createClassFromSpec({'spec': chartSpecification as Spec});
|
||||
let SquiggleVegaChart = createClassFromSpec({
|
||||
spec: chartSpecification as Spec,
|
||||
});
|
||||
|
||||
let SquigglePercentilesChart = createClassFromSpec({'spec': percentilesSpec as Spec});
|
||||
let SquigglePercentilesChart = createClassFromSpec({
|
||||
spec: percentilesSpec as Spec,
|
||||
});
|
||||
|
||||
export interface SquiggleChartProps {
|
||||
/** The input string for squiggle */
|
||||
squiggleString : string,
|
||||
squiggleString: string;
|
||||
|
||||
/** If the output requires monte carlo sampling, the amount of samples */
|
||||
sampleCount? : number,
|
||||
sampleCount?: number;
|
||||
/** The amount of points returned to draw the distribution */
|
||||
outputXYPoints? : number,
|
||||
kernelWidth? : number,
|
||||
pointDistLength? : number,
|
||||
outputXYPoints?: number;
|
||||
kernelWidth?: number;
|
||||
pointDistLength?: number;
|
||||
/** If the result is a function, where the function starts */
|
||||
diagramStart? : number,
|
||||
diagramStart?: number;
|
||||
/** If the result is a function, where the function ends */
|
||||
diagramStop? : number,
|
||||
diagramStop?: number;
|
||||
/** If the result is a function, how many points along the function it samples */
|
||||
diagramCount? : number,
|
||||
diagramCount?: number;
|
||||
/** variables declared before this expression */
|
||||
environment? : exportEnv,
|
||||
environment?: exportEnv;
|
||||
/** When the environment changes */
|
||||
onEnvChange?(env: exportEnv): void
|
||||
onEnvChange?(env: exportEnv): void;
|
||||
}
|
||||
|
||||
export const SquiggleChart : React.FC<SquiggleChartProps> = props => {
|
||||
export const SquiggleChart: React.FC<SquiggleChartProps> = (props) => {
|
||||
let samplingInputs: SamplingInputs = {
|
||||
sampleCount: props.sampleCount,
|
||||
outputXYPoints: props.outputXYPoints,
|
||||
kernelWidth: props.kernelWidth,
|
||||
pointDistLength : props.pointDistLength
|
||||
}
|
||||
|
||||
pointDistLength: props.pointDistLength,
|
||||
};
|
||||
|
||||
let result = run(props.squiggleString, samplingInputs, props.environment);
|
||||
if (result.tag === "Ok") {
|
||||
let environment = result.value.environment
|
||||
let exports = result.value.exports
|
||||
if(props.onEnvChange)
|
||||
props.onEnvChange(environment)
|
||||
let environment = result.value.environment;
|
||||
let exports = result.value.exports;
|
||||
if (props.onEnvChange) props.onEnvChange(environment);
|
||||
let chartResults = exports.map((chartResult: exportDistribution) => {
|
||||
if (chartResult["NAME"] === "Float") {
|
||||
return <MakeNumberShower precision={3} number={chartResult["VAL"]} />;
|
||||
}
|
||||
else if(chartResult["NAME"] === "DistPlus"){
|
||||
} else if (chartResult["NAME"] === "DistPlus") {
|
||||
let shape = chartResult.VAL.pointSetDist;
|
||||
if (shape.tag === "Continuous") {
|
||||
let xyShape = shape.value.xyShape;
|
||||
let totalY = xyShape.ys.reduce((a, b) => a + b);
|
||||
let total = 0;
|
||||
let cdf = xyShape.ys.map(y => {
|
||||
let cdf = xyShape.ys.map((y) => {
|
||||
total += y;
|
||||
return total / totalY;
|
||||
})
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y ]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
|
||||
});
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
x: x,
|
||||
y: y,
|
||||
}));
|
||||
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
data={{"con": values}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
else if(shape.tag === "Discrete"){
|
||||
return <SquiggleVegaChart data={{ con: values }} />;
|
||||
} else if (shape.tag === "Discrete") {
|
||||
let xyShape = shape.value.xyShape;
|
||||
let totalY = xyShape.ys.reduce((a, b) => a + b);
|
||||
let total = 0;
|
||||
let cdf = xyShape.ys.map(y => {
|
||||
let cdf = xyShape.ys.map((y) => {
|
||||
total += y;
|
||||
return total / totalY;
|
||||
})
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x,y]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
|
||||
});
|
||||
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
x: x,
|
||||
y: y,
|
||||
}));
|
||||
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
data={{"dis": values}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
else if(shape.tag === "Mixed"){
|
||||
return <SquiggleVegaChart data={{ dis: values }} />;
|
||||
} else if (shape.tag === "Mixed") {
|
||||
let discreteShape = shape.value.discrete.xyShape;
|
||||
let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
|
||||
|
||||
|
@ -95,141 +99,150 @@ export const SquiggleChart : React.FC<SquiggleChartProps> = props => {
|
|||
let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
|
||||
|
||||
interface labeledPoint {
|
||||
x: number,
|
||||
y: number,
|
||||
type: "discrete" | "continuous"
|
||||
};
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
|
||||
let markedDisPoints : labeledPoint[] = discretePoints.map(([x,y]) => ({x: x, y: y, type: "discrete"}))
|
||||
let markedConPoints : labeledPoint[] = continuousPoints.map(([x,y]) => ({x: x, y: y, type: "continuous"}))
|
||||
let markedDisPoints: labeledPoint[] = discretePoints.map(
|
||||
([x, y]) => ({ x: x, y: y, type: "discrete" })
|
||||
);
|
||||
let markedConPoints: labeledPoint[] = continuousPoints.map(
|
||||
([x, y]) => ({ x: x, y: y, type: "continuous" })
|
||||
);
|
||||
|
||||
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), 'x')
|
||||
let sortedPoints = _.sortBy(
|
||||
markedDisPoints.concat(markedConPoints),
|
||||
"x"
|
||||
);
|
||||
|
||||
let totalContinuous = 1 - totalDiscrete;
|
||||
let totalY = continuousShape.ys.reduce((a:number, b:number) => a + b);
|
||||
let totalY = continuousShape.ys.reduce(
|
||||
(a: number, b: number) => a + b
|
||||
);
|
||||
|
||||
let total = 0;
|
||||
let cdf = sortedPoints.map((point: labeledPoint) => {
|
||||
if (point.type == "discrete") {
|
||||
total += point.y;
|
||||
return total;
|
||||
}
|
||||
else if (point.type == "continuous") {
|
||||
total += point.y / totalY * totalContinuous;
|
||||
} else if (point.type == "continuous") {
|
||||
total += (point.y / totalY) * totalContinuous;
|
||||
return total;
|
||||
}
|
||||
});
|
||||
|
||||
interface cdfLabeledPoint {
|
||||
cdf: string,
|
||||
x: number,
|
||||
y: number,
|
||||
type: "discrete" | "continuous"
|
||||
cdf: string;
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
let cdfLabeledPoint : cdfLabeledPoint[] = _.zipWith(cdf, sortedPoints, (c: number, point: labeledPoint) => ({...point, cdf: (c * 100).toFixed(2) + "%"}))
|
||||
let continuousValues = cdfLabeledPoint.filter(x => x.type == "continuous")
|
||||
let discreteValues = cdfLabeledPoint.filter(x => x.type == "discrete")
|
||||
let cdfLabeledPoint: cdfLabeledPoint[] = _.zipWith(
|
||||
cdf,
|
||||
sortedPoints,
|
||||
(c: number, point: labeledPoint) => ({
|
||||
...point,
|
||||
cdf: (c * 100).toFixed(2) + "%",
|
||||
})
|
||||
);
|
||||
let continuousValues = cdfLabeledPoint.filter(
|
||||
(x) => x.type == "continuous"
|
||||
);
|
||||
let discreteValues = cdfLabeledPoint.filter(
|
||||
(x) => x.type == "discrete"
|
||||
);
|
||||
|
||||
return (
|
||||
<SquiggleVegaChart
|
||||
data={{"con": continuousValues, "dis": discreteValues}}
|
||||
data={{ con: continuousValues, dis: discreteValues }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(chartResult.NAME === "Function"){
|
||||
} else if (chartResult.NAME === "Function") {
|
||||
// We are looking at a function. In this case, we draw a Percentiles chart
|
||||
let start = props.diagramStart ? props.diagramStart : 0
|
||||
let stop = props.diagramStop ? props.diagramStop : 10
|
||||
let count = props.diagramCount ? props.diagramCount : 0.1
|
||||
let step = (stop - start)/ count
|
||||
let data = _.range(start, stop, step).map(x => {
|
||||
let start = props.diagramStart ? props.diagramStart : 0;
|
||||
let stop = props.diagramStop ? props.diagramStop : 10;
|
||||
let count = props.diagramCount ? props.diagramCount : 0.1;
|
||||
let step = (stop - start) / count;
|
||||
let data = _.range(start, stop, step).map((x) => {
|
||||
if (chartResult.NAME == "Function") {
|
||||
let result = chartResult.VAL(x);
|
||||
if (result.tag == "Ok") {
|
||||
let 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
|
||||
]
|
||||
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,
|
||||
];
|
||||
|
||||
let percentiles = getPercentiles(percentileArray, result.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]
|
||||
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 <SquigglePercentilesChart data={{"facet": data}} />
|
||||
});
|
||||
return <SquigglePercentilesChart data={{ facet: data }} />;
|
||||
}
|
||||
})
|
||||
});
|
||||
return <>{chartResults}</>;
|
||||
}
|
||||
else if(result.tag == "Error") {
|
||||
} else if (result.tag == "Error") {
|
||||
// At this point, we came across an error. What was our error?
|
||||
return (<p>{"Error parsing Squiggle: " + result.value}</p>)
|
||||
|
||||
return <p>{"Error parsing Squiggle: " + result.value}</p>;
|
||||
}
|
||||
return (<p>{"Invalid Response"}</p>)
|
||||
return <p>{"Invalid Response"}</p>;
|
||||
};
|
||||
|
||||
function getPercentiles(percentiles: number[], t: DistPlus) {
|
||||
if (t.pointSetDist.tag == "Discrete") {
|
||||
let total = 0;
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs)
|
||||
let bounds = percentiles.map(_ => maxX);
|
||||
_.zipWith(t.pointSetDist.value.xyShape.xs,t.pointSetDist.value.xyShape.ys, (x,y) => {
|
||||
total += y
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs);
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
_.zipWith(
|
||||
t.pointSetDist.value.xyShape.xs,
|
||||
t.pointSetDist.value.xyShape.ys,
|
||||
(x, y) => {
|
||||
total += y;
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] == maxX) {
|
||||
bounds[i] = x
|
||||
bounds[i] = x;
|
||||
}
|
||||
})
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
else if(t.pointSetDist.tag == "Continuous"){
|
||||
);
|
||||
return bounds;
|
||||
} else if (t.pointSetDist.tag == "Continuous") {
|
||||
let total = 0;
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs)
|
||||
let totalY = _.sum(t.pointSetDist.value.xyShape.ys)
|
||||
let bounds = percentiles.map(_ => maxX);
|
||||
_.zipWith(t.pointSetDist.value.xyShape.xs,t.pointSetDist.value.xyShape.ys, (x,y) => {
|
||||
let maxX = _.max(t.pointSetDist.value.xyShape.xs);
|
||||
let totalY = _.sum(t.pointSetDist.value.xyShape.ys);
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
_.zipWith(
|
||||
t.pointSetDist.value.xyShape.xs,
|
||||
t.pointSetDist.value.xyShape.ys,
|
||||
(x, y) => {
|
||||
total += y / totalY;
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] == maxX) {
|
||||
bounds[i] = x
|
||||
bounds[i] = x;
|
||||
}
|
||||
})
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
else if(t.pointSetDist.tag == "Mixed"){
|
||||
);
|
||||
return bounds;
|
||||
} else if (t.pointSetDist.tag == "Mixed") {
|
||||
let discreteShape = t.pointSetDist.value.discrete.xyShape;
|
||||
let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
|
||||
|
||||
|
@ -238,58 +251,65 @@ function getPercentiles(percentiles:number[], t : DistPlus) {
|
|||
let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
|
||||
|
||||
interface labeledPoint {
|
||||
x: number,
|
||||
y: number,
|
||||
type: "discrete" | "continuous"
|
||||
};
|
||||
x: number;
|
||||
y: number;
|
||||
type: "discrete" | "continuous";
|
||||
}
|
||||
|
||||
let markedDisPoints : labeledPoint[] = discretePoints.map(([x,y]) => ({x: x, y: y, type: "discrete"}))
|
||||
let markedConPoints : labeledPoint[] = continuousPoints.map(([x,y]) => ({x: x, y: y, type: "continuous"}))
|
||||
let markedDisPoints: labeledPoint[] = discretePoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "discrete",
|
||||
}));
|
||||
let markedConPoints: labeledPoint[] = continuousPoints.map(([x, y]) => ({
|
||||
x: x,
|
||||
y: y,
|
||||
type: "continuous",
|
||||
}));
|
||||
|
||||
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), 'x')
|
||||
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), "x");
|
||||
|
||||
let totalContinuous = 1 - totalDiscrete;
|
||||
let totalY = continuousShape.ys.reduce((a: number, b: number) => a + b);
|
||||
|
||||
let total = 0;
|
||||
let maxX = _.max(sortedPoints.map(x => x.x));
|
||||
let bounds = percentiles.map(_ => maxX);
|
||||
let maxX = _.max(sortedPoints.map((x) => x.x));
|
||||
let bounds = percentiles.map((_) => maxX);
|
||||
sortedPoints.map((point: labeledPoint) => {
|
||||
if (point.type == "discrete") {
|
||||
total += point.y;
|
||||
}
|
||||
else if (point.type == "continuous") {
|
||||
total += point.y / totalY * totalContinuous;
|
||||
} else if (point.type == "continuous") {
|
||||
total += (point.y / totalY) * totalContinuous;
|
||||
}
|
||||
percentiles.forEach((v, i) => {
|
||||
if (total > v && bounds[i] == maxX) {
|
||||
bounds[i] = total;
|
||||
}
|
||||
})
|
||||
});
|
||||
return total;
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
|
||||
function MakeNumberShower(props: {number: number, precision :number}){
|
||||
function MakeNumberShower(props: { number: number; precision: number }) {
|
||||
let numberWithPresentation = numberShow(props.number, props.precision);
|
||||
return (
|
||||
<span>
|
||||
{numberWithPresentation.value}
|
||||
{numberWithPresentation.symbol}
|
||||
{numberWithPresentation.power ?
|
||||
{numberWithPresentation.power ? (
|
||||
<span>
|
||||
{'\u00b710'}
|
||||
{"\u00b710"}
|
||||
<span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
|
||||
{numberWithPresentation.power}
|
||||
</span>
|
||||
</span>
|
||||
: <></>}
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</span>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
const orderOfMagnitudeNum = (n: number) => {
|
||||
|
@ -308,8 +328,8 @@ function withXSigFigs(number:number, sigFigs:number) {
|
|||
}
|
||||
|
||||
class NumberShower {
|
||||
number: number
|
||||
precision: number
|
||||
number: number;
|
||||
precision: number;
|
||||
|
||||
constructor(number: number, precision = 2) {
|
||||
this.number = number;
|
||||
|
@ -320,9 +340,9 @@ class NumberShower {
|
|||
const number = Math.abs(this.number);
|
||||
const response = this.evaluate(number);
|
||||
if (this.number < 0) {
|
||||
response.value = '-' + response.value;
|
||||
response.value = "-" + response.value;
|
||||
}
|
||||
return response
|
||||
return response;
|
||||
}
|
||||
|
||||
metricSystem(number: number, order: number) {
|
||||
|
@ -333,7 +353,7 @@ class NumberShower {
|
|||
|
||||
evaluate(number: number) {
|
||||
if (number === 0) {
|
||||
return { value: this.metricSystem(0, 0) }
|
||||
return { value: this.metricSystem(0, 0) };
|
||||
}
|
||||
|
||||
const order = orderOfMagnitude(number);
|
||||
|
@ -342,13 +362,13 @@ class NumberShower {
|
|||
} else if (order < 4) {
|
||||
return { value: this.metricSystem(number, 0) };
|
||||
} else if (order < 6) {
|
||||
return { value: this.metricSystem(number, 3), symbol: 'K' };
|
||||
return { value: this.metricSystem(number, 3), symbol: "K" };
|
||||
} else if (order < 9) {
|
||||
return { value: this.metricSystem(number, 6), symbol: 'M' };
|
||||
return { value: this.metricSystem(number, 6), symbol: "M" };
|
||||
} else if (order < 12) {
|
||||
return { value: this.metricSystem(number, 9), symbol: 'B' };
|
||||
return { value: this.metricSystem(number, 9), symbol: "B" };
|
||||
} else if (order < 15) {
|
||||
return { value: this.metricSystem(number, 12), symbol: 'T' };
|
||||
return { value: this.metricSystem(number, 12), symbol: "T" };
|
||||
} else {
|
||||
return { value: this.metricSystem(number, order), power: order };
|
||||
}
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { SquiggleChart } from './SquiggleChart'
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import { SquiggleChart } from "./SquiggleChart";
|
||||
import { ReactCodeJar } from "react-codejar";
|
||||
import type { exportEnv } from '@quri/squiggle-lang'
|
||||
|
||||
import type { exportEnv } from "@quri/squiggle-lang";
|
||||
|
||||
export interface SquiggleEditorProps {
|
||||
/** The input string for squiggle */
|
||||
initialSquiggleString? : string,
|
||||
|
||||
initialSquiggleString?: string;
|
||||
/** If the output requires monte carlo sampling, the amount of samples */
|
||||
sampleCount? : number,
|
||||
sampleCount?: number;
|
||||
/** The amount of points returned to draw the distribution */
|
||||
outputXYPoints? : number,
|
||||
kernelWidth? : number,
|
||||
pointDistLength? : number,
|
||||
outputXYPoints?: number;
|
||||
kernelWidth?: number;
|
||||
pointDistLength?: number;
|
||||
/** If the result is a function, where the function starts */
|
||||
diagramStart? : number,
|
||||
diagramStart?: number;
|
||||
/** If the result is a function, where the function ends */
|
||||
diagramStop? : number,
|
||||
diagramStop?: number;
|
||||
/** If the result is a function, how many points along the function it samples */
|
||||
diagramCount? : number,
|
||||
diagramCount?: number;
|
||||
/** The environment, other variables that were already declared */
|
||||
environment?: exportEnv,
|
||||
environment?: exportEnv;
|
||||
/** when the environment changes. Used again for notebook magic*/
|
||||
onEnvChange?(env: exportEnv) : void
|
||||
onEnvChange?(env: exportEnv): void;
|
||||
}
|
||||
|
||||
const highlight = (editor: HTMLInputElement) => {
|
||||
|
@ -34,26 +32,28 @@ const highlight = (editor: HTMLInputElement) => {
|
|||
};
|
||||
|
||||
interface SquiggleEditorState {
|
||||
expression: string,
|
||||
env: exportEnv
|
||||
expression: string;
|
||||
env: exportEnv;
|
||||
}
|
||||
|
||||
export class SquiggleEditor extends React.Component<SquiggleEditorProps, SquiggleEditorState>{
|
||||
export class SquiggleEditor extends React.Component<
|
||||
SquiggleEditorProps,
|
||||
SquiggleEditorState
|
||||
> {
|
||||
constructor(props: SquiggleEditorProps) {
|
||||
super(props)
|
||||
let code = props.initialSquiggleString ? props.initialSquiggleString : ""
|
||||
this.state = {expression: code, env: props.environment }
|
||||
|
||||
super(props);
|
||||
let code = props.initialSquiggleString ? props.initialSquiggleString : "";
|
||||
this.state = { expression: code, env: props.environment };
|
||||
}
|
||||
render() {
|
||||
let {expression, env} = this.state
|
||||
let props = this.props
|
||||
let { expression, env } = this.state;
|
||||
let props = this.props;
|
||||
return (
|
||||
<div>
|
||||
<ReactCodeJar
|
||||
code={expression}
|
||||
onUpdate={e => {
|
||||
this.setState({expression: e})
|
||||
onUpdate={(e) => {
|
||||
this.setState({ expression: e });
|
||||
}}
|
||||
style={{
|
||||
borderRadius: "6px",
|
||||
|
@ -65,7 +65,7 @@ export class SquiggleEditor extends React.Component<SquiggleEditorProps, Squiggl
|
|||
letterSpacing: "normal",
|
||||
lineHeight: "20px",
|
||||
padding: "10px",
|
||||
tabSize: "4"
|
||||
tabSize: "4",
|
||||
}}
|
||||
highlight={highlight}
|
||||
lineNumbers={false}
|
||||
|
@ -83,21 +83,25 @@ export class SquiggleEditor extends React.Component<SquiggleEditorProps, Squiggl
|
|||
onEnvChange={props.onEnvChange}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function renderSquiggleEditor(props: SquiggleEditorProps) {
|
||||
let parent = document.createElement("div")
|
||||
ReactDOM.render(<SquiggleEditor {...props} onEnvChange={env => {
|
||||
|
||||
let parent = document.createElement("div");
|
||||
ReactDOM.render(
|
||||
<SquiggleEditor
|
||||
{...props}
|
||||
onEnvChange={(env) => {
|
||||
// I can set the value here because I need it for creating notebooks
|
||||
// @ts-ignore
|
||||
parent.value = env
|
||||
parent.value = env;
|
||||
|
||||
parent.dispatchEvent(new CustomEvent("input"))
|
||||
if(props.onEnvChange)
|
||||
props.onEnvChange(env)
|
||||
}} /> , parent)
|
||||
return parent
|
||||
parent.dispatchEvent(new CustomEvent("input"));
|
||||
if (props.onEnvChange) props.onEnvChange(env);
|
||||
}}
|
||||
/>,
|
||||
parent
|
||||
);
|
||||
return parent;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export { SquiggleChart } from './SquiggleChart';
|
||||
export { SquiggleEditor, renderSquiggleEditor } from './SquiggleEditor';
|
||||
export { SquiggleChart } from "./SquiggleChart";
|
||||
export { SquiggleEditor, renderSquiggleEditor } from "./SquiggleEditor";
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
}
|
||||
],
|
||||
|
||||
"scales": [{
|
||||
"scales": [
|
||||
{
|
||||
"name": "xscale",
|
||||
"type": "pow",
|
||||
"exponent": { "signal": "xscale" },
|
||||
|
@ -48,7 +49,8 @@
|
|||
{ "data": "dis", "field": "x" }
|
||||
]
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"name": "yscale",
|
||||
"type": "pow",
|
||||
"exponent": { "signal": "yscale" },
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Meta } from '@storybook/addon-docs';
|
||||
import { Meta } from "@storybook/addon-docs";
|
||||
|
||||
<Meta title="Squiggle/Introduction" />
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { SquiggleChart } from '../SquiggleChart'
|
||||
import { Canvas, Meta, Story, Props } from '@storybook/addon-docs';
|
||||
import { SquiggleChart } from "../SquiggleChart";
|
||||
import { Canvas, Meta, Story, Props } from "@storybook/addon-docs";
|
||||
|
||||
<Meta title="Squiggle/SquiggleChart" component={SquiggleChart} />
|
||||
|
||||
export const Template = SquiggleChart
|
||||
export const Template = SquiggleChart;
|
||||
|
||||
# Squiggle Chart
|
||||
|
||||
|
@ -19,53 +19,62 @@ could be continuous, discrete or mixed.
|
|||
## Distributions
|
||||
|
||||
An example of a normal distribution is:
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Normal"
|
||||
args={{
|
||||
squiggleString: "normal(5,2)"
|
||||
}}>
|
||||
squiggleString: "normal(5,2)",
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
|
||||
An example of a Discrete distribution is:
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Discrete"
|
||||
args={{
|
||||
squiggleString: "mm(0, 1, [0.5, 0.5])"
|
||||
}}>
|
||||
squiggleString: "mm(0, 1, [0.5, 0.5])",
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
An example of a Mixed distribution is:
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Mixed"
|
||||
args={{
|
||||
squiggleString: "mm(0, 5 to 10, [0.5, 0.5])"
|
||||
}}>
|
||||
squiggleString: "mm(0, 5 to 10, [0.5, 0.5])",
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
## Constants
|
||||
|
||||
A constant is a simple number as a result. This has special formatting rules
|
||||
to allow large and small numbers being printed cleanly.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Constant"
|
||||
args={{
|
||||
squiggleString: "500000 * 5000000"
|
||||
}}>
|
||||
squiggleString: "500000 * 5000000",
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
## Functions
|
||||
|
||||
Finally, a function can be returned, and this shows how the distribution changes
|
||||
over the axis between x = 0 and 10.
|
||||
|
||||
|
@ -73,8 +82,9 @@ over the axis between x = 0 and 10.
|
|||
<Story
|
||||
name="Function"
|
||||
args={{
|
||||
squiggleString: "f(x) = normal(x,x)\nf"
|
||||
}}>
|
||||
squiggleString: "f(x) = normal(x,x)\nf",
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
const path = require('path');
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
entry: './src/index.ts',
|
||||
mode: "production",
|
||||
devtool: "source-map",
|
||||
entry: "./src/index.ts",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
use: "ts-loader",
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.tsx', '.ts'],
|
||||
extensions: [".js", ".tsx", ".ts"],
|
||||
},
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: "bundle.js",
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
library: {
|
||||
name: 'squiggle_components',
|
||||
type: 'umd',
|
||||
name: "squiggle_components",
|
||||
type: "umd",
|
||||
},
|
||||
},
|
||||
devServer: {
|
||||
static: {
|
||||
directory: path.join(__dirname, 'public'),
|
||||
directory: path.join(__dirname, "public"),
|
||||
},
|
||||
compress: true,
|
||||
port: 9000,
|
||||
|
|
|
@ -14370,6 +14370,11 @@ prepend-http@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18"
|
||||
integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==
|
||||
|
||||
prettier@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.0.tgz#12f8f504c4d8ddb76475f441337542fa799207d4"
|
||||
integrity sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==
|
||||
|
||||
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
|
||||
|
|
Loading…
Reference in New Issue
Block a user