/
useLayoutFactory.ts
54 lines (45 loc) · 1.41 KB
/
useLayoutFactory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { useCallback, useRef } from "react";
import Graph from "graphology";
import { useSigma, isEqual } from "@react-sigma/core";
/**
* Generic type for Graphology layout.
*/
interface GraphologyLayout<T> {
(graph: Graph, options: T): { [node: string]: { [dimension: string]: number } };
assign(graph: Graph, options: T): void;
}
/**
* Generic type for layout hooks.
*/
export type LayoutHook<T> = (settings?: T) => {
/**
* Returns a positions map by node key.
*/
positions: () => { [node: string]: { [dimension: string]: number } };
/**
* Assign layout node's position into the sigma graph.
*/
assign: () => void;
};
/**
* Factory for layout hook.
*/
export function useLayoutFactory<T>(layout: GraphologyLayout<T>, defaultSettings: T): LayoutHook<T> {
const hook: LayoutHook<T> = (parameter: T = defaultSettings) => {
const sigma = useSigma();
// Default layout settings
const settings = useRef<T>(defaultSettings);
if (!isEqual(settings.current, parameter)) settings.current = parameter;
const positions = useCallback(() => {
if (settings.current) return layout(sigma.getGraph(), settings.current);
else return {};
}, [sigma, settings]);
const assign = useCallback(() => {
if (settings.current) {
layout.assign(sigma.getGraph(), settings.current);
}
}, [sigma, settings]);
return { positions, assign };
};
return hook;
}