Working arrows pointing between boxes

This commit is contained in:
Xevion
2022-12-17 16:58:48 -06:00
parent 30343f1d48
commit 3547b83b3e
5 changed files with 55 additions and 23 deletions

View File

@@ -21,6 +21,7 @@
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-no-ssr": "^1.1.0", "react-no-ssr": "^1.1.0",
"react-xarrows": "^2.0.2",
"sass": "^1.57.0", "sass": "^1.57.0",
"superjson": "1.9.1", "superjson": "1.9.1",
"zod": "^3.18.0" "zod": "^3.18.0"

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
interface BoxGraphicProps { interface BoxGraphicProps {
id?: string;
className?: string; className?: string;
children: React.ReactNode; children: React.ReactNode;
} }
@@ -23,8 +24,8 @@ const [xOffset, yOffset] = [-180, -100];
points = Object.fromEntries(Object.entries(points).map(([k, p]) => [k, [p[0] + xOffset, p[1] + yOffset]])) points = Object.fromEntries(Object.entries(points).map(([k, p]) => [k, [p[0] + xOffset, p[1] + yOffset]]))
const {A, B, C, D, E, F, Z} = points; const {A, B, C, D, E, F, Z} = points;
const BoxGraphic = ({children, className}: BoxGraphicProps) => { const BoxGraphic = ({id, children, className}: BoxGraphicProps) => {
return <svg className={className} viewBox="0 0 370 370" xmlns="http://www.w3.org/2000/svg"> return <svg id={id} className={className} viewBox="0 0 370 370" xmlns="http://www.w3.org/2000/svg">
<g shapeRendering="auto"> <g shapeRendering="auto">
<path id="left" d={`M ${F} L ${Z} L ${D} L ${E} L ${F} Z`} fill={leftColor}/> <path id="left" d={`M ${F} L ${Z} L ${D} L ${E} L ${F} Z`} fill={leftColor}/>
<path id="right" d={`M ${D} L ${C} L ${B} L ${Z} L ${D} Z`} fill={rightColor}/> <path id="right" d={`M ${D} L ${C} L ${B} L ${Z} L ${D} Z`} fill={rightColor}/>

View File

@@ -1,27 +1,47 @@
import {range} from "../utils/helpers"; import {range} from "../utils/helpers";
import BoxGraphic from "./BoxGraphic"; import BoxGraphic from "./BoxGraphic";
import Xarrow from "react-xarrows";
import Chance from "chance"; import Chance from "chance";
import {useState} from "react";
const chance = new Chance(); const chance = new Chance();
const sources = range(0, 100 - 1); const sources = range(1, 100);
const destinations = chance.shuffle(sources); const destinations = chance.shuffle(sources);
const boxes: [number, number][] = sources.map((e, i) => [e, destinations[i] as number]) const boxes: [number, number][] = sources.map((e, i) => [e, destinations[i] as number])
const BoxTable = () => { const BoxTable = () => {
const [line, setLine] = useState<[string, string] | null>(null);
const showLine = (from: number, to: number) => {
setLine([from.toString(), to.toString()]);
}
const hideLine = () => {
setLine(null);
}
const columns = Math.ceil(Math.sqrt(boxes.length));
return ( return (
<div className="grid grid-cols-10 w-full space-y-2"> <>
{boxes.map(([source, destination]) => {line != null ? <Xarrow color={"red"} start={line[0]} end={line[1]} zIndex={50}/> : null}
<div key={source} className="col-span-1 px-2"> <div className="grid w-full space-y-2"
<div className="box aspect-square relative"> style={{gridTemplateColumns: `repeat(${Math.max(3, columns)}, minmax(0, 1fr))`}}>
<span className="absolute left-6 top-8 cursor-pointer">{destination}</span> {boxes.map(([source, destination]) =>
<BoxGraphic className="transition-all cursor-pointer relative z-30"> <div key={source} className="col-span-1 px-2" onMouseEnter={() => showLine(source, destination)}
{source + 1} onMouseLeave={hideLine}>
</BoxGraphic> <div
className="box flex items-center justify-center aspect-square relative">
<div className="text absolute pt-[30%] cursor-pointer">{destination}</div>
<BoxGraphic id={source.toString()} className="transition-all cursor-pointer relative z-30">
{source}
</BoxGraphic>
</div>
</div> </div>
</div> )}
)} </div>
</div> </>
); );
} }

View File

@@ -10,17 +10,13 @@ body {
font-family: "Merriweather", serif; font-family: "Merriweather", serif;
} }
svg {
@apply max-w-full max-h-full;
}
.box { .box {
@apply transition-all; @apply transition-all;
> span { @apply transition-opacity opacity-30; } > .text { @apply transition-opacity opacity-30; }
&:hover { &:hover {
> span { @apply opacity-100; } > .text { @apply opacity-100; }
> svg { > svg {
@apply -translate-y-7; @apply max-w-full max-h-full -translate-y-7;
} }
} }
} }

View File

@@ -216,7 +216,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.16.tgz#966cae211e970199559cfbd295888fca189e49af" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.16.tgz#966cae211e970199559cfbd295888fca189e49af"
integrity sha512-6T7P5bDkRhqRxrQtwj7vru+bWTpelgtcETAZEUSdq0YISKz8WKdoBukQLYQQ6DFHvU9JRsbFq0JH5C51X2ZdnA== integrity sha512-6T7P5bDkRhqRxrQtwj7vru+bWTpelgtcETAZEUSdq0YISKz8WKdoBukQLYQQ6DFHvU9JRsbFq0JH5C51X2ZdnA==
"@types/prop-types@*": "@types/prop-types@*", "@types/prop-types@^15.7.3":
version "15.7.5" version "15.7.5"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
@@ -1482,6 +1482,11 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0, loose-envify@^1.4.0: loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -1814,7 +1819,7 @@ prettier@^2.7.1:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc"
integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==
prop-types@^15.8.1: prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1" version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -1863,6 +1868,15 @@ react-ssr-prepass@^1.5.0:
resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz#bc4ca7fcb52365e6aea11cc254a3d1bdcbd030c5" resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz#bc4ca7fcb52365e6aea11cc254a3d1bdcbd030c5"
integrity sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ== integrity sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ==
react-xarrows@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/react-xarrows/-/react-xarrows-2.0.2.tgz#7555687612339eaefd4ed55fc5c63f2302726d9c"
integrity sha512-tDlAqaxHNmy0vegW/6NdhoWyXJq1LANX/WUAlHyzoHe9BwFVnJPPDghmDjYeVr7XWFmBrVTUrHsrW7GKYI6HtQ==
dependencies:
"@types/prop-types" "^15.7.3"
lodash "^4.17.21"
prop-types "^15.7.2"
react@18.2.0: react@18.2.0:
version "18.2.0" version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"