react-arborist 3.3.0-rc.1 → 3.3.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main/components/cursor.d.ts +1 -0
- package/dist/main/components/cursor.js +20 -0
- package/dist/{components → main/components}/default-container.d.ts +1 -2
- package/dist/main/components/default-container.js +238 -0
- package/dist/main/components/default-cursor.js +35 -0
- package/dist/{components → main/components}/default-drag-preview.d.ts +1 -2
- package/dist/main/components/default-drag-preview.js +57 -0
- package/dist/{components → main/components}/default-node.d.ts +1 -2
- package/dist/main/components/default-node.js +32 -0
- package/dist/{components → main/components}/default-row.d.ts +1 -2
- package/dist/main/components/default-row.js +8 -0
- package/dist/main/components/drag-preview-container.d.ts +1 -0
- package/dist/main/components/drag-preview-container.js +21 -0
- package/dist/{components → main/components}/list-inner-element.d.ts +1 -1
- package/dist/main/components/list-inner-element.js +25 -0
- package/dist/main/components/list-outer-element.d.ts +2 -0
- package/dist/main/components/list-outer-element.js +38 -0
- package/dist/main/components/outer-drop.js +9 -0
- package/dist/{components → main/components}/provider.d.ts +2 -2
- package/dist/main/components/provider.js +52 -0
- package/dist/{components → main/components}/row-container.d.ts +2 -2
- package/dist/main/components/row-container.js +84 -0
- package/dist/main/components/tree-container.d.ts +1 -0
- package/dist/main/components/tree-container.js +12 -0
- package/dist/{components → main/components}/tree.d.ts +1 -1
- package/dist/main/components/tree.js +15 -0
- package/dist/{context.d.ts → main/context.d.ts} +4 -4
- package/dist/main/context.js +33 -0
- package/dist/main/data/create-index.js +10 -0
- package/dist/main/data/create-list.js +62 -0
- package/dist/main/data/create-root.js +43 -0
- package/dist/main/data/make-tree.d.ts +5 -0
- package/dist/main/data/make-tree.js +40 -0
- package/dist/{data → main/data}/simple-tree.d.ts +1 -1
- package/dist/main/data/simple-tree.js +100 -0
- package/dist/{dnd → main/dnd}/compute-drop.d.ts +6 -6
- package/dist/main/dnd/compute-drop.js +129 -0
- package/dist/main/dnd/drag-hook.js +46 -0
- package/dist/{dnd → main/dnd}/drop-hook.d.ts +1 -1
- package/dist/main/dnd/drop-hook.js +42 -0
- package/dist/main/dnd/measure-hover.d.ts +8 -0
- package/dist/main/dnd/measure-hover.js +21 -0
- package/dist/main/dnd/outer-drop-hook.js +45 -0
- package/dist/main/hooks/use-fresh-node.js +18 -0
- package/dist/{hooks → main/hooks}/use-simple-tree.d.ts +1 -1
- package/dist/main/hooks/use-simple-tree.js +35 -0
- package/dist/main/hooks/use-validated-props.js +29 -0
- package/dist/main/index.js +27 -0
- package/dist/{interfaces → main/interfaces}/node-api.d.ts +1 -1
- package/dist/main/interfaces/node-api.js +164 -0
- package/dist/{interfaces → main/interfaces}/tree-api.d.ts +87 -7
- package/dist/main/interfaces/tree-api.js +649 -0
- package/dist/main/interfaces/tree-api.test.d.ts +1 -0
- package/dist/main/interfaces/tree-api.test.js +14 -0
- package/dist/{state → main/state}/dnd-slice.d.ts +1 -1
- package/dist/main/state/dnd-slice.js +35 -0
- package/dist/{state → main/state}/drag-slice.d.ts +1 -1
- package/dist/main/state/drag-slice.js +24 -0
- package/dist/{state → main/state}/edit-slice.d.ts +1 -1
- package/dist/main/state/edit-slice.js +18 -0
- package/dist/{state → main/state}/focus-slice.d.ts +1 -1
- package/dist/main/state/focus-slice.js +26 -0
- package/dist/main/state/initial.js +29 -0
- package/dist/{state → main/state}/open-slice.d.ts +2 -2
- package/dist/main/state/open-slice.js +48 -0
- package/dist/main/state/root-reducer.d.ts +96 -0
- package/dist/main/state/root-reducer.js +20 -0
- package/dist/{state → main/state}/selection-slice.d.ts +1 -1
- package/dist/main/state/selection-slice.js +59 -0
- package/dist/{types → main/types}/dnd.d.ts +2 -2
- package/dist/main/types/dnd.js +2 -0
- package/dist/{types → main/types}/handlers.d.ts +5 -5
- package/dist/main/types/handlers.js +2 -0
- package/dist/{types → main/types}/renderers.d.ts +4 -4
- package/dist/main/types/renderers.js +2 -0
- package/dist/main/types/state.d.ts +2 -0
- package/dist/main/types/state.js +2 -0
- package/dist/main/types/tree-props.js +2 -0
- package/dist/{types → main/types}/utils.d.ts +5 -5
- package/dist/main/types/utils.js +2 -0
- package/dist/main/utils.js +183 -0
- package/dist/module/components/cursor.d.ts +1 -0
- package/dist/module/components/cursor.js +16 -0
- package/dist/module/components/default-container.d.ts +6 -0
- package/dist/module/components/default-container.js +234 -0
- package/dist/module/components/default-cursor.d.ts +3 -0
- package/dist/module/components/default-cursor.js +29 -0
- package/dist/module/components/default-drag-preview.d.ts +2 -0
- package/dist/module/components/default-drag-preview.js +53 -0
- package/dist/module/components/default-node.d.ts +2 -0
- package/dist/module/components/default-node.js +28 -0
- package/dist/module/components/default-row.d.ts +2 -0
- package/dist/module/components/default-row.js +4 -0
- package/dist/module/components/drag-preview-container.d.ts +1 -0
- package/dist/module/components/drag-preview-container.js +17 -0
- package/dist/module/components/list-inner-element.d.ts +2 -0
- package/dist/module/components/list-inner-element.js +22 -0
- package/dist/module/components/list-outer-element.d.ts +2 -0
- package/dist/module/components/list-outer-element.js +35 -0
- package/dist/module/components/outer-drop.d.ts +4 -0
- package/dist/module/components/outer-drop.js +5 -0
- package/dist/module/components/provider.d.ts +10 -0
- package/dist/module/components/provider.js +48 -0
- package/dist/module/components/row-container.d.ts +7 -0
- package/dist/module/components/row-container.js +58 -0
- package/dist/module/components/tree-container.d.ts +1 -0
- package/dist/module/components/tree-container.js +8 -0
- package/dist/module/components/tree.d.ts +8 -0
- package/dist/module/components/tree.js +12 -0
- package/dist/module/context.d.ts +22 -0
- package/dist/module/context.js +26 -0
- package/dist/module/data/create-index.d.ts +4 -0
- package/dist/module/data/create-index.js +6 -0
- package/dist/module/data/create-list.d.ts +3 -0
- package/dist/module/data/create-list.js +58 -0
- package/dist/module/data/create-root.d.ts +4 -0
- package/dist/module/data/create-root.js +39 -0
- package/dist/module/data/make-tree.d.ts +5 -0
- package/dist/module/data/make-tree.js +36 -0
- package/dist/module/data/simple-tree.d.ts +44 -0
- package/dist/module/data/simple-tree.js +96 -0
- package/dist/module/dnd/compute-drop.d.ts +37 -0
- package/dist/module/dnd/compute-drop.js +125 -0
- package/dist/module/dnd/drag-hook.d.ts +3 -0
- package/dist/module/dnd/drag-hook.js +42 -0
- package/dist/module/dnd/drop-hook.d.ts +8 -0
- package/dist/module/dnd/drop-hook.js +38 -0
- package/dist/module/dnd/measure-hover.d.ts +8 -0
- package/dist/module/dnd/measure-hover.js +17 -0
- package/dist/module/dnd/outer-drop-hook.d.ts +1 -0
- package/dist/module/dnd/outer-drop-hook.js +41 -0
- package/dist/module/hooks/use-fresh-node.d.ts +1 -0
- package/dist/module/hooks/use-fresh-node.js +14 -0
- package/dist/module/hooks/use-simple-tree.d.ts +12 -0
- package/dist/module/hooks/use-simple-tree.js +31 -0
- package/dist/module/hooks/use-validated-props.d.ts +2 -0
- package/dist/module/hooks/use-validated-props.js +25 -0
- package/dist/module/index.d.ts +8 -0
- package/dist/module/index.js +9 -0
- package/dist/module/interfaces/node-api.d.ts +71 -0
- package/dist/module/interfaces/node-api.js +160 -0
- package/dist/module/interfaces/tree-api.d.ts +214 -0
- package/dist/module/interfaces/tree-api.js +622 -0
- package/dist/module/interfaces/tree-api.test.d.ts +1 -0
- package/dist/module/interfaces/tree-api.test.js +12 -0
- package/dist/module/state/dnd-slice.d.ts +29 -0
- package/dist/module/state/dnd-slice.js +31 -0
- package/dist/module/state/drag-slice.d.ts +9 -0
- package/dist/module/state/drag-slice.js +20 -0
- package/dist/module/state/edit-slice.d.ts +8 -0
- package/dist/module/state/edit-slice.js +13 -0
- package/dist/module/state/focus-slice.d.ts +12 -0
- package/dist/module/state/focus-slice.js +20 -0
- package/dist/module/state/initial.d.ts +3 -0
- package/dist/module/state/initial.js +25 -0
- package/dist/module/state/open-slice.d.ts +30 -0
- package/dist/module/state/open-slice.js +44 -0
- package/dist/module/state/root-reducer.d.ts +96 -0
- package/dist/module/state/root-reducer.js +17 -0
- package/dist/module/state/selection-slice.d.ts +42 -0
- package/dist/module/state/selection-slice.js +55 -0
- package/dist/module/types/dnd.d.ts +8 -0
- package/dist/module/types/dnd.js +1 -0
- package/dist/module/types/handlers.d.ts +30 -0
- package/dist/module/types/handlers.js +1 -0
- package/dist/module/types/renderers.d.ts +29 -0
- package/dist/module/types/renderers.js +1 -0
- package/dist/module/types/state.d.ts +2 -0
- package/dist/module/types/state.js +1 -0
- package/dist/module/types/tree-props.d.ts +56 -0
- package/dist/module/types/tree-props.js +1 -0
- package/dist/module/types/utils.d.ts +17 -0
- package/dist/module/types/utils.js +1 -0
- package/dist/module/utils.d.ts +24 -0
- package/dist/module/utils.js +162 -0
- package/package.json +26 -25
- package/src/components/default-container.tsx +2 -0
- package/src/components/provider.tsx +3 -2
- package/src/components/row-container.tsx +1 -1
- package/dist/components/cursor.d.ts +0 -2
- package/dist/components/drag-preview-container.d.ts +0 -2
- package/dist/components/list-outer-element.d.ts +0 -2
- package/dist/components/tree-container.d.ts +0 -2
- package/dist/index.js +0 -2433
- package/dist/index.js.map +0 -1
- package/dist/module.js +0 -2406
- package/dist/module.js.map +0 -1
- package/dist/state/root-reducer.d.ts +0 -13
- package/dist/types/state.d.ts +0 -2
- package/jest.config.js +0 -5
- package/tsconfig.json +0 -4
- /package/dist/{components → main/components}/default-cursor.d.ts +0 -0
- /package/dist/{components → main/components}/outer-drop.d.ts +0 -0
- /package/dist/{data → main/data}/create-index.d.ts +0 -0
- /package/dist/{data → main/data}/create-list.d.ts +0 -0
- /package/dist/{data → main/data}/create-root.d.ts +0 -0
- /package/dist/{dnd → main/dnd}/drag-hook.d.ts +0 -0
- /package/dist/{dnd → main/dnd}/outer-drop-hook.d.ts +0 -0
- /package/dist/{hooks → main/hooks}/use-fresh-node.d.ts +0 -0
- /package/dist/{hooks → main/hooks}/use-validated-props.d.ts +0 -0
- /package/dist/{index.d.ts → main/index.d.ts} +0 -0
- /package/dist/{state → main/state}/initial.d.ts +0 -0
- /package/dist/{types → main/types}/tree-props.d.ts +0 -0
- /package/dist/{utils.d.ts → main/utils.d.ts} +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { TreeApi } from "../interfaces/tree-api";
|
|
3
|
+
import { TreeProps } from "../types/tree-props";
|
|
4
|
+
type Props<T> = {
|
|
5
|
+
treeProps: TreeProps<T>;
|
|
6
|
+
imperativeHandle: React.Ref<TreeApi<T> | undefined>;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export declare function TreeProvider<T>({ treeProps, imperativeHandle, children, }: Props<T>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useImperativeHandle, useMemo, useRef, } from "react";
|
|
3
|
+
import { useSyncExternalStore } from "use-sync-external-store/shim";
|
|
4
|
+
import { DataUpdatesContext, DndContext, NodesContext, TreeApiContext, } from "../context";
|
|
5
|
+
import { TreeApi } from "../interfaces/tree-api";
|
|
6
|
+
import { initialState } from "../state/initial";
|
|
7
|
+
import { rootReducer } from "../state/root-reducer";
|
|
8
|
+
import { HTML5Backend } from "react-dnd-html5-backend";
|
|
9
|
+
import { DndProvider } from "react-dnd";
|
|
10
|
+
import { createStore } from "redux";
|
|
11
|
+
import { actions as visibility } from "../state/open-slice";
|
|
12
|
+
const SERVER_STATE = initialState();
|
|
13
|
+
export function TreeProvider({ treeProps, imperativeHandle, children, }) {
|
|
14
|
+
const list = useRef(null);
|
|
15
|
+
const listEl = useRef(null);
|
|
16
|
+
const store = useRef(
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
createStore(rootReducer, initialState(treeProps)));
|
|
19
|
+
const state = useSyncExternalStore(store.current.subscribe, store.current.getState, () => SERVER_STATE);
|
|
20
|
+
/* The tree api object is stable. */
|
|
21
|
+
const api = useMemo(() => {
|
|
22
|
+
return new TreeApi(store.current, treeProps, list, listEl);
|
|
23
|
+
}, []);
|
|
24
|
+
/* Make sure the tree instance stays in sync */
|
|
25
|
+
const updateCount = useRef(0);
|
|
26
|
+
useMemo(() => {
|
|
27
|
+
updateCount.current += 1;
|
|
28
|
+
api.update(treeProps);
|
|
29
|
+
}, [...Object.values(treeProps), state.nodes.open]);
|
|
30
|
+
/* Expose the tree api */
|
|
31
|
+
useImperativeHandle(imperativeHandle, () => api);
|
|
32
|
+
/* Change selection based on props */
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (api.props.selection) {
|
|
35
|
+
api.select(api.props.selection, { focus: false });
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
api.deselectAll();
|
|
39
|
+
}
|
|
40
|
+
}, [api.props.selection]);
|
|
41
|
+
/* Clear visability for filtered nodes */
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!api.props.searchTerm) {
|
|
44
|
+
store.current.dispatch(visibility.clear(true));
|
|
45
|
+
}
|
|
46
|
+
}, [api.props.searchTerm]);
|
|
47
|
+
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 })) }) }) }) }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
3
|
+
import { useDataUpdates, useNodesContext, useTreeApi } from "../context";
|
|
4
|
+
import { useDragHook } from "../dnd/drag-hook";
|
|
5
|
+
import { useDropHook } from "../dnd/drop-hook";
|
|
6
|
+
import { useFreshNode } from "../hooks/use-fresh-node";
|
|
7
|
+
export const RowContainer = React.memo(function RowContainer({ index, style, }) {
|
|
8
|
+
/* When will the <Row> will re-render.
|
|
9
|
+
*
|
|
10
|
+
* The row component is memo'd so it will only render
|
|
11
|
+
* when a new instance of the NodeApi class is passed
|
|
12
|
+
* to it.
|
|
13
|
+
*
|
|
14
|
+
* The TreeApi instance is stable. It does not
|
|
15
|
+
* change when the internal state changes.
|
|
16
|
+
*
|
|
17
|
+
* The TreeApi has all the references to the nodes.
|
|
18
|
+
* We need to clone the nodes when their state
|
|
19
|
+
* changes. The node class contains no state itself,
|
|
20
|
+
* It always checks the tree for state. The tree's
|
|
21
|
+
* state will always be up to date.
|
|
22
|
+
*/
|
|
23
|
+
useDataUpdates(); // Re-render when tree props or visability changes
|
|
24
|
+
const _ = useNodesContext(); // So that we re-render appropriately
|
|
25
|
+
const tree = useTreeApi(); // Tree already has the fresh state
|
|
26
|
+
const node = useFreshNode(index);
|
|
27
|
+
const el = useRef(null);
|
|
28
|
+
const dragRef = useDragHook(node);
|
|
29
|
+
const dropRef = useDropHook(el, node);
|
|
30
|
+
const innerRef = useCallback((n) => {
|
|
31
|
+
el.current = n;
|
|
32
|
+
dropRef(n);
|
|
33
|
+
}, [dropRef]);
|
|
34
|
+
const indent = tree.indent * node.level;
|
|
35
|
+
const nodeStyle = useMemo(() => ({ paddingLeft: indent }), [indent]);
|
|
36
|
+
const rowStyle = useMemo(() => {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
return (Object.assign(Object.assign({}, style), { top: parseFloat(style.top) +
|
|
39
|
+
((_b = (_a = tree.props.padding) !== null && _a !== void 0 ? _a : tree.props.paddingTop) !== null && _b !== void 0 ? _b : 0) }));
|
|
40
|
+
}, [style, tree.props.padding, tree.props.paddingTop]);
|
|
41
|
+
const rowAttrs = {
|
|
42
|
+
role: "treeitem",
|
|
43
|
+
"aria-level": node.level + 1,
|
|
44
|
+
"aria-selected": node.isSelected,
|
|
45
|
+
style: rowStyle,
|
|
46
|
+
tabIndex: -1,
|
|
47
|
+
className: tree.props.rowClassName,
|
|
48
|
+
};
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
var _a;
|
|
51
|
+
if (!node.isEditing && node.isFocused) {
|
|
52
|
+
(_a = el.current) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
|
|
53
|
+
}
|
|
54
|
+
}, [node.isEditing, node.isFocused, el.current]);
|
|
55
|
+
const Node = tree.renderNode;
|
|
56
|
+
const Row = tree.renderRow;
|
|
57
|
+
return (_jsx(Row, { node: node, innerRef: innerRef, attrs: rowAttrs, children: _jsx(Node, { node: node, tree: tree, style: nodeStyle, dragHandle: dragRef }) }));
|
|
58
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function TreeContainer(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useTreeApi } from "../context";
|
|
3
|
+
import { DefaultContainer } from "./default-container";
|
|
4
|
+
export function TreeContainer() {
|
|
5
|
+
const tree = useTreeApi();
|
|
6
|
+
const Container = tree.props.renderContainer || DefaultContainer;
|
|
7
|
+
return (_jsx(_Fragment, { children: _jsx(Container, {}) }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { TreeApi } from "../interfaces/tree-api";
|
|
3
|
+
import { TreeProps } from "../types/tree-props";
|
|
4
|
+
declare function TreeComponent<T>(props: TreeProps<T>, ref: React.Ref<TreeApi<T> | undefined>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare const Tree: <T>(props: TreeProps<T> & {
|
|
6
|
+
ref?: import("react").ForwardedRef<TreeApi<T> | undefined> | undefined;
|
|
7
|
+
}) => ReturnType<typeof TreeComponent>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { TreeProvider } from "./provider";
|
|
4
|
+
import { OuterDrop } from "./outer-drop";
|
|
5
|
+
import { TreeContainer } from "./tree-container";
|
|
6
|
+
import { DragPreviewContainer } from "./drag-preview-container";
|
|
7
|
+
import { useValidatedProps } from "../hooks/use-validated-props";
|
|
8
|
+
function TreeComponent(props, ref) {
|
|
9
|
+
const treeProps = useValidatedProps(props);
|
|
10
|
+
return (_jsxs(TreeProvider, { treeProps: treeProps, imperativeHandle: ref, children: [_jsx(OuterDrop, { children: _jsx(TreeContainer, {}) }), _jsx(DragPreviewContainer, {})] }));
|
|
11
|
+
}
|
|
12
|
+
export const Tree = forwardRef(TreeComponent);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { TreeApi } from "./interfaces/tree-api";
|
|
3
|
+
export declare const TreeApiContext: React.Context<TreeApi<any> | null>;
|
|
4
|
+
export declare function useTreeApi<T>(): TreeApi<T>;
|
|
5
|
+
export declare const NodesContext: React.Context<{
|
|
6
|
+
focus: import("./state/focus-slice").FocusState;
|
|
7
|
+
edit: import("./state/edit-slice").EditState;
|
|
8
|
+
open: import("./state/open-slice").OpenSlice;
|
|
9
|
+
selection: import("./state/selection-slice").SelectionState;
|
|
10
|
+
drag: import("./state/drag-slice").DragSlice;
|
|
11
|
+
} | null>;
|
|
12
|
+
export declare function useNodesContext(): {
|
|
13
|
+
focus: import("./state/focus-slice").FocusState;
|
|
14
|
+
edit: import("./state/edit-slice").EditState;
|
|
15
|
+
open: import("./state/open-slice").OpenSlice;
|
|
16
|
+
selection: import("./state/selection-slice").SelectionState;
|
|
17
|
+
drag: import("./state/drag-slice").DragSlice;
|
|
18
|
+
};
|
|
19
|
+
export declare const DndContext: React.Context<import("./state/dnd-slice").DndState | null>;
|
|
20
|
+
export declare function useDndContext(): import("./state/dnd-slice").DndState;
|
|
21
|
+
export declare const DataUpdatesContext: React.Context<number>;
|
|
22
|
+
export declare function useDataUpdates(): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
export const TreeApiContext = createContext(null);
|
|
3
|
+
export function useTreeApi() {
|
|
4
|
+
const value = useContext(TreeApiContext);
|
|
5
|
+
if (value === null)
|
|
6
|
+
throw new Error("No Tree Api Provided");
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
export const NodesContext = createContext(null);
|
|
10
|
+
export function useNodesContext() {
|
|
11
|
+
const value = useContext(NodesContext);
|
|
12
|
+
if (value === null)
|
|
13
|
+
throw new Error("Provide a NodesContext");
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
export const DndContext = createContext(null);
|
|
17
|
+
export function useDndContext() {
|
|
18
|
+
const value = useContext(DndContext);
|
|
19
|
+
if (value === null)
|
|
20
|
+
throw new Error("Provide a DnDContext");
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
export const DataUpdatesContext = createContext(0);
|
|
24
|
+
export function useDataUpdates() {
|
|
25
|
+
useContext(DataUpdatesContext);
|
|
26
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export function createList(tree) {
|
|
2
|
+
if (tree.isFiltered) {
|
|
3
|
+
return flattenAndFilterTree(tree.root, tree.isMatch.bind(tree));
|
|
4
|
+
}
|
|
5
|
+
else {
|
|
6
|
+
return flattenTree(tree.root);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function flattenTree(root) {
|
|
10
|
+
const list = [];
|
|
11
|
+
function collect(node) {
|
|
12
|
+
var _a;
|
|
13
|
+
if (node.level >= 0) {
|
|
14
|
+
list.push(node);
|
|
15
|
+
}
|
|
16
|
+
if (node.isOpen) {
|
|
17
|
+
(_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(collect);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
collect(root);
|
|
21
|
+
list.forEach(assignRowIndex);
|
|
22
|
+
return list;
|
|
23
|
+
}
|
|
24
|
+
function flattenAndFilterTree(root, isMatch) {
|
|
25
|
+
const matches = {};
|
|
26
|
+
const list = [];
|
|
27
|
+
function markMatch(node) {
|
|
28
|
+
const yes = !node.isRoot && isMatch(node);
|
|
29
|
+
if (yes) {
|
|
30
|
+
matches[node.id] = true;
|
|
31
|
+
let parent = node.parent;
|
|
32
|
+
while (parent) {
|
|
33
|
+
matches[parent.id] = true;
|
|
34
|
+
parent = parent.parent;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (node.children) {
|
|
38
|
+
for (let child of node.children)
|
|
39
|
+
markMatch(child);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function collect(node) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (node.level >= 0 && matches[node.id]) {
|
|
45
|
+
list.push(node);
|
|
46
|
+
}
|
|
47
|
+
if (node.isOpen) {
|
|
48
|
+
(_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(collect);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
markMatch(root);
|
|
52
|
+
collect(root);
|
|
53
|
+
list.forEach(assignRowIndex);
|
|
54
|
+
return list;
|
|
55
|
+
}
|
|
56
|
+
function assignRowIndex(node, index) {
|
|
57
|
+
node.rowIndex = index;
|
|
58
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NodeApi } from "../interfaces/node-api";
|
|
2
|
+
export const ROOT_ID = "__REACT_ARBORIST_INTERNAL_ROOT__";
|
|
3
|
+
export function createRoot(tree) {
|
|
4
|
+
var _a;
|
|
5
|
+
function visitSelfAndChildren(data, level, parent) {
|
|
6
|
+
const id = tree.accessId(data);
|
|
7
|
+
const node = new NodeApi({
|
|
8
|
+
tree,
|
|
9
|
+
data,
|
|
10
|
+
level,
|
|
11
|
+
parent,
|
|
12
|
+
id,
|
|
13
|
+
children: null,
|
|
14
|
+
isDraggable: tree.isDraggable(data),
|
|
15
|
+
rowIndex: null,
|
|
16
|
+
});
|
|
17
|
+
const children = tree.accessChildren(data);
|
|
18
|
+
if (children) {
|
|
19
|
+
node.children = children.map((child) => visitSelfAndChildren(child, level + 1, node));
|
|
20
|
+
}
|
|
21
|
+
return node;
|
|
22
|
+
}
|
|
23
|
+
const root = new NodeApi({
|
|
24
|
+
tree,
|
|
25
|
+
id: ROOT_ID,
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
data: { id: ROOT_ID },
|
|
28
|
+
level: -1,
|
|
29
|
+
parent: null,
|
|
30
|
+
children: null,
|
|
31
|
+
isDraggable: true,
|
|
32
|
+
rowIndex: null,
|
|
33
|
+
});
|
|
34
|
+
const data = (_a = tree.props.data) !== null && _a !== void 0 ? _a : [];
|
|
35
|
+
root.children = data.map((child) => {
|
|
36
|
+
return visitSelfAndChildren(child, 0, root);
|
|
37
|
+
});
|
|
38
|
+
return root;
|
|
39
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// A function that turns a string of text into a tree
|
|
2
|
+
// Each line is a node
|
|
3
|
+
// The number of spaces at the beginning indicate the level
|
|
4
|
+
export function makeTree(string) {
|
|
5
|
+
const root = { id: "ROOT", name: "ROOT", isOpen: true };
|
|
6
|
+
let prevNode = root;
|
|
7
|
+
let prevLevel = -1;
|
|
8
|
+
let id = 1;
|
|
9
|
+
string.split("\n").forEach((line) => {
|
|
10
|
+
const name = line.trimStart();
|
|
11
|
+
const level = line.length - name.length;
|
|
12
|
+
const diff = level - prevLevel;
|
|
13
|
+
const node = { id: (id++).toString(), name, isOpen: false };
|
|
14
|
+
if (diff === 1) {
|
|
15
|
+
// First child
|
|
16
|
+
//@ts-ignore
|
|
17
|
+
node.parent = prevNode;
|
|
18
|
+
//@ts-ignore
|
|
19
|
+
prevNode.children = [node];
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
// Find the parent and go up
|
|
23
|
+
//@ts-ignore
|
|
24
|
+
let parent = prevNode.parent;
|
|
25
|
+
for (let i = diff; i < 0; i++) {
|
|
26
|
+
parent = parent.parent;
|
|
27
|
+
}
|
|
28
|
+
//@ts-ignore
|
|
29
|
+
node.parent = parent;
|
|
30
|
+
parent.children.push(node);
|
|
31
|
+
}
|
|
32
|
+
prevNode = node;
|
|
33
|
+
prevLevel = level;
|
|
34
|
+
});
|
|
35
|
+
return root;
|
|
36
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
type SimpleData = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
children?: SimpleData[];
|
|
5
|
+
};
|
|
6
|
+
export declare class SimpleTree<T extends SimpleData> {
|
|
7
|
+
root: SimpleNode<T>;
|
|
8
|
+
constructor(data: T[]);
|
|
9
|
+
get data(): T[];
|
|
10
|
+
create(args: {
|
|
11
|
+
parentId: string | null;
|
|
12
|
+
index: number;
|
|
13
|
+
data: T;
|
|
14
|
+
}): null | undefined;
|
|
15
|
+
move(args: {
|
|
16
|
+
id: string;
|
|
17
|
+
parentId: string | null;
|
|
18
|
+
index: number;
|
|
19
|
+
}): void;
|
|
20
|
+
update(args: {
|
|
21
|
+
id: string;
|
|
22
|
+
changes: Partial<T>;
|
|
23
|
+
}): void;
|
|
24
|
+
drop(args: {
|
|
25
|
+
id: string;
|
|
26
|
+
}): void;
|
|
27
|
+
find(id: string, node?: SimpleNode<T>): SimpleNode<T> | null;
|
|
28
|
+
}
|
|
29
|
+
declare class SimpleNode<T extends SimpleData> {
|
|
30
|
+
data: T;
|
|
31
|
+
parent: SimpleNode<T> | null;
|
|
32
|
+
id: string;
|
|
33
|
+
children?: SimpleNode<T>[];
|
|
34
|
+
constructor(data: T, parent: SimpleNode<T> | null);
|
|
35
|
+
hasParent(): this is this & {
|
|
36
|
+
parent: SimpleNode<T>;
|
|
37
|
+
};
|
|
38
|
+
get childIndex(): number;
|
|
39
|
+
addChild(data: T, index: number): void;
|
|
40
|
+
removeChild(index: number): void;
|
|
41
|
+
update(changes: Partial<T>): void;
|
|
42
|
+
drop(): void;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export class SimpleTree {
|
|
2
|
+
constructor(data) {
|
|
3
|
+
this.root = createRoot(data);
|
|
4
|
+
}
|
|
5
|
+
get data() {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
return (_b = (_a = this.root.children) === null || _a === void 0 ? void 0 : _a.map((node) => node.data)) !== null && _b !== void 0 ? _b : [];
|
|
8
|
+
}
|
|
9
|
+
create(args) {
|
|
10
|
+
const parent = args.parentId ? this.find(args.parentId) : this.root;
|
|
11
|
+
if (!parent)
|
|
12
|
+
return null;
|
|
13
|
+
parent.addChild(args.data, args.index);
|
|
14
|
+
}
|
|
15
|
+
move(args) {
|
|
16
|
+
const src = this.find(args.id);
|
|
17
|
+
const parent = args.parentId ? this.find(args.parentId) : this.root;
|
|
18
|
+
if (!src || !parent)
|
|
19
|
+
return;
|
|
20
|
+
parent.addChild(src.data, args.index);
|
|
21
|
+
src.drop();
|
|
22
|
+
}
|
|
23
|
+
update(args) {
|
|
24
|
+
const node = this.find(args.id);
|
|
25
|
+
if (node)
|
|
26
|
+
node.update(args.changes);
|
|
27
|
+
}
|
|
28
|
+
drop(args) {
|
|
29
|
+
const node = this.find(args.id);
|
|
30
|
+
if (node)
|
|
31
|
+
node.drop();
|
|
32
|
+
}
|
|
33
|
+
find(id, node = this.root) {
|
|
34
|
+
if (!node)
|
|
35
|
+
return null;
|
|
36
|
+
if (node.id === id)
|
|
37
|
+
return node;
|
|
38
|
+
if (node.children) {
|
|
39
|
+
for (let child of node.children) {
|
|
40
|
+
const found = this.find(id, child);
|
|
41
|
+
if (found)
|
|
42
|
+
return found;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function createRoot(data) {
|
|
50
|
+
const root = new SimpleNode({ id: "ROOT" }, null);
|
|
51
|
+
root.children = data.map((d) => createNode(d, root));
|
|
52
|
+
return root;
|
|
53
|
+
}
|
|
54
|
+
function createNode(data, parent) {
|
|
55
|
+
const node = new SimpleNode(data, parent);
|
|
56
|
+
if (data.children)
|
|
57
|
+
node.children = data.children.map((d) => createNode(d, node));
|
|
58
|
+
return node;
|
|
59
|
+
}
|
|
60
|
+
class SimpleNode {
|
|
61
|
+
constructor(data, parent) {
|
|
62
|
+
this.data = data;
|
|
63
|
+
this.parent = parent;
|
|
64
|
+
this.id = data.id;
|
|
65
|
+
}
|
|
66
|
+
hasParent() {
|
|
67
|
+
return !!this.parent;
|
|
68
|
+
}
|
|
69
|
+
get childIndex() {
|
|
70
|
+
return this.hasParent() ? this.parent.children.indexOf(this) : -1;
|
|
71
|
+
}
|
|
72
|
+
addChild(data, index) {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
const node = createNode(data, this);
|
|
75
|
+
this.children = (_a = this.children) !== null && _a !== void 0 ? _a : [];
|
|
76
|
+
this.children.splice(index, 0, node);
|
|
77
|
+
this.data.children = (_b = this.data.children) !== null && _b !== void 0 ? _b : [];
|
|
78
|
+
this.data.children.splice(index, 0, data);
|
|
79
|
+
}
|
|
80
|
+
removeChild(index) {
|
|
81
|
+
var _a, _b;
|
|
82
|
+
(_a = this.children) === null || _a === void 0 ? void 0 : _a.splice(index, 1);
|
|
83
|
+
(_b = this.data.children) === null || _b === void 0 ? void 0 : _b.splice(index, 1);
|
|
84
|
+
}
|
|
85
|
+
update(changes) {
|
|
86
|
+
if (this.hasParent()) {
|
|
87
|
+
const i = this.childIndex;
|
|
88
|
+
this.parent.addChild(Object.assign(Object.assign({}, this.data), changes), i);
|
|
89
|
+
this.drop();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
drop() {
|
|
93
|
+
if (this.hasParent())
|
|
94
|
+
this.parent.removeChild(this.childIndex);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { XYCoord } from "react-dnd";
|
|
2
|
+
import { NodeApi } from "../interfaces/node-api";
|
|
3
|
+
import { DropResult } from "./drop-hook";
|
|
4
|
+
type Args = {
|
|
5
|
+
element: HTMLElement;
|
|
6
|
+
offset: XYCoord;
|
|
7
|
+
indent: number;
|
|
8
|
+
node: NodeApi | null;
|
|
9
|
+
prevNode: NodeApi | null;
|
|
10
|
+
nextNode: NodeApi | null;
|
|
11
|
+
};
|
|
12
|
+
export type ComputedDrop = {
|
|
13
|
+
drop: DropResult | null;
|
|
14
|
+
cursor: Cursor | null;
|
|
15
|
+
};
|
|
16
|
+
declare function lineCursor(index: number, level: number): {
|
|
17
|
+
type: "line";
|
|
18
|
+
index: number;
|
|
19
|
+
level: number;
|
|
20
|
+
};
|
|
21
|
+
declare function noCursor(): {
|
|
22
|
+
type: "none";
|
|
23
|
+
};
|
|
24
|
+
declare function highlightCursor(id: string): {
|
|
25
|
+
type: "highlight";
|
|
26
|
+
id: string;
|
|
27
|
+
};
|
|
28
|
+
export type LineCursor = ReturnType<typeof lineCursor>;
|
|
29
|
+
export type NoCursor = ReturnType<typeof noCursor>;
|
|
30
|
+
export type HighlightCursor = ReturnType<typeof highlightCursor>;
|
|
31
|
+
export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
32
|
+
/**
|
|
33
|
+
* This is the most complex, tricky function in the whole repo.
|
|
34
|
+
* It could be simplified and made more understandable.
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeDrop(args: Args): ComputedDrop;
|
|
37
|
+
export {};
|