feat(charts): manage investigation charts in a scrolling workspace
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { useLayoutEffect, useState } from "react";
|
||||
import { columnsForLayout, reconcileChartSlots, swapChartSlots, type ChartLayout, type ChartSlot } from "../utils/chart-window-slots";
|
||||
|
||||
/** Keep chart identities in fixed positions throughout the scrolling grid. */
|
||||
export function useChartWindowLayout(ids: string[]) {
|
||||
const [container, setContainer] = useState<HTMLElement | null>(null);
|
||||
const [narrow, setNarrow] = useState(window.innerWidth < 760);
|
||||
const [preferredLayout, setPreferredLayout] = useState<ChartLayout>("four");
|
||||
const layout = narrow ? "one" : preferredLayout;
|
||||
const columns = columnsForLayout(layout);
|
||||
const [slots, setSlots] = useState<ChartSlot[]>([]);
|
||||
const available = reconcileChartSlots(slots, ids, columns);
|
||||
if (available !== slots) setSlots(available);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!container) return;
|
||||
const measure = () => setNarrow(container.clientWidth < 720);
|
||||
measure();
|
||||
const observer = new ResizeObserver(measure);
|
||||
observer.observe(container);
|
||||
return () => observer.disconnect();
|
||||
}, [container]);
|
||||
|
||||
return {
|
||||
containerRef: setContainer,
|
||||
layout,
|
||||
preferredLayout,
|
||||
narrow,
|
||||
setLayout: setPreferredLayout,
|
||||
slots: available,
|
||||
columns,
|
||||
move: (id: string, target: number) => {
|
||||
const source = available.indexOf(id);
|
||||
const next = swapChartSlots(available, source, target);
|
||||
if (next !== available) {
|
||||
setSlots(next);
|
||||
}
|
||||
},
|
||||
reset: () => {
|
||||
setSlots(reconcileChartSlots([], ids, columns));
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user