Added lots of tailwind styling
This commit is contained in:
parent
afbc0199aa
commit
6b80118e7e
|
@ -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",
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { XCircleIcon } from "@heroicons/react/solid";
|
||||||
|
|
||||||
export const ErrorBox: React.FC<{
|
export const ErrorBox: React.FC<{
|
||||||
heading: string;
|
heading: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}> = ({ heading = "Error", children }) => {
|
}> = ({ heading = "Error", children }) => {
|
||||||
return (
|
return (
|
||||||
<div className="border border-red-200 bg-gray-50 p-4">
|
<div className="rounded-md bg-red-100 p-4 m-4">
|
||||||
<h3>{heading}</h3>
|
<div className="flex">
|
||||||
{children}
|
<div className="flex-shrink-0">
|
||||||
|
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
<div className="ml-3">
|
||||||
|
<h3 className="text-sm font-medium text-red-800">{heading}</h3>
|
||||||
|
<div className="mt-2 text-sm text-red-700">{children}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -54,7 +54,7 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
return (
|
return (
|
||||||
<div className="bg-white border border-grey-200 m-2">
|
<div className="bg-white border border-grey-200 m-2">
|
||||||
<div className="border-b border-grey-200 p-3">
|
<div className="border-b border-grey-200 p-3">
|
||||||
<h3>{heading}</h3>
|
<h3 className="font-mono">{heading}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-3">{children}</div>
|
<div className="p-3">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,6 +8,9 @@ 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";
|
||||||
|
import { CodeIcon } from "@heroicons/react/solid";
|
||||||
|
import { CogIcon } from "@heroicons/react/solid";
|
||||||
|
|
||||||
interface ShowBoxProps {
|
interface ShowBoxProps {
|
||||||
height: number;
|
height: number;
|
||||||
|
@ -15,9 +18,7 @@ interface ShowBoxProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShowBox: React.FC<ShowBoxProps> = ({ height, children }) => (
|
const ShowBox: React.FC<ShowBoxProps> = ({ height, children }) => (
|
||||||
<div className="border border-grey-100" style={{ height: height + "px" }}>
|
<div className="border border-gray-500">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
interface TitleProps {
|
interface TitleProps {
|
||||||
|
@ -26,12 +27,7 @@ interface TitleProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Display: React.FC<TitleProps> = ({ maxHeight, children }) => (
|
const Display: React.FC<TitleProps> = ({ maxHeight, children }) => (
|
||||||
<div
|
<div style={{ maxHeight: maxHeight + "px" }}>{children}</div>
|
||||||
className="bg-gray-50 border-l border-grey-100 p-2"
|
|
||||||
style={{ maxHeight: maxHeight + "px" }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
interface PlaygroundProps {
|
interface PlaygroundProps {
|
||||||
|
@ -88,12 +84,70 @@ type InputProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const InputItem: React.FC<InputProps> = ({ label, children }) => (
|
const InputItem: React.FC<InputProps> = ({ label, children }) => (
|
||||||
<div>
|
<div className="col-span-3">
|
||||||
<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";
|
||||||
|
let checkboxStyle =
|
||||||
|
"focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded";
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{ name: "Editor", href: "#", current: true },
|
||||||
|
{ name: "Settings", href: "#", current: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
function classNames(...classes) {
|
||||||
|
return classes.filter(Boolean).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function Example() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="sm:hidden">
|
||||||
|
<label htmlFor="tabs" className="sr-only">
|
||||||
|
Select a tab
|
||||||
|
</label>
|
||||||
|
{/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
|
||||||
|
<select
|
||||||
|
id="tabs"
|
||||||
|
name="tabs"
|
||||||
|
className="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
|
||||||
|
defaultValue={"Editor"}
|
||||||
|
>
|
||||||
|
{tabs.map((tab) => (
|
||||||
|
<option key={tab.name}>{tab.name}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="hidden sm:block">
|
||||||
|
<div className="border-b border-gray-200">
|
||||||
|
<nav className="-mb-px flex space-x-8" aria-label="Tabs">
|
||||||
|
{tabs.map((tab) => (
|
||||||
|
<a
|
||||||
|
key={tab.name}
|
||||||
|
href={tab.href}
|
||||||
|
className={classNames(
|
||||||
|
tab.current
|
||||||
|
? "border-indigo-500 text-indigo-600"
|
||||||
|
: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300",
|
||||||
|
"whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
|
||||||
|
)}
|
||||||
|
aria-current={tab.current ? "page" : undefined}
|
||||||
|
>
|
||||||
|
{tab.name}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let SquigglePlayground: FC<PlaygroundProps> = ({
|
let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
initialSquiggleString = "",
|
initialSquiggleString = "",
|
||||||
height = 500,
|
height = 500,
|
||||||
|
@ -142,80 +196,186 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
setImportsAreValid(false);
|
setImportsAreValid(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tab = (key, icon) => (
|
||||||
|
<Tab
|
||||||
|
key={key}
|
||||||
|
className={({ selected }) =>
|
||||||
|
classNames(
|
||||||
|
"whitespace-nowrap pb-1 pt-2 px-1 border-b-2 font-medium text-sm focus-within:outline-none group inline-flex items-center",
|
||||||
|
selected
|
||||||
|
? "border-slate-400 text-gray-500"
|
||||||
|
: "border-transparent text-gray-400 hover:text-gray-600 hover:border-slate-300"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
<span>{key}</span>
|
||||||
|
</Tab>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShowBox height={height}>
|
<div className="border border-slate-300 rounded-sm">
|
||||||
<input type="checkbox" {...register("showSettingsPage")} />
|
<Tab.Group>
|
||||||
<div className="columns-2">
|
<div className="bg-slate-200 rounded-tl-sm rounded-tr-sm">
|
||||||
<div className="break-inside-avoid">
|
<div className="pb-3 pl-3">
|
||||||
{vars.showSettingsPage ? (
|
<div className="border-b border-gray-200">
|
||||||
<>
|
<Tab.List className="-mb-px flex space-x-4">
|
||||||
<InputItem label="Sample Count">
|
{tab(
|
||||||
<input type="number" {...register("sampleCount")} />
|
"Code",
|
||||||
</InputItem>
|
<CodeIcon
|
||||||
<InputItem label="XYPointLength Count">
|
className="text-gray-400 group-hover:text-gray-500 -ml-0.5 mr-2 h-4 w-4"
|
||||||
<input type="number" {...register("xyPointLength")} />
|
aria-hidden="true"
|
||||||
</InputItem>
|
|
||||||
<InputItem label="Chart Height (in Pixels)">
|
|
||||||
<input type="number" {...register("chartHeight")} />
|
|
||||||
</InputItem>
|
|
||||||
<InputItem label="Show Types">
|
|
||||||
<input type="checkbox" {...register("showTypes")} />
|
|
||||||
</InputItem>
|
|
||||||
<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}
|
|
||||||
showGutter={true}
|
|
||||||
height={100}
|
|
||||||
/>
|
/>
|
||||||
{importsAreValid ? "Valid" : "Invalid"}
|
)}
|
||||||
|
{tab(
|
||||||
|
"Settings",
|
||||||
|
<CogIcon
|
||||||
|
className="text-gray-400 group-hover:text-gray-500 -ml-0.5 mr-2 h-4 w-4"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Tab.List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex" style={{ height: height + "px" }}>
|
||||||
|
<div className="w-1/2">
|
||||||
|
<Tab.Panels>
|
||||||
|
<Tab.Panel>
|
||||||
|
<CodeEditor
|
||||||
|
value={squiggleString}
|
||||||
|
onChange={setSquiggleString}
|
||||||
|
oneLine={false}
|
||||||
|
showGutter={true}
|
||||||
|
height={height - 1}
|
||||||
|
/>
|
||||||
|
</Tab.Panel>
|
||||||
|
<Tab.Panel>
|
||||||
|
<>
|
||||||
|
<form className="space-y-6 p-3">
|
||||||
|
<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 be overridden by specific 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>
|
||||||
|
<InputItem label="Chart Height (in Pixels)">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
{...register("chartHeight")}
|
||||||
|
className={numberStyle}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
<InputItem label="Editor Width">
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="1"
|
||||||
|
max="100"
|
||||||
|
className="slider"
|
||||||
|
{...register("leftSizePercent")}
|
||||||
|
/>
|
||||||
|
</InputItem>
|
||||||
|
<fieldset className="space-y-2">
|
||||||
|
<div className="relative flex items-start">
|
||||||
|
<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">
|
||||||
|
Type Names
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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">
|
||||||
|
X-Y Coordinate Scales
|
||||||
|
</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">
|
||||||
|
Summary Statistics
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<InputItem label="Json Editor for imports">
|
||||||
|
<>
|
||||||
|
<JsonEditor
|
||||||
|
value={importString}
|
||||||
|
onChange={getChangeJson}
|
||||||
|
oneLine={false}
|
||||||
|
showGutter={true}
|
||||||
|
height={100}
|
||||||
|
/>
|
||||||
|
{importsAreValid ? "Valid" : "Invalid"}
|
||||||
|
</>
|
||||||
|
</InputItem>
|
||||||
|
</form>
|
||||||
</>
|
</>
|
||||||
</InputItem>
|
</Tab.Panel>
|
||||||
</>
|
</Tab.Panels>
|
||||||
) : (
|
</div>
|
||||||
<CodeEditor
|
|
||||||
value={squiggleString}
|
<div className="w-1/2 border-l border-gray-300 p-2">
|
||||||
onChange={setSquiggleString}
|
<div style={{ maxHeight: height + "px" }}>
|
||||||
oneLine={false}
|
<SquiggleChart
|
||||||
showGutter={true}
|
squiggleString={squiggleString}
|
||||||
height={height - 3}
|
environment={env}
|
||||||
/>
|
chartSettings={chartSettings}
|
||||||
)}
|
height={vars.chartHeight}
|
||||||
|
showTypes={vars.showTypes}
|
||||||
|
showControls={vars.showControls}
|
||||||
|
bindings={defaultBindings}
|
||||||
|
jsImports={imports}
|
||||||
|
showSummary={vars.showSummary}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</Tab.Group>
|
||||||
<Display maxHeight={height - 3}>
|
</div>
|
||||||
<SquiggleChart
|
|
||||||
squiggleString={squiggleString}
|
|
||||||
environment={env}
|
|
||||||
chartSettings={chartSettings}
|
|
||||||
height={vars.chartHeight}
|
|
||||||
showTypes={vars.showTypes}
|
|
||||||
showControls={vars.showControls}
|
|
||||||
bindings={defaultBindings}
|
|
||||||
jsImports={imports}
|
|
||||||
showSummary={vars.showSummary}
|
|
||||||
/>
|
|
||||||
</Display>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ShowBox>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default SquigglePlayground;
|
export default SquigglePlayground;
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -1824,6 +1824,16 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/hoek" "^9.0.0"
|
"@hapi/hoek" "^9.0.0"
|
||||||
|
|
||||||
|
"@headlessui/react@^1.6.4":
|
||||||
|
version "1.6.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.4.tgz#c73084e23386bef5fb86cd16da3352c3a844bb4c"
|
||||||
|
integrity sha512-0yqz1scwbFtwljmbbKjXsSGl5ABEYNICVHZnMCWo0UtOZodo2Tpu94uOVgCRjRZ77l2WcTi2S0uidINDvG7lsA==
|
||||||
|
|
||||||
|
"@heroicons/react@^1.0.6":
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"
|
||||||
|
integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==
|
||||||
|
|
||||||
"@hookform/resolvers@^2.8.10":
|
"@hookform/resolvers@^2.8.10":
|
||||||
version "2.8.10"
|
version "2.8.10"
|
||||||
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d"
|
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user