diff --git a/src/components/BoxTable.tsx b/src/components/BoxTable.tsx index e32052f..171e900 100644 --- a/src/components/BoxTable.tsx +++ b/src/components/BoxTable.tsx @@ -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(range(1, 100)); const [destinations] = useState(chance.shuffle(sources)); const [boxes] = useState<[number, number][]>(sources.map((e, i) => [e, destinations[i] as number])) + const [boxesBySource] = useState>(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>(Object.fromEntries( + sources.map(n => [n, false]) + )); const [enabledLines, setEnabledLines] = useState>(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 = () => {
{boxes.map(([source, destination]) => -
showLine(source)} +
toggleLines(source)} onMouseEnter={() => showLine(source)} onMouseLeave={() => hideLine(source)}>
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 4e972bf..c35c637 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,2 +1,6 @@ export const range = (start: number, stop: number, step = 1) => - Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step); \ No newline at end of file + Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step); + +export function classNames(...classes: (string | null | undefined)[]) { + return classes.filter(Boolean).join(" "); +} \ No newline at end of file