remove collapse animation; tooltips with types
This commit is contained in:
parent
0ef2428c80
commit
c401f39520
|
@ -3,6 +3,8 @@
|
|||
"version": "0.2.20",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^0.7.2",
|
||||
"@floating-ui/react-dom-interactions": "^0.6.6",
|
||||
"@headlessui/react": "^1.6.5",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@hookform/resolvers": "^2.9.3",
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from "./DistributionChart";
|
||||
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
||||
import clsx from "clsx";
|
||||
import { LayoutGroup, motion } from "framer-motion";
|
||||
import { Tooltip } from "./ui/Tooltip";
|
||||
|
||||
function getRange<a>(x: declaration<a>) {
|
||||
const first = x.args[0];
|
||||
|
@ -40,59 +40,45 @@ interface VariableBoxProps {
|
|||
name?: string;
|
||||
heading: string;
|
||||
children: React.ReactNode;
|
||||
showTypes: boolean;
|
||||
}
|
||||
|
||||
const VariableBox: React.FC<VariableBoxProps> = ({
|
||||
name,
|
||||
heading = "Error",
|
||||
children,
|
||||
showTypes = false,
|
||||
}) => {
|
||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||
return (
|
||||
<motion.div layout transition={{ type: "tween" }}>
|
||||
{name || showTypes ? (
|
||||
<motion.header
|
||||
layout="position"
|
||||
transition={{ type: "tween" }}
|
||||
<div>
|
||||
{name ? (
|
||||
<header
|
||||
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}
|
||||
{name ? (
|
||||
<Tooltip text={heading}>
|
||||
<span>{name}:</span>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{isCollapsed ? (
|
||||
<span className="bg-slate-200 rounded p-0.5 font-xs">...</span>
|
||||
) : null}
|
||||
</motion.header>
|
||||
</header>
|
||||
) : null}
|
||||
{isCollapsed ? null : (
|
||||
<motion.div layout="position" transition={{ type: "tween" }}>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</motion.div>
|
||||
{isCollapsed ? null : <div>{children}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const VariableList: React.FC<{
|
||||
name?: string;
|
||||
heading: string;
|
||||
showTypes: boolean;
|
||||
children: React.ReactNode;
|
||||
}> = ({ name, heading, showTypes, children }) => (
|
||||
<VariableBox name={name} heading={heading} showTypes={showTypes}>
|
||||
<motion.div
|
||||
layout="position"
|
||||
transition={{ type: "tween" }}
|
||||
className={clsx(
|
||||
"space-y-3",
|
||||
name ? "border-l pl-4" : null,
|
||||
name || showTypes ? "pt-1 mt-1" : null
|
||||
)}
|
||||
>
|
||||
<LayoutGroup>{children}</LayoutGroup>
|
||||
</motion.div>
|
||||
}> = ({ name, heading, children }) => (
|
||||
<VariableBox name={name} heading={heading}>
|
||||
<div className={clsx("space-y-3", name ? "border-l pl-4 pt-1 mt-1" : null)}>
|
||||
{children}
|
||||
</div>
|
||||
</VariableBox>
|
||||
);
|
||||
|
||||
|
@ -103,8 +89,8 @@ export interface SquiggleItemProps {
|
|||
width?: number;
|
||||
height: number;
|
||||
distributionPlotSettings: DistributionPlottingSettings;
|
||||
/** Whether to show type information */
|
||||
showTypes: boolean;
|
||||
/** Whether to show type information; deprecated */
|
||||
showTypes?: boolean;
|
||||
/** Settings for displaying functions */
|
||||
chartSettings: FunctionChartSettings;
|
||||
/** Environment for further function executions */
|
||||
|
@ -124,7 +110,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
switch (expression.tag) {
|
||||
case "number":
|
||||
return (
|
||||
<VariableBox name={name} heading="Number" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Number">
|
||||
<div className="font-semibold text-slate-600">
|
||||
<NumberShower precision={3} number={expression.value} />
|
||||
</div>
|
||||
|
@ -135,12 +121,10 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
return (
|
||||
<VariableBox
|
||||
name={name}
|
||||
heading={`Distribution (${distType})`}
|
||||
showTypes={showTypes}
|
||||
heading={`Distribution (${distType})\n${
|
||||
distType === "Symbolic" ? expression.value.toString() : ""
|
||||
}`}
|
||||
>
|
||||
{distType === "Symbolic" && showTypes ? (
|
||||
<div>{expression.value.toString()}</div>
|
||||
) : null}
|
||||
<DistributionChart
|
||||
distribution={expression.value}
|
||||
{...distributionPlotSettings}
|
||||
|
@ -152,7 +136,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
}
|
||||
case "string":
|
||||
return (
|
||||
<VariableBox name={name} heading="String" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="String">
|
||||
<span className="text-slate-400">"</span>
|
||||
<span className="text-slate-600 font-semibold font-mono">
|
||||
{expression.value}
|
||||
|
@ -162,45 +146,45 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
);
|
||||
case "boolean":
|
||||
return (
|
||||
<VariableBox name={name} heading="Boolean" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Boolean">
|
||||
{expression.value.toString()}
|
||||
</VariableBox>
|
||||
);
|
||||
case "symbol":
|
||||
return (
|
||||
<VariableBox name={name} heading="Symbol" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Symbol">
|
||||
<span className="text-slate-500 mr-2">Undefined Symbol:</span>
|
||||
<span className="text-slate-600">{expression.value}</span>
|
||||
</VariableBox>
|
||||
);
|
||||
case "call":
|
||||
return (
|
||||
<VariableBox name={name} heading="Call" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Call">
|
||||
{expression.value}
|
||||
</VariableBox>
|
||||
);
|
||||
case "arraystring":
|
||||
return (
|
||||
<VariableBox name={name} heading="Array String" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Array String">
|
||||
{expression.value.map((r) => `"${r}"`).join(", ")}
|
||||
</VariableBox>
|
||||
);
|
||||
case "date":
|
||||
return (
|
||||
<VariableBox name={name} heading="Date" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Date">
|
||||
{expression.value.toDateString()}
|
||||
</VariableBox>
|
||||
);
|
||||
case "timeDuration": {
|
||||
return (
|
||||
<VariableBox name={name} heading="Time Duration" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Time Duration">
|
||||
<NumberShower precision={3} number={expression.value} />
|
||||
</VariableBox>
|
||||
);
|
||||
}
|
||||
case "lambda":
|
||||
return (
|
||||
<VariableBox name={name} heading="Function" showTypes={showTypes}>
|
||||
<VariableBox name={name} heading="Function">
|
||||
<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>
|
||||
|
@ -218,11 +202,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
);
|
||||
case "lambdaDeclaration": {
|
||||
return (
|
||||
<VariableBox
|
||||
name={name}
|
||||
heading="Function Declaration"
|
||||
showTypes={showTypes}
|
||||
>
|
||||
<VariableBox name={name} heading="Function Declaration">
|
||||
<FunctionChart
|
||||
fn={expression.value.fn}
|
||||
chartSettings={getChartSettings(expression.value)}
|
||||
|
@ -238,7 +218,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
}
|
||||
case "module": {
|
||||
return (
|
||||
<VariableList name={name} heading="Module" showTypes={showTypes}>
|
||||
<VariableList name={name} heading="Module">
|
||||
{Object.entries(expression.value)
|
||||
.filter(([key, r]) => key !== "Math")
|
||||
.map(([key, r]) => (
|
||||
|
@ -248,7 +228,6 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
expression={r}
|
||||
width={width !== undefined ? width - 20 : width}
|
||||
height={height / 3}
|
||||
showTypes={showTypes}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
|
@ -259,7 +238,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
}
|
||||
case "record":
|
||||
return (
|
||||
<VariableList name={name} heading="Record" showTypes={showTypes}>
|
||||
<VariableList name={name} heading="Record">
|
||||
{Object.entries(expression.value).map(([key, r]) => (
|
||||
<SquiggleItem
|
||||
key={key}
|
||||
|
@ -267,7 +246,6 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
expression={r}
|
||||
width={width !== undefined ? width - 20 : width}
|
||||
height={height / 3}
|
||||
showTypes={showTypes}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
|
@ -277,7 +255,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
);
|
||||
case "array":
|
||||
return (
|
||||
<VariableList name={name} heading="Array" showTypes={showTypes}>
|
||||
<VariableList name={name} heading="Array">
|
||||
{expression.value.map((r, i) => (
|
||||
<SquiggleItem
|
||||
key={i}
|
||||
|
@ -286,7 +264,6 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
width={width !== undefined ? width - 20 : width}
|
||||
height={50}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
showTypes={showTypes}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
/>
|
||||
|
|
63
packages/components/src/components/ui/Tooltip.tsx
Normal file
63
packages/components/src/components/ui/Tooltip.tsx
Normal file
|
@ -0,0 +1,63 @@
|
|||
import React, { cloneElement, useState } from "react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import {
|
||||
shift,
|
||||
useDismiss,
|
||||
useFloating,
|
||||
useHover,
|
||||
useInteractions,
|
||||
useRole,
|
||||
} from "@floating-ui/react-dom-interactions";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
export const Tooltip: React.FC<Props> = ({ text, children }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { x, y, reference, floating, strategy, context } = useFloating({
|
||||
placement: "top",
|
||||
open,
|
||||
onOpenChange: setOpen,
|
||||
middleware: [shift()],
|
||||
});
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||
useHover(context),
|
||||
useRole(context, { role: "tooltip" }),
|
||||
useDismiss(context),
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{cloneElement(
|
||||
children,
|
||||
getReferenceProps({ ref: reference, ...children.props })
|
||||
)}
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
{...getFloatingProps({
|
||||
ref: floating,
|
||||
className:
|
||||
"text-xs p-2 border border-gray-300 rounded bg-white z-10",
|
||||
style: {
|
||||
position: strategy,
|
||||
top: y ?? 0,
|
||||
left: x ?? 0,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<pre>{text}</pre>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
};
|
48
yarn.lock
48
yarn.lock
|
@ -1829,6 +1829,35 @@
|
|||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@floating-ui/core@^0.7.3":
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86"
|
||||
integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==
|
||||
|
||||
"@floating-ui/dom@^0.5.3":
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1"
|
||||
integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^0.7.3"
|
||||
|
||||
"@floating-ui/react-dom-interactions@^0.6.6":
|
||||
version "0.6.6"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.6.6.tgz#8542e8c4bcbee2cd0d512de676c6a493e0a2d168"
|
||||
integrity sha512-qnao6UPjSZNHnXrF+u4/n92qVroQkx0Umlhy3Avk1oIebm/5ee6yvDm4xbHob0OjY7ya8WmUnV3rQlPwX3Atwg==
|
||||
dependencies:
|
||||
"@floating-ui/react-dom" "^0.7.2"
|
||||
aria-hidden "^1.1.3"
|
||||
use-isomorphic-layout-effect "^1.1.1"
|
||||
|
||||
"@floating-ui/react-dom@^0.7.2":
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864"
|
||||
integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "^0.5.3"
|
||||
use-isomorphic-layout-effect "^1.1.1"
|
||||
|
||||
"@gar/promisify@^1.0.1":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
|
@ -4421,10 +4450,10 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^18.0.1", "@types/react@^18.0.9":
|
||||
version "18.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d"
|
||||
integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q==
|
||||
"@types/react@*", "@types/react@17.0.43", "@types/react@^18.0.9":
|
||||
version "17.0.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
|
||||
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
|
@ -5373,6 +5402,13 @@ argv@0.0.2:
|
|||
resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab"
|
||||
integrity sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==
|
||||
|
||||
aria-hidden@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
|
||||
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
|
||||
dependencies:
|
||||
tslib "^1.0.0"
|
||||
|
||||
aria-query@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
||||
|
@ -14872,7 +14908,7 @@ react-vega@^7.5.1:
|
|||
prop-types "^15.8.1"
|
||||
vega-embed "^6.5.1"
|
||||
|
||||
react@^18.0.0, react@^18.1.0:
|
||||
react@^18.1.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
|
@ -17071,7 +17107,7 @@ tsconfig-paths@^3.14.1, tsconfig-paths@^3.9.0:
|
|||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.8.1:
|
||||
tslib@^1.0.0, tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
|
Loading…
Reference in New Issue
Block a user