From 0bc016632f396173bba84f0c3e6fea629bacdf68 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 15:36:20 +0000 Subject: [PATCH 01/14] Mobile support --- .../src/components/DistributionChart.tsx | 25 +++++++++++++++---- .../src/components/SquiggleChart.tsx | 18 ++++++++----- .../src/components/SquiggleEditor.tsx | 10 +++----- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 6bef36c7..8aaba9cb 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -6,7 +6,6 @@ import { distributionErrorToString } from "@quri/squiggle-lang"; import { createClassFromSpec } from "react-vega"; import * as chartSpecification from "../vega-specs/spec-distributions.json"; import { ErrorBox } from "./ErrorBox"; -import styled from "styled-components"; let SquiggleVegaChart = createClassFromSpec({ spec: chartSpecification as Spec, @@ -14,18 +13,34 @@ let SquiggleVegaChart = createClassFromSpec({ type DistributionChartProps = { distribution: Distribution; - width: number; + width?: number; height: number; }; export const DistributionChart: React.FC = ({ distribution, - width, height, + width, }: DistributionChartProps) => { + // This code with refs and effects is a bit messy, and it's because we were + // having a large amount of trouble getting vega charts to be responsive. This + // is the solution we ended up with + const ref = React.useRef(null); + const [actualWidth, setActualWidth] = React.useState(undefined); + + React.useEffect(() => { + // @ts-ignore + let getWidth = () => (ref.current ? ref.current.offsetWidth : 0); + + window.addEventListener("resize", () => setActualWidth(getWidth())); + + setActualWidth(getWidth()); + }, [ref.current]); + let shape = distribution.pointSet(); if (shape.tag === "Ok") { - let widthProp = width ? width - 20 : undefined; + let widthProp = width ? width - 20 : actualWidth; + console.log("widthProp", widthProp); var result = ( = ({ ); } - return result; + return
{result}
; }; diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 31cd9787..82997f44 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -52,7 +52,7 @@ let RecordKeyHeader = styled.h3``; export interface SquiggleItemProps { /** The input string for squiggle */ expression: squiggleExpression; - width: number; + width?: number; height: number; } @@ -105,7 +105,11 @@ const SquiggleItem: React.FC = ({ return ( {expression.value.map((r) => ( - + ))} ); @@ -115,7 +119,11 @@ const SquiggleItem: React.FC = ({ {Object.entries(expression.value).map(([key, r]) => ( <> {key} - + ))} @@ -144,8 +152,6 @@ export interface SquiggleChartProps { diagramStop?: number; /** If the result is a function, how many points along the function it samples */ diagramCount?: number; - /** variables declared before this expression */ - environment?: unknown; /** When the environment changes */ onChange?(expr: squiggleExpression): void; /** CSS width of the element */ @@ -171,7 +177,7 @@ export const SquiggleChart: React.FC = ({ height = 60, bindings = defaultBindings, jsImports = defaultImports, - width = NaN, + width, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 2c01f72f..2997867d 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -32,16 +32,14 @@ export interface SquiggleEditorProps { diagramStop?: number; /** If the result is a function, how many points along the function it samples */ diagramCount?: number; - /** The environment, other variables that were already declared */ - environment?: unknown; /** when the environment changes. Used again for notebook magic*/ onChange?(expr: squiggleExpression): void; /** The width of the element */ width: number; /** Previous variable declarations */ - bindings: bindings; + bindings?: bindings; /** JS Imports */ - jsImports: jsImports; + jsImports?: jsImports; } const Input = styled.div` @@ -52,7 +50,7 @@ const Input = styled.div` export let SquiggleEditor: React.FC = ({ initialSquiggleString = "", - width = 500, + width, sampleCount, outputXYPoints, kernelWidth, @@ -61,7 +59,6 @@ export let SquiggleEditor: React.FC = ({ diagramStop, diagramCount, onChange, - environment, bindings = defaultBindings, jsImports = defaultImports, }: SquiggleEditorProps) => { @@ -87,7 +84,6 @@ export let SquiggleEditor: React.FC = ({ diagramStart={diagramStart} diagramStop={diagramStop} diagramCount={diagramCount} - environment={environment} onChange={onChange} bindings={bindings} jsImports={jsImports} From a542325f31ca6a40a83b0a057cf11541fda9e9ca Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 15:59:37 +0000 Subject: [PATCH 02/14] A simple showTypes prop --- .../src/components/SquiggleChart.tsx | 82 +++++++++++++------ .../src/components/SquiggleEditor.tsx | 4 + 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 699a7e28..4297f032 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -33,18 +33,29 @@ const variableBox = { `, }; -export const VariableBox: React.FC<{ +interface VariableBoxProps { heading: string; children: React.ReactNode; -}> = ({ heading = "Error", children }) => { - return ( - - -

{heading}

-
- {children} -
- ); + showTypes?: boolean; +} + +export const VariableBox: React.FC = ({ + heading = "Error", + children, + showTypes = false, +}: VariableBoxProps) => { + if (showTypes) { + return ( + + +

{heading}

+
+ {children} +
+ ); + } else { + return <>{children}; + } }; let RecordKeyHeader = styled.h3``; @@ -54,25 +65,31 @@ export interface SquiggleItemProps { expression: squiggleExpression; width: number; height: number; + /** Whether to show type information */ + showTypes?: boolean; } const SquiggleItem: React.FC = ({ expression, width, height, + showTypes = false, }: SquiggleItemProps) => { switch (expression.tag) { case "number": return ( - + ); case "distribution": { let distType = expression.value.type(); return ( - - {distType === "Symbolic" ? ( + + {distType === "Symbolic" && showTypes ? ( <>
{expression.value.toString()}
@@ -89,21 +106,32 @@ const SquiggleItem: React.FC = ({ } case "string": return ( - {`"${expression.value}"`} + {`"${expression.value}"`} ); case "boolean": return ( - + {expression.value.toString()} ); case "symbol": - return {expression.value}; + return ( + + {expression.value} + + ); case "call": - return {expression.value}; + return ( + + {expression.value} + + ); case "array": return ( - + {expression.value.map((r) => ( ))} @@ -111,7 +139,7 @@ const SquiggleItem: React.FC = ({ ); case "record": return ( - + {Object.entries(expression.value).map(([key, r]) => ( <> {key} @@ -120,12 +148,6 @@ const SquiggleItem: React.FC = ({ ))} ); - default: - return ( - - {"We don't currently have a working viewer for record types."} - - ); } }; @@ -153,6 +175,8 @@ export interface SquiggleChartProps { bindings?: bindings; /** JS imported parameters */ jsImports?: jsImports; + /** Whether to show type information about returns, default false */ + showTypes?: boolean; } const ChartWrapper = styled.div` @@ -170,6 +194,7 @@ export const SquiggleChart: React.FC = ({ bindings = defaultBindings, jsImports = defaultImports, width = NaN, + showTypes = false, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, @@ -186,7 +211,12 @@ export const SquiggleChart: React.FC = ({ let expression = expressionResult.value; onChange(expression); internal = ( - + ); } else { internal = ( diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 23686a4f..2b546574 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -40,6 +40,8 @@ export interface SquiggleEditorProps { bindings?: bindings; /** JS Imports */ jsImports?: jsImports; + /** Whether to show detail about types of the returns, default false */ + showTypes?: boolean; } const Input = styled.div` @@ -61,6 +63,7 @@ export let SquiggleEditor: React.FC = ({ onChange, bindings = defaultBindings, jsImports = defaultImports, + showTypes = false, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -87,6 +90,7 @@ export let SquiggleEditor: React.FC = ({ onChange={onChange} bindings={bindings} jsImports={jsImports} + showTypes={showTypes} /> ); From 213808d3aa6ebb1e825470a2a027256b44f97a43 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 16:59:54 +0000 Subject: [PATCH 03/14] Using useSize size to size charts to make them usable --- packages/components/package.json | 1 + .../src/components/DistributionChart.tsx | 40 ++--- .../src/components/SquiggleChart.tsx | 4 +- yarn.lock | 150 +++++++++++++++++- 4 files changed, 163 insertions(+), 32 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index 4888a0a5..f3ce1c3f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -9,6 +9,7 @@ "react": "^18.1.0", "react-ace": "^10.1.0", "react-dom": "^18.1.0", + "react-use": "^17.3.2", "react-vega": "^7.5.0", "styled-components": "^5.3.5", "vega": "^5.22.1", diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 8aaba9cb..e2e92591 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -6,6 +6,7 @@ import { distributionErrorToString } from "@quri/squiggle-lang"; import { createClassFromSpec } from "react-vega"; import * as chartSpecification from "../vega-specs/spec-distributions.json"; import { ErrorBox } from "./ErrorBox"; +import { useSize } from 'react-use'; let SquiggleVegaChart = createClassFromSpec({ spec: chartSpecification as Spec, @@ -22,39 +23,28 @@ export const DistributionChart: React.FC = ({ height, width, }: DistributionChartProps) => { - // This code with refs and effects is a bit messy, and it's because we were - // having a large amount of trouble getting vega charts to be responsive. This - // is the solution we ended up with - const ref = React.useRef(null); - const [actualWidth, setActualWidth] = React.useState(undefined); - React.useEffect(() => { - // @ts-ignore - let getWidth = () => (ref.current ? ref.current.offsetWidth : 0); - - window.addEventListener("resize", () => setActualWidth(getWidth())); - - setActualWidth(getWidth()); - }, [ref.current]); - - let shape = distribution.pointSet(); + const [sized, _] = useSize((size) => { + let shape = distribution.pointSet(); + let widthProp = width !== undefined ? width - 20 : size.width - 10; if (shape.tag === "Ok") { - let widthProp = width ? width - 20 : actualWidth; - console.log("widthProp", widthProp); - var result = ( + return (
- ); +
+ ); } else { - var result = ( - - {distributionErrorToString(shape.value)} - - ); + return (
+ + {distributionErrorToString(shape.value)} + +
+ ) } - return
{result}
; + }) + return sized; }; diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 82997f44..652db5cb 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -107,7 +107,7 @@ const SquiggleItem: React.FC = ({ {expression.value.map((r) => ( ))} @@ -121,7 +121,7 @@ const SquiggleItem: React.FC = ({ {key} diff --git a/yarn.lock b/yarn.lock index 89928253..5361a2f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4025,6 +4025,11 @@ jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -4180,10 +4185,10 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.9.19", "@types/react@^18.0.1", "@types/react@^18.0.3": - version "18.0.8" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.8.tgz#a051eb380a9fbcaa404550543c58e1cf5ce4ab87" - integrity sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw== +"@types/react@*", "@types/react@17.0.43", "@types/react@^16.9.19", "@types/react@^18.0.3": + version "17.0.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55" + integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -4721,6 +4726,11 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe" integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== +"@xobotyi/scrollbar-width@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" + integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -6991,6 +7001,14 @@ css-has-pseudo@^3.0.4: dependencies: postcss-selector-parser "^6.0.9" +css-in-js-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99" + integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA== + dependencies: + hyphenate-style-name "^1.0.2" + isobject "^3.0.1" + css-loader@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" @@ -7247,7 +7265,7 @@ csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda" integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA== -csstype@^3.0.2: +csstype@^3.0.2, csstype@^3.0.6: version "3.0.11" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== @@ -8662,6 +8680,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" + integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== + fast-url-parser@1.1.3, fast-url-parser@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" @@ -8674,6 +8697,11 @@ fastest-levenshtein@^1.0.12: resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== +fastest-stable-stringify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76" + integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -9881,6 +9909,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +hyphenate-style-name@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -10037,6 +10070,13 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +inline-style-prefixer@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.1.tgz#c5c0e43ba8831707afc5f5bbfd97edf45c1fa7ae" + integrity sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ== + dependencies: + css-in-js-utils "^2.0.0" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -11163,6 +11203,11 @@ joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -12183,6 +12228,20 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== +nano-css@^5.3.1: + version "5.3.4" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.4.tgz#40af6a83a76f84204f346e8ccaa9169cdae9167b" + integrity sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg== + dependencies: + css-tree "^1.1.2" + csstype "^3.0.6" + fastest-stable-stringify "^2.0.2" + inline-style-prefixer "^6.0.0" + rtl-css-js "^1.14.0" + sourcemap-codec "^1.4.8" + stacktrace-js "^2.0.2" + stylis "^4.0.6" + nanoid@^3.1.23, nanoid@^3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" @@ -14778,6 +14837,31 @@ react-textarea-autosize@^8.3.0, react-textarea-autosize@^8.3.2: use-composed-ref "^1.0.0" use-latest "^1.0.0" +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + +react-use@^17.3.2: + version "17.3.2" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.3.2.tgz#448abf515f47c41c32455024db28167cb6e53be8" + integrity sha512-bj7OD0/1wL03KyWmzFXAFe425zziuTf7q8olwCYBfOeFHY1qfO1FAMjROQLsLZYwG4Rx63xAfb7XAbBrJsZmEw== + dependencies: + "@types/js-cookie" "^2.2.6" + "@xobotyi/scrollbar-width" "^1.9.5" + copy-to-clipboard "^3.3.1" + fast-deep-equal "^3.1.3" + fast-shallow-equal "^1.0.0" + js-cookie "^2.2.1" + nano-css "^5.3.1" + react-universal-interface "^0.6.2" + resize-observer-polyfill "^1.5.1" + screenfull "^5.1.0" + set-harmonic-interval "^1.0.1" + throttle-debounce "^3.0.1" + ts-easing "^0.2.0" + tslib "^2.1.0" + react-vega@^7.5.0: version "7.5.0" resolved "https://registry.yarnpkg.com/react-vega/-/react-vega-7.5.0.tgz#b9726d4fd7f35299d417d340935e093bf4bed558" @@ -15335,6 +15419,13 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rtl-css-js@^1.14.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.15.0.tgz#680ed816e570a9ebccba9e1cd0f202c6a8bb2dc0" + integrity sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew== + dependencies: + "@babel/runtime" "^7.1.2" + rtl-detect@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" @@ -15496,6 +15587,11 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" +screenfull@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + scroll-into-view-if-needed@^2.2.25: version "2.2.29" resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" @@ -15669,6 +15765,11 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-harmonic-interval@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" + integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -15900,6 +16001,11 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -16024,6 +16130,13 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-generator@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36" + integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q== + dependencies: + stackframe "^1.1.1" + stack-utils@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" @@ -16036,6 +16149,23 @@ stackframe@^1.1.1: resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1" integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg== +stacktrace-gps@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a" + integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg== + dependencies: + source-map "0.5.6" + stackframe "^1.1.1" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + state-toggle@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" @@ -16348,6 +16478,11 @@ stylehacks@^5.1.0: browserslist "^4.16.6" postcss-selector-parser "^6.0.4" +stylis@^4.0.6: + version "4.1.1" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.1.tgz#e46c6a9bbf7c58db1e65bb730be157311ae1fe12" + integrity sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ== + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -16792,6 +16927,11 @@ ts-dedent@^2.0.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== +ts-easing@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" + integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== + ts-jest@^27.1.4: version "27.1.4" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.4.tgz#84d42cf0f4e7157a52e7c64b1492c46330943e00" From 8452995c31ef0c34600cdfb7efe990dd2cbb615c Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 17:01:09 +0000 Subject: [PATCH 04/14] Lint components --- .../src/components/DistributionChart.tsx | 47 ++++++++++--------- .../src/components/SquiggleChart.tsx | 2 +- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index e2e92591..4ff4d9fd 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -6,7 +6,7 @@ import { distributionErrorToString } from "@quri/squiggle-lang"; import { createClassFromSpec } from "react-vega"; import * as chartSpecification from "../vega-specs/spec-distributions.json"; import { ErrorBox } from "./ErrorBox"; -import { useSize } from 'react-use'; +import { useSize } from "react-use"; let SquiggleVegaChart = createClassFromSpec({ spec: chartSpecification as Spec, @@ -23,28 +23,29 @@ export const DistributionChart: React.FC = ({ height, width, }: DistributionChartProps) => { - const [sized, _] = useSize((size) => { - let shape = distribution.pointSet(); - let widthProp = width !== undefined ? width - 20 : size.width - 10; - if (shape.tag === "Ok") { - return (
- -
+ let shape = distribution.pointSet(); + let widthProp = width !== undefined ? width - 20 : size.width - 10; + if (shape.tag === "Ok") { + return ( +
+ +
); - } else { - return (
- - {distributionErrorToString(shape.value)} - -
- ) - } - }) - return sized; + } else { + return ( +
+ + {distributionErrorToString(shape.value)} + +
+ ); + } + }); + return sized; }; diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 652db5cb..db8e12c2 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -121,7 +121,7 @@ const SquiggleItem: React.FC = ({ {key} From c5c65f5bc7d18f768588ff265efdf2bbc00dcb24 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 17:14:16 +0000 Subject: [PATCH 05/14] Update yarn.lock --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9b59e400..11bb1227 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4185,10 +4185,10 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@17.0.43", "@types/react@^16.9.19", "@types/react@^18.0.3": - version "17.0.43" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55" - integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A== +"@types/react@*", "@types/react@^16.9.19", "@types/react@^18.0.1", "@types/react@^18.0.3": + version "18.0.8" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.8.tgz#a051eb380a9fbcaa404550543c58e1cf5ce4ab87" + integrity sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" From f4085e93ad52a34cda43d50c0b6499c16bd1246a Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 18:29:59 +0000 Subject: [PATCH 06/14] Real log scales --- .../src/components/DistributionChart.tsx | 99 +++++++++++++++---- .../src/components/DistributionVegaScales.ts | 80 +++++++++++++++ .../src/vega-specs/spec-distributions.json | 69 +------------ packages/squiggle-lang/src/js/index.ts | 5 +- 4 files changed, 166 insertions(+), 87 deletions(-) create mode 100644 packages/components/src/components/DistributionVegaScales.ts diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 6bef36c7..4fe063a5 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -1,16 +1,16 @@ import * as React from "react"; import _ from "lodash"; -import type { Spec } from "vega"; import type { Distribution } from "@quri/squiggle-lang"; -import { distributionErrorToString } from "@quri/squiggle-lang"; -import { createClassFromSpec } from "react-vega"; +import { distributionErrorToString, result, shape } from "@quri/squiggle-lang"; +import { Vega, VisualizationSpec } from "react-vega"; import * as chartSpecification from "../vega-specs/spec-distributions.json"; import { ErrorBox } from "./ErrorBox"; -import styled from "styled-components"; - -let SquiggleVegaChart = createClassFromSpec({ - spec: chartSpecification as Spec, -}); +import { + linearXScale, + logXScale, + linearYScale, + expYScale, +} from "./DistributionVegaScales"; type DistributionChartProps = { distribution: Distribution; @@ -23,17 +23,30 @@ export const DistributionChart: React.FC = ({ width, height, }: DistributionChartProps) => { + let [isLogX, setLogX] = React.useState(false); + let [isExpY, setExpY] = React.useState(false); let shape = distribution.pointSet(); if (shape.tag === "Ok") { - let widthProp = width ? width - 20 : undefined; - var result = ( - - ); + let spec = buildSpec(isLogX, isExpY, shape.value); + if (spec.tag == "Ok") { + let widthProp = width ? width - 20 : undefined; + var result = ( +
+ +
+ ); + } else { + // Log scales don't work when you have points below 0 + var result = ( + {spec.value.error} + ); + } } else { var result = ( @@ -41,5 +54,55 @@ export const DistributionChart: React.FC = ({ ); } - return result; + return ( + <> + {result} +
+ + +
+ + ); +}; + +type ViewError = { heading: string; error: string }; + +function buildSpec( + isLogX: boolean, + isExpY: boolean, + shape: shape +): result { + let someBelow0 = + shape.continuous.some((x) => x.x <= 0) || + shape.discrete.some((x) => x.x <= 0); + if (!(isLogX && someBelow0)) { + return { + tag: "Ok", + value: { + ...chartSpecification, + scales: [ + isLogX ? logXScale : linearXScale, + isExpY ? expYScale : linearYScale, + ], + } as VisualizationSpec, + }; + } else { + return { + tag: "Error", + value: { + heading: "Log Viewing error", + error: + "Distribution contains values lower than or equal to 0. Cannot view", + }, + }; + } +} + +export const CheckBox = ({ label, onChange, value }) => { + return ( + + onChange(!value)} /> + + + ); }; diff --git a/packages/components/src/components/DistributionVegaScales.ts b/packages/components/src/components/DistributionVegaScales.ts new file mode 100644 index 00000000..f0c5c8f6 --- /dev/null +++ b/packages/components/src/components/DistributionVegaScales.ts @@ -0,0 +1,80 @@ +import type { LogScale, LinearScale, PowScale } from "vega"; +export let linearXScale: LinearScale = { + name: "xscale", + type: "linear", + range: "width", + zero: false, + nice: false, + domain: { + fields: [ + { + data: "con", + field: "x", + }, + { + data: "dis", + field: "x", + }, + ], + }, +}; +export let linearYScale: LinearScale = { + name: "yscale", + type: "linear", + range: "height", + zero: true, + domain: { + fields: [ + { + data: "con", + field: "y", + }, + { + data: "dis", + field: "y", + }, + ], + }, +}; + +export let logXScale: LogScale = { + name: "xscale", + type: "log", + range: "width", + zero: false, + base: 10, + nice: false, + domain: { + fields: [ + { + data: "con", + field: "x", + }, + { + data: "dis", + field: "x", + }, + ], + }, +}; + +export let expYScale: PowScale = { + name: "yscale", + type: "pow", + exponent: 0.1, + range: "height", + zero: true, + nice: false, + domain: { + fields: [ + { + data: "con", + field: "y", + }, + { + data: "dis", + field: "y", + }, + ], + }, +}; diff --git a/packages/components/src/vega-specs/spec-distributions.json b/packages/components/src/vega-specs/spec-distributions.json index 5b6ed261..5ca9576f 100644 --- a/packages/components/src/vega-specs/spec-distributions.json +++ b/packages/components/src/vega-specs/spec-distributions.json @@ -3,7 +3,6 @@ "description": "A basic area chart example", "width": 500, "height": 100, - "autosize": "fit", "padding": 5, "data": [ { @@ -13,72 +12,8 @@ "name": "dis" } ], - "signals": [ - { - "name": "xscale", - "description": "The transform of the x scale", - "value": false, - "bind": { - "input": "checkbox", - "name": "log x scale" - } - }, - { - "name": "yscale", - "description": "The transform of the y scale", - "value": false, - "bind": { - "input": "checkbox", - "name": "log y scale" - } - } - ], - "scales": [ - { - "name": "xscale", - "type": "pow", - "exponent": { - "signal": "xscale ? 0.1 : 1" - }, - "range": "width", - "zero": false, - "nice": false, - "domain": { - "fields": [ - { - "data": "con", - "field": "x" - }, - { - "data": "dis", - "field": "x" - } - ] - } - }, - { - "name": "yscale", - "type": "pow", - "exponent": { - "signal": "yscale ? 0.1 : 1" - }, - "range": "height", - "nice": true, - "zero": true, - "domain": { - "fields": [ - { - "data": "con", - "field": "y" - }, - { - "data": "dis", - "field": "y" - } - ] - } - } - ], + "signals": [], + "scales": [], "axes": [ { "orient": "bottom", diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index ce4d9428..7140cbc7 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -11,6 +11,7 @@ export { makeSampleSetDist, errorValueToString, distributionErrorToString, + distributionError } from "../rescript/TypescriptInterface.gen"; export type { samplingParams, @@ -26,9 +27,9 @@ import { convertRawToTypescript, } from "./rescript_interop"; import { result, resultMap, tag, tagged } from "./types"; -import { Distribution } from "./distribution"; +import { Distribution, shape } from "./distribution"; -export { Distribution, squiggleExpression, result, resultMap }; +export { Distribution, squiggleExpression, result, resultMap, shape }; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, From 71fc3149301736aae2945f1a3d80f21508959477 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 18:54:41 +0000 Subject: [PATCH 07/14] Hotfix playground chart Value: [0.001 to 0.01] --- packages/components/src/components/SquigglePlayground.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index a8ad84d5..93e1d963 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -74,7 +74,7 @@ const Display = styled.div` const Row = styled.div` display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 50% 50%; `; const Col = styled.div``; From 17a5f948fe1c0c9543993ea4d54286917581613a Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 18:59:52 +0000 Subject: [PATCH 08/14] Format and fix CI bugs --- packages/components/src/components/DistributionChart.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 9ba4d898..47c105c8 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -24,9 +24,9 @@ export const DistributionChart: React.FC = ({ height, width, }: DistributionChartProps) => { + let [isLogX, setLogX] = React.useState(false); + let [isExpY, setExpY] = React.useState(false); const [sized, _] = useSize((size) => { - let [isLogX, setLogX] = React.useState(false); - let [isExpY, setExpY] = React.useState(false); let shape = distribution.pointSet(); if (shape.tag === "Ok") { let spec = buildSpec(isLogX, isExpY, shape.value); From cc7004790489da2f51815174c98c98b30168348a Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 19:04:16 +0000 Subject: [PATCH 09/14] Lint js --- packages/squiggle-lang/src/js/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 7140cbc7..c884164a 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -11,7 +11,7 @@ export { makeSampleSetDist, errorValueToString, distributionErrorToString, - distributionError + distributionError, } from "../rescript/TypescriptInterface.gen"; export type { samplingParams, From 47b67a9efbab60657df787781d0cd7a3772dbe01 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 19:58:24 +0000 Subject: [PATCH 10/14] Add Patrial storybook and update partial bindings async --- .../src/components/SquiggleEditor.tsx | 44 +++++++++------- .../src/stories/SquigglePartial.stories.mdx | 51 +++++++++++++++++++ packages/squiggle-lang/src/js/index.ts | 1 + 3 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 packages/components/src/stories/SquigglePartial.stories.mdx diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 2b6cbf96..2bb5c2ac 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -164,33 +164,43 @@ export let SquigglePartial: React.FC = ({ xyPointLength: outputXYPoints, }; let [expression, setExpression] = React.useState(initialSquiggleString); - let squiggleResult = runPartial( - expression, - bindings, - samplingInputs, - jsImports - ); - if (squiggleResult.tag == "Ok") { - if (onChange) onChange(squiggleResult.value); - } + let [error, setError] = React.useState(null); + + // Runs squiggle and updates state/calls props apprropriately + let runSquiggle = (newExpression: string) => { + let squiggleResult = runPartial( + newExpression, + bindings, + samplingInputs, + jsImports + ); + if (squiggleResult.tag == "Ok") { + if (onChange) onChange(squiggleResult.value); + setError(null); + } else { + setError(errorValueToString(squiggleResult.value)); + } + }; + + // Run this once on mount, so that the next cells can get relevent values + React.useEffect(() => runSquiggle(expression), []); + return (
{ + // When the code changes, rerun squiggle and inform next cells + setExpression(x); + runSquiggle(x); + }} oneLine={true} showGutter={false} height={20} /> - {squiggleResult.tag == "Error" ? ( - - {errorValueToString(squiggleResult.value)} - - ) : ( - <> - )} + {error !== null ? {error} : <>}
); }; diff --git a/packages/components/src/stories/SquigglePartial.stories.mdx b/packages/components/src/stories/SquigglePartial.stories.mdx new file mode 100644 index 00000000..b4446402 --- /dev/null +++ b/packages/components/src/stories/SquigglePartial.stories.mdx @@ -0,0 +1,51 @@ +import { SquigglePartial, SquiggleEditor } from "../components/SquiggleEditor"; +import { useState } from "react"; +import { Canvas, Meta, Story, Props } from "@storybook/addon-docs"; + + + +export const Template = (props) => ; + +# Squiggle Partial + +A Squiggle Partial is an editor that does not return a graph to the user, but +instead returns bindings that can be used by further Squiggle Editors. + + + + {Template.bind({})} + + + + + + {(props) => { + let [bindings, setBindings] = useState({}); + return ( + <> + + + + ); + }} + + diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index ce4d9428..0b521079 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -11,6 +11,7 @@ export { makeSampleSetDist, errorValueToString, distributionErrorToString, + distributionError, } from "../rescript/TypescriptInterface.gen"; export type { samplingParams, From 7e05d6300926718d621b3ef1a7cea8fba721248b Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 20:40:15 +0000 Subject: [PATCH 11/14] Make a tooltip to restrict users from log scales --- .../src/components/DistributionChart.tsx | 126 ++++++++++-------- 1 file changed, 70 insertions(+), 56 deletions(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 47c105c8..38b96054 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import _ from "lodash"; import type { Distribution } from "@quri/squiggle-lang"; -import { distributionErrorToString, result, shape } from "@quri/squiggle-lang"; +import { distributionErrorToString } from "@quri/squiggle-lang"; import { Vega, VisualizationSpec } from "react-vega"; import * as chartSpecification from "../vega-specs/spec-distributions.json"; import { ErrorBox } from "./ErrorBox"; @@ -12,6 +12,7 @@ import { linearYScale, expYScale, } from "./DistributionVegaScales"; +import styled from "styled-components"; type DistributionChartProps = { distribution: Distribution; @@ -26,28 +27,29 @@ export const DistributionChart: React.FC = ({ }: DistributionChartProps) => { let [isLogX, setLogX] = React.useState(false); let [isExpY, setExpY] = React.useState(false); + let shape = distribution.pointSet(); const [sized, _] = useSize((size) => { - let shape = distribution.pointSet(); + var disableLog = false; if (shape.tag === "Ok") { - let spec = buildSpec(isLogX, isExpY, shape.value); - if (spec.tag == "Ok") { - let widthProp = width ? width - 20 : size.width - 10; - var result = ( -
- -
- ); - } else { - var result = ( - {spec.value.error} - ); + let massBelow0 = + shape.value.continuous.some((x) => x.x <= 0) || + shape.value.discrete.some((x) => x.x <= 0); + if (massBelow0) { + disableLog = true; } + let spec = buildVegaSpec(isLogX, isExpY); + let widthProp = width ? width - 20 : size.width - 10; + var result = ( +
+ +
+ ); } else { var result = ( @@ -59,7 +61,19 @@ export const DistributionChart: React.FC = ({ <> {result}
- + {disableLog ? ( + + ) : ( + + )}
@@ -68,44 +82,44 @@ export const DistributionChart: React.FC = ({ return sized; }; -type ViewError = { heading: string; error: string }; - -function buildSpec( - isLogX: boolean, - isExpY: boolean, - shape: shape -): result { - let someBelow0 = - shape.continuous.some((x) => x.x <= 0) || - shape.discrete.some((x) => x.x <= 0); - if (!(isLogX && someBelow0)) { - return { - tag: "Ok", - value: { - ...chartSpecification, - scales: [ - isLogX ? logXScale : linearXScale, - isExpY ? expYScale : linearYScale, - ], - } as VisualizationSpec, - }; - } else { - return { - tag: "Error", - value: { - heading: "Log Viewing error", - error: - "Distribution contains values lower than or equal to 0. Cannot view", - }, - }; - } +function buildVegaSpec(isLogX: boolean, isExpY: boolean): VisualizationSpec { + return { + ...chartSpecification, + scales: [ + isLogX ? logXScale : linearXScale, + isExpY ? expYScale : linearYScale, + ], + } as VisualizationSpec; } -export const CheckBox = ({ label, onChange, value }) => { +interface CheckBoxProps { + label: string; + onChange: (x: boolean) => void; + value: boolean; + disabled?: boolean; + tooltip?: string; +} + +const Label = styled.label<{ disabled: boolean }>` + ${(props) => props.disabled && "color: #999;"} +`; + +export const CheckBox = ({ + label, + onChange, + value, + disabled = false, + tooltip, +}: CheckBoxProps) => { return ( - - onChange(!value)} /> - + + onChange(!value)} + disabled={disabled} + /> + ); }; From 5fc829efc9f8493a5e47bc48c26209b2912d1cce Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 20:52:55 +0000 Subject: [PATCH 12/14] Refactor and shrink effect code --- .../components/src/components/SquiggleEditor.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 2bb5c2ac..8ea70afa 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -166,10 +166,9 @@ export let SquigglePartial: React.FC = ({ let [expression, setExpression] = React.useState(initialSquiggleString); let [error, setError] = React.useState(null); - // Runs squiggle and updates state/calls props apprropriately - let runSquiggle = (newExpression: string) => { + React.useEffect(() => { let squiggleResult = runPartial( - newExpression, + expression, bindings, samplingInputs, jsImports @@ -180,21 +179,14 @@ export let SquigglePartial: React.FC = ({ } else { setError(errorValueToString(squiggleResult.value)); } - }; - - // Run this once on mount, so that the next cells can get relevent values - React.useEffect(() => runSquiggle(expression), []); + }, [expression]); return (
{ - // When the code changes, rerun squiggle and inform next cells - setExpression(x); - runSquiggle(x); - }} + onChange={setExpression} oneLine={true} showGutter={false} height={20} From 06c479b54769d46cc691ed2b1717f44786a75c21 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 20:54:33 +0000 Subject: [PATCH 13/14] Make error message more descriptive --- packages/components/src/components/DistributionChart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 38b96054..f43b642c 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -68,7 +68,7 @@ export const DistributionChart: React.FC = ({ onChange={setLogX} disabled={true} tooltip={ - "Your distribution has mass lower than or equal to 0, cannot use log scale" + "Your distribution has mass lower than or equal to 0. Log only works on strictly positive values." } /> ) : ( From 0d14216e9feb89a448a2f4f788a221a4103a026f Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 2 May 2022 21:05:59 +0000 Subject: [PATCH 14/14] Refactor and rename lambda in partial --- packages/components/src/components/SquiggleEditor.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 8ea70afa..9a453ab8 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -166,7 +166,7 @@ export let SquigglePartial: React.FC = ({ let [expression, setExpression] = React.useState(initialSquiggleString); let [error, setError] = React.useState(null); - React.useEffect(() => { + let runSquiggleAndUpdateBindings = () => { let squiggleResult = runPartial( expression, bindings, @@ -179,7 +179,9 @@ export let SquigglePartial: React.FC = ({ } else { setError(errorValueToString(squiggleResult.value)); } - }, [expression]); + }; + + React.useEffect(runSquiggleAndUpdateBindings, [expression]); return (