@itwin/presentation-hierarchies-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +303 -0
  4. package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts +75 -0
  5. package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
  6. package/lib/cjs/presentation-hierarchies-react/TreeNode.js +16 -0
  7. package/lib/cjs/presentation-hierarchies-react/TreeNode.js.map +1 -0
  8. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
  9. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
  10. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js +28 -0
  11. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
  12. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
  13. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
  14. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js +102 -0
  15. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
  16. package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts +85 -0
  17. package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
  18. package/lib/cjs/presentation-hierarchies-react/UseTree.js +214 -0
  19. package/lib/cjs/presentation-hierarchies-react/UseTree.js.map +1 -0
  20. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
  21. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
  22. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js +236 -0
  23. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
  24. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
  25. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
  26. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js +71 -0
  27. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
  28. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
  29. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
  30. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js +154 -0
  31. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
  32. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
  33. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
  34. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js +96 -0
  35. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
  36. package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
  37. package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
  38. package/lib/cjs/presentation-hierarchies-react/internal/Utils.js +45 -0
  39. package/lib/cjs/presentation-hierarchies-react/internal/Utils.js.map +1 -0
  40. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
  41. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
  42. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js +35 -0
  43. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
  44. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
  45. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
  46. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
  47. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +101 -0
  48. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
  49. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
  50. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
  51. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js +83 -0
  52. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
  53. package/lib/cjs/presentation-hierarchies-react.d.ts +10 -0
  54. package/lib/cjs/presentation-hierarchies-react.d.ts.map +1 -0
  55. package/lib/cjs/presentation-hierarchies-react.js +27 -0
  56. package/lib/cjs/presentation-hierarchies-react.js.map +1 -0
  57. package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts +75 -0
  58. package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
  59. package/lib/esm/presentation-hierarchies-react/TreeNode.js +12 -0
  60. package/lib/esm/presentation-hierarchies-react/TreeNode.js.map +1 -0
  61. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
  62. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
  63. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js +23 -0
  64. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
  65. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
  66. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
  67. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js +98 -0
  68. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
  69. package/lib/esm/presentation-hierarchies-react/UseTree.d.ts +85 -0
  70. package/lib/esm/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
  71. package/lib/esm/presentation-hierarchies-react/UseTree.js +209 -0
  72. package/lib/esm/presentation-hierarchies-react/UseTree.js.map +1 -0
  73. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
  74. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
  75. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js +232 -0
  76. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
  77. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
  78. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
  79. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js +67 -0
  80. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
  81. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
  82. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
  83. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js +149 -0
  84. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
  85. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
  86. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
  87. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js +92 -0
  88. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
  89. package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
  90. package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
  91. package/lib/esm/presentation-hierarchies-react/internal/Utils.js +40 -0
  92. package/lib/esm/presentation-hierarchies-react/internal/Utils.js.map +1 -0
  93. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
  94. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
  95. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js +30 -0
  96. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
  97. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
  98. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
  99. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
  100. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +94 -0
  101. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
  102. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
  103. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
  104. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js +78 -0
  105. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
  106. package/lib/esm/presentation-hierarchies-react.d.ts +10 -0
  107. package/lib/esm/presentation-hierarchies-react.d.ts.map +1 -0
  108. package/lib/esm/presentation-hierarchies-react.js +13 -0
  109. package/lib/esm/presentation-hierarchies-react.js.map +1 -0
  110. package/package.json +103 -0
@@ -0,0 +1,232 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { enableMapSet, produce } from "immer";
6
+ import { EMPTY, reduce, Subject, takeUntil } from "rxjs";
7
+ import { HierarchyNode } from "@itwin/presentation-hierarchies";
8
+ import { TreeLoader } from "./TreeLoader";
9
+ import { isTreeModelHierarchyNode, isTreeModelInfoNode, TreeModel } from "./TreeModel";
10
+ import { createNodeId, sameNodes } from "./Utils";
11
+ enableMapSet();
12
+ /** @internal */
13
+ export class TreeActions {
14
+ _onModelChanged;
15
+ _loader;
16
+ _currentModel;
17
+ _disposed = new Subject();
18
+ constructor(_onModelChanged, seed) {
19
+ this._onModelChanged = _onModelChanged;
20
+ this._loader = new NoopTreeLoader();
21
+ this._currentModel = seed ?? /* istanbul ignore next */ {
22
+ idToNode: new Map(),
23
+ parentChildMap: new Map(),
24
+ rootNode: { id: undefined, nodeData: undefined },
25
+ };
26
+ }
27
+ updateTreeModel(updater) {
28
+ const newModel = produce(this._currentModel, updater);
29
+ if (this._currentModel === newModel) {
30
+ return;
31
+ }
32
+ this._currentModel = newModel;
33
+ this._onModelChanged(this._currentModel);
34
+ }
35
+ handleLoadedHierarchy(parentId, loadedHierarchy) {
36
+ this.updateTreeModel((model) => {
37
+ TreeModel.addHierarchyPart(model, parentId, loadedHierarchy);
38
+ });
39
+ }
40
+ onLoadingComplete(parentId) {
41
+ this.updateTreeModel((model) => {
42
+ TreeModel.setIsLoading(model, parentId, false);
43
+ });
44
+ }
45
+ loadNodes(parentId, ignoreCache) {
46
+ const parentNode = this._currentModel.idToNode.get(parentId);
47
+ // istanbul ignore if
48
+ if (!parentNode || !isTreeModelHierarchyNode(parentNode)) {
49
+ return;
50
+ }
51
+ this._loader
52
+ .loadNodes({
53
+ parent: parentNode,
54
+ getHierarchyLevelOptions: (node) => createHierarchyLevelOptions(this._currentModel, getNonGroupedParentId(node)),
55
+ shouldLoadChildren: (node) => !!node.nodeData.autoExpand,
56
+ ignoreCache,
57
+ })
58
+ .pipe(collectTreePartsUntil(this._disposed))
59
+ .subscribe({
60
+ next: (loadedHierarchy) => {
61
+ this.handleLoadedHierarchy(parentId, loadedHierarchy);
62
+ },
63
+ complete: () => {
64
+ this.onLoadingComplete(parentId);
65
+ },
66
+ });
67
+ }
68
+ reloadSubTree(parentId, oldModel, options) {
69
+ const currModel = this._currentModel;
70
+ const expandedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === true);
71
+ const collapsedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === false);
72
+ const getHierarchyLevelOptions = (node) => {
73
+ if (!!options?.discardState) {
74
+ return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };
75
+ }
76
+ const filteredNodeId = getNonGroupedParentId(node);
77
+ return createHierarchyLevelOptions(filteredNodeId === parentId ? currModel : oldModel, filteredNodeId);
78
+ };
79
+ const shouldLoadChildren = (node) => {
80
+ if (expandedNodes.findIndex((expandedNode) => sameNodes(expandedNode.nodeData, node.nodeData)) !== -1) {
81
+ return true;
82
+ }
83
+ if (collapsedNodes.findIndex((collapsedNode) => sameNodes(collapsedNode.nodeData, node.nodeData)) !== -1) {
84
+ return false;
85
+ }
86
+ return !!node.nodeData.autoExpand;
87
+ };
88
+ const buildNode = (node) => (!!options?.discardState || node.id === parentId ? node : addAttributes(node, oldModel));
89
+ const rootNode = parentId !== undefined ? this.getNode(parentId) : currModel.rootNode;
90
+ // istanbul ignore if
91
+ if (!rootNode || isTreeModelInfoNode(rootNode)) {
92
+ return;
93
+ }
94
+ if (parentId === undefined) {
95
+ // cancel all ongoing requests
96
+ this._disposed.next();
97
+ }
98
+ this._loader
99
+ .loadNodes({ parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode })
100
+ .pipe(collectTreePartsUntil(this._disposed, !!options?.discardState ? undefined : { ...currModel.rootNode }))
101
+ .subscribe({
102
+ next: (newModel) => {
103
+ this.handleLoadedHierarchy(parentId, newModel);
104
+ },
105
+ complete: () => {
106
+ this.onLoadingComplete(parentId);
107
+ },
108
+ });
109
+ }
110
+ dispose() {
111
+ this._disposed.next();
112
+ }
113
+ setHierarchyProvider(provider) {
114
+ this._loader = provider ? new TreeLoader(provider) : /* istanbul ignore next */ new NoopTreeLoader();
115
+ }
116
+ getNode(nodeId) {
117
+ return TreeModel.getNode(this._currentModel, nodeId);
118
+ }
119
+ selectNodes(nodeIds, changeType) {
120
+ this.updateTreeModel((model) => {
121
+ TreeModel.selectNodes(model, nodeIds, changeType);
122
+ });
123
+ }
124
+ expandNode(nodeId, isExpanded) {
125
+ let childrenAction = "none";
126
+ this.updateTreeModel((model) => {
127
+ childrenAction = TreeModel.expandNode(model, nodeId, isExpanded);
128
+ });
129
+ if (childrenAction === "none") {
130
+ return;
131
+ }
132
+ this.loadNodes(nodeId, childrenAction === "reloadChildren");
133
+ }
134
+ setHierarchyLimit(nodeId, limit) {
135
+ const oldModel = this._currentModel;
136
+ let loadChildren = false;
137
+ this.updateTreeModel((model) => {
138
+ loadChildren = TreeModel.setHierarchyLimit(model, nodeId, limit);
139
+ });
140
+ if (!loadChildren) {
141
+ return;
142
+ }
143
+ this.reloadSubTree(nodeId, oldModel);
144
+ }
145
+ setInstanceFilter(nodeId, filter) {
146
+ const oldModel = this._currentModel;
147
+ let loadChildren = false;
148
+ this.updateTreeModel((model) => {
149
+ loadChildren = TreeModel.setInstanceFilter(model, nodeId, filter);
150
+ });
151
+ if (!loadChildren) {
152
+ return;
153
+ }
154
+ this.reloadSubTree(nodeId, oldModel);
155
+ }
156
+ reloadTree(options) {
157
+ const oldModel = this._currentModel;
158
+ this.updateTreeModel((model) => {
159
+ model.rootNode.isLoading = true;
160
+ });
161
+ this.reloadSubTree(undefined, oldModel, { ...options });
162
+ }
163
+ }
164
+ function collectTreePartsUntil(untilNotifier, rootNode) {
165
+ return (source) => source.pipe(reduce((treeModel, loadedPart) => {
166
+ addNodesToModel(treeModel, loadedPart);
167
+ return treeModel;
168
+ }, {
169
+ idToNode: new Map(),
170
+ parentChildMap: new Map(),
171
+ rootNode: rootNode ?? { id: undefined, nodeData: undefined },
172
+ }), takeUntil(untilNotifier));
173
+ }
174
+ function addNodesToModel(model, hierarchyPart) {
175
+ model.parentChildMap.set(hierarchyPart.parentId, hierarchyPart.loadedNodes.map((node) => node.id));
176
+ for (const node of hierarchyPart.loadedNodes) {
177
+ model.idToNode.set(node.id, node);
178
+ }
179
+ const parentNode = hierarchyPart.parentId ? model.idToNode.get(hierarchyPart.parentId) : undefined;
180
+ if (parentNode && isTreeModelHierarchyNode(parentNode)) {
181
+ parentNode.isExpanded = true;
182
+ }
183
+ }
184
+ function addAttributes(node, oldModel) {
185
+ const oldNode = oldModel.idToNode.get(node.id);
186
+ if (oldNode && isTreeModelHierarchyNode(oldNode)) {
187
+ node.hierarchyLimit = oldNode.hierarchyLimit;
188
+ node.instanceFilter = oldNode.instanceFilter;
189
+ node.isSelected = oldNode.isSelected;
190
+ }
191
+ return node;
192
+ }
193
+ function collectNodes(parentId, model, pred) {
194
+ const currentChildren = model.parentChildMap.get(parentId);
195
+ if (!currentChildren) {
196
+ return [];
197
+ }
198
+ if (parentId === undefined) {
199
+ return currentChildren.flatMap((child) => collectNodes(child, model, pred));
200
+ }
201
+ const currNode = model.idToNode.get(parentId);
202
+ if (!currNode || !isTreeModelHierarchyNode(currNode) || !pred(currNode)) {
203
+ return [];
204
+ }
205
+ return [currNode, ...currentChildren.flatMap((child) => collectNodes(child, model, pred))];
206
+ }
207
+ function getNonGroupedParentId(node) {
208
+ if (!node.nodeData || !HierarchyNode.isGroupingNode(node.nodeData)) {
209
+ return node.id;
210
+ }
211
+ if (!node.nodeData.nonGroupingAncestor) {
212
+ return undefined;
213
+ }
214
+ return createNodeId(node.nodeData.nonGroupingAncestor);
215
+ }
216
+ function createHierarchyLevelOptions(model, nodeId) {
217
+ if (nodeId === undefined) {
218
+ return { instanceFilter: model.rootNode.instanceFilter, hierarchyLevelSizeLimit: model.rootNode.hierarchyLimit };
219
+ }
220
+ const modelNode = model.idToNode.get(nodeId);
221
+ if (!modelNode || isTreeModelInfoNode(modelNode)) {
222
+ return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };
223
+ }
224
+ return { instanceFilter: modelNode.instanceFilter, hierarchyLevelSizeLimit: modelNode.hierarchyLimit };
225
+ }
226
+ // istanbul ignore next
227
+ class NoopTreeLoader {
228
+ loadNodes() {
229
+ return EMPTY;
230
+ }
231
+ }
232
+ //# sourceMappingURL=TreeActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeActions.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeActions.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 { Draft, enableMapSet, produce } from \"immer\";\nimport { EMPTY, Observable, reduce, Subject, takeUntil } from \"rxjs\";\nimport { GenericInstanceFilter, HierarchyNode, HierarchyProvider } from \"@itwin/presentation-hierarchies\";\nimport { SelectionChangeType } from \"../UseSelectionHandler\";\nimport { HierarchyLevelOptions, ITreeLoader, LoadedTreePart, TreeLoader } from \"./TreeLoader\";\nimport { isTreeModelHierarchyNode, isTreeModelInfoNode, TreeModel, TreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from \"./TreeModel\";\nimport { createNodeId, sameNodes } from \"./Utils\";\n\nenableMapSet();\n\n/** @internal */\nexport class TreeActions {\n private _loader: ITreeLoader;\n private _currentModel: TreeModel;\n private _disposed = new Subject<void>();\n\n constructor(\n private _onModelChanged: (model: TreeModel) => void,\n seed?: TreeModel,\n ) {\n this._loader = new NoopTreeLoader();\n this._currentModel = seed ?? /* istanbul ignore next */ {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: { id: undefined, nodeData: undefined },\n };\n }\n\n private updateTreeModel(updater: (model: Draft<TreeModel>) => void) {\n const newModel = produce(this._currentModel, updater);\n if (this._currentModel === newModel) {\n return;\n }\n\n this._currentModel = newModel;\n this._onModelChanged(this._currentModel);\n }\n\n private handleLoadedHierarchy(parentId: string | undefined, loadedHierarchy: TreeModel) {\n this.updateTreeModel((model) => {\n TreeModel.addHierarchyPart(model, parentId, loadedHierarchy);\n });\n }\n\n private onLoadingComplete(parentId: string | undefined) {\n this.updateTreeModel((model) => {\n TreeModel.setIsLoading(model, parentId, false);\n });\n }\n\n private loadNodes(parentId: string, ignoreCache?: boolean) {\n const parentNode = this._currentModel.idToNode.get(parentId);\n // istanbul ignore if\n if (!parentNode || !isTreeModelHierarchyNode(parentNode)) {\n return;\n }\n\n this._loader\n .loadNodes({\n parent: parentNode,\n getHierarchyLevelOptions: (node) => createHierarchyLevelOptions(this._currentModel, getNonGroupedParentId(node)),\n shouldLoadChildren: (node) => !!node.nodeData.autoExpand,\n ignoreCache,\n })\n .pipe(collectTreePartsUntil(this._disposed))\n .subscribe({\n next: (loadedHierarchy) => {\n this.handleLoadedHierarchy(parentId, loadedHierarchy);\n },\n complete: () => {\n this.onLoadingComplete(parentId);\n },\n });\n }\n\n private reloadSubTree(parentId: string | undefined, oldModel: TreeModel, options?: { discardState?: boolean }) {\n const currModel = this._currentModel;\n const expandedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === true);\n const collapsedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === false);\n const getHierarchyLevelOptions = (node: TreeModelRootNode | TreeModelHierarchyNode) => {\n if (!!options?.discardState) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n const filteredNodeId = getNonGroupedParentId(node);\n return createHierarchyLevelOptions(filteredNodeId === parentId ? currModel : oldModel, filteredNodeId);\n };\n const shouldLoadChildren = (node: TreeModelHierarchyNode) => {\n if (expandedNodes.findIndex((expandedNode) => sameNodes(expandedNode.nodeData, node.nodeData)) !== -1) {\n return true;\n }\n if (collapsedNodes.findIndex((collapsedNode) => sameNodes(collapsedNode.nodeData, node.nodeData)) !== -1) {\n return false;\n }\n return !!node.nodeData.autoExpand;\n };\n const buildNode = (node: TreeModelHierarchyNode) => (!!options?.discardState || node.id === parentId ? node : addAttributes(node, oldModel));\n\n const rootNode = parentId !== undefined ? this.getNode(parentId) : currModel.rootNode;\n // istanbul ignore if\n if (!rootNode || isTreeModelInfoNode(rootNode)) {\n return;\n }\n\n if (parentId === undefined) {\n // cancel all ongoing requests\n this._disposed.next();\n }\n\n this._loader\n .loadNodes({ parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode })\n .pipe(collectTreePartsUntil(this._disposed, !!options?.discardState ? undefined : { ...currModel.rootNode }))\n .subscribe({\n next: (newModel) => {\n this.handleLoadedHierarchy(parentId, newModel);\n },\n complete: () => {\n this.onLoadingComplete(parentId);\n },\n });\n }\n\n public dispose() {\n this._disposed.next();\n }\n\n public setHierarchyProvider(provider?: HierarchyProvider) {\n this._loader = provider ? new TreeLoader(provider) : /* istanbul ignore next */ new NoopTreeLoader();\n }\n\n public getNode(nodeId: string | undefined): TreeModelNode | TreeModelRootNode | undefined {\n return TreeModel.getNode(this._currentModel, nodeId);\n }\n\n public selectNodes(nodeIds: Array<string>, changeType: SelectionChangeType) {\n this.updateTreeModel((model) => {\n TreeModel.selectNodes(model, nodeIds, changeType);\n });\n }\n\n public expandNode(nodeId: string, isExpanded: boolean) {\n let childrenAction: ReturnType<typeof TreeModel.expandNode> = \"none\";\n this.updateTreeModel((model) => {\n childrenAction = TreeModel.expandNode(model, nodeId, isExpanded);\n });\n\n if (childrenAction === \"none\") {\n return;\n }\n\n this.loadNodes(nodeId, childrenAction === \"reloadChildren\");\n }\n\n public setHierarchyLimit(nodeId: string | undefined, limit?: number | \"unbounded\") {\n const oldModel = this._currentModel;\n let loadChildren = false;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setHierarchyLimit(model, nodeId, limit);\n });\n\n if (!loadChildren) {\n return;\n }\n\n this.reloadSubTree(nodeId, oldModel);\n }\n\n public setInstanceFilter(nodeId: string | undefined, filter?: GenericInstanceFilter) {\n const oldModel = this._currentModel;\n let loadChildren = false;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setInstanceFilter(model, nodeId, filter);\n });\n\n if (!loadChildren) {\n return;\n }\n\n this.reloadSubTree(nodeId, oldModel);\n }\n\n public reloadTree(options?: { discardState?: boolean }) {\n const oldModel = this._currentModel;\n this.updateTreeModel((model) => {\n model.rootNode.isLoading = true;\n });\n\n this.reloadSubTree(undefined, oldModel, { ...options });\n }\n}\n\nfunction collectTreePartsUntil(untilNotifier: Observable<void>, rootNode?: TreeModelRootNode) {\n return (source: Observable<LoadedTreePart>) =>\n source.pipe(\n reduce<LoadedTreePart, TreeModel>(\n (treeModel, loadedPart) => {\n addNodesToModel(treeModel, loadedPart);\n return treeModel;\n },\n {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: rootNode ?? { id: undefined, nodeData: undefined },\n },\n ),\n takeUntil(untilNotifier),\n );\n}\n\nfunction addNodesToModel(model: TreeModel, hierarchyPart: LoadedTreePart) {\n model.parentChildMap.set(\n hierarchyPart.parentId,\n hierarchyPart.loadedNodes.map((node) => node.id),\n );\n for (const node of hierarchyPart.loadedNodes) {\n model.idToNode.set(node.id, node);\n }\n const parentNode = hierarchyPart.parentId ? model.idToNode.get(hierarchyPart.parentId) : undefined;\n if (parentNode && isTreeModelHierarchyNode(parentNode)) {\n parentNode.isExpanded = true;\n }\n}\n\nfunction addAttributes(node: TreeModelHierarchyNode, oldModel: TreeModel) {\n const oldNode = oldModel.idToNode.get(node.id);\n if (oldNode && isTreeModelHierarchyNode(oldNode)) {\n node.hierarchyLimit = oldNode.hierarchyLimit;\n node.instanceFilter = oldNode.instanceFilter;\n node.isSelected = oldNode.isSelected;\n }\n return node;\n}\n\nfunction collectNodes(parentId: string | undefined, model: TreeModel, pred: (node: TreeModelHierarchyNode) => boolean): TreeModelHierarchyNode[] {\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return [];\n }\n\n if (parentId === undefined) {\n return currentChildren.flatMap((child) => collectNodes(child, model, pred));\n }\n\n const currNode = model.idToNode.get(parentId);\n if (!currNode || !isTreeModelHierarchyNode(currNode) || !pred(currNode)) {\n return [];\n }\n\n return [currNode, ...currentChildren.flatMap((child) => collectNodes(child, model, pred))];\n}\n\nfunction getNonGroupedParentId(node: TreeModelHierarchyNode | TreeModelRootNode) {\n if (!node.nodeData || !HierarchyNode.isGroupingNode(node.nodeData)) {\n return node.id;\n }\n\n if (!node.nodeData.nonGroupingAncestor) {\n return undefined;\n }\n\n return createNodeId(node.nodeData.nonGroupingAncestor);\n}\n\nfunction createHierarchyLevelOptions(model: TreeModel, nodeId: string | undefined): HierarchyLevelOptions {\n if (nodeId === undefined) {\n return { instanceFilter: model.rootNode.instanceFilter, hierarchyLevelSizeLimit: model.rootNode.hierarchyLimit };\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode || isTreeModelInfoNode(modelNode)) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n return { instanceFilter: modelNode.instanceFilter, hierarchyLevelSizeLimit: modelNode.hierarchyLimit };\n}\n\n// istanbul ignore next\nclass NoopTreeLoader implements ITreeLoader {\n public loadNodes(): Observable<LoadedTreePart> {\n return EMPTY;\n }\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import { Observable } from "rxjs";
2
+ import { GenericInstanceFilter, HierarchyProvider } from "@itwin/presentation-hierarchies";
3
+ import { TreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from "./TreeModel";
4
+ /** @internal */
5
+ export interface LoadedTreePart {
6
+ parentId: string | undefined;
7
+ loadedNodes: TreeModelNode[];
8
+ }
9
+ /** @internal */
10
+ export interface HierarchyLevelOptions {
11
+ instanceFilter?: GenericInstanceFilter;
12
+ hierarchyLevelSizeLimit?: number | "unbounded";
13
+ }
14
+ /** @internal */
15
+ export interface LoadNodesOptions {
16
+ parent: TreeModelHierarchyNode | TreeModelRootNode;
17
+ getHierarchyLevelOptions: (node: TreeModelRootNode | TreeModelHierarchyNode) => HierarchyLevelOptions;
18
+ shouldLoadChildren: (node: TreeModelHierarchyNode) => boolean;
19
+ buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;
20
+ ignoreCache?: boolean;
21
+ }
22
+ /** @internal */
23
+ export interface ITreeLoader {
24
+ loadNodes(options: LoadNodesOptions): Observable<LoadedTreePart>;
25
+ }
26
+ /** @internal */
27
+ export declare class TreeLoader implements ITreeLoader {
28
+ private _hierarchyProvider;
29
+ constructor(_hierarchyProvider: HierarchyProvider);
30
+ private loadChildren;
31
+ loadNodes({ shouldLoadChildren, ...options }: LoadNodesOptions): Observable<LoadedTreePart>;
32
+ }
33
+ //# sourceMappingURL=TreeLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeLoader.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeLoader.ts"],"names":[],"mappings":"AAKA,OAAO,EAA2C,UAAU,EAAe,MAAM,MAAM,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAiB,iBAAiB,EAA0B,MAAM,iCAAiC,CAAC;AAClI,OAAO,EAA4B,sBAAsB,EAAqB,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGpI,gBAAgB;AAChB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,gBAAgB;AAChB,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,uBAAuB,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CAChD;AAED,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,sBAAsB,GAAG,iBAAiB,CAAC;IACnD,wBAAwB,EAAE,CAAC,IAAI,EAAE,iBAAiB,GAAG,sBAAsB,KAAK,qBAAqB,CAAC;IACtG,kBAAkB,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,OAAO,CAAC;IAC9D,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,sBAAsB,CAAC;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,gBAAgB;AAChB,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;CAClE;AAED,gBAAgB;AAChB,qBAAa,UAAW,YAAW,WAAW;IAChC,OAAO,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,iBAAiB;IAEzD,OAAO,CAAC,YAAY;IAyCb,SAAS,CAAC,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE,EAAE,gBAAgB;CAStE"}
@@ -0,0 +1,67 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { catchError, expand, from, map, mergeMap, of, toArray } from "rxjs";
6
+ import { RowsLimitExceededError } from "@itwin/presentation-hierarchies";
7
+ import { isTreeModelHierarchyNode } from "./TreeModel";
8
+ import { createNodeId } from "./Utils";
9
+ /** @internal */
10
+ export class TreeLoader {
11
+ _hierarchyProvider;
12
+ constructor(_hierarchyProvider) {
13
+ this._hierarchyProvider = _hierarchyProvider;
14
+ }
15
+ loadChildren({ parent, getHierarchyLevelOptions, buildNode, ignoreCache }) {
16
+ const { instanceFilter, hierarchyLevelSizeLimit } = getHierarchyLevelOptions(parent);
17
+ const infoNodeIdBase = `${parent.id ?? "<root>"}`;
18
+ const treeModelNodesFactory = createTreeModelNodesFactory(buildNode);
19
+ return from(this._hierarchyProvider.getNodes({
20
+ parentNode: parent.nodeData,
21
+ hierarchyLevelSizeLimit,
22
+ instanceFilter,
23
+ ignoreCache,
24
+ })).pipe(toArray(), catchError((err) => {
25
+ const nodeProps = {
26
+ id: `${infoNodeIdBase}-${err.message}`,
27
+ parentId: parent.id,
28
+ };
29
+ if (err instanceof RowsLimitExceededError) {
30
+ return of([{ ...nodeProps, type: "ResultSetTooLarge", resultSetSizeLimit: err.limit }]);
31
+ }
32
+ return of([{ ...nodeProps, type: "Unknown", message: "Failed to create hierarchy level" }]);
33
+ }), map((childNodes) => ({
34
+ parentId: parent.id,
35
+ loadedNodes: instanceFilter && childNodes.length === 0
36
+ ? [
37
+ {
38
+ id: `${infoNodeIdBase}-no-filter-matches`,
39
+ parentId: parent.id,
40
+ type: "NoFilterMatches",
41
+ },
42
+ ]
43
+ : childNodes.map(treeModelNodesFactory),
44
+ })));
45
+ }
46
+ loadNodes({ shouldLoadChildren, ...options }) {
47
+ return this.loadChildren(options).pipe(expand((loadedPart) => from(loadedPart.loadedNodes.filter((node) => isTreeModelHierarchyNode(node) && shouldLoadChildren(node))).pipe(mergeMap((node) => this.loadChildren({ ...options, parent: node })))));
48
+ }
49
+ }
50
+ function createTreeModelNodesFactory(buildNode) {
51
+ return (node) => {
52
+ if (!isHierarchyNode(node)) {
53
+ return node;
54
+ }
55
+ const modelNode = {
56
+ id: createNodeId(node),
57
+ children: node.children,
58
+ label: node.label,
59
+ nodeData: node,
60
+ };
61
+ return buildNode ? buildNode(modelNode) : modelNode;
62
+ };
63
+ }
64
+ function isHierarchyNode(node) {
65
+ return "key" in node && node.key !== undefined;
66
+ }
67
+ //# sourceMappingURL=TreeLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeLoader.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeLoader.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 { catchError, expand, from, map, mergeMap, Observable, of, toArray } from \"rxjs\";\nimport { GenericInstanceFilter, HierarchyNode, HierarchyProvider, RowsLimitExceededError } from \"@itwin/presentation-hierarchies\";\nimport { isTreeModelHierarchyNode, TreeModelHierarchyNode, TreeModelInfoNode, TreeModelNode, TreeModelRootNode } from \"./TreeModel\";\nimport { createNodeId } from \"./Utils\";\n\n/** @internal */\nexport interface LoadedTreePart {\n parentId: string | undefined;\n loadedNodes: TreeModelNode[];\n}\n\n/** @internal */\nexport interface HierarchyLevelOptions {\n instanceFilter?: GenericInstanceFilter;\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n}\n\n/** @internal */\nexport interface LoadNodesOptions {\n parent: TreeModelHierarchyNode | TreeModelRootNode;\n getHierarchyLevelOptions: (node: TreeModelRootNode | TreeModelHierarchyNode) => HierarchyLevelOptions;\n shouldLoadChildren: (node: TreeModelHierarchyNode) => boolean;\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;\n ignoreCache?: boolean;\n}\n\n/** @internal */\nexport interface ITreeLoader {\n loadNodes(options: LoadNodesOptions): Observable<LoadedTreePart>;\n}\n\n/** @internal */\nexport class TreeLoader implements ITreeLoader {\n constructor(private _hierarchyProvider: HierarchyProvider) {}\n\n private loadChildren({ parent, getHierarchyLevelOptions, buildNode, ignoreCache }: Omit<LoadNodesOptions, \"shouldLoadChildren\">) {\n const { instanceFilter, hierarchyLevelSizeLimit } = getHierarchyLevelOptions(parent);\n const infoNodeIdBase = `${parent.id ?? \"<root>\"}`;\n const treeModelNodesFactory = createTreeModelNodesFactory(buildNode);\n return from(\n this._hierarchyProvider.getNodes({\n parentNode: parent.nodeData,\n hierarchyLevelSizeLimit,\n instanceFilter,\n ignoreCache,\n }),\n ).pipe(\n toArray(),\n catchError((err) => {\n const nodeProps = {\n id: `${infoNodeIdBase}-${err.message}`,\n parentId: parent.id,\n };\n if (err instanceof RowsLimitExceededError) {\n return of([{ ...nodeProps, type: \"ResultSetTooLarge\" as const, resultSetSizeLimit: err.limit }]);\n }\n return of([{ ...nodeProps, type: \"Unknown\" as const, message: \"Failed to create hierarchy level\" }]);\n }),\n map(\n (childNodes): LoadedTreePart => ({\n parentId: parent.id,\n loadedNodes:\n instanceFilter && childNodes.length === 0\n ? [\n {\n id: `${infoNodeIdBase}-no-filter-matches`,\n parentId: parent.id,\n type: \"NoFilterMatches\" as const,\n },\n ]\n : childNodes.map(treeModelNodesFactory),\n }),\n ),\n );\n }\n\n public loadNodes({ shouldLoadChildren, ...options }: LoadNodesOptions) {\n return this.loadChildren(options).pipe(\n expand((loadedPart) =>\n from(loadedPart.loadedNodes.filter((node): node is TreeModelHierarchyNode => isTreeModelHierarchyNode(node) && shouldLoadChildren(node))).pipe(\n mergeMap((node) => this.loadChildren({ ...options, parent: node })),\n ),\n ),\n );\n }\n}\n\nfunction createTreeModelNodesFactory(\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode,\n): (node: TreeModelInfoNode | HierarchyNode) => TreeModelNode {\n return (node: TreeModelInfoNode | HierarchyNode) => {\n if (!isHierarchyNode(node)) {\n return node;\n }\n\n const modelNode: TreeModelHierarchyNode = {\n id: createNodeId(node),\n children: node.children,\n label: node.label,\n nodeData: node,\n };\n return buildNode ? buildNode(modelNode) : modelNode;\n };\n}\n\nfunction isHierarchyNode(node: TreeModelInfoNode | HierarchyNode): node is HierarchyNode {\n return \"key\" in node && node.key !== undefined;\n}\n"]}
@@ -0,0 +1,70 @@
1
+ import { GenericInstanceFilter, HierarchyNode } from "@itwin/presentation-hierarchies";
2
+ import { SelectionChangeType } from "../UseSelectionHandler";
3
+ /** @internal */
4
+ export interface TreeModelRootNode {
5
+ id: undefined;
6
+ nodeData: undefined;
7
+ hierarchyLimit?: number | "unbounded";
8
+ instanceFilter?: GenericInstanceFilter;
9
+ isLoading?: boolean;
10
+ }
11
+ /** @internal */
12
+ export interface TreeModelHierarchyNode {
13
+ id: string;
14
+ nodeData: HierarchyNode;
15
+ label: string;
16
+ children: boolean;
17
+ isLoading?: boolean;
18
+ isExpanded?: boolean;
19
+ isSelected?: boolean;
20
+ hierarchyLimit?: number | "unbounded";
21
+ instanceFilter?: GenericInstanceFilter;
22
+ }
23
+ /** @internal */
24
+ export interface TreeModelGenericInfoNode {
25
+ id: string;
26
+ parentId: string | undefined;
27
+ type: "Unknown";
28
+ message: string;
29
+ }
30
+ /** @internal */
31
+ export interface TreeModelNoFilterMatchesInfoNode {
32
+ id: string;
33
+ parentId: string | undefined;
34
+ type: "NoFilterMatches";
35
+ }
36
+ /** @internal */
37
+ export interface TreeModelResultSetTooLargeInfoNode {
38
+ id: string;
39
+ parentId: string | undefined;
40
+ type: "ResultSetTooLarge";
41
+ resultSetSizeLimit: number;
42
+ }
43
+ /** @internal */
44
+ export type TreeModelInfoNode = TreeModelGenericInfoNode | TreeModelResultSetTooLargeInfoNode | TreeModelNoFilterMatchesInfoNode;
45
+ /** @internal */
46
+ export type TreeModelNode = TreeModelHierarchyNode | TreeModelInfoNode;
47
+ /** @internal */
48
+ export declare function isTreeModelHierarchyNode(node: TreeModelHierarchyNode | TreeModelInfoNode | TreeModelRootNode): node is TreeModelHierarchyNode;
49
+ /** @internal */
50
+ export declare function isTreeModelInfoNode(node: TreeModelHierarchyNode | TreeModelInfoNode | TreeModelRootNode): node is TreeModelInfoNode;
51
+ /** @internal */
52
+ export interface TreeModel {
53
+ parentChildMap: Map<string | undefined, string[]>;
54
+ idToNode: Map<string, TreeModelNode>;
55
+ rootNode: TreeModelRootNode;
56
+ }
57
+ /** @internal */
58
+ export declare namespace TreeModel {
59
+ function expandNode(model: TreeModel, nodeId: string, isExpanded: boolean): "none" | "loadChildren" | "reloadChildren";
60
+ /** @internal */
61
+ function addHierarchyPart(model: TreeModel, rootId: string | undefined, hierarchyPart: TreeModel): void;
62
+ function removeSubTree(model: TreeModel, parentId: string | undefined): void;
63
+ function setHierarchyLimit(model: TreeModel, nodeId: string | undefined, limit?: number | "unbounded"): boolean;
64
+ function setInstanceFilter(model: TreeModel, nodeId: string | undefined, filter?: GenericInstanceFilter): boolean;
65
+ function selectNodes(model: TreeModel, nodeIds: Array<string>, changeType: SelectionChangeType): void;
66
+ function isNodeSelected(model: TreeModel, nodeId: string): boolean;
67
+ function getNode(model: TreeModel, nodeId: string | undefined): TreeModelNode | TreeModelRootNode | undefined;
68
+ function setIsLoading(model: TreeModel, nodeId: string | undefined, isLoading: boolean): void;
69
+ }
70
+ //# sourceMappingURL=TreeModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeModel.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeModel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ /** @internal */
6
+ export function isTreeModelHierarchyNode(node) {
7
+ return "nodeData" in node && node.nodeData !== undefined;
8
+ }
9
+ /** @internal */
10
+ export function isTreeModelInfoNode(node) {
11
+ return "type" in node && node.type !== undefined;
12
+ }
13
+ /** @internal */
14
+ export var TreeModel;
15
+ (function (TreeModel) {
16
+ function expandNode(model, nodeId, isExpanded) {
17
+ const node = model.idToNode.get(nodeId);
18
+ if (!node || !isTreeModelHierarchyNode(node)) {
19
+ return "none";
20
+ }
21
+ node.isExpanded = isExpanded;
22
+ if (!isExpanded || !node.children) {
23
+ return "none";
24
+ }
25
+ const children = model.parentChildMap.get(node.id);
26
+ if (!children) {
27
+ node.isLoading = true;
28
+ return "loadChildren";
29
+ }
30
+ if (children.length !== 1) {
31
+ return "none";
32
+ }
33
+ const firstChild = TreeModel.getNode(model, children[0]);
34
+ if (!firstChild || !isTreeModelInfoNode(firstChild) || firstChild.type !== "Unknown") {
35
+ return "none";
36
+ }
37
+ // remove subtree if there is only one `Unknown` info node in order to attempt reloading children
38
+ TreeModel.removeSubTree(model, nodeId);
39
+ node.isLoading = true;
40
+ return "reloadChildren";
41
+ }
42
+ TreeModel.expandNode = expandNode;
43
+ /** @internal */
44
+ function addHierarchyPart(model, rootId, hierarchyPart) {
45
+ removeSubTree(model, rootId);
46
+ for (const [parentId, children] of hierarchyPart.parentChildMap) {
47
+ model.parentChildMap.set(parentId, children);
48
+ }
49
+ for (const [nodeId, node] of hierarchyPart.idToNode) {
50
+ model.idToNode.set(nodeId, node);
51
+ }
52
+ const parentNode = rootId !== undefined ? model.idToNode.get(rootId) : model.rootNode;
53
+ // istanbul ignore else
54
+ if (parentNode && !isTreeModelInfoNode(parentNode)) {
55
+ parentNode.isLoading = false;
56
+ }
57
+ }
58
+ TreeModel.addHierarchyPart = addHierarchyPart;
59
+ function removeSubTree(model, parentId) {
60
+ const currentChildren = model.parentChildMap.get(parentId);
61
+ if (!currentChildren) {
62
+ return;
63
+ }
64
+ model.parentChildMap.delete(parentId);
65
+ for (const childId of currentChildren) {
66
+ const childNode = model.idToNode.get(childId);
67
+ if (childNode && isTreeModelHierarchyNode(childNode)) {
68
+ removeSubTree(model, childNode.id);
69
+ }
70
+ model.idToNode.delete(childId);
71
+ }
72
+ }
73
+ TreeModel.removeSubTree = removeSubTree;
74
+ function setHierarchyLimit(model, nodeId, limit) {
75
+ return updateForReload(model, nodeId, (node) => {
76
+ node.hierarchyLimit = limit;
77
+ });
78
+ }
79
+ TreeModel.setHierarchyLimit = setHierarchyLimit;
80
+ function setInstanceFilter(model, nodeId, filter) {
81
+ return updateForReload(model, nodeId, (node) => {
82
+ node.instanceFilter = filter;
83
+ });
84
+ }
85
+ TreeModel.setInstanceFilter = setInstanceFilter;
86
+ function selectNodes(model, nodeIds, changeType) {
87
+ if (changeType === "replace") {
88
+ for (const [nodeId, node] of model.idToNode) {
89
+ if (!isTreeModelHierarchyNode(node)) {
90
+ continue;
91
+ }
92
+ node.isSelected = !!nodeIds.find((id) => id === nodeId);
93
+ }
94
+ return;
95
+ }
96
+ for (const nodeId of nodeIds) {
97
+ const modelNode = model.idToNode.get(nodeId);
98
+ if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {
99
+ return;
100
+ }
101
+ modelNode.isSelected = changeType === "add";
102
+ }
103
+ }
104
+ TreeModel.selectNodes = selectNodes;
105
+ function isNodeSelected(model, nodeId) {
106
+ const currentNode = model.idToNode.get(nodeId);
107
+ return !!currentNode && isTreeModelHierarchyNode(currentNode) && !!currentNode.isSelected;
108
+ }
109
+ TreeModel.isNodeSelected = isNodeSelected;
110
+ function getNode(model, nodeId) {
111
+ if (!nodeId) {
112
+ return model.rootNode;
113
+ }
114
+ return model.idToNode.get(nodeId);
115
+ }
116
+ TreeModel.getNode = getNode;
117
+ function setIsLoading(model, nodeId, isLoading) {
118
+ if (nodeId === undefined) {
119
+ model.rootNode.isLoading = isLoading;
120
+ return;
121
+ }
122
+ const modelNode = model.idToNode.get(nodeId);
123
+ // istanbul ignore if
124
+ if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {
125
+ return;
126
+ }
127
+ modelNode.isLoading = isLoading;
128
+ }
129
+ TreeModel.setIsLoading = setIsLoading;
130
+ })(TreeModel || (TreeModel = {}));
131
+ function updateForReload(model, nodeId, update) {
132
+ TreeModel.removeSubTree(model, nodeId);
133
+ if (nodeId === undefined) {
134
+ update(model.rootNode);
135
+ model.rootNode.isLoading = true;
136
+ return true;
137
+ }
138
+ const modelNode = model.idToNode.get(nodeId);
139
+ if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {
140
+ return false;
141
+ }
142
+ update(modelNode);
143
+ if (modelNode.isExpanded) {
144
+ modelNode.isLoading = true;
145
+ return true;
146
+ }
147
+ return false;
148
+ }
149
+ //# sourceMappingURL=TreeModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeModel.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeModel.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 { GenericInstanceFilter, HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { SelectionChangeType } from \"../UseSelectionHandler\";\n\n/** @internal */\nexport interface TreeModelRootNode {\n id: undefined;\n nodeData: undefined;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n isLoading?: boolean;\n}\n\n/** @internal */\nexport interface TreeModelHierarchyNode {\n id: string;\n nodeData: HierarchyNode;\n label: string;\n children: boolean;\n isLoading?: boolean;\n isExpanded?: boolean;\n isSelected?: boolean;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n}\n\n/** @internal */\nexport interface TreeModelGenericInfoNode {\n id: string;\n parentId: string | undefined;\n type: \"Unknown\";\n message: string;\n}\n\n/** @internal */\nexport interface TreeModelNoFilterMatchesInfoNode {\n id: string;\n parentId: string | undefined;\n type: \"NoFilterMatches\";\n}\n\n/** @internal */\nexport interface TreeModelResultSetTooLargeInfoNode {\n id: string;\n parentId: string | undefined;\n type: \"ResultSetTooLarge\";\n resultSetSizeLimit: number;\n}\n\n/** @internal */\nexport type TreeModelInfoNode = TreeModelGenericInfoNode | TreeModelResultSetTooLargeInfoNode | TreeModelNoFilterMatchesInfoNode;\n\n/** @internal */\nexport type TreeModelNode = TreeModelHierarchyNode | TreeModelInfoNode;\n\n/** @internal */\nexport function isTreeModelHierarchyNode(node: TreeModelHierarchyNode | TreeModelInfoNode | TreeModelRootNode): node is TreeModelHierarchyNode {\n return \"nodeData\" in node && node.nodeData !== undefined;\n}\n\n/** @internal */\nexport function isTreeModelInfoNode(node: TreeModelHierarchyNode | TreeModelInfoNode | TreeModelRootNode): node is TreeModelInfoNode {\n return \"type\" in node && node.type !== undefined;\n}\n\n/** @internal */\nexport interface TreeModel {\n parentChildMap: Map<string | undefined, string[]>;\n idToNode: Map<string, TreeModelNode>;\n rootNode: TreeModelRootNode;\n}\n\n/** @internal */\nexport namespace TreeModel {\n export function expandNode(model: TreeModel, nodeId: string, isExpanded: boolean): \"none\" | \"loadChildren\" | \"reloadChildren\" {\n const node = model.idToNode.get(nodeId);\n if (!node || !isTreeModelHierarchyNode(node)) {\n return \"none\";\n }\n\n node.isExpanded = isExpanded;\n if (!isExpanded || !node.children) {\n return \"none\";\n }\n\n const children = model.parentChildMap.get(node.id);\n if (!children) {\n node.isLoading = true;\n return \"loadChildren\";\n }\n\n if (children.length !== 1) {\n return \"none\";\n }\n\n const firstChild = TreeModel.getNode(model, children[0]);\n if (!firstChild || !isTreeModelInfoNode(firstChild) || firstChild.type !== \"Unknown\") {\n return \"none\";\n }\n\n // remove subtree if there is only one `Unknown` info node in order to attempt reloading children\n TreeModel.removeSubTree(model, nodeId);\n node.isLoading = true;\n return \"reloadChildren\";\n }\n\n /** @internal */\n export function addHierarchyPart(model: TreeModel, rootId: string | undefined, hierarchyPart: TreeModel): void {\n removeSubTree(model, rootId);\n\n for (const [parentId, children] of hierarchyPart.parentChildMap) {\n model.parentChildMap.set(parentId, children);\n }\n\n for (const [nodeId, node] of hierarchyPart.idToNode) {\n model.idToNode.set(nodeId, node);\n }\n\n const parentNode = rootId !== undefined ? model.idToNode.get(rootId) : model.rootNode;\n // istanbul ignore else\n if (parentNode && !isTreeModelInfoNode(parentNode)) {\n parentNode.isLoading = false;\n }\n }\n\n export function removeSubTree(model: TreeModel, parentId: string | undefined): void {\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return;\n }\n model.parentChildMap.delete(parentId);\n\n for (const childId of currentChildren) {\n const childNode = model.idToNode.get(childId);\n if (childNode && isTreeModelHierarchyNode(childNode)) {\n removeSubTree(model, childNode.id);\n }\n model.idToNode.delete(childId);\n }\n }\n\n export function setHierarchyLimit(model: TreeModel, nodeId: string | undefined, limit?: number | \"unbounded\"): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.hierarchyLimit = limit;\n });\n }\n\n export function setInstanceFilter(model: TreeModel, nodeId: string | undefined, filter?: GenericInstanceFilter): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.instanceFilter = filter;\n });\n }\n\n export function selectNodes(model: TreeModel, nodeIds: Array<string>, changeType: SelectionChangeType) {\n if (changeType === \"replace\") {\n for (const [nodeId, node] of model.idToNode) {\n if (!isTreeModelHierarchyNode(node)) {\n continue;\n }\n node.isSelected = !!nodeIds.find((id) => id === nodeId);\n }\n return;\n }\n for (const nodeId of nodeIds) {\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {\n return;\n }\n modelNode.isSelected = changeType === \"add\";\n }\n }\n\n export function isNodeSelected(model: TreeModel, nodeId: string): boolean {\n const currentNode = model.idToNode.get(nodeId);\n return !!currentNode && isTreeModelHierarchyNode(currentNode) && !!currentNode.isSelected;\n }\n\n export function getNode(model: TreeModel, nodeId: string | undefined): TreeModelNode | TreeModelRootNode | undefined {\n if (!nodeId) {\n return model.rootNode;\n }\n return model.idToNode.get(nodeId);\n }\n\n export function setIsLoading(model: TreeModel, nodeId: string | undefined, isLoading: boolean) {\n if (nodeId === undefined) {\n model.rootNode.isLoading = isLoading;\n return;\n }\n const modelNode = model.idToNode.get(nodeId);\n // istanbul ignore if\n if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {\n return;\n }\n modelNode.isLoading = isLoading;\n }\n}\n\nfunction updateForReload(model: TreeModel, nodeId: string | undefined, update: (node: TreeModelHierarchyNode | TreeModelRootNode) => void) {\n TreeModel.removeSubTree(model, nodeId);\n if (nodeId === undefined) {\n update(model.rootNode);\n model.rootNode.isLoading = true;\n return true;\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode || !isTreeModelHierarchyNode(modelNode)) {\n return false;\n }\n\n update(modelNode);\n if (modelNode.isExpanded) {\n modelNode.isLoading = true;\n return true;\n }\n return false;\n}\n"]}