diff --git a/packages/components/src/components/Alert.tsx b/packages/components/src/components/Alert.tsx index cb579536..52b4a3e4 100644 --- a/packages/components/src/components/Alert.tsx +++ b/packages/components/src/components/Alert.tsx @@ -24,7 +24,7 @@ export const Alert: React.FC<{ children, }) => { return ( -
+
= ({ editorProps={{ $blockScrolling: true, }} - setOptions={{ - enableBasicAutocompletion: false, - enableLiveAutocompletion: false, - }} + setOptions={{}} commands={[ { name: "submit", diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 215031a7..53bd4695 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -1,5 +1,10 @@ import * as React from "react"; -import { SqValue, environment, SqProject } from "@quri/squiggle-lang"; +import { + SqValue, + environment, + SqProject, + defaultEnvironment, +} from "@quri/squiggle-lang"; import { useSquiggle } from "../lib/hooks"; import { SquiggleViewer } from "./SquiggleViewer"; import { JsImports } from "../lib/jsImports"; @@ -66,7 +71,6 @@ type ProjectExecutionProps = { }; const defaultOnChange = () => {}; const defaultImports: JsImports = {}; -const defaultContinues: string[] = []; export const splitSquiggleChartSettings = (props: SquiggleChartProps) => { const { @@ -120,24 +124,15 @@ export const SquiggleChart: React.FC = React.memo( width, height = 200, enableLocalSettings = false, - continues = defaultContinues, + continues, + project, + environment, } = props; - const p = React.useMemo(() => { - if (props.project) { - return props.project; - } else { - const p = SqProject.create(); - if (props.environment) { - p.setEnvironment(props.environment); - } - return p; - } - }, [props.project, props.environment]); - const resultAndBindings = useSquiggle({ + environment, continues, - project: p, + project, code, jsImports, onChange, @@ -153,7 +148,9 @@ export const SquiggleChart: React.FC = React.memo( height={height} distributionPlotSettings={distributionPlotSettings} chartSettings={chartSettings} - environment={p.getEnvironment()} + environment={ + project ? project.getEnvironment() : environment ?? defaultEnvironment + } enableLocalSettings={enableLocalSettings} /> ); diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 38caa04d..73cc0d69 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -54,17 +54,13 @@ export const SquiggleEditor: React.FC = (props) => { width, height = 200, enableLocalSettings = false, + continues, + project, } = props; - const project = React.useMemo(() => { - const p = SqProject.create(); - if (environment) { - p.setEnvironment(environment); - } - return p; - }, [environment]); - const resultAndBindings = useSquiggle({ + environment, + continues, code, project, jsImports, diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 9a778297..6870f6fa 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -251,6 +251,8 @@ export const SquigglePlayground: FC = ({ onSettingsChange, showEditor = true, showShareButton = false, + continues, + project, }) => { const [code, setCode] = useMaybeControlledValue({ value: controlledCode, @@ -305,15 +307,9 @@ export const SquigglePlayground: FC = ({ executionId, } = useRunnerState(code); - const project = React.useMemo(() => { - const p = SqProject.create(); - if (environment) { - p.setEnvironment(environment); - } - return p; - }, [environment]); - const resultAndBindings = useSquiggle({ + environment, + continues, code: renderedCode, project, jsImports: imports, diff --git a/packages/components/src/components/SquiggleViewer/VariableBox.tsx b/packages/components/src/components/SquiggleViewer/VariableBox.tsx index ca0fc875..62431d5e 100644 --- a/packages/components/src/components/SquiggleViewer/VariableBox.tsx +++ b/packages/components/src/components/SquiggleViewer/VariableBox.tsx @@ -45,7 +45,7 @@ export const VariableBox: React.FC = ({ : location.path.items[location.path.items.length - 1]; return ( -
+
void; }; @@ -27,15 +29,25 @@ const importSourceName = (sourceName: string) => "imports-" + sourceName; const defaultContinues = []; export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { + const project = useMemo(() => { + if (args.project) { + return args.project; + } else { + const p = SqProject.create(); + if (args.environment) { + p.setEnvironment(args.environment); + } + return p; + } + }, [args.project, args.environment]); + const sourceName = useMemo(() => uuid.v4(), []); - const env = args.project.getEnvironment(); + const env = project.getEnvironment(); const continues = args.continues || defaultContinues; const result = useMemo( () => { - const project = args.project; - project.setSource(sourceName, args.code); let fullContinues = continues; if (args.jsImports && Object.keys(args.jsImports).length) { @@ -59,7 +71,7 @@ export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { args.executionId, sourceName, continues, - args.project, + project, env, ] ); @@ -75,11 +87,11 @@ export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { useEffect(() => { return () => { - args.project.removeSource(sourceName); - if (args.project.getSource(importSourceName(sourceName))) - args.project.removeSource(importSourceName(sourceName)); + project.removeSource(sourceName); + if (project.getSource(importSourceName(sourceName))) + project.removeSource(importSourceName(sourceName)); }; - }, [args.project, sourceName]); + }, [project, sourceName]); return result; }; diff --git a/packages/components/test/basic.test.tsx b/packages/components/test/basic.test.tsx index e77f104b..37585461 100644 --- a/packages/components/test/basic.test.tsx +++ b/packages/components/test/basic.test.tsx @@ -1,9 +1,14 @@ -import { render } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import React from "react"; import "@testing-library/jest-dom"; -import { SquiggleChart } from "../src/index"; +import { + SquiggleChart, + SquiggleEditor, + SquigglePlayground, +} from "../src/index"; +import { SqProject } from "@quri/squiggle-lang"; -test("Logs nothing on render", async () => { +test("Chart logs nothing on render", async () => { const { unmount } = render(); unmount(); @@ -11,3 +16,38 @@ test("Logs nothing on render", async () => { expect(console.warn).not.toBeCalled(); expect(console.error).not.toBeCalled(); }); + +test("Editor logs nothing on render", async () => { + const { unmount } = render(); + unmount(); + + expect(console.log).not.toBeCalled(); + expect(console.warn).not.toBeCalled(); + expect(console.error).not.toBeCalled(); +}); + +test("Project dependencies work in editors", async () => { + const project = SqProject.create(); + + render(); + const source = project.getSourceIds()[0]; + const { container } = render( + + ); + expect(container).toHaveTextContent("2"); +}); + +test("Project dependencies work in playgrounds", async () => { + const project = SqProject.create(); + project.setSource("depend", "x = 1"); + + render( + + ); + // We must await here because SquigglePlayground loads results asynchronously + expect(await screen.findByRole("status")).toHaveTextContent("2"); +});