@deepdub/react-arborist
Version:
49 lines (48 loc) • 2.43 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useImperativeHandle, useMemo, useRef, } from "react";
import { useSyncExternalStore } from "use-sync-external-store/shim";
import { DataUpdatesContext, DndContext, NodesContext, TreeApiContext, } from "../context";
import { TreeApi } from "../interfaces/tree-api";
import { initialState } from "../state/initial";
import { rootReducer } from "../state/root-reducer";
import { HTML5Backend } from "react-dnd-html5-backend";
import { DndProvider } from "react-dnd";
import { createStore } from "redux";
import { actions as visibility } from "../state/open-slice";
const SERVER_STATE = initialState();
export function TreeProvider({ treeProps, imperativeHandle, children, }) {
const list = useRef(null);
const listEl = useRef(null);
const store = useRef(
// @ts-ignore
createStore(rootReducer, initialState(treeProps)));
const state = useSyncExternalStore(store.current.subscribe, store.current.getState, () => SERVER_STATE);
/* The tree api object is stable. */
const api = useMemo(() => {
return new TreeApi(store.current, treeProps, list, listEl);
}, []);
/* Make sure the tree instance stays in sync */
const updateCount = useRef(0);
useMemo(() => {
updateCount.current += 1;
api.update(treeProps);
}, [...Object.values(treeProps), state.nodes.open]);
/* Expose the tree api */
useImperativeHandle(imperativeHandle, () => api);
/* Change selection based on props */
useEffect(() => {
if (api.props.selection) {
api.select(api.props.selection, { focus: false });
}
else {
api.deselectAll();
}
}, [api.props.selection]);
/* Clear visability for filtered nodes */
useEffect(() => {
if (!api.props.searchTerm) {
store.current.dispatch(visibility.clear(true));
}
}, [api.props.searchTerm]);
return (_jsx(TreeApiContext.Provider, { value: api, children: _jsx(DataUpdatesContext.Provider, { value: updateCount.current, children: _jsx(NodesContext.Provider, { value: state.nodes, children: _jsx(DndContext.Provider, { value: state.dnd, children: _jsx(DndProvider, Object.assign({ backend: HTML5Backend, options: { rootElement: api.props.dndRootElement || undefined } }, (treeProps.dndManager && { manager: treeProps.dndManager }), { children: children })) }) }) }) }));
}