From 9cbeee04515c7f290a80ff39981c51d4ffbfef59 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Tue, 12 Jul 2022 17:09:24 +1000 Subject: [PATCH 01/16] Add multiple plotting --- .../src/components/DistributionChart.tsx | 76 +++++++++++++++--- .../src/components/SquiggleItem.tsx | 17 +++- .../src/lib/distributionSpecBuilder.ts | 79 +++++++++++++------ 3 files changed, 135 insertions(+), 37 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index af644d29..0b9535b2 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -4,6 +4,7 @@ import { result, distributionError, distributionErrorToString, + squiggleExpression, } from "@quri/squiggle-lang"; import { Vega } from "react-vega"; import { ErrorAlert } from "./Alert"; @@ -23,16 +24,58 @@ export type DistributionPlottingSettings = { showControls: boolean; } & DistributionChartSpecOptions; +export type Plot = { + distributions: Distribution[]; +}; + export type DistributionChartProps = { - distribution: Distribution; + plot: Plot; width?: number; height: number; actions?: boolean; } & DistributionPlottingSettings; +export function defaultPlot(distribution: Distribution): Plot { + return { distributions: [distribution] }; +} +export function makePlot(expression: { + [key: string]: squiggleExpression; +}): Plot | void { + if (expression["distributions"].tag === "array") { + let distributions: Distribution[] = expression["distributions"].value + .map((x) => { + if (x.tag === "distribution") { + return x.value; + } + }) + .filter((x): x is Distribution => x !== undefined); + return { distributions }; + } +} +function all(arr: boolean[]): boolean { + return arr.reduce((x, y) => x && y, true); +} + +function flattenResult(x: result[]): result { + if (x.length === 0) { + return { tag: "Ok", value: [] }; + } else { + if (x[0].tag === "Error") { + return x[0]; + } else { + let rest = flattenResult(x.splice(1)); + if (rest.tag === "Error") { + return rest; + } else { + return { tag: "Ok", value: [x[0].value].concat(rest.value) }; + } + } + } +} + export const DistributionChart: React.FC = (props) => { const { - distribution, + plot, height, showSummary, width, @@ -47,19 +90,23 @@ export const DistributionChart: React.FC = (props) => { React.useEffect(() => setLogX(logX), [logX]); React.useEffect(() => setExpY(expY), [expY]); - const shape = distribution.pointSet(); const [sized] = useSize((size) => { - if (shape.tag === "Error") { + let shapes = flattenResult(plot.distributions.map((x) => x.pointSet())); + if (shapes.tag === "Error") { return ( - {distributionErrorToString(shape.value)} + {distributionErrorToString(shapes.value)} ); } - const massBelow0 = - shape.value.continuous.some((x) => x.x <= 0) || - shape.value.discrete.some((x) => x.x <= 0); + const massBelow0 = all( + shapes.value.map( + (shape) => + shape.continuous.some((x) => x.x <= 0) || + shape.discrete.some((x) => x.x <= 0) + ) + ); const spec = buildVegaSpec(props); let widthProp = width ? width : size.width; @@ -69,13 +116,20 @@ export const DistributionChart: React.FC = (props) => { ); widthProp = 20; } + let continuousPoints = shapes.value.flatMap((shape, i) => + shape.continuous.map((point) => ({ ...point, name: i + 1 })) + ); + let discretePoints = shapes.value.flatMap((shape, i) => + shape.discrete.map((point) => ({ ...point, name: i + 1 })) + ); + console.log(continuousPoints); return (
{!(isLogX && massBelow0) ? ( = (props) => { )}
- {showSummary && } + {showSummary && plot.distributions.length == 1 && ( + + )}
{showControls && (
diff --git a/packages/components/src/components/SquiggleItem.tsx b/packages/components/src/components/SquiggleItem.tsx index 48a8a0fb..09b9fa27 100644 --- a/packages/components/src/components/SquiggleItem.tsx +++ b/packages/components/src/components/SquiggleItem.tsx @@ -8,6 +8,8 @@ import { NumberShower } from "./NumberShower"; import { DistributionChart, DistributionPlottingSettings, + makePlot, + defaultPlot, } from "./DistributionChart"; import { FunctionChart, FunctionChartSettings } from "./FunctionChart"; @@ -102,7 +104,7 @@ export const SquiggleItem: React.FC = ({
{expression.value.toString()}
) : null} = ({ ); case "record": + let plot = makePlot(expression.value); + if (plot) { + return ( + + ); + } return (
@@ -246,7 +259,7 @@ export const SquiggleItem: React.FC = ({
{Object.entries(expression.value) - .filter(([key, r]) => key !== "Math") + .filter(([key, _]) => key !== "Math") .map(([key, r]) => (
diff --git a/packages/components/src/lib/distributionSpecBuilder.ts b/packages/components/src/lib/distributionSpecBuilder.ts index 4286dbdb..515a1b9f 100644 --- a/packages/components/src/lib/distributionSpecBuilder.ts +++ b/packages/components/src/lib/distributionSpecBuilder.ts @@ -137,7 +137,21 @@ export function buildVegaSpec( }, ], signals: [], - scales: [xScale, expY ? expYScale : linearYScale], + scales: [ + xScale, + expY ? expYScale : linearYScale, + { + name: "color", + type: "ordinal", + domain: { + fields: [ + { data: "con", field: "name" }, + { data: "dis", field: "name" }, + ], + }, + range: { scheme: "category20b" }, + }, + ], axes: [ { orient: "bottom", @@ -153,33 +167,48 @@ export function buildVegaSpec( ], marks: [ { - type: "area", + name: "group", + type: "group", from: { - data: "con", - }, - encode: { - update: { - interpolate: { value: "linear" }, - x: { - scale: "xscale", - field: "x", - }, - y: { - scale: "yscale", - field: "y", - }, - y2: { - scale: "yscale", - value: 0, - }, - fill: { - value: color, - }, - fillOpacity: { - value: 1, - }, + facet: { + name: "faceted_path_main", + data: "con", + groupby: ["name"], }, }, + marks: [ + { + name: "distribution_charts", + type: "area", + from: { + data: "faceted_path_main", + }, + encode: { + update: { + interpolate: { value: "linear" }, + x: { + scale: "xscale", + field: "x", + }, + y: { + scale: "yscale", + field: "y", + }, + y2: { + scale: "yscale", + value: 0, + }, + fill: { + field: "name", + scale: "color", + }, + fillOpacity: { + value: 1, + }, + }, + }, + }, + ], }, { type: "rect", From 98ae0459c96765126e530918ab1e8494bc870fd1 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Wed, 13 Jul 2022 14:15:07 +1000 Subject: [PATCH 02/16] Refactor specification to include discrete --- .../src/components/DistributionChart.tsx | 48 +++- .../src/components/FunctionChart1Dist.tsx | 3 +- .../src/lib/distributionSpecBuilder.ts | 267 ++++++++---------- 3 files changed, 157 insertions(+), 161 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 0b9535b2..f1253629 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -5,6 +5,7 @@ import { distributionError, distributionErrorToString, squiggleExpression, + resultMap, } from "@quri/squiggle-lang"; import { Vega } from "react-vega"; import { ErrorAlert } from "./Alert"; @@ -24,8 +25,10 @@ export type DistributionPlottingSettings = { showControls: boolean; } & DistributionChartSpecOptions; +export type LabeledDistribution = { name: string; distribution: Distribution }; + export type Plot = { - distributions: Distribution[]; + distributions: LabeledDistribution[]; }; export type DistributionChartProps = { @@ -36,19 +39,29 @@ export type DistributionChartProps = { } & DistributionPlottingSettings; export function defaultPlot(distribution: Distribution): Plot { - return { distributions: [distribution] }; + return { distributions: [{ name: "default", distribution }] }; } + export function makePlot(expression: { [key: string]: squiggleExpression; }): Plot | void { if (expression["distributions"].tag === "array") { - let distributions: Distribution[] = expression["distributions"].value + let distributions: LabeledDistribution[] = expression["distributions"].value .map((x) => { - if (x.tag === "distribution") { - return x.value; + if ( + x.tag === "record" && + x.value["name"] && + x.value["name"].tag === "string" && + x.value["distribution"] && + x.value["distribution"].tag === "distribution" + ) { + return { + name: x.value["name"].value, + distribution: x.value["distribution"].value, + }; } }) - .filter((x): x is Distribution => x !== undefined); + .filter((x): x is LabeledDistribution => x !== undefined); return { distributions }; } } @@ -91,7 +104,15 @@ export const DistributionChart: React.FC = (props) => { React.useEffect(() => setExpY(expY), [expY]); const [sized] = useSize((size) => { - let shapes = flattenResult(plot.distributions.map((x) => x.pointSet())); + let shapes = flattenResult( + plot.distributions.map((x) => + resultMap(x.distribution.pointSet(), (shape) => ({ + name: x.name, + continuous: shape.continuous, + discrete: shape.discrete, + })) + ) + ); if (shapes.tag === "Error") { return ( @@ -116,20 +137,17 @@ export const DistributionChart: React.FC = (props) => { ); widthProp = 20; } - let continuousPoints = shapes.value.flatMap((shape, i) => - shape.continuous.map((point) => ({ ...point, name: i + 1 })) - ); - let discretePoints = shapes.value.flatMap((shape, i) => - shape.discrete.map((point) => ({ ...point, name: i + 1 })) + const domain = shapes.value.flatMap((shape) => + shape.discrete.concat(shape.continuous) ); + console.log(shapes.value); - console.log(continuousPoints); return (
{!(isLogX && massBelow0) ? ( = (props) => { )}
{showSummary && plot.distributions.length == 1 && ( - + )}
{showControls && ( diff --git a/packages/components/src/components/FunctionChart1Dist.tsx b/packages/components/src/components/FunctionChart1Dist.tsx index 650d2753..3b203de5 100644 --- a/packages/components/src/components/FunctionChart1Dist.tsx +++ b/packages/components/src/components/FunctionChart1Dist.tsx @@ -16,6 +16,7 @@ import * as percentilesSpec from "../vega-specs/spec-percentiles.json"; import { DistributionChart, DistributionPlottingSettings, + defaultPlot, } from "./DistributionChart"; import { NumberShower } from "./NumberShower"; import { ErrorAlert } from "./Alert"; @@ -177,7 +178,7 @@ export const FunctionChart1Dist: React.FC = ({ let showChart = mouseItem.tag === "Ok" && mouseItem.value.tag === "distribution" ? ( Date: Wed, 13 Jul 2022 15:29:39 +1000 Subject: [PATCH 03/16] Make parser of distributions stricter --- .../src/components/DistributionChart.tsx | 116 +++++++++++++++--- 1 file changed, 97 insertions(+), 19 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index f1253629..b8310609 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -42,27 +42,105 @@ export function defaultPlot(distribution: Distribution): Plot { return { distributions: [{ name: "default", distribution }] }; } -export function makePlot(expression: { +function error(err: b): result { + return { tag: "Error", value: err }; +} + +function ok(x: a): result { + return { tag: "Ok", value: x }; +} + +function parseString(expr: squiggleExpression): result { + if (expr.tag === "string") { + return ok(expr.value); + } else { + return error("Expression was not string"); + } +} + +function parseRecord( + expr: squiggleExpression +): result<{ [key: string]: squiggleExpression }, string> { + if (expr.tag === "record") { + return ok(expr.value); + } else { + return error("Expression was not a record"); + } +} + +function parseDistribution( + expr: squiggleExpression +): result { + if (expr.tag === "distribution") { + return ok(expr.value); + } else { + return error("Expression was not a distribution"); + } +} + +function parseArray( + expr: squiggleExpression +): result { + if (expr.tag === "array") { + return ok(expr.value); + } else { + return error("Expression was not a distribution"); + } +} + +function parseField( + record: { [key: string]: squiggleExpression }, + field: string, + parser: (expr: squiggleExpression) => result +): result { + if (record[field]) { + return parser(record[field]); + } else { + return error("record does not have field " + field); + } +} + +function resultBind( + x: result, + fn: (y: a) => result +): result { + if (x.tag === "Ok") { + return fn(x.value); + } else { + return x; + } +} + +function parseLabeledDistribution( + x: squiggleExpression +): result { + return resultBind(parseRecord(x), (record) => + resultBind(parseField(record, "name", parseString), (name) => + resultBind( + parseField(record, "distribution", parseDistribution), + (distribution) => ok({ name, distribution }) + ) + ) + ); +} + +function parsePlot(record: { + [key: string]: squiggleExpression; +}): result { + return resultBind(parseField(record, "distributions", parseArray), (array) => + resultBind( + flattenResult(array.map(parseLabeledDistribution)), + (distributions) => ok({ distributions }) + ) + ); +} + +export function makePlot(record: { [key: string]: squiggleExpression; }): Plot | void { - if (expression["distributions"].tag === "array") { - let distributions: LabeledDistribution[] = expression["distributions"].value - .map((x) => { - if ( - x.tag === "record" && - x.value["name"] && - x.value["name"].tag === "string" && - x.value["distribution"] && - x.value["distribution"].tag === "distribution" - ) { - return { - name: x.value["name"].value, - distribution: x.value["distribution"].value, - }; - } - }) - .filter((x): x is LabeledDistribution => x !== undefined); - return { distributions }; + const plotResult = parsePlot(record); + if (plotResult.tag == "Ok") { + return plotResult.value; } } function all(arr: boolean[]): boolean { From 0c7ac98aaf1e9055b434cc526ab87fd9a79441ce Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Wed, 13 Jul 2022 15:32:28 +1000 Subject: [PATCH 04/16] Color discrete components of distributions --- packages/components/src/lib/distributionSpecBuilder.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/components/src/lib/distributionSpecBuilder.ts b/packages/components/src/lib/distributionSpecBuilder.ts index 36f298d2..229e9ffe 100644 --- a/packages/components/src/lib/distributionSpecBuilder.ts +++ b/packages/components/src/lib/distributionSpecBuilder.ts @@ -213,6 +213,10 @@ export function buildVegaSpec( scale: "yscale", value: 0, }, + fill: { + scale: "color", + field: { parent: "name" }, + }, }, }, }, @@ -240,6 +244,10 @@ export function buildVegaSpec( scale: "yscale", field: "y", }, + fill: { + scale: "color", + field: { parent: "name" }, + }, }, }, }, From a5a131daf15766c50bde4df2802cdf05446a4893 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Wed, 13 Jul 2022 15:33:38 +1000 Subject: [PATCH 05/16] Remove console.log --- packages/components/src/components/DistributionChart.tsx | 1 - packages/components/src/components/SquigglePlayground.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index b8310609..6d4e7c55 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -218,7 +218,6 @@ export const DistributionChart: React.FC = (props) => { const domain = shapes.value.flatMap((shape) => shape.discrete.concat(shape.continuous) ); - console.log(shapes.value); return (
diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 534be721..d24ba141 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -529,7 +529,6 @@ export const SquigglePlayground: FC = ({ const withoutEditor =
{tabs}
; - console.log(vars); return ( From 9cc000070b4544e97873e077f6bd5d2350c554eb Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Wed, 13 Jul 2022 15:54:45 +1000 Subject: [PATCH 06/16] Refactor parsing to lib files --- .../src/components/DistributionChart.tsx | 121 +----------------- packages/components/src/lib/plotting.ts | 90 +++++++++++++ packages/components/src/lib/utility.ts | 33 +++++ 3 files changed, 125 insertions(+), 119 deletions(-) create mode 100644 packages/components/src/lib/plotting.ts create mode 100644 packages/components/src/lib/utility.ts diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 6d4e7c55..7556da26 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -17,6 +17,8 @@ import { DistributionChartSpecOptions, } from "../lib/distributionSpecBuilder"; import { NumberShower } from "./NumberShower"; +import { Plot, parsePlot } from "../lib/plotting"; +import { flattenResult, all } from "../lib/utility"; export type DistributionPlottingSettings = { /** Whether to show a summary of means, stdev, percentiles etc */ @@ -25,12 +27,6 @@ export type DistributionPlottingSettings = { showControls: boolean; } & DistributionChartSpecOptions; -export type LabeledDistribution = { name: string; distribution: Distribution }; - -export type Plot = { - distributions: LabeledDistribution[]; -}; - export type DistributionChartProps = { plot: Plot; width?: number; @@ -42,99 +38,6 @@ export function defaultPlot(distribution: Distribution): Plot { return { distributions: [{ name: "default", distribution }] }; } -function error(err: b): result { - return { tag: "Error", value: err }; -} - -function ok(x: a): result { - return { tag: "Ok", value: x }; -} - -function parseString(expr: squiggleExpression): result { - if (expr.tag === "string") { - return ok(expr.value); - } else { - return error("Expression was not string"); - } -} - -function parseRecord( - expr: squiggleExpression -): result<{ [key: string]: squiggleExpression }, string> { - if (expr.tag === "record") { - return ok(expr.value); - } else { - return error("Expression was not a record"); - } -} - -function parseDistribution( - expr: squiggleExpression -): result { - if (expr.tag === "distribution") { - return ok(expr.value); - } else { - return error("Expression was not a distribution"); - } -} - -function parseArray( - expr: squiggleExpression -): result { - if (expr.tag === "array") { - return ok(expr.value); - } else { - return error("Expression was not a distribution"); - } -} - -function parseField
( - record: { [key: string]: squiggleExpression }, - field: string, - parser: (expr: squiggleExpression) => result -): result { - if (record[field]) { - return parser(record[field]); - } else { - return error("record does not have field " + field); - } -} - -function resultBind( - x: result, - fn: (y: a) => result -): result { - if (x.tag === "Ok") { - return fn(x.value); - } else { - return x; - } -} - -function parseLabeledDistribution( - x: squiggleExpression -): result { - return resultBind(parseRecord(x), (record) => - resultBind(parseField(record, "name", parseString), (name) => - resultBind( - parseField(record, "distribution", parseDistribution), - (distribution) => ok({ name, distribution }) - ) - ) - ); -} - -function parsePlot(record: { - [key: string]: squiggleExpression; -}): result { - return resultBind(parseField(record, "distributions", parseArray), (array) => - resultBind( - flattenResult(array.map(parseLabeledDistribution)), - (distributions) => ok({ distributions }) - ) - ); -} - export function makePlot(record: { [key: string]: squiggleExpression; }): Plot | void { @@ -143,26 +46,6 @@ export function makePlot(record: { return plotResult.value; } } -function all(arr: boolean[]): boolean { - return arr.reduce((x, y) => x && y, true); -} - -function flattenResult(x: result[]): result { - if (x.length === 0) { - return { tag: "Ok", value: [] }; - } else { - if (x[0].tag === "Error") { - return x[0]; - } else { - let rest = flattenResult(x.splice(1)); - if (rest.tag === "Error") { - return rest; - } else { - return { tag: "Ok", value: [x[0].value].concat(rest.value) }; - } - } - } -} export const DistributionChart: React.FC = (props) => { const { diff --git a/packages/components/src/lib/plotting.ts b/packages/components/src/lib/plotting.ts new file mode 100644 index 00000000..5b7ca31d --- /dev/null +++ b/packages/components/src/lib/plotting.ts @@ -0,0 +1,90 @@ +import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang"; +import { flattenResult, resultBind } from "./utility"; + +export type LabeledDistribution = { name: string; distribution: Distribution }; + +export type Plot = { + distributions: LabeledDistribution[]; +}; + +function error(err: b): result { + return { tag: "Error", value: err }; +} + +function ok(x: a): result { + return { tag: "Ok", value: x }; +} + +function parseString(expr: squiggleExpression): result { + if (expr.tag === "string") { + return ok(expr.value); + } else { + return error("Expression was not string"); + } +} + +function parseRecord( + expr: squiggleExpression +): result<{ [key: string]: squiggleExpression }, string> { + if (expr.tag === "record") { + return ok(expr.value); + } else { + return error("Expression was not a record"); + } +} + +function parseDistribution( + expr: squiggleExpression +): result { + if (expr.tag === "distribution") { + return ok(expr.value); + } else { + return error("Expression was not a distribution"); + } +} + +function parseArray( + expr: squiggleExpression +): result { + if (expr.tag === "array") { + return ok(expr.value); + } else { + return error("Expression was not a distribution"); + } +} + +function parseField( + record: { [key: string]: squiggleExpression }, + field: string, + parser: (expr: squiggleExpression) => result +): result { + if (record[field]) { + return parser(record[field]); + } else { + return error("record does not have field " + field); + } +} + +function parseLabeledDistribution( + x: squiggleExpression +): result { + return resultBind(parseRecord(x), (record) => + resultBind(parseField(record, "name", parseString), (name) => + resultBind( + parseField(record, "distribution", parseDistribution), + (distribution) => ok({ name, distribution }) + ) + ) + ); +} + +export function parsePlot(record: { + [key: string]: squiggleExpression; +}): result { + return resultBind(parseField(record, "distributions", parseArray), (array) => + resultBind( + flattenResult(array.map(parseLabeledDistribution)), + (distributions) => ok({ distributions }) + ) + ); +} diff --git a/packages/components/src/lib/utility.ts b/packages/components/src/lib/utility.ts new file mode 100644 index 00000000..4a5ecc6b --- /dev/null +++ b/packages/components/src/lib/utility.ts @@ -0,0 +1,33 @@ +import { result } from "@quri/squiggle-lang"; + +export function flattenResult(x: result[]): result { + if (x.length === 0) { + return { tag: "Ok", value: [] }; + } else { + if (x[0].tag === "Error") { + return x[0]; + } else { + let rest = flattenResult(x.splice(1)); + if (rest.tag === "Error") { + return rest; + } else { + return { tag: "Ok", value: [x[0].value].concat(rest.value) }; + } + } + } +} + +export function resultBind( + x: result, + fn: (y: a) => result +): result { + if (x.tag === "Ok") { + return fn(x.value); + } else { + return x; + } +} + +export function all(arr: boolean[]): boolean { + return arr.reduce((x, y) => x && y, true); +} From ad1d391f49d5ba34f11cfd41aadf06d746ea946c Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Thu, 14 Jul 2022 16:36:12 +1000 Subject: [PATCH 07/16] Rename plotting to plotParser --- packages/components/src/components/DistributionChart.tsx | 2 +- packages/components/src/lib/{plotting.ts => plotParser.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/components/src/lib/{plotting.ts => plotParser.ts} (100%) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 7556da26..f3f84adf 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -17,7 +17,7 @@ import { DistributionChartSpecOptions, } from "../lib/distributionSpecBuilder"; import { NumberShower } from "./NumberShower"; -import { Plot, parsePlot } from "../lib/plotting"; +import { Plot, parsePlot } from "../lib/plotParser"; import { flattenResult, all } from "../lib/utility"; export type DistributionPlottingSettings = { diff --git a/packages/components/src/lib/plotting.ts b/packages/components/src/lib/plotParser.ts similarity index 100% rename from packages/components/src/lib/plotting.ts rename to packages/components/src/lib/plotParser.ts From 4aab78b45cd98dce56e5e38de7a48086869aaaa9 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Thu, 11 Aug 2022 12:31:44 +0100 Subject: [PATCH 08/16] Format code --- packages/components/src/components/DistributionChart.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 741e8f6a..50715229 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -46,14 +46,7 @@ export function makePlot(record: { } export const DistributionChart: React.FC = (props) => { - const { - plot, - height, - showSummary, - width, - logX, - actions = false, - } = props; + const { plot, height, showSummary, width, logX, actions = false } = props; const shape = distribution.pointSet(); const [sized] = useSize((size) => { let shapes = flattenResult( From c97d1d457ef69d49c1639b50af98036c8940962a Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Thu, 11 Aug 2022 14:22:55 +0100 Subject: [PATCH 09/16] Remove unneccesary line --- packages/components/src/components/DistributionChart.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 50715229..12f52754 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -47,7 +47,6 @@ export function makePlot(record: { export const DistributionChart: React.FC = (props) => { const { plot, height, showSummary, width, logX, actions = false } = props; - const shape = distribution.pointSet(); const [sized] = useSize((size) => { let shapes = flattenResult( plot.distributions.map((x) => From 70f26a08ba66734aa9f23da6ca81e64ca792a46b Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sat, 13 Aug 2022 10:52:56 +0100 Subject: [PATCH 10/16] Fix multiple charting --- .../src/components/DistributionChart.tsx | 2 +- .../SquiggleViewer/ExpressionViewer.tsx | 75 ++++++++++++++----- packages/components/src/lib/utility.ts | 4 + 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 12f52754..84bc5fef 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -80,7 +80,7 @@ export const DistributionChart: React.FC = (props) => { return (
- {logX && hasMassBelowZero(shape.value) ? ( + {logX && shapes.value.some(hasMassBelowZero) ? ( Cannot graph distribution with negative values on logarithmic scale. diff --git a/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx b/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx index 9a3e266e..51f8dcb4 100644 --- a/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx +++ b/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx @@ -1,7 +1,7 @@ import React from "react"; import { squiggleExpression, declaration } from "@quri/squiggle-lang"; import { NumberShower } from "../NumberShower"; -import { DistributionChart } from "../DistributionChart"; +import { DistributionChart, defaultPlot, makePlot } from "../DistributionChart"; import { FunctionChart, FunctionChartSettings } from "../FunctionChart"; import clsx from "clsx"; import { VariableBox } from "./VariableBox"; @@ -102,7 +102,7 @@ export const ExpressionViewer: React.FC = ({ {(settings) => { return ( = ({ case "module": { return ( - {(settings) => + {(_) => Object.entries(expression.value) - .filter(([key, r]) => !key.match(/^(Math|System)\./)) + .filter(([key, _]) => !key.match(/^(Math|System)\./)) .map(([key, r]) => ( = ({ ); } case "record": - return ( - - {(settings) => - Object.entries(expression.value).map(([key, r]) => ( - - )) - } - - ); + const plot = makePlot(expression.value); + if (plot) { + return ( + { + let disableLogX = plot.distributions.some((x) => { + let pointSet = x.distribution.pointSet(); + return ( + pointSet.tag === "Ok" && hasMassBelowZero(pointSet.value) + ); + }); + return ( + + ); + }} + > + {(settings) => { + return ( + + ); + }} + + ); + } else { + return ( + + {(_) => + Object.entries(expression.value).map(([key, r]) => ( + + )) + } + + ); + } case "array": return ( - {(settings) => + {(_) => expression.value.map((r, i) => ( ( export function all(arr: boolean[]): boolean { return arr.reduce((x, y) => x && y, true); } + +export function some(arr: boolean[]): boolean { + return arr.reduce((x, y) => x || y, false); +} From 127fbe50a287f8a89559a5ca34e65941418b619a Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Thu, 18 Aug 2022 15:13:23 -0700 Subject: [PATCH 11/16] docs site: algolia search --- packages/website/docusaurus.config.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/website/docusaurus.config.js b/packages/website/docusaurus.config.js index f48ac952..3949e98b 100644 --- a/packages/website/docusaurus.config.js +++ b/packages/website/docusaurus.config.js @@ -52,6 +52,29 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + algolia: { + // The application ID provided by Algolia + appId: "NEUN2KAR5K", + + // Public API key: it is safe to commit it + apiKey: "1f5c74a2d72799add24eb7682531a1b0", + + indexName: "squiggle_docs", + + // Optional: see doc section below + contextualSearch: true, + + // Optional: Specify domains where the navigation should occur through window.location instead on history.push. Useful when our Algolia config crawls multiple documentation sites and we want to navigate with window.location.href to them. + // externalUrlRegex: 'external\\.com|domain\\.com', + + // Optional: Algolia search parameters + searchParameters: {}, + + // Optional: path for search page that enabled by default (`false` to disable it) + searchPagePath: "search", + + //... other Algolia params + }, navbar: { title: "Squiggle", hideOnScroll: true, From 61051ffe5fe0f3d9cf16303c9bfb261eaf2869b1 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 29 Jul 2022 18:10:57 +0400 Subject: [PATCH 12/16] multiple plots story --- .../src/stories/SquiggleChart.stories.mdx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/components/src/stories/SquiggleChart.stories.mdx b/packages/components/src/stories/SquiggleChart.stories.mdx index bc289c36..14a3f1fe 100644 --- a/packages/components/src/stories/SquiggleChart.stories.mdx +++ b/packages/components/src/stories/SquiggleChart.stories.mdx @@ -93,6 +93,20 @@ could be continuous, discrete or mixed. +## Multiple plots + + + + {Template.bind({})} + + + ## Constants A constant is a simple number as a result. This has special formatting rules From 7866203ac49c5b07da356b1b27487ad313884688 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 19 Aug 2022 15:17:31 +0400 Subject: [PATCH 13/16] reimplement parsePlot with yup --- packages/components/src/lib/plotParser.ts | 109 ++++++++-------------- 1 file changed, 40 insertions(+), 69 deletions(-) diff --git a/packages/components/src/lib/plotParser.ts b/packages/components/src/lib/plotParser.ts index 5b7ca31d..033ac2a3 100644 --- a/packages/components/src/lib/plotParser.ts +++ b/packages/components/src/lib/plotParser.ts @@ -1,5 +1,5 @@ +import * as yup from "yup"; import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang"; -import { flattenResult, resultBind } from "./utility"; export type LabeledDistribution = { name: string; distribution: Distribution }; @@ -15,76 +15,47 @@ function ok(x: a): result { return { tag: "Ok", value: x }; } -function parseString(expr: squiggleExpression): result { - if (expr.tag === "string") { - return ok(expr.value); - } else { - return error("Expression was not string"); - } -} - -function parseRecord( - expr: squiggleExpression -): result<{ [key: string]: squiggleExpression }, string> { - if (expr.tag === "record") { - return ok(expr.value); - } else { - return error("Expression was not a record"); - } -} - -function parseDistribution( - expr: squiggleExpression -): result { - if (expr.tag === "distribution") { - return ok(expr.value); - } else { - return error("Expression was not a distribution"); - } -} - -function parseArray( - expr: squiggleExpression -): result { - if (expr.tag === "array") { - return ok(expr.value); - } else { - return error("Expression was not a distribution"); - } -} - -function parseField( - record: { [key: string]: squiggleExpression }, - field: string, - parser: (expr: squiggleExpression) => result -): result { - if (record[field]) { - return parser(record[field]); - } else { - return error("record does not have field " + field); - } -} - -function parseLabeledDistribution( - x: squiggleExpression -): result { - return resultBind(parseRecord(x), (record) => - resultBind(parseField(record, "name", parseString), (name) => - resultBind( - parseField(record, "distribution", parseDistribution), - (distribution) => ok({ name, distribution }) - ) - ) - ); -} +const schema = yup + .object() + .strict() + .noUnknown() + .shape({ + distributions: yup.object().shape({ + tag: yup.mixed().oneOf(["array"]), + value: yup + .array() + .of( + yup.object().shape({ + tag: yup.mixed().oneOf(["record"]), + value: yup.object().shape({ + name: yup.object().shape({ + tag: yup.mixed().oneOf(["string"]), + value: yup.string().required(), + }), + distribution: yup.object().shape({ + tag: yup.mixed().oneOf(["distribution"]), + value: yup.mixed(), + }), + }), + }) + ) + .required(), + }), + }); export function parsePlot(record: { [key: string]: squiggleExpression; }): result { - return resultBind(parseField(record, "distributions", parseArray), (array) => - resultBind( - flattenResult(array.map(parseLabeledDistribution)), - (distributions) => ok({ distributions }) - ) - ); + try { + const plotRecord = schema.validateSync(record); + return ok({ + distributions: plotRecord.distributions.value.map((x) => ({ + name: x.value.name.value, + distribution: x.value.distribution.value, + })), + }); + } catch (e) { + const message = e instanceof Error ? e.message : "Unknown error"; + return error(message); + } } From fc29a7211ee3bccbd8c25a40f9d75ace34514caf Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 19 Aug 2022 15:17:41 +0400 Subject: [PATCH 14/16] minor improvements --- packages/components/src/components/DistributionChart.tsx | 2 +- packages/components/src/lib/distributionSpecBuilder.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 84bc5fef..a09e8b69 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -40,7 +40,7 @@ export function makePlot(record: { [key: string]: squiggleExpression; }): Plot | void { const plotResult = parsePlot(record); - if (plotResult.tag == "Ok") { + if (plotResult.tag === "Ok") { return plotResult.value; } } diff --git a/packages/components/src/lib/distributionSpecBuilder.ts b/packages/components/src/lib/distributionSpecBuilder.ts index a0af7f0c..a6aaf915 100644 --- a/packages/components/src/lib/distributionSpecBuilder.ts +++ b/packages/components/src/lib/distributionSpecBuilder.ts @@ -83,7 +83,7 @@ export function buildVegaSpec( let spec: VisualizationSpec = { $schema: "https://vega.github.io/schema/vega/v5.json", - description: "A basic area chart example", + description: "Squiggle plot chart", width: 500, height: 100, padding: 5, From bf02f69acaa6a4dbea6806e5df2ba3f4d13318fd Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 19 Aug 2022 21:14:08 +0400 Subject: [PATCH 15/16] legends, blues colors scheme, remove color setting --- .../src/components/DistributionChart.tsx | 5 ++- .../src/components/SquigglePlayground.tsx | 7 +--- .../SquiggleViewer/ItemSettingsMenu.tsx | 7 +--- .../src/components/ViewSettings.tsx | 12 +----- .../src/lib/distributionSpecBuilder.ts | 42 ++++++++++++++----- packages/components/src/lib/plotParser.ts | 17 ++++++-- .../src/stories/SquiggleChart.stories.mdx | 15 ++++++- 7 files changed, 65 insertions(+), 40 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index a09e8b69..79536e12 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -17,7 +17,7 @@ import { } from "../lib/distributionSpecBuilder"; import { NumberShower } from "./NumberShower"; import { Plot, parsePlot } from "../lib/plotParser"; -import { flattenResult, all } from "../lib/utility"; +import { flattenResult } from "../lib/utility"; import { hasMassBelowZero } from "../lib/distributionUtils"; export type DistributionPlottingSettings = { @@ -52,6 +52,7 @@ export const DistributionChart: React.FC = (props) => { plot.distributions.map((x) => resultMap(x.distribution.pointSet(), (shape) => ({ name: x.name, + // color: x.color, // not supported yet continuous: shape.continuous, discrete: shape.discrete, })) @@ -94,7 +95,7 @@ export const DistributionChart: React.FC = (props) => { /> )}
- {showSummary && plot.distributions.length == 1 && ( + {showSummary && plot.distributions.length === 1 && ( )}
diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 626fc354..c3e38b1a 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -37,10 +37,7 @@ import { InputItem } from "./ui/InputItem"; import { Text } from "./ui/Text"; import { ViewSettings, viewSettingsSchema } from "./ViewSettings"; import { HeadedSection } from "./ui/HeadedSection"; -import { - defaultColor, - defaultTickFormat, -} from "../lib/distributionSpecBuilder"; +import { defaultTickFormat } from "../lib/distributionSpecBuilder"; import { Button } from "./ui/Button"; type PlaygroundProps = SquiggleChartProps & { @@ -240,7 +237,6 @@ export const SquigglePlayground: FC = ({ title, minX, maxX, - color = defaultColor, tickFormat = defaultTickFormat, distributionChartActions, code: controlledCode, @@ -268,7 +264,6 @@ export const SquigglePlayground: FC = ({ title, minX, maxX, - color, tickFormat, distributionChartActions, showSummary, diff --git a/packages/components/src/components/SquiggleViewer/ItemSettingsMenu.tsx b/packages/components/src/components/SquiggleViewer/ItemSettingsMenu.tsx index 2c26b9aa..49c2eacc 100644 --- a/packages/components/src/components/SquiggleViewer/ItemSettingsMenu.tsx +++ b/packages/components/src/components/SquiggleViewer/ItemSettingsMenu.tsx @@ -6,10 +6,7 @@ import { Modal } from "../ui/Modal"; import { ViewSettings, viewSettingsSchema } from "../ViewSettings"; import { Path, pathAsString } from "./utils"; import { ViewerContext } from "./ViewerContext"; -import { - defaultColor, - defaultTickFormat, -} from "../../lib/distributionSpecBuilder"; +import { defaultTickFormat } from "../../lib/distributionSpecBuilder"; import { PlaygroundContext } from "../SquigglePlayground"; type Props = { @@ -46,7 +43,6 @@ const ItemSettingsModal: React.FC< tickFormat: mergedSettings.distributionPlotSettings.format || defaultTickFormat, title: mergedSettings.distributionPlotSettings.title, - color: mergedSettings.distributionPlotSettings.color || defaultColor, minX: mergedSettings.distributionPlotSettings.minX, maxX: mergedSettings.distributionPlotSettings.maxX, distributionChartActions: mergedSettings.distributionPlotSettings.actions, @@ -66,7 +62,6 @@ const ItemSettingsModal: React.FC< expY: vars.expY, format: vars.tickFormat, title: vars.title, - color: vars.color, minX: vars.minX, maxX: vars.maxX, actions: vars.distributionChartActions, diff --git a/packages/components/src/components/ViewSettings.tsx b/packages/components/src/components/ViewSettings.tsx index 9a2ce562..7d70bfc8 100644 --- a/packages/components/src/components/ViewSettings.tsx +++ b/packages/components/src/components/ViewSettings.tsx @@ -5,10 +5,7 @@ import { InputItem } from "./ui/InputItem"; import { Checkbox } from "./ui/Checkbox"; import { HeadedSection } from "./ui/HeadedSection"; import { Text } from "./ui/Text"; -import { - defaultColor, - defaultTickFormat, -} from "../lib/distributionSpecBuilder"; +import { defaultTickFormat } from "../lib/distributionSpecBuilder"; export const viewSettingsSchema = yup.object({}).shape({ chartHeight: yup.number().required().positive().integer().default(350), @@ -18,7 +15,6 @@ export const viewSettingsSchema = yup.object({}).shape({ expY: yup.boolean().required(), tickFormat: yup.string().default(defaultTickFormat), title: yup.string(), - color: yup.string().default(defaultColor).required(), minX: yup.number(), maxX: yup.number(), distributionChartActions: yup.boolean(), @@ -114,12 +110,6 @@ export const ViewSettings: React.FC<{ register={register} label="Tick Format" /> -
diff --git a/packages/components/src/lib/distributionSpecBuilder.ts b/packages/components/src/lib/distributionSpecBuilder.ts index a6aaf915..2b3ac952 100644 --- a/packages/components/src/lib/distributionSpecBuilder.ts +++ b/packages/components/src/lib/distributionSpecBuilder.ts @@ -10,8 +10,6 @@ export type DistributionChartSpecOptions = { minX?: number; /** The maximum x coordinate shown on the chart */ maxX?: number; - /** The color of the chart */ - color?: string; /** The title of the chart */ title?: string; /** The formatting of the ticks */ @@ -57,14 +55,12 @@ export let expYScale: PowScale = { }; export const defaultTickFormat = ".9~s"; -export const defaultColor = "#739ECC"; export function buildVegaSpec( specOptions: DistributionChartSpecOptions ): VisualizationSpec { const { format = defaultTickFormat, - color = defaultColor, title, minX, maxX, @@ -106,7 +102,7 @@ export function buildVegaSpec( data: "data", field: "name", }, - range: { scheme: "category10" }, + range: { scheme: "blues" }, }, ], axes: [ @@ -120,6 +116,7 @@ export function buildVegaSpec( domainOpacity: 0.0, format: format, tickCount: 10, + labelOverlap: "greedy", }, ], marks: [ @@ -259,15 +256,38 @@ export function buildVegaSpec( ], }, ], - }; - if (title) { - spec = { - ...spec, + legends: [ + { + fill: "color", + orient: "top", + labelFontSize: 12, + encode: { + symbols: { + update: { + fill: [ + { test: "length(domain('color')) == 1", value: "transparent" }, + { scale: "color", field: "value" }, + ], + }, + }, + labels: { + interactive: true, + update: { + fill: [ + { test: "length(domain('color')) == 1", value: "transparent" }, + { value: "black" }, + ], + }, + }, + }, + }, + ], + ...(title && { title: { text: title, }, - }; - } + }), + }; return spec; } diff --git a/packages/components/src/lib/plotParser.ts b/packages/components/src/lib/plotParser.ts index 033ac2a3..9d5e224a 100644 --- a/packages/components/src/lib/plotParser.ts +++ b/packages/components/src/lib/plotParser.ts @@ -1,7 +1,11 @@ import * as yup from "yup"; import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang"; -export type LabeledDistribution = { name: string; distribution: Distribution }; +export type LabeledDistribution = { + name: string; + distribution: Distribution; + color?: string; +}; export type Plot = { distributions: LabeledDistribution[]; @@ -27,12 +31,18 @@ const schema = yup .of( yup.object().shape({ tag: yup.mixed().oneOf(["record"]), - value: yup.object().shape({ + value: yup.object({ name: yup.object().shape({ tag: yup.mixed().oneOf(["string"]), value: yup.string().required(), }), - distribution: yup.object().shape({ + // color: yup + // .object({ + // tag: yup.mixed().oneOf(["string"]), + // value: yup.string().required(), + // }) + // .default(undefined), + distribution: yup.object({ tag: yup.mixed().oneOf(["distribution"]), value: yup.mixed(), }), @@ -51,6 +61,7 @@ export function parsePlot(record: { return ok({ distributions: plotRecord.distributions.value.map((x) => ({ name: x.value.name.value, + // color: x.value.color?.value, // not supported yet distribution: x.value.distribution.value, })), }); diff --git a/packages/components/src/stories/SquiggleChart.stories.mdx b/packages/components/src/stories/SquiggleChart.stories.mdx index 14a3f1fe..3c272982 100644 --- a/packages/components/src/stories/SquiggleChart.stories.mdx +++ b/packages/components/src/stories/SquiggleChart.stories.mdx @@ -99,7 +99,20 @@ could be continuous, discrete or mixed. From c46845705216da85f93bedec60031c7cf444ef97 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 19 Aug 2022 21:54:29 +0400 Subject: [PATCH 16/16] update squiggle-components version (fixes playground) --- packages/website/package.json | 2 +- yarn.lock | 122 +++------------------------------- 2 files changed, 9 insertions(+), 115 deletions(-) diff --git a/packages/website/package.json b/packages/website/package.json index 7bd1f80c..53d94c2d 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -15,7 +15,7 @@ "@docusaurus/core": "2.0.1", "@docusaurus/preset-classic": "2.0.1", "@heroicons/react": "^1.0.6", - "@quri/squiggle-components": "^0.2.23", + "@quri/squiggle-components": "^0.3", "base64-js": "^1.5.1", "clsx": "^1.2.1", "hast-util-is-element": "2.1.2", diff --git a/yarn.lock b/yarn.lock index 79d240a0..b341972f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2188,23 +2188,11 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@floating-ui/core@^0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" - integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== - "@floating-ui/core@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.0.0.tgz#ec1d31f54c72dd0460276e2149e59bd13c0f01f6" integrity sha512-sm3nW0hHAxTv3gRDdCH8rNVQxijF+qPFo5gAeXCErRjKC7Qc28lIQ3R9Vd7Gw+KgwfA7RhRydDFuGeI0peGq7A== -"@floating-ui/dom@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" - integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== - dependencies: - "@floating-ui/core" "^0.7.3" - "@floating-ui/dom@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.0.0.tgz#66923a56755b6cb7a5958ecf25fe293912672d65" @@ -2212,15 +2200,6 @@ dependencies: "@floating-ui/core" "^1.0.0" -"@floating-ui/react-dom-interactions@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.6.6.tgz#8542e8c4bcbee2cd0d512de676c6a493e0a2d168" - integrity sha512-qnao6UPjSZNHnXrF+u4/n92qVroQkx0Umlhy3Avk1oIebm/5ee6yvDm4xbHob0OjY7ya8WmUnV3rQlPwX3Atwg== - dependencies: - "@floating-ui/react-dom" "^0.7.2" - aria-hidden "^1.1.3" - use-isomorphic-layout-effect "^1.1.1" - "@floating-ui/react-dom-interactions@^0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.9.2.tgz#9a364cc44ecbc242b5218dff0e0d071de115e13a" @@ -2229,14 +2208,6 @@ "@floating-ui/react-dom" "^1.0.0" aria-hidden "^1.1.3" -"@floating-ui/react-dom@^0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" - integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== - dependencies: - "@floating-ui/dom" "^0.5.3" - use-isomorphic-layout-effect "^1.1.1" - "@floating-ui/react-dom@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-1.0.0.tgz#e0975966694433f1f0abffeee5d8e6bb69b7d16e" @@ -2279,7 +2250,7 @@ resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324" integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ== -"@hookform/resolvers@^2.9.6", "@hookform/resolvers@^2.9.7": +"@hookform/resolvers@^2.9.7": version "2.9.7" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.7.tgz#8b257ae67234ce0270e6b044c1a61fb98ec02b4b" integrity sha512-BloehX3MOLwuFEwT4yZnmolPjVmqyn8VsSuodLfazbCIqxBHsQ4qUZsi+bvNNCduRli1AGWFrkDLGD5QoNzsoA== @@ -2683,7 +2654,7 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@motionone/animation@^10.12.0", "@motionone/animation@^10.13.1": +"@motionone/animation@^10.13.1": version "10.13.2" resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.13.2.tgz#174a55a3bac1b6fb314cc1c3627093dc790ae081" integrity sha512-YGWss58IR2X4lOjW89rv1Q+/Nq/QhfltaggI7i8sZTpKC1yUvM+XYDdvlRpWc6dk8LviMBrddBJAlLdbaqeRmw== @@ -2693,18 +2664,6 @@ "@motionone/utils" "^10.13.2" tslib "^2.3.1" -"@motionone/dom@10.12.0": - version "10.12.0" - resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.12.0.tgz#ae30827fd53219efca4e1150a5ff2165c28351ed" - integrity sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw== - dependencies: - "@motionone/animation" "^10.12.0" - "@motionone/generators" "^10.12.0" - "@motionone/types" "^10.12.0" - "@motionone/utils" "^10.12.0" - hey-listen "^1.0.8" - tslib "^2.3.1" - "@motionone/dom@10.13.1": version "10.13.1" resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.13.1.tgz#fc29ea5d12538f21b211b3168e502cfc07a24882" @@ -2725,7 +2684,7 @@ "@motionone/utils" "^10.13.2" tslib "^2.3.1" -"@motionone/generators@^10.12.0", "@motionone/generators@^10.13.1": +"@motionone/generators@^10.13.1": version "10.13.2" resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.13.2.tgz#dd972195b899e7a556d65bd27fae2fd423055e10" integrity sha512-QMoXV1MXEEhR6D3dct/RMMS1FwJlAsW+kMPbFGzBA4NbweblgeYQCft9DcDAVpV9wIwD6qvlBG9u99sOXLfHiA== @@ -2734,12 +2693,12 @@ "@motionone/utils" "^10.13.2" tslib "^2.3.1" -"@motionone/types@^10.12.0", "@motionone/types@^10.13.0", "@motionone/types@^10.13.2": +"@motionone/types@^10.13.0", "@motionone/types@^10.13.2": version "10.13.2" resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.13.2.tgz#c560090d81bd0149e7451aae23ab7af458570363" integrity sha512-yYV4q5v5F0iADhab4wHfqaRJnM/eVtQLjUPhyEcS72aUz/xyOzi09GzD/Gu+K506BDfqn5eULIilUI77QNaqhw== -"@motionone/utils@^10.12.0", "@motionone/utils@^10.13.1", "@motionone/utils@^10.13.2": +"@motionone/utils@^10.13.1", "@motionone/utils@^10.13.2": version "10.13.2" resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.13.2.tgz#ce79bfe1d133493c217cdc0584960434e065648d" integrity sha512-6Lw5bDA/w7lrPmT/jYWQ76lkHlHs9fl2NZpJ22cVy1kKDdEH+Cl1U6hMTpdphO6VQktQ6v2APngag91WBKLqlA== @@ -2818,33 +2777,7 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== -"@quri/squiggle-components@^0.2.23": - version "0.2.24" - resolved "https://registry.yarnpkg.com/@quri/squiggle-components/-/squiggle-components-0.2.24.tgz#16a2d72fb16f46a0bf71388c85d1238927676923" - integrity sha512-slBGryELfCsM6WX+AwQcqiPPoImLRHNyXZDueL7a+OKEAx09w3pKOqVzLWNGL7+dJe3dF8as9X/Gv1JbbIj5yw== - dependencies: - "@floating-ui/react-dom" "^0.7.2" - "@floating-ui/react-dom-interactions" "^0.6.6" - "@headlessui/react" "^1.6.6" - "@heroicons/react" "^1.0.6" - "@hookform/resolvers" "^2.9.6" - "@quri/squiggle-lang" "^0.2.8" - "@react-hook/size" "^2.1.2" - clsx "^1.2.1" - framer-motion "^6.5.1" - lodash "^4.17.21" - react "^18.1.0" - react-ace "^10.1.0" - react-hook-form "^7.33.1" - react-use "^17.4.0" - react-vega "^7.6.0" - vega "^5.22.1" - vega-embed "^6.21.0" - vega-lite "^5.3.0" - vscode-uri "^3.0.3" - yup "^0.32.11" - -"@quri/squiggle-lang@^0.2.11", "@quri/squiggle-lang@^0.2.8": +"@quri/squiggle-lang@^0.2.11": version "0.2.12" resolved "https://registry.yarnpkg.com/@quri/squiggle-lang/-/squiggle-lang-0.2.12.tgz#e8fdb22a84aa75df71c071d1ed4ae5c55f15d447" integrity sha512-fgv9DLvPlX/TqPSacKSW3GZ5S9H/YwqaMoRdFrn5SJjHnnMh/xJW/9iyzzgOxPCXov9xFeDvL159tkbStMm7vw== @@ -9721,20 +9654,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -framer-motion@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7" - integrity sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw== - dependencies: - "@motionone/dom" "10.12.0" - framesync "6.0.1" - hey-listen "^1.0.8" - popmotion "11.0.3" - style-value-types "5.0.0" - tslib "^2.1.0" - optionalDependencies: - "@emotion/is-prop-valid" "^0.8.2" - framer-motion@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-7.1.1.tgz#4d56ed18a7cf2c6a1a4a1af5b57714f8e6b52d9e" @@ -9749,13 +9668,6 @@ framer-motion@^7.1.1: optionalDependencies: "@emotion/is-prop-valid" "^0.8.2" -framesync@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" - integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== - dependencies: - tslib "^2.1.0" - framesync@6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.1.2.tgz#755eff2fb5b8f3b4d2b266dd18121b300aefea27" @@ -13963,16 +13875,6 @@ polished@^4.2.2: dependencies: "@babel/runtime" "^7.17.8" -popmotion@11.0.3: - version "11.0.3" - resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" - integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== - dependencies: - framesync "6.0.1" - hey-listen "^1.0.8" - style-value-types "5.0.0" - tslib "^2.1.0" - popmotion@11.0.5: version "11.0.5" resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.5.tgz#8e3e014421a0ffa30ecd722564fd2558954e1f7d" @@ -15165,7 +15067,7 @@ react-helmet-async@*, react-helmet-async@^1.3.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-hook-form@^7.33.1, react-hook-form@^7.34.1: +react-hook-form@^7.34.1: version "7.34.1" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.34.1.tgz#06cb216daf706bf9ae4969747115afae0d09410d" integrity sha512-tH7TaZgAURMhjzVE2M/EFmxHz2HdaPMAVs9FXTweNW551VlhXSuVcpcYlkiMZf2zHQiTztupVFpBHJFTma+N7w== @@ -16972,14 +16874,6 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -style-value-types@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" - integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== - dependencies: - hey-listen "^1.0.8" - tslib "^2.1.0" - style-value-types@5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.1.2.tgz#6be66b237bd546048a764883528072ed95713b62" @@ -18236,7 +18130,7 @@ vega-label@~1.2.0: vega-scenegraph "^4.9.2" vega-util "^1.15.2" -vega-lite@^5.3.0, vega-lite@^5.4.0: +vega-lite@^5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/vega-lite/-/vega-lite-5.4.0.tgz#d09331e2a1c87843d5865de0fa7704919796ab56" integrity sha512-e/P5iOtBE62WEWZhKP7sLcBd92YS9prfUQafelxoOeloooSSrkUwM/ZDmN5Q5ffByEZTiKfODtnwD6/xKDYUmw==