@itwin/presentation-hierarchies 2.0.0-alpha.12 → 2.0.0-alpha.13
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 +268 -16
- package/README.md +2 -2
- package/lib/cjs/hierarchies/HierarchyNode.d.ts +13 -11
- package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNode.js +18 -0
- package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeIdentifier.d.ts +2 -0
- package/lib/cjs/hierarchies/HierarchyNodeIdentifier.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeIdentifier.js +23 -6
- package/lib/cjs/hierarchies/HierarchyNodeIdentifier.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.d.ts +5 -4
- package/lib/cjs/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts +3 -3
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchySearch.d.ts +184 -78
- package/lib/cjs/hierarchies/HierarchySearch.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchySearch.js +305 -113
- package/lib/cjs/hierarchies/HierarchySearch.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts +2 -2
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyNode.d.ts +3 -3
- package/lib/cjs/hierarchies/imodel/IModelHierarchyNode.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyNode.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts +9 -4
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js +25 -16
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts +4 -4
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js +12 -9
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts +3 -3
- package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts +2 -2
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js +31 -55
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts +2 -2
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js +1 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js +4 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.d.ts +2 -2
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Sorting.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Sorting.js.map +1 -1
- package/lib/cjs/presentation-hierarchies.d.ts +1 -1
- package/lib/cjs/presentation-hierarchies.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies.js +2 -1
- package/lib/cjs/presentation-hierarchies.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.d.ts +13 -11
- package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.js +18 -0
- package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeIdentifier.d.ts +2 -0
- package/lib/esm/hierarchies/HierarchyNodeIdentifier.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeIdentifier.js +23 -6
- package/lib/esm/hierarchies/HierarchyNodeIdentifier.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.d.ts +5 -4
- package/lib/esm/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.d.ts +3 -3
- package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/HierarchySearch.d.ts +184 -78
- package/lib/esm/hierarchies/HierarchySearch.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchySearch.js +304 -111
- package/lib/esm/hierarchies/HierarchySearch.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts +2 -2
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyNode.d.ts +3 -3
- package/lib/esm/hierarchies/imodel/IModelHierarchyNode.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyNode.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts +9 -4
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js +26 -17
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts +4 -4
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js +13 -10
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
- package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts +3 -3
- package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.js.map +1 -1
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts +2 -2
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js +32 -56
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -1
- package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts +2 -2
- package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js +2 -2
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js +4 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/ReduceToMergeMap.d.ts +2 -2
- package/lib/esm/hierarchies/internal/operators/ReduceToMergeMap.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/ReduceToMergeMap.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/Sorting.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/Sorting.js.map +1 -1
- package/lib/esm/presentation-hierarchies.d.ts +1 -1
- package/lib/esm/presentation-hierarchies.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies.js +1 -1
- package/lib/esm/presentation-hierarchies.js.map +1 -1
- package/package.json +8 -8
|
@@ -2,38 +2,11 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { firstValueFrom, from, map, reduce } from "rxjs";
|
|
6
|
+
import { Dictionary } from "@itwin/core-bentley";
|
|
5
7
|
import { HierarchyNodeIdentifier } from "./HierarchyNodeIdentifier.js";
|
|
6
8
|
import { HierarchyNodeKey } from "./HierarchyNodeKey.js";
|
|
7
|
-
|
|
8
|
-
(function (HierarchySearchPathOptions) {
|
|
9
|
-
function mergeRevealOptions(lhs, rhs) {
|
|
10
|
-
if (rhs === true || lhs === true) {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
if (!rhs || !lhs) {
|
|
14
|
-
return !!rhs ? rhs : lhs;
|
|
15
|
-
}
|
|
16
|
-
const lhsDepth = "depthInPath" in lhs ? lhs.depthInPath : lhs.depthInHierarchy;
|
|
17
|
-
const rhsDepth = "depthInPath" in rhs ? rhs.depthInPath : rhs.depthInHierarchy;
|
|
18
|
-
const isLhsDepthBasedOnPath = "depthInPath" in lhs;
|
|
19
|
-
const isRhsDepthBasedOnPath = "depthInPath" in rhs;
|
|
20
|
-
if (isLhsDepthBasedOnPath) {
|
|
21
|
-
if (isRhsDepthBasedOnPath) {
|
|
22
|
-
return lhsDepth > rhsDepth ? lhs : rhs;
|
|
23
|
-
}
|
|
24
|
-
return lhs;
|
|
25
|
-
}
|
|
26
|
-
if (isRhsDepthBasedOnPath) {
|
|
27
|
-
return rhs;
|
|
28
|
-
}
|
|
29
|
-
return lhsDepth > rhsDepth ? lhs : rhs;
|
|
30
|
-
}
|
|
31
|
-
HierarchySearchPathOptions.mergeRevealOptions = mergeRevealOptions;
|
|
32
|
-
function mergeAutoExpandOption(lhs, rhs) {
|
|
33
|
-
return lhs || rhs ? true : undefined;
|
|
34
|
-
}
|
|
35
|
-
HierarchySearchPathOptions.mergeAutoExpandOption = mergeAutoExpandOption;
|
|
36
|
-
})(HierarchySearchPathOptions || (HierarchySearchPathOptions = {}));
|
|
9
|
+
import { releaseMainThreadOnItemsCount } from "./internal/operators/ReleaseMainThread.js";
|
|
37
10
|
/** @public */
|
|
38
11
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
39
12
|
export var HierarchySearchPath;
|
|
@@ -57,14 +30,14 @@ export var HierarchySearchPath;
|
|
|
57
30
|
* - else if only one of the inputs is an object, return it,
|
|
58
31
|
* - else if both inputs are falsy, return `false` or `undefined`,
|
|
59
32
|
* - else:
|
|
60
|
-
* - if only one of the inputs has `
|
|
61
|
-
* - else
|
|
33
|
+
* - if only one of the inputs has `groupingLevel` set, return that one,
|
|
34
|
+
* - else compare by matching reveal type (`groupingLevel` or `depthInPath`) and return the deeper one.
|
|
62
35
|
*
|
|
63
36
|
* @public
|
|
64
37
|
*/
|
|
65
38
|
function mergeOptions(lhs, rhs) {
|
|
66
|
-
const reveal =
|
|
67
|
-
const autoExpand =
|
|
39
|
+
const reveal = mergeRevealOptions(lhs?.reveal, rhs?.reveal);
|
|
40
|
+
const autoExpand = mergeAutoExpandOption(lhs?.autoExpand, rhs?.autoExpand);
|
|
68
41
|
return reveal || autoExpand
|
|
69
42
|
? {
|
|
70
43
|
...(reveal !== undefined ? { reveal } : undefined),
|
|
@@ -73,7 +46,254 @@ export var HierarchySearchPath;
|
|
|
73
46
|
: undefined;
|
|
74
47
|
}
|
|
75
48
|
HierarchySearchPath.mergeOptions = mergeOptions;
|
|
49
|
+
function mergeRevealOptions(lhs, rhs) {
|
|
50
|
+
if (rhs === true || lhs === true) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (!rhs || !lhs) {
|
|
54
|
+
return !!rhs ? rhs : lhs;
|
|
55
|
+
}
|
|
56
|
+
if ("groupingLevel" in lhs) {
|
|
57
|
+
if ("groupingLevel" in rhs) {
|
|
58
|
+
return lhs.groupingLevel > rhs.groupingLevel ? lhs : rhs;
|
|
59
|
+
}
|
|
60
|
+
return lhs;
|
|
61
|
+
}
|
|
62
|
+
else if ("groupingLevel" in rhs) {
|
|
63
|
+
return rhs;
|
|
64
|
+
}
|
|
65
|
+
return lhs.depthInPath > rhs.depthInPath ? lhs : rhs;
|
|
66
|
+
}
|
|
67
|
+
function mergeAutoExpandOption(lhs, rhs) {
|
|
68
|
+
return lhs || rhs ? true : undefined;
|
|
69
|
+
}
|
|
76
70
|
})(HierarchySearchPath || (HierarchySearchPath = {}));
|
|
71
|
+
/** @public */
|
|
72
|
+
export var HierarchySearchTree;
|
|
73
|
+
(function (HierarchySearchTree) {
|
|
74
|
+
/**
|
|
75
|
+
* Create a `HierarchySearchTree` builder utility that accepts hierarchy search paths or search trees one by one and builds
|
|
76
|
+
* a `HierarchySearchTree` structure based on them.
|
|
77
|
+
*
|
|
78
|
+
* Usage example:
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const builder = HierarchySearchTree.createBuilder();
|
|
82
|
+
* for (const path of searchPaths) {
|
|
83
|
+
* builder.accept({ path });
|
|
84
|
+
* }
|
|
85
|
+
* const searchTree = builder.getTree();
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
function createBuilder() {
|
|
91
|
+
var _a;
|
|
92
|
+
return new (class Impl {
|
|
93
|
+
#rootsDictionary = new Dictionary(HierarchyNodeIdentifier.compare);
|
|
94
|
+
static #mapDictionaryToTree(dictionary) {
|
|
95
|
+
const list = [];
|
|
96
|
+
for (const { children, extras: _, ...entry } of dictionary.values()) {
|
|
97
|
+
list.push({ ...entry, ...(children ? { children: Impl.#mapDictionaryToTree(children) } : undefined) });
|
|
98
|
+
}
|
|
99
|
+
return list;
|
|
100
|
+
}
|
|
101
|
+
static #assignAutoExpandOptionsBasedOnReveal(treePath, revealOption) {
|
|
102
|
+
if (revealOption === true) {
|
|
103
|
+
Impl.#assignOptionsOnTreePath({
|
|
104
|
+
treePath,
|
|
105
|
+
targetEntryIndex: treePath.length - 1,
|
|
106
|
+
getEntryOptions: (index, targetEntryIndex) => {
|
|
107
|
+
if (index === targetEntryIndex) {
|
|
108
|
+
// auto-expand all grouping nodes of the revealed node
|
|
109
|
+
return { autoExpand: { groupingLevel: Number.MAX_SAFE_INTEGER } };
|
|
110
|
+
}
|
|
111
|
+
// auto-expand all parent nodes
|
|
112
|
+
return { autoExpand: true };
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else if (revealOption && "groupingLevel" in revealOption) {
|
|
117
|
+
Impl.#assignOptionsOnTreePath({
|
|
118
|
+
treePath,
|
|
119
|
+
targetEntryIndex: treePath.length - 1,
|
|
120
|
+
getEntryOptions: (index, targetEntryIndex) => {
|
|
121
|
+
if (index === targetEntryIndex) {
|
|
122
|
+
// the last entry should have `autoExpand` with `groupingLevel` set to the value based on `reveal.groupingLevel`
|
|
123
|
+
return { autoExpand: { groupingLevel: Math.max(revealOption.groupingLevel - 1, 0) } };
|
|
124
|
+
}
|
|
125
|
+
// auto-expand all parent nodes
|
|
126
|
+
return { autoExpand: true };
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else if (revealOption && "depthInPath" in revealOption) {
|
|
131
|
+
Impl.#assignOptionsOnTreePath({
|
|
132
|
+
treePath,
|
|
133
|
+
targetEntryIndex: Math.min(revealOption.depthInPath, treePath.length - 1),
|
|
134
|
+
getEntryOptions: (index, targetEntryIndex) => {
|
|
135
|
+
if (index === targetEntryIndex) {
|
|
136
|
+
// auto-expand all grouping nodes of the revealed node
|
|
137
|
+
return { autoExpand: { groupingLevel: Number.MAX_SAFE_INTEGER } };
|
|
138
|
+
}
|
|
139
|
+
// auto-expand all parent nodes
|
|
140
|
+
return { autoExpand: true };
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
static #assignOptionsOnTreePath({ treePath, targetEntryIndex, getEntryOptions, }) {
|
|
146
|
+
// set all parent entries to auto-expand
|
|
147
|
+
for (let i = 0; i <= targetEntryIndex; i++) {
|
|
148
|
+
const options = mergeOptions(treePath[i].options, getEntryOptions(i, targetEntryIndex));
|
|
149
|
+
if (options) {
|
|
150
|
+
treePath[i].options = options;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
#acceptNode({ parentEntries, level, node, handler, }) {
|
|
155
|
+
let entry = level.get(node.identifier);
|
|
156
|
+
if (!entry) {
|
|
157
|
+
if (handler?.onNewEntry && !handler.onNewEntry({ parentEntries, inputEntry: node })) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
entry = {
|
|
161
|
+
identifier: node.identifier,
|
|
162
|
+
children: node.hasChildren ? new Dictionary(HierarchyNodeIdentifier.compare) : undefined,
|
|
163
|
+
extras: {},
|
|
164
|
+
};
|
|
165
|
+
level.set(node.identifier, entry);
|
|
166
|
+
}
|
|
167
|
+
const isNodeSearchTarget = node.isTarget || !node.hasChildren;
|
|
168
|
+
if (isNodeSearchTarget && entry.children) {
|
|
169
|
+
entry.isTarget = true;
|
|
170
|
+
}
|
|
171
|
+
if (!entry.children && node.hasChildren) {
|
|
172
|
+
// Existing leaf nodes are implied targets. Preserve that status when adding children.
|
|
173
|
+
entry.isTarget = true;
|
|
174
|
+
entry.children = new Dictionary(HierarchyNodeIdentifier.compare);
|
|
175
|
+
}
|
|
176
|
+
handler?.onEntryHandled?.({ parentEntries, treeEntry: entry, inputEntry: node });
|
|
177
|
+
return entry;
|
|
178
|
+
}
|
|
179
|
+
#acceptPath({ path, handler }) {
|
|
180
|
+
const normalized = HierarchySearchPath.normalize(path);
|
|
181
|
+
const treePath = [];
|
|
182
|
+
let currentLevel = this.#rootsDictionary;
|
|
183
|
+
for (let i = 0; i < normalized.path.length; i++) {
|
|
184
|
+
const identifier = normalized.path[i];
|
|
185
|
+
const acceptedNode = this.#acceptNode({
|
|
186
|
+
parentEntries: treePath,
|
|
187
|
+
node: { identifier, hasChildren: i < normalized.path.length - 1 },
|
|
188
|
+
level: currentLevel,
|
|
189
|
+
handler,
|
|
190
|
+
});
|
|
191
|
+
if (!acceptedNode) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
treePath.push(acceptedNode);
|
|
195
|
+
if (!acceptedNode.children) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
currentLevel = acceptedNode.children;
|
|
199
|
+
}
|
|
200
|
+
if (treePath.length === 0) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// handle auto-expand
|
|
204
|
+
const lastNode = treePath[treePath.length - 1];
|
|
205
|
+
if (normalized.options?.autoExpand) {
|
|
206
|
+
(lastNode.options ??= {}).autoExpand = true;
|
|
207
|
+
}
|
|
208
|
+
// handle auto-reveal
|
|
209
|
+
Impl.#assignAutoExpandOptionsBasedOnReveal(treePath, normalized.options?.reveal);
|
|
210
|
+
}
|
|
211
|
+
#acceptTree({ tree, handler }) {
|
|
212
|
+
const acceptTreeNode = (parentEntries, parentInputs, level, node) => {
|
|
213
|
+
const acceptedNode = this.#acceptNode({
|
|
214
|
+
parentEntries,
|
|
215
|
+
node: { ...node, hasChildren: node.children !== undefined },
|
|
216
|
+
level,
|
|
217
|
+
handler,
|
|
218
|
+
});
|
|
219
|
+
if (!acceptedNode) {
|
|
220
|
+
// It was decided to reject this node and its children, if any
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const treePath = [...parentEntries, acceptedNode];
|
|
224
|
+
const inputsPath = [...parentInputs, node];
|
|
225
|
+
if (!node.children || node.isTarget) {
|
|
226
|
+
// Found an effective search target - merge options from its path
|
|
227
|
+
Impl.#assignOptionsOnTreePath({
|
|
228
|
+
treePath,
|
|
229
|
+
targetEntryIndex: treePath.length - 1,
|
|
230
|
+
getEntryOptions: (index) => inputsPath[index].options,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
const currentLevel = acceptedNode.children;
|
|
234
|
+
if (currentLevel) {
|
|
235
|
+
node.children?.forEach((child) => acceptTreeNode(treePath, inputsPath, currentLevel, child));
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
acceptTreeNode([], [], this.#rootsDictionary, tree);
|
|
239
|
+
}
|
|
240
|
+
accept(props) {
|
|
241
|
+
if ("path" in props) {
|
|
242
|
+
this.#acceptPath(props);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
this.#acceptTree(props);
|
|
246
|
+
}
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
getTree() {
|
|
250
|
+
return Impl.#mapDictionaryToTree(this.#rootsDictionary);
|
|
251
|
+
}
|
|
252
|
+
})();
|
|
253
|
+
}
|
|
254
|
+
HierarchySearchTree.createBuilder = createBuilder;
|
|
255
|
+
/**
|
|
256
|
+
* Builds a list of `HierarchySearchTree` nodes from an iterable of search paths. Shared
|
|
257
|
+
* path prefixes are merged so that each unique hierarchy node identifier appears only once
|
|
258
|
+
* per level. The resulting trees carry `isTarget`, `options`, and `children` attributes
|
|
259
|
+
* derived from the paths and their options (`autoExpand`, `reveal`).
|
|
260
|
+
*
|
|
261
|
+
* @public
|
|
262
|
+
*/
|
|
263
|
+
async function createFromPathsList(paths) {
|
|
264
|
+
return firstValueFrom(from(paths).pipe(releaseMainThreadOnItemsCount(1000), reduce((builder, path) => builder.accept({ path }), createBuilder()), map((builder) => builder.getTree())));
|
|
265
|
+
}
|
|
266
|
+
HierarchySearchTree.createFromPathsList = createFromPathsList;
|
|
267
|
+
/**
|
|
268
|
+
* Merges two `HierarchySearchTree` option objects. For the `autoExpand` attribute,
|
|
269
|
+
* `true` takes precedence over `{ groupingLevel }`, and when both sides are
|
|
270
|
+
* `{ groupingLevel }` objects the larger value wins.
|
|
271
|
+
* @public
|
|
272
|
+
*/
|
|
273
|
+
function mergeOptions(lhs, rhs) {
|
|
274
|
+
if (!lhs) {
|
|
275
|
+
return rhs;
|
|
276
|
+
}
|
|
277
|
+
if (!rhs) {
|
|
278
|
+
return lhs;
|
|
279
|
+
}
|
|
280
|
+
const autoExpand = mergeSearchTreeAutoExpandOption(lhs.autoExpand, rhs.autoExpand);
|
|
281
|
+
const options = {
|
|
282
|
+
...(autoExpand ? { autoExpand } : undefined),
|
|
283
|
+
};
|
|
284
|
+
return Object.keys(options).length > 0 ? options : undefined;
|
|
285
|
+
}
|
|
286
|
+
HierarchySearchTree.mergeOptions = mergeOptions;
|
|
287
|
+
function mergeSearchTreeAutoExpandOption(lhs, rhs) {
|
|
288
|
+
if (!lhs) {
|
|
289
|
+
return rhs;
|
|
290
|
+
}
|
|
291
|
+
if (!rhs) {
|
|
292
|
+
return lhs;
|
|
293
|
+
}
|
|
294
|
+
return lhs === true || rhs === true ? true : { groupingLevel: Math.max(lhs.groupingLevel, rhs.groupingLevel) };
|
|
295
|
+
}
|
|
296
|
+
})(HierarchySearchTree || (HierarchySearchTree = {}));
|
|
77
297
|
function extractSearchPropsInternal(rootLevelSearchProps, parentNode) {
|
|
78
298
|
if (!parentNode) {
|
|
79
299
|
return rootLevelSearchProps ? { childrenTargetPaths: rootLevelSearchProps, hasSearchTargetAncestor: false } : undefined;
|
|
@@ -94,41 +314,37 @@ export function createHierarchySearchHelper(rootLevelSearchProps, parentNode) {
|
|
|
94
314
|
const searchProps = extractSearchPropsInternal(rootLevelSearchProps, parentNode);
|
|
95
315
|
const hasSearch = !!searchProps;
|
|
96
316
|
function saveSearchPropsFromPathsIntoReducer(extractionProps) {
|
|
97
|
-
// Passes down matching
|
|
98
|
-
// It uses `nodeKey`, `pathMatcher` or `asyncPathMatcher` to check if `HierarchyNodeIdentifier`
|
|
317
|
+
// Passes down matching hierarchy search trees to the reducer.
|
|
318
|
+
// It uses `nodeKey`, `pathMatcher` or `asyncPathMatcher` to check if `HierarchyNodeIdentifier` in the search tree item's identifier matches the node
|
|
99
319
|
// and if it does, the path is passed down to the reducer.
|
|
100
|
-
// This function returns a promise only if asyncPathMatcher returns a promise.
|
|
320
|
+
// This function returns a promise only if `asyncPathMatcher` returns a promise.
|
|
101
321
|
if (!searchProps?.childrenTargetPaths) {
|
|
102
322
|
return;
|
|
103
323
|
}
|
|
104
|
-
const
|
|
105
|
-
for (const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
(HierarchyNodeKey.isInstances(extractionProps.nodeKey) &&
|
|
114
|
-
extractionProps.nodeKey.instanceKeys.some((ik) => HierarchyNodeIdentifier.equal(normalizedPath.path[0], ik)))) {
|
|
115
|
-
extractionProps.pathsReducer.accept(normalizedPath);
|
|
324
|
+
const matchedTreePromises = new Array();
|
|
325
|
+
for (const childrenSearchTree of searchProps.childrenTargetPaths) {
|
|
326
|
+
if ("asyncPathMatcher" in extractionProps) {
|
|
327
|
+
const matchesPossiblyPromise = extractionProps.asyncPathMatcher(childrenSearchTree.identifier);
|
|
328
|
+
if (matchesPossiblyPromise instanceof Promise) {
|
|
329
|
+
matchedTreePromises.push(matchesPossiblyPromise.then((matches) => (matches ? childrenSearchTree : undefined)));
|
|
330
|
+
}
|
|
331
|
+
else if (matchesPossiblyPromise) {
|
|
332
|
+
extractionProps.pathsReducer.accept(childrenSearchTree);
|
|
116
333
|
}
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
const matchesPossiblyPromise = "pathMatcher" in extractionProps ? extractionProps.pathMatcher(normalizedPath.path[0]) : extractionProps.asyncPathMatcher(normalizedPath.path[0]);
|
|
120
|
-
if (matchesPossiblyPromise instanceof Promise) {
|
|
121
|
-
matchedPathPromises.push(matchesPossiblyPromise.then((matches) => (matches ? normalizedPath : undefined)));
|
|
122
|
-
continue;
|
|
123
334
|
}
|
|
124
|
-
|
|
125
|
-
extractionProps
|
|
335
|
+
else {
|
|
336
|
+
const matches = "pathMatcher" in extractionProps
|
|
337
|
+
? extractionProps.pathMatcher(childrenSearchTree.identifier)
|
|
338
|
+
: nodeKeyMatchesIdentifier(extractionProps.nodeKey, childrenSearchTree.identifier);
|
|
339
|
+
if (matches) {
|
|
340
|
+
extractionProps.pathsReducer.accept(childrenSearchTree);
|
|
341
|
+
}
|
|
126
342
|
}
|
|
127
343
|
}
|
|
128
|
-
if (
|
|
344
|
+
if (matchedTreePromises.length === 0) {
|
|
129
345
|
return;
|
|
130
346
|
}
|
|
131
|
-
return Promise.all(
|
|
347
|
+
return Promise.all(matchedTreePromises).then((matchedTrees) => matchedTrees.forEach((matchedTree) => matchedTree && extractionProps.pathsReducer.accept(matchedTree)));
|
|
132
348
|
}
|
|
133
349
|
function createChildNodeProps(props) {
|
|
134
350
|
if (!hasSearch) {
|
|
@@ -136,15 +352,15 @@ export function createHierarchySearchHelper(rootLevelSearchProps, parentNode) {
|
|
|
136
352
|
}
|
|
137
353
|
const reducer = new MatchingSearchPathsReducer(searchProps.hasSearchTargetAncestor);
|
|
138
354
|
if ("asyncPathMatcher" in props) {
|
|
139
|
-
const extractResult = saveSearchPropsFromPathsIntoReducer({ pathsReducer: reducer, asyncPathMatcher: props.asyncPathMatcher });
|
|
355
|
+
const extractResult = saveSearchPropsFromPathsIntoReducer({ pathsReducer: reducer, nodeKey: props.nodeKey, asyncPathMatcher: props.asyncPathMatcher });
|
|
140
356
|
if (extractResult instanceof Promise) {
|
|
141
|
-
return extractResult.then(() => reducer.
|
|
357
|
+
return extractResult.then(() => reducer.aggregatedOptions);
|
|
142
358
|
}
|
|
143
359
|
}
|
|
144
360
|
else {
|
|
145
|
-
saveSearchPropsFromPathsIntoReducer({
|
|
361
|
+
saveSearchPropsFromPathsIntoReducer({ pathsReducer: reducer, ...props });
|
|
146
362
|
}
|
|
147
|
-
return reducer.
|
|
363
|
+
return reducer.aggregatedOptions;
|
|
148
364
|
}
|
|
149
365
|
return {
|
|
150
366
|
/** Returns a flag indicating if the hierarchy level is filtered. */
|
|
@@ -164,10 +380,7 @@ export function createHierarchySearchHelper(rootLevelSearchProps, parentNode) {
|
|
|
164
380
|
if (!searchProps?.childrenTargetPaths) {
|
|
165
381
|
return undefined;
|
|
166
382
|
}
|
|
167
|
-
return searchProps.childrenTargetPaths
|
|
168
|
-
.map(HierarchySearchPath.normalize)
|
|
169
|
-
.filter(({ path }) => path.length > 0)
|
|
170
|
-
.map(({ path }) => path[0]);
|
|
383
|
+
return searchProps.childrenTargetPaths.map(({ identifier }) => identifier);
|
|
171
384
|
},
|
|
172
385
|
/**
|
|
173
386
|
* When a hierarchy node is created for a filtered hierarchy level, it needs some attributes (e.g. `search`
|
|
@@ -179,13 +392,16 @@ export function createHierarchySearchHelper(rootLevelSearchProps, parentNode) {
|
|
|
179
392
|
* `nodeKey` prop can be used to check the whole identifier.
|
|
180
393
|
*
|
|
181
394
|
* There are multiple overloads of `createChildNodeProps`: depending on props type it returns different values:
|
|
182
|
-
* - `
|
|
183
|
-
* - `
|
|
184
|
-
* - props have `asyncPathMatcher` - returns either Promise or the regular return value based on whether or not `asyncPathMatcher` returns a promise.
|
|
395
|
+
* - `asyncPathMatcher` is provided - returns either Promise or the regular return value based on whether or not `asyncPathMatcher` returns a `Promise`.
|
|
396
|
+
* - `pathMatcher` or only `nodeKey` is provided - returns undefined **or** `search` and `autoExpand` prop from `HierarchyNode`;
|
|
185
397
|
*/
|
|
186
398
|
createChildNodeProps,
|
|
187
399
|
};
|
|
188
400
|
}
|
|
401
|
+
function nodeKeyMatchesIdentifier(nodeKey, identifier) {
|
|
402
|
+
return ((HierarchyNodeKey.isGeneric(nodeKey) && HierarchyNodeIdentifier.equal(identifier, nodeKey)) ||
|
|
403
|
+
(HierarchyNodeKey.isInstances(nodeKey) && nodeKey.instanceKeys.some((ik) => HierarchyNodeIdentifier.equal(identifier, ik))));
|
|
404
|
+
}
|
|
189
405
|
/**
|
|
190
406
|
* Extracts information from search paths and later returns `search` and `autoExpand` values from `HierarchyNode`.
|
|
191
407
|
*
|
|
@@ -199,56 +415,33 @@ class MatchingSearchPathsReducer {
|
|
|
199
415
|
_hasSearchTargetAncestor;
|
|
200
416
|
_childrenTargetPaths = new Array();
|
|
201
417
|
_isSearchTarget = false;
|
|
202
|
-
|
|
203
|
-
_revealOption = false;
|
|
418
|
+
_options = undefined;
|
|
204
419
|
constructor(_hasSearchTargetAncestor) {
|
|
205
420
|
this._hasSearchTargetAncestor = _hasSearchTargetAncestor;
|
|
206
421
|
}
|
|
207
|
-
accept(
|
|
208
|
-
|
|
209
|
-
if (path.length === 1) {
|
|
422
|
+
accept(tree) {
|
|
423
|
+
if (tree.isTarget || tree.children === undefined) {
|
|
210
424
|
this._isSearchTarget = true;
|
|
211
|
-
this._searchTargetOptions = HierarchySearchPath.mergeOptions(this._searchTargetOptions, options);
|
|
212
425
|
}
|
|
213
|
-
|
|
214
|
-
this._childrenTargetPaths.push(
|
|
215
|
-
this._revealOption = HierarchySearchPathOptions.mergeRevealOptions(options?.reveal, this._revealOption);
|
|
426
|
+
if (tree.children && tree.children.length > 0) {
|
|
427
|
+
this._childrenTargetPaths.push(...tree.children);
|
|
216
428
|
}
|
|
429
|
+
this._options = HierarchySearchTree.mergeOptions(this._options, tree.options);
|
|
217
430
|
}
|
|
218
|
-
|
|
431
|
+
get aggregatedOptions() {
|
|
432
|
+
const search = this._hasSearchTargetAncestor || this._isSearchTarget || this._childrenTargetPaths.length > 0 || this._options
|
|
433
|
+
? {
|
|
434
|
+
...(this._hasSearchTargetAncestor ? { hasSearchTargetAncestor: true } : undefined),
|
|
435
|
+
...(this._isSearchTarget ? { isSearchTarget: true } : undefined),
|
|
436
|
+
...(this._childrenTargetPaths.length > 0 ? { childrenTargetPaths: this._childrenTargetPaths } : undefined),
|
|
437
|
+
...(this._options ? { options: this._options } : undefined),
|
|
438
|
+
}
|
|
439
|
+
: undefined;
|
|
440
|
+
const autoExpand = this._options?.autoExpand === true;
|
|
219
441
|
return {
|
|
220
|
-
...(
|
|
221
|
-
|
|
222
|
-
search: {
|
|
223
|
-
...(this._hasSearchTargetAncestor ? { hasSearchTargetAncestor: true } : undefined),
|
|
224
|
-
...(this._isSearchTarget ? { isSearchTarget: true, searchTargetOptions: this._searchTargetOptions } : undefined),
|
|
225
|
-
...(this._childrenTargetPaths.length > 0 ? { childrenTargetPaths: this._childrenTargetPaths } : undefined),
|
|
226
|
-
},
|
|
227
|
-
}
|
|
228
|
-
: undefined),
|
|
229
|
-
...(parentKeys &&
|
|
230
|
-
(shouldAutoExpandBasedOnReveal({
|
|
231
|
-
reveal: this._revealOption,
|
|
232
|
-
nodePositionInHierarchy: parentKeys.length,
|
|
233
|
-
nodePositionInPath: parentKeys.filter((key) => !HierarchyNodeKey.isGrouping(key)).length,
|
|
234
|
-
}) ||
|
|
235
|
-
!!this._searchTargetOptions?.autoExpand)
|
|
236
|
-
? { autoExpand: true }
|
|
237
|
-
: undefined),
|
|
442
|
+
...(search ? { search } : undefined),
|
|
443
|
+
...(autoExpand ? { autoExpand } : undefined),
|
|
238
444
|
};
|
|
239
445
|
}
|
|
240
446
|
}
|
|
241
|
-
/** @internal */
|
|
242
|
-
export function shouldAutoExpandBasedOnReveal({ reveal, nodePositionInPath, nodePositionInHierarchy, }) {
|
|
243
|
-
if (!reveal) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
if (reveal === true) {
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
if ("depthInHierarchy" in reveal) {
|
|
250
|
-
return nodePositionInHierarchy < reveal.depthInHierarchy;
|
|
251
|
-
}
|
|
252
|
-
return nodePositionInPath < reveal.depthInPath;
|
|
253
|
-
}
|
|
254
447
|
//# sourceMappingURL=HierarchySearch.js.map
|