Show full loop, add onClick box filtering

This commit is contained in:
Xevion
2022-12-17 19:09:12 -06:00
parent 9b3d6798f4
commit 287575827a
2 changed files with 47 additions and 6 deletions

View File

@@ -1,4 +1,4 @@
import {range} from "../utils/helpers";
import {classNames, range} from "../utils/helpers";
import BoxGraphic from "./BoxGraphic";
import Xarrow from "react-xarrows";
@@ -30,18 +30,53 @@ const BoxTable = () => {
const [sources] = useState<number[]>(range(1, 100));
const [destinations] = useState<number[]>(chance.shuffle(sources));
const [boxes] = useState<[number, number][]>(sources.map((e, i) => [e, destinations[i] as number]))
const [boxesBySource] = useState<Record<number, number>>(Object.fromEntries(boxes));
const extractLoop = (start: number): number[] => {
const results: number[] = [];
results.push(start);
while (true) {
const last = results[results.length - 1] as number;
const next = boxesBySource[last] as number;
if (next == start) break;
results.push(next)
}
return results;
}
const [filteredBoxes, setFilteredBoxes] = useState<Record<number, boolean>>(Object.fromEntries(
sources.map(n => [n, false])
));
const [enabledLines, setEnabledLines] = useState<Record<number, boolean>>(Object.fromEntries(
sources.map(n => [n, false])
));
const showLine = (from: number) => {
setEnabledLines((prev) => ({...prev, [from]: true}))
const [isFiltered, setFiltered] = useState(false);
const toggleLines = (from: number) => {
hideLine(from);
const newState = !isFiltered;
setFiltered(newState);
showLine(from, newState);
const loop = Object.fromEntries(extractLoop(from).map(n => [n, false]));
setFilteredBoxes((prev) => {
const outsideLoop = Object.fromEntries(Object.entries(prev).map(([n]) => [n, newState]))
return {...outsideLoop, ...loop};
})
}
const showLine = (from: number, showLess: boolean | null = null) => {
const loop = Object.fromEntries(extractLoop(from).slice(0, (showLess ?? isFiltered) ? 15 : 3).map(n => [n, true]));
setEnabledLines((prev) => ({...prev, ...loop}))
}
const hideLine = (from: number) => {
setEnabledLines((prev) => ({...prev, [from]: false}))
const loop = Object.fromEntries(extractLoop(from).slice(0, isFiltered ? 15 : 3).map(n => [n, false]));
setEnabledLines((prev) => ({...prev, ...loop}))
}
const getColor = (seed: any) => {
@@ -55,7 +90,9 @@ const BoxTable = () => {
<div className="grid w-full space-y-2"
style={{gridTemplateColumns: `repeat(${Math.max(3, columns)}, minmax(0, 1fr))`}}>
{boxes.map(([source, destination]) =>
<div key={source} className="col-span-1 px-2" onMouseEnter={() => showLine(source)}
<div key={source}
className={classNames("col-span-1 px-2", isFiltered && filteredBoxes[source] ? "opacity-0 pointer-events-none" : null)}
onClick={() => toggleLines(source)} onMouseEnter={() => showLine(source)}
onMouseLeave={() => hideLine(source)}>
<div
className="box flex items-center justify-center aspect-square relative">

View File

@@ -1,2 +1,6 @@
export const range = (start: number, stop: number, step = 1) =>
Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step);
Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step);
export function classNames(...classes: (string | null | undefined)[]) {
return classes.filter(Boolean).join(" ");
}