-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathgrid-stack-render-provider.tsx
More file actions
87 lines (80 loc) · 2.59 KB
/
grid-stack-render-provider.tsx
File metadata and controls
87 lines (80 loc) · 2.59 KB
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {
PropsWithChildren,
useCallback,
useLayoutEffect,
useMemo,
useRef,
} from "react";
import { useGridStackContext } from "./grid-stack-context";
import { GridStack, GridStackOptions, GridStackWidget } from "gridstack";
import { GridStackRenderContext } from "./grid-stack-render-context";
import isEqual from "react-fast-compare";
export function GridStackRenderProvider({ children }: PropsWithChildren) {
const {
_gridStack: { value: gridStack, set: setGridStack },
initialOptions,
} = useGridStackContext();
const widgetContainersRef = useRef<Map<string, HTMLElement>>(new Map());
const containerRef = useRef<HTMLDivElement>(null);
const optionsRef = useRef<GridStackOptions>(initialOptions);
const renderCBFn = useCallback(
(element: HTMLElement, widget: GridStackWidget) => {
if (widget.id) {
widgetContainersRef.current.set(widget.id, element);
}
},
[]
);
const initGrid = useCallback(() => {
if (containerRef.current) {
GridStack.renderCB = renderCBFn;
return GridStack.init(optionsRef.current, containerRef.current);
// ! Change event not firing on nested grids (resize, move...) https://github.com/gridstack/gridstack.js/issues/2671
// .on("change", () => {
// console.log("changed");
// })
// .on("resize", () => {
// console.log("resize");
// })
}
return null;
}, [renderCBFn]);
useLayoutEffect(() => {
if (!isEqual(initialOptions, optionsRef.current) && gridStack) {
try {
gridStack.removeAll(false);
gridStack.destroy(false);
widgetContainersRef.current.clear();
optionsRef.current = initialOptions;
setGridStack(initGrid());
} catch (e) {
console.error("Error reinitializing gridstack", e);
}
}
}, [initialOptions, gridStack, initGrid, setGridStack]);
useLayoutEffect(() => {
if (!gridStack) {
try {
setGridStack(initGrid());
} catch (e) {
console.error("Error initializing gridstack", e);
}
}
}, [gridStack, initGrid, setGridStack]);
return (
<GridStackRenderContext.Provider
value={useMemo(
() => ({
getWidgetContainer: (widgetId: string) => {
return widgetContainersRef.current.get(widgetId) || null;
},
}),
// ! gridStack is required to reinitialize the grid when the options change
// eslint-disable-next-line react-hooks/exhaustive-deps
[gridStack]
)}
>
<div ref={containerRef}>{gridStack ? children : null}</div>
</GridStackRenderContext.Provider>
);
}