Respond to PR comments
This commit is contained in:
parent
df3608d9b2
commit
c4d2ad922a
|
@ -20,7 +20,7 @@ Add to `App.js`:
|
||||||
```jsx
|
```jsx
|
||||||
import { SquiggleEditor } from "@quri/squiggle-components";
|
import { SquiggleEditor } from "@quri/squiggle-components";
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
squiggleString="x = beta($alpha, 10); x + $shift"
|
defaultCode="x = beta($alpha, 10); x + $shift"
|
||||||
jsImports={{ alpha: 3, shift: 20 }}
|
jsImports={{ alpha: 3, shift: 20 }}
|
||||||
/>;
|
/>;
|
||||||
```
|
```
|
||||||
|
@ -50,7 +50,7 @@ export function DynamicSquiggleChart({ squiggleString }) {
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
squiggleString={squiggleString}
|
defaultCode={squiggleString}
|
||||||
width={445}
|
width={445}
|
||||||
height={200}
|
height={200}
|
||||||
showSummary={true}
|
showSummary={true}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import { environment, bindings, jsImports } from "@quri/squiggle-lang";
|
import { environment, bindings, jsImports } from "@quri/squiggle-lang";
|
||||||
import { defaultImports, defaultBindings } from "@quri/squiggle-lang";
|
import { defaultImports, defaultBindings } from "@quri/squiggle-lang";
|
||||||
import { SquiggleContainer } from "./SquiggleContainer";
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
||||||
import { useSquigglePartial } from "../lib/hooks";
|
import { useSquigglePartial, useMaybeControlledValue } from "../lib/hooks";
|
||||||
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
||||||
|
|
||||||
const WrappedCodeEditor: React.FC<{
|
const WrappedCodeEditor: React.FC<{
|
||||||
|
@ -28,21 +28,16 @@ export type SquiggleEditorProps = SquiggleChartProps & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SquiggleEditor: React.FC<SquiggleEditorProps> = (props) => {
|
export const SquiggleEditor: React.FC<SquiggleEditorProps> = (props) => {
|
||||||
let defaultCode = props.defaultCode ?? "";
|
const [code, setCode] = useMaybeControlledValue({
|
||||||
const [uncontrolledCode, setCode] = useState(defaultCode);
|
value: props.code,
|
||||||
let code = props.code ?? uncontrolledCode;
|
defaultValue: props.defaultCode,
|
||||||
|
onChange: props.onCodeChange,
|
||||||
|
});
|
||||||
|
|
||||||
let chartProps = { ...props, code };
|
let chartProps = { ...props, code };
|
||||||
return (
|
return (
|
||||||
<SquiggleContainer>
|
<SquiggleContainer>
|
||||||
<WrappedCodeEditor
|
<WrappedCodeEditor code={code} setCode={setCode} />
|
||||||
code={code}
|
|
||||||
setCode={(code) => {
|
|
||||||
if (props.onCodeChange) props.onCodeChange(code);
|
|
||||||
|
|
||||||
if (props.code === undefined) setCode(code);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<SquiggleChart {...chartProps} />
|
<SquiggleChart {...chartProps} />
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
);
|
);
|
||||||
|
@ -66,7 +61,7 @@ export interface SquigglePartialProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
code,
|
code: controlledCode,
|
||||||
defaultCode = "",
|
defaultCode = "",
|
||||||
onChange,
|
onChange,
|
||||||
onCodeChange,
|
onCodeChange,
|
||||||
|
@ -74,11 +69,14 @@ export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
environment,
|
environment,
|
||||||
jsImports = defaultImports,
|
jsImports = defaultImports,
|
||||||
}: SquigglePartialProps) => {
|
}: SquigglePartialProps) => {
|
||||||
const [uncontrolledCode, setCode] = useState(defaultCode);
|
const [code, setCode] = useMaybeControlledValue<string>({
|
||||||
let codeProp = code ?? uncontrolledCode;
|
value: controlledCode,
|
||||||
|
defaultValue: defaultCode,
|
||||||
|
onChange: onCodeChange,
|
||||||
|
});
|
||||||
|
|
||||||
const result = useSquigglePartial({
|
const result = useSquigglePartial({
|
||||||
code: codeProp,
|
code,
|
||||||
bindings,
|
bindings,
|
||||||
environment,
|
environment,
|
||||||
jsImports,
|
jsImports,
|
||||||
|
@ -87,14 +85,7 @@ export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SquiggleContainer>
|
<SquiggleContainer>
|
||||||
<WrappedCodeEditor
|
<WrappedCodeEditor code={code} setCode={setCode} />
|
||||||
code={codeProp}
|
|
||||||
setCode={(code) => {
|
|
||||||
if (onCodeChange) onCodeChange(code);
|
|
||||||
|
|
||||||
if (code === undefined) setCode(code);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{result.tag !== "Ok" ? <SquiggleErrorAlert error={result.value} /> : null}
|
{result.tag !== "Ok" ? <SquiggleErrorAlert error={result.value} /> : null}
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { FC, Fragment, useState, useEffect } from "react";
|
import React, { FC, Fragment, useState, useEffect } from "react";
|
||||||
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
import { useMaybeControlledValue } from "../lib/hooks";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
import {
|
import {
|
||||||
|
@ -216,7 +217,11 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
onSettingsChange,
|
onSettingsChange,
|
||||||
showEditor = true,
|
showEditor = true,
|
||||||
}) => {
|
}) => {
|
||||||
const [uncontrolledCode, setUncontrolledCode] = useState(defaultCode);
|
const [code, setCode] = useMaybeControlledValue({
|
||||||
|
value: controlledCode,
|
||||||
|
defaultValue: defaultCode,
|
||||||
|
onChange: onCodeChange,
|
||||||
|
});
|
||||||
const [importString, setImportString] = useState("{}");
|
const [importString, setImportString] = useState("{}");
|
||||||
const [imports, setImports] = useState({});
|
const [imports, setImports] = useState({});
|
||||||
const [importsAreValid, setImportsAreValid] = useState(true);
|
const [importsAreValid, setImportsAreValid] = useState(true);
|
||||||
|
@ -261,8 +266,6 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const code = controlledCode ?? uncontrolledCode;
|
|
||||||
|
|
||||||
const samplingSettings = (
|
const samplingSettings = (
|
||||||
<div className="space-y-6 p-3 max-w-xl">
|
<div className="space-y-6 p-3 max-w-xl">
|
||||||
<div>
|
<div>
|
||||||
|
@ -434,14 +437,8 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
const firstTab = vars.showEditor ? (
|
const firstTab = vars.showEditor ? (
|
||||||
<div className="border border-slate-200">
|
<div className="border border-slate-200">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={code}
|
value={code ?? ""}
|
||||||
onChange={(newCode) => {
|
onChange={setCode}
|
||||||
if (controlledCode === undefined) {
|
|
||||||
// uncontrolled mode
|
|
||||||
setUncontrolledCode(newCode);
|
|
||||||
}
|
|
||||||
onCodeChange?.(newCode);
|
|
||||||
}}
|
|
||||||
oneLine={false}
|
oneLine={false}
|
||||||
showGutter={true}
|
showGutter={true}
|
||||||
height={height - 1}
|
height={height - 1}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
run,
|
run,
|
||||||
runPartial,
|
runPartial,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
type SquiggleArgs<T extends ReturnType<typeof run | typeof runPartial>> = {
|
type SquiggleArgs<T extends ReturnType<typeof run | typeof runPartial>> = {
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -42,3 +42,23 @@ export const useSquigglePartial = (
|
||||||
export const useSquiggle = (args: SquiggleArgs<ReturnType<typeof run>>) => {
|
export const useSquiggle = (args: SquiggleArgs<ReturnType<typeof run>>) => {
|
||||||
return useSquiggleAny(args, run);
|
return useSquiggleAny(args, run);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ControlledValueArgs<T> = {
|
||||||
|
value?: T;
|
||||||
|
defaultValue: T;
|
||||||
|
onChange?: (x: T) => void;
|
||||||
|
};
|
||||||
|
export function useMaybeControlledValue<T>(
|
||||||
|
args: ControlledValueArgs<T>
|
||||||
|
): [T, (x: T) => void] {
|
||||||
|
let [uncontrolledValue, setUncontrolledValue] = useState(args.defaultValue);
|
||||||
|
let value = args.value ?? uncontrolledValue;
|
||||||
|
let onChange = (newValue: T) => {
|
||||||
|
if (args.value === undefined) {
|
||||||
|
// uncontrolled mode
|
||||||
|
setUncontrolledValue(newValue);
|
||||||
|
}
|
||||||
|
args.onChange?.(newValue);
|
||||||
|
};
|
||||||
|
return [value, onChange];
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,19 @@ the distribution.
|
||||||
</Story>
|
</Story>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|
||||||
|
It's also possible to create a controlled version of the same component
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story
|
||||||
|
name="Controlled"
|
||||||
|
args={{
|
||||||
|
code: "normal(5,2)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Template.bind({})}
|
||||||
|
</Story>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
You can also name variables like so:
|
You can also name variables like so:
|
||||||
|
|
||||||
<Canvas>
|
<Canvas>
|
||||||
|
|
|
@ -14,7 +14,7 @@ including sampling settings, in squiggle.
|
||||||
<Story
|
<Story
|
||||||
name="Normal"
|
name="Normal"
|
||||||
args={{
|
args={{
|
||||||
initialSquiggleString: "normal(5,2)",
|
defaultCode: "normal(5,2)",
|
||||||
height: 800,
|
height: 800,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user