Merge branch 'develop' into Documentation-auto-generation
* develop: (22 commits) components-lint respects components prettierignore format main.css and prettierignore base.css scoped tailwind preflight, top-level .squiggle wrapper grammar: identifiers with modules Refactored reducerInterface files Added simple scientific units Added stdev to table of stats, when needed Added stdev and variance to Distribution Operation Constructors Quick addition of stdev-variance-min-max-mode ⬆️ Bump @types/node from 17.0.38 to 17.0.40 ⬆️ Bump webpack from 5.72.1 to 5.73.0 ⬆️ Bump @storybook/react from 6.5.6 to 6.5.7 ⬆️ Bump ts-node from 10.8.0 to 10.8.1 ⬆️ Bump @storybook/builder-webpack5 from 6.5.6 to 6.5.7 ⬆️ Bump peggy from 2.0.0 to 2.0.1 ⬆️ Bump @storybook/addon-essentials from 6.5.6 to 6.5.7 ⬆️ Bump @storybook/preset-create-react-app from 4.1.1 to 4.1.2 ⬆️ Bump @hookform/resolvers from 2.8.10 to 2.9.0 ⬆️ Bump typescript from 4.7.2 to 4.7.3 ⬆️ Bump @storybook/manager-webpack5 from 6.5.6 to 6.5.7 ...
This commit is contained in:
commit
8fd5c6a1be
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -100,7 +100,7 @@ jobs:
|
||||||
uses: creyD/prettier_action@v4.2
|
uses: creyD/prettier_action@v4.2
|
||||||
with:
|
with:
|
||||||
dry: true
|
dry: true
|
||||||
prettier_options: --check packages/components
|
prettier_options: --check packages/components --ignore-path packages/components/.prettierignore
|
||||||
|
|
||||||
components-bundle-build:
|
components-bundle-build:
|
||||||
name: Components bundle and build
|
name: Components bundle and build
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
dist/
|
dist/
|
||||||
storybook-static
|
storybook-static
|
||||||
|
src/styles/base.css
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
import "../src/tailwind.css";
|
import "../src/styles/main.css";
|
||||||
|
import "!style-loader!css-loader!postcss-loader!../src/styles/main.css";
|
||||||
|
import { SquiggleContainer } from "../src/components/SquiggleContainer";
|
||||||
|
|
||||||
|
export const decorators = [
|
||||||
|
(Story) => (
|
||||||
|
<SquiggleContainer>
|
||||||
|
<Story />
|
||||||
|
</SquiggleContainer>
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
export const parameters = {
|
export const parameters = {
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||||
controls: {
|
controls: {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.6.4",
|
"@headlessui/react": "^1.6.4",
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@hookform/resolvers": "^2.8.10",
|
"@hookform/resolvers": "^2.9.0",
|
||||||
"@quri/squiggle-lang": "^0.2.8",
|
"@quri/squiggle-lang": "^0.2.8",
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -22,42 +22,44 @@
|
||||||
},
|
},
|
||||||
"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.6",
|
"@storybook/addon-actions": "^6.5.7",
|
||||||
"@storybook/addon-essentials": "^6.5.6",
|
"@storybook/addon-essentials": "^6.5.7",
|
||||||
"@storybook/addon-links": "^6.5.6",
|
"@storybook/addon-links": "^6.5.7",
|
||||||
"@storybook/builder-webpack5": "^6.5.6",
|
"@storybook/builder-webpack5": "^6.5.7",
|
||||||
"@storybook/manager-webpack5": "^6.5.6",
|
"@storybook/manager-webpack5": "^6.5.7",
|
||||||
"@storybook/node-logger": "^6.5.6",
|
"@storybook/node-logger": "^6.5.6",
|
||||||
"@storybook/preset-create-react-app": "^4.1.1",
|
"@storybook/preset-create-react-app": "^4.1.2",
|
||||||
"@storybook/react": "^6.5.6",
|
"@storybook/react": "^6.5.7",
|
||||||
"@tailwindcss/forms": "^0.5.2",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.3.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.36",
|
"@types/node": "^17.0.40",
|
||||||
"@types/react": "^18.0.9",
|
"@types/react": "^18.0.9",
|
||||||
"@types/react-dom": "^18.0.5",
|
"@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",
|
||||||
"mini-css-extract-plugin": "^2.6.0",
|
"mini-css-extract-plugin": "^2.6.0",
|
||||||
|
"postcss-cli": "^9.1.0",
|
||||||
|
"postcss-import": "^14.1.0",
|
||||||
"postcss-loader": "^7.0.0",
|
"postcss-loader": "^7.0.0",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"tailwindcss": "^3.0.24",
|
"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.7.2",
|
"typescript": "^4.7.3",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"webpack": "^5.72.1",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-dev-server": "^4.9.0"
|
"webpack-dev-server": "^4.9.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
||||||
"build": "tsc -b && tailwindcss -i ./src/tailwind.css -o ./dist/main.css && build-storybook -s public",
|
"build": "tsc -b && postcss ./src/styles/main.css -o ./dist/main.css && build-storybook -s public",
|
||||||
"bundle": "webpack",
|
"bundle": "webpack",
|
||||||
"all": "yarn bundle && yarn build",
|
"all": "yarn bundle && yarn build",
|
||||||
"lint": "prettier --check .",
|
"lint": "prettier --check .",
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
|
"postcss-import": {},
|
||||||
|
"tailwindcss/nesting": {},
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
cssnano: {},
|
cssnano: {},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
InformationCircleIcon,
|
InformationCircleIcon,
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
} from "@heroicons/react/solid";
|
} from "@heroicons/react/solid";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
export const Alert: React.FC<{
|
export const Alert: React.FC<{
|
||||||
heading: string;
|
heading: string;
|
||||||
|
@ -23,18 +24,18 @@ export const Alert: React.FC<{
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className={`rounded-md p-4 ${backgroundColor}`}>
|
<div className={clsx("rounded-md p-4", backgroundColor)}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<Icon
|
<Icon
|
||||||
className={`h-5 w-5 flex-shrink-0 ${iconColor}`}
|
className={clsx("h-5 w-5 flex-shrink-0", iconColor)}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
<div className="ml-3">
|
<div className="ml-3">
|
||||||
<header className={`text-sm font-medium ${headingColor}`}>
|
<header className={clsx("text-sm font-medium", headingColor)}>
|
||||||
{heading}
|
{heading}
|
||||||
</header>
|
</header>
|
||||||
{children && React.Children.count(children) ? (
|
{children && React.Children.count(children) ? (
|
||||||
<div className={`mt-2 text-sm ${bodyColor}`}>{children}</div>
|
<div className={clsx("mt-2 text-sm", bodyColor)}>{children}</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,6 +9,8 @@ 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 { ErrorAlert } from "./Alert";
|
import { ErrorAlert } from "./Alert";
|
||||||
import { useSize } from "react-use";
|
import { useSize } from "react-use";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
linearXScale,
|
linearXScale,
|
||||||
logXScale,
|
logXScale,
|
||||||
|
@ -128,7 +130,7 @@ export const CheckBox: React.FC<CheckBoxProps> = ({
|
||||||
onChange={() => onChange(!value)}
|
onChange={() => onChange(!value)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<label className={disabled ? "text-slate-400" : ""}> {label}</label>
|
<label className={clsx(disabled && "text-slate-400")}> {label}</label>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -153,6 +155,7 @@ type SummaryTableProps = {
|
||||||
|
|
||||||
const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
||||||
const mean = distribution.mean();
|
const mean = distribution.mean();
|
||||||
|
const stdev = distribution.stdev();
|
||||||
const p5 = distribution.inv(0.05);
|
const p5 = distribution.inv(0.05);
|
||||||
const p10 = distribution.inv(0.1);
|
const p10 = distribution.inv(0.1);
|
||||||
const p25 = distribution.inv(0.25);
|
const p25 = distribution.inv(0.25);
|
||||||
|
@ -161,6 +164,9 @@ const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
||||||
const p90 = distribution.inv(0.9);
|
const p90 = distribution.inv(0.9);
|
||||||
const p95 = distribution.inv(0.95);
|
const p95 = distribution.inv(0.95);
|
||||||
|
|
||||||
|
const hasResult = (x: result<number, distributionError>): boolean =>
|
||||||
|
x.tag === "Ok";
|
||||||
|
|
||||||
const unwrapResult = (
|
const unwrapResult = (
|
||||||
x: result<number, distributionError>
|
x: result<number, distributionError>
|
||||||
): React.ReactNode => {
|
): React.ReactNode => {
|
||||||
|
@ -180,6 +186,7 @@ const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
||||||
<thead className="bg-slate-50">
|
<thead className="bg-slate-50">
|
||||||
<tr>
|
<tr>
|
||||||
<TableHeadCell>{"Mean"}</TableHeadCell>
|
<TableHeadCell>{"Mean"}</TableHeadCell>
|
||||||
|
{hasResult(stdev) && <TableHeadCell>{"Stdev"}</TableHeadCell>}
|
||||||
<TableHeadCell>{"5%"}</TableHeadCell>
|
<TableHeadCell>{"5%"}</TableHeadCell>
|
||||||
<TableHeadCell>{"10%"}</TableHeadCell>
|
<TableHeadCell>{"10%"}</TableHeadCell>
|
||||||
<TableHeadCell>{"25%"}</TableHeadCell>
|
<TableHeadCell>{"25%"}</TableHeadCell>
|
||||||
|
@ -192,6 +199,7 @@ const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<Cell>{unwrapResult(mean)}</Cell>
|
<Cell>{unwrapResult(mean)}</Cell>
|
||||||
|
{hasResult(stdev) && <Cell>{unwrapResult(stdev)}</Cell>}
|
||||||
<Cell>{unwrapResult(p5)}</Cell>
|
<Cell>{unwrapResult(p5)}</Cell>
|
||||||
<Cell>{unwrapResult(p10)}</Cell>
|
<Cell>{unwrapResult(p10)}</Cell>
|
||||||
<Cell>{unwrapResult(p25)}</Cell>
|
<Cell>{unwrapResult(p25)}</Cell>
|
||||||
|
|
25
packages/components/src/components/SquiggleContainer.tsx
Normal file
25
packages/components/src/components/SquiggleContainer.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React, { useContext } from "react";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SquiggleContextShape = {
|
||||||
|
containerized: boolean;
|
||||||
|
};
|
||||||
|
const SquiggleContext = React.createContext<SquiggleContextShape>({
|
||||||
|
containerized: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SquiggleContainer: React.FC<Props> = ({ children }) => {
|
||||||
|
const context = useContext(SquiggleContext);
|
||||||
|
if (context.containerized) {
|
||||||
|
return <>{children}</>;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<SquiggleContext.Provider value={{ containerized: true }}>
|
||||||
|
<div className="squiggle">{children}</div>
|
||||||
|
</SquiggleContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
|
@ -15,6 +15,7 @@ import {
|
||||||
defaultBindings,
|
defaultBindings,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { ErrorAlert } from "./Alert";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
|
|
||||||
export interface SquiggleEditorProps {
|
export interface SquiggleEditorProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
|
@ -64,29 +65,31 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
count: diagramCount,
|
count: diagramCount,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<SquiggleContainer>
|
||||||
<div className="border border-grey-200 p-2 m-4">
|
<div>
|
||||||
<CodeEditor
|
<div className="border border-grey-200 p-2 m-4">
|
||||||
value={expression}
|
<CodeEditor
|
||||||
onChange={setExpression}
|
value={expression}
|
||||||
oneLine={true}
|
onChange={setExpression}
|
||||||
showGutter={false}
|
oneLine={true}
|
||||||
height={20}
|
showGutter={false}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<SquiggleChart
|
||||||
|
width={width}
|
||||||
|
environment={environment}
|
||||||
|
squiggleString={expression}
|
||||||
|
chartSettings={chartSettings}
|
||||||
|
onChange={onChange}
|
||||||
|
bindings={bindings}
|
||||||
|
jsImports={jsImports}
|
||||||
|
showTypes={showTypes}
|
||||||
|
showControls={showControls}
|
||||||
|
showSummary={showSummary}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SquiggleChart
|
</SquiggleContainer>
|
||||||
width={width}
|
|
||||||
environment={environment}
|
|
||||||
squiggleString={expression}
|
|
||||||
chartSettings={chartSettings}
|
|
||||||
onChange={onChange}
|
|
||||||
bindings={bindings}
|
|
||||||
jsImports={jsImports}
|
|
||||||
showTypes={showTypes}
|
|
||||||
showControls={showControls}
|
|
||||||
showSummary={showSummary}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,18 +174,22 @@ export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
React.useEffect(runSquiggleAndUpdateBindings, [expression]);
|
React.useEffect(runSquiggleAndUpdateBindings, [expression]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<SquiggleContainer>
|
||||||
<div className="border border-grey-200 p-2 m-4">
|
<div>
|
||||||
<CodeEditor
|
<div className="border border-grey-200 p-2 m-4">
|
||||||
value={expression}
|
<CodeEditor
|
||||||
onChange={setExpression}
|
value={expression}
|
||||||
oneLine={true}
|
onChange={setExpression}
|
||||||
showGutter={false}
|
oneLine={true}
|
||||||
height={20}
|
showGutter={false}
|
||||||
/>
|
height={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error !== null ? (
|
||||||
|
<ErrorAlert heading="Error">{error}</ErrorAlert>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{error !== null ? <ErrorAlert heading="Error">{error}</ErrorAlert> : null}
|
</SquiggleContainer>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
CogIcon,
|
CogIcon,
|
||||||
CurrencyDollarIcon,
|
CurrencyDollarIcon,
|
||||||
} from "@heroicons/react/solid";
|
} from "@heroicons/react/solid";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
import { defaultBindings, environment } from "@quri/squiggle-lang";
|
import { defaultBindings, environment } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ import { SquiggleChart } from "./SquiggleChart";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import { JsonEditor } from "./JsonEditor";
|
import { JsonEditor } from "./JsonEditor";
|
||||||
import { ErrorAlert, SuccessAlert } from "./Alert";
|
import { ErrorAlert, SuccessAlert } from "./Alert";
|
||||||
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
|
|
||||||
interface PlaygroundProps {
|
interface PlaygroundProps {
|
||||||
/** The initial squiggle string to put in the playground */
|
/** The initial squiggle string to put in the playground */
|
||||||
|
@ -87,10 +89,6 @@ const schema = yup
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
function classNames(...classes: string[]) {
|
|
||||||
return classes.filter(Boolean).join(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
type StyledTabProps = {
|
type StyledTabProps = {
|
||||||
name: string;
|
name: string;
|
||||||
icon: (props: React.ComponentProps<"svg">) => JSX.Element;
|
icon: (props: React.ComponentProps<"svg">) => JSX.Element;
|
||||||
|
@ -102,15 +100,13 @@ const StyledTab: React.FC<StyledTabProps> = ({ name, icon: Icon }) => {
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<button className="group flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100">
|
<button className="group flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100">
|
||||||
<span
|
<span
|
||||||
className={classNames(
|
className={clsx(
|
||||||
"p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
|
"p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
|
||||||
selected
|
selected && "bg-white shadow-sm ring-1 ring-black ring-opacity-5"
|
||||||
? "bg-white shadow-sm ring-1 ring-black ring-opacity-5"
|
|
||||||
: ""
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
className={classNames(
|
className={clsx(
|
||||||
"-ml-0.5 mr-2 h-4 w-4",
|
"-ml-0.5 mr-2 h-4 w-4",
|
||||||
selected
|
selected
|
||||||
? "text-slate-500"
|
? "text-slate-500"
|
||||||
|
@ -118,11 +114,11 @@ const StyledTab: React.FC<StyledTabProps> = ({ name, icon: Icon }) => {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
className={
|
className={clsx(
|
||||||
selected
|
selected
|
||||||
? "text-gray-900"
|
? "text-gray-900"
|
||||||
: "text-gray-600 group-hover:text-gray-900"
|
: "text-gray-600 group-hover:text-gray-900"
|
||||||
}
|
)}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
|
@ -160,13 +156,14 @@ function InputItem<T>({
|
||||||
type: "number";
|
type: "number";
|
||||||
register: UseFormRegister<T>;
|
register: UseFormRegister<T>;
|
||||||
}) {
|
}) {
|
||||||
const 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";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className="block">
|
<label className="block">
|
||||||
<div className="text-sm font-medium text-gray-600 mb-1">{label}</div>
|
<div className="text-sm font-medium text-gray-600 mb-1">{label}</div>
|
||||||
<input type={type} {...register(name)} className={numberStyle} />
|
<input
|
||||||
|
type={type}
|
||||||
|
{...register(name)}
|
||||||
|
className="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"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -378,54 +375,57 @@ const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group>
|
<SquiggleContainer>
|
||||||
<div className="pb-4">
|
<Tab.Group>
|
||||||
<Tab.List className="flex w-fit p-0.5 rounded-md bg-slate-100 hover:bg-slate-200">
|
<div className="pb-4">
|
||||||
<StyledTab name="Code" icon={CodeIcon} />
|
<Tab.List className="flex w-fit p-0.5 rounded-md bg-slate-100 hover:bg-slate-200">
|
||||||
<StyledTab name="Sampling Settings" icon={CogIcon} />
|
<StyledTab name="Code" icon={CodeIcon} />
|
||||||
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
<StyledTab name="Sampling Settings" icon={CogIcon} />
|
||||||
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
||||||
</Tab.List>
|
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
||||||
</div>
|
</Tab.List>
|
||||||
<div className="flex" style={{ height }}>
|
|
||||||
<div className="w-1/2">
|
|
||||||
<Tab.Panels>
|
|
||||||
<Tab.Panel>
|
|
||||||
<div className="border border-slate-200">
|
|
||||||
<CodeEditor
|
|
||||||
value={squiggleString}
|
|
||||||
onChange={setSquiggleString}
|
|
||||||
oneLine={false}
|
|
||||||
showGutter={true}
|
|
||||||
height={height - 1}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tab.Panel>
|
|
||||||
<Tab.Panel>{samplingSettings}</Tab.Panel>
|
|
||||||
<Tab.Panel>{viewSettings}</Tab.Panel>
|
|
||||||
<Tab.Panel>{inputVariableSettings}</Tab.Panel>
|
|
||||||
</Tab.Panels>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex" style={{ height }}>
|
||||||
|
<div className="w-1/2">
|
||||||
|
<Tab.Panels>
|
||||||
|
<Tab.Panel>
|
||||||
|
<div className="border border-slate-200">
|
||||||
|
<CodeEditor
|
||||||
|
value={squiggleString}
|
||||||
|
onChange={setSquiggleString}
|
||||||
|
oneLine={false}
|
||||||
|
showGutter={true}
|
||||||
|
height={height - 1}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tab.Panel>
|
||||||
|
<Tab.Panel>{samplingSettings}</Tab.Panel>
|
||||||
|
<Tab.Panel>{viewSettings}</Tab.Panel>
|
||||||
|
<Tab.Panel>{inputVariableSettings}</Tab.Panel>
|
||||||
|
</Tab.Panels>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="w-1/2 p-2 pl-4">
|
<div className="w-1/2 p-2 pl-4">
|
||||||
<div style={{ maxHeight: height }}>
|
<div style={{ maxHeight: height }}>
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
squiggleString={squiggleString}
|
squiggleString={squiggleString}
|
||||||
environment={env}
|
environment={env}
|
||||||
chartSettings={chartSettings}
|
chartSettings={chartSettings}
|
||||||
height={vars.chartHeight}
|
height={vars.chartHeight}
|
||||||
showTypes={vars.showTypes}
|
showTypes={vars.showTypes}
|
||||||
showControls={vars.showControls}
|
showControls={vars.showControls}
|
||||||
bindings={defaultBindings}
|
bindings={defaultBindings}
|
||||||
jsImports={imports}
|
jsImports={imports}
|
||||||
showSummary={vars.showSummary}
|
showSummary={vars.showSummary}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tab.Group>
|
||||||
</Tab.Group>
|
</SquiggleContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SquigglePlayground;
|
export default SquigglePlayground;
|
||||||
export function renderSquigglePlaygroundToDom(props: PlaygroundProps) {
|
export function renderSquigglePlaygroundToDom(props: PlaygroundProps) {
|
||||||
const parent = document.createElement("div");
|
const parent = document.createElement("div");
|
||||||
|
|
|
@ -9,5 +9,6 @@ export {
|
||||||
default as SquigglePlayground,
|
default as SquigglePlayground,
|
||||||
renderSquigglePlaygroundToDom,
|
renderSquigglePlaygroundToDom,
|
||||||
} from "./components/SquigglePlayground";
|
} from "./components/SquigglePlayground";
|
||||||
|
export { SquiggleContainer } from "./components/SquiggleContainer";
|
||||||
|
|
||||||
export { mergeBindings } from "@quri/squiggle-lang";
|
export { mergeBindings } from "@quri/squiggle-lang";
|
||||||
|
|
510
packages/components/src/styles/base.css
Normal file
510
packages/components/src/styles/base.css
Normal file
|
@ -0,0 +1,510 @@
|
||||||
|
.squiggle {
|
||||||
|
/*
|
||||||
|
This file contains:
|
||||||
|
1) Base Tailwind preflight styles
|
||||||
|
2) Base https://github.com/tailwindlabs/tailwindcss-forms styles
|
||||||
|
|
||||||
|
(Both are wrapped in .squiggle)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Use a consistent sensible line-height in all browsers.
|
||||||
|
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
3. Use a more readable tab size.
|
||||||
|
4. Use the user's configured `sans` font-family by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* html { */
|
||||||
|
line-height: 1.5; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
-moz-tab-size: 4; /* 3 */
|
||||||
|
tab-size: 4; /* 3 */
|
||||||
|
font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, -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"); /* 4 */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Remove the margin in all browsers.
|
||||||
|
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* body { */
|
||||||
|
margin: 0; /* 1 */
|
||||||
|
line-height: inherit; /* 2 */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
||||||
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
||||||
|
*/
|
||||||
|
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
border-width: 0; /* 2 */
|
||||||
|
border-style: solid; /* 2 */
|
||||||
|
border-color: theme('borderColor.DEFAULT', currentColor); /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
--tw-content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Add the correct height in Firefox.
|
||||||
|
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
||||||
|
3. Ensure horizontal rules are visible by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 0; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
border-top-width: 1px; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the correct text decoration in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr:where([title]) {
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove the default font size and weight for headings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reset links to optimize for opt-in styling instead of opt-out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the correct font weight in Edge and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Use the user's configured `mono` font family by default.
|
||||||
|
2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp,
|
||||||
|
pre {
|
||||||
|
font-family: theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
||||||
|
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
||||||
|
3. Remove gaps between table borders by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
table {
|
||||||
|
text-indent: 0; /* 1 */
|
||||||
|
border-color: inherit; /* 2 */
|
||||||
|
border-collapse: collapse; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Change the font styles in all browsers.
|
||||||
|
2. Remove the margin in Firefox and Safari.
|
||||||
|
3. Remove default padding in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
font-weight: inherit; /* 1 */
|
||||||
|
line-height: inherit; /* 1 */
|
||||||
|
color: inherit; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove the inheritance of text transform in Edge and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
2. Remove default button styles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type='button'],
|
||||||
|
[type='reset'],
|
||||||
|
[type='submit'] {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
background-color: transparent; /* 2 */
|
||||||
|
background-image: none; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use the modern Firefox focus style for all focusable elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:-moz-focusring {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
||||||
|
*/
|
||||||
|
|
||||||
|
:-moz-ui-invalid {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the correct vertical alignment in Chrome and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Correct the cursor style of increment and decrement buttons in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-inner-spin-button,
|
||||||
|
::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type='search'] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the correct display in Chrome and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Removes the default spacing and border for appropriate elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
blockquote,
|
||||||
|
dl,
|
||||||
|
dd,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
hr,
|
||||||
|
figure,
|
||||||
|
p,
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
menu {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prevent resizing textareas horizontally by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
||||||
|
2. Set the default placeholder color to the user's configured gray 400 color.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input::placeholder,
|
||||||
|
textarea::placeholder {
|
||||||
|
opacity: 1; /* 1 */
|
||||||
|
color: theme('colors.gray.400', #9ca3af); /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set the default cursor for buttons.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[role="button"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Make sure disabled buttons don't get the pointer cursor.
|
||||||
|
*/
|
||||||
|
:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||||
|
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
||||||
|
This can trigger a poorly considered lint error in some tools but is included by design.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img,
|
||||||
|
svg,
|
||||||
|
video,
|
||||||
|
canvas,
|
||||||
|
audio,
|
||||||
|
iframe,
|
||||||
|
embed,
|
||||||
|
object {
|
||||||
|
display: block; /* 1 */
|
||||||
|
vertical-align: middle; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||||
|
*/
|
||||||
|
|
||||||
|
img,
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* these styles were generated by tailwindcss-forms */
|
||||||
|
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
|
||||||
|
appearance: none;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
border-color: #2563eb;
|
||||||
|
}
|
||||||
|
input::placeholder,textarea::placeholder {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
::-webkit-datetime-edit-fields-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
::-webkit-date-and-time-value {
|
||||||
|
min-height: 1.5em;
|
||||||
|
}
|
||||||
|
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||||
|
background-position: right 0.5rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.5em 1.5em;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
[multiple] {
|
||||||
|
background-image: initial;
|
||||||
|
background-position: initial;
|
||||||
|
background-repeat: unset;
|
||||||
|
background-size: initial;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
-webkit-print-color-adjust: unset;
|
||||||
|
print-color-adjust: unset;
|
||||||
|
}
|
||||||
|
[type='checkbox'],[type='radio'] {
|
||||||
|
appearance: none;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-origin: border-box;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
color: #2563eb;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
[type='checkbox'] {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
[type='radio'] {
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
[type='checkbox']:focus,[type='radio']:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 2px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
[type='checkbox']:checked,[type='radio']:checked {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
[type='checkbox']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
[type='radio']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
[type='checkbox']:indeterminate {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
[type='file'] {
|
||||||
|
background: unset;
|
||||||
|
border-color: inherit;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: unset;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
[type='file']:focus {
|
||||||
|
outline: 1px solid ButtonText;
|
||||||
|
outline: 1px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
packages/components/src/styles/main.css
Normal file
8
packages/components/src/styles/main.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
@import "./base.css";
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* necessary hack because scoped preflight in ./base.css has higher specificity */
|
||||||
|
.ace_cursor {
|
||||||
|
border-left: 2px solid !important;
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
@tailwind forms;
|
|
|
@ -3,5 +3,6 @@ module.exports = {
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
|
important: ".squiggle",
|
||||||
plugins: [require("@tailwindcss/forms")],
|
plugins: [require("@tailwindcss/forms")],
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ module.exports = {
|
||||||
mode: "production",
|
mode: "production",
|
||||||
devtool: "source-map",
|
devtool: "source-map",
|
||||||
profile: true,
|
profile: true,
|
||||||
entry: ["./src/index.ts", "./src/tailwind.css"],
|
entry: ["./src/index.ts", "./src/styles/main.css"],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,6 +232,7 @@ describe("Peggy parse", () => {
|
||||||
})
|
})
|
||||||
describe("unit", () => {
|
describe("unit", () => {
|
||||||
testParse("1m", "{(::fromUnit_m 1)}")
|
testParse("1m", "{(::fromUnit_m 1)}")
|
||||||
|
testParse("1M", "{(::fromUnit_M 1)}")
|
||||||
testParse("1m+2cm", "{(::add (::fromUnit_m 1) (::fromUnit_cm 2))}")
|
testParse("1m+2cm", "{(::add (::fromUnit_m 1) (::fromUnit_cm 2))}")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -56,14 +56,14 @@
|
||||||
"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": "^2.0.0",
|
"peggy": "^2.0.1",
|
||||||
"reanalyze": "^2.22.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.1",
|
||||||
"typescript": "^4.7.2",
|
"typescript": "^4.7.3",
|
||||||
"webpack": "^5.72.1",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.9.2"
|
"webpack-cli": "^4.9.2"
|
||||||
},
|
},
|
||||||
"source": "./src/js/index.ts",
|
"source": "./src/js/index.ts",
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
import { result, resultMap, Ok } from "./types";
|
import { result, resultMap, Ok } from "./types";
|
||||||
import {
|
import {
|
||||||
Constructors_mean,
|
Constructors_mean,
|
||||||
|
Constructors_stdev,
|
||||||
Constructors_sample,
|
Constructors_sample,
|
||||||
Constructors_pdf,
|
Constructors_pdf,
|
||||||
Constructors_cdf,
|
Constructors_cdf,
|
||||||
|
@ -69,6 +70,10 @@ export class Distribution {
|
||||||
return Constructors_mean({ env: this.env }, this.t);
|
return Constructors_mean({ env: this.env }, this.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stdev(): result<number, distributionError> {
|
||||||
|
return Constructors_stdev({ env: this.env }, this.t);
|
||||||
|
}
|
||||||
|
|
||||||
sample(): result<number, distributionError> {
|
sample(): result<number, distributionError> {
|
||||||
return Constructors_sample({ env: this.env }, this.t);
|
return Constructors_sample({ env: this.env }, this.t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,8 @@ module Constructors = {
|
||||||
module C = DistributionTypes.Constructors.UsingDists
|
module C = DistributionTypes.Constructors.UsingDists
|
||||||
open OutputLocal
|
open OutputLocal
|
||||||
let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR
|
let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR
|
||||||
|
let stdev = (~env, dist) => C.stdev(dist)->run(~env)->toFloatR
|
||||||
|
let variance = (~env, dist) => C.variance(dist)->run(~env)->toFloatR
|
||||||
let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR
|
let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR
|
||||||
let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR
|
let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR
|
||||||
let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR
|
let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR
|
||||||
|
|
|
@ -49,6 +49,10 @@ module Constructors: {
|
||||||
@genType
|
@genType
|
||||||
let mean: (~env: env, genericDist) => result<float, error>
|
let mean: (~env: env, genericDist) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
|
let stdev: (~env: env, genericDist) => result<float, error>
|
||||||
|
@genType
|
||||||
|
let variance: (~env: env, genericDist) => result<float, error>
|
||||||
|
@genType
|
||||||
let sample: (~env: env, genericDist) => result<float, error>
|
let sample: (~env: env, genericDist) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let cdf: (~env: env, genericDist, float) => result<float, error>
|
let cdf: (~env: env, genericDist, float) => result<float, error>
|
||||||
|
|
|
@ -30,9 +30,9 @@ module Error = {
|
||||||
@genType
|
@genType
|
||||||
let toString = (err: error): string =>
|
let toString = (err: error): string =>
|
||||||
switch err {
|
switch err {
|
||||||
| NotYetImplemented => "Function Not Yet Implemented"
|
| NotYetImplemented => "Function not yet implemented"
|
||||||
| Unreachable => "Unreachable"
|
| Unreachable => "Unreachable"
|
||||||
| DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift is Invalid"
|
| DistributionVerticalShiftIsInvalid => "Distribution vertical shift is invalid"
|
||||||
| ArgumentError(s) => `Argument Error ${s}`
|
| ArgumentError(s) => `Argument Error ${s}`
|
||||||
| LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}`
|
| LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}`
|
||||||
| SampleSetError(TooFewSamples) => "Too Few Samples"
|
| SampleSetError(TooFewSamples) => "Too Few Samples"
|
||||||
|
@ -68,6 +68,11 @@ module DistributionOperation = {
|
||||||
| #Mean
|
| #Mean
|
||||||
| #Sample
|
| #Sample
|
||||||
| #IntegralSum
|
| #IntegralSum
|
||||||
|
| #Mode
|
||||||
|
| #Stdev
|
||||||
|
| #Min
|
||||||
|
| #Max
|
||||||
|
| #Variance
|
||||||
]
|
]
|
||||||
|
|
||||||
type toScaleFn = [
|
type toScaleFn = [
|
||||||
|
@ -117,6 +122,11 @@ module DistributionOperation = {
|
||||||
| ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})`
|
| ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})`
|
||||||
| ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})`
|
| ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})`
|
||||||
| ToFloat(#Mean) => `mean`
|
| ToFloat(#Mean) => `mean`
|
||||||
|
| ToFloat(#Min) => `min`
|
||||||
|
| ToFloat(#Max) => `max`
|
||||||
|
| ToFloat(#Stdev) => `stdev`
|
||||||
|
| ToFloat(#Variance) => `variance`
|
||||||
|
| ToFloat(#Mode) => `mode`
|
||||||
| ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})`
|
| ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})`
|
||||||
| ToFloat(#Sample) => `sample`
|
| ToFloat(#Sample) => `sample`
|
||||||
| ToFloat(#IntegralSum) => `integralSum`
|
| ToFloat(#IntegralSum) => `integralSum`
|
||||||
|
@ -151,6 +161,8 @@ module Constructors = {
|
||||||
module UsingDists = {
|
module UsingDists = {
|
||||||
@genType
|
@genType
|
||||||
let mean = (dist): t => FromDist(ToFloat(#Mean), dist)
|
let mean = (dist): t => FromDist(ToFloat(#Mean), dist)
|
||||||
|
let stdev = (dist): t => FromDist(ToFloat(#Stdev), dist)
|
||||||
|
let variance = (dist): t => FromDist(ToFloat(#Variance), dist)
|
||||||
let sample = (dist): t => FromDist(ToFloat(#Sample), dist)
|
let sample = (dist): t => FromDist(ToFloat(#Sample), dist)
|
||||||
let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist)
|
let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist)
|
||||||
let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist)
|
let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist)
|
||||||
|
|
|
@ -108,7 +108,7 @@ let toFloatOperation = (
|
||||||
) => {
|
) => {
|
||||||
switch distToFloatOperation {
|
switch distToFloatOperation {
|
||||||
| #IntegralSum => Ok(integralEndY(t))
|
| #IntegralSum => Ok(integralEndY(t))
|
||||||
| (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample) as op => {
|
| (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample | #Min | #Max) as op => {
|
||||||
let trySymbolicSolution = switch (t: t) {
|
let trySymbolicSolution = switch (t: t) {
|
||||||
| Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption
|
| Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption
|
||||||
| _ => None
|
| _ => None
|
||||||
|
@ -118,6 +118,8 @@ let toFloatOperation = (
|
||||||
| (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
|
| (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
|
||||||
| (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
|
| (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
|
||||||
| (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
|
| (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
|
||||||
|
| (SampleSet(sampleSet), #Min) => SampleSetDist.min(sampleSet)->Some
|
||||||
|
| (SampleSet(sampleSet), #Max) => SampleSetDist.max(sampleSet)->Some
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +132,16 @@ let toFloatOperation = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| (#Stdev | #Variance | #Mode) as op =>
|
||||||
|
switch t {
|
||||||
|
| SampleSet(s) =>
|
||||||
|
switch op {
|
||||||
|
| #Stdev => SampleSetDist.stdev(s)->Ok
|
||||||
|
| #Variance => SampleSetDist.variance(s)->Ok
|
||||||
|
| #Mode => SampleSetDist.mode(s)->Ok
|
||||||
|
}
|
||||||
|
| _ => Error(DistributionTypes.NotYetImplemented)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float =>
|
||||||
| #Inv(f) => inv(f, s)
|
| #Inv(f) => inv(f, s)
|
||||||
| #Sample => sample(s)
|
| #Sample => sample(s)
|
||||||
| #Mean => T.mean(s)
|
| #Mean => T.mean(s)
|
||||||
|
| #Min => T.minX(s)
|
||||||
|
| #Max => T.maxX(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
let toSparkline = (t: t, bucketCount): result<string, PointSetTypes.sparklineError> =>
|
let toSparkline = (t: t, bucketCount): result<string, PointSetTypes.sparklineError> =>
|
||||||
|
|
|
@ -449,6 +449,8 @@ module T = {
|
||||||
| #Cdf(f) => Ok(cdf(f, s))
|
| #Cdf(f) => Ok(cdf(f, s))
|
||||||
| #Pdf(f) => Ok(pdf(f, s))
|
| #Pdf(f) => Ok(pdf(f, s))
|
||||||
| #Inv(f) => Ok(inv(f, s))
|
| #Inv(f) => Ok(inv(f, s))
|
||||||
|
| #Min => Ok(min(s))
|
||||||
|
| #Max => Ok(max(s))
|
||||||
| #Sample => Ok(sample(s))
|
| #Sample => Ok(sample(s))
|
||||||
| #Mean => mean(s)
|
| #Mean => mean(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,31 +224,23 @@ postOperator = indexedValue
|
||||||
|
|
||||||
indexedValue
|
indexedValue
|
||||||
= collectionElement
|
= collectionElement
|
||||||
/ recordElement
|
|
||||||
/ atom
|
/ atom
|
||||||
|
|
||||||
collectionElement
|
collectionElement
|
||||||
= head:atom &('['/'('/'.')
|
= head:atom &('['/'('/'.')
|
||||||
tail:(
|
tail:(
|
||||||
_ '[' _nl arg:expression _nl ']' {return {fn: postOperatorToFunction['[]'], args: [arg]}}
|
_ '[' _nl arg:expression _nl ']' {return {fn: postOperatorToFunction['[]'], args: [arg]}}
|
||||||
/ _ '(' _nl args:array_functionArguments _nl ')' {return {fn: postOperatorToFunction['()'], args: args}}
|
/ _ '(' _nl args:array_functionArguments _nl ')' {return {fn: postOperatorToFunction['()'], args: args}}
|
||||||
/ '.' arg:$dollarIdentifier {return {fn: postOperatorToFunction['[]'], args: [nodeString(arg)]}}
|
/ '.' arg:$dollarIdentifier {return {fn: postOperatorToFunction['[]'], args: [nodeString(arg)]}}
|
||||||
)*
|
)*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(element.fn, [result, ...element.args])
|
return makeFunctionCall(element.fn, [result, ...element.args])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
array_functionArguments
|
array_functionArguments
|
||||||
= head:expression tail:(_ ',' _nl @expression)*
|
= head:expression tail:(_ ',' _nl @expression)*
|
||||||
{ return [head, ...tail]; }
|
{ return [head, ...tail]; }
|
||||||
|
|
||||||
recordElement
|
|
||||||
= head:dollarIdentifier &'.'
|
|
||||||
tail:(_ '.' _nl arg:$dollarIdentifier {return {fn: postOperatorToFunction['.'], args: [nodeString(arg)]}})*
|
|
||||||
{ return tail.reduce(function(result, element) {
|
|
||||||
return makeFunctionCall(element.fn, [result, ...element.args])
|
|
||||||
}, head)}
|
|
||||||
|
|
||||||
atom
|
atom
|
||||||
= '(' _nl expression:expression _nl ')' {return expression}
|
= '(' _nl expression:expression _nl ')' {return expression}
|
||||||
/ basicValue
|
/ basicValue
|
||||||
|
@ -259,19 +251,36 @@ basicLiteral
|
||||||
= string
|
= string
|
||||||
/ number
|
/ number
|
||||||
/ boolean
|
/ boolean
|
||||||
|
/ dollarIdentifierWithModule
|
||||||
/ dollarIdentifier
|
/ dollarIdentifier
|
||||||
|
|
||||||
|
dollarIdentifierWithModule 'identifier'
|
||||||
|
= head:moduleIdentifier
|
||||||
|
tail:('.' _nl @moduleIdentifier)* '.' _nl
|
||||||
|
final:dollarIdentifier
|
||||||
|
{ tail.push(final);
|
||||||
|
return tail.reduce(function(result, element) {
|
||||||
|
return makeFunctionCall(postOperatorToFunction['[]'], [result, element])
|
||||||
|
}, head)}
|
||||||
|
|
||||||
identifier 'identifier'
|
identifier 'identifier'
|
||||||
= ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
= ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||||
|
|
||||||
|
unitIdentifier 'identifier'
|
||||||
|
= ([_a-zA-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||||
|
|
||||||
dollarIdentifier '$identifier'
|
dollarIdentifier '$identifier'
|
||||||
= ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())}
|
= ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||||
|
|
||||||
|
moduleIdentifier 'identifier'
|
||||||
|
= ([A-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||||
|
|
||||||
|
|
||||||
string 'string'
|
string 'string'
|
||||||
= characters:("'" @([^'])* "'") {return nodeString(characters.join(''))}
|
= characters:("'" @([^'])* "'") {return nodeString(characters.join(''))}
|
||||||
/ characters:('"' @([^"])* '"') {return nodeString(characters.join(''))}
|
/ characters:('"' @([^"])* '"') {return nodeString(characters.join(''))}
|
||||||
|
|
||||||
number = number:(float / integer) unit:identifier?
|
number = number:(float / integer) unit:unitIdentifier?
|
||||||
{
|
{
|
||||||
if (unit === null)
|
if (unit === null)
|
||||||
{ return number }
|
{ return number }
|
||||||
|
@ -335,7 +344,7 @@ recordConstructor 'record'
|
||||||
_ 'whitespace'
|
_ 'whitespace'
|
||||||
= whiteSpaceCharactersOrComment*
|
= whiteSpaceCharactersOrComment*
|
||||||
|
|
||||||
_nl 'optional whitespace or newline'
|
_nl 'whitespace or newline'
|
||||||
= (whiteSpaceCharactersOrComment / commentOrNewLine)*
|
= (whiteSpaceCharactersOrComment / commentOrNewLine)*
|
||||||
|
|
||||||
__ 'whitespace'
|
__ 'whitespace'
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
module EV = ReducerInterface_ExpressionValue
|
||||||
|
type expressionValue = EV.expressionValue
|
||||||
|
|
||||||
|
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||||
|
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
|
> => {
|
||||||
|
switch call {
|
||||||
|
| ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
|
||||||
|
| ("makeDateFromYear", [EvNumber(year)]) =>
|
||||||
|
switch DateTime.Date.makeFromYear(year) {
|
||||||
|
| Ok(t) => EV.EvDate(t)->Ok->Some
|
||||||
|
| Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
|
||||||
|
}
|
||||||
|
| ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
|
||||||
|
| ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
|
||||||
|
| ("subtract", [EvDate(d1), EvDate(d2)]) =>
|
||||||
|
switch DateTime.Date.subtract(d1, d2) {
|
||||||
|
| Ok(d) => EV.EvTimeDuration(d)->Ok
|
||||||
|
| Error(e) => Error(RETodo(e))
|
||||||
|
}->Some
|
||||||
|
| ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
|
||||||
|
EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
||||||
|
| ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
|
||||||
|
EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,7 @@
|
||||||
module EV = ReducerInterface_ExpressionValue
|
module EV = ReducerInterface_ExpressionValue
|
||||||
type expressionValue = EV.expressionValue
|
type expressionValue = EV.expressionValue
|
||||||
|
|
||||||
let dateDispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
|
||||||
> => {
|
|
||||||
switch call {
|
|
||||||
| ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
|
|
||||||
| ("makeDateFromYear", [EvNumber(year)]) =>
|
|
||||||
switch DateTime.Date.makeFromYear(year) {
|
|
||||||
| Ok(t) => EV.EvDate(t)->Ok->Some
|
|
||||||
| Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
|
|
||||||
}
|
|
||||||
| ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
|
|
||||||
| ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
|
|
||||||
| ("subtract", [EvDate(d1), EvDate(d2)]) =>
|
|
||||||
switch DateTime.Date.subtract(d1, d2) {
|
|
||||||
| Ok(d) => EV.EvTimeDuration(d)->Ok
|
|
||||||
| Error(e) => Error(RETodo(e))
|
|
||||||
}->Some
|
|
||||||
| ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
|
|
||||||
EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
|
||||||
| ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
|
|
||||||
EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
|
||||||
| _ => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let durationDispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
> => {
|
> => {
|
||||||
switch call {
|
switch call {
|
||||||
|
@ -55,16 +30,3 @@ let durationDispatch = (call: EV.functionCall, _: DistributionOperation.env): op
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatch = (call: EV.functionCall, env: DistributionOperation.env): option<
|
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
|
||||||
> => {
|
|
||||||
switch dateDispatch(call, env) {
|
|
||||||
| Some(r) => Some(r)
|
|
||||||
| None =>
|
|
||||||
switch durationDispatch(call, env) {
|
|
||||||
| Some(r) => Some(r)
|
|
||||||
| None => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,15 +14,27 @@ type expressionValue = ExpressionValue.expressionValue
|
||||||
Map external calls of Reducer
|
Map external calls of Reducer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
|
||||||
|
let registry = FunctionRegistry_Library.registry
|
||||||
|
|
||||||
|
let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => {
|
||||||
|
FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
|
||||||
|
E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
|
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
|
||||||
expressionValue,
|
expressionValue,
|
||||||
'e,
|
'e,
|
||||||
> =>
|
> => {
|
||||||
switch ReducerInterface_GenericDistribution.dispatch(call, environment) {
|
E.A.O.firstSomeFn([
|
||||||
| Some(r) => r
|
() => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||||
| None =>
|
() => ReducerInterface_Date.dispatch(call, environment),
|
||||||
ReducerInterface_DateTime.dispatch(call, environment) |> E.O.default(chain(call, environment))
|
() => ReducerInterface_Duration.dispatch(call, environment),
|
||||||
}
|
() => ReducerInterface_Number.dispatch(call, environment),
|
||||||
|
() => tryRegistry(call, environment),
|
||||||
|
])->E.O2.default(chain(call, environment))
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally.
|
If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally.
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,18 @@ let dispatchToGenericOutput = (
|
||||||
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
||||||
| ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
|
| ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
|
||||||
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
||||||
| ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist, ~env)
|
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [EvDistribution(dist)]) => {
|
||||||
|
let fn = switch op {
|
||||||
|
| "mean" => #Mean
|
||||||
|
| "stdev" => #Stdev
|
||||||
|
| "variance" => #Variance
|
||||||
|
| "min" => #Min
|
||||||
|
| "max" => #Max
|
||||||
|
| "mode" => #Mode
|
||||||
|
| _ => #Mean
|
||||||
|
}
|
||||||
|
Helpers.toFloatFn(fn, dist, ~env)
|
||||||
|
}
|
||||||
| ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
| ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||||
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||||
| ("toSparkline", [EvDistribution(dist)]) =>
|
| ("toSparkline", [EvDistribution(dist)]) =>
|
||||||
|
@ -348,20 +359,5 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
||||||
| GenDistError(err) => Error(REDistributionError(err))
|
| GenDistError(err) => Error(REDistributionError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
|
let dispatch = (call: ExpressionValue.functionCall, environment) =>
|
||||||
let registry = FunctionRegistry_Library.registry
|
dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
|
||||||
|
|
||||||
let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => {
|
|
||||||
FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
|
|
||||||
E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let dispatch = (call: ExpressionValue.functionCall, environment) => {
|
|
||||||
let regularDispatch =
|
|
||||||
dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
|
|
||||||
switch regularDispatch {
|
|
||||||
| Some(x) => Some(x)
|
|
||||||
| None => tryRegistry(call, environment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
module EV = ReducerInterface_ExpressionValue
|
||||||
|
type expressionValue = EV.expressionValue
|
||||||
|
|
||||||
|
module ScientificUnit = {
|
||||||
|
let nameToMultiplier = str =>
|
||||||
|
switch str {
|
||||||
|
| "n" => Some(1E-9)
|
||||||
|
| "m" => Some(1E-3)
|
||||||
|
| "k" => Some(1E3)
|
||||||
|
| "M" => Some(1E6)
|
||||||
|
| "B" => Some(1E9)
|
||||||
|
| "G" => Some(1E9)
|
||||||
|
| "T" => Some(1E12)
|
||||||
|
| "P" => Some(1E15)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
|
||||||
|
let getMultiplier = (r: string) => {
|
||||||
|
let match = Js.String2.match_(r, %re(`/fromUnit_([_a-zA-Z]*)/`))
|
||||||
|
switch match {
|
||||||
|
| Some([_, unit]) => nameToMultiplier(unit)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||||
|
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
|
> => {
|
||||||
|
switch call {
|
||||||
|
| (
|
||||||
|
("fromUnit_n"
|
||||||
|
| "fromUnit_m"
|
||||||
|
| "fromUnit_k"
|
||||||
|
| "fromUnit_M"
|
||||||
|
| "fromUnit_B"
|
||||||
|
| "fromUnit_G"
|
||||||
|
| "fromUnit_T"
|
||||||
|
| "fromUnit_P") as op,
|
||||||
|
[EvNumber(f)],
|
||||||
|
) =>
|
||||||
|
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => EV.EvNumber(f *. multiplier)->Ok)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ type distToFloatOperation = [
|
||||||
| #Inv(float)
|
| #Inv(float)
|
||||||
| #Mean
|
| #Mean
|
||||||
| #Sample
|
| #Sample
|
||||||
|
| #Min
|
||||||
|
| #Max
|
||||||
]
|
]
|
||||||
|
|
||||||
module Convolution = {
|
module Convolution = {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
"@docusaurus/preset-classic": "2.0.0-beta.21",
|
"@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",
|
"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",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user