collapsible results (WIP)

This commit is contained in:
Vyacheslav Matyukhin 2022-07-06 19:21:54 +04:00
parent 6e968c492b
commit 8a2269b7d0
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C

View File

@ -1,4 +1,4 @@
import * as React from "react"; import React, { useState } from "react";
import { import {
squiggleExpression, squiggleExpression,
environment, environment,
@ -10,6 +10,8 @@ import {
DistributionPlottingSettings, DistributionPlottingSettings,
} from "./DistributionChart"; } from "./DistributionChart";
import { FunctionChart, FunctionChartSettings } from "./FunctionChart"; import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
import clsx from "clsx";
import { LayoutGroup, motion } from "framer-motion";
function getRange<a>(x: declaration<a>) { function getRange<a>(x: declaration<a>) {
const first = x.args[0]; const first = x.args[0];
@ -35,33 +37,48 @@ function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
} }
interface VariableBoxProps { interface VariableBoxProps {
name?: string;
heading: string; heading: string;
children: React.ReactNode; children: React.ReactNode;
showTypes: boolean; showTypes: boolean;
} }
export const VariableBox: React.FC<VariableBoxProps> = ({ export const VariableBox: React.FC<VariableBoxProps> = ({
name,
heading = "Error", heading = "Error",
children, children,
showTypes = false, showTypes = false,
}) => { }) => {
if (showTypes) { const [isCollapsed, setIsCollapsed] = useState(false);
return ( return (
<div className="bg-white border border-grey-200 m-2"> <motion.div
<div className="border-b border-grey-200 p-3"> layout="position"
<header className="font-mono">{heading}</header> transition={{ type: "spring", bounce: 0, duration: 0.2 }}
</div> >
<div className="p-3">{children}</div> {name || showTypes ? (
</div> <motion.header
layout="position"
className="inline-flex space-x-1 text-slate-500 font-mono text-sm cursor-pointer"
onClick={() => setIsCollapsed(!isCollapsed)}
>
{name ? <span>{name}:</span> : null}
{showTypes ? <span>{heading}</span> : null}
{isCollapsed ? (
<span className="bg-slate-200 rounded p-0.5 font-xs">...</span>
) : null}
</motion.header>
) : null}
{isCollapsed ? null : (
<motion.div layout="position">{children}</motion.div>
)}
</motion.div>
); );
} else {
return <div>{children}</div>;
}
}; };
export interface SquiggleItemProps { export interface SquiggleItemProps {
/** The input string for squiggle */ /** The output of squiggle's run */
expression: squiggleExpression; expression: squiggleExpression;
name?: string;
width?: number; width?: number;
height: number; height: number;
distributionPlotSettings: DistributionPlottingSettings; distributionPlotSettings: DistributionPlottingSettings;
@ -74,6 +91,7 @@ export interface SquiggleItemProps {
} }
export const SquiggleItem: React.FC<SquiggleItemProps> = ({ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
name,
expression, expression,
width, width,
height, height,
@ -85,7 +103,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
switch (expression.tag) { switch (expression.tag) {
case "number": case "number":
return ( return (
<VariableBox heading="Number" showTypes={showTypes}> <VariableBox name={name} heading="Number" showTypes={showTypes}>
<div className="font-semibold text-slate-600"> <div className="font-semibold text-slate-600">
<NumberShower precision={3} number={expression.value} /> <NumberShower precision={3} number={expression.value} />
</div> </div>
@ -95,6 +113,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
const distType = expression.value.type(); const distType = expression.value.type();
return ( return (
<VariableBox <VariableBox
name={name}
heading={`Distribution (${distType})`} heading={`Distribution (${distType})`}
showTypes={showTypes} showTypes={showTypes}
> >
@ -112,9 +131,9 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
} }
case "string": case "string":
return ( return (
<VariableBox heading="String" showTypes={showTypes}> <VariableBox name={name} heading="String" showTypes={showTypes}>
<span className="text-slate-400">"</span> <span className="text-slate-400">"</span>
<span className="text-slate-600 font-semibold"> <span className="text-slate-600 font-semibold font-mono">
{expression.value} {expression.value}
</span> </span>
<span className="text-slate-400">"</span> <span className="text-slate-400">"</span>
@ -122,94 +141,45 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
); );
case "boolean": case "boolean":
return ( return (
<VariableBox heading="Boolean" showTypes={showTypes}> <VariableBox name={name} heading="Boolean" showTypes={showTypes}>
{expression.value.toString()} {expression.value.toString()}
</VariableBox> </VariableBox>
); );
case "symbol": case "symbol":
return ( return (
<VariableBox heading="Symbol" showTypes={showTypes}> <VariableBox name={name} heading="Symbol" showTypes={showTypes}>
<span className="text-slate-500 mr-2">Undefined Symbol:</span> <span className="text-slate-500 mr-2">Undefined Symbol:</span>
<span className="text-slate-600">{expression.value}</span> <span className="text-slate-600">{expression.value}</span>
</VariableBox> </VariableBox>
); );
case "call": case "call":
return ( return (
<VariableBox heading="Call" showTypes={showTypes}> <VariableBox name={name} heading="Call" showTypes={showTypes}>
{expression.value} {expression.value}
</VariableBox> </VariableBox>
); );
case "array":
return (
<VariableBox heading="Array" showTypes={showTypes}>
{expression.value.map((r, i) => (
<div key={i} className="flex pt-1">
<div className="flex-none bg-slate-100 rounded-sm px-1">
<header className="text-slate-400 font-mono">{i}</header>
</div>
<div className="px-2 mb-2 grow">
<SquiggleItem
key={i}
expression={r}
width={width !== undefined ? width - 20 : width}
height={50}
distributionPlotSettings={distributionPlotSettings}
showTypes={showTypes}
chartSettings={chartSettings}
environment={environment}
/>
</div>
</div>
))}
</VariableBox>
);
case "record":
return (
<VariableBox heading="Record" showTypes={showTypes}>
<div className="space-y-3">
{Object.entries(expression.value).map(([key, r]) => (
<div key={key} className="flex space-x-2">
<div className="flex-none">
<header className="text-slate-500 font-mono">{key}:</header>
</div>
<div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
<SquiggleItem
expression={r}
width={width !== undefined ? width - 20 : width}
height={height / 3}
showTypes={showTypes}
distributionPlotSettings={distributionPlotSettings}
chartSettings={chartSettings}
environment={environment}
/>
</div>
</div>
))}
</div>
</VariableBox>
);
case "arraystring": case "arraystring":
return ( return (
<VariableBox heading="Array String" showTypes={showTypes}> <VariableBox name={name} heading="Array String" showTypes={showTypes}>
{expression.value.map((r) => `"${r}"`).join(", ")} {expression.value.map((r) => `"${r}"`).join(", ")}
</VariableBox> </VariableBox>
); );
case "date": case "date":
return ( return (
<VariableBox heading="Date" showTypes={showTypes}> <VariableBox name={name} heading="Date" showTypes={showTypes}>
{expression.value.toDateString()} {expression.value.toDateString()}
</VariableBox> </VariableBox>
); );
case "timeDuration": { case "timeDuration": {
return ( return (
<VariableBox heading="Time Duration" showTypes={showTypes}> <VariableBox name={name} heading="Time Duration" showTypes={showTypes}>
<NumberShower precision={3} number={expression.value} /> <NumberShower precision={3} number={expression.value} />
</VariableBox> </VariableBox>
); );
} }
case "lambda": case "lambda":
return ( return (
<VariableBox heading="Function" showTypes={showTypes}> <VariableBox name={name} 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 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> )})`}</div>
@ -227,7 +197,11 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
); );
case "lambdaDeclaration": { case "lambdaDeclaration": {
return ( return (
<VariableBox heading="Function Declaration" showTypes={showTypes}> <VariableBox
name={name}
heading="Function Declaration"
showTypes={showTypes}
>
<FunctionChart <FunctionChart
fn={expression.value.fn} fn={expression.value.fn}
chartSettings={getChartSettings(expression.value)} chartSettings={getChartSettings(expression.value)}
@ -243,17 +217,21 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
} }
case "module": { case "module": {
return ( return (
<VariableBox heading="Module" showTypes={showTypes}> <VariableBox name={name} heading="Module" showTypes={showTypes}>
<div className="space-y-3"> <div
className={clsx(
"space-y-3",
name ? "border-l pl-4" : null,
name || showTypes ? "pt-1 mt-1" : null
)}
>
<LayoutGroup>
{Object.entries(expression.value) {Object.entries(expression.value)
.filter(([key, r]) => key !== "Math") .filter(([key, r]) => key !== "Math")
.map(([key, r]) => ( .map(([key, r]) => (
<div key={key} className="flex space-x-2">
<div className="flex-none">
<header className="text-slate-500 font-mono">{key}:</header>
</div>
<div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
<SquiggleItem <SquiggleItem
key={key}
name={key}
expression={r} expression={r}
width={width !== undefined ? width - 20 : width} width={width !== undefined ? width - 20 : width}
height={height / 3} height={height / 3}
@ -262,13 +240,68 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
chartSettings={chartSettings} chartSettings={chartSettings}
environment={environment} environment={environment}
/> />
</div>
</div>
))} ))}
</LayoutGroup>
</div> </div>
</VariableBox> </VariableBox>
); );
} }
case "record":
return (
<VariableBox name={name} heading="Record" showTypes={showTypes}>
<div
className={clsx(
"space-y-3",
name ? "border-l pl-4" : null,
name || showTypes ? "pt-1 mt-1" : null
)}
>
<LayoutGroup>
{Object.entries(expression.value).map(([key, r]) => (
<SquiggleItem
key={key}
name={key}
expression={r}
width={width !== undefined ? width - 20 : width}
height={height / 3}
showTypes={showTypes}
distributionPlotSettings={distributionPlotSettings}
chartSettings={chartSettings}
environment={environment}
/>
))}
</LayoutGroup>
</div>
</VariableBox>
);
case "array":
return (
<VariableBox name={name} heading="Array" showTypes={showTypes}>
<div
className={clsx(
"space-y-3",
name ? "border-l pl-4" : null,
name || showTypes ? "pt-1 mt-1" : null
)}
>
<LayoutGroup>
{expression.value.map((r, i) => (
<SquiggleItem
key={i}
name={String(i)}
expression={r}
width={width !== undefined ? width - 20 : width}
height={50}
distributionPlotSettings={distributionPlotSettings}
showTypes={showTypes}
chartSettings={chartSettings}
environment={environment}
/>
))}
</LayoutGroup>
</div>
</VariableBox>
);
default: { default: {
return ( return (
<div> <div>