react-arborist 3.3.2-0 → 3.4.1
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/README.md +16 -0
- package/dist/main/components/cursor.js +1 -2
- package/dist/main/components/default-container.js +1 -2
- package/dist/main/components/default-drag-preview.js +1 -2
- package/dist/main/components/default-node.js +1 -2
- package/dist/main/components/default-row.js +1 -2
- package/dist/main/components/drag-preview-container.js +1 -2
- package/dist/main/components/list-outer-element.d.ts +0 -1
- package/dist/main/components/outer-drop.js +1 -2
- package/dist/main/components/provider.js +1 -2
- package/dist/main/components/tree-container.js +1 -2
- package/dist/main/components/tree.d.ts +1 -2
- package/dist/main/context.js +5 -5
- package/dist/main/data/create-list.js +1 -2
- package/dist/main/data/create-root.js +2 -2
- package/dist/main/data/make-tree.js +1 -2
- package/dist/main/dnd/compute-drop.d.ts +0 -1
- package/dist/main/dnd/compute-drop.js +38 -25
- package/dist/main/dnd/drag-hook.js +2 -3
- package/dist/main/dnd/drop-hook.js +1 -2
- package/dist/main/dnd/measure-hover.js +1 -2
- package/dist/main/dnd/outer-drop-hook.js +1 -2
- package/dist/main/hooks/use-fresh-node.js +1 -2
- package/dist/main/hooks/use-simple-tree.js +1 -2
- package/dist/main/hooks/use-validated-props.js +1 -2
- package/dist/main/interfaces/tree-api.d.ts +4 -4
- package/dist/main/interfaces/tree-api.js +5 -7
- package/dist/main/state/dnd-slice.js +2 -2
- package/dist/main/state/drag-slice.js +1 -2
- package/dist/main/state/edit-slice.js +2 -3
- package/dist/main/state/focus-slice.js +3 -4
- package/dist/main/state/open-slice.js +2 -2
- package/dist/main/state/root-reducer.d.ts +4 -4
- package/dist/main/state/selection-slice.js +2 -2
- package/dist/main/utils.d.ts +1 -0
- package/dist/main/utils.js +22 -17
- package/dist/module/components/list-outer-element.d.ts +0 -1
- package/dist/module/components/tree.d.ts +1 -2
- package/dist/module/dnd/compute-drop.d.ts +0 -1
- package/dist/module/dnd/compute-drop.js +38 -24
- package/dist/module/dnd/drag-hook.js +1 -1
- package/dist/module/interfaces/tree-api.d.ts +4 -4
- package/dist/module/interfaces/tree-api.js +5 -7
- package/dist/module/state/root-reducer.d.ts +4 -4
- package/dist/module/utils.d.ts +1 -0
- package/dist/module/utils.js +4 -0
- package/package.json +3 -4
- package/src/dnd/compute-drop.ts +46 -29
- package/src/dnd/drag-hook.ts +1 -1
- package/src/interfaces/tree-api.ts +2 -2
- package/src/utils.ts +4 -0
package/README.md
CHANGED
|
@@ -68,6 +68,8 @@ const data = [
|
|
|
68
68
|
Use all the defaults. The _initialData_ prop makes the tree an uncontrolled component. Create, move, rename, and delete will be handled internally.
|
|
69
69
|
|
|
70
70
|
```jsx
|
|
71
|
+
import { Tree } from 'react-arborist';
|
|
72
|
+
|
|
71
73
|
function App() {
|
|
72
74
|
return <Tree initialData={data} />;
|
|
73
75
|
}
|
|
@@ -241,6 +243,20 @@ function App() {
|
|
|
241
243
|
}
|
|
242
244
|
```
|
|
243
245
|
|
|
246
|
+
### Dynamic sizing
|
|
247
|
+
|
|
248
|
+
You can add a ref to it with this package [ZeeCoder/use-resize-observer](https://github.com/ZeeCoder/use-resize-observer)
|
|
249
|
+
|
|
250
|
+
That hook will return the height and width of the parent whenever it changes. You then pass these numbers to the Tree.
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
const { ref, width, height } = useResizeObserver();
|
|
254
|
+
|
|
255
|
+
<div className="parent" ref={ref}>
|
|
256
|
+
<Tree height={height} width={width} />
|
|
257
|
+
</div>
|
|
258
|
+
```
|
|
259
|
+
|
|
244
260
|
## API Reference
|
|
245
261
|
|
|
246
262
|
- Components
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Cursor =
|
|
3
|
+
exports.Cursor = Cursor;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const context_1 = require("../context");
|
|
6
6
|
function Cursor() {
|
|
@@ -17,4 +17,3 @@ function Cursor() {
|
|
|
17
17
|
const Cursor = tree.renderCursor;
|
|
18
18
|
return (0, jsx_runtime_1.jsx)(Cursor, { top, left, indent });
|
|
19
19
|
}
|
|
20
|
-
exports.Cursor = Cursor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultContainer =
|
|
3
|
+
exports.DefaultContainer = DefaultContainer;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_window_1 = require("react-window");
|
|
6
6
|
const context_1 = require("../context");
|
|
@@ -235,4 +235,3 @@ function DefaultContainer() {
|
|
|
235
235
|
tree.focus(node.id);
|
|
236
236
|
}, children: (0, jsx_runtime_1.jsx)(react_window_1.FixedSizeList, { className: tree.props.className, outerRef: tree.listEl, itemCount: tree.visibleNodes.length, height: tree.height, width: tree.width, itemSize: tree.rowHeight, overscanCount: tree.overscanCount, itemKey: (index) => { var _a; return ((_a = tree.visibleNodes[index]) === null || _a === void 0 ? void 0 : _a.id) || index; }, outerElementType: list_outer_element_1.ListOuterElement, innerElementType: list_inner_element_1.ListInnerElement, onScroll: tree.props.onScroll, onItemsRendered: tree.onItemsRendered.bind(tree), ref: tree.list, children: row_container_1.RowContainer }) }));
|
|
237
237
|
}
|
|
238
|
-
exports.DefaultContainer = DefaultContainer;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultDragPreview =
|
|
3
|
+
exports.DefaultDragPreview = DefaultDragPreview;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const context_1 = require("../context");
|
|
@@ -28,7 +28,6 @@ const getCountStyle = (offset) => {
|
|
|
28
28
|
function DefaultDragPreview({ offset, mouse, id, dragIds, isDragging, }) {
|
|
29
29
|
return ((0, jsx_runtime_1.jsxs)(Overlay, { isDragging: isDragging, children: [(0, jsx_runtime_1.jsx)(Position, { offset: offset, children: (0, jsx_runtime_1.jsx)(PreviewNode, { id: id, dragIds: dragIds }) }), (0, jsx_runtime_1.jsx)(Count, { mouse: mouse, count: dragIds.length })] }));
|
|
30
30
|
}
|
|
31
|
-
exports.DefaultDragPreview = DefaultDragPreview;
|
|
32
31
|
const Overlay = (0, react_1.memo)(function Overlay(props) {
|
|
33
32
|
if (!props.isDragging)
|
|
34
33
|
return null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultNode =
|
|
3
|
+
exports.DefaultNode = DefaultNode;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
function DefaultNode(props) {
|
|
@@ -9,7 +9,6 @@ function DefaultNode(props) {
|
|
|
9
9
|
props.node.toggle();
|
|
10
10
|
}, children: props.node.isLeaf ? "🌳" : props.node.isOpen ? "🗁" : "🗀" }), " ", props.node.isEditing ? (0, jsx_runtime_1.jsx)(Edit, Object.assign({}, props)) : (0, jsx_runtime_1.jsx)(Show, Object.assign({}, props))] }));
|
|
11
11
|
}
|
|
12
|
-
exports.DefaultNode = DefaultNode;
|
|
13
12
|
function Show(props) {
|
|
14
13
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("span", { children: props.node.data.name }) }));
|
|
15
14
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultRow =
|
|
3
|
+
exports.DefaultRow = DefaultRow;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
function DefaultRow({ node, attrs, innerRef, children, }) {
|
|
6
6
|
return ((0, jsx_runtime_1.jsx)("div", Object.assign({}, attrs, { ref: innerRef, onFocus: (e) => e.stopPropagation(), onClick: node.handleClick, children: children })));
|
|
7
7
|
}
|
|
8
|
-
exports.DefaultRow = DefaultRow;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DragPreviewContainer =
|
|
3
|
+
exports.DragPreviewContainer = DragPreviewContainer;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_dnd_1 = require("react-dnd");
|
|
6
6
|
const context_1 = require("../context");
|
|
@@ -18,4 +18,3 @@ function DragPreviewContainer() {
|
|
|
18
18
|
const DragPreview = tree.props.renderDragPreview || default_drag_preview_1.DefaultDragPreview;
|
|
19
19
|
return ((0, jsx_runtime_1.jsx)(DragPreview, { offset: offset, mouse: mouse, id: (item === null || item === void 0 ? void 0 : item.id) || null, dragIds: (item === null || item === void 0 ? void 0 : item.dragIds) || [], isDragging: isDragging }));
|
|
20
20
|
}
|
|
21
|
-
exports.DragPreviewContainer = DragPreviewContainer;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OuterDrop =
|
|
3
|
+
exports.OuterDrop = OuterDrop;
|
|
4
4
|
const outer_drop_hook_1 = require("../dnd/outer-drop-hook");
|
|
5
5
|
function OuterDrop(props) {
|
|
6
6
|
(0, outer_drop_hook_1.useOuterDrop)();
|
|
7
7
|
return props.children;
|
|
8
8
|
}
|
|
9
|
-
exports.OuterDrop = OuterDrop;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TreeProvider =
|
|
3
|
+
exports.TreeProvider = TreeProvider;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const shim_1 = require("use-sync-external-store/shim");
|
|
@@ -49,4 +49,3 @@ function TreeProvider({ treeProps, imperativeHandle, children, }) {
|
|
|
49
49
|
}, [api.props.searchTerm]);
|
|
50
50
|
return ((0, jsx_runtime_1.jsx)(context_1.TreeApiContext.Provider, { value: api, children: (0, jsx_runtime_1.jsx)(context_1.DataUpdatesContext.Provider, { value: updateCount.current, children: (0, jsx_runtime_1.jsx)(context_1.NodesContext.Provider, { value: state.nodes, children: (0, jsx_runtime_1.jsx)(context_1.DndContext.Provider, { value: state.dnd, children: (0, jsx_runtime_1.jsx)(react_dnd_1.DndProvider, Object.assign({ backend: react_dnd_html5_backend_1.HTML5Backend, options: { rootElement: api.props.dndRootElement || undefined } }, (treeProps.dndManager && { manager: treeProps.dndManager }), { children: children })) }) }) }) }));
|
|
51
51
|
}
|
|
52
|
-
exports.TreeProvider = TreeProvider;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TreeContainer =
|
|
3
|
+
exports.TreeContainer = TreeContainer;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const context_1 = require("../context");
|
|
6
6
|
const default_container_1 = require("./default-container");
|
|
@@ -9,4 +9,3 @@ function TreeContainer() {
|
|
|
9
9
|
const Container = tree.props.renderContainer || default_container_1.DefaultContainer;
|
|
10
10
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Container, {}) }));
|
|
11
11
|
}
|
|
12
|
-
exports.TreeContainer = TreeContainer;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { TreeApi } from "../interfaces/tree-api";
|
|
3
2
|
import { TreeProps } from "../types/tree-props";
|
|
4
3
|
declare function TreeComponent<T>(props: TreeProps<T>, ref: React.Ref<TreeApi<T> | undefined>): import("react/jsx-runtime").JSX.Element;
|
|
5
4
|
export declare const Tree: <T>(props: TreeProps<T> & {
|
|
6
|
-
ref?:
|
|
5
|
+
ref?: React.ForwardedRef<TreeApi<T> | undefined>;
|
|
7
6
|
}) => ReturnType<typeof TreeComponent>;
|
|
8
7
|
export {};
|
package/dist/main/context.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DataUpdatesContext = exports.DndContext = exports.NodesContext = exports.TreeApiContext = void 0;
|
|
4
|
+
exports.useTreeApi = useTreeApi;
|
|
5
|
+
exports.useNodesContext = useNodesContext;
|
|
6
|
+
exports.useDndContext = useDndContext;
|
|
7
|
+
exports.useDataUpdates = useDataUpdates;
|
|
4
8
|
const react_1 = require("react");
|
|
5
9
|
exports.TreeApiContext = (0, react_1.createContext)(null);
|
|
6
10
|
function useTreeApi() {
|
|
@@ -9,7 +13,6 @@ function useTreeApi() {
|
|
|
9
13
|
throw new Error("No Tree Api Provided");
|
|
10
14
|
return value;
|
|
11
15
|
}
|
|
12
|
-
exports.useTreeApi = useTreeApi;
|
|
13
16
|
exports.NodesContext = (0, react_1.createContext)(null);
|
|
14
17
|
function useNodesContext() {
|
|
15
18
|
const value = (0, react_1.useContext)(exports.NodesContext);
|
|
@@ -17,7 +20,6 @@ function useNodesContext() {
|
|
|
17
20
|
throw new Error("Provide a NodesContext");
|
|
18
21
|
return value;
|
|
19
22
|
}
|
|
20
|
-
exports.useNodesContext = useNodesContext;
|
|
21
23
|
exports.DndContext = (0, react_1.createContext)(null);
|
|
22
24
|
function useDndContext() {
|
|
23
25
|
const value = (0, react_1.useContext)(exports.DndContext);
|
|
@@ -25,9 +27,7 @@ function useDndContext() {
|
|
|
25
27
|
throw new Error("Provide a DnDContext");
|
|
26
28
|
return value;
|
|
27
29
|
}
|
|
28
|
-
exports.useDndContext = useDndContext;
|
|
29
30
|
exports.DataUpdatesContext = (0, react_1.createContext)(0);
|
|
30
31
|
function useDataUpdates() {
|
|
31
32
|
(0, react_1.useContext)(exports.DataUpdatesContext);
|
|
32
33
|
}
|
|
33
|
-
exports.useDataUpdates = useDataUpdates;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createList =
|
|
3
|
+
exports.createList = createList;
|
|
4
4
|
function createList(tree) {
|
|
5
5
|
if (tree.isFiltered) {
|
|
6
6
|
return flattenAndFilterTree(tree.root, tree.isMatch.bind(tree));
|
|
@@ -9,7 +9,6 @@ function createList(tree) {
|
|
|
9
9
|
return flattenTree(tree.root);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
exports.createList = createList;
|
|
13
12
|
function flattenTree(root) {
|
|
14
13
|
const list = [];
|
|
15
14
|
function collect(node) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ROOT_ID = void 0;
|
|
4
|
+
exports.createRoot = createRoot;
|
|
4
5
|
const node_api_1 = require("../interfaces/node-api");
|
|
5
6
|
exports.ROOT_ID = "__REACT_ARBORIST_INTERNAL_ROOT__";
|
|
6
7
|
function createRoot(tree) {
|
|
@@ -40,4 +41,3 @@ function createRoot(tree) {
|
|
|
40
41
|
});
|
|
41
42
|
return root;
|
|
42
43
|
}
|
|
43
|
-
exports.createRoot = createRoot;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Each line is a node
|
|
4
4
|
// The number of spaces at the beginning indicate the level
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.makeTree =
|
|
6
|
+
exports.makeTree = makeTree;
|
|
7
7
|
function makeTree(string) {
|
|
8
8
|
const root = { id: "ROOT", name: "ROOT", isOpen: true };
|
|
9
9
|
let prevNode = root;
|
|
@@ -37,4 +37,3 @@ function makeTree(string) {
|
|
|
37
37
|
});
|
|
38
38
|
return root;
|
|
39
39
|
}
|
|
40
|
-
exports.makeTree = makeTree;
|
|
@@ -31,7 +31,6 @@ export type HighlightCursor = ReturnType<typeof highlightCursor>;
|
|
|
31
31
|
export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
32
32
|
/**
|
|
33
33
|
* This is the most complex, tricky function in the whole repo.
|
|
34
|
-
* It could be simplified and made more understandable.
|
|
35
34
|
*/
|
|
36
35
|
export declare function computeDrop(args: Args): ComputedDrop;
|
|
37
36
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.computeDrop =
|
|
3
|
+
exports.computeDrop = computeDrop;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
function measureHover(el, offset) {
|
|
6
6
|
const rect = el.getBoundingClientRect();
|
|
@@ -41,23 +41,6 @@ function getNodesAroundCursor(node, prev, next, hover) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
function getDropLevel(hovering, aboveCursor, belowCursor, indent) {
|
|
45
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
46
|
-
let min, max;
|
|
47
|
-
if (!aboveCursor) {
|
|
48
|
-
max = 0;
|
|
49
|
-
min = 0;
|
|
50
|
-
}
|
|
51
|
-
else if (!belowCursor) {
|
|
52
|
-
max = aboveCursor.level;
|
|
53
|
-
min = 0;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
max = aboveCursor.level;
|
|
57
|
-
min = belowCursor.level;
|
|
58
|
-
}
|
|
59
|
-
return (0, utils_1.bound)(hoverLevel, min, max);
|
|
60
|
-
}
|
|
61
44
|
function dropAt(parentId, index) {
|
|
62
45
|
return { parentId: parentId || null, index };
|
|
63
46
|
}
|
|
@@ -91,11 +74,12 @@ function walkUpFrom(node, level) {
|
|
|
91
74
|
}
|
|
92
75
|
/**
|
|
93
76
|
* This is the most complex, tricky function in the whole repo.
|
|
94
|
-
* It could be simplified and made more understandable.
|
|
95
77
|
*/
|
|
96
78
|
function computeDrop(args) {
|
|
97
79
|
var _a;
|
|
98
80
|
const hover = measureHover(args.element, args.offset);
|
|
81
|
+
const indent = args.indent;
|
|
82
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
99
83
|
const { node, nextNode, prevNode } = args;
|
|
100
84
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
101
85
|
/* Hovering over the middle of a folder */
|
|
@@ -105,25 +89,54 @@ function computeDrop(args) {
|
|
|
105
89
|
cursor: highlightCursor(node.id),
|
|
106
90
|
};
|
|
107
91
|
}
|
|
108
|
-
/*
|
|
92
|
+
/*
|
|
93
|
+
* Now we only need to care about the node above the cursor
|
|
94
|
+
* ----------- -------
|
|
95
|
+
*/
|
|
96
|
+
/* There is no node above the cursor line */
|
|
109
97
|
if (!above) {
|
|
110
98
|
return {
|
|
111
99
|
drop: dropAt((_a = below === null || below === void 0 ? void 0 : below.parent) === null || _a === void 0 ? void 0 : _a.id, 0),
|
|
112
100
|
cursor: lineCursor(0, 0),
|
|
113
101
|
};
|
|
114
102
|
}
|
|
115
|
-
/* The above
|
|
116
|
-
if ((0, utils_1.isItem)(above)
|
|
117
|
-
const level =
|
|
103
|
+
/* The node above the cursor line is an item */
|
|
104
|
+
if ((0, utils_1.isItem)(above)) {
|
|
105
|
+
const level = (0, utils_1.bound)(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
106
|
+
return {
|
|
107
|
+
drop: walkUpFrom(above, level),
|
|
108
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/* The node above the cursor line is a closed folder */
|
|
112
|
+
if ((0, utils_1.isClosed)(above)) {
|
|
113
|
+
const level = (0, utils_1.bound)(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
118
114
|
return {
|
|
119
115
|
drop: walkUpFrom(above, level),
|
|
120
116
|
cursor: lineCursor(above.rowIndex + 1, level),
|
|
121
117
|
};
|
|
122
118
|
}
|
|
123
|
-
/* The above
|
|
119
|
+
/* The node above the cursor line is an open folder with no children */
|
|
120
|
+
if ((0, utils_1.isOpenWithEmptyChildren)(above)) {
|
|
121
|
+
const level = (0, utils_1.bound)(hoverLevel, 0, above.level + 1);
|
|
122
|
+
if (level > above.level) {
|
|
123
|
+
/* Will be the first child of the empty folder */
|
|
124
|
+
return {
|
|
125
|
+
drop: dropAt(above.id, 0),
|
|
126
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
131
|
+
return {
|
|
132
|
+
drop: walkUpFrom(above, level),
|
|
133
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/* The node above the cursor is a an open folder with children */
|
|
124
138
|
return {
|
|
125
139
|
drop: dropAt(above === null || above === void 0 ? void 0 : above.id, 0),
|
|
126
140
|
cursor: lineCursor(above.rowIndex + 1, above.level + 1),
|
|
127
141
|
};
|
|
128
142
|
}
|
|
129
|
-
exports.computeDrop = computeDrop;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useDragHook =
|
|
3
|
+
exports.useDragHook = useDragHook;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const react_dnd_1 = require("react-dnd");
|
|
6
6
|
const react_dnd_html5_backend_1 = require("react-dnd-html5-backend");
|
|
@@ -18,7 +18,7 @@ function useDragHook(node) {
|
|
|
18
18
|
// This is fired once at the begging of a drag operation
|
|
19
19
|
const dragIds = tree.isSelected(node.id) ? Array.from(ids) : [node.id];
|
|
20
20
|
tree.dispatch(dnd_slice_1.actions.dragStart(node.id, dragIds));
|
|
21
|
-
return { id: node.id };
|
|
21
|
+
return { id: node.id, dragIds };
|
|
22
22
|
},
|
|
23
23
|
end: () => {
|
|
24
24
|
tree.hideCursor();
|
|
@@ -43,4 +43,3 @@ function useDragHook(node) {
|
|
|
43
43
|
}, [preview]);
|
|
44
44
|
return ref;
|
|
45
45
|
}
|
|
46
|
-
exports.useDragHook = useDragHook;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useDropHook =
|
|
3
|
+
exports.useDropHook = useDropHook;
|
|
4
4
|
const react_dnd_1 = require("react-dnd");
|
|
5
5
|
const context_1 = require("../context");
|
|
6
6
|
const compute_drop_1 = require("./compute-drop");
|
|
@@ -39,4 +39,3 @@ function useDropHook(el, node) {
|
|
|
39
39
|
}), [node, el.current, tree.props]);
|
|
40
40
|
return dropRef;
|
|
41
41
|
}
|
|
42
|
-
exports.useDropHook = useDropHook;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.measureHover =
|
|
3
|
+
exports.measureHover = measureHover;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
function measureHover(el, offset, indent) {
|
|
6
6
|
const nextEl = el.nextElementSibling;
|
|
@@ -18,4 +18,3 @@ function measureHover(el, offset, indent) {
|
|
|
18
18
|
const level = (0, utils_1.bound)(Math.floor(x / indent), minLevel, maxLevel);
|
|
19
19
|
return { level, inTopHalf, inBottomHalf, inMiddle };
|
|
20
20
|
}
|
|
21
|
-
exports.measureHover = measureHover;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useOuterDrop =
|
|
3
|
+
exports.useOuterDrop = useOuterDrop;
|
|
4
4
|
const react_dnd_1 = require("react-dnd");
|
|
5
5
|
const context_1 = require("../context");
|
|
6
6
|
const compute_drop_1 = require("./compute-drop");
|
|
@@ -42,4 +42,3 @@ function useOuterDrop() {
|
|
|
42
42
|
}), [tree]);
|
|
43
43
|
drop(tree.listEl);
|
|
44
44
|
}
|
|
45
|
-
exports.useOuterDrop = useOuterDrop;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useFreshNode =
|
|
3
|
+
exports.useFreshNode = useFreshNode;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const context_1 = require("../context");
|
|
6
6
|
function useFreshNode(index) {
|
|
@@ -15,4 +15,3 @@ function useFreshNode(index) {
|
|
|
15
15
|
// Return a fresh instance if the state values change
|
|
16
16
|
}, [...Object.values(original.state), original]);
|
|
17
17
|
}
|
|
18
|
-
exports.useFreshNode = useFreshNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useSimpleTree =
|
|
3
|
+
exports.useSimpleTree = useSimpleTree;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const simple_tree_1 = require("../data/simple-tree");
|
|
6
6
|
let nextId = 0;
|
|
@@ -32,4 +32,3 @@ function useSimpleTree(initialData) {
|
|
|
32
32
|
const controller = { onMove, onRename, onCreate, onDelete };
|
|
33
33
|
return [data, controller];
|
|
34
34
|
}
|
|
35
|
-
exports.useSimpleTree = useSimpleTree;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useValidatedProps =
|
|
3
|
+
exports.useValidatedProps = useValidatedProps;
|
|
4
4
|
const use_simple_tree_1 = require("./use-simple-tree");
|
|
5
5
|
function useValidatedProps(props) {
|
|
6
6
|
if (props.initialData && props.data) {
|
|
@@ -26,4 +26,3 @@ Use the data prop if you want to provide your own handlers.`);
|
|
|
26
26
|
return props;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
exports.useValidatedProps = useValidatedProps;
|
|
@@ -62,11 +62,11 @@ export declare class TreeApi<T> {
|
|
|
62
62
|
type: "SELECTION_ONLY";
|
|
63
63
|
id: string;
|
|
64
64
|
};
|
|
65
|
-
add: (id: string |
|
|
65
|
+
add: (id: string | string[] | IdObj | IdObj[]) => {
|
|
66
66
|
type: "SELECTION_ADD";
|
|
67
67
|
ids: string[];
|
|
68
68
|
};
|
|
69
|
-
remove: (id: string |
|
|
69
|
+
remove: (id: string | string[] | IdObj | IdObj[]) => {
|
|
70
70
|
type: "SELECTION_REMOVE";
|
|
71
71
|
ids: string[];
|
|
72
72
|
};
|
|
@@ -80,11 +80,11 @@ export declare class TreeApi<T> {
|
|
|
80
80
|
mostRecent: string | null;
|
|
81
81
|
type: "SELECTION_SET";
|
|
82
82
|
};
|
|
83
|
-
mostRecent: (id: string |
|
|
83
|
+
mostRecent: (id: string | null | IdObj) => {
|
|
84
84
|
type: "SELECTION_MOST_RECENT";
|
|
85
85
|
id: string | null;
|
|
86
86
|
};
|
|
87
|
-
anchor: (id: string |
|
|
87
|
+
anchor: (id: string | null | IdObj) => {
|
|
88
88
|
type: "SELECTION_ANCHOR";
|
|
89
89
|
id: string | null;
|
|
90
90
|
};
|
|
@@ -192,9 +192,9 @@ class TreeApi {
|
|
|
192
192
|
createLeaf() {
|
|
193
193
|
return this.create({ type: "leaf" });
|
|
194
194
|
}
|
|
195
|
-
create(
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
create() {
|
|
196
|
+
return __awaiter(this, arguments, void 0, function* (opts = {}) {
|
|
197
|
+
var _a, _b;
|
|
198
198
|
const parentId = opts.parentId === undefined
|
|
199
199
|
? utils.getInsertParentId(this)
|
|
200
200
|
: opts.parentId;
|
|
@@ -588,14 +588,12 @@ class TreeApi {
|
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
isEditable(data) {
|
|
591
|
-
var _a;
|
|
592
591
|
const check = this.props.disableEdit || (() => false);
|
|
593
|
-
return
|
|
592
|
+
return !utils.access(data, check);
|
|
594
593
|
}
|
|
595
594
|
isDraggable(data) {
|
|
596
|
-
var _a;
|
|
597
595
|
const check = this.props.disableDrag || (() => false);
|
|
598
|
-
return
|
|
596
|
+
return !utils.access(data, check);
|
|
599
597
|
}
|
|
600
598
|
isDragging(node) {
|
|
601
599
|
const id = identifyNull(node);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.actions = void 0;
|
|
4
|
+
exports.reducer = reducer;
|
|
4
5
|
const initial_1 = require("./initial");
|
|
5
6
|
/* Actions */
|
|
6
7
|
exports.actions = {
|
|
@@ -32,4 +33,3 @@ function reducer(state = (0, initial_1.initialState)()["dnd"], action) {
|
|
|
32
33
|
return state;
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
exports.reducer = reducer;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.reducer =
|
|
3
|
+
exports.reducer = reducer;
|
|
4
4
|
const initial_1 = require("./initial");
|
|
5
5
|
/* Reducer */
|
|
6
6
|
function reducer(state = (0, initial_1.initialState)().nodes.drag, action) {
|
|
@@ -21,4 +21,3 @@ function reducer(state = (0, initial_1.initialState)().nodes.drag, action) {
|
|
|
21
21
|
return state;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
exports.reducer = reducer;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.edit = edit;
|
|
4
|
+
exports.reducer = reducer;
|
|
4
5
|
/* Actions */
|
|
5
6
|
function edit(id) {
|
|
6
7
|
return { type: "EDIT", id };
|
|
7
8
|
}
|
|
8
|
-
exports.edit = edit;
|
|
9
9
|
/* Reducer */
|
|
10
10
|
function reducer(state = { id: null }, action) {
|
|
11
11
|
if (action.type === "EDIT") {
|
|
@@ -15,4 +15,3 @@ function reducer(state = { id: null }, action) {
|
|
|
15
15
|
return state;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
exports.reducer = reducer;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* Types */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.focus = focus;
|
|
5
|
+
exports.treeBlur = treeBlur;
|
|
6
|
+
exports.reducer = reducer;
|
|
5
7
|
/* Actions */
|
|
6
8
|
function focus(id) {
|
|
7
9
|
return { type: "FOCUS", id };
|
|
8
10
|
}
|
|
9
|
-
exports.focus = focus;
|
|
10
11
|
function treeBlur() {
|
|
11
12
|
return { type: "TREE_BLUR" };
|
|
12
13
|
}
|
|
13
|
-
exports.treeBlur = treeBlur;
|
|
14
14
|
/* Reducer */
|
|
15
15
|
function reducer(state = { id: null, treeFocused: false }, action) {
|
|
16
16
|
if (action.type === "FOCUS") {
|
|
@@ -23,4 +23,3 @@ function reducer(state = { id: null, treeFocused: false }, action) {
|
|
|
23
23
|
return state;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
exports.reducer = reducer;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.actions = void 0;
|
|
4
|
+
exports.reducer = reducer;
|
|
4
5
|
/* Actions */
|
|
5
6
|
exports.actions = {
|
|
6
7
|
open(id, filtered) {
|
|
@@ -45,4 +46,3 @@ function reducer(state = { filtered: {}, unfiltered: {} }, action) {
|
|
|
45
46
|
return Object.assign(Object.assign({}, state), { unfiltered: openMapReducer(state.unfiltered, action) });
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
exports.reducer = reducer;
|
|
@@ -44,11 +44,11 @@ export declare const rootReducer: import("redux").Reducer<{
|
|
|
44
44
|
type: "SELECTION_ONLY";
|
|
45
45
|
id: string;
|
|
46
46
|
};
|
|
47
|
-
add: (id: string | import("../types/utils").IdObj |
|
|
47
|
+
add: (id: string | string[] | import("../types/utils").IdObj | import("../types/utils").IdObj[]) => {
|
|
48
48
|
type: "SELECTION_ADD";
|
|
49
49
|
ids: string[];
|
|
50
50
|
};
|
|
51
|
-
remove: (id: string | import("../types/utils").IdObj |
|
|
51
|
+
remove: (id: string | string[] | import("../types/utils").IdObj | import("../types/utils").IdObj[]) => {
|
|
52
52
|
type: "SELECTION_REMOVE";
|
|
53
53
|
ids: string[];
|
|
54
54
|
};
|
|
@@ -62,11 +62,11 @@ export declare const rootReducer: import("redux").Reducer<{
|
|
|
62
62
|
mostRecent: string | null;
|
|
63
63
|
type: "SELECTION_SET";
|
|
64
64
|
};
|
|
65
|
-
mostRecent: (id: string | import("../types/utils").IdObj
|
|
65
|
+
mostRecent: (id: string | null | import("../types/utils").IdObj) => {
|
|
66
66
|
type: "SELECTION_MOST_RECENT";
|
|
67
67
|
id: string | null;
|
|
68
68
|
};
|
|
69
|
-
anchor: (id: string | import("../types/utils").IdObj
|
|
69
|
+
anchor: (id: string | null | import("../types/utils").IdObj) => {
|
|
70
70
|
type: "SELECTION_ANCHOR";
|
|
71
71
|
id: string | null;
|
|
72
72
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.actions = void 0;
|
|
4
|
+
exports.reducer = reducer;
|
|
4
5
|
const utils_1 = require("../utils");
|
|
5
6
|
const initial_1 = require("./initial");
|
|
6
7
|
/* Actions */
|
|
@@ -56,4 +57,3 @@ function reducer(state = (0, initial_1.initialState)()["nodes"]["selection"], ac
|
|
|
56
57
|
return state;
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
exports.reducer = reducer;
|
package/dist/main/utils.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { IdObj } from "./types/utils";
|
|
|
4
4
|
export declare function bound(n: number, min: number, max: number): number;
|
|
5
5
|
export declare function isItem(node: NodeApi<any> | null): boolean | null;
|
|
6
6
|
export declare function isClosed(node: NodeApi<any> | null): boolean | null;
|
|
7
|
+
export declare function isOpenWithEmptyChildren(node: NodeApi<any> | null): boolean | null;
|
|
7
8
|
/**
|
|
8
9
|
* Is first param a descendant of the second param
|
|
9
10
|
*/
|
package/dist/main/utils.js
CHANGED
|
@@ -1,18 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.indexOf = exports.isDescendant = void 0;
|
|
4
|
+
exports.bound = bound;
|
|
5
|
+
exports.isItem = isItem;
|
|
6
|
+
exports.isClosed = isClosed;
|
|
7
|
+
exports.isOpenWithEmptyChildren = isOpenWithEmptyChildren;
|
|
8
|
+
exports.noop = noop;
|
|
9
|
+
exports.dfs = dfs;
|
|
10
|
+
exports.walk = walk;
|
|
11
|
+
exports.focusNextElement = focusNextElement;
|
|
12
|
+
exports.focusPrevElement = focusPrevElement;
|
|
13
|
+
exports.access = access;
|
|
14
|
+
exports.identifyNull = identifyNull;
|
|
15
|
+
exports.identify = identify;
|
|
16
|
+
exports.mergeRefs = mergeRefs;
|
|
17
|
+
exports.safeRun = safeRun;
|
|
18
|
+
exports.waitFor = waitFor;
|
|
19
|
+
exports.getInsertIndex = getInsertIndex;
|
|
20
|
+
exports.getInsertParentId = getInsertParentId;
|
|
4
21
|
function bound(n, min, max) {
|
|
5
22
|
return Math.max(Math.min(n, max), min);
|
|
6
23
|
}
|
|
7
|
-
exports.bound = bound;
|
|
8
24
|
function isItem(node) {
|
|
9
25
|
return node && node.isLeaf;
|
|
10
26
|
}
|
|
11
|
-
exports.isItem = isItem;
|
|
12
27
|
function isClosed(node) {
|
|
13
28
|
return node && node.isInternal && !node.isOpen;
|
|
14
29
|
}
|
|
15
|
-
|
|
30
|
+
function isOpenWithEmptyChildren(node) {
|
|
31
|
+
var _a;
|
|
32
|
+
return node && node.isOpen && !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length);
|
|
33
|
+
}
|
|
16
34
|
/**
|
|
17
35
|
* Is first param a descendant of the second param
|
|
18
36
|
*/
|
|
@@ -33,7 +51,6 @@ const indexOf = (node) => {
|
|
|
33
51
|
};
|
|
34
52
|
exports.indexOf = indexOf;
|
|
35
53
|
function noop() { }
|
|
36
|
-
exports.noop = noop;
|
|
37
54
|
function dfs(node, id) {
|
|
38
55
|
if (!node)
|
|
39
56
|
return null;
|
|
@@ -48,7 +65,6 @@ function dfs(node, id) {
|
|
|
48
65
|
}
|
|
49
66
|
return null;
|
|
50
67
|
}
|
|
51
|
-
exports.dfs = dfs;
|
|
52
68
|
function walk(node, fn) {
|
|
53
69
|
fn(node);
|
|
54
70
|
if (node.children) {
|
|
@@ -57,7 +73,6 @@ function walk(node, fn) {
|
|
|
57
73
|
}
|
|
58
74
|
}
|
|
59
75
|
}
|
|
60
|
-
exports.walk = walk;
|
|
61
76
|
function focusNextElement(target) {
|
|
62
77
|
const elements = getFocusable(target);
|
|
63
78
|
let next;
|
|
@@ -71,7 +86,6 @@ function focusNextElement(target) {
|
|
|
71
86
|
// @ts-ignore ??
|
|
72
87
|
next === null || next === void 0 ? void 0 : next.focus();
|
|
73
88
|
}
|
|
74
|
-
exports.focusNextElement = focusNextElement;
|
|
75
89
|
function focusPrevElement(target) {
|
|
76
90
|
const elements = getFocusable(target);
|
|
77
91
|
let next;
|
|
@@ -85,7 +99,6 @@ function focusPrevElement(target) {
|
|
|
85
99
|
// @ts-ignore
|
|
86
100
|
next === null || next === void 0 ? void 0 : next.focus();
|
|
87
101
|
}
|
|
88
|
-
exports.focusPrevElement = focusPrevElement;
|
|
89
102
|
function nextItem(list, index) {
|
|
90
103
|
if (index + 1 < list.length) {
|
|
91
104
|
return list[index + 1];
|
|
@@ -112,18 +125,15 @@ function access(obj, accessor) {
|
|
|
112
125
|
return obj[accessor];
|
|
113
126
|
return accessor(obj);
|
|
114
127
|
}
|
|
115
|
-
exports.access = access;
|
|
116
128
|
function identifyNull(obj) {
|
|
117
129
|
if (obj === null)
|
|
118
130
|
return null;
|
|
119
131
|
else
|
|
120
132
|
return identify(obj);
|
|
121
133
|
}
|
|
122
|
-
exports.identifyNull = identifyNull;
|
|
123
134
|
function identify(obj) {
|
|
124
135
|
return typeof obj === "string" ? obj : obj.id;
|
|
125
136
|
}
|
|
126
|
-
exports.identify = identify;
|
|
127
137
|
function mergeRefs(...refs) {
|
|
128
138
|
return (instance) => {
|
|
129
139
|
refs.forEach((ref) => {
|
|
@@ -136,12 +146,10 @@ function mergeRefs(...refs) {
|
|
|
136
146
|
});
|
|
137
147
|
};
|
|
138
148
|
}
|
|
139
|
-
exports.mergeRefs = mergeRefs;
|
|
140
149
|
function safeRun(fn, ...args) {
|
|
141
150
|
if (fn)
|
|
142
151
|
return fn(...args);
|
|
143
152
|
}
|
|
144
|
-
exports.safeRun = safeRun;
|
|
145
153
|
function waitFor(fn) {
|
|
146
154
|
return new Promise((resolve, reject) => {
|
|
147
155
|
let tries = 0;
|
|
@@ -157,7 +165,6 @@ function waitFor(fn) {
|
|
|
157
165
|
check();
|
|
158
166
|
});
|
|
159
167
|
}
|
|
160
|
-
exports.waitFor = waitFor;
|
|
161
168
|
function getInsertIndex(tree) {
|
|
162
169
|
var _a, _b;
|
|
163
170
|
const focus = tree.focusedNode;
|
|
@@ -169,7 +176,6 @@ function getInsertIndex(tree) {
|
|
|
169
176
|
return focus.childIndex + 1;
|
|
170
177
|
return 0;
|
|
171
178
|
}
|
|
172
|
-
exports.getInsertIndex = getInsertIndex;
|
|
173
179
|
function getInsertParentId(tree) {
|
|
174
180
|
const focus = tree.focusedNode;
|
|
175
181
|
if (!focus)
|
|
@@ -180,4 +186,3 @@ function getInsertParentId(tree) {
|
|
|
180
186
|
return focus.parent.id;
|
|
181
187
|
return null;
|
|
182
188
|
}
|
|
183
|
-
exports.getInsertParentId = getInsertParentId;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { TreeApi } from "../interfaces/tree-api";
|
|
3
2
|
import { TreeProps } from "../types/tree-props";
|
|
4
3
|
declare function TreeComponent<T>(props: TreeProps<T>, ref: React.Ref<TreeApi<T> | undefined>): import("react/jsx-runtime").JSX.Element;
|
|
5
4
|
export declare const Tree: <T>(props: TreeProps<T> & {
|
|
6
|
-
ref?:
|
|
5
|
+
ref?: React.ForwardedRef<TreeApi<T> | undefined>;
|
|
7
6
|
}) => ReturnType<typeof TreeComponent>;
|
|
8
7
|
export {};
|
|
@@ -31,7 +31,6 @@ export type HighlightCursor = ReturnType<typeof highlightCursor>;
|
|
|
31
31
|
export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
32
32
|
/**
|
|
33
33
|
* This is the most complex, tricky function in the whole repo.
|
|
34
|
-
* It could be simplified and made more understandable.
|
|
35
34
|
*/
|
|
36
35
|
export declare function computeDrop(args: Args): ComputedDrop;
|
|
37
36
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bound, indexOf, isClosed, isItem } from "../utils";
|
|
1
|
+
import { bound, indexOf, isClosed, isItem, isOpenWithEmptyChildren, } from "../utils";
|
|
2
2
|
function measureHover(el, offset) {
|
|
3
3
|
const rect = el.getBoundingClientRect();
|
|
4
4
|
const x = offset.x - Math.round(rect.x);
|
|
@@ -38,23 +38,6 @@ function getNodesAroundCursor(node, prev, next, hover) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
function getDropLevel(hovering, aboveCursor, belowCursor, indent) {
|
|
42
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
43
|
-
let min, max;
|
|
44
|
-
if (!aboveCursor) {
|
|
45
|
-
max = 0;
|
|
46
|
-
min = 0;
|
|
47
|
-
}
|
|
48
|
-
else if (!belowCursor) {
|
|
49
|
-
max = aboveCursor.level;
|
|
50
|
-
min = 0;
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
max = aboveCursor.level;
|
|
54
|
-
min = belowCursor.level;
|
|
55
|
-
}
|
|
56
|
-
return bound(hoverLevel, min, max);
|
|
57
|
-
}
|
|
58
41
|
function dropAt(parentId, index) {
|
|
59
42
|
return { parentId: parentId || null, index };
|
|
60
43
|
}
|
|
@@ -88,11 +71,12 @@ function walkUpFrom(node, level) {
|
|
|
88
71
|
}
|
|
89
72
|
/**
|
|
90
73
|
* This is the most complex, tricky function in the whole repo.
|
|
91
|
-
* It could be simplified and made more understandable.
|
|
92
74
|
*/
|
|
93
75
|
export function computeDrop(args) {
|
|
94
76
|
var _a;
|
|
95
77
|
const hover = measureHover(args.element, args.offset);
|
|
78
|
+
const indent = args.indent;
|
|
79
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
96
80
|
const { node, nextNode, prevNode } = args;
|
|
97
81
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
98
82
|
/* Hovering over the middle of a folder */
|
|
@@ -102,22 +86,52 @@ export function computeDrop(args) {
|
|
|
102
86
|
cursor: highlightCursor(node.id),
|
|
103
87
|
};
|
|
104
88
|
}
|
|
105
|
-
/*
|
|
89
|
+
/*
|
|
90
|
+
* Now we only need to care about the node above the cursor
|
|
91
|
+
* ----------- -------
|
|
92
|
+
*/
|
|
93
|
+
/* There is no node above the cursor line */
|
|
106
94
|
if (!above) {
|
|
107
95
|
return {
|
|
108
96
|
drop: dropAt((_a = below === null || below === void 0 ? void 0 : below.parent) === null || _a === void 0 ? void 0 : _a.id, 0),
|
|
109
97
|
cursor: lineCursor(0, 0),
|
|
110
98
|
};
|
|
111
99
|
}
|
|
112
|
-
/* The above
|
|
113
|
-
if (isItem(above)
|
|
114
|
-
const level =
|
|
100
|
+
/* The node above the cursor line is an item */
|
|
101
|
+
if (isItem(above)) {
|
|
102
|
+
const level = bound(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
103
|
+
return {
|
|
104
|
+
drop: walkUpFrom(above, level),
|
|
105
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/* The node above the cursor line is a closed folder */
|
|
109
|
+
if (isClosed(above)) {
|
|
110
|
+
const level = bound(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
115
111
|
return {
|
|
116
112
|
drop: walkUpFrom(above, level),
|
|
117
113
|
cursor: lineCursor(above.rowIndex + 1, level),
|
|
118
114
|
};
|
|
119
115
|
}
|
|
120
|
-
/* The above
|
|
116
|
+
/* The node above the cursor line is an open folder with no children */
|
|
117
|
+
if (isOpenWithEmptyChildren(above)) {
|
|
118
|
+
const level = bound(hoverLevel, 0, above.level + 1);
|
|
119
|
+
if (level > above.level) {
|
|
120
|
+
/* Will be the first child of the empty folder */
|
|
121
|
+
return {
|
|
122
|
+
drop: dropAt(above.id, 0),
|
|
123
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
128
|
+
return {
|
|
129
|
+
drop: walkUpFrom(above, level),
|
|
130
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/* The node above the cursor is a an open folder with children */
|
|
121
135
|
return {
|
|
122
136
|
drop: dropAt(above === null || above === void 0 ? void 0 : above.id, 0),
|
|
123
137
|
cursor: lineCursor(above.rowIndex + 1, above.level + 1),
|
|
@@ -15,7 +15,7 @@ export function useDragHook(node) {
|
|
|
15
15
|
// This is fired once at the begging of a drag operation
|
|
16
16
|
const dragIds = tree.isSelected(node.id) ? Array.from(ids) : [node.id];
|
|
17
17
|
tree.dispatch(dnd.dragStart(node.id, dragIds));
|
|
18
|
-
return { id: node.id };
|
|
18
|
+
return { id: node.id, dragIds };
|
|
19
19
|
},
|
|
20
20
|
end: () => {
|
|
21
21
|
tree.hideCursor();
|
|
@@ -62,11 +62,11 @@ export declare class TreeApi<T> {
|
|
|
62
62
|
type: "SELECTION_ONLY";
|
|
63
63
|
id: string;
|
|
64
64
|
};
|
|
65
|
-
add: (id: string |
|
|
65
|
+
add: (id: string | string[] | IdObj | IdObj[]) => {
|
|
66
66
|
type: "SELECTION_ADD";
|
|
67
67
|
ids: string[];
|
|
68
68
|
};
|
|
69
|
-
remove: (id: string |
|
|
69
|
+
remove: (id: string | string[] | IdObj | IdObj[]) => {
|
|
70
70
|
type: "SELECTION_REMOVE";
|
|
71
71
|
ids: string[];
|
|
72
72
|
};
|
|
@@ -80,11 +80,11 @@ export declare class TreeApi<T> {
|
|
|
80
80
|
mostRecent: string | null;
|
|
81
81
|
type: "SELECTION_SET";
|
|
82
82
|
};
|
|
83
|
-
mostRecent: (id: string |
|
|
83
|
+
mostRecent: (id: string | null | IdObj) => {
|
|
84
84
|
type: "SELECTION_MOST_RECENT";
|
|
85
85
|
id: string | null;
|
|
86
86
|
};
|
|
87
|
-
anchor: (id: string |
|
|
87
|
+
anchor: (id: string | null | IdObj) => {
|
|
88
88
|
type: "SELECTION_ANCHOR";
|
|
89
89
|
id: string | null;
|
|
90
90
|
};
|
|
@@ -166,9 +166,9 @@ export class TreeApi {
|
|
|
166
166
|
createLeaf() {
|
|
167
167
|
return this.create({ type: "leaf" });
|
|
168
168
|
}
|
|
169
|
-
create(
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
create() {
|
|
170
|
+
return __awaiter(this, arguments, void 0, function* (opts = {}) {
|
|
171
|
+
var _a, _b;
|
|
172
172
|
const parentId = opts.parentId === undefined
|
|
173
173
|
? utils.getInsertParentId(this)
|
|
174
174
|
: opts.parentId;
|
|
@@ -562,14 +562,12 @@ export class TreeApi {
|
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
isEditable(data) {
|
|
565
|
-
var _a;
|
|
566
565
|
const check = this.props.disableEdit || (() => false);
|
|
567
|
-
return
|
|
566
|
+
return !utils.access(data, check);
|
|
568
567
|
}
|
|
569
568
|
isDraggable(data) {
|
|
570
|
-
var _a;
|
|
571
569
|
const check = this.props.disableDrag || (() => false);
|
|
572
|
-
return
|
|
570
|
+
return !utils.access(data, check);
|
|
573
571
|
}
|
|
574
572
|
isDragging(node) {
|
|
575
573
|
const id = identifyNull(node);
|
|
@@ -44,11 +44,11 @@ export declare const rootReducer: import("redux").Reducer<{
|
|
|
44
44
|
type: "SELECTION_ONLY";
|
|
45
45
|
id: string;
|
|
46
46
|
};
|
|
47
|
-
add: (id: string | import("../types/utils").IdObj |
|
|
47
|
+
add: (id: string | string[] | import("../types/utils").IdObj | import("../types/utils").IdObj[]) => {
|
|
48
48
|
type: "SELECTION_ADD";
|
|
49
49
|
ids: string[];
|
|
50
50
|
};
|
|
51
|
-
remove: (id: string | import("../types/utils").IdObj |
|
|
51
|
+
remove: (id: string | string[] | import("../types/utils").IdObj | import("../types/utils").IdObj[]) => {
|
|
52
52
|
type: "SELECTION_REMOVE";
|
|
53
53
|
ids: string[];
|
|
54
54
|
};
|
|
@@ -62,11 +62,11 @@ export declare const rootReducer: import("redux").Reducer<{
|
|
|
62
62
|
mostRecent: string | null;
|
|
63
63
|
type: "SELECTION_SET";
|
|
64
64
|
};
|
|
65
|
-
mostRecent: (id: string | import("../types/utils").IdObj
|
|
65
|
+
mostRecent: (id: string | null | import("../types/utils").IdObj) => {
|
|
66
66
|
type: "SELECTION_MOST_RECENT";
|
|
67
67
|
id: string | null;
|
|
68
68
|
};
|
|
69
|
-
anchor: (id: string | import("../types/utils").IdObj
|
|
69
|
+
anchor: (id: string | null | import("../types/utils").IdObj) => {
|
|
70
70
|
type: "SELECTION_ANCHOR";
|
|
71
71
|
id: string | null;
|
|
72
72
|
};
|
package/dist/module/utils.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { IdObj } from "./types/utils";
|
|
|
4
4
|
export declare function bound(n: number, min: number, max: number): number;
|
|
5
5
|
export declare function isItem(node: NodeApi<any> | null): boolean | null;
|
|
6
6
|
export declare function isClosed(node: NodeApi<any> | null): boolean | null;
|
|
7
|
+
export declare function isOpenWithEmptyChildren(node: NodeApi<any> | null): boolean | null;
|
|
7
8
|
/**
|
|
8
9
|
* Is first param a descendant of the second param
|
|
9
10
|
*/
|
package/dist/module/utils.js
CHANGED
|
@@ -7,6 +7,10 @@ export function isItem(node) {
|
|
|
7
7
|
export function isClosed(node) {
|
|
8
8
|
return node && node.isInternal && !node.isOpen;
|
|
9
9
|
}
|
|
10
|
+
export function isOpenWithEmptyChildren(node) {
|
|
11
|
+
var _a;
|
|
12
|
+
return node && node.isOpen && !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length);
|
|
13
|
+
}
|
|
10
14
|
/**
|
|
11
15
|
* Is first param a descendant of the second param
|
|
12
16
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-arborist",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"main": "dist/main/index.js",
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"npm-run-all": "^4.1.5",
|
|
58
58
|
"rimraf": "^5.0.5",
|
|
59
59
|
"ts-jest": "^29.1.1",
|
|
60
|
-
"typescript": "^5.
|
|
61
|
-
}
|
|
62
|
-
"stableVersion": "3.3.1"
|
|
60
|
+
"typescript": "^5.6.0"
|
|
61
|
+
}
|
|
63
62
|
}
|
package/src/dnd/compute-drop.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { XYCoord } from "react-dnd";
|
|
2
2
|
import { NodeApi } from "../interfaces/node-api";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
bound,
|
|
5
|
+
indexOf,
|
|
6
|
+
isClosed,
|
|
7
|
+
isItem,
|
|
8
|
+
isOpenWithEmptyChildren,
|
|
9
|
+
} from "../utils";
|
|
4
10
|
import { DropResult } from "./drop-hook";
|
|
5
11
|
|
|
6
12
|
function measureHover(el: HTMLElement, offset: XYCoord) {
|
|
@@ -56,28 +62,6 @@ type Args = {
|
|
|
56
62
|
nextNode: NodeApi | null;
|
|
57
63
|
};
|
|
58
64
|
|
|
59
|
-
function getDropLevel(
|
|
60
|
-
hovering: HoverData,
|
|
61
|
-
aboveCursor: NodeApi | null,
|
|
62
|
-
belowCursor: NodeApi | null,
|
|
63
|
-
indent: number
|
|
64
|
-
) {
|
|
65
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
66
|
-
let min, max;
|
|
67
|
-
if (!aboveCursor) {
|
|
68
|
-
max = 0;
|
|
69
|
-
min = 0;
|
|
70
|
-
} else if (!belowCursor) {
|
|
71
|
-
max = aboveCursor.level;
|
|
72
|
-
min = 0;
|
|
73
|
-
} else {
|
|
74
|
-
max = aboveCursor.level;
|
|
75
|
-
min = belowCursor.level;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return bound(hoverLevel, min, max);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
65
|
export type ComputedDrop = {
|
|
82
66
|
drop: DropResult | null;
|
|
83
67
|
cursor: Cursor | null;
|
|
@@ -128,10 +112,11 @@ export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
|
128
112
|
|
|
129
113
|
/**
|
|
130
114
|
* This is the most complex, tricky function in the whole repo.
|
|
131
|
-
* It could be simplified and made more understandable.
|
|
132
115
|
*/
|
|
133
116
|
export function computeDrop(args: Args): ComputedDrop {
|
|
134
117
|
const hover = measureHover(args.element, args.offset);
|
|
118
|
+
const indent = args.indent;
|
|
119
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
135
120
|
const { node, nextNode, prevNode } = args;
|
|
136
121
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
137
122
|
|
|
@@ -143,7 +128,12 @@ export function computeDrop(args: Args): ComputedDrop {
|
|
|
143
128
|
};
|
|
144
129
|
}
|
|
145
130
|
|
|
146
|
-
/*
|
|
131
|
+
/*
|
|
132
|
+
* Now we only need to care about the node above the cursor
|
|
133
|
+
* ----------- -------
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/* There is no node above the cursor line */
|
|
147
137
|
if (!above) {
|
|
148
138
|
return {
|
|
149
139
|
drop: dropAt(below?.parent?.id, 0),
|
|
@@ -151,16 +141,43 @@ export function computeDrop(args: Args): ComputedDrop {
|
|
|
151
141
|
};
|
|
152
142
|
}
|
|
153
143
|
|
|
154
|
-
/* The above
|
|
155
|
-
if (isItem(above)
|
|
156
|
-
const level =
|
|
144
|
+
/* The node above the cursor line is an item */
|
|
145
|
+
if (isItem(above)) {
|
|
146
|
+
const level = bound(hoverLevel, below?.level || 0, above.level);
|
|
147
|
+
return {
|
|
148
|
+
drop: walkUpFrom(above, level),
|
|
149
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* The node above the cursor line is a closed folder */
|
|
154
|
+
if (isClosed(above)) {
|
|
155
|
+
const level = bound(hoverLevel, below?.level || 0, above.level);
|
|
157
156
|
return {
|
|
158
157
|
drop: walkUpFrom(above, level),
|
|
159
158
|
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
160
159
|
};
|
|
161
160
|
}
|
|
162
161
|
|
|
163
|
-
/* The above
|
|
162
|
+
/* The node above the cursor line is an open folder with no children */
|
|
163
|
+
if (isOpenWithEmptyChildren(above)) {
|
|
164
|
+
const level = bound(hoverLevel, 0, above.level + 1);
|
|
165
|
+
if (level > above.level) {
|
|
166
|
+
/* Will be the first child of the empty folder */
|
|
167
|
+
return {
|
|
168
|
+
drop: dropAt(above.id, 0),
|
|
169
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
173
|
+
return {
|
|
174
|
+
drop: walkUpFrom(above, level),
|
|
175
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* The node above the cursor is a an open folder with children */
|
|
164
181
|
return {
|
|
165
182
|
drop: dropAt(above?.id, 0),
|
|
166
183
|
cursor: lineCursor(above.rowIndex! + 1, above.level + 1),
|
package/src/dnd/drag-hook.ts
CHANGED
|
@@ -20,7 +20,7 @@ export function useDragHook<T>(node: NodeApi<T>): ConnectDragSource {
|
|
|
20
20
|
// This is fired once at the begging of a drag operation
|
|
21
21
|
const dragIds = tree.isSelected(node.id) ? Array.from(ids) : [node.id];
|
|
22
22
|
tree.dispatch(dnd.dragStart(node.id, dragIds));
|
|
23
|
-
return { id: node.id };
|
|
23
|
+
return { id: node.id, dragIds };
|
|
24
24
|
},
|
|
25
25
|
end: () => {
|
|
26
26
|
tree.hideCursor();
|
|
@@ -593,12 +593,12 @@ export class TreeApi<T> {
|
|
|
593
593
|
|
|
594
594
|
isEditable(data: T) {
|
|
595
595
|
const check = this.props.disableEdit || (() => false);
|
|
596
|
-
return !utils.access(data, check)
|
|
596
|
+
return !utils.access(data, check);
|
|
597
597
|
}
|
|
598
598
|
|
|
599
599
|
isDraggable(data: T) {
|
|
600
600
|
const check = this.props.disableDrag || (() => false);
|
|
601
|
-
return !utils.access(data, check)
|
|
601
|
+
return !utils.access(data, check);
|
|
602
602
|
}
|
|
603
603
|
|
|
604
604
|
isDragging(node: string | IdObj | null) {
|
package/src/utils.ts
CHANGED
|
@@ -14,6 +14,10 @@ export function isClosed(node: NodeApi<any> | null) {
|
|
|
14
14
|
return node && node.isInternal && !node.isOpen;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function isOpenWithEmptyChildren(node: NodeApi<any> | null) {
|
|
18
|
+
return node && node.isOpen && !node.children?.length;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* Is first param a descendant of the second param
|
|
19
23
|
*/
|