@mui/x-tree-view 7.1.1 → 7.2.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/CHANGELOG.md +86 -0
- package/RichTreeView/RichTreeView.types.d.ts +3 -3
- package/TreeItem/TreeItem.js +1 -1
- package/TreeItem2/TreeItem2.d.ts +5 -1
- package/TreeItem2/TreeItem2.js +0 -1
- package/index.js +1 -1
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +16 -0
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
- package/internals/TreeViewProvider/TreeViewContext.d.ts +2 -0
- package/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -1
- package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/internals/models/plugin.d.ts +13 -5
- package/internals/models/treeView.d.ts +1 -2
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +19 -15
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +4 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +3 -2
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/internals/useTreeView/useTreeView.js +21 -3
- package/internals/utils/tree.d.ts +8 -0
- package/internals/utils/tree.js +137 -0
- package/modern/TreeItem/TreeItem.js +1 -1
- package/modern/TreeItem2/TreeItem2.js +0 -1
- package/modern/index.js +1 -1
- package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
- package/modern/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
- package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/modern/internals/useTreeView/useTreeView.js +21 -3
- package/modern/internals/utils/tree.js +137 -0
- package/modern/useTreeItem2/useTreeItem2.js +1 -1
- package/node/TreeItem/TreeItem.js +1 -1
- package/node/TreeItem2/TreeItem2.js +0 -1
- package/node/index.js +1 -1
- package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +67 -0
- package/node/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +15 -0
- package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/node/internals/useTreeView/useTreeView.js +21 -3
- package/node/internals/utils/tree.js +148 -0
- package/node/useTreeItem2/useTreeItem2.js +1 -1
- package/package.json +1 -1
- package/useTreeItem2/useTreeItem2.js +1 -1
- package/internals/TreeViewProvider/DescendantProvider.d.ts +0 -38
- package/internals/TreeViewProvider/DescendantProvider.js +0 -176
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +0 -17
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
- package/internals/useTreeView/useTreeView.utils.d.ts +0 -9
- package/internals/useTreeView/useTreeView.utils.js +0 -46
- package/modern/internals/TreeViewProvider/DescendantProvider.js +0 -176
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
- package/modern/internals/useTreeView/useTreeView.utils.js +0 -46
- package/node/internals/TreeViewProvider/DescendantProvider.js +0 -185
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -62
- package/node/internals/useTreeView/useTreeView.utils.js +0 -58
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getPreviousNavigableItem = exports.getNextNavigableItem = exports.getNavigableItemsInRange = exports.getLastNavigableItem = exports.getFirstNavigableItem = void 0;
|
|
7
|
+
const getLastNavigableItemInArray = (instance, items) => {
|
|
8
|
+
// Equivalent to Array.prototype.findLastIndex
|
|
9
|
+
let itemIndex = items.length - 1;
|
|
10
|
+
while (itemIndex >= 0 && !instance.isItemNavigable(items[itemIndex])) {
|
|
11
|
+
itemIndex -= 1;
|
|
12
|
+
}
|
|
13
|
+
if (itemIndex === -1) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return items[itemIndex];
|
|
17
|
+
};
|
|
18
|
+
const getPreviousNavigableItem = (instance, itemId) => {
|
|
19
|
+
const itemMeta = instance.getItemMeta(itemId);
|
|
20
|
+
const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
|
|
21
|
+
const itemIndex = instance.getItemIndex(itemId);
|
|
22
|
+
|
|
23
|
+
// TODO: What should we do if the parent is not navigable?
|
|
24
|
+
if (itemIndex === 0) {
|
|
25
|
+
return itemMeta.parentId;
|
|
26
|
+
}
|
|
27
|
+
let currentItemId = siblings[itemIndex - 1];
|
|
28
|
+
let lastNavigableChild = getLastNavigableItemInArray(instance, instance.getItemOrderedChildrenIds(currentItemId));
|
|
29
|
+
while (instance.isItemExpanded(currentItemId) && lastNavigableChild != null) {
|
|
30
|
+
currentItemId = lastNavigableChild;
|
|
31
|
+
lastNavigableChild = instance.getItemOrderedChildrenIds(currentItemId).find(instance.isItemNavigable);
|
|
32
|
+
}
|
|
33
|
+
return currentItemId;
|
|
34
|
+
};
|
|
35
|
+
exports.getPreviousNavigableItem = getPreviousNavigableItem;
|
|
36
|
+
const getNextNavigableItem = (instance, itemId) => {
|
|
37
|
+
// If the item is expanded and has some navigable children, return the first of them.
|
|
38
|
+
if (instance.isItemExpanded(itemId)) {
|
|
39
|
+
const firstNavigableChild = instance.getItemOrderedChildrenIds(itemId).find(instance.isItemNavigable);
|
|
40
|
+
if (firstNavigableChild != null) {
|
|
41
|
+
return firstNavigableChild;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let itemMeta = instance.getItemMeta(itemId);
|
|
45
|
+
while (itemMeta != null) {
|
|
46
|
+
// Try to find the first navigable sibling after the current item.
|
|
47
|
+
const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
|
|
48
|
+
const currentItemIndex = instance.getItemIndex(itemMeta.id);
|
|
49
|
+
if (currentItemIndex < siblings.length - 1) {
|
|
50
|
+
let nextItemIndex = currentItemIndex + 1;
|
|
51
|
+
while (!instance.isItemNavigable(siblings[nextItemIndex]) && nextItemIndex < siblings.length - 1) {
|
|
52
|
+
nextItemIndex += 1;
|
|
53
|
+
}
|
|
54
|
+
if (instance.isItemNavigable(siblings[nextItemIndex])) {
|
|
55
|
+
return siblings[nextItemIndex];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// If the sibling does not exist, go up a level to the parent and try again.
|
|
60
|
+
itemMeta = instance.getItemMeta(itemMeta.parentId);
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
64
|
+
exports.getNextNavigableItem = getNextNavigableItem;
|
|
65
|
+
const getLastNavigableItem = instance => {
|
|
66
|
+
let itemId = null;
|
|
67
|
+
while (itemId == null || instance.isItemExpanded(itemId)) {
|
|
68
|
+
const children = instance.getItemOrderedChildrenIds(itemId);
|
|
69
|
+
const lastNavigableChild = getLastNavigableItemInArray(instance, children);
|
|
70
|
+
|
|
71
|
+
// The item has no navigable children.
|
|
72
|
+
if (lastNavigableChild == null) {
|
|
73
|
+
return itemId;
|
|
74
|
+
}
|
|
75
|
+
itemId = lastNavigableChild;
|
|
76
|
+
}
|
|
77
|
+
return itemId;
|
|
78
|
+
};
|
|
79
|
+
exports.getLastNavigableItem = getLastNavigableItem;
|
|
80
|
+
const getFirstNavigableItem = instance => instance.getItemOrderedChildrenIds(null).find(instance.isItemNavigable);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* This is used to determine the start and end of a selection range so
|
|
84
|
+
* we can get the items between the two border items.
|
|
85
|
+
*
|
|
86
|
+
* It finds the items' common ancestor using
|
|
87
|
+
* a naive implementation of a lowest common ancestor algorithm
|
|
88
|
+
* (https://en.wikipedia.org/wiki/Lowest_common_ancestor).
|
|
89
|
+
* Then compares the ancestor's 2 children that are ancestors of itemA and ItemB
|
|
90
|
+
* so we can compare their indexes to work out which item comes first in a depth first search.
|
|
91
|
+
* (https://en.wikipedia.org/wiki/Depth-first_search)
|
|
92
|
+
*
|
|
93
|
+
* Another way to put it is which item is shallower in a trémaux tree
|
|
94
|
+
* https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree
|
|
95
|
+
*/
|
|
96
|
+
exports.getFirstNavigableItem = getFirstNavigableItem;
|
|
97
|
+
const findOrderInTremauxTree = (instance, itemAId, itemBId) => {
|
|
98
|
+
if (itemAId === itemBId) {
|
|
99
|
+
return [itemAId, itemBId];
|
|
100
|
+
}
|
|
101
|
+
const itemMetaA = instance.getItemMeta(itemAId);
|
|
102
|
+
const itemMetaB = instance.getItemMeta(itemBId);
|
|
103
|
+
if (itemMetaA.parentId === itemMetaB.id || itemMetaB.parentId === itemMetaA.id) {
|
|
104
|
+
return itemMetaB.parentId === itemMetaA.id ? [itemMetaA.id, itemMetaB.id] : [itemMetaB.id, itemMetaA.id];
|
|
105
|
+
}
|
|
106
|
+
const aFamily = [itemMetaA.id];
|
|
107
|
+
const bFamily = [itemMetaB.id];
|
|
108
|
+
let aAncestor = itemMetaA.parentId;
|
|
109
|
+
let bAncestor = itemMetaB.parentId;
|
|
110
|
+
let aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
|
|
111
|
+
let bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
|
|
112
|
+
let continueA = true;
|
|
113
|
+
let continueB = true;
|
|
114
|
+
while (!bAncestorIsCommon && !aAncestorIsCommon) {
|
|
115
|
+
if (continueA) {
|
|
116
|
+
aFamily.push(aAncestor);
|
|
117
|
+
aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
|
|
118
|
+
continueA = aAncestor !== null;
|
|
119
|
+
if (!aAncestorIsCommon && continueA) {
|
|
120
|
+
aAncestor = instance.getItemMeta(aAncestor).parentId;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (continueB && !aAncestorIsCommon) {
|
|
124
|
+
bFamily.push(bAncestor);
|
|
125
|
+
bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
|
|
126
|
+
continueB = bAncestor !== null;
|
|
127
|
+
if (!bAncestorIsCommon && continueB) {
|
|
128
|
+
bAncestor = instance.getItemMeta(bAncestor).parentId;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor;
|
|
133
|
+
const ancestorFamily = instance.getItemOrderedChildrenIds(commonAncestor);
|
|
134
|
+
const aSide = aFamily[aFamily.indexOf(commonAncestor) - 1];
|
|
135
|
+
const bSide = bFamily[bFamily.indexOf(commonAncestor) - 1];
|
|
136
|
+
return ancestorFamily.indexOf(aSide) < ancestorFamily.indexOf(bSide) ? [itemAId, itemBId] : [itemBId, itemAId];
|
|
137
|
+
};
|
|
138
|
+
const getNavigableItemsInRange = (instance, itemAId, itemBId) => {
|
|
139
|
+
const [first, last] = findOrderInTremauxTree(instance, itemAId, itemBId);
|
|
140
|
+
const items = [first];
|
|
141
|
+
let current = first;
|
|
142
|
+
while (current !== last) {
|
|
143
|
+
current = getNextNavigableItem(instance, current);
|
|
144
|
+
items.push(current);
|
|
145
|
+
}
|
|
146
|
+
return items;
|
|
147
|
+
};
|
|
148
|
+
exports.getNavigableItemsInRange = getNavigableItemsInRange;
|
|
@@ -38,7 +38,7 @@ const useTreeItem2 = parameters => {
|
|
|
38
38
|
itemId,
|
|
39
39
|
children
|
|
40
40
|
});
|
|
41
|
-
const idAttribute = instance.
|
|
41
|
+
const idAttribute = instance.getTreeItemIdAttribute(itemId, id);
|
|
42
42
|
const handleRootRef = (0, _useForkRef.default)(rootRef, pluginRootRef);
|
|
43
43
|
const createRootHandleFocus = otherHandlers => event => {
|
|
44
44
|
otherHandlers.onFocus?.(event);
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ export const useTreeItem2 = parameters => {
|
|
|
31
31
|
itemId,
|
|
32
32
|
children
|
|
33
33
|
});
|
|
34
|
-
const idAttribute = instance.
|
|
34
|
+
const idAttribute = instance.getTreeItemIdAttribute(itemId, id);
|
|
35
35
|
const handleRootRef = useForkRef(rootRef, pluginRootRef);
|
|
36
36
|
const createRootHandleFocus = otherHandlers => event => {
|
|
37
37
|
otherHandlers.onFocus?.(event);
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* This hook registers our descendant by passing it into an array. We can then
|
|
4
|
-
* search that array by to find its index when registering it in the component.
|
|
5
|
-
* We use this for focus management, keyboard navigation, and typeahead
|
|
6
|
-
* functionality for some components.
|
|
7
|
-
*
|
|
8
|
-
* The hook accepts the element item
|
|
9
|
-
*
|
|
10
|
-
* Our main goals with this are:
|
|
11
|
-
* 1) maximum composability,
|
|
12
|
-
* 2) minimal API friction
|
|
13
|
-
* 3) SSR compatibility*
|
|
14
|
-
* 4) concurrent safe
|
|
15
|
-
* 5) index always up-to-date with the tree despite changes
|
|
16
|
-
* 6) works with memoization of any component in the tree (hopefully)
|
|
17
|
-
*
|
|
18
|
-
* * As for SSR, the good news is that we don't actually need the index on the
|
|
19
|
-
* server for most use-cases, as we are only using it to determine the order of
|
|
20
|
-
* composed descendants for keyboard navigation.
|
|
21
|
-
*/
|
|
22
|
-
export declare function useDescendant(descendant: TreeItemDescendant): {
|
|
23
|
-
parentId: string | null;
|
|
24
|
-
index: number;
|
|
25
|
-
};
|
|
26
|
-
interface DescendantProviderProps {
|
|
27
|
-
id?: string;
|
|
28
|
-
children: React.ReactNode;
|
|
29
|
-
}
|
|
30
|
-
export declare function DescendantProvider(props: DescendantProviderProps): React.JSX.Element;
|
|
31
|
-
export declare namespace DescendantProvider {
|
|
32
|
-
var propTypes: any;
|
|
33
|
-
}
|
|
34
|
-
export interface TreeItemDescendant {
|
|
35
|
-
element: HTMLLIElement;
|
|
36
|
-
id: string;
|
|
37
|
-
}
|
|
38
|
-
export {};
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
|
-
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
const _excluded = ["element"];
|
|
4
|
-
import * as React from 'react';
|
|
5
|
-
import PropTypes from 'prop-types';
|
|
6
|
-
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
7
|
-
|
|
8
|
-
/** Credit: https://github.com/reach/reach-ui/blob/86a046f54d53b6420e392b3fa56dd991d9d4e458/packages/descendants/README.md
|
|
9
|
-
* Modified slightly to suit our purposes.
|
|
10
|
-
*/
|
|
11
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
-
function binaryFindElement(array, element) {
|
|
13
|
-
let start = 0;
|
|
14
|
-
let end = array.length - 1;
|
|
15
|
-
while (start <= end) {
|
|
16
|
-
const middle = Math.floor((start + end) / 2);
|
|
17
|
-
if (array[middle].element === element) {
|
|
18
|
-
return middle;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// eslint-disable-next-line no-bitwise
|
|
22
|
-
if (array[middle].element.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_PRECEDING) {
|
|
23
|
-
end = middle - 1;
|
|
24
|
-
} else {
|
|
25
|
-
start = middle + 1;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return start;
|
|
29
|
-
}
|
|
30
|
-
const DescendantContext = /*#__PURE__*/React.createContext({});
|
|
31
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
32
|
-
DescendantContext.displayName = 'DescendantContext';
|
|
33
|
-
}
|
|
34
|
-
function usePrevious(value) {
|
|
35
|
-
const ref = React.useRef(null);
|
|
36
|
-
React.useEffect(() => {
|
|
37
|
-
ref.current = value;
|
|
38
|
-
}, [value]);
|
|
39
|
-
return ref.current;
|
|
40
|
-
}
|
|
41
|
-
const noop = () => {};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* This hook registers our descendant by passing it into an array. We can then
|
|
45
|
-
* search that array by to find its index when registering it in the component.
|
|
46
|
-
* We use this for focus management, keyboard navigation, and typeahead
|
|
47
|
-
* functionality for some components.
|
|
48
|
-
*
|
|
49
|
-
* The hook accepts the element item
|
|
50
|
-
*
|
|
51
|
-
* Our main goals with this are:
|
|
52
|
-
* 1) maximum composability,
|
|
53
|
-
* 2) minimal API friction
|
|
54
|
-
* 3) SSR compatibility*
|
|
55
|
-
* 4) concurrent safe
|
|
56
|
-
* 5) index always up-to-date with the tree despite changes
|
|
57
|
-
* 6) works with memoization of any component in the tree (hopefully)
|
|
58
|
-
*
|
|
59
|
-
* * As for SSR, the good news is that we don't actually need the index on the
|
|
60
|
-
* server for most use-cases, as we are only using it to determine the order of
|
|
61
|
-
* composed descendants for keyboard navigation.
|
|
62
|
-
*/
|
|
63
|
-
export function useDescendant(descendant) {
|
|
64
|
-
const [, forceUpdate] = React.useState();
|
|
65
|
-
const {
|
|
66
|
-
registerDescendant = noop,
|
|
67
|
-
unregisterDescendant = noop,
|
|
68
|
-
descendants = [],
|
|
69
|
-
parentId = null
|
|
70
|
-
} = React.useContext(DescendantContext);
|
|
71
|
-
|
|
72
|
-
// This will initially return -1 because we haven't registered the descendant
|
|
73
|
-
// on the first render. After we register, this will then return the correct
|
|
74
|
-
// index on the following render, and we will re-register descendants
|
|
75
|
-
// so that everything is up-to-date before the user interacts with a
|
|
76
|
-
// collection.
|
|
77
|
-
const index = descendants.findIndex(item => item.element === descendant.element);
|
|
78
|
-
const previousDescendants = usePrevious(descendants);
|
|
79
|
-
|
|
80
|
-
// We also need to re-register descendants any time ANY of the other
|
|
81
|
-
// descendants have changed. My brain was melting when I wrote this and it
|
|
82
|
-
// feels a little off, but checking in render and using the result in the
|
|
83
|
-
// effect's dependency array works well enough.
|
|
84
|
-
const someDescendantsHaveChanged = descendants.some((newDescendant, position) => {
|
|
85
|
-
return previousDescendants && previousDescendants[position] && previousDescendants[position].element !== newDescendant.element;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Prevent any flashing
|
|
89
|
-
useEnhancedEffect(() => {
|
|
90
|
-
if (descendant.element) {
|
|
91
|
-
registerDescendant(_extends({}, descendant, {
|
|
92
|
-
index
|
|
93
|
-
}));
|
|
94
|
-
return () => {
|
|
95
|
-
unregisterDescendant(descendant.element);
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
forceUpdate({});
|
|
99
|
-
return undefined;
|
|
100
|
-
}, [registerDescendant, unregisterDescendant, index, someDescendantsHaveChanged, descendant]);
|
|
101
|
-
return {
|
|
102
|
-
parentId,
|
|
103
|
-
index
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
export function DescendantProvider(props) {
|
|
107
|
-
const {
|
|
108
|
-
children,
|
|
109
|
-
id
|
|
110
|
-
} = props;
|
|
111
|
-
const [items, set] = React.useState([]);
|
|
112
|
-
const registerDescendant = React.useCallback(_ref => {
|
|
113
|
-
let {
|
|
114
|
-
element
|
|
115
|
-
} = _ref,
|
|
116
|
-
other = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
117
|
-
set(oldItems => {
|
|
118
|
-
if (oldItems.length === 0) {
|
|
119
|
-
// If there are no items, register at index 0 and bail.
|
|
120
|
-
return [_extends({}, other, {
|
|
121
|
-
element,
|
|
122
|
-
index: 0
|
|
123
|
-
})];
|
|
124
|
-
}
|
|
125
|
-
const index = binaryFindElement(oldItems, element);
|
|
126
|
-
let newItems;
|
|
127
|
-
if (oldItems[index] && oldItems[index].element === element) {
|
|
128
|
-
// If the element is already registered, just use the same array
|
|
129
|
-
newItems = oldItems;
|
|
130
|
-
} else {
|
|
131
|
-
// When registering a descendant, we need to make sure we insert in
|
|
132
|
-
// into the array in the same order that it appears in the DOM. So as
|
|
133
|
-
// new descendants are added or maybe some are removed, we always know
|
|
134
|
-
// that the array is up-to-date and correct.
|
|
135
|
-
//
|
|
136
|
-
// So here we look at our registered descendants and see if the new
|
|
137
|
-
// element we are adding appears earlier than an existing descendant's
|
|
138
|
-
// DOM node via `node.compareDocumentPosition`. If it does, we insert
|
|
139
|
-
// the new element at this index. Because `registerDescendant` will be
|
|
140
|
-
// called in an effect every time the descendants state value changes,
|
|
141
|
-
// we should be sure that this index is accurate when descendent
|
|
142
|
-
// elements come or go from our component.
|
|
143
|
-
|
|
144
|
-
const newItem = _extends({}, other, {
|
|
145
|
-
element,
|
|
146
|
-
index
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// If an index is not found we will push the element to the end.
|
|
150
|
-
newItems = oldItems.slice();
|
|
151
|
-
newItems.splice(index, 0, newItem);
|
|
152
|
-
}
|
|
153
|
-
newItems.forEach((item, position) => {
|
|
154
|
-
item.index = position;
|
|
155
|
-
});
|
|
156
|
-
return newItems;
|
|
157
|
-
});
|
|
158
|
-
}, []);
|
|
159
|
-
const unregisterDescendant = React.useCallback(element => {
|
|
160
|
-
set(oldItems => oldItems.filter(item => element !== item.element));
|
|
161
|
-
}, []);
|
|
162
|
-
const value = React.useMemo(() => ({
|
|
163
|
-
descendants: items,
|
|
164
|
-
registerDescendant,
|
|
165
|
-
unregisterDescendant,
|
|
166
|
-
parentId: id
|
|
167
|
-
}), [items, registerDescendant, unregisterDescendant, id]);
|
|
168
|
-
return /*#__PURE__*/_jsx(DescendantContext.Provider, {
|
|
169
|
-
value: value,
|
|
170
|
-
children: children
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
process.env.NODE_ENV !== "production" ? DescendantProvider.propTypes = {
|
|
174
|
-
children: PropTypes.node,
|
|
175
|
-
id: PropTypes.string
|
|
176
|
-
} : void 0;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { TreeViewInstance } from '../../models';
|
|
2
|
-
import { UseTreeViewItemsSignature } from '../useTreeViewItems';
|
|
3
|
-
/**
|
|
4
|
-
* This is used to determine the start and end of a selection range so
|
|
5
|
-
* we can get the items between the two border items.
|
|
6
|
-
*
|
|
7
|
-
* It finds the items' common ancestor using
|
|
8
|
-
* a naive implementation of a lowest common ancestor algorithm
|
|
9
|
-
* (https://en.wikipedia.org/wiki/Lowest_common_ancestor).
|
|
10
|
-
* Then compares the ancestor's 2 children that are ancestors of itemA and ItemB
|
|
11
|
-
* so we can compare their indexes to work out which item comes first in a depth first search.
|
|
12
|
-
* (https://en.wikipedia.org/wiki/Depth-first_search)
|
|
13
|
-
*
|
|
14
|
-
* Another way to put it is which item is shallower in a trémaux tree
|
|
15
|
-
* https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree
|
|
16
|
-
*/
|
|
17
|
-
export declare const findOrderInTremauxTree: (instance: TreeViewInstance<[UseTreeViewItemsSignature]>, nodeAId: string, nodeBId: string) => string[];
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is used to determine the start and end of a selection range so
|
|
3
|
-
* we can get the items between the two border items.
|
|
4
|
-
*
|
|
5
|
-
* It finds the items' common ancestor using
|
|
6
|
-
* a naive implementation of a lowest common ancestor algorithm
|
|
7
|
-
* (https://en.wikipedia.org/wiki/Lowest_common_ancestor).
|
|
8
|
-
* Then compares the ancestor's 2 children that are ancestors of itemA and ItemB
|
|
9
|
-
* so we can compare their indexes to work out which item comes first in a depth first search.
|
|
10
|
-
* (https://en.wikipedia.org/wiki/Depth-first_search)
|
|
11
|
-
*
|
|
12
|
-
* Another way to put it is which item is shallower in a trémaux tree
|
|
13
|
-
* https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree
|
|
14
|
-
*/
|
|
15
|
-
export const findOrderInTremauxTree = (instance, nodeAId, nodeBId) => {
|
|
16
|
-
if (nodeAId === nodeBId) {
|
|
17
|
-
return [nodeAId, nodeBId];
|
|
18
|
-
}
|
|
19
|
-
const nodeA = instance.getNode(nodeAId);
|
|
20
|
-
const nodeB = instance.getNode(nodeBId);
|
|
21
|
-
if (nodeA.parentId === nodeB.id || nodeB.parentId === nodeA.id) {
|
|
22
|
-
return nodeB.parentId === nodeA.id ? [nodeA.id, nodeB.id] : [nodeB.id, nodeA.id];
|
|
23
|
-
}
|
|
24
|
-
const aFamily = [nodeA.id];
|
|
25
|
-
const bFamily = [nodeB.id];
|
|
26
|
-
let aAncestor = nodeA.parentId;
|
|
27
|
-
let bAncestor = nodeB.parentId;
|
|
28
|
-
let aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
|
|
29
|
-
let bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
|
|
30
|
-
let continueA = true;
|
|
31
|
-
let continueB = true;
|
|
32
|
-
while (!bAncestorIsCommon && !aAncestorIsCommon) {
|
|
33
|
-
if (continueA) {
|
|
34
|
-
aFamily.push(aAncestor);
|
|
35
|
-
aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
|
|
36
|
-
continueA = aAncestor !== null;
|
|
37
|
-
if (!aAncestorIsCommon && continueA) {
|
|
38
|
-
aAncestor = instance.getNode(aAncestor).parentId;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (continueB && !aAncestorIsCommon) {
|
|
42
|
-
bFamily.push(bAncestor);
|
|
43
|
-
bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
|
|
44
|
-
continueB = bAncestor !== null;
|
|
45
|
-
if (!bAncestorIsCommon && continueB) {
|
|
46
|
-
bAncestor = instance.getNode(bAncestor).parentId;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor;
|
|
51
|
-
const ancestorFamily = instance.getChildrenIds(commonAncestor);
|
|
52
|
-
const aSide = aFamily[aFamily.indexOf(commonAncestor) - 1];
|
|
53
|
-
const bSide = bFamily[bFamily.indexOf(commonAncestor) - 1];
|
|
54
|
-
return ancestorFamily.indexOf(aSide) < ancestorFamily.indexOf(bSide) ? [nodeAId, nodeBId] : [nodeBId, nodeAId];
|
|
55
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { TreeViewAnyPluginSignature, TreeViewInstance, TreeViewUsedInstance, TreeViewUsedPublicAPI } from '../models';
|
|
2
|
-
import type { UseTreeViewExpansionSignature } from '../plugins/useTreeViewExpansion';
|
|
3
|
-
import type { UseTreeViewItemsSignature } from '../plugins/useTreeViewItems';
|
|
4
|
-
export declare const getPreviousItem: (instance: TreeViewInstance<[UseTreeViewItemsSignature, UseTreeViewExpansionSignature]>, itemId: string) => string | null;
|
|
5
|
-
export declare const getNextItem: (instance: TreeViewInstance<[UseTreeViewExpansionSignature, UseTreeViewItemsSignature]>, itemId: string) => string | null;
|
|
6
|
-
export declare const getLastItem: (instance: TreeViewInstance<[UseTreeViewExpansionSignature, UseTreeViewItemsSignature]>) => string;
|
|
7
|
-
export declare const getFirstItem: (instance: TreeViewInstance<[UseTreeViewItemsSignature]>) => string;
|
|
8
|
-
export declare const populateInstance: <T extends TreeViewAnyPluginSignature>(instance: TreeViewUsedInstance<T>, methods: T["instance"]) => void;
|
|
9
|
-
export declare const populatePublicAPI: <T extends TreeViewAnyPluginSignature>(publicAPI: TreeViewUsedPublicAPI<T>, methods: T["publicAPI"]) => void;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export const getPreviousItem = (instance, itemId) => {
|
|
2
|
-
const node = instance.getNode(itemId);
|
|
3
|
-
const siblings = instance.getNavigableChildrenIds(node.parentId);
|
|
4
|
-
const itemIndex = siblings.indexOf(itemId);
|
|
5
|
-
if (itemIndex === 0) {
|
|
6
|
-
return node.parentId;
|
|
7
|
-
}
|
|
8
|
-
let currentItem = siblings[itemIndex - 1];
|
|
9
|
-
while (instance.isItemExpanded(currentItem) && instance.getNavigableChildrenIds(currentItem).length > 0) {
|
|
10
|
-
currentItem = instance.getNavigableChildrenIds(currentItem).pop();
|
|
11
|
-
}
|
|
12
|
-
return currentItem;
|
|
13
|
-
};
|
|
14
|
-
export const getNextItem = (instance, itemId) => {
|
|
15
|
-
// If expanded get first child
|
|
16
|
-
if (instance.isItemExpanded(itemId) && instance.getNavigableChildrenIds(itemId).length > 0) {
|
|
17
|
-
return instance.getNavigableChildrenIds(itemId)[0];
|
|
18
|
-
}
|
|
19
|
-
let node = instance.getNode(itemId);
|
|
20
|
-
while (node != null) {
|
|
21
|
-
// Try to get next sibling
|
|
22
|
-
const siblings = instance.getNavigableChildrenIds(node.parentId);
|
|
23
|
-
const nextSibling = siblings[siblings.indexOf(node.id) + 1];
|
|
24
|
-
if (nextSibling) {
|
|
25
|
-
return nextSibling;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// If the sibling does not exist, go up a level to the parent and try again.
|
|
29
|
-
node = instance.getNode(node.parentId);
|
|
30
|
-
}
|
|
31
|
-
return null;
|
|
32
|
-
};
|
|
33
|
-
export const getLastItem = instance => {
|
|
34
|
-
let lastItem = instance.getNavigableChildrenIds(null).pop();
|
|
35
|
-
while (instance.isItemExpanded(lastItem)) {
|
|
36
|
-
lastItem = instance.getNavigableChildrenIds(lastItem).pop();
|
|
37
|
-
}
|
|
38
|
-
return lastItem;
|
|
39
|
-
};
|
|
40
|
-
export const getFirstItem = instance => instance.getNavigableChildrenIds(null)[0];
|
|
41
|
-
export const populateInstance = (instance, methods) => {
|
|
42
|
-
Object.assign(instance, methods);
|
|
43
|
-
};
|
|
44
|
-
export const populatePublicAPI = (publicAPI, methods) => {
|
|
45
|
-
Object.assign(publicAPI, methods);
|
|
46
|
-
};
|