@itwin/presentation-hierarchies 2.0.0-alpha.5 → 2.0.0-alpha.7
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 +62 -0
- package/README.md +3 -3
- package/lib/cjs/hierarchies/HierarchyMerge.d.ts +19 -0
- package/lib/cjs/hierarchies/HierarchyMerge.d.ts.map +1 -0
- package/lib/cjs/hierarchies/HierarchyMerge.js +43 -0
- package/lib/cjs/hierarchies/HierarchyMerge.js.map +1 -0
- package/lib/cjs/hierarchies/HierarchyNode.d.ts +14 -24
- package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNode.js +1 -21
- package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.js +8 -8
- package/lib/cjs/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts +11 -29
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.js +0 -37
- package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchySearch.d.ts +167 -0
- package/lib/cjs/hierarchies/HierarchySearch.d.ts.map +1 -0
- package/lib/cjs/hierarchies/HierarchySearch.js +261 -0
- package/lib/cjs/hierarchies/HierarchySearch.js.map +1 -0
- package/lib/cjs/hierarchies/imodel/HierarchyCache.js +3 -3
- package/lib/cjs/hierarchies/imodel/HierarchyCache.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js +155 -64
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/{FilteringHierarchyDefinition.d.ts → SearchHierarchyDefinition.d.ts} +12 -10
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
- package/lib/cjs/hierarchies/imodel/{FilteringHierarchyDefinition.js → SearchHierarchyDefinition.js} +88 -73
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js +8 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.d.ts +3 -0
- package/lib/cjs/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.js +12 -1
- package/lib/cjs/hierarchies/internal/Common.js.map +1 -1
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js +2 -1
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -1
- package/lib/cjs/presentation-hierarchies.d.ts +4 -3
- package/lib/cjs/presentation-hierarchies.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies.js +7 -7
- package/lib/cjs/presentation-hierarchies.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyMerge.d.ts +19 -0
- package/lib/esm/hierarchies/HierarchyMerge.d.ts.map +1 -0
- package/lib/esm/hierarchies/HierarchyMerge.js +40 -0
- package/lib/esm/hierarchies/HierarchyMerge.js.map +1 -0
- package/lib/esm/hierarchies/HierarchyNode.d.ts +14 -24
- package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.js +0 -20
- package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.js +9 -9
- package/lib/esm/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.d.ts +11 -29
- package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.js +1 -36
- package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/HierarchySearch.d.ts +167 -0
- package/lib/esm/hierarchies/HierarchySearch.d.ts.map +1 -0
- package/lib/esm/hierarchies/HierarchySearch.js +256 -0
- package/lib/esm/hierarchies/HierarchySearch.js.map +1 -0
- package/lib/esm/hierarchies/imodel/HierarchyCache.js +3 -3
- package/lib/esm/hierarchies/imodel/HierarchyCache.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js +157 -67
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/imodel/{FilteringHierarchyDefinition.d.ts → SearchHierarchyDefinition.d.ts} +12 -10
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
- package/lib/esm/hierarchies/imodel/{FilteringHierarchyDefinition.js → SearchHierarchyDefinition.js} +86 -71
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
- package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js +8 -1
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/esm/hierarchies/internal/Common.d.ts +3 -0
- package/lib/esm/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/Common.js +11 -1
- package/lib/esm/hierarchies/internal/Common.js.map +1 -1
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js +3 -2
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -1
- package/lib/esm/presentation-hierarchies.d.ts +4 -3
- package/lib/esm/presentation-hierarchies.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies.js +3 -3
- package/lib/esm/presentation-hierarchies.js.map +1 -1
- package/package.json +7 -7
- package/lib/cjs/hierarchies/HierarchyFiltering.d.ts +0 -136
- package/lib/cjs/hierarchies/HierarchyFiltering.d.ts.map +0 -1
- package/lib/cjs/hierarchies/HierarchyFiltering.js +0 -249
- package/lib/cjs/hierarchies/HierarchyFiltering.js.map +0 -1
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
- package/lib/esm/hierarchies/HierarchyFiltering.d.ts +0 -136
- package/lib/esm/hierarchies/HierarchyFiltering.d.ts.map +0 -1
- package/lib/esm/hierarchies/HierarchyFiltering.js +0 -244
- package/lib/esm/hierarchies/HierarchyFiltering.js.map +0 -1
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
|
@@ -4,41 +4,4 @@
|
|
|
4
4
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.mergeProviders = mergeProviders;
|
|
8
|
-
require("./internal/DisposePolyfill.js");
|
|
9
|
-
const rxjs_1 = require("rxjs");
|
|
10
|
-
const core_bentley_1 = require("@itwin/core-bentley");
|
|
11
|
-
const Common_js_1 = require("./internal/Common.js");
|
|
12
|
-
const EachValueFrom_js_1 = require("./internal/EachValueFrom.js");
|
|
13
|
-
const Sorting_js_1 = require("./internal/operators/Sorting.js");
|
|
14
|
-
/**
|
|
15
|
-
* Creates a single, merged, hierarchy provider from multiple given providers.
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
function mergeProviders({ providers }) {
|
|
19
|
-
const hierarchyChanged = new core_bentley_1.BeEvent();
|
|
20
|
-
providers.forEach((p) => {
|
|
21
|
-
p.hierarchyChanged.addListener(() => hierarchyChanged.raiseEvent());
|
|
22
|
-
});
|
|
23
|
-
const dispose = () => {
|
|
24
|
-
hierarchyChanged.clear();
|
|
25
|
-
providers.forEach((p) => (0, Common_js_1.safeDispose)(p));
|
|
26
|
-
};
|
|
27
|
-
return {
|
|
28
|
-
hierarchyChanged,
|
|
29
|
-
getNodes: (props) => (0, EachValueFrom_js_1.eachValueFrom)((0, rxjs_1.from)(providers).pipe((0, rxjs_1.mergeMap)((provider) => (0, rxjs_1.from)(provider.getNodes(props)).pipe((0, rxjs_1.mergeMap)((node) => {
|
|
30
|
-
if (node.children) {
|
|
31
|
-
return (0, rxjs_1.of)(node);
|
|
32
|
-
}
|
|
33
|
-
// each provider only considers its own data when determining node's children - in case it says
|
|
34
|
-
// the node has no children, we have to check against the other providers too
|
|
35
|
-
return (0, rxjs_1.from)(providers).pipe((0, rxjs_1.filter)((p) => p !== provider), (0, rxjs_1.mergeMap)((p) => p.getNodes({ parentNode: node })), (0, rxjs_1.map)(() => true), (0, rxjs_1.first)(undefined, false), (0, rxjs_1.map)((hasChildren) => ({ ...node, children: hasChildren })));
|
|
36
|
-
}))), Sorting_js_1.sortNodesByLabelOperator)),
|
|
37
|
-
getNodeInstanceKeys: (props) => (0, EachValueFrom_js_1.eachValueFrom)((0, rxjs_1.from)(providers).pipe((0, rxjs_1.mergeMap)((p) => p.getNodeInstanceKeys(props)))),
|
|
38
|
-
setFormatter: (formatter) => providers.forEach((p) => p.setFormatter(formatter)),
|
|
39
|
-
setHierarchyFilter: (props) => providers.forEach((p) => p.setHierarchyFilter(props)),
|
|
40
|
-
[Symbol.dispose]: dispose,
|
|
41
|
-
dispose,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
7
|
//# sourceMappingURL=HierarchyProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HierarchyProvider.js","sourceRoot":"","sources":["../../../src/hierarchies/HierarchyProvider.ts"],"names":[],"mappings":";AAAA;;;gGAGgG
|
|
1
|
+
{"version":3,"file":"HierarchyProvider.js","sourceRoot":"","sources":["../../../src/hierarchies/HierarchyProvider.ts"],"names":[],"mappings":";AAAA;;;gGAGgG","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GenericInstanceFilter } from \"@itwin/core-common\";\nimport { Event, InstanceKey, IPrimitiveValueFormatter, Props } from \"@itwin/presentation-shared\";\nimport { HierarchyNode, ParentHierarchyNode } from \"./HierarchyNode.js\";\nimport { HierarchySearchPath } from \"./HierarchySearch.js\";\n\n/**\n * Props for the `HierarchyProvider.getNodes` call.\n * @public\n */\nexport interface GetHierarchyNodesProps {\n /** Parent node to get children for. Pass `undefined` to get root nodes. */\n parentNode: ParentHierarchyNode | undefined;\n\n /** Optional hierarchy level filter. Has no effect if `parentNode` is a `GroupingNode`. */\n instanceFilter?: GenericInstanceFilter;\n\n /**\n * Optional hierarchy level size limit override. This value is passed to `LimitingECSqlQueryExecutor` used\n * by this provider to override query rows limit per hierarchy level. If not provided, defaults to whatever\n * is used by the limiting query executor.\n *\n * Has no effect if `parentNode` is a `GroupingNode`.\n */\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n\n /** When set to `true` ignores the cache and fetches the nodes again. */\n ignoreCache?: boolean;\n}\n\n/**\n * Event arguments for `HierarchyProvider.hierarchyChanged` event.\n * @public\n */\ninterface HierarchyChangedEventArgs {\n /** Set when the hierarchy change was caused by a formatter change. */\n formatterChange?: {\n newFormatter: IPrimitiveValueFormatter | undefined;\n };\n\n /** Set when the hierarchy change was caused by a hierarchy search change. */\n searchChange?: {\n newSearch: Props<HierarchyProvider[\"setHierarchySearch\"]>;\n };\n}\n\n/**\n * An interface for a hierarchy provider that knows how to create child nodes for a given parent node.\n * @public\n */\nexport interface HierarchyProvider {\n /**\n * An event that provider raises due to a hierarchy change, that requires a reload. Provider may\n * set additional event arguments to provide extra information about what caused the change.\n *\n * Consumers are expected to subscribe to this event and reload the hierarchy when it's raised.\n * Implementations may provide additional details on what caused the change through the optional\n * event arguments.\n */\n readonly hierarchyChanged: Event<(args?: HierarchyChangedEventArgs) => void>;\n\n /**\n * Gets nodes for the specified parent node. This is **the method to implement**, otherwise\n * the provider doesn't return any nodes.\n */\n getNodes(props: GetHierarchyNodesProps): AsyncIterableIterator<HierarchyNode>;\n\n /**\n * Gets instance keys for the specified parent node.\n *\n * The result of this method may be used to determine instances whose nodes would be displayed as children\n * of the specified parent node. For such use cases calling this method should be more efficient compared\n * to calling `getNodes`.\n */\n getNodeInstanceKeys(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): AsyncIterableIterator<InstanceKey>;\n\n /**\n * Overrides the property value formatter used by the hierarchy provider. Setting to `undefined`\n * resets the formatter, but what that means depends on the provider implementation - it could just\n * use unformatted values, or use some default formatter, e.g. the on created by `createDefaultValueFormatter`\n * from `@itwin/presentation-shared` package.\n *\n * @note Changing formatter is expected to trigger the `hierarchyChanged` event with `formatterChange` arg.\n */\n setFormatter(formatter: IPrimitiveValueFormatter | undefined): void;\n\n /**\n * Sets the hierarchy search used by this hierarchy provider. Setting to `undefined`\n * removes the search.\n *\n * @note There's a difference between `undefined` search and search with empty paths list. The\n * former means no search is applied, while the latter means the search is applied and it filters-out\n * all hierarchy.\n *\n * @note Changing search is expected to trigger the `hierarchyChanged` event with `searchChange` arg.\n */\n setHierarchySearch(\n props:\n | {\n /** A list of node identifiers from root to target node. */\n paths: HierarchySearchPath[];\n }\n | undefined,\n ): void;\n}\n"]}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { NonGroupingHierarchyNode } from "./HierarchyNode.js";
|
|
2
|
+
import { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from "./HierarchyNodeIdentifier.js";
|
|
3
|
+
import { GenericNodeKey, HierarchyNodeKey, InstancesNodeKey } from "./HierarchyNodeKey.js";
|
|
4
|
+
/** @public */
|
|
5
|
+
export interface SearchPathRevealDepthInPath {
|
|
6
|
+
/**
|
|
7
|
+
* Index of the node in search path should be revealed in hierarchy by auto-expanding its ancestors.
|
|
8
|
+
*
|
|
9
|
+
* Use when you want to expand up to specific instance node and don't care about grouping nodes.
|
|
10
|
+
*
|
|
11
|
+
* **Use case example:**
|
|
12
|
+
*
|
|
13
|
+
* All nodes up to `Element1` should be expanded in the following hierarchy:
|
|
14
|
+
* - Node1
|
|
15
|
+
* - GroupingNode1
|
|
16
|
+
* - GroupingNode2
|
|
17
|
+
* - Element1
|
|
18
|
+
* - Element2
|
|
19
|
+
*
|
|
20
|
+
* Provide `{ path: [Node1, Element1], reveal: { depthInPath: 1 } }`
|
|
21
|
+
*
|
|
22
|
+
* **NOTE**: All nodes that are up to `depthInPath` will be expanded **except** search targets.
|
|
23
|
+
*/
|
|
24
|
+
depthInPath: number;
|
|
25
|
+
}
|
|
26
|
+
/** @public */
|
|
27
|
+
export interface SearchPathRevealDepthInHierarchy {
|
|
28
|
+
/**
|
|
29
|
+
* Considering the list of nodes from root to the target node, this is an index in that list, identifying the node that should be revealed in hierarchy by auto-expanding its ancestors.
|
|
30
|
+
*
|
|
31
|
+
* This should take into account the number of grouping nodes in hierarchy.
|
|
32
|
+
*
|
|
33
|
+
* **Use case example:**
|
|
34
|
+
*
|
|
35
|
+
* Only `Node1` and `GroupingNode1` should have `autoExpand` flag in the following hierarchy:
|
|
36
|
+
* - Node1
|
|
37
|
+
* - GroupingNode1
|
|
38
|
+
* - GroupingNode2
|
|
39
|
+
* - Element1
|
|
40
|
+
* - Element2
|
|
41
|
+
*
|
|
42
|
+
* Provide `{ path: [Node1, Element1], reveal: { depthInHierarchy: 2 } }`
|
|
43
|
+
*
|
|
44
|
+
* To get the correct depth use `HierarchyNode.parentKeys.length`.
|
|
45
|
+
*
|
|
46
|
+
* **NOTE**: All nodes that are up to `depthInHierarchy` will be expanded **except** search targets.
|
|
47
|
+
*/
|
|
48
|
+
depthInHierarchy: number;
|
|
49
|
+
}
|
|
50
|
+
/** @public */
|
|
51
|
+
export interface HierarchySearchPathOptions {
|
|
52
|
+
/**
|
|
53
|
+
* This option specifies the way `autoExpand` flag should be assigned to nodes in the searched hierarchy.
|
|
54
|
+
* - If it's `false` or `undefined`, nodes have no 'autoExpand' flag.
|
|
55
|
+
* - If it's `true`, then all nodes up to the search target will have `autoExpand` flag.
|
|
56
|
+
* - If it's an instance of `SearchPathRevealDepthInPath`, then all nodes up to `depthInPath` will have `autoExpand` flag.
|
|
57
|
+
* - If it's an instance of `SearchPathRevealDepthInHierarchy`, then all nodes up to `depthInHierarchy` will have `autoExpand` flag.
|
|
58
|
+
*/
|
|
59
|
+
reveal?: boolean | SearchPathRevealDepthInHierarchy | SearchPathRevealDepthInPath;
|
|
60
|
+
/**
|
|
61
|
+
* This option specifies whether or not search target should be expanded.
|
|
62
|
+
* - If it's `false` or `undefined`, search target won't have 'autoExpand' flag.
|
|
63
|
+
* - If it's `true`, search target will have `autoExpand` flag.
|
|
64
|
+
*
|
|
65
|
+
* **NOTE**: this attribute does not set `autoExpand` flag on nodes up to the search target. For that use `reveal`.
|
|
66
|
+
*/
|
|
67
|
+
autoExpand?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A path of hierarchy node identifiers for search the hierarchy with additional options.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
export type HierarchySearchPath = HierarchyNodeIdentifiersPath | {
|
|
74
|
+
path: HierarchyNodeIdentifiersPath;
|
|
75
|
+
options?: HierarchySearchPathOptions;
|
|
76
|
+
};
|
|
77
|
+
/** @public */
|
|
78
|
+
export declare namespace HierarchySearchPath {
|
|
79
|
+
/**
|
|
80
|
+
* Normalizes the hierarchy search path to the object form.
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
function normalize(source: HierarchySearchPath): Exclude<HierarchySearchPath, HierarchyNodeIdentifiersPath>;
|
|
84
|
+
/**
|
|
85
|
+
* Merges two given `HierarchySearchPathOptions` objects.
|
|
86
|
+
*
|
|
87
|
+
* For the `reveal` attribute, the merge chooses to `reveal` as deep as the deepest input:
|
|
88
|
+
* - if any one of the inputs is `true`, return `true`,
|
|
89
|
+
* - else if only one of the inputs is an object, return it,
|
|
90
|
+
* - else if both inputs are falsy, return `false` or `undefined`,
|
|
91
|
+
* - else:
|
|
92
|
+
* - if only one of the inputs has `depthInHierarchy` set, return the other one,
|
|
93
|
+
* - else return the one with greater `depthInPath` or `depthInHierarchy`.
|
|
94
|
+
*
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
function mergeOptions(lhs: HierarchySearchPathOptions | undefined, rhs: HierarchySearchPathOptions | undefined): HierarchySearchPathOptions | undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a set of utilities for making it easier to search the given hierarchy
|
|
101
|
+
* level.
|
|
102
|
+
*
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
export declare function createHierarchySearchHelper(rootLevelSearchProps: HierarchySearchPath[] | undefined, parentNode: Pick<NonGroupingHierarchyNode, "search"> | undefined): {
|
|
106
|
+
/** Returns a flag indicating if the hierarchy level is filtered. */
|
|
107
|
+
hasSearch: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Returns a flag indicating whether this hierarchy level has an ancestor node
|
|
110
|
+
* that is a search target. That generally means that this and all downstream hierarchy
|
|
111
|
+
* levels should be displayed without search being applied to them, even if search paths
|
|
112
|
+
* say otherwise.
|
|
113
|
+
*/
|
|
114
|
+
hasSearchTargetAncestor: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Returns a list of hierarchy node identifiers that apply specifically for this
|
|
117
|
+
* hierarchy level. Returns `undefined` if search is not applied to this level.
|
|
118
|
+
*/
|
|
119
|
+
getChildNodeSearchIdentifiers: () => HierarchyNodeIdentifier[] | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* When a hierarchy node is created for a filtered hierarchy level, it needs some attributes (e.g. `search`
|
|
122
|
+
* and `autoExpand`) to be set based on the search paths and search options. This function calculates
|
|
123
|
+
* these props for a child node based on its key or path matcher.
|
|
124
|
+
*
|
|
125
|
+
* When using `pathMatcher` or `asyncPathMatcher` prop, callers have more flexibility to decide whether the given `HierarchyNodeIdentifier` applies
|
|
126
|
+
* to their node. For example, only some parts of the identifier can be checked for improved performance. Otherwise, the
|
|
127
|
+
* `nodeKey` prop can be used to check the whole identifier.
|
|
128
|
+
*
|
|
129
|
+
* There are multiple overloads of `createChildNodeProps`: depending on props type it returns different values:
|
|
130
|
+
* - `parentKeys` is defined and `pathMatcher` or `nodeKey` is provided - returns undefined **or** `search` and `autoExpand` prop from `HierarchyNode`;
|
|
131
|
+
* - `parentKeys` is undefined - does not return `HierarchyNode.autoExpand` option;
|
|
132
|
+
* - props have `asyncPathMatcher` - returns either Promise or the regular return value based on whether or not `asyncPathMatcher` returns a promise.
|
|
133
|
+
*/
|
|
134
|
+
createChildNodeProps: {
|
|
135
|
+
(props: {
|
|
136
|
+
parentKeys?: undefined;
|
|
137
|
+
nodeKey: InstancesNodeKey | GenericNodeKey;
|
|
138
|
+
}): Pick<NonGroupingHierarchyNode, "search"> | undefined;
|
|
139
|
+
(props: {
|
|
140
|
+
parentKeys?: undefined;
|
|
141
|
+
pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean;
|
|
142
|
+
}): Pick<NonGroupingHierarchyNode, "search"> | undefined;
|
|
143
|
+
(props: {
|
|
144
|
+
parentKeys?: undefined;
|
|
145
|
+
asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;
|
|
146
|
+
}): Promise<Pick<NonGroupingHierarchyNode, "search"> | undefined> | Pick<NonGroupingHierarchyNode, "search"> | undefined;
|
|
147
|
+
(props: {
|
|
148
|
+
parentKeys: HierarchyNodeKey[];
|
|
149
|
+
nodeKey: InstancesNodeKey | GenericNodeKey;
|
|
150
|
+
}): Pick<NonGroupingHierarchyNode, "search" | "autoExpand"> | undefined;
|
|
151
|
+
(props: {
|
|
152
|
+
parentKeys: HierarchyNodeKey[];
|
|
153
|
+
pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean;
|
|
154
|
+
}): Pick<NonGroupingHierarchyNode, "search" | "autoExpand"> | undefined;
|
|
155
|
+
(props: {
|
|
156
|
+
parentKeys: HierarchyNodeKey[];
|
|
157
|
+
asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;
|
|
158
|
+
}): Promise<Pick<NonGroupingHierarchyNode, "search" | "autoExpand"> | undefined> | Pick<NonGroupingHierarchyNode, "search" | "autoExpand"> | undefined;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
/** @internal */
|
|
162
|
+
export declare function shouldAutoExpandBasedOnReveal({ reveal, nodePositionInPath, nodePositionInHierarchy, }: {
|
|
163
|
+
reveal: HierarchySearchPathOptions["reveal"];
|
|
164
|
+
nodePositionInPath: number;
|
|
165
|
+
nodePositionInHierarchy: number;
|
|
166
|
+
}): boolean;
|
|
167
|
+
//# sourceMappingURL=HierarchySearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HierarchySearch.d.ts","sourceRoot":"","sources":["../../../src/hierarchies/HierarchySearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.HierarchySearchPath = void 0;
|
|
8
|
+
exports.createHierarchySearchHelper = createHierarchySearchHelper;
|
|
9
|
+
exports.shouldAutoExpandBasedOnReveal = shouldAutoExpandBasedOnReveal;
|
|
10
|
+
const HierarchyNodeIdentifier_js_1 = require("./HierarchyNodeIdentifier.js");
|
|
11
|
+
const HierarchyNodeKey_js_1 = require("./HierarchyNodeKey.js");
|
|
12
|
+
var HierarchySearchPathOptions;
|
|
13
|
+
(function (HierarchySearchPathOptions) {
|
|
14
|
+
function mergeRevealOptions(lhs, rhs) {
|
|
15
|
+
if (rhs === true || lhs === true) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (!rhs || !lhs) {
|
|
19
|
+
return !!rhs ? rhs : lhs;
|
|
20
|
+
}
|
|
21
|
+
const lhsDepth = "depthInPath" in lhs ? lhs.depthInPath : lhs.depthInHierarchy;
|
|
22
|
+
const rhsDepth = "depthInPath" in rhs ? rhs.depthInPath : rhs.depthInHierarchy;
|
|
23
|
+
const isLhsDepthBasedOnPath = "depthInPath" in lhs;
|
|
24
|
+
const isRhsDepthBasedOnPath = "depthInPath" in rhs;
|
|
25
|
+
if (isLhsDepthBasedOnPath) {
|
|
26
|
+
if (isRhsDepthBasedOnPath) {
|
|
27
|
+
return lhsDepth > rhsDepth ? lhs : rhs;
|
|
28
|
+
}
|
|
29
|
+
return lhs;
|
|
30
|
+
}
|
|
31
|
+
if (isRhsDepthBasedOnPath) {
|
|
32
|
+
return rhs;
|
|
33
|
+
}
|
|
34
|
+
return lhsDepth > rhsDepth ? lhs : rhs;
|
|
35
|
+
}
|
|
36
|
+
HierarchySearchPathOptions.mergeRevealOptions = mergeRevealOptions;
|
|
37
|
+
function mergeAutoExpandOption(lhs, rhs) {
|
|
38
|
+
return lhs || rhs ? true : undefined;
|
|
39
|
+
}
|
|
40
|
+
HierarchySearchPathOptions.mergeAutoExpandOption = mergeAutoExpandOption;
|
|
41
|
+
})(HierarchySearchPathOptions || (HierarchySearchPathOptions = {}));
|
|
42
|
+
/** @public */
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
44
|
+
var HierarchySearchPath;
|
|
45
|
+
(function (HierarchySearchPath) {
|
|
46
|
+
/**
|
|
47
|
+
* Normalizes the hierarchy search path to the object form.
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
function normalize(source) {
|
|
51
|
+
if (Array.isArray(source)) {
|
|
52
|
+
return { path: source };
|
|
53
|
+
}
|
|
54
|
+
return source;
|
|
55
|
+
}
|
|
56
|
+
HierarchySearchPath.normalize = normalize;
|
|
57
|
+
/**
|
|
58
|
+
* Merges two given `HierarchySearchPathOptions` objects.
|
|
59
|
+
*
|
|
60
|
+
* For the `reveal` attribute, the merge chooses to `reveal` as deep as the deepest input:
|
|
61
|
+
* - if any one of the inputs is `true`, return `true`,
|
|
62
|
+
* - else if only one of the inputs is an object, return it,
|
|
63
|
+
* - else if both inputs are falsy, return `false` or `undefined`,
|
|
64
|
+
* - else:
|
|
65
|
+
* - if only one of the inputs has `depthInHierarchy` set, return the other one,
|
|
66
|
+
* - else return the one with greater `depthInPath` or `depthInHierarchy`.
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
function mergeOptions(lhs, rhs) {
|
|
71
|
+
const reveal = HierarchySearchPathOptions.mergeRevealOptions(lhs?.reveal, rhs?.reveal);
|
|
72
|
+
const autoExpand = HierarchySearchPathOptions.mergeAutoExpandOption(lhs?.autoExpand, rhs?.autoExpand);
|
|
73
|
+
return reveal || autoExpand
|
|
74
|
+
? {
|
|
75
|
+
...(reveal !== undefined ? { reveal } : undefined),
|
|
76
|
+
...(autoExpand !== undefined ? { autoExpand } : undefined),
|
|
77
|
+
}
|
|
78
|
+
: undefined;
|
|
79
|
+
}
|
|
80
|
+
HierarchySearchPath.mergeOptions = mergeOptions;
|
|
81
|
+
})(HierarchySearchPath || (exports.HierarchySearchPath = HierarchySearchPath = {}));
|
|
82
|
+
// TODO: remove c8 ignore start and add tests to cover the gaps
|
|
83
|
+
/* c8 ignore start */
|
|
84
|
+
function extractSearchPropsInternal(rootLevelSearchProps, parentNode) {
|
|
85
|
+
if (!parentNode) {
|
|
86
|
+
return rootLevelSearchProps ? { childrenTargetPaths: rootLevelSearchProps, hasSearchTargetAncestor: false } : undefined;
|
|
87
|
+
}
|
|
88
|
+
const searchProps = {
|
|
89
|
+
...(parentNode.search?.childrenTargetPaths ? { childrenTargetPaths: parentNode.search.childrenTargetPaths } : undefined),
|
|
90
|
+
hasSearchTargetAncestor: !!parentNode.search?.hasSearchTargetAncestor || !!parentNode.search?.isSearchTarget,
|
|
91
|
+
};
|
|
92
|
+
return searchProps.childrenTargetPaths || searchProps.hasSearchTargetAncestor ? searchProps : undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates a set of utilities for making it easier to search the given hierarchy
|
|
96
|
+
* level.
|
|
97
|
+
*
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
100
|
+
function createHierarchySearchHelper(rootLevelSearchProps, parentNode) {
|
|
101
|
+
const searchProps = extractSearchPropsInternal(rootLevelSearchProps, parentNode);
|
|
102
|
+
const hasSearch = !!searchProps;
|
|
103
|
+
function saveSearchPropsFromPathsIntoReducer(extractionProps) {
|
|
104
|
+
// Passes down matching normalized paths to the reducer.
|
|
105
|
+
// It uses `nodeKey`, `pathMatcher` or `asyncPathMatcher` to check if `HierarchyNodeIdentifier` at the first position in search path matches the node
|
|
106
|
+
// and if it does, the path is passed down to the reducer.
|
|
107
|
+
// This function returns a promise only if asyncPathMatcher returns a promise.
|
|
108
|
+
if (!searchProps?.childrenTargetPaths) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const matchedPathPromises = new Array();
|
|
112
|
+
for (const childrenTargetPaths of searchProps.childrenTargetPaths) {
|
|
113
|
+
const normalizedPath = HierarchySearchPath.normalize(childrenTargetPaths);
|
|
114
|
+
/* c8 ignore next 3 */
|
|
115
|
+
if (normalizedPath.path.length === 0) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if ("nodeKey" in extractionProps) {
|
|
119
|
+
if ((HierarchyNodeKey_js_1.HierarchyNodeKey.isGeneric(extractionProps.nodeKey) && HierarchyNodeIdentifier_js_1.HierarchyNodeIdentifier.equal(normalizedPath.path[0], extractionProps.nodeKey)) ||
|
|
120
|
+
(HierarchyNodeKey_js_1.HierarchyNodeKey.isInstances(extractionProps.nodeKey) &&
|
|
121
|
+
extractionProps.nodeKey.instanceKeys.some((ik) => HierarchyNodeIdentifier_js_1.HierarchyNodeIdentifier.equal(normalizedPath.path[0], ik)))) {
|
|
122
|
+
extractionProps.pathsReducer.accept(normalizedPath);
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const matchesPossiblyPromise = "pathMatcher" in extractionProps ? extractionProps.pathMatcher(normalizedPath.path[0]) : extractionProps.asyncPathMatcher(normalizedPath.path[0]);
|
|
127
|
+
if (matchesPossiblyPromise instanceof Promise) {
|
|
128
|
+
matchedPathPromises.push(matchesPossiblyPromise.then((matches) => (matches ? normalizedPath : undefined)));
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (matchesPossiblyPromise) {
|
|
132
|
+
extractionProps.pathsReducer.accept(normalizedPath);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (matchedPathPromises.length === 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
return Promise.all(matchedPathPromises).then((matchedPath) => matchedPath.forEach((normalizedPath) => normalizedPath && extractionProps.pathsReducer.accept(normalizedPath)));
|
|
139
|
+
}
|
|
140
|
+
function createChildNodeProps(props) {
|
|
141
|
+
if (!hasSearch) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
const reducer = new MatchingSearchPathsReducer(searchProps.hasSearchTargetAncestor);
|
|
145
|
+
if ("asyncPathMatcher" in props) {
|
|
146
|
+
const extractResult = saveSearchPropsFromPathsIntoReducer({ pathsReducer: reducer, asyncPathMatcher: props.asyncPathMatcher });
|
|
147
|
+
if (extractResult instanceof Promise) {
|
|
148
|
+
return extractResult.then(() => reducer.getNodeProps(props.parentKeys));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
saveSearchPropsFromPathsIntoReducer({ ...props, pathsReducer: reducer });
|
|
153
|
+
}
|
|
154
|
+
return reducer.getNodeProps(props.parentKeys);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
/** Returns a flag indicating if the hierarchy level is filtered. */
|
|
158
|
+
hasSearch,
|
|
159
|
+
/**
|
|
160
|
+
* Returns a flag indicating whether this hierarchy level has an ancestor node
|
|
161
|
+
* that is a search target. That generally means that this and all downstream hierarchy
|
|
162
|
+
* levels should be displayed without search being applied to them, even if search paths
|
|
163
|
+
* say otherwise.
|
|
164
|
+
*/
|
|
165
|
+
hasSearchTargetAncestor: searchProps?.hasSearchTargetAncestor ?? false,
|
|
166
|
+
/**
|
|
167
|
+
* Returns a list of hierarchy node identifiers that apply specifically for this
|
|
168
|
+
* hierarchy level. Returns `undefined` if search is not applied to this level.
|
|
169
|
+
*/
|
|
170
|
+
getChildNodeSearchIdentifiers: () => {
|
|
171
|
+
if (!searchProps?.childrenTargetPaths) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
return searchProps.childrenTargetPaths
|
|
175
|
+
.map(HierarchySearchPath.normalize)
|
|
176
|
+
.filter(({ path }) => path.length > 0)
|
|
177
|
+
.map(({ path }) => path[0]);
|
|
178
|
+
},
|
|
179
|
+
/**
|
|
180
|
+
* When a hierarchy node is created for a filtered hierarchy level, it needs some attributes (e.g. `search`
|
|
181
|
+
* and `autoExpand`) to be set based on the search paths and search options. This function calculates
|
|
182
|
+
* these props for a child node based on its key or path matcher.
|
|
183
|
+
*
|
|
184
|
+
* When using `pathMatcher` or `asyncPathMatcher` prop, callers have more flexibility to decide whether the given `HierarchyNodeIdentifier` applies
|
|
185
|
+
* to their node. For example, only some parts of the identifier can be checked for improved performance. Otherwise, the
|
|
186
|
+
* `nodeKey` prop can be used to check the whole identifier.
|
|
187
|
+
*
|
|
188
|
+
* There are multiple overloads of `createChildNodeProps`: depending on props type it returns different values:
|
|
189
|
+
* - `parentKeys` is defined and `pathMatcher` or `nodeKey` is provided - returns undefined **or** `search` and `autoExpand` prop from `HierarchyNode`;
|
|
190
|
+
* - `parentKeys` is undefined - does not return `HierarchyNode.autoExpand` option;
|
|
191
|
+
* - props have `asyncPathMatcher` - returns either Promise or the regular return value based on whether or not `asyncPathMatcher` returns a promise.
|
|
192
|
+
*/
|
|
193
|
+
createChildNodeProps,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Extracts information from search paths and later returns `search` and `autoExpand` values from `HierarchyNode`.
|
|
198
|
+
*
|
|
199
|
+
* Saved values can be applied to a single `HierarchyNode` - this means that a new reducer should be created every time these props are requested for a `HierarchyNode`.
|
|
200
|
+
*
|
|
201
|
+
* Extracts information using `accept` function:
|
|
202
|
+
* - Determines if node is search target, and if it is saves the options as `searchTargetOptions`
|
|
203
|
+
* - Saves `HierarchySearchPathOptions` and `childrenTargetPaths`
|
|
204
|
+
*/
|
|
205
|
+
class MatchingSearchPathsReducer {
|
|
206
|
+
_hasSearchTargetAncestor;
|
|
207
|
+
_childrenTargetPaths = new Array();
|
|
208
|
+
_isSearchTarget = false;
|
|
209
|
+
_searchTargetOptions = undefined;
|
|
210
|
+
_revealOption = false;
|
|
211
|
+
constructor(_hasSearchTargetAncestor) {
|
|
212
|
+
this._hasSearchTargetAncestor = _hasSearchTargetAncestor;
|
|
213
|
+
}
|
|
214
|
+
accept(normalizedPath) {
|
|
215
|
+
const { path, options } = normalizedPath;
|
|
216
|
+
if (path.length === 1) {
|
|
217
|
+
this._isSearchTarget = true;
|
|
218
|
+
this._searchTargetOptions = HierarchySearchPath.mergeOptions(this._searchTargetOptions, options);
|
|
219
|
+
}
|
|
220
|
+
else if (path.length > 1) {
|
|
221
|
+
this._childrenTargetPaths.push({ path: path.slice(1), options });
|
|
222
|
+
this._revealOption = HierarchySearchPathOptions.mergeRevealOptions(options?.reveal, this._revealOption);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
getNodeProps(parentKeys) {
|
|
226
|
+
return {
|
|
227
|
+
...(this._hasSearchTargetAncestor || this._isSearchTarget || this._childrenTargetPaths.length > 0
|
|
228
|
+
? {
|
|
229
|
+
search: {
|
|
230
|
+
...(this._hasSearchTargetAncestor ? { hasSearchTargetAncestor: true } : undefined),
|
|
231
|
+
...(this._isSearchTarget ? { isSearchTarget: true, searchTargetOptions: this._searchTargetOptions } : undefined),
|
|
232
|
+
...(this._childrenTargetPaths.length > 0 ? { childrenTargetPaths: this._childrenTargetPaths } : undefined),
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
: undefined),
|
|
236
|
+
...(parentKeys &&
|
|
237
|
+
(shouldAutoExpandBasedOnReveal({
|
|
238
|
+
reveal: this._revealOption,
|
|
239
|
+
nodePositionInHierarchy: parentKeys.length,
|
|
240
|
+
nodePositionInPath: parentKeys.filter((key) => !HierarchyNodeKey_js_1.HierarchyNodeKey.isGrouping(key)).length,
|
|
241
|
+
}) ||
|
|
242
|
+
!!this._searchTargetOptions?.autoExpand)
|
|
243
|
+
? { autoExpand: true }
|
|
244
|
+
: undefined),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/** @internal */
|
|
249
|
+
function shouldAutoExpandBasedOnReveal({ reveal, nodePositionInPath, nodePositionInHierarchy, }) {
|
|
250
|
+
if (!reveal) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
if (reveal === true) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
if ("depthInHierarchy" in reveal) {
|
|
257
|
+
return nodePositionInHierarchy < reveal.depthInHierarchy;
|
|
258
|
+
}
|
|
259
|
+
return nodePositionInPath < reveal.depthInPath;
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=HierarchySearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HierarchySearch.js","sourceRoot":"","sources":["../../../src/hierarchies/HierarchySearch.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { NonGroupingHierarchyNode } from \"./HierarchyNode.js\";\nimport { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from \"./HierarchyNodeIdentifier.js\";\nimport { GenericNodeKey, HierarchyNodeKey, InstancesNodeKey } from \"./HierarchyNodeKey.js\";\n\n/** @public */\nexport interface SearchPathRevealDepthInPath {\n /**\n * Index of the node in search path should be revealed in hierarchy by auto-expanding its ancestors.\n *\n * Use when you want to expand up to specific instance node and don't care about grouping nodes.\n *\n * **Use case example:**\n *\n * All nodes up to `Element1` should be expanded in the following hierarchy:\n * - Node1\n * - GroupingNode1\n * - GroupingNode2\n * - Element1\n * - Element2\n *\n * Provide `{ path: [Node1, Element1], reveal: { depthInPath: 1 } }`\n *\n * **NOTE**: All nodes that are up to `depthInPath` will be expanded **except** search targets.\n */\n depthInPath: number;\n}\n\n/** @public */\nexport interface SearchPathRevealDepthInHierarchy {\n /**\n * Considering the list of nodes from root to the target node, this is an index in that list, identifying the node that should be revealed in hierarchy by auto-expanding its ancestors.\n *\n * This should take into account the number of grouping nodes in hierarchy.\n *\n * **Use case example:**\n *\n * Only `Node1` and `GroupingNode1` should have `autoExpand` flag in the following hierarchy:\n * - Node1\n * - GroupingNode1\n * - GroupingNode2\n * - Element1\n * - Element2\n *\n * Provide `{ path: [Node1, Element1], reveal: { depthInHierarchy: 2 } }`\n *\n * To get the correct depth use `HierarchyNode.parentKeys.length`.\n *\n * **NOTE**: All nodes that are up to `depthInHierarchy` will be expanded **except** search targets.\n */\n depthInHierarchy: number;\n}\n\n/** @public */\nexport interface HierarchySearchPathOptions {\n /**\n * This option specifies the way `autoExpand` flag should be assigned to nodes in the searched hierarchy.\n * - If it's `false` or `undefined`, nodes have no 'autoExpand' flag.\n * - If it's `true`, then all nodes up to the search target will have `autoExpand` flag.\n * - If it's an instance of `SearchPathRevealDepthInPath`, then all nodes up to `depthInPath` will have `autoExpand` flag.\n * - If it's an instance of `SearchPathRevealDepthInHierarchy`, then all nodes up to `depthInHierarchy` will have `autoExpand` flag.\n */\n reveal?: boolean | SearchPathRevealDepthInHierarchy | SearchPathRevealDepthInPath;\n /**\n * This option specifies whether or not search target should be expanded.\n * - If it's `false` or `undefined`, search target won't have 'autoExpand' flag.\n * - If it's `true`, search target will have `autoExpand` flag.\n *\n * **NOTE**: this attribute does not set `autoExpand` flag on nodes up to the search target. For that use `reveal`.\n */\n autoExpand?: boolean;\n}\n\nnamespace HierarchySearchPathOptions {\n export function mergeRevealOptions(\n lhs: HierarchySearchPathOptions[\"reveal\"],\n rhs: HierarchySearchPathOptions[\"reveal\"],\n ): HierarchySearchPathOptions[\"reveal\"] {\n if (rhs === true || lhs === true) {\n return true;\n }\n if (!rhs || !lhs) {\n return !!rhs ? rhs : lhs;\n }\n\n const lhsDepth = \"depthInPath\" in lhs ? lhs.depthInPath : lhs.depthInHierarchy;\n const rhsDepth = \"depthInPath\" in rhs ? rhs.depthInPath : rhs.depthInHierarchy;\n const isLhsDepthBasedOnPath = \"depthInPath\" in lhs;\n const isRhsDepthBasedOnPath = \"depthInPath\" in rhs;\n\n if (isLhsDepthBasedOnPath) {\n if (isRhsDepthBasedOnPath) {\n return lhsDepth > rhsDepth ? lhs : rhs;\n }\n return lhs;\n }\n if (isRhsDepthBasedOnPath) {\n return rhs;\n }\n return lhsDepth > rhsDepth ? lhs : rhs;\n }\n\n export function mergeAutoExpandOption(\n lhs: HierarchySearchPathOptions[\"autoExpand\"],\n rhs: HierarchySearchPathOptions[\"autoExpand\"],\n ): HierarchySearchPathOptions[\"autoExpand\"] {\n return lhs || rhs ? true : undefined;\n }\n}\n\n/**\n * A path of hierarchy node identifiers for search the hierarchy with additional options.\n * @public\n */\nexport type HierarchySearchPath = HierarchyNodeIdentifiersPath | { path: HierarchyNodeIdentifiersPath; options?: HierarchySearchPathOptions };\n/** @public */\n// eslint-disable-next-line @typescript-eslint/no-redeclare\nexport namespace HierarchySearchPath {\n /**\n * Normalizes the hierarchy search path to the object form.\n * @public\n */\n export function normalize(source: HierarchySearchPath): Exclude<HierarchySearchPath, HierarchyNodeIdentifiersPath> {\n if (Array.isArray(source)) {\n return { path: source };\n }\n return source;\n }\n\n /**\n * Merges two given `HierarchySearchPathOptions` objects.\n *\n * For the `reveal` attribute, the merge chooses to `reveal` as deep as the deepest input:\n * - if any one of the inputs is `true`, return `true`,\n * - else if only one of the inputs is an object, return it,\n * - else if both inputs are falsy, return `false` or `undefined`,\n * - else:\n * - if only one of the inputs has `depthInHierarchy` set, return the other one,\n * - else return the one with greater `depthInPath` or `depthInHierarchy`.\n *\n * @public\n */\n export function mergeOptions(\n lhs: HierarchySearchPathOptions | undefined,\n rhs: HierarchySearchPathOptions | undefined,\n ): HierarchySearchPathOptions | undefined {\n const reveal = HierarchySearchPathOptions.mergeRevealOptions(lhs?.reveal, rhs?.reveal);\n const autoExpand = HierarchySearchPathOptions.mergeAutoExpandOption(lhs?.autoExpand, rhs?.autoExpand);\n return reveal || autoExpand\n ? {\n ...(reveal !== undefined ? { reveal } : undefined),\n ...(autoExpand !== undefined ? { autoExpand } : undefined),\n }\n : undefined;\n }\n}\n\n// TODO: remove c8 ignore start and add tests to cover the gaps\n/* c8 ignore start */\n\nfunction extractSearchPropsInternal(\n rootLevelSearchProps: HierarchySearchPath[] | undefined,\n parentNode: Pick<NonGroupingHierarchyNode, \"search\"> | undefined,\n):\n | {\n childrenTargetPaths?: HierarchySearchPath[];\n hasSearchTargetAncestor: boolean;\n }\n | undefined {\n if (!parentNode) {\n return rootLevelSearchProps ? { childrenTargetPaths: rootLevelSearchProps, hasSearchTargetAncestor: false } : undefined;\n }\n const searchProps: {\n childrenTargetPaths?: HierarchySearchPath[];\n hasSearchTargetAncestor: boolean;\n } = {\n ...(parentNode.search?.childrenTargetPaths ? { childrenTargetPaths: parentNode.search.childrenTargetPaths } : undefined),\n hasSearchTargetAncestor: !!parentNode.search?.hasSearchTargetAncestor || !!parentNode.search?.isSearchTarget,\n };\n return searchProps.childrenTargetPaths || searchProps.hasSearchTargetAncestor ? searchProps : undefined;\n}\n\n/**\n * Creates a set of utilities for making it easier to search the given hierarchy\n * level.\n *\n * @public\n */\nexport function createHierarchySearchHelper(\n rootLevelSearchProps: HierarchySearchPath[] | undefined,\n parentNode: Pick<NonGroupingHierarchyNode, \"search\"> | undefined,\n) {\n const searchProps = extractSearchPropsInternal(rootLevelSearchProps, parentNode);\n const hasSearch = !!searchProps;\n\n function saveSearchPropsFromPathsIntoReducer(\n extractionProps: {\n pathsReducer: MatchingSearchPathsReducer;\n } & (\n | {\n nodeKey: InstancesNodeKey | GenericNodeKey;\n }\n | { pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean }\n ),\n ): void;\n function saveSearchPropsFromPathsIntoReducer(extractionProps: {\n pathsReducer: MatchingSearchPathsReducer;\n asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;\n }): void | Promise<void>;\n function saveSearchPropsFromPathsIntoReducer(\n extractionProps: {\n pathsReducer: MatchingSearchPathsReducer;\n } & (\n | {\n nodeKey: InstancesNodeKey | GenericNodeKey;\n }\n | { pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean }\n | { asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean> }\n ),\n ): void | Promise<void> {\n // Passes down matching normalized paths to the reducer.\n // It uses `nodeKey`, `pathMatcher` or `asyncPathMatcher` to check if `HierarchyNodeIdentifier` at the first position in search path matches the node\n // and if it does, the path is passed down to the reducer.\n // This function returns a promise only if asyncPathMatcher returns a promise.\n if (!searchProps?.childrenTargetPaths) {\n return;\n }\n const matchedPathPromises = new Array<Promise<NormalizedSearchPath | undefined>>();\n for (const childrenTargetPaths of searchProps.childrenTargetPaths) {\n const normalizedPath = HierarchySearchPath.normalize(childrenTargetPaths);\n /* c8 ignore next 3 */\n if (normalizedPath.path.length === 0) {\n continue;\n }\n if (\"nodeKey\" in extractionProps) {\n if (\n (HierarchyNodeKey.isGeneric(extractionProps.nodeKey) && HierarchyNodeIdentifier.equal(normalizedPath.path[0], extractionProps.nodeKey)) ||\n (HierarchyNodeKey.isInstances(extractionProps.nodeKey) &&\n extractionProps.nodeKey.instanceKeys.some((ik) => HierarchyNodeIdentifier.equal(normalizedPath.path[0], ik)))\n ) {\n extractionProps.pathsReducer.accept(normalizedPath);\n }\n continue;\n }\n\n const matchesPossiblyPromise =\n \"pathMatcher\" in extractionProps ? extractionProps.pathMatcher(normalizedPath.path[0]) : extractionProps.asyncPathMatcher(normalizedPath.path[0]);\n if (matchesPossiblyPromise instanceof Promise) {\n matchedPathPromises.push(matchesPossiblyPromise.then((matches) => (matches ? normalizedPath : undefined)));\n continue;\n }\n if (matchesPossiblyPromise) {\n extractionProps.pathsReducer.accept(normalizedPath);\n }\n }\n if (matchedPathPromises.length === 0) {\n return;\n }\n return Promise.all(matchedPathPromises).then((matchedPath) =>\n matchedPath.forEach((normalizedPath) => normalizedPath && extractionProps.pathsReducer.accept(normalizedPath)),\n );\n }\n\n function createChildNodeProps(props: {\n parentKeys?: undefined;\n nodeKey: InstancesNodeKey | GenericNodeKey;\n }): Pick<NonGroupingHierarchyNode, \"search\"> | undefined;\n function createChildNodeProps(props: {\n parentKeys?: undefined;\n pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean;\n }): Pick<NonGroupingHierarchyNode, \"search\"> | undefined;\n function createChildNodeProps(props: {\n parentKeys?: undefined;\n asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;\n }): Promise<Pick<NonGroupingHierarchyNode, \"search\"> | undefined> | Pick<NonGroupingHierarchyNode, \"search\"> | undefined;\n function createChildNodeProps(props: {\n parentKeys: HierarchyNodeKey[];\n nodeKey: InstancesNodeKey | GenericNodeKey;\n }): Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> | undefined;\n function createChildNodeProps(props: {\n parentKeys: HierarchyNodeKey[];\n pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean;\n }): Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> | undefined;\n function createChildNodeProps(props: {\n parentKeys: HierarchyNodeKey[];\n asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;\n }): Promise<Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> | undefined> | Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> | undefined;\n function createChildNodeProps(\n props: { parentKeys?: HierarchyNodeKey[] } & (\n | {\n asyncPathMatcher: (identifier: HierarchyNodeIdentifier) => boolean | Promise<boolean>;\n }\n | {\n pathMatcher: (identifier: HierarchyNodeIdentifier) => boolean;\n }\n | {\n nodeKey: InstancesNodeKey | GenericNodeKey;\n }\n ),\n ):\n | Promise<Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> | Pick<NonGroupingHierarchyNode, \"search\"> | undefined>\n | Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\">\n | Pick<NonGroupingHierarchyNode, \"search\">\n | undefined {\n if (!hasSearch) {\n return undefined;\n }\n const reducer = new MatchingSearchPathsReducer(searchProps.hasSearchTargetAncestor);\n if (\"asyncPathMatcher\" in props) {\n const extractResult = saveSearchPropsFromPathsIntoReducer({ pathsReducer: reducer, asyncPathMatcher: props.asyncPathMatcher });\n if (extractResult instanceof Promise) {\n return extractResult.then(() => reducer.getNodeProps(props.parentKeys));\n }\n } else {\n saveSearchPropsFromPathsIntoReducer({ ...props, pathsReducer: reducer });\n }\n return reducer.getNodeProps(props.parentKeys);\n }\n return {\n /** Returns a flag indicating if the hierarchy level is filtered. */\n hasSearch,\n /**\n * Returns a flag indicating whether this hierarchy level has an ancestor node\n * that is a search target. That generally means that this and all downstream hierarchy\n * levels should be displayed without search being applied to them, even if search paths\n * say otherwise.\n */\n hasSearchTargetAncestor: searchProps?.hasSearchTargetAncestor ?? false,\n /**\n * Returns a list of hierarchy node identifiers that apply specifically for this\n * hierarchy level. Returns `undefined` if search is not applied to this level.\n */\n getChildNodeSearchIdentifiers: () => {\n if (!searchProps?.childrenTargetPaths) {\n return undefined;\n }\n return searchProps.childrenTargetPaths\n .map(HierarchySearchPath.normalize)\n .filter(({ path }) => path.length > 0)\n .map(({ path }) => path[0]);\n },\n /**\n * When a hierarchy node is created for a filtered hierarchy level, it needs some attributes (e.g. `search`\n * and `autoExpand`) to be set based on the search paths and search options. This function calculates\n * these props for a child node based on its key or path matcher.\n *\n * When using `pathMatcher` or `asyncPathMatcher` prop, callers have more flexibility to decide whether the given `HierarchyNodeIdentifier` applies\n * to their node. For example, only some parts of the identifier can be checked for improved performance. Otherwise, the\n * `nodeKey` prop can be used to check the whole identifier.\n *\n * There are multiple overloads of `createChildNodeProps`: depending on props type it returns different values:\n * - `parentKeys` is defined and `pathMatcher` or `nodeKey` is provided - returns undefined **or** `search` and `autoExpand` prop from `HierarchyNode`;\n * - `parentKeys` is undefined - does not return `HierarchyNode.autoExpand` option;\n * - props have `asyncPathMatcher` - returns either Promise or the regular return value based on whether or not `asyncPathMatcher` returns a promise.\n */\n createChildNodeProps,\n };\n}\n\ntype NormalizedSearchPath = ReturnType<(typeof HierarchySearchPath)[\"normalize\"]>;\n\n/**\n * Extracts information from search paths and later returns `search` and `autoExpand` values from `HierarchyNode`.\n *\n * Saved values can be applied to a single `HierarchyNode` - this means that a new reducer should be created every time these props are requested for a `HierarchyNode`.\n *\n * Extracts information using `accept` function:\n * - Determines if node is search target, and if it is saves the options as `searchTargetOptions`\n * - Saves `HierarchySearchPathOptions` and `childrenTargetPaths`\n */\nclass MatchingSearchPathsReducer {\n private _childrenTargetPaths = new Array<NormalizedSearchPath>();\n private _isSearchTarget = false;\n private _searchTargetOptions: HierarchySearchPathOptions | undefined = undefined;\n private _revealOption: HierarchySearchPathOptions[\"reveal\"] = false;\n\n public constructor(private _hasSearchTargetAncestor: boolean) {}\n\n public accept(normalizedPath: NormalizedSearchPath): void {\n const { path, options } = normalizedPath;\n if (path.length === 1) {\n this._isSearchTarget = true;\n this._searchTargetOptions = HierarchySearchPath.mergeOptions(this._searchTargetOptions, options);\n } else if (path.length > 1) {\n this._childrenTargetPaths.push({ path: path.slice(1), options });\n this._revealOption = HierarchySearchPathOptions.mergeRevealOptions(options?.reveal, this._revealOption);\n }\n }\n\n public getNodeProps<T extends HierarchyNodeKey[] | undefined = undefined>(\n parentKeys?: T,\n ): T extends undefined ? Pick<NonGroupingHierarchyNode, \"search\"> : Pick<NonGroupingHierarchyNode, \"search\" | \"autoExpand\"> {\n return {\n ...(this._hasSearchTargetAncestor || this._isSearchTarget || this._childrenTargetPaths.length > 0\n ? {\n search: {\n ...(this._hasSearchTargetAncestor ? { hasSearchTargetAncestor: true } : undefined),\n ...(this._isSearchTarget ? { isSearchTarget: true, searchTargetOptions: this._searchTargetOptions } : undefined),\n ...(this._childrenTargetPaths.length > 0 ? { childrenTargetPaths: this._childrenTargetPaths } : undefined),\n },\n }\n : undefined),\n ...(parentKeys &&\n (shouldAutoExpandBasedOnReveal({\n reveal: this._revealOption,\n nodePositionInHierarchy: parentKeys.length,\n nodePositionInPath: parentKeys.filter((key) => !HierarchyNodeKey.isGrouping(key)).length,\n }) ||\n !!this._searchTargetOptions?.autoExpand)\n ? { autoExpand: true }\n : undefined),\n };\n }\n}\n\n/** @internal */\nexport function shouldAutoExpandBasedOnReveal({\n reveal,\n nodePositionInPath,\n nodePositionInHierarchy,\n}: {\n reveal: HierarchySearchPathOptions[\"reveal\"];\n nodePositionInPath: number;\n nodePositionInHierarchy: number;\n}): boolean {\n if (!reveal) {\n return false;\n }\n if (reveal === true) {\n return true;\n }\n if (\"depthInHierarchy\" in reveal) {\n return nodePositionInHierarchy < reveal.depthInHierarchy;\n }\n return nodePositionInPath < reveal.depthInPath;\n}\n"]}
|
|
@@ -17,11 +17,11 @@ class HierarchyCache {
|
|
|
17
17
|
}
|
|
18
18
|
createCacheKeys(props) {
|
|
19
19
|
function createVariationKey() {
|
|
20
|
-
const { instanceFilter, hierarchyLevelSizeLimit,
|
|
21
|
-
if (instanceFilter === undefined && hierarchyLevelSizeLimit === undefined &&
|
|
20
|
+
const { instanceFilter, hierarchyLevelSizeLimit, targetInstanceKeys } = props;
|
|
21
|
+
if (instanceFilter === undefined && hierarchyLevelSizeLimit === undefined && targetInstanceKeys === undefined) {
|
|
22
22
|
return undefined;
|
|
23
23
|
}
|
|
24
|
-
return JSON.stringify({ instanceFilter, hierarchyLevelSizeLimit,
|
|
24
|
+
return JSON.stringify({ instanceFilter, hierarchyLevelSizeLimit, targetInstanceKeys });
|
|
25
25
|
}
|
|
26
26
|
if (!props.parentNode) {
|
|
27
27
|
return { primaryKey: [], variationKey: createVariationKey() };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HierarchyCache.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/HierarchyCache.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;;AAEhG,sDAAsE;AAEtE,gEAA0D;AAe1D,gBAAgB;AAChB,MAAa,cAAc;IACjB,IAAI,CAA4D;IAChE,MAAM,CAAiC;IAE/C,YAAmB,KAAqC;QACtD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,4BAAa,CAA6C,KAAK,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;IAClH,CAAC;IAEO,eAAe,CACrB,KAGC;QAED,SAAS,kBAAkB;YACzB,MAAM,EAAE,cAAc,EAAE,uBAAuB,EAAE,
|
|
1
|
+
{"version":3,"file":"HierarchyCache.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/HierarchyCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LRUCache, LRUDictionary, LRUMap } from \"@itwin/core-bentley\";\nimport { InstanceKey } from \"@itwin/presentation-shared\";\nimport { HierarchyNodeKey } from \"../HierarchyNodeKey.js\";\nimport { GetHierarchyNodesProps } from \"../HierarchyProvider.js\";\n\ninterface HierarchyCacheEntry<T> {\n /** Stores observables for the default case - no instance filter or custom limit for the hierarchy level. */\n primary: T | undefined;\n /** Stores a limited number of variations with custom instance filter and/or custom limit for the hierarchy level. */\n variations: LRUCache<string, T>;\n}\n\ninterface ChildNodeObservablesCacheProps {\n size: number;\n variationsCount?: number;\n}\n\n/** @internal */\nexport class HierarchyCache<T> {\n private _map: LRUDictionary<HierarchyNodeKey[], HierarchyCacheEntry<T>>;\n private _props: ChildNodeObservablesCacheProps;\n\n public constructor(props: ChildNodeObservablesCacheProps) {\n this._props = props;\n this._map = new LRUDictionary<HierarchyNodeKey[], HierarchyCacheEntry<T>>(props.size, compareHierarchyNodeKeys);\n }\n\n private createCacheKeys(\n props: Omit<GetHierarchyNodesProps, \"parentNode\"> & {\n parentNode: { key: HierarchyNodeKey; parentKeys: HierarchyNodeKey[] } | undefined;\n targetInstanceKeys?: InstanceKey[];\n },\n ) {\n function createVariationKey() {\n const { instanceFilter, hierarchyLevelSizeLimit, targetInstanceKeys } = props;\n if (instanceFilter === undefined && hierarchyLevelSizeLimit === undefined && targetInstanceKeys === undefined) {\n return undefined;\n }\n return JSON.stringify({ instanceFilter, hierarchyLevelSizeLimit, targetInstanceKeys });\n }\n\n if (!props.parentNode) {\n return { primaryKey: [], variationKey: createVariationKey() };\n }\n\n const parentKeys = props.parentNode.parentKeys;\n\n return {\n primaryKey: [...parentKeys, props.parentNode.key],\n variationKey: createVariationKey(),\n };\n }\n\n private getCacheAccessors(primaryKey: HierarchyNodeKey[], variationKey?: string) {\n const getMapEntry = (create: boolean) => {\n let entry = this._map.get(primaryKey);\n if (!entry && create) {\n entry = { primary: undefined, variations: new LRUMap(this._props.variationsCount ?? 1) };\n this._map.set(primaryKey, entry);\n }\n return entry;\n };\n if (variationKey) {\n return {\n get: () => getMapEntry(false)?.variations.get(variationKey),\n set: (value: T) => {\n getMapEntry(true)!.variations.set(variationKey, value);\n },\n };\n }\n return {\n get: () => getMapEntry(false)?.primary,\n set: (value: T) => {\n getMapEntry(true)!.primary = value;\n },\n };\n }\n\n public set(requestProps: GetHierarchyNodesProps, value: T) {\n const { primaryKey, variationKey } = this.createCacheKeys(requestProps);\n this.getCacheAccessors(primaryKey, variationKey).set(value);\n }\n\n public get(requestProps: GetHierarchyNodesProps): T | undefined {\n const { primaryKey, variationKey } = this.createCacheKeys(requestProps);\n return this.getCacheAccessors(primaryKey, variationKey).get();\n }\n\n public clear() {\n this._map.clear();\n }\n}\n\nfunction compareHierarchyNodeKeys(lhs: HierarchyNodeKey[], rhs: HierarchyNodeKey[]) {\n if (lhs.length !== rhs.length) {\n return lhs.length - rhs.length;\n }\n for (let i = 0; i < lhs.length; ++i) {\n const keysCompareResult = HierarchyNodeKey.compare(lhs[i], rhs[i]);\n if (keysCompareResult !== 0) {\n return keysCompareResult;\n }\n }\n return 0;\n}\n"]}
|