First attempt at playground configurable toggles

This commit is contained in:
Ozzie Gooen 2022-05-26 10:08:19 -04:00
parent 7b865c95f5
commit c9a54d4c14
6 changed files with 205 additions and 18 deletions

View File

@ -3,18 +3,21 @@
"version": "0.2.20",
"license": "MIT",
"dependencies": {
"@hookform/resolvers": "^2.8.10",
"@quri/squiggle-lang": "^0.2.8",
"@react-hook/size": "^2.1.2",
"lodash": "^4.17.21",
"react": "^18.1.0",
"react-ace": "^10.1.0",
"react-dom": "^18.1.0",
"react-hook-form": "^7.31.2",
"react-use": "^17.4.0",
"react-vega": "^7.5.1",
"styled-components": "^5.3.5",
"vega": "^5.22.1",
"vega-embed": "^6.20.6",
"vega-lite": "^5.2.0"
"vega-lite": "^5.2.0",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.17.12",

View File

@ -45,6 +45,7 @@ interface FunctionChartProps {
fn: lambdaValue;
chartSettings: FunctionChartSettings;
environment: environment;
height: number;
}
type percentiles = {
@ -149,6 +150,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
fn,
chartSettings,
environment,
height
}: FunctionChartProps) => {
let [mouseOverlay, setMouseOverlay] = React.useState(0);
function handleHover(_name: string, value: unknown) {
@ -172,7 +174,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
<DistributionChart
distribution={mouseItem.value.value}
width={400}
height={140}
height={50}
showSummary={false}
/>
) : (
@ -188,6 +190,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
<>
<SquigglePercentilesChart
data={{ facet: getPercentilesMemoized.percentiles }}
height={height}
actions={false}
signalListeners={signalListeners}
/>

View File

@ -0,0 +1,55 @@
import _ from "lodash";
import React, { FC } from "react";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-github";
import {
jsImports,
defaultImports,
} from "@quri/squiggle-lang";
interface CodeEditorProps {
value: string;
onChange: (value: string) => void;
oneLine?: boolean;
width?: number;
height: number;
showGutter?: boolean;
}
export let JsonEditor: FC<CodeEditorProps> = ({
value,
onChange,
oneLine = false,
showGutter = false,
height,
}: CodeEditorProps) => {
let lineCount = value.split("\n").length;
let id = _.uniqueId();
return (
<AceEditor
value={value}
mode="json"
theme="github"
width={"100%"}
height={String(height) + "px"}
minLines={oneLine ? lineCount : undefined}
maxLines={oneLine ? lineCount : undefined}
showGutter={showGutter}
highlightActiveLine={false}
showPrintMargin={false}
onChange={onChange}
name={id}
editorProps={{
$blockScrolling: true,
}}
setOptions={{
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
}}
/>
);
};
export default JsonEditor;

View File

@ -207,6 +207,7 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
<FunctionChart
fn={expression.value}
chartSettings={chartSettings}
height={height}
environment={{
sampleCount: environment.sampleCount / 10,
xyPointLength: environment.xyPointLength / 10,

View File

@ -3,7 +3,11 @@ import React, { FC, ReactElement, useState } from "react";
import ReactDOM from "react-dom";
import { SquiggleChart } from "./SquiggleChart";
import CodeEditor from "./CodeEditor";
import JsonEditor from "./JsonEditor";
import styled from "styled-components";
import { useForm, useWatch } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import {
defaultBindings,
environment,
@ -87,6 +91,32 @@ interface PlaygroundProps {
showSummary?: boolean;
}
const schema = yup
.object()
.shape({
sampleCount: yup
.number()
.required()
.positive()
.integer()
.default(1000)
.min(10)
.max(1000000),
xyPointLength: yup
.number()
.required()
.positive()
.integer()
.default(1000)
.min(10)
.max(10000),
chartHeight: yup.number().required().positive().integer().default(350),
showTypes: yup.boolean(),
showControls: yup.boolean(),
showSummary: yup.boolean(),
})
.required();
let SquigglePlayground: FC<PlaygroundProps> = ({
initialSquiggleString = "",
height = 300,
@ -95,9 +125,12 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
showSummary = false,
}: PlaygroundProps) => {
let [squiggleString, setSquiggleString] = useState(initialSquiggleString);
let [sampleCount, setSampleCount] = useState(1000);
let [outputXYPoints, setOutputXYPoints] = useState(1000);
let [pointDistLength, setPointDistLength] = useState(1000);
let [importString, setImportString] = useState("{}");
let [imports, setImports] = useState({});
let [importsAreValid, setImportsAreValid] = useState(true);
let [showTypesInput, setShowTypesInput] = useState(showTypes);
let [showControlsInput, setShowControlsInput] = useState(showControls);
let [showSummaryInput, setShowSummaryInput] = useState(showSummary);
let [diagramStart, setDiagramStart] = useState(0);
let [diagramStop, setDiagramStop] = useState(10);
let [diagramCount, setDiagramCount] = useState(20);
@ -106,12 +139,46 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
stop: diagramStop,
count: diagramCount,
};
const {
register,
formState: { errors },
control,
} = useForm({
resolver: yupResolver(schema),
defaultValues: {
sampleCount: 1000,
xyPointLength: 1000,
chartHeight: 150,
showTypes: showTypes,
showControls: showControls,
showSummary: showSummary,
},
});
const foo = useWatch({
control,
});
let env: environment = {
sampleCount: sampleCount,
xyPointLength: outputXYPoints,
sampleCount: Number(foo.sampleCount),
xyPointLength: Number(foo.xyPointLength),
};
let getChangeJson = (r: string) => {
setImportString(r);
try {
setImports(JSON.parse(r));
setImportsAreValid(true);
} catch (e) {
setImportsAreValid(false);
}
("");
};
return (
<ShowBox height={height}>
<input type="number" {...register("sampleCount")} />
<input type="number" {...register("xyPointLength")} />
<input type="number" {...register("chartHeight")} />
<input type="checkbox" {...register("showTypes")} />
<input type="checkbox" {...register("showControls")} />
<input type="checkbox" {...register("showSummary")} />
<Row>
<Col>
<CodeEditor
@ -121,6 +188,14 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
showGutter={true}
height={height - 3}
/>
<JsonEditor
value={importString}
onChange={getChangeJson}
oneLine={false}
showGutter={true}
height={100}
/>
{importsAreValid ? "Valid" : "INVALID"}
</Col>
<Col>
<Display maxHeight={height - 3}>
@ -128,12 +203,12 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
squiggleString={squiggleString}
environment={env}
chartSettings={chartSettings}
height={150}
showTypes={showTypes}
showControls={showControls}
height={foo.chartHeight}
showTypes={foo.showTypes}
showControls={foo.showControls}
bindings={defaultBindings}
jsImports={defaultImports}
showSummary={showSummary}
jsImports={imports}
showSummary={foo.showSummary}
/>
</Display>
</Col>

View File

@ -1245,6 +1245,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.15.4":
version "7.18.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4"
integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.3.3":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
@ -1839,6 +1846,11 @@
dependencies:
"@hapi/hoek" "^9.0.0"
"@hookform/resolvers@^2.8.10":
version "2.8.10"
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d"
integrity sha512-DDFtNlugsbwAhCJHYp3NcN5LvJrwSsCLPi41Wo5O8UAIbUFnBfY/jW+zKnlX57BZ4jE0j/g6R9rB3JlO89ad0g==
"@humanwhocodes/config-array@^0.9.2":
version "0.9.5"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
@ -4163,7 +4175,7 @@
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5"
integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==
"@types/lodash@^4.14.167", "@types/lodash@^4.14.182":
"@types/lodash@^4.14.167", "@types/lodash@^4.14.175", "@types/lodash@^4.14.182":
version "4.14.182"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2"
integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
@ -4298,10 +4310,10 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.0.1", "@types/react@^18.0.9":
version "18.0.9"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.9.tgz#d6712a38bd6cd83469603e7359511126f122e878"
integrity sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==
"@types/react@*", "@types/react@17.0.43", "@types/react@^18.0.9":
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" "*"
@ -11601,6 +11613,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash.assignin@^4.0.9:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
@ -12290,6 +12307,11 @@ nano-css@^5.3.1:
stacktrace-js "^2.0.2"
stylis "^4.0.6"
nanoclone@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
nanoid@^3.3.1, nanoid@^3.3.3:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
@ -13998,6 +14020,11 @@ prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
object-assign "^4.1.1"
react-is "^16.13.1"
property-expr@^2.0.4:
version "2.0.5"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==
property-information@^5.0.0, property-information@^5.3.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69"
@ -14328,6 +14355,11 @@ react-helmet-async@*, react-helmet-async@^1.3.0:
react-fast-compare "^3.2.0"
shallowequal "^1.1.0"
react-hook-form@^7.31.2:
version "7.31.2"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.2.tgz#efb7ac469810954488b7cf40be4e5017122c6e5e"
integrity sha512-oPudn3YuyzWg//IsT9z2cMEjWocAgHWX/bmueDT8cmsYQnGY5h7/njjvMDfLVv3mbdhYBjslTRnII2MIT7eNCA==
react-inspector@^5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.1.1.tgz#58476c78fde05d5055646ed8ec02030af42953c8"
@ -14525,7 +14557,7 @@ react-vega@^7.5.1:
prop-types "^15.8.1"
vega-embed "^6.5.1"
react@^18.0.0, react@^18.1.0:
react@^18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==
@ -16559,6 +16591,11 @@ topojson-client@^3.1.0:
dependencies:
commander "2"
toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
totalist@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
@ -18440,6 +18477,19 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
yup@^0.32.11:
version "0.32.11"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"
integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/lodash" "^4.14.175"
lodash "^4.17.21"
lodash-es "^4.17.21"
nanoclone "^0.2.1"
property-expr "^2.0.4"
toposort "^2.0.2"
zwitch@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"