diff --git a/packages/components/package.json b/packages/components/package.json index 8e11a913..24d2fa85 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@quri/squiggle-components", - "version": "0.2.23", + "version": "0.2.24", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^0.7.2", diff --git a/packages/components/src/components/SquiggleEditorWithImportedBindings.tsx b/packages/components/src/components/SquiggleEditorWithImportedBindings.tsx new file mode 100644 index 00000000..5dcc3241 --- /dev/null +++ b/packages/components/src/components/SquiggleEditorWithImportedBindings.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { SquiggleEditor } from "./SquiggleEditor"; +import type { SquiggleEditorProps } from "./SquiggleEditor"; +import { runPartial, defaultBindings } from "@quri/squiggle-lang"; +import type { + result, + errorValue, + bindings as bindingsType, +} from "@quri/squiggle-lang"; + +function resultDefault(x: result): bindingsType { + switch (x.tag) { + case "Ok": + return x.value; + case "Error": + return defaultBindings; + } +} + +export type SquiggleEditorWithImportedBindingsProps = SquiggleEditorProps & { + bindingsImportUrl: string; +}; + +export const SquiggleEditorWithImportedBindings: React.FC< + SquiggleEditorWithImportedBindingsProps +> = (props) => { + const { bindingsImportUrl, ...editorProps } = props; + const [bindingsResult, setBindingsResult] = React.useState({ + tag: "Ok", + value: defaultBindings, + } as result); + React.useEffect(() => { + async function retrieveBindings(fileName: string) { + let contents = await fetch(fileName).then((response) => { + return response.text(); + }); + setBindingsResult( + runPartial( + contents, + editorProps.bindings, + editorProps.environment, + editorProps.jsImports + ) + ); + } + retrieveBindings(bindingsImportUrl); + }, [bindingsImportUrl]); + const deliveredBindings = resultDefault(bindingsResult); + return ( + + ); +}; diff --git a/packages/components/src/components/SquiggleItem.tsx b/packages/components/src/components/SquiggleItem.tsx deleted file mode 100644 index 52330e8b..00000000 --- a/packages/components/src/components/SquiggleItem.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import * as React from "react"; -import { - squiggleExpression, - environment, - declaration, -} from "@quri/squiggle-lang"; -import { NumberShower } from "./NumberShower"; -import { - DistributionChart, - DistributionPlottingSettings, -} from "./DistributionChart"; -import { FunctionChart, FunctionChartSettings } from "./FunctionChart"; - -function getRange(x: declaration) { - const first = x.args[0]; - switch (first.tag) { - case "Float": { - return { floats: { min: first.value.min, max: first.value.max } }; - } - case "Date": { - return { time: { min: first.value.min, max: first.value.max } }; - } - } -} - -function getChartSettings(x: declaration): FunctionChartSettings { - const range = getRange(x); - const min = range.floats ? range.floats.min : 0; - const max = range.floats ? range.floats.max : 10; - return { - start: min, - stop: max, - count: 20, - }; -} - -interface VariableBoxProps { - heading: string; - children: React.ReactNode; - showTypes: boolean; -} - -export const VariableBox: React.FC = ({ - heading = "Error", - children, - showTypes = false, -}) => { - if (showTypes) { - return ( -
-
-
{heading}
-
-
{children}
-
- ); - } else { - return
{children}
; - } -}; - -export interface SquiggleItemProps { - /** The input string for squiggle */ - expression: squiggleExpression; - width?: number; - height: number; - distributionPlotSettings: DistributionPlottingSettings; - /** Whether to show type information */ - showTypes: boolean; - /** Settings for displaying functions */ - chartSettings: FunctionChartSettings; - /** Environment for further function executions */ - environment: environment; -} - -export const SquiggleItem: React.FC = ({ - expression, - width, - height, - distributionPlotSettings, - showTypes = false, - chartSettings, - environment, -}) => { - switch (expression.tag) { - case "number": - return ( - -
- -
-
- ); - case "distribution": { - const distType = expression.value.type(); - return ( - - {distType === "Symbolic" && showTypes ? ( -
{expression.value.toString()}
- ) : null} - -
- ); - } - case "string": - return ( - - " - - {expression.value} - - " - - ); - case "boolean": - return ( - - {expression.value.toString()} - - ); - case "symbol": - return ( - - Undefined Symbol: - {expression.value} - - ); - case "call": - return ( - - {expression.value} - - ); - case "array": - return ( - - {expression.value.map((r, i) => ( -
-
-
{i}
-
-
- -
-
- ))} -
- ); - case "record": - return ( - -
- {Object.entries(expression.value).map(([key, r]) => ( -
-
-
{key}:
-
-
- -
-
- ))} -
-
- ); - case "arraystring": - return ( - - {expression.value.map((r) => `"${r}"`).join(", ")} - - ); - case "date": - return ( - - {expression.value.toDateString()} - - ); - case "void": - return ( - - {"Void"} - - ); - case "timeDuration": { - return ( - - - - ); - } - case "lambda": - return ( - -
{`function(${expression.value.parameters.join( - "," - )})`}
- -
- ); - case "lambdaDeclaration": { - return ( - - - - ); - } - case "module": { - return ( - -
- {Object.entries(expression.value) - .filter(([key, r]) => key !== "Math") - .map(([key, r]) => ( -
-
-
{key}:
-
-
- -
-
- ))} -
-
- ); - } - default: { - return ( -
- No display for type: {" "} - {expression.tag} -
- ); - } - } -}; diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 837c4bed..626fc354 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -13,6 +13,7 @@ import { yupResolver } from "@hookform/resolvers/yup"; import { ChartSquareBarIcon, CheckCircleIcon, + ClipboardCopyIcon, CodeIcon, CogIcon, CurrencyDollarIcon, @@ -40,6 +41,7 @@ import { defaultColor, defaultTickFormat, } from "../lib/distributionSpecBuilder"; +import { Button } from "./ui/Button"; type PlaygroundProps = SquiggleChartProps & { /** The initial squiggle string to put in the playground */ @@ -49,6 +51,8 @@ type PlaygroundProps = SquiggleChartProps & { onSettingsChange?(settings: any): void; /** Should we show the editor? */ showEditor?: boolean; + /** Useful for playground on squiggle website, where we update the anchor link based on current code and settings */ + showShareButton?: boolean; }; const schema = yup @@ -197,6 +201,29 @@ const RunControls: React.FC<{ ); }; +const ShareButton: React.FC = () => { + const [isCopied, setIsCopied] = useState(false); + const copy = () => { + navigator.clipboard.writeText((window.top || window).location.href); + setIsCopied(true); + setTimeout(() => setIsCopied(false), 1000); + }; + return ( +
+ +
+ ); +}; + type PlaygroundContextShape = { getLeftPanelElement: () => HTMLDivElement | undefined; }; @@ -220,6 +247,7 @@ export const SquigglePlayground: FC = ({ onCodeChange, onSettingsChange, showEditor = true, + showShareButton = false, }) => { const [code, setCode] = useMaybeControlledValue({ value: controlledCode, @@ -370,13 +398,16 @@ export const SquigglePlayground: FC = ({ - +
+ + {showShareButton && } +
{vars.showEditor ? withEditor : withoutEditor} diff --git a/packages/components/src/components/ui/Button.tsx b/packages/components/src/components/ui/Button.tsx new file mode 100644 index 00000000..008b2084 --- /dev/null +++ b/packages/components/src/components/ui/Button.tsx @@ -0,0 +1,22 @@ +import clsx from "clsx"; +import React from "react"; + +type Props = { + onClick: () => void; + children: React.ReactNode; + wide?: boolean; // stretch the button horizontally +}; + +export const Button: React.FC = ({ onClick, wide, children }) => { + return ( + + ); +}; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index ce6e107c..f51ab57a 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -2,5 +2,6 @@ export { SquiggleChart } from "./components/SquiggleChart"; export { SquiggleEditor, SquigglePartial } from "./components/SquiggleEditor"; export { SquigglePlayground } from "./components/SquigglePlayground"; export { SquiggleContainer } from "./components/SquiggleContainer"; +export { SquiggleEditorWithImportedBindings } from "./components/SquiggleEditorWithImportedBindings"; export { mergeBindings } from "@quri/squiggle-lang"; diff --git a/packages/components/src/stories/SquigglePlayground.stories.mdx b/packages/components/src/stories/SquigglePlayground.stories.mdx index 0c198f42..c9c7c3eb 100644 --- a/packages/components/src/stories/SquigglePlayground.stories.mdx +++ b/packages/components/src/stories/SquigglePlayground.stories.mdx @@ -21,3 +21,16 @@ including sampling settings, in squiggle. {Template.bind({})} + + + + {Template.bind({})} + + diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res index 6c133332..ec6c4fd4 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res @@ -1,6 +1,7 @@ module Bindings = Reducer_Bindings -let internalStdLib = Bindings.emptyBindings->SquiggleLibrary_Math.makeBindings->SquiggleLibrary_Versions.makeBindings +let internalStdLib = + Bindings.emptyBindings->SquiggleLibrary_Math.makeBindings->SquiggleLibrary_Versions.makeBindings @genType let externalStdLib = internalStdLib->Bindings.toTypeScriptBindings diff --git a/packages/vscode-ext/README.md b/packages/vscode-ext/README.md index 1c529ddd..cb161038 100644 --- a/packages/vscode-ext/README.md +++ b/packages/vscode-ext/README.md @@ -9,7 +9,7 @@ Features: - Preview `.squiggle` files in a preview pane - Syntax highlighting for `.squiggle` and `.squiggleU` files -## Installation +## Installation You can install this extension by going to the "extensions" tab, searching for "Squiggle", and then installing it. @@ -23,7 +23,7 @@ After loading a `.squiggle` file, an "Open Preview" button will appear. If you c ### Configuration (optional) -Some preview settings, e.g. whether to show the summary table or types of outputs, can be configurable on in the VS Code settings and persist between different preview sessions. The VS Code settings can be accessed with the shortcut `Ctrl+,` with `Ctrl+Shift+P` + searching "Open Settings", or by accessing a file like `$HOME/.config/Code/User/settings.json` in Linux (see [here](https://stackoverflow.com/questions/65908987/how-can-i-open-visual-studio-codes-settings-json-file)) for other operating systems. +Some preview settings, e.g. whether to show the summary table or types of outputs, can be configurable on in the VS Code settings and persist between different preview sessions. The VS Code settings can be accessed with the shortcut `Ctrl+,` with `Ctrl+Shift+P` + searching "Open Settings", or by accessing a file like `$HOME/.config/Code/User/settings.json` in Linux (see [here](https://stackoverflow.com/questions/65908987/how-can-i-open-visual-studio-codes-settings-json-file)) for other operating systems. ![](./images/vs-code-settings.png) diff --git a/packages/website/docs/Guides/DistributionCreation.mdx b/packages/website/docs/Guides/DistributionCreation.mdx index a0833a6d..eb796f77 100644 --- a/packages/website/docs/Guides/DistributionCreation.mdx +++ b/packages/website/docs/Guides/DistributionCreation.mdx @@ -17,7 +17,7 @@ The `to` function is an easy way to generate simple distributions using predicte If both values are above zero, a `lognormal` distribution is used. If not, a `normal` distribution is used. - + When 5 to 10 is entered, both numbers are positive, so it generates a lognormal distribution with 5th and 95th percentiles at 5 and @@ -74,7 +74,7 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no The `mixture` mixes combines multiple distributions to create a mixture. You can optionally pass in a list of proportional weights. - + @@ -139,7 +139,7 @@ mx(forecast, forecast_if_completely_wrong, [1-chance_completely_wrong, chance_co Creates a [normal distribution](https://en.wikipedia.org/wiki/Normal_distribution) with the given mean and standard deviation. - + @@ -234,7 +234,7 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi `pointMass()` distributions are currently the only discrete distributions accessible in Squiggle. - + @@ -263,7 +263,7 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) with the given `alpha` and `beta` values. For a good summary of the beta distribution, see [this explanation](https://stats.stackexchange.com/a/47782) on Stack Overflow. - + @@ -300,7 +300,7 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w

Examples - + diff --git a/packages/website/docs/Internal/ImportIntoMdx.mdx b/packages/website/docs/Internal/ImportIntoMdx.mdx new file mode 100644 index 00000000..683f9311 --- /dev/null +++ b/packages/website/docs/Internal/ImportIntoMdx.mdx @@ -0,0 +1,37 @@ +--- +title: How to import squiggle files into `.mdx` documents +sidebar_position: 5 +--- + +import { SquiggleEditorWithImportedBindings } from "../../src/components/SquiggleEditor"; + +_Proof of concept_ + +## Consider the following squiggle file + +In our docusaurus repo, we have a static asset called `demo.squiggle`. It looks like this + +```js +x = 1 to 2 +y = {a: x, b: 1e1} +f(t) = normal(t, 1.1) +z = y.b * y.a +``` + +We can call `f(z)` upon the assignments in `demo.squiggle` like so: + +```jsx +import { SquiggleEditorWithImportedBindings } from "../../src/components/SquiggleEditor"; + +; +``` + +Which would then look exactly like + + diff --git a/packages/website/package.json b/packages/website/package.json index 986b44c1..11e83791 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -15,7 +15,7 @@ "@docusaurus/core": "2.0.0-rc.1", "@docusaurus/preset-classic": "2.0.0-rc.1", "@heroicons/react": "^1.0.6", - "@quri/squiggle-components": "^0.2.20", + "@quri/squiggle-components": "^0.2.23", "base64-js": "^1.5.1", "clsx": "^1.2.1", "hast-util-is-element": "2.1.2", diff --git a/packages/website/src/components/SquiggleEditor.jsx b/packages/website/src/components/SquiggleEditor.jsx index d8404b82..353fa0b2 100644 --- a/packages/website/src/components/SquiggleEditor.jsx +++ b/packages/website/src/components/SquiggleEditor.jsx @@ -12,3 +12,15 @@ export function SquiggleEditor(props) { ); } + +export function SquiggleEditorWithImportedBindings(props) { + return ( + }> + {() => { + const LibComponent = + require("@quri/squiggle-components").SquiggleEditorWithImportedBindings; + return ; + }} + + ); +} diff --git a/packages/website/src/pages/playground.js b/packages/website/src/pages/playground.js index 1f33d54d..4192f31a 100644 --- a/packages/website/src/pages/playground.js +++ b/packages/website/src/pages/playground.js @@ -44,6 +44,7 @@ export default function PlaygroundPage() { const playgroundProps = { defaultCode: "normal(0,1)", height: 700, + showShareButton: true, ...hashData, onCodeChange: (code) => setHashData({ initialSquiggleString: code }), onSettingsChange: (settings) => { diff --git a/packages/website/static/estimates/demo.squiggle b/packages/website/static/estimates/demo.squiggle new file mode 100644 index 00000000..94ab4ac7 --- /dev/null +++ b/packages/website/static/estimates/demo.squiggle @@ -0,0 +1,4 @@ +x = 1 to 2 +y = {a: x, b: 1e1} +f(t) = normal(t, 1.1) +z = y.b * y.a