44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
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));
|
|
}
|
|
};
|
|
}
|