From fc68a8d0694fa9dfe5077fecf88d0a39220df7e9 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 24 Jun 2022 03:43:30 +0000 Subject: [PATCH] Remove observable boilerplate + refactors --- packages/components/package.json | 2 - .../src/components/SquiggleChart.tsx | 22 ++- .../src/components/SquiggleEditor.tsx | 150 +++--------------- .../src/components/SquigglePlayground.tsx | 16 +- packages/components/src/index.ts | 12 +- packages/components/src/lib/hooks.ts | 23 +-- .../src/stories/SquiggleEditor.stories.mdx | 4 +- .../src/stories/SquigglePartial.stories.mdx | 6 +- packages/website/docs/Discussions/Bugs.mdx | 4 +- .../docs/Guides/DistributionCreation.mdx | 64 ++++---- packages/website/docs/Guides/Functions.mdx | 58 +++---- packages/website/docs/Guides/Language.mdx | 12 +- yarn.lock | 2 +- 13 files changed, 120 insertions(+), 255 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index 7c64463c..bd86a257 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -38,7 +38,6 @@ "@types/lodash": "^4.14.182", "@types/node": "^18.0.0", "@types/react": "^18.0.9", - "@types/react-dom": "^18.0.5", "@types/styled-components": "^5.1.24", "@types/webpack": "^5.28.0", "cross-env": "^7.0.3", @@ -47,7 +46,6 @@ "postcss-import": "^14.1.0", "postcss-loader": "^7.0.0", "react": "^18.1.0", - "react-dom": "^18.2.0", "react-scripts": "^5.0.1", "style-loader": "^3.3.1", "tailwindcss": "^3.1.3", diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index f7bb7ace..3e712396 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -8,7 +8,6 @@ import { defaultBindings, defaultEnvironment, } from "@quri/squiggle-lang"; -import { FunctionChartSettings } from "./FunctionChart"; import { useSquiggle } from "../lib/hooks"; import { SquiggleErrorAlert } from "./SquiggleErrorAlert"; import { SquiggleItem } from "./SquiggleItem"; @@ -20,8 +19,12 @@ export interface SquiggleChartProps { sampleCount?: number; /** The amount of points returned to draw the distribution */ environment?: environment; - /** If the result is a function, where the function starts, ends and the amount of stops */ - chartSettings?: FunctionChartSettings; + /** If the result is a function, where the function domain starts */ + diagramStart?: number; + /** If the result is a function, where the function domain ends */ + diagramStop?: number; + /** If the result is a function, the amount of stops sampled */ + diagramCount?: number; /** When the squiggle code gets reevaluated */ onChange?(expr: squiggleExpression | undefined): void; /** CSS width of the element */ @@ -44,7 +47,6 @@ export interface SquiggleChartProps { } const defaultOnChange = () => {}; -const defaultChartSettings = { start: 0, stop: 10, count: 20 }; export const SquiggleChart: React.FC = ({ squiggleString = "", @@ -59,9 +61,11 @@ export const SquiggleChart: React.FC = ({ showControls = false, logX = false, expY = false, - chartSettings = defaultChartSettings, + diagramStart = 0, + diagramStop = 10, + diagramCount = 100, }) => { - const { result } = useSquiggle({ + const result = useSquiggle({ code: squiggleString, bindings, environment, @@ -80,6 +84,12 @@ export const SquiggleChart: React.FC = ({ expY, }; + let chartSettings = { + start: diagramStart, + stop: diagramStop, + count: diagramCount, + }; + return ( ); -export interface SquiggleEditorProps { - /** The input string for squiggle */ - initialSquiggleString?: string; - /** The width of the element */ - width?: number; - /** If the result is a function, where the function starts */ - diagramStart?: number; - /** If the result is a function, where the function ends */ - diagramStop?: number; - /** If the result is a function, how many points along the function it samples */ - diagramCount?: number; - /** When the environment changes. Used again for notebook magic */ - onChange?(expr: squiggleExpression | undefined): void; - /** Previous variable declarations */ - bindings?: bindings; - /** If the output requires monte carlo sampling, the amount of samples */ - environment?: environment; - /** JS Imports */ - jsImports?: jsImports; - /** Whether to show detail about types of the returns, default false */ - showTypes?: boolean; - /** Whether to give users access to graph controls */ - showControls?: boolean; - /** Whether to show a summary table */ - showSummary?: boolean; - /** Whether to log the x coordinate on distribution charts */ - logX?: boolean; - /** Whether to exp the y coordinate on distribution charts */ - expY?: boolean; -} +export type SquiggleEditorProps = SquiggleChartProps; -export const SquiggleEditor: React.FC = ({ - initialSquiggleString = "", - width, - diagramStart = 0, - diagramStop = 10, - diagramCount = 20, - onChange, - bindings = defaultBindings, - environment, - jsImports = defaultImports, - showTypes = false, - showControls = false, - showSummary = false, - logX = false, - expY = false, -}: SquiggleEditorProps) => { - const [code, setCode] = useState(initialSquiggleString); - React.useEffect( - () => setCode(initialSquiggleString), - [initialSquiggleString] - ); - - const { result, observableRef } = useSquiggle({ - code, - bindings, - environment, - jsImports, - onChange, - }); - - const chartSettings = { - start: diagramStart, - stop: diagramStop, - count: diagramCount, - }; - - const distributionPlotSettings = { - showControls, - showSummary, - logX, - expY, - }; +export const SquiggleEditor: React.FC = (props) => { + const { squiggleString = "" } = props; + const [code, setCode] = useState(squiggleString); + React.useEffect(() => setCode(squiggleString), [squiggleString]); + let chartProps = { ...props, squiggleString: code }; return ( -
- - - {result.tag === "Ok" ? ( - - ) : ( - - )} - -
+ + + + ); }; -export function renderSquiggleEditorToDom(props: SquiggleEditorProps) { - const parent = document.createElement("div"); - ReactDOM.render(, parent); - return parent; -} - export interface SquigglePartialProps { /** The input string for squiggle */ - initialSquiggleString?: string; + squiggleString?: string; /** when the environment changes. Used again for notebook magic*/ onChange?(expr: bindings | undefined): void; /** Previously declared variables */ @@ -145,19 +52,16 @@ export interface SquigglePartialProps { } export const SquigglePartial: React.FC = ({ - initialSquiggleString = "", + squiggleString = "", onChange, bindings = defaultBindings, environment, jsImports = defaultImports, }: SquigglePartialProps) => { - const [code, setCode] = useState(initialSquiggleString); - React.useEffect( - () => setCode(initialSquiggleString), - [initialSquiggleString] - ); + const [code, setCode] = useState(squiggleString); + React.useEffect(() => setCode(squiggleString), [squiggleString]); - const { result, observableRef } = useSquigglePartial({ + const result = useSquigglePartial({ code, bindings, environment, @@ -166,19 +70,9 @@ export const SquigglePartial: React.FC = ({ }); return ( -
- - - {result.tag !== "Ok" ? ( - - ) : null} - -
+ + + {result.tag !== "Ok" ? : null} + ); }; - -export function renderSquigglePartialToDom(props: SquigglePartialProps) { - const parent = document.createElement("div"); - ReactDOM.render(, parent); - return parent; -} diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 2cd755b2..ce59b5a4 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -1,5 +1,4 @@ import React, { FC, Fragment, useState, useEffect } from "react"; -import ReactDOM from "react-dom"; import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form"; import * as yup from "yup"; import { yupResolver } from "@hookform/resolvers/yup"; @@ -250,11 +249,6 @@ export const SquigglePlayground: FC = ({ onSettingsChange?.(vars); }, [vars, onSettingsChange]); - const chartSettings = { - start: Number(vars.diagramStart), - stop: Number(vars.diagramStop), - count: Number(vars.diagramCount), - }; const env: environment = { sampleCount: Number(vars.sampleCount), xyPointLength: Number(vars.xyPointLength), @@ -425,7 +419,9 @@ export const SquigglePlayground: FC = ({ = ({ ); }; - -export function renderSquigglePlaygroundToDom(props: PlaygroundProps) { - const parent = document.createElement("div"); - ReactDOM.render(, parent); - return parent; -} diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index de0b6dff..ce6e107c 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -1,14 +1,6 @@ export { SquiggleChart } from "./components/SquiggleChart"; -export { - SquiggleEditor, - SquigglePartial, - renderSquiggleEditorToDom, - renderSquigglePartialToDom, -} from "./components/SquiggleEditor"; -export { - SquigglePlayground, - renderSquigglePlaygroundToDom, -} from "./components/SquigglePlayground"; +export { SquiggleEditor, SquigglePartial } from "./components/SquiggleEditor"; +export { SquigglePlayground } from "./components/SquigglePlayground"; export { SquiggleContainer } from "./components/SquiggleContainer"; export { mergeBindings } from "@quri/squiggle-lang"; diff --git a/packages/components/src/lib/hooks.ts b/packages/components/src/lib/hooks.ts index 42db01ce..03b8c69d 100644 --- a/packages/components/src/lib/hooks.ts +++ b/packages/components/src/lib/hooks.ts @@ -5,7 +5,7 @@ import { run, runPartial, } from "@quri/squiggle-lang"; -import { useEffect, useMemo, useRef } from "react"; +import { useEffect, useMemo } from "react"; type SquiggleArgs> = { code: string; @@ -19,37 +19,18 @@ const useSquiggleAny = >( args: SquiggleArgs, f: (...args: Parameters) => T ) => { - // We're using observable, where div elements can have a `value` property: - // https://observablehq.com/@observablehq/introduction-to-views - // - // This is here to get the 'viewof' part of: - // viewof env = cell('normal(0,1)') - // to work - const ref = useRef< - HTMLDivElement & { value?: Extract["value"] } - >(null); const result: T = useMemo( () => f(args.code, args.bindings, args.environment, args.jsImports), [f, args.code, args.bindings, args.environment, args.jsImports] ); - useEffect(() => { - if (!ref.current) return; - ref.current.value = result.tag === "Ok" ? result.value : undefined; - - ref.current.dispatchEvent(new CustomEvent("input")); - }, [result]); - const { onChange } = args; useEffect(() => { onChange?.(result.tag === "Ok" ? result.value : undefined); }, [result, onChange]); - return { - result, // squiggleExpression or externalBindings - observableRef: ref, // can be passed to outermost
if you want to use your component as an observablehq's view - }; + return result; }; export const useSquigglePartial = ( diff --git a/packages/components/src/stories/SquiggleEditor.stories.mdx b/packages/components/src/stories/SquiggleEditor.stories.mdx index 3ae37bb3..7e8f7e66 100644 --- a/packages/components/src/stories/SquiggleEditor.stories.mdx +++ b/packages/components/src/stories/SquiggleEditor.stories.mdx @@ -14,7 +14,7 @@ the distribution. {Template.bind({})} @@ -27,7 +27,7 @@ You can also name variables like so: {Template.bind({})} diff --git a/packages/components/src/stories/SquigglePartial.stories.mdx b/packages/components/src/stories/SquigglePartial.stories.mdx index b4446402..c4f4814a 100644 --- a/packages/components/src/stories/SquigglePartial.stories.mdx +++ b/packages/components/src/stories/SquigglePartial.stories.mdx @@ -15,7 +15,7 @@ instead returns bindings that can be used by further Squiggle Editors. {Template.bind({})} @@ -36,12 +36,12 @@ instead returns bindings that can be used by further Squiggle Editors. <> diff --git a/packages/website/docs/Discussions/Bugs.mdx b/packages/website/docs/Discussions/Bugs.mdx index a39223a9..2c077eb0 100644 --- a/packages/website/docs/Discussions/Bugs.mdx +++ b/packages/website/docs/Discussions/Bugs.mdx @@ -16,7 +16,7 @@ If you take the pointwise mixture of two distributions with very different means In the following case, the mean of the mixture should be equal to the sum of the means of the parts. These are shown as the first two displayed variables. These variables diverge as the underlying distributions change. diff --git a/packages/website/docs/Guides/DistributionCreation.mdx b/packages/website/docs/Guides/DistributionCreation.mdx index 5e84b47f..8ca22294 100644 --- a/packages/website/docs/Guides/DistributionCreation.mdx +++ b/packages/website/docs/Guides/DistributionCreation.mdx @@ -22,22 +22,22 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no When 5 to 10 is entered, both numbers are positive, so it generates a lognormal distribution with 5th and 95th percentiles at 5 and 10. - + 5 to 10 does the same thing as to(5,10). - + When -5 to 5 is entered, there's negative values, so it generates a normal distribution. This has 5th and 95th percentiles at 5 and 10. - + It's very easy to generate distributions with very long tails. If this happens, you can click the "log x scale" box to view this using a log scale. - + @@ -76,16 +76,16 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can - + - + - + - + @@ -111,7 +111,7 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can In this case, I have a 20% chance of spending 0 time with it. I might estimate my hours with,

@@ -125,7 +125,7 @@ mx(hours_the_project_will_take, 0, [chance_of_doing_anything, 1 - chance_of_doin very wide, just in case they were dramatically off for some weird reason.

- + - + @@ -165,7 +165,7 @@ Creates a [log-normal distribution](https://en.wikipedia.org/wiki/Log-normal_dis you take the log of our lognormal distribution. They can be difficult to directly reason about. Because of this complexity, we recommend typically using the to syntax instead of estimating `mu` and `sigma` directly. - + ### Arguments @@ -185,7 +185,7 @@ Because of this complexity, we recommend typically using the to ) with the given low and high values. - + ### Arguments @@ -236,19 +236,19 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi - + - + - + - + - + @@ -264,19 +264,19 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w - + - + - + - + - + @@ -295,16 +295,16 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w Examples - + - + - + - + @@ -316,7 +316,7 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w Creates an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) with the given rate. - + ### Arguments @@ -334,7 +334,7 @@ Creates a [triangular distribution](https://en.wikipedia.org/wiki/Triangular_dis - `mode`: Number greater than `low` - `high`: Number greater than `mode` - + ## FromSamples @@ -342,7 +342,7 @@ Creates a [triangular distribution](https://en.wikipedia.org/wiki/Triangular_dis Creates a sample set distribution using an array of samples. - + ### Arguments diff --git a/packages/website/docs/Guides/Functions.mdx b/packages/website/docs/Guides/Functions.mdx index be579834..a58df345 100644 --- a/packages/website/docs/Guides/Functions.mdx +++ b/packages/website/docs/Guides/Functions.mdx @@ -16,7 +16,7 @@ the value of one random sample chosen from the first distribution and the value chosen from the second distribution. @@ -28,7 +28,7 @@ the distribution of the value of one random sample chosen from the first distrib the value of one random sample chosen from the second distribution. @@ -40,14 +40,14 @@ the value of one random sample chosen from the first distribution times the valu chosen from the second distribution. We also provide concatenation of two distributions as a syntax sugar for `*` - + ### Division @@ -58,7 +58,7 @@ chosen from the second distribution. If the second distribution has some values tends to be particularly unstable. @@ -69,12 +69,12 @@ A projection over a contracted x-axis. The exponentiation operation represents t the exponentiation of the value of one random sample chosen from the first distribution to the power of the value one random sample chosen from the second distribution. - + ### Taking the base `e` exponential @@ -83,19 +83,19 @@ exp(dist)`} A projection over a stretched x-axis. Base `x` @@ -114,7 +114,7 @@ For every point on the x-axis, operate the corresponding points in the y axis of TODO: this isn't in the new interpreter/parser yet. @@ -124,7 +124,7 @@ dist1 .+ dist2`} TODO: this isn't in the new interpreter/parser yet. @@ -132,7 +132,7 @@ dist1 .- dist2`} ### Pointwise multiplication @@ -140,7 +140,7 @@ dist1 .* dist2`} ### Pointwise division @@ -148,7 +148,7 @@ dist1 ./ dist2`} ### Pointwise exponentiation @@ -160,7 +160,7 @@ dist1 .^ dist2`} The `pdf(dist, x)` function returns the density of a distribution at the given point x. - + #### Validity @@ -172,7 +172,7 @@ given point x. The `cdf(dist, x)` gives the cumulative probability of the distribution or all values lower than x. It is the inverse of `quantile`. - + #### Validity @@ -185,7 +185,7 @@ The `quantile(dist, prob)` gives the value x or which the probability for all va lower than x is equal to prob. It is the inverse of `cdf`. In the literature, it is also known as the quantiles function. - + #### Validity @@ -196,29 +196,29 @@ is also known as the quantiles function. The `mean(distribution)` function gives the mean (expected value) of a distribution. - + ### Sampling a distribution The `sample(distribution)` samples a given distribution. - + ## Converting between distribution formats Recall the [three formats of distributions](https://develop--squiggle-documentation.netlify.app/docs/Discussions/Three-Types-Of-Distributions). We can force any distribution into `SampleSet` format - + Or `PointSet` format - + ### `toSampleSet` has two signatures Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number of samples. If you'd like to provide the number of samples, it has a binary signature as well (floored) - + #### Validity @@ -230,13 +230,13 @@ Some distribution operations (like horizontal shift) return an unnormalized dist We provide a `normalize` function - + #### Validity - Input to `normalize` must be a dist We provide a predicate `isNormalized`, for when we have simple control flow - + #### Validity @@ -246,7 +246,7 @@ We provide a predicate `isNormalized`, for when we have simple control flow You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation. - + Save for a logging side effect, `inspect` does nothing to input and returns it. @@ -254,12 +254,12 @@ Save for a logging side effect, `inspect` does nothing to input and returns it. You can cut off from the left - + You can cut off from the right - + You can cut off from both sides - + diff --git a/packages/website/docs/Guides/Language.mdx b/packages/website/docs/Guides/Language.mdx index 4cfd9ea8..bdc58e41 100644 --- a/packages/website/docs/Guides/Language.mdx +++ b/packages/website/docs/Guides/Language.mdx @@ -9,22 +9,22 @@ import { SquiggleEditor } from "../../src/components/SquiggleEditor"; ### Distributions - + ### Numbers - + ### Arrays ### Records @@ -33,7 +33,7 @@ d.dist`} A statement assigns expressions to names. It looks like ` = ` @@ -42,7 +42,7 @@ A statement assigns expressions to names. It looks like ` = We can define functions diff --git a/yarn.lock b/yarn.lock index ae8a6f60..d7c13cbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4311,7 +4311,7 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.5": +"@types/react-dom@^18.0.0": version "18.0.5" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a" integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==