Merge branch 'develop' into reducer-type-grammar
This commit is contained in:
commit
9e4a70c516
|
@ -1,3 +1,4 @@
|
||||||
|
import "../src/tailwind.css";
|
||||||
export const parameters = {
|
export const parameters = {
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||||
controls: {
|
controls: {
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
"version": "0.2.20",
|
"version": "0.2.20",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@headlessui/react": "^1.6.4",
|
||||||
|
"@heroicons/react": "^1.0.6",
|
||||||
"@hookform/resolvers": "^2.8.10",
|
"@hookform/resolvers": "^2.8.10",
|
||||||
"@quri/squiggle-lang": "^0.2.8",
|
"@quri/squiggle-lang": "^0.2.8",
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
|
@ -10,10 +12,9 @@
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.1.0",
|
||||||
"react-hook-form": "^7.31.2",
|
"react-hook-form": "^7.31.3",
|
||||||
"react-use": "^17.4.0",
|
"react-use": "^17.4.0",
|
||||||
"react-vega": "^7.5.1",
|
"react-vega": "^7.5.1",
|
||||||
"styled-components": "^5.3.5",
|
|
||||||
"vega": "^5.22.1",
|
"vega": "^5.22.1",
|
||||||
"vega-embed": "^6.20.6",
|
"vega-embed": "^6.20.6",
|
||||||
"vega-lite": "^5.2.0",
|
"vega-lite": "^5.2.0",
|
||||||
|
@ -21,30 +22,32 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.17.12",
|
"@babel/plugin-proposal-private-property-in-object": "^7.17.12",
|
||||||
"@storybook/addon-actions": "^6.5.3",
|
"@storybook/addon-actions": "^6.5.6",
|
||||||
"@storybook/addon-essentials": "^6.5.4",
|
"@storybook/addon-essentials": "^6.5.6",
|
||||||
"@storybook/addon-links": "^6.5.4",
|
"@storybook/addon-links": "^6.5.6",
|
||||||
"@storybook/builder-webpack5": "^6.5.4",
|
"@storybook/builder-webpack5": "^6.5.6",
|
||||||
"@storybook/manager-webpack5": "^6.5.4",
|
"@storybook/manager-webpack5": "^6.5.6",
|
||||||
"@storybook/node-logger": "^6.5.4",
|
"@storybook/node-logger": "^6.5.6",
|
||||||
"@storybook/preset-create-react-app": "^4.1.1",
|
"@storybook/preset-create-react-app": "^4.1.1",
|
||||||
"@storybook/react": "^6.5.4",
|
"@storybook/react": "^6.5.6",
|
||||||
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.2.0",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^14.2.0",
|
"@testing-library/user-event": "^14.2.0",
|
||||||
"@types/jest": "^27.5.0",
|
"@types/jest": "^27.5.0",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^17.0.35",
|
"@types/node": "^17.0.36",
|
||||||
"@types/react": "^18.0.9",
|
"@types/react": "^18.0.9",
|
||||||
"@types/react-dom": "^18.0.4",
|
"@types/react-dom": "^18.0.5",
|
||||||
"@types/styled-components": "^5.1.24",
|
"@types/styled-components": "^5.1.24",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
|
"tailwindcss": "^3.0.24",
|
||||||
"ts-loader": "^9.3.0",
|
"ts-loader": "^9.3.0",
|
||||||
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.7.2",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"webpack": "^5.72.1",
|
"webpack": "^5.72.1",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
|
|
83
packages/components/src/components/Alert.tsx
Normal file
83
packages/components/src/components/Alert.tsx
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import {
|
||||||
|
XCircleIcon,
|
||||||
|
InformationCircleIcon,
|
||||||
|
CheckCircleIcon,
|
||||||
|
} from "@heroicons/react/solid";
|
||||||
|
|
||||||
|
export const Alert: React.FC<{
|
||||||
|
heading: string;
|
||||||
|
backgroundColor: string;
|
||||||
|
headingColor: string;
|
||||||
|
bodyColor: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}> = ({
|
||||||
|
heading = "Error",
|
||||||
|
backgroundColor,
|
||||||
|
headingColor,
|
||||||
|
bodyColor,
|
||||||
|
icon,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={`rounded-md p-4 ${backgroundColor}`}>
|
||||||
|
<div className="flex">
|
||||||
|
<div className="flex-shrink-0">{icon}</div>
|
||||||
|
<div className="ml-3">
|
||||||
|
<h3 className={`text-sm font-medium ${headingColor}`}>{heading}</h3>
|
||||||
|
<div className={`mt-2 text-sm ${bodyColor}`}>{children}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ErrorAlert: React.FC<{
|
||||||
|
heading: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}> = ({ heading = "Error", children }) => (
|
||||||
|
<Alert
|
||||||
|
heading={heading}
|
||||||
|
children={children}
|
||||||
|
backgroundColor="bg-red-100"
|
||||||
|
headingColor="text-red-800"
|
||||||
|
bodyColor="text-red-700"
|
||||||
|
icon={<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MessageAlert: React.FC<{
|
||||||
|
heading: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}> = ({ heading = "Error", children }) => (
|
||||||
|
<Alert
|
||||||
|
heading={heading}
|
||||||
|
children={children}
|
||||||
|
backgroundColor="bg-slate-100"
|
||||||
|
headingColor="text-slate-700"
|
||||||
|
bodyColor="text-slate-700"
|
||||||
|
icon={
|
||||||
|
<InformationCircleIcon
|
||||||
|
className="h-5 w-5 text-slate-400"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SuccessAlert: React.FC<{
|
||||||
|
heading: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}> = ({ heading = "Error", children }) => (
|
||||||
|
<Alert
|
||||||
|
heading={heading}
|
||||||
|
children={children}
|
||||||
|
backgroundColor="bg-green-50"
|
||||||
|
headingColor="text-green-800"
|
||||||
|
bodyColor="text-green-700"
|
||||||
|
icon={
|
||||||
|
<CheckCircleIcon className="h-5 w-5 text-green-400" aria-hidden="true" />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
|
@ -29,6 +29,7 @@ export let CodeEditor: FC<CodeEditorProps> = ({
|
||||||
mode="golang"
|
mode="golang"
|
||||||
theme="github"
|
theme="github"
|
||||||
width={"100%"}
|
width={"100%"}
|
||||||
|
fontSize={14}
|
||||||
height={String(height) + "px"}
|
height={String(height) + "px"}
|
||||||
minLines={oneLine ? lineCount : undefined}
|
minLines={oneLine ? lineCount : undefined}
|
||||||
maxLines={oneLine ? lineCount : undefined}
|
maxLines={oneLine ? lineCount : undefined}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { Vega, VisualizationSpec } from "react-vega";
|
import { Vega, VisualizationSpec } from "react-vega";
|
||||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert } from "./Alert";
|
||||||
import { useSize } from "react-use";
|
import { useSize } from "react-use";
|
||||||
import {
|
import {
|
||||||
linearXScale,
|
linearXScale,
|
||||||
|
@ -16,7 +16,6 @@ import {
|
||||||
linearYScale,
|
linearYScale,
|
||||||
expYScale,
|
expYScale,
|
||||||
} from "./DistributionVegaScales";
|
} from "./DistributionVegaScales";
|
||||||
import styled from "styled-components";
|
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
|
|
||||||
type DistributionChartProps = {
|
type DistributionChartProps = {
|
||||||
|
@ -46,6 +45,12 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
shape.value.discrete.some((x) => x.x <= 0);
|
shape.value.discrete.some((x) => x.x <= 0);
|
||||||
let spec = buildVegaSpec(isLogX, isExpY);
|
let spec = buildVegaSpec(isLogX, isExpY);
|
||||||
let widthProp = width ? width : size.width;
|
let widthProp = width ? width : size.width;
|
||||||
|
if (widthProp < 20) {
|
||||||
|
console.warn(
|
||||||
|
`Width of Distribution is set to ${widthProp}, which is too small`
|
||||||
|
);
|
||||||
|
widthProp = 20;
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether we should disable the checkbox
|
// Check whether we should disable the checkbox
|
||||||
var logCheckbox = (
|
var logCheckbox = (
|
||||||
|
@ -66,7 +71,7 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = (
|
var result = (
|
||||||
<ChartContainer width={widthProp + "px"}>
|
<div style={{ width: widthProp + "px" }}>
|
||||||
<Vega
|
<Vega
|
||||||
spec={spec}
|
spec={spec}
|
||||||
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
||||||
|
@ -74,20 +79,22 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
height={height}
|
height={height}
|
||||||
actions={false}
|
actions={false}
|
||||||
/>
|
/>
|
||||||
{showSummary && <SummaryTable distribution={distribution} />}
|
<div className="flex justify-center">
|
||||||
|
{showSummary && <SummaryTable distribution={distribution} />}
|
||||||
|
</div>
|
||||||
{showControls && (
|
{showControls && (
|
||||||
<div>
|
<div>
|
||||||
{logCheckbox}
|
{logCheckbox}
|
||||||
<CheckBox label="Exp Y scale" value={isExpY} onChange={setExpY} />
|
<CheckBox label="Exp Y scale" value={isExpY} onChange={setExpY} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ChartContainer>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
var result = (
|
var result = (
|
||||||
<ErrorBox heading="Distribution Error">
|
<ErrorAlert heading="Distribution Error">
|
||||||
{distributionErrorToString(shape.value)}
|
{distributionErrorToString(shape.value)}
|
||||||
</ErrorBox>
|
</ErrorAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +103,6 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
return sized;
|
return sized;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ChartContainerProps = { width: string };
|
|
||||||
|
|
||||||
let ChartContainer = styled.div<ChartContainerProps>`
|
|
||||||
width: ${(props) => props.width};
|
|
||||||
`;
|
|
||||||
|
|
||||||
function buildVegaSpec(isLogX: boolean, isExpY: boolean): VisualizationSpec {
|
function buildVegaSpec(isLogX: boolean, isExpY: boolean): VisualizationSpec {
|
||||||
return {
|
return {
|
||||||
...chartSpecification,
|
...chartSpecification,
|
||||||
|
@ -120,10 +121,6 @@ interface CheckBoxProps {
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Label = styled.label<{ disabled: boolean }>`
|
|
||||||
${(props) => props.disabled && "color: #999;"}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const CheckBox = ({
|
export const CheckBox = ({
|
||||||
label,
|
label,
|
||||||
onChange,
|
onChange,
|
||||||
|
@ -139,7 +136,7 @@ export const CheckBox = ({
|
||||||
onChange={() => onChange(!value)}
|
onChange={() => onChange(!value)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<Label disabled={disabled}>{label}</Label>
|
<label className={disabled ? "text-slate-400" : ""}> {label}</label>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -148,34 +145,6 @@ type SummaryTableProps = {
|
||||||
distribution: Distribution;
|
distribution: Distribution;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Table = styled.table`
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-align: center;
|
|
||||||
border-style: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TableHead = styled.thead`
|
|
||||||
border-bottom: 1px solid rgb(141 149 167);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TableHeadCell = styled.th`
|
|
||||||
border-right: 1px solid rgb(141 149 167);
|
|
||||||
border-left: 1px solid rgb(141 149 167);
|
|
||||||
padding: 0.3em;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TableBody = styled.tbody``;
|
|
||||||
|
|
||||||
const Row = styled.tr``;
|
|
||||||
|
|
||||||
const Cell = styled.td`
|
|
||||||
padding: 0.3em;
|
|
||||||
border-right: 1px solid rgb(141 149 167);
|
|
||||||
border-left: 1px solid rgb(141 149 167);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SummaryTable: React.FC<SummaryTableProps> = ({
|
const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
distribution,
|
distribution,
|
||||||
}: SummaryTableProps) => {
|
}: SummaryTableProps) => {
|
||||||
|
@ -194,17 +163,30 @@ const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
return <NumberShower number={x.value} />;
|
return <NumberShower number={x.value} />;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<ErrorBox heading="Distribution Error">
|
<ErrorAlert heading="Distribution Error">
|
||||||
{distributionErrorToString(x.value)}
|
{distributionErrorToString(x.value)}
|
||||||
</ErrorBox>
|
</ErrorAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let TableHeadCell: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => (
|
||||||
|
<th className="border border-slate-200 bg-slate-50 py-1 px-2 text-slate-500 font-semibold">
|
||||||
|
{children}
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
let Cell: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||||
|
<td className="border border-slate-200 py-1 px-2 text-slate-900 ">
|
||||||
|
{children}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table>
|
<table className="border border-collapse border-slate-400">
|
||||||
<TableHead>
|
<thead className="bg-slate-50">
|
||||||
<Row>
|
<tr>
|
||||||
<TableHeadCell>{"Mean"}</TableHeadCell>
|
<TableHeadCell>{"Mean"}</TableHeadCell>
|
||||||
<TableHeadCell>{"5%"}</TableHeadCell>
|
<TableHeadCell>{"5%"}</TableHeadCell>
|
||||||
<TableHeadCell>{"10%"}</TableHeadCell>
|
<TableHeadCell>{"10%"}</TableHeadCell>
|
||||||
|
@ -213,10 +195,10 @@ const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
<TableHeadCell>{"75%"}</TableHeadCell>
|
<TableHeadCell>{"75%"}</TableHeadCell>
|
||||||
<TableHeadCell>{"90%"}</TableHeadCell>
|
<TableHeadCell>{"90%"}</TableHeadCell>
|
||||||
<TableHeadCell>{"95%"}</TableHeadCell>
|
<TableHeadCell>{"95%"}</TableHeadCell>
|
||||||
</Row>
|
</tr>
|
||||||
</TableHead>
|
</thead>
|
||||||
<TableBody>
|
<tbody>
|
||||||
<Row>
|
<tr>
|
||||||
<Cell>{unwrapResult(mean)}</Cell>
|
<Cell>{unwrapResult(mean)}</Cell>
|
||||||
<Cell>{unwrapResult(p5)}</Cell>
|
<Cell>{unwrapResult(p5)}</Cell>
|
||||||
<Cell>{unwrapResult(p10)}</Cell>
|
<Cell>{unwrapResult(p10)}</Cell>
|
||||||
|
@ -225,8 +207,8 @@ const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
<Cell>{unwrapResult(p75)}</Cell>
|
<Cell>{unwrapResult(p75)}</Cell>
|
||||||
<Cell>{unwrapResult(p90)}</Cell>
|
<Cell>{unwrapResult(p90)}</Cell>
|
||||||
<Cell>{unwrapResult(p95)}</Cell>
|
<Cell>{unwrapResult(p95)}</Cell>
|
||||||
</Row>
|
</tr>
|
||||||
</TableBody>
|
</tbody>
|
||||||
</Table>
|
</table>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
const ShowError = styled.div`
|
|
||||||
border: 1px solid #792e2e;
|
|
||||||
background: #eee2e2;
|
|
||||||
padding: 0.4em 0.8em;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const ErrorBox: React.FC<{
|
|
||||||
heading: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}> = ({ heading = "Error", children }) => {
|
|
||||||
return (
|
|
||||||
<ShowError>
|
|
||||||
<h3>{heading}</h3>
|
|
||||||
{children}
|
|
||||||
</ShowError>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -2,7 +2,7 @@ import * as React from "react";
|
||||||
import { lambdaValue, environment, runForeign } from "@quri/squiggle-lang";
|
import { lambdaValue, environment, runForeign } from "@quri/squiggle-lang";
|
||||||
import { FunctionChart1Dist } from "./FunctionChart1Dist";
|
import { FunctionChart1Dist } from "./FunctionChart1Dist";
|
||||||
import { FunctionChart1Number } from "./FunctionChart1Number";
|
import { FunctionChart1Number } from "./FunctionChart1Number";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert, MessageAlert } from "./Alert";
|
||||||
|
|
||||||
export type FunctionChartSettings = {
|
export type FunctionChartSettings = {
|
||||||
start: number;
|
start: number;
|
||||||
|
@ -23,9 +23,16 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
|
||||||
environment,
|
environment,
|
||||||
height,
|
height,
|
||||||
}: FunctionChartProps) => {
|
}: FunctionChartProps) => {
|
||||||
let result1 = runForeign(fn, [chartSettings.start], environment);
|
if (fn.parameters.length > 1) {
|
||||||
let result2 = runForeign(fn, [chartSettings.stop], environment);
|
return (
|
||||||
let getValidResult = () => {
|
<MessageAlert heading="Function Display Not Supported">
|
||||||
|
Only functions with one parameter are displayed.
|
||||||
|
</MessageAlert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const result1 = runForeign(fn, [chartSettings.start], environment);
|
||||||
|
const result2 = runForeign(fn, [chartSettings.stop], environment);
|
||||||
|
const getValidResult = () => {
|
||||||
if (result1.tag === "Ok") {
|
if (result1.tag === "Ok") {
|
||||||
return result1;
|
return result1;
|
||||||
} else if (result2.tag === "Ok") {
|
} else if (result2.tag === "Ok") {
|
||||||
|
@ -34,41 +41,39 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
|
||||||
return result1;
|
return result1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let validResult = getValidResult();
|
const validResult = getValidResult();
|
||||||
let resultType = validResult.tag === "Ok" ? validResult.value.tag : "Error";
|
const resultType =
|
||||||
|
validResult.tag === "Ok" ? validResult.value.tag : ("Error" as const);
|
||||||
|
|
||||||
let component = () => {
|
switch (resultType) {
|
||||||
switch (resultType) {
|
case "distribution":
|
||||||
case "distribution":
|
return (
|
||||||
return (
|
<FunctionChart1Dist
|
||||||
<FunctionChart1Dist
|
fn={fn}
|
||||||
fn={fn}
|
chartSettings={chartSettings}
|
||||||
chartSettings={chartSettings}
|
environment={environment}
|
||||||
environment={environment}
|
height={height}
|
||||||
height={height}
|
/>
|
||||||
/>
|
);
|
||||||
);
|
case "number":
|
||||||
case "number":
|
return (
|
||||||
return (
|
<FunctionChart1Number
|
||||||
<FunctionChart1Number
|
fn={fn}
|
||||||
fn={fn}
|
chartSettings={chartSettings}
|
||||||
chartSettings={chartSettings}
|
environment={environment}
|
||||||
environment={environment}
|
height={height}
|
||||||
height={height}
|
/>
|
||||||
/>
|
);
|
||||||
);
|
case "Error":
|
||||||
case "Error":
|
return (
|
||||||
return (
|
<ErrorAlert heading="Error">The function failed to be run</ErrorAlert>
|
||||||
<ErrorBox heading="Error">The function failed to be run</ErrorBox>
|
);
|
||||||
);
|
default:
|
||||||
default:
|
return (
|
||||||
return (
|
<MessageAlert heading="Function Display Not Supported">
|
||||||
<ErrorBox heading="No Viewer">
|
There is no function visualization for this type of output:{" "}
|
||||||
There is no function visualization for this type of function
|
<span className="font-bold">{resultType}</span>
|
||||||
</ErrorBox>
|
</MessageAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return component();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { createClassFromSpec } from "react-vega";
|
||||||
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
|
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
|
||||||
import { DistributionChart } from "./DistributionChart";
|
import { DistributionChart } from "./DistributionChart";
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
|
||||||
let SquigglePercentilesChart = createClassFromSpec({
|
let SquigglePercentilesChart = createClassFromSpec({
|
||||||
spec: percentilesSpec as Spec,
|
spec: percentilesSpec as Spec,
|
||||||
|
@ -197,7 +197,7 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
|
||||||
{showChart}
|
{showChart}
|
||||||
{_.entries(getPercentilesMemoized.errors).map(
|
{_.entries(getPercentilesMemoized.errors).map(
|
||||||
([errorName, errorPoints]) => (
|
([errorName, errorPoints]) => (
|
||||||
<ErrorBox key={errorName} heading={errorName}>
|
<ErrorAlert key={errorName} heading={errorName}>
|
||||||
Values:{" "}
|
Values:{" "}
|
||||||
{errorPoints
|
{errorPoints
|
||||||
.map((r, i) => <NumberShower key={i} number={r.x} />)
|
.map((r, i) => <NumberShower key={i} number={r.x} />)
|
||||||
|
@ -206,7 +206,7 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
|
||||||
{a}, {b}
|
{a}, {b}
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</ErrorBox>
|
</ErrorAlert>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { createClassFromSpec } from "react-vega";
|
import { createClassFromSpec } from "react-vega";
|
||||||
import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
|
import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
|
||||||
let SquiggleLineChart = createClassFromSpec({
|
let SquiggleLineChart = createClassFromSpec({
|
||||||
spec: lineChartSpec as Spec,
|
spec: lineChartSpec as Spec,
|
||||||
|
@ -110,9 +110,9 @@ export const FunctionChart1Number: React.FC<FunctionChart1NumberProps> = ({
|
||||||
actions={false}
|
actions={false}
|
||||||
/>
|
/>
|
||||||
{getFunctionImageMemoized.errors.map(({ x, value }) => (
|
{getFunctionImageMemoized.errors.map(({ x, value }) => (
|
||||||
<ErrorBox key={x} heading={value}>
|
<ErrorAlert key={x} heading={value}>
|
||||||
Error at point ${x}
|
Error at point ${x}
|
||||||
</ErrorBox>
|
</ErrorAlert>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import styled from "styled-components";
|
|
||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
|
@ -11,12 +10,11 @@ import {
|
||||||
defaultImports,
|
defaultImports,
|
||||||
defaultBindings,
|
defaultBindings,
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
declarationArg,
|
|
||||||
declaration,
|
declaration,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
import { DistributionChart } from "./DistributionChart";
|
import { DistributionChart } from "./DistributionChart";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert } from "./Alert";
|
||||||
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
||||||
|
|
||||||
function getRange<a>(x: declaration<a>) {
|
function getRange<a>(x: declaration<a>) {
|
||||||
|
@ -41,24 +39,6 @@ function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const variableBox = {
|
|
||||||
Component: styled.div`
|
|
||||||
background: white;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 2px;
|
|
||||||
margin-bottom: 0.4em;
|
|
||||||
`,
|
|
||||||
Heading: styled.div`
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding-left: 0.8em;
|
|
||||||
padding-right: 0.8em;
|
|
||||||
padding-top: 0.1em;
|
|
||||||
`,
|
|
||||||
Body: styled.div`
|
|
||||||
padding: 0.4em 0.8em;
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface VariableBoxProps {
|
interface VariableBoxProps {
|
||||||
heading: string;
|
heading: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
@ -72,20 +52,18 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
}: VariableBoxProps) => {
|
}: VariableBoxProps) => {
|
||||||
if (showTypes) {
|
if (showTypes) {
|
||||||
return (
|
return (
|
||||||
<variableBox.Component>
|
<div className="bg-white border border-grey-200 m-2">
|
||||||
<variableBox.Heading>
|
<div className="border-b border-grey-200 p-3">
|
||||||
<h3>{heading}</h3>
|
<h3 className="font-mono">{heading}</h3>
|
||||||
</variableBox.Heading>
|
</div>
|
||||||
<variableBox.Body>{children}</variableBox.Body>
|
<div className="p-3">{children}</div>
|
||||||
</variableBox.Component>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return <div>{children}</div>;
|
return <div>{children}</div>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let RecordKeyHeader = styled.h3``;
|
|
||||||
|
|
||||||
export interface SquiggleItemProps {
|
export interface SquiggleItemProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
expression: squiggleExpression;
|
expression: squiggleExpression;
|
||||||
|
@ -117,7 +95,9 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
case "number":
|
case "number":
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Number" showTypes={showTypes}>
|
<VariableBox heading="Number" showTypes={showTypes}>
|
||||||
<NumberShower precision={3} number={expression.value} />
|
<div className="font-semibold text-slate-600">
|
||||||
|
<NumberShower precision={3} number={expression.value} />
|
||||||
|
</div>
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "distribution": {
|
case "distribution": {
|
||||||
|
@ -146,10 +126,13 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
}
|
}
|
||||||
case "string":
|
case "string":
|
||||||
return (
|
return (
|
||||||
<VariableBox
|
<VariableBox heading="String" showTypes={showTypes}>
|
||||||
heading="String"
|
<span className="text-slate-400">"</span>
|
||||||
showTypes={showTypes}
|
<span className="text-slate-600 font-semibold">
|
||||||
>{`"${expression.value}"`}</VariableBox>
|
{expression.value}
|
||||||
|
</span>
|
||||||
|
<span className="text-slate-400">"</span>
|
||||||
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return (
|
return (
|
||||||
|
@ -160,7 +143,8 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
case "symbol":
|
case "symbol":
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Symbol" showTypes={showTypes}>
|
<VariableBox heading="Symbol" showTypes={showTypes}>
|
||||||
{expression.value}
|
<span className="text-slate-500 mr-2">Undefined Symbol:</span>
|
||||||
|
<span className="text-slate-600">{expression.value}</span>
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "call":
|
case "call":
|
||||||
|
@ -173,17 +157,24 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Array" showTypes={showTypes}>
|
<VariableBox heading="Array" showTypes={showTypes}>
|
||||||
{expression.value.map((r, i) => (
|
{expression.value.map((r, i) => (
|
||||||
<SquiggleItem
|
<div key={i} className="flex flex-row pt-1">
|
||||||
key={i}
|
<div className="flex-none bg-slate-100 rounded-sm px-1">
|
||||||
expression={r}
|
<h3 className="text-slate-400 font-mono">{i}</h3>
|
||||||
width={width !== undefined ? width - 20 : width}
|
</div>
|
||||||
height={50}
|
<div className="px-2 mb-2 grow ">
|
||||||
showTypes={showTypes}
|
<SquiggleItem
|
||||||
showControls={showControls}
|
key={i}
|
||||||
chartSettings={chartSettings}
|
expression={r}
|
||||||
environment={environment}
|
width={width !== undefined ? width - 20 : width}
|
||||||
showSummary={showSummary}
|
height={50}
|
||||||
/>
|
showTypes={showTypes}
|
||||||
|
showControls={showControls}
|
||||||
|
chartSettings={chartSettings}
|
||||||
|
environment={environment}
|
||||||
|
showSummary={showSummary}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
|
@ -191,18 +182,22 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Record" showTypes={showTypes}>
|
<VariableBox heading="Record" showTypes={showTypes}>
|
||||||
{Object.entries(expression.value).map(([key, r]) => (
|
{Object.entries(expression.value).map(([key, r]) => (
|
||||||
<div key={key}>
|
<div key={key} className="flex flex-row pt-1">
|
||||||
<RecordKeyHeader>{key}</RecordKeyHeader>
|
<div className="flex-none pr-2">
|
||||||
<SquiggleItem
|
<h3 className="text-slate-500 font-mono">{key}:</h3>
|
||||||
expression={r}
|
</div>
|
||||||
width={width !== undefined ? width - 20 : width}
|
<div className="pl-2 pr-2 mb-2 grow bg-gray-50 border border-gray-100 rounded-sm">
|
||||||
height={height / 3}
|
<SquiggleItem
|
||||||
showTypes={showTypes}
|
expression={r}
|
||||||
showSummary={showSummary}
|
width={width !== undefined ? width - 20 : width}
|
||||||
showControls={showControls}
|
height={height / 3}
|
||||||
chartSettings={chartSettings}
|
showTypes={showTypes}
|
||||||
environment={environment}
|
showSummary={showSummary}
|
||||||
/>
|
showControls={showControls}
|
||||||
|
chartSettings={chartSettings}
|
||||||
|
environment={environment}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
|
@ -229,6 +224,9 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
case "lambda":
|
case "lambda":
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Function" showTypes={showTypes}>
|
<VariableBox heading="Function" showTypes={showTypes}>
|
||||||
|
<div className="text-amber-700 bg-amber-100 rounded-md font-mono p-1 pl-2 mb-3 mt-1 text-sm">{`function(${expression.value.parameters.join(
|
||||||
|
","
|
||||||
|
)})`}</div>
|
||||||
<FunctionChart
|
<FunctionChart
|
||||||
fn={expression.value}
|
fn={expression.value}
|
||||||
chartSettings={chartSettings}
|
chartSettings={chartSettings}
|
||||||
|
@ -287,12 +285,6 @@ export interface SquiggleChartProps {
|
||||||
showControls?: boolean;
|
showControls?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChartWrapper = styled.div`
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
||||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
|
||||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
||||||
`;
|
|
||||||
|
|
||||||
let defaultChartSettings = { start: 0, stop: 10, count: 20 };
|
let defaultChartSettings = { start: 0, stop: 10, count: 20 };
|
||||||
|
|
||||||
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
|
@ -328,10 +320,10 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
internal = (
|
internal = (
|
||||||
<ErrorBox heading={"Parse Error"}>
|
<ErrorAlert heading={"Parse Error"}>
|
||||||
{errorValueToString(expressionResult.value)}
|
{errorValueToString(expressionResult.value)}
|
||||||
</ErrorBox>
|
</ErrorAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <ChartWrapper>{internal}</ChartWrapper>;
|
return internal;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,6 @@ import * as React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
import * as ReactDOM from "react-dom";
|
||||||
import { SquiggleChart } from "./SquiggleChart";
|
import { SquiggleChart } from "./SquiggleChart";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import styled from "styled-components";
|
|
||||||
import type {
|
import type {
|
||||||
squiggleExpression,
|
squiggleExpression,
|
||||||
environment,
|
environment,
|
||||||
|
@ -15,7 +14,7 @@ import {
|
||||||
defaultImports,
|
defaultImports,
|
||||||
defaultBindings,
|
defaultBindings,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
|
||||||
export interface SquiggleEditorProps {
|
export interface SquiggleEditorProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
|
@ -44,12 +43,6 @@ export interface SquiggleEditorProps {
|
||||||
showSummary?: boolean;
|
showSummary?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Input = styled.div`
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
padding: 0.3em 0.3em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
initialSquiggleString = "",
|
initialSquiggleString = "",
|
||||||
width,
|
width,
|
||||||
|
@ -72,7 +65,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Input>
|
<div className="border border-grey-200 p-2 m-4">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={expression}
|
value={expression}
|
||||||
onChange={setExpression}
|
onChange={setExpression}
|
||||||
|
@ -80,7 +73,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
showGutter={false}
|
showGutter={false}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
/>
|
||||||
</Input>
|
</div>
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
width={width}
|
width={width}
|
||||||
environment={environment}
|
environment={environment}
|
||||||
|
@ -179,7 +172,7 @@ export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Input>
|
<div className="border border-grey-200 p-2 m-4">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={expression}
|
value={expression}
|
||||||
onChange={setExpression}
|
onChange={setExpression}
|
||||||
|
@ -187,8 +180,12 @@ export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
showGutter={false}
|
showGutter={false}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
/>
|
||||||
</Input>
|
</div>
|
||||||
{error !== null ? <ErrorBox heading="Error">{error}</ErrorBox> : <></>}
|
{error !== null ? (
|
||||||
|
<ErrorAlert heading="Error">{error}</ErrorAlert>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,80 +4,17 @@ import ReactDOM from "react-dom";
|
||||||
import { SquiggleChart } from "./SquiggleChart";
|
import { SquiggleChart } from "./SquiggleChart";
|
||||||
import CodeEditor from "./CodeEditor";
|
import CodeEditor from "./CodeEditor";
|
||||||
import JsonEditor from "./JsonEditor";
|
import JsonEditor from "./JsonEditor";
|
||||||
import styled from "styled-components";
|
|
||||||
import { useForm, useWatch } from "react-hook-form";
|
import { useForm, useWatch } from "react-hook-form";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { defaultBindings, environment } from "@quri/squiggle-lang";
|
import { defaultBindings, environment } from "@quri/squiggle-lang";
|
||||||
|
import { Tab } from "@headlessui/react";
|
||||||
interface FieldFloatProps {
|
import { CodeIcon } from "@heroicons/react/solid";
|
||||||
label: string;
|
import { CogIcon } from "@heroicons/react/solid";
|
||||||
className?: string;
|
import { ChartSquareBarIcon } from "@heroicons/react/solid";
|
||||||
value: number;
|
import { CurrencyDollarIcon } from "@heroicons/react/solid";
|
||||||
onChange: (value: number) => void;
|
import { Fragment } from "react";
|
||||||
}
|
import { ErrorAlert, SuccessAlert } from "./Alert";
|
||||||
|
|
||||||
const Input = styled.input``;
|
|
||||||
|
|
||||||
const FormItem = (props: { label: string; children: ReactElement }) => (
|
|
||||||
<div>
|
|
||||||
<label>{props.label}</label>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
function FieldFloat(Props: FieldFloatProps) {
|
|
||||||
let [contents, setContents] = useState(Props.value + "");
|
|
||||||
return (
|
|
||||||
<FormItem label={Props.label}>
|
|
||||||
<Input
|
|
||||||
value={contents}
|
|
||||||
className={Props.className ? Props.className : ""}
|
|
||||||
onChange={(e) => {
|
|
||||||
setContents(e.target.value);
|
|
||||||
let result = parseFloat(contents);
|
|
||||||
if (_.isFinite(result)) {
|
|
||||||
Props.onChange(result);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShowBoxProps {
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ShowBox = styled.div<ShowBoxProps>`
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 2px;
|
|
||||||
height: ${(props) => props.height};
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface TitleProps {
|
|
||||||
readonly maxHeight: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Display = styled.div<TitleProps>`
|
|
||||||
background: #f6f6f6;
|
|
||||||
border-left: 1px solid #eee;
|
|
||||||
height: 100vh;
|
|
||||||
padding: 3px;
|
|
||||||
overflow-y: auto;
|
|
||||||
max-height: ${(props) => props.maxHeight}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface RowProps {
|
|
||||||
readonly leftPercentage: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Row = styled.div<RowProps>`
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: ${(p) => p.leftPercentage}% ${(p) =>
|
|
||||||
100 - p.leftPercentage}%;
|
|
||||||
`;
|
|
||||||
const Col = styled.div``;
|
|
||||||
|
|
||||||
interface PlaygroundProps {
|
interface PlaygroundProps {
|
||||||
/** The initial squiggle string to put in the playground */
|
/** The initial squiggle string to put in the playground */
|
||||||
|
@ -124,6 +61,27 @@ const schema = yup
|
||||||
showControls: yup.boolean(),
|
showControls: yup.boolean(),
|
||||||
showSummary: yup.boolean(),
|
showSummary: yup.boolean(),
|
||||||
showSettingsPage: yup.boolean().default(false),
|
showSettingsPage: yup.boolean().default(false),
|
||||||
|
diagramStart: yup
|
||||||
|
.number()
|
||||||
|
.required()
|
||||||
|
.positive()
|
||||||
|
.integer()
|
||||||
|
.default(0)
|
||||||
|
.min(0),
|
||||||
|
diagramStop: yup
|
||||||
|
.number()
|
||||||
|
.required()
|
||||||
|
.positive()
|
||||||
|
.integer()
|
||||||
|
.default(10)
|
||||||
|
.min(0),
|
||||||
|
diagramCount: yup
|
||||||
|
.number()
|
||||||
|
.required()
|
||||||
|
.positive()
|
||||||
|
.integer()
|
||||||
|
.default(20)
|
||||||
|
.min(2),
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
|
@ -133,12 +91,68 @@ type InputProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const InputItem: React.FC<InputProps> = ({ label, children }) => (
|
const InputItem: React.FC<InputProps> = ({ label, children }) => (
|
||||||
<div>
|
<div className="col-span-4">
|
||||||
<label>{label}</label>
|
<label className="block text-sm font-medium text-gray-600">{label}</label>
|
||||||
{children}
|
<div className="mt-1">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let numberStyle =
|
||||||
|
"max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md";
|
||||||
|
|
||||||
|
function classNames(...classes: string[]) {
|
||||||
|
return classes.filter(Boolean).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
type StyledTabProps = {
|
||||||
|
name: string;
|
||||||
|
iconName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledTab: React.FC<StyledTabProps> = ({ name, iconName }) => {
|
||||||
|
let iconStyle = (isSelected: boolean) =>
|
||||||
|
classNames(
|
||||||
|
"-ml-0.5 mr-2 h-4 w-4 ",
|
||||||
|
isSelected ? "text-slate-500" : "text-gray-400 group-hover:text-gray-900"
|
||||||
|
);
|
||||||
|
|
||||||
|
let icon = (selected: boolean) =>
|
||||||
|
({
|
||||||
|
code: <CodeIcon className={iconStyle(selected)} />,
|
||||||
|
cog: <CogIcon className={iconStyle(selected)} />,
|
||||||
|
squareBar: <ChartSquareBarIcon className={iconStyle(selected)} />,
|
||||||
|
dollar: <CurrencyDollarIcon className={iconStyle(selected)} />,
|
||||||
|
}[iconName]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab key={name} as={Fragment}>
|
||||||
|
{({ selected }) => (
|
||||||
|
<button className="flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100 ">
|
||||||
|
<span
|
||||||
|
className={classNames(
|
||||||
|
"p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
|
||||||
|
selected
|
||||||
|
? "bg-white shadow-sm ring-1 ring-black ring-opacity-5"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{icon(selected)}
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
selected
|
||||||
|
? "text-gray-900"
|
||||||
|
: "text-gray-600 group-hover:text-gray-900"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Tab>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
let SquigglePlayground: FC<PlaygroundProps> = ({
|
let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
initialSquiggleString = "",
|
initialSquiggleString = "",
|
||||||
height = 500,
|
height = 500,
|
||||||
|
@ -150,19 +164,7 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
let [importString, setImportString] = useState("{}");
|
let [importString, setImportString] = useState("{}");
|
||||||
let [imports, setImports] = useState({});
|
let [imports, setImports] = useState({});
|
||||||
let [importsAreValid, setImportsAreValid] = useState(true);
|
let [importsAreValid, setImportsAreValid] = useState(true);
|
||||||
let [diagramStart, setDiagramStart] = useState(0);
|
const { register, control } = useForm({
|
||||||
let [diagramStop, setDiagramStop] = useState(10);
|
|
||||||
let [diagramCount, setDiagramCount] = useState(20);
|
|
||||||
let chartSettings = {
|
|
||||||
start: diagramStart,
|
|
||||||
stop: diagramStop,
|
|
||||||
count: diagramCount,
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
formState: { errors },
|
|
||||||
control,
|
|
||||||
} = useForm({
|
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
sampleCount: 1000,
|
sampleCount: 1000,
|
||||||
|
@ -173,11 +175,19 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
showSummary: showSummary,
|
showSummary: showSummary,
|
||||||
leftSizePercent: 50,
|
leftSizePercent: 50,
|
||||||
showSettingsPage: false,
|
showSettingsPage: false,
|
||||||
|
diagramStart: 0,
|
||||||
|
diagramStop: 10,
|
||||||
|
diagramCount: 20,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const vars = useWatch({
|
const vars = useWatch({
|
||||||
control,
|
control,
|
||||||
});
|
});
|
||||||
|
let chartSettings = {
|
||||||
|
start: Number(vars.diagramStart),
|
||||||
|
stop: Number(vars.diagramStop),
|
||||||
|
count: Number(vars.diagramCount),
|
||||||
|
};
|
||||||
let env: environment = {
|
let env: environment = {
|
||||||
sampleCount: Number(vars.sampleCount),
|
sampleCount: Number(vars.sampleCount),
|
||||||
xyPointLength: Number(vars.xyPointLength),
|
xyPointLength: Number(vars.xyPointLength),
|
||||||
|
@ -191,80 +201,222 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
setImportsAreValid(false);
|
setImportsAreValid(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let samplingSettings = (
|
||||||
|
<div className="space-y-6 p-3 max-w-xl">
|
||||||
|
<InputItem label="Sample Count">
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("sampleCount")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
<p className="mt-2 text-sm text-gray-500">
|
||||||
|
How many samples to use for Monte Carlo simulations. This can
|
||||||
|
occasionally be overridden by specific Squiggle programs.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
</InputItem>
|
||||||
|
<InputItem label="Coordinate Count (For PointSet Shapes)">
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("xyPointLength")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
<p className="mt-2 text-sm text-gray-500">
|
||||||
|
When distributions are converted into PointSet shapes, we need to
|
||||||
|
know how many coordinates to use.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
</InputItem>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
let viewSettings = (
|
||||||
|
<div className="space-y-6 p-3 divide-y divide-gray-200 max-w-xl">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
|
||||||
|
General Display Settings
|
||||||
|
</h3>
|
||||||
|
<InputItem label="Chart Height (in pixels)">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("chartHeight")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
<div className="relative flex items-start pt-3">
|
||||||
|
<div className="flex items-center h-5">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
{...register("showTypes")}
|
||||||
|
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3 text-sm">
|
||||||
|
<label className="font-medium text-gray-700">
|
||||||
|
Show information about displayed types.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2 pt-8">
|
||||||
|
<h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
|
||||||
|
Distribution Display Settings
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div className="relative flex items-start">
|
||||||
|
<div className="flex items-center h-5">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
{...register("showControls")}
|
||||||
|
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3 text-sm">
|
||||||
|
<label className="font-medium text-gray-700">
|
||||||
|
Show toggles to adjust scale of x and y axes
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="relative flex items-start">
|
||||||
|
<div className="flex items-center h-5">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
{...register("showSummary")}
|
||||||
|
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3 text-sm">
|
||||||
|
<label className="font-medium text-gray-700">
|
||||||
|
Show summary statistics
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2 pt-8">
|
||||||
|
<h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
|
||||||
|
Function Display Settings
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className="mt-2 text-sm text-gray-500">
|
||||||
|
When displaying functions of single variables that return numbers or
|
||||||
|
distributions, we need to use defaults for the x-axis. We need to
|
||||||
|
select a minimum and maximum value of x to sample, and a number n of
|
||||||
|
the number of points to sample.
|
||||||
|
</p>
|
||||||
|
<div className="pt-4 grid grid-cols-1 gap-y-4 gap-x-4">
|
||||||
|
<InputItem label="Min X Value">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("diagramStart")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
<InputItem label="Max X Value">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("diagramStop")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
<InputItem label="Points between X min and X max to sample">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("diagramCount")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
let inputVariableSettings = (
|
||||||
|
<div className="space-y-6 p-3 max-w-3xl">
|
||||||
|
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
Import Variables from JSON
|
||||||
|
</h3>
|
||||||
|
<p className="mt-2 text-sm text-gray-500">
|
||||||
|
You can import variables from JSON into your Squiggle code. Variables
|
||||||
|
are accessed with dollar signs. For example, "timeNow" would be accessed
|
||||||
|
as "$timeNow".
|
||||||
|
</p>
|
||||||
|
<div className="border border-slate-200 mt-6 mb-2">
|
||||||
|
<JsonEditor
|
||||||
|
value={importString}
|
||||||
|
onChange={getChangeJson}
|
||||||
|
oneLine={false}
|
||||||
|
showGutter={true}
|
||||||
|
height={150}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-1 pt-2">
|
||||||
|
{importsAreValid ? (
|
||||||
|
<SuccessAlert heading="Valid Json">
|
||||||
|
<></>
|
||||||
|
</SuccessAlert>
|
||||||
|
) : (
|
||||||
|
<ErrorAlert heading="Invalid JSON">
|
||||||
|
You must use valid json in this editor.
|
||||||
|
</ErrorAlert>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShowBox height={height}>
|
<Tab.Group>
|
||||||
<input type="checkbox" {...register("showSettingsPage")} />
|
<div className=" flex-col flex">
|
||||||
<Row leftPercentage={vars.leftSizePercent || 50}>
|
<div className="pb-4">
|
||||||
<Col>
|
<Tab.List className="p-0.5 rounded-md bg-slate-100 hover:bg-slate-200 inline-flex">
|
||||||
{vars.showSettingsPage ? (
|
<StyledTab name="Code" iconName="code" />
|
||||||
<>
|
<StyledTab name="Sampling Settings" iconName="cog" />
|
||||||
<InputItem label="Sample Count">
|
<StyledTab name="View Settings" iconName="squareBar" />
|
||||||
<input type="number" {...register("sampleCount")} />
|
<StyledTab name="Input Variables" iconName="dollar" />
|
||||||
</InputItem>
|
</Tab.List>
|
||||||
<InputItem label="XYPointLength Count">
|
</div>
|
||||||
<input type="number" {...register("xyPointLength")} />
|
<div className="flex" style={{ height: height + "px" }}>
|
||||||
</InputItem>
|
<div className="w-1/2">
|
||||||
<InputItem label="Chart Height (in Pixels)">
|
<Tab.Panels>
|
||||||
<input type="number" {...register("chartHeight")} />
|
<Tab.Panel>
|
||||||
</InputItem>
|
<div className="border border-slate-200">
|
||||||
<InputItem label="Show Types">
|
<CodeEditor
|
||||||
<input type="checkbox" {...register("showTypes")} />
|
value={squiggleString}
|
||||||
</InputItem>
|
onChange={setSquiggleString}
|
||||||
<InputItem label="Show Controls">
|
|
||||||
<input type="checkbox" {...register("showControls")} />
|
|
||||||
</InputItem>
|
|
||||||
<InputItem label="Show Summary Statistics">
|
|
||||||
<input type="checkbox" {...register("showSummary")} />
|
|
||||||
</InputItem>
|
|
||||||
<InputItem label="Editor Width">
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min="1"
|
|
||||||
max="100"
|
|
||||||
className="slider"
|
|
||||||
{...register("leftSizePercent")}
|
|
||||||
/>
|
|
||||||
</InputItem>
|
|
||||||
<InputItem label="Json Editor for imports">
|
|
||||||
<>
|
|
||||||
<JsonEditor
|
|
||||||
value={importString}
|
|
||||||
onChange={getChangeJson}
|
|
||||||
oneLine={false}
|
oneLine={false}
|
||||||
showGutter={true}
|
showGutter={true}
|
||||||
height={100}
|
height={height - 1}
|
||||||
/>
|
/>
|
||||||
{importsAreValid ? "Valid" : "Invalid"}
|
</div>
|
||||||
</>
|
</Tab.Panel>
|
||||||
</InputItem>
|
<Tab.Panel>{samplingSettings}</Tab.Panel>
|
||||||
</>
|
<Tab.Panel>{viewSettings}</Tab.Panel>
|
||||||
) : (
|
<Tab.Panel>{inputVariableSettings}</Tab.Panel>
|
||||||
<CodeEditor
|
</Tab.Panels>
|
||||||
value={squiggleString}
|
</div>
|
||||||
onChange={setSquiggleString}
|
|
||||||
oneLine={false}
|
<div className="w-1/2 p-2 pl-4">
|
||||||
showGutter={true}
|
<div style={{ maxHeight: height + "px" }}>
|
||||||
height={height - 3}
|
<SquiggleChart
|
||||||
/>
|
squiggleString={squiggleString}
|
||||||
)}
|
environment={env}
|
||||||
</Col>
|
chartSettings={chartSettings}
|
||||||
<Col>
|
height={vars.chartHeight}
|
||||||
<Display maxHeight={height - 3}>
|
showTypes={vars.showTypes}
|
||||||
<SquiggleChart
|
showControls={vars.showControls}
|
||||||
squiggleString={squiggleString}
|
bindings={defaultBindings}
|
||||||
environment={env}
|
jsImports={imports}
|
||||||
chartSettings={chartSettings}
|
showSummary={vars.showSummary}
|
||||||
height={vars.chartHeight}
|
/>
|
||||||
showTypes={vars.showTypes}
|
</div>
|
||||||
showControls={vars.showControls}
|
</div>
|
||||||
bindings={defaultBindings}
|
</div>
|
||||||
jsImports={imports}
|
</div>
|
||||||
showSummary={vars.showSummary}
|
</Tab.Group>
|
||||||
/>
|
|
||||||
</Display>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</ShowBox>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default SquigglePlayground;
|
export default SquigglePlayground;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import SquigglePlayground from "../components/SquigglePlayground";
|
import SquigglePlayground from "../components/SquigglePlayground";
|
||||||
import { Canvas, Meta, Story, Props } from "@storybook/addon-docs";
|
import { Canvas, Meta, Story, Props } from "@storybook/addon-docs";
|
||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
<Meta title="Squiggle/SquigglePlayground" component={SquigglePlayground} />
|
<Meta title="Squiggle/SquigglePlayground" component={SquigglePlayground} />
|
||||||
|
|
||||||
|
|
4
packages/components/src/tailwind.css
Normal file
4
packages/components/src/tailwind.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
@tailwind forms;
|
|
@ -33,6 +33,7 @@
|
||||||
"from": {
|
"from": {
|
||||||
"data": "con"
|
"data": "con"
|
||||||
},
|
},
|
||||||
|
"interpolate": "linear",
|
||||||
"encode": {
|
"encode": {
|
||||||
"update": {
|
"update": {
|
||||||
"x": {
|
"x": {
|
||||||
|
@ -48,10 +49,10 @@
|
||||||
"value": 0
|
"value": 0
|
||||||
},
|
},
|
||||||
"fill": {
|
"fill": {
|
||||||
"value": "#4C78A8"
|
"value": "#739ECC"
|
||||||
},
|
},
|
||||||
"interpolate": {
|
"interpolate": {
|
||||||
"value": "monotone"
|
"value": "linear"
|
||||||
},
|
},
|
||||||
"fillOpacity": {
|
"fillOpacity": {
|
||||||
"value": 1
|
"value": 1
|
||||||
|
|
7
packages/components/tailwind.config.js
Normal file
7
packages/components/tailwind.config.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{html,tsx,ts,js,jsx}"],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [require("@tailwindcss/forms")],
|
||||||
|
};
|
|
@ -38,7 +38,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@stdlib/stats": "^0.0.13",
|
"@stdlib/stats": "^0.0.13",
|
||||||
"jstat": "^1.9.5",
|
"jstat": "^1.9.5",
|
||||||
"mathjs": "^10.5.2",
|
"mathjs": "^10.6.0",
|
||||||
"pdfast": "^0.2.0",
|
"pdfast": "^0.2.0",
|
||||||
"rescript": "^9.1.4"
|
"rescript": "^9.1.4"
|
||||||
},
|
},
|
||||||
|
@ -51,18 +51,18 @@
|
||||||
"chalk": "^5.0.1",
|
"chalk": "^5.0.1",
|
||||||
"codecov": "^3.8.3",
|
"codecov": "^3.8.3",
|
||||||
"fast-check": "^2.25.0",
|
"fast-check": "^2.25.0",
|
||||||
"gentype": "^4.3.0",
|
"gentype": "^4.4.0",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moduleserve": "^0.9.1",
|
"moduleserve": "^0.9.1",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"peggy": "^1.2.0",
|
"peggy": "^2.0.0",
|
||||||
"reanalyze": "^2.19.0",
|
"reanalyze": "^2.22.0",
|
||||||
"rescript-fast-check": "^1.1.1",
|
"rescript-fast-check": "^1.1.1",
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^27.1.4",
|
||||||
"ts-loader": "^9.3.0",
|
"ts-loader": "^9.3.0",
|
||||||
"ts-node": "^10.8.0",
|
"ts-node": "^10.8.0",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.7.2",
|
||||||
"webpack": "^5.72.1",
|
"webpack": "^5.72.1",
|
||||||
"webpack-cli": "^4.9.2"
|
"webpack-cli": "^4.9.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
import {
|
import type {
|
||||||
environment,
|
environment,
|
||||||
|
expressionValue,
|
||||||
|
externalBindings,
|
||||||
|
errorValue,
|
||||||
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
|
import {
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
evaluatePartialUsingExternalBindings,
|
evaluatePartialUsingExternalBindings,
|
||||||
evaluateUsingOptions,
|
evaluateUsingOptions,
|
||||||
externalBindings,
|
|
||||||
expressionValue,
|
|
||||||
errorValue,
|
|
||||||
foreignFunctionInterface,
|
foreignFunctionInterface,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export {
|
export {
|
||||||
makeSampleSetDist,
|
makeSampleSetDist,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
distributionErrorToString,
|
distributionErrorToString,
|
||||||
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
|
export type {
|
||||||
distributionError,
|
distributionError,
|
||||||
declarationArg,
|
declarationArg,
|
||||||
declaration,
|
declaration,
|
||||||
|
@ -30,16 +34,8 @@ import {
|
||||||
import { result, resultMap, tag, tagged } from "./types";
|
import { result, resultMap, tag, tagged } from "./types";
|
||||||
import { Distribution, shape } from "./distribution";
|
import { Distribution, shape } from "./distribution";
|
||||||
|
|
||||||
export {
|
export { Distribution, resultMap, defaultEnvironment };
|
||||||
Distribution,
|
export type { result, shape, environment, lambdaValue, squiggleExpression };
|
||||||
squiggleExpression,
|
|
||||||
result,
|
|
||||||
resultMap,
|
|
||||||
shape,
|
|
||||||
lambdaValue,
|
|
||||||
environment,
|
|
||||||
defaultEnvironment,
|
|
||||||
};
|
|
||||||
|
|
||||||
export let defaultSamplingInputs: environment = {
|
export let defaultSamplingInputs: environment = {
|
||||||
sampleCount: 10000,
|
sampleCount: 10000,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
import {
|
import type {
|
||||||
expressionValue,
|
expressionValue,
|
||||||
mixedShape,
|
mixedShape,
|
||||||
sampleSetDist,
|
sampleSetDist,
|
||||||
|
|
|
@ -231,9 +231,8 @@ let doN = (n, fn) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample = (t: t): float => {
|
let sample = (t: t): float => {
|
||||||
let randomItem = Random.float(1.)
|
let randomItem = Random.float(1.0)
|
||||||
let bar = t |> T.Integral.yToX(randomItem)
|
t |> T.Integral.yToX(randomItem)
|
||||||
bar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isFloat = (t: t) =>
|
let isFloat = (t: t) =>
|
||||||
|
|
|
@ -9,6 +9,7 @@ module Wrappers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module Prepare = {
|
module Prepare = {
|
||||||
|
type t = frValue
|
||||||
type ts = array<frValue>
|
type ts = array<frValue>
|
||||||
type err = string
|
type err = string
|
||||||
|
|
||||||
|
@ -26,6 +27,14 @@ module Prepare = {
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module Array = {
|
||||||
|
let openA = (inputs: t): result<ts, err> =>
|
||||||
|
switch inputs {
|
||||||
|
| FRValueArray(n) => Ok(n)
|
||||||
|
| _ => Error(impossibleError)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module ToValueTuple = {
|
module ToValueTuple = {
|
||||||
|
@ -55,6 +64,19 @@ module Prepare = {
|
||||||
values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber)
|
values->ToValueArray.Record.twoArgs->E.R.bind(twoDistOrNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ToArrayRecordPairs = {
|
||||||
|
let twoArgs = (input: t): result<array<ts>, err> => {
|
||||||
|
let array = input->ToValueArray.Array.openA
|
||||||
|
let pairs =
|
||||||
|
array->E.R.bind(pairs =>
|
||||||
|
pairs
|
||||||
|
->E.A2.fmap(xyCoord => [xyCoord]->ToValueArray.Record.twoArgs)
|
||||||
|
->E.A.R.firstErrorOrOpen
|
||||||
|
)
|
||||||
|
pairs
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Process = {
|
module Process = {
|
||||||
|
|
|
@ -30,9 +30,46 @@ module Declaration = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
|
||||||
|
let array = inputs->E.A.unsafe_get(0)->Prepare.ToValueArray.Array.openA
|
||||||
|
let xyCoords =
|
||||||
|
array->E.R.bind(xyCoords =>
|
||||||
|
xyCoords
|
||||||
|
->E.A2.fmap(xyCoord =>
|
||||||
|
[xyCoord]->Prepare.ToValueArray.Record.twoArgs->E.R.bind(Prepare.ToValueTuple.twoNumbers)
|
||||||
|
)
|
||||||
|
->E.A.R.firstErrorOrOpen
|
||||||
|
)
|
||||||
|
let expressionValue =
|
||||||
|
xyCoords
|
||||||
|
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
||||||
|
->E.R2.fmap(r => ReducerInterface_ExpressionValue.EvDistribution(PointSet(makeDist(r))))
|
||||||
|
expressionValue
|
||||||
|
}
|
||||||
|
|
||||||
let registry = [
|
let registry = [
|
||||||
Function.make(
|
Function.make(
|
||||||
~name="FnMake",
|
~name="toContinuousPointSet",
|
||||||
|
~definitions=[
|
||||||
|
FnDefinition.make(
|
||||||
|
~name="toContinuousPointSet",
|
||||||
|
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
||||||
|
~run=(inputs, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Function.make(
|
||||||
|
~name="toDiscretePointSet",
|
||||||
|
~definitions=[
|
||||||
|
FnDefinition.make(
|
||||||
|
~name="toDiscretePointSet",
|
||||||
|
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
||||||
|
~run=(inputs, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Function.make(
|
||||||
|
~name="Declaration",
|
||||||
~definitions=[
|
~definitions=[
|
||||||
FnDefinition.make(~name="declareFn", ~inputs=[Declaration.frType], ~run=(inputs, _) => {
|
FnDefinition.make(~name="declareFn", ~inputs=[Declaration.frType], ~run=(inputs, _) => {
|
||||||
inputs->E.A.unsafe_get(0)->Declaration.fromExpressionValue
|
inputs->E.A.unsafe_get(0)->Declaration.fromExpressionValue
|
||||||
|
|
|
@ -571,6 +571,7 @@ module A = {
|
||||||
let tail = Belt.Array.sliceToEnd(_, 1)
|
let tail = Belt.Array.sliceToEnd(_, 1)
|
||||||
|
|
||||||
let zip = Belt.Array.zip
|
let zip = Belt.Array.zip
|
||||||
|
let unzip = Belt.Array.unzip
|
||||||
let zip3 = (a, b, c) =>
|
let zip3 = (a, b, c) =>
|
||||||
Belt.Array.zip(a, b)->Belt.Array.zip(c)->Belt.Array.map((((v1, v2), v3)) => (v1, v2, v3))
|
Belt.Array.zip(a, b)->Belt.Array.zip(c)->Belt.Array.map((((v1, v2), v3)) => (v1, v2, v3))
|
||||||
// This zips while taking the longest elements of each array.
|
// This zips while taking the longest elements of each array.
|
||||||
|
|
|
@ -148,6 +148,11 @@ module T = {
|
||||||
| None => Ok(attempt)
|
| None => Ok(attempt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let makeFromZipped = (values: array<(float, float)>) => {
|
||||||
|
let (xs, ys) = E.A.unzip(values)
|
||||||
|
make(~xs, ~ys)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Ts = {
|
module Ts = {
|
||||||
|
|
|
@ -20,6 +20,7 @@ const config = {
|
||||||
projectName: "squiggle", // Usually your repo name.
|
projectName: "squiggle", // Usually your repo name.
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
|
"docusaurus-tailwindcss",
|
||||||
() => ({
|
() => ({
|
||||||
configureWebpack(config, isServer, utils, content) {
|
configureWebpack(config, isServer, utils, content) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -12,16 +12,17 @@
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "2.0.0-beta.20",
|
"@docusaurus/core": "2.0.0-beta.21",
|
||||||
"@docusaurus/preset-classic": "2.0.0-beta.20",
|
"@docusaurus/preset-classic": "2.0.0-beta.21",
|
||||||
"@quri/squiggle-components": "^0.2.20",
|
"@quri/squiggle-components": "^0.2.20",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
|
"docusaurus-tailwindcss": "^0.1.0",
|
||||||
|
"hast-util-is-element": "2.1.2",
|
||||||
"prism-react-renderer": "^1.3.3",
|
"prism-react-renderer": "^1.3.3",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.1.0",
|
||||||
"remark-math": "^3",
|
|
||||||
"rehype-katex": "^5",
|
"rehype-katex": "^5",
|
||||||
"hast-util-is-element": "2.1.2"
|
"remark-math": "^3"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
* work well for content-centric websites.
|
* work well for content-centric websites.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
/* You can override the default Infima variables here. */
|
/* You can override the default Infima variables here. */
|
||||||
:root {
|
:root {
|
||||||
--ifm-color-primary: #2488df;
|
--ifm-color-primary: #2488df;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user