Added storybook stories for most SquiggleChart Types

This commit is contained in:
Ozzie Gooen 2022-04-15 17:14:07 -04:00
parent 20f93539ad
commit 012a1e4793
4 changed files with 183 additions and 116 deletions

View File

@ -11,7 +11,6 @@
"@types/lodash": "^4.14.181",
"@types/node": "^17.0.24",
"@types/react": "^18.0.3",
"@types/styled-components": "^5.1.25",
"@types/react-dom": "^18.0.1",
"antd": "^4.19.3",
"cross-env": "^7.0.3",

View File

@ -12,6 +12,105 @@ import { DistributionChart } from "./DistributionChart";
import { ErrorBox } from "./ErrorBox";
import useSize from "@react-hook/size";
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;
`,
};
export const VariableBox: React.FC<{
heading: string;
children: React.ReactNode;
}> = ({ heading = "Error", children }) => {
return (
<variableBox.Component>
<variableBox.Heading>
<h3>{heading}</h3>
</variableBox.Heading>
<variableBox.Body>{children}</variableBox.Body>
</variableBox.Component>
);
};
export interface SquiggleItemProps {
/** The input string for squiggle */
expression: squiggleExpression;
width: number;
height: number;
}
const SquiggleItem: React.FC<SquiggleItemProps> = ({
expression,
width,
height,
}: SquiggleItemProps) => {
if (expression.tag === "number") {
return (
<VariableBox heading="Number">
<NumberShower precision={3} number={expression.value} />
</VariableBox>
);
} else if (expression.tag === "distribution") {
let distType = expression.value.type();
return (
<VariableBox heading={`Distribution (${distType})`}>
{distType === "Symbolic" ? (
<>
<div>{expression.value.toString()}</div>
</>
) : (
<></>
)}
<DistributionChart
distribution={expression.value}
height={height}
width={width}
/>
</VariableBox>
);
} else if (expression.tag === "string") {
return (
<VariableBox heading="String">{`"${expression.value}"`}</VariableBox>
);
} else if (expression.tag === "boolean") {
return (
<VariableBox heading="Boolean">
{expression.value == true ? "True" : "False"}
</VariableBox>
);
} else if (expression.tag === "symbol") {
return <VariableBox heading="Symbol">{expression.value}</VariableBox>;
} else if (expression.tag === "call") {
return <VariableBox heading="Call">{expression.value}</VariableBox>;
} else if (expression.tag === "array") {
return (
<VariableBox heading="Array">
{expression.value.map((r) => (
<SquiggleItem expression={r} width={width - 20} height={50} />
))}
</VariableBox>
);
} else {
return (
<ErrorBox heading="No Viewer">
{"We don't currently have a viewer for record types."}
</ErrorBox>
);
}
};
export interface SquiggleChartProps {
/** The input string for squiggle */
squiggleString?: string;
@ -36,105 +135,6 @@ export interface SquiggleChartProps {
height?: number;
}
export interface SquiggleItemProps {
/** The input string for squiggle */
expression: squiggleExpression;
width: number;
height: number;
}
const ShowBox = styled.div`
background: white;
border: 1px solid #eee;
border-radius: 2px;
margin-bottom: 0.4em;
`;
const ShowBoxHeading = styled.div`
border-bottom: 1px solid #eee;
padding-left: 0.8em;
padding-right: 0.8em;
padding-top: 0.1em;
`;
const ShowBoxPadding = styled.div`
padding: 0.4em 0.8em;
`;
export const Box: React.FC<{
heading: string;
children: React.ReactNode;
}> = ({ heading = "Error", children }) => {
return (
<ShowBox>
<ShowBoxHeading>
<h3>{heading}</h3>
</ShowBoxHeading>
<ShowBoxPadding>{children}</ShowBoxPadding>
</ShowBox>
);
};
const SquiggleItem: React.FC<SquiggleItemProps> = ({
expression,
width,
height,
}: SquiggleItemProps) => {
if (expression.tag === "number") {
return (
<Box heading="Number">
<NumberShower precision={3} number={expression.value} />
</Box>
);
} else if (expression.tag === "distribution") {
let distType = expression.value.type();
return (
<Box heading={`Distribution (${distType})`}>
{distType === "Symbolic" ? (
<>
<div>{expression.value.toString()}</div>
</>
) : (
<></>
)}
<DistributionChart
distribution={expression.value}
height={height}
width={width}
/>
</Box>
);
} else if (expression.tag === "string") {
return <Box heading="String">{`"${expression.value}"`}</Box>;
} else if (expression.tag === "boolean") {
return (
<Box heading="Boolean">
({expression.value == true ? "True" : "False"})
</Box>
);
} else if (expression.tag === "symbol") {
return <Box heading="Symbol">({expression.value})</Box>;
} else if (expression.tag === "call") {
return <Box heading="Call">({expression.value})</Box>;
} else if (expression.tag === "array") {
return (
<Box heading="Array">
<div>
{expression.value.map((r) => (
<SquiggleItem expression={r} width={width - 20} height={50} />
))}
</div>
</Box>
);
} else {
return (
<ErrorBox heading="No Viewer">
{"We don't currently have a viewer for record types."}
</ErrorBox>
);
}
};
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
squiggleString = "",
sampleCount = 1000,

View File

@ -45,14 +45,13 @@ interface Props2 {
const ShowBox = styled.div<Props2>`
border: 1px solid #eee;
border-radius: 2px;
height: ${props => props.height};
height: ${(props) => props.height};
`;
const MyComponent = styled.div`
color: ${props => props.theme.colors.main};
color: ${(props) => props.theme.colors.main};
`;
interface TitleProps {
readonly maxHeight: number;
}
@ -63,10 +62,13 @@ const Display = styled.div<TitleProps>`
height: 100vh;
padding: 3px;
overflow-y: auto;
max-height: ${props => props.maxHeight}px;
max-height: ${(props) => props.maxHeight}px;
`;
let SquigglePlayground: FC<Props> = ({ initialSquiggleString = "", height = 300 }: Props) => {
let SquigglePlayground: FC<Props> = ({
initialSquiggleString = "",
height = 300,
}: Props) => {
let [squiggleString, setSquiggleString] = useState(initialSquiggleString);
let [sampleCount, setSampleCount] = useState(1000);
let [outputXYPoints, setOutputXYPoints] = useState(1000);

View File

@ -8,7 +8,7 @@ export const Template = SquiggleChart;
We have to hardcode a width here, because otherwise some interaction with
Storybook creates an infinite loop with the internal width
*/
const width = 500;
const width = 600;
# Squiggle Chart
@ -23,11 +23,11 @@ could be continuous, discrete or mixed.
## Distributions
### Continuous Distributions
### Continuous Distributions (Symbolic)
<Canvas>
<Story
name="Normal"
name="Continuous Symbolic"
args={{
squiggleString: "normal(5,2)",
width,
@ -37,6 +37,34 @@ could be continuous, discrete or mixed.
</Story>
</Canvas>
### Continuous Distributions (PointSet)
<Canvas>
<Story
name="Continuous Pointset"
args={{
squiggleString: "toPointSet(normal(5,2))",
width,
}}
>
{Template.bind({})}
</Story>
</Canvas>
### Continuous Distributions (SampleSet)
<Canvas>
<Story
name="Continuous SampleSet"
args={{
squiggleString: "toSampleSet(normal(5,2), 1000)",
width,
}}
>
{Template.bind({})}
</Story>
</Canvas>
### Discrete Distributions
<Canvas>
@ -83,17 +111,13 @@ to allow large and small numbers being printed cleanly.
</Story>
</Canvas>
## Functions
Full functions can be returned. These plot out the results of distributions between a set of x-coordinates.
The default is show 10 points between 0 and 10.
## Arrays
<Canvas>
<Story
name="Function"
name="Array"
args={{
squiggleString: "f(x) = normal(x^2,(x+.1)^1.8)\nf",
squiggleString: "[normal(5,2), normal(10,1), normal(40,2), 400000]",
width,
}}
>
@ -115,4 +139,46 @@ The default is show 10 points between 0 and 10.
</Story>
</Canvas>
## Booleans
<Canvas>
<Story
name="Boolean"
args={{
squiggleString: "3 == 3",
width,
}}
>
{Template.bind({})}
</Story>
</Canvas>
## Records
<Canvas>
<Story
name="Record"
args={{
squiggleString: "{foo: 35 to 50, bar: [1,2,3]}",
width,
}}
>
{Template.bind({})}
</Story>
</Canvas>
## Strings
<Canvas>
<Story
name="String"
args={{
squiggleString: '"Lucky day!"',
width,
}}
>
{Template.bind({})}
</Story>
</Canvas>
<Props of={SquiggleChart} />