@itwin/tree-widget-react 4.0.0-alpha.13 → 4.0.0-alpha.15

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 (121) hide show
  1. package/CHANGELOG.md +62 -1
  2. package/README.md +50 -2
  3. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  4. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.css +1 -1
  5. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  6. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -2
  7. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  8. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  9. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  10. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +1 -0
  11. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +25 -19
  12. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  13. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +3 -5
  14. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  15. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +7 -7
  16. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +21 -17
  17. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  18. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.d.ts +0 -2
  19. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js +352 -311
  20. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js.map +1 -1
  21. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js +4 -3
  22. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js.map +1 -1
  23. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.d.ts +2 -2
  24. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.js +4 -3
  25. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.js.map +1 -1
  26. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.d.ts +1 -1
  27. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js +2 -2
  28. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js.map +1 -1
  29. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +10 -1
  30. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +268 -0
  31. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
  32. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.d.ts +3 -2
  33. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +46 -8
  34. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
  35. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +20 -7
  36. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +96 -20
  37. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
  38. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +2 -2
  39. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +1 -1
  40. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.d.ts +3 -1
  41. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js +410 -253
  42. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js.map +1 -1
  43. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/FilteredTree.d.ts +37 -0
  44. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/FilteredTree.js +193 -0
  45. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/FilteredTree.js.map +1 -0
  46. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.d.ts +18 -0
  47. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.js +51 -0
  48. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.js.map +1 -0
  49. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +4 -0
  50. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +20 -17
  51. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  52. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.d.ts +2 -2
  53. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +1 -1
  54. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  55. package/lib/esm/tree-widget-react/components/trees/common/Utils.d.ts +4 -0
  56. package/lib/esm/tree-widget-react/components/trees/common/Utils.js +49 -0
  57. package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
  58. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.d.ts +1 -1
  59. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js +2 -2
  60. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js.map +1 -1
  61. package/lib/esm/tree-widget-react/components/trees/common/components/EmptyTree.d.ts +6 -0
  62. package/lib/esm/tree-widget-react/components/trees/common/components/EmptyTree.js +4 -0
  63. package/lib/esm/tree-widget-react/components/trees/common/components/EmptyTree.js.map +1 -1
  64. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.d.ts +23 -3
  65. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js +26 -5
  66. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
  67. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  68. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +7 -8
  69. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  70. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +3 -3
  71. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
  72. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +2 -2
  73. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  74. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +3 -3
  75. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js +10 -9
  76. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  77. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js +49 -34
  78. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +1 -1
  79. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js.map +1 -1
  80. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +7 -17
  81. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +26 -16
  82. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -1
  83. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +5 -5
  84. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +3 -2
  85. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -1
  86. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
  87. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +2 -2
  88. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  89. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.d.ts +1 -1
  90. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
  91. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +2 -2
  92. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +2 -2
  93. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  94. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +1 -1
  95. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
  97. package/lib/esm/tree-widget-react/components/trees/index.d.ts +2 -0
  98. package/lib/esm/tree-widget-react/components/trees/index.js +3 -0
  99. package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
  100. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +2 -2
  101. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +3 -2
  102. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  103. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -1
  104. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +12 -10
  106. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +33 -29
  107. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  108. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +19 -1
  109. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +12 -5
  110. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +6 -4
  112. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +24 -11
  113. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  114. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +35 -44
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +373 -186
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +11 -2
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +88 -34
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
  120. package/lib/public/locales/en/TreeWidget.json +11 -1
  121. package/package.json +12 -12
@@ -2,16 +2,16 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- import { concat, concatAll, defaultIfEmpty, defer, distinct, EMPTY, filter, firstValueFrom, forkJoin, from, fromEventPattern, map, merge, mergeAll, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeUntil, tap, toArray, } from "rxjs";
5
+ import { concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, firstValueFrom, forkJoin, from, fromEventPattern, map, merge, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeUntil, tap, } from "rxjs";
6
6
  import { assert, Id64 } from "@itwin/core-bentley";
7
7
  import { PerModelCategoryVisibility } from "@itwin/core-frontend";
8
8
  import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
9
9
  import { AlwaysAndNeverDrawnElementInfo } from "../../common/internal/AlwaysAndNeverDrawnElementInfo.js";
10
10
  import { toVoidPromise } from "../../common/internal/Rxjs.js";
11
11
  import { createVisibilityStatus } from "../../common/internal/Tooltip.js";
12
- import { getClassesByView, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../../common/internal/Utils.js";
12
+ import { getClassesByView, getSetFromId64Arg, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../../common/internal/Utils.js";
13
13
  import { createVisibilityChangeEventListener } from "../../common/internal/VisibilityChangeEventListener.js";
14
- import { changeElementStateNoChildrenOperator, enableCategoryDisplay, enableSubCategoryDisplay, filterSubModeledElementIds, getElementOverriddenVisibility, getElementVisibility, getSubModeledElementsVisibilityStatus, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses, } from "../../common/internal/VisibilityUtils.js";
14
+ import { changeElementStateNoChildrenOperator, enableCategoryDisplay, enableSubCategoryDisplay, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses, } from "../../common/internal/VisibilityUtils.js";
15
15
  import { createVisibilityHandlerResult } from "../../common/UseHierarchyVisibility.js";
16
16
  import { CategoriesTreeNode } from "./CategoriesTreeNode.js";
17
17
  import { createFilteredTree, parseCategoryKey, parseSubCategoryKey } from "./FilteredTree.js";
@@ -38,7 +38,7 @@ class CategoriesTreeVisibilityHandlerImpl {
38
38
  listeners: {
39
39
  models: true,
40
40
  categories: true,
41
- elements: _props.hierarchyConfig.showElements,
41
+ elements: true,
42
42
  displayStyle: true,
43
43
  },
44
44
  });
@@ -101,26 +101,26 @@ class CategoriesTreeVisibilityHandlerImpl {
101
101
  return this.getFilteredNodeVisibility({ node });
102
102
  }
103
103
  if (HierarchyNode.isClassGroupingNode(node)) {
104
- return this.getClassGroupingNodeDisplayStatus(node);
104
+ const nodeInfo = this.getGroupingNodeInfo(node);
105
+ return this.getGroupedElementsVisibilityStatus({ categoryId: nodeInfo.categoryId, modelElementsMap: nodeInfo.modelElementsMap });
105
106
  }
106
107
  if (!HierarchyNode.isInstancesNode(node)) {
107
108
  return of(createVisibilityStatus("disabled"));
108
109
  }
109
110
  if (CategoriesTreeNode.isDefinitionContainerNode(node)) {
110
- return this.getDefinitionContainerDisplayStatus({
111
+ return this.getDefinitionContainersVisibilityStatus({
111
112
  definitionContainerIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
112
113
  });
113
114
  }
114
115
  if (CategoriesTreeNode.isModelNode(node)) {
115
- return this.getModelVisibilityStatus({
116
+ return this.getModelsVisibilityStatus({
116
117
  modelIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
117
118
  });
118
119
  }
119
120
  if (CategoriesTreeNode.isCategoryNode(node)) {
120
- return this.getCategoryDisplayStatus({
121
+ return this.getCategoriesVisibilityStatus({
121
122
  categoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
122
123
  modelId: CategoriesTreeNode.getModelId(node),
123
- ignoreSubCategories: node.extendedData?.isCategoryOfSubModel,
124
124
  });
125
125
  }
126
126
  const categoryId = CategoriesTreeNode.getCategoryId(node);
@@ -128,7 +128,7 @@ class CategoriesTreeVisibilityHandlerImpl {
128
128
  return of(createVisibilityStatus("disabled"));
129
129
  }
130
130
  if (CategoriesTreeNode.isSubCategoryNode(node)) {
131
- return this.getSubCategoryDisplayStatus({
131
+ return this.getSubCategoriesVisibilityStatus({
132
132
  categoryId,
133
133
  subCategoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
134
134
  });
@@ -137,8 +137,8 @@ class CategoriesTreeVisibilityHandlerImpl {
137
137
  if (!modelId) {
138
138
  return of(createVisibilityStatus("disabled"));
139
139
  }
140
- return this.getElementDisplayStatus({
141
- elementId: node.key.instanceKeys[0].id,
140
+ return this.getElementsVisibilityStatus({
141
+ elementIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
142
142
  modelId,
143
143
  categoryId,
144
144
  });
@@ -147,272 +147,243 @@ class CategoriesTreeVisibilityHandlerImpl {
147
147
  return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ definitionContainerIds: definitionContainers, subCategories, modelIds: models, categories, elements }) => {
148
148
  const observables = new Array();
149
149
  if (definitionContainers?.size) {
150
- observables.push(from(definitionContainers).pipe(mergeMap((definitionContainerId) => this.getDefinitionContainerDisplayStatus({ definitionContainerIds: [definitionContainerId] }))));
150
+ observables.push(from(definitionContainers).pipe(mergeMap((definitionContainerId) => this.getDefinitionContainersVisibilityStatus({ definitionContainerIds: definitionContainerId }))));
151
151
  }
152
152
  if (models?.size) {
153
- observables.push(this.getModelVisibilityStatus({ modelIds: models }));
153
+ observables.push(this.getModelsVisibilityStatus({ modelIds: models }));
154
154
  }
155
155
  if (categories?.size) {
156
156
  observables.push(from(categories).pipe(mergeMap((key) => {
157
157
  const { modelId, categoryId } = parseCategoryKey(key);
158
- return this.getCategoryDisplayStatus({ ignoreSubCategories: !!modelId, modelId, categoryIds: [categoryId] });
158
+ return this.getCategoriesVisibilityStatus({ modelId, categoryIds: categoryId });
159
159
  })));
160
160
  }
161
161
  if (subCategories?.size) {
162
162
  observables.push(from(subCategories).pipe(mergeMap((key) => {
163
163
  const { subCategoryId, categoryId } = parseSubCategoryKey(key);
164
- return this.getSubCategoryDisplayStatus({ subCategoryIds: [subCategoryId], categoryId });
164
+ return this.getSubCategoriesVisibilityStatus({ subCategoryIds: subCategoryId, categoryId });
165
165
  })));
166
166
  }
167
167
  if (elements?.size) {
168
168
  observables.push(from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementIds]) => {
169
169
  const { modelId, categoryId } = parseCategoryKey(categoryKey);
170
170
  assert(modelId !== undefined);
171
- return from(elementIds).pipe(releaseMainThreadOnItemsCount(1000), mergeMap((elementId) => this.getElementDisplayStatus({ modelId, categoryId, elementId })));
171
+ return from(elementIds).pipe(releaseMainThreadOnItemsCount(1000), mergeMap((elementId) => this.getElementsVisibilityStatus({ modelId, categoryId, elementIds: elementId })));
172
172
  })));
173
173
  }
174
174
  return merge(...observables);
175
175
  }), mergeVisibilityStatuses);
176
176
  }
177
- getModelVisibilityStatus({ modelIds }) {
177
+ getModelsVisibilityStatus({ modelIds }) {
178
178
  const result = defer(() => {
179
- const viewport = this._props.viewport;
180
- return from(modelIds).pipe(distinct(), mergeMap((modelId) => {
181
- if (!viewport.view.viewsModel(modelId)) {
182
- return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeMap((categoryIds) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), getSubModeledElementsVisibilityStatus({
183
- parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
184
- getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
179
+ return from(Id64.iterable(modelIds)).pipe(mergeMap((modelId) => {
180
+ // For hidden models we only need to check subModels
181
+ if (!this._props.viewport.view.viewsModel(modelId)) {
182
+ return this.getSubModels({ modelIds: modelId }).pipe(mergeMap(({ subModels }) => {
183
+ if (subModels && Id64.sizeOf(subModels) > 0) {
184
+ return this.getModelsVisibilityStatus({ modelIds: subModels }).pipe(map((subModelsVisibilityStatus) => subModelsVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
185
+ }
186
+ return of(createVisibilityStatus("hidden"));
185
187
  }));
186
188
  }
187
- return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeMap((categoryIds) => this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreSubCategories: true })), mergeVisibilityStatuses);
189
+ // For visible models we need to check all categories
190
+ return this.getCategories({ modelIds: modelId }).pipe(mergeMap(({ drawingCategories, spatialCategories }) => merge(drawingCategories ? of(drawingCategories).pipe(mergeMap((categoryIds) => this.getCategoriesVisibilityStatus({ modelId, categoryIds }))) : EMPTY, spatialCategories ? of(spatialCategories).pipe(mergeMap((categoryIds) => this.getCategoriesVisibilityStatus({ modelId, categoryIds }))) : EMPTY)), defaultIfEmpty(createVisibilityStatus("visible")));
188
191
  }), mergeVisibilityStatuses);
189
192
  });
190
- return createVisibilityHandlerResult(this, { ids: modelIds }, result, undefined);
193
+ return createVisibilityHandlerResult(this, { modelIds }, result, undefined);
191
194
  }
192
- getDefinitionContainerDisplayStatus(props) {
195
+ getDefinitionContainersVisibilityStatus(props) {
193
196
  const result = defer(() => {
194
- return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeAll(), mergeMap((categoryId) => this.getCategoryDisplayStatus({ categoryIds: [categoryId] })), mergeVisibilityStatuses);
197
+ return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeMap((categoryIds) => this.getCategoriesVisibilityStatus({
198
+ categoryIds,
199
+ modelId: undefined,
200
+ })));
195
201
  });
196
202
  return createVisibilityHandlerResult(this, props, result, undefined);
197
203
  }
198
- getSubCategoryDisplayStatus(props) {
199
- const result = defer(async () => {
200
- const { categoryId, subCategoryIds } = props;
201
- let visibility = "unknown";
202
- const categoryModels = [...(await this._idsCache.getCategoriesElementModels([categoryId], true)).values()].flat();
203
- let nonDefaultModelDisplayStatesCount = 0;
204
- for (const modelId of categoryModels) {
205
- if (!this._props.viewport.view.viewsModel(modelId)) {
206
- if (visibility === "visible") {
207
- return createVisibilityStatus("partial");
204
+ getVisibleModelCategoriesVisibilityStatus({ modelId, categoryIds }) {
205
+ return merge(this.getVisibilityFromAlwaysAndNeverDrawnElements({
206
+ queryProps: { modelId, categoryIds },
207
+ defaultStatus: () => this.getVisibleModelDefaultCategoriesVisibilityStatus({ modelId, categoryIds }),
208
+ }), this.getSubModels({ modelId, categoryIds }).pipe(mergeMap(({ subModels }) => {
209
+ if (subModels && Id64.sizeOf(subModels) > 0) {
210
+ return this.getModelsVisibilityStatus({ modelIds: subModels });
211
+ }
212
+ return EMPTY;
213
+ }))).pipe(mergeVisibilityStatuses);
214
+ }
215
+ getVisibileCategorySubCategoriesVisibilityStatus(props) {
216
+ const { subCategoryIds } = props;
217
+ let subCategoryVisiblity = "unknown";
218
+ for (const subCategoryId of Id64.iterable(subCategoryIds)) {
219
+ const isSubCategoryVisible = this._props.viewport.isSubCategoryVisible(subCategoryId);
220
+ if (isSubCategoryVisible && subCategoryVisiblity === "hidden") {
221
+ return createVisibilityStatus("partial");
222
+ }
223
+ if (!isSubCategoryVisible && subCategoryVisiblity === "visible") {
224
+ return createVisibilityStatus("partial");
225
+ }
226
+ subCategoryVisiblity = isSubCategoryVisible ? "visible" : "hidden";
227
+ }
228
+ // If visibility is unknown, no subCategories were provided,
229
+ // Since category is visible we return visible
230
+ return createVisibilityStatus(subCategoryVisiblity === "unknown" ? "visible" : subCategoryVisiblity);
231
+ }
232
+ getSubCategoriesVisibilityStatus(props) {
233
+ const result = defer(() => {
234
+ return (props.modelId ? of({ id: props.categoryId, models: props.modelId }) : from(this.getModels({ categoryIds: props.categoryId }))).pipe(map(({ models }) => {
235
+ let visibility = "unknown";
236
+ let nonDefaultModelDisplayStatesCount = 0;
237
+ for (const modelId of Id64.iterable(models ?? [])) {
238
+ if (!this._props.viewport.view.viewsModel(modelId)) {
239
+ if (visibility === "visible") {
240
+ return createVisibilityStatus("partial");
241
+ }
242
+ visibility = "hidden";
243
+ ++nonDefaultModelDisplayStatesCount;
244
+ continue;
208
245
  }
209
- visibility = "hidden";
210
- ++nonDefaultModelDisplayStatesCount;
211
- continue;
212
- }
213
- const override = this._props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId);
214
- if (override === PerModelCategoryVisibility.Override.Show) {
215
- if (visibility === "hidden") {
216
- return createVisibilityStatus("partial");
246
+ const override = this._props.viewport.perModelCategoryVisibility.getOverride(modelId, props.categoryId);
247
+ if (override === PerModelCategoryVisibility.Override.Show) {
248
+ if (visibility === "hidden") {
249
+ return createVisibilityStatus("partial");
250
+ }
251
+ visibility = "visible";
252
+ ++nonDefaultModelDisplayStatesCount;
253
+ continue;
217
254
  }
218
- visibility = "visible";
219
- ++nonDefaultModelDisplayStatesCount;
220
- continue;
221
- }
222
- if (override === PerModelCategoryVisibility.Override.Hide) {
223
- if (visibility === "visible") {
224
- return createVisibilityStatus("partial");
255
+ if (override === PerModelCategoryVisibility.Override.Hide) {
256
+ if (visibility === "visible") {
257
+ return createVisibilityStatus("partial");
258
+ }
259
+ visibility = "hidden";
260
+ ++nonDefaultModelDisplayStatesCount;
261
+ continue;
225
262
  }
226
- visibility = "hidden";
227
- ++nonDefaultModelDisplayStatesCount;
228
- continue;
229
263
  }
230
- }
231
- if (categoryModels.length > 0 && nonDefaultModelDisplayStatesCount === categoryModels.length) {
232
- assert(visibility === "visible" || visibility === "hidden");
233
- return createVisibilityStatus(visibility);
234
- }
235
- if (!this._props.viewport.view.viewsCategory(categoryId)) {
236
- return createVisibilityStatus(visibility === "visible" ? "partial" : "hidden");
237
- }
238
- if (subCategoryIds.length === 0) {
239
- if (visibility === "hidden") {
240
- return createVisibilityStatus("partial");
264
+ if (models && Id64.sizeOf(models) > 0 && nonDefaultModelDisplayStatesCount === Id64.sizeOf(models)) {
265
+ assert(visibility === "visible" || visibility === "hidden");
266
+ return createVisibilityStatus(visibility);
241
267
  }
242
- return createVisibilityStatus("visible");
243
- }
244
- for (const subCategoryId of subCategoryIds) {
245
- const isSubCategoryVisible = this._props.viewport.isSubCategoryVisible(subCategoryId);
246
- if (isSubCategoryVisible && visibility === "hidden") {
247
- return createVisibilityStatus("partial");
268
+ if (!this._props.viewport.view.viewsCategory(props.categoryId)) {
269
+ return createVisibilityStatus(visibility === "visible" ? "partial" : "hidden");
248
270
  }
249
- if (!isSubCategoryVisible && visibility === "visible") {
250
- return createVisibilityStatus("partial");
271
+ if (Id64.sizeOf(props.subCategoryIds) === 0) {
272
+ if (visibility === "hidden") {
273
+ return createVisibilityStatus("partial");
274
+ }
275
+ return createVisibilityStatus("visible");
251
276
  }
252
- visibility = isSubCategoryVisible ? "visible" : "hidden";
253
- }
254
- assert(visibility === "visible" || visibility === "hidden");
255
- return createVisibilityStatus(visibility);
277
+ const subCategoriesVisibility = this.getVisibileCategorySubCategoriesVisibilityStatus({ subCategoryIds: props.subCategoryIds });
278
+ return subCategoriesVisibility.state === visibility || visibility === "unknown" ? subCategoriesVisibility : createVisibilityStatus("partial");
279
+ }), mergeVisibilityStatuses);
256
280
  });
257
281
  return createVisibilityHandlerResult(this, props, result, undefined);
258
282
  }
259
- getDefaultModelsCategoryVisibilityStatus({ modelId, categoryIds }) {
283
+ getVisibleModelDefaultCategoriesVisibilityStatus({ modelId, categoryIds }) {
260
284
  const viewport = this._props.viewport;
261
- if (!viewport.view.viewsModel(modelId)) {
262
- return createVisibilityStatus("hidden");
263
- }
264
285
  let visibleCount = 0;
265
- let hiddenCount = 0;
266
- let visibleThroughCategorySelectorCount = 0;
267
- for (const categoryId of categoryIds) {
268
- if (viewport.view.viewsCategory(categoryId)) {
269
- ++visibleThroughCategorySelectorCount;
270
- }
286
+ for (const categoryId of Id64.iterable(categoryIds)) {
271
287
  const override = this._props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId);
272
- if (override === PerModelCategoryVisibility.Override.Show) {
288
+ if (override === PerModelCategoryVisibility.Override.Show ||
289
+ (override === PerModelCategoryVisibility.Override.None && viewport.view.viewsCategory(categoryId))) {
273
290
  ++visibleCount;
274
291
  continue;
275
292
  }
276
- if (override === PerModelCategoryVisibility.Override.Hide) {
277
- ++hiddenCount;
278
- continue;
279
- }
280
- if (visibleCount > 0 && hiddenCount > 0) {
293
+ if (visibleCount > 0) {
281
294
  return createVisibilityStatus("partial");
282
295
  }
283
296
  }
284
- if (hiddenCount + visibleCount > 0) {
285
- return createVisibilityStatus(hiddenCount > 0 ? "hidden" : "visible");
286
- }
287
- return createVisibilityStatus(visibleThroughCategorySelectorCount > 0 ? "visible" : "hidden");
297
+ return visibleCount > 0 ? createVisibilityStatus("visible") : createVisibilityStatus("hidden");
288
298
  }
289
- getDefaultCategoryVisibilityStatus({ categoryIds }) {
290
- return from(this._idsCache.getSubCategories(categoryIds)).pipe(mergeMap((categoriesSubCategoriesMap) => {
291
- return from(categoryIds).pipe(mergeMap((categoryId) => {
292
- const subCategoryIds = categoriesSubCategoriesMap.get(categoryId);
293
- return this.getSubCategoryDisplayStatus({ subCategoryIds: subCategoryIds ?? [], categoryId });
294
- }), mergeVisibilityStatuses);
295
- }));
296
- }
297
- getCategoryDisplayStatus(props) {
299
+ getCategoriesVisibilityStatus({ categoryIds, modelId: modelIdFromProps, }) {
298
300
  const result = defer(() => {
299
- if (!this._props.hierarchyConfig.showElements) {
300
- return from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds }));
301
- }
302
- const modelsObservable = props.modelId
303
- ? of(new Map(props.categoryIds.map((id) => [id, [props.modelId]])))
304
- : from(this._idsCache.getCategoriesElementModels(props.categoryIds));
305
- return merge(
306
- // get visibility status from always and never drawn elements
307
- this._props.hierarchyConfig.showElements
308
- ? modelsObservable.pipe(mergeMap((categoryModelsMap) => {
309
- if (categoryModelsMap.size === 0) {
310
- return props.modelId
311
- ? of(this.getDefaultModelsCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds }))
312
- : from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds }));
301
+ return (modelIdFromProps
302
+ ? from(Id64.iterable(categoryIds)).pipe(map((categoryId) => ({ id: categoryId, models: modelIdFromProps })))
303
+ : this.getModels({ categoryIds })).pipe(map(({ id, models }) => {
304
+ const acc = { categoryId: id, visibleModels: new Array(), hiddenModels: new Array() };
305
+ if (!models) {
306
+ return acc;
307
+ }
308
+ for (const modelId of Id64.iterable(models)) {
309
+ if (this._props.viewport.viewsModel(modelId)) {
310
+ acc.visibleModels.push(modelId);
313
311
  }
314
- return from(categoryModelsMap).pipe(mergeMap(([category, models]) => from(models).pipe(mergeMap((model) => {
315
- if (this._props.viewport.view.viewsModel(model)) {
316
- return this.getVisibilityFromAlwaysAndNeverDrawnElements({
317
- queryProps: props,
318
- defaultStatus: () => this.getDefaultModelsCategoryVisibilityStatus({ modelId: model, categoryIds: [category] }),
319
- }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
320
- return from(this._idsCache.getCategoriesModeledElements(model, [category])).pipe(getSubModeledElementsVisibilityStatus({
321
- parentNodeVisibilityStatus: visibilityStatusAlwaysAndNeverDraw,
322
- getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
323
- }));
324
- }));
325
- }
326
- return from(this._idsCache.getCategoriesModeledElements(model, [category])).pipe(getSubModeledElementsVisibilityStatus({
327
- parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
328
- getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
329
- }));
330
- }), mergeVisibilityStatuses)), mergeVisibilityStatuses);
331
- }), map((visibilityStatus) => {
332
- return { visibilityStatus, type: 0 };
333
- }))
334
- : EMPTY,
335
- // get category status
336
- (props.modelId
337
- ? of(this.getDefaultModelsCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds }))
338
- : from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds }))).pipe(map((visibilityStatus) => {
339
- return { visibilityStatus, type: 1 };
340
- }))).pipe(toArray(), mergeMap(async (visibilityStatusesInfo) => {
341
- let defaultStatus;
342
- let alwaysNeverDrawStatus;
343
- visibilityStatusesInfo.forEach((visibilityStatusInfo) => {
344
- switch (visibilityStatusInfo.type) {
345
- case 0:
346
- alwaysNeverDrawStatus = visibilityStatusInfo.visibilityStatus;
347
- break;
348
- case 1:
349
- defaultStatus = visibilityStatusInfo.visibilityStatus;
350
- break;
312
+ else {
313
+ acc.hiddenModels.push(modelId);
351
314
  }
352
- });
353
- assert(defaultStatus !== undefined);
354
- if (defaultStatus.state === "partial") {
355
- return defaultStatus;
356
- }
357
- // This can happen if:
358
- // a) showElements is set to false
359
- // b) root category does not have any elements (that dont have Parent)
360
- // In both cases we don't need to look at modeled elements visibility
361
- if (alwaysNeverDrawStatus === undefined) {
362
- return defaultStatus;
363
315
  }
364
- // In cases where
365
- // a) SubCategories are hidden
366
- // b) Category has model (it means that category is under hidden subModel)
367
- // We dont need to look at default category status, it is already accounted for in always/never drawn visibility
368
- if (this._props.hierarchyConfig.hideSubCategories || props.modelId) {
369
- return alwaysNeverDrawStatus;
370
- }
371
- if ((await this._idsCache.getSubCategories(props.categoryIds)).size === 0) {
372
- return alwaysNeverDrawStatus;
373
- }
374
- if (alwaysNeverDrawStatus.state === "partial" || alwaysNeverDrawStatus.state !== defaultStatus.state) {
375
- return createVisibilityStatus("partial");
376
- }
377
- return alwaysNeverDrawStatus;
378
- }));
316
+ return acc;
317
+ }), mergeMap(({ categoryId, visibleModels, hiddenModels }) => {
318
+ return merge(
319
+ // For hidden models we only need to check subModels
320
+ hiddenModels.length > 0
321
+ ? this.getSubModels({ modelIds: hiddenModels }).pipe(mergeMap(({ subModels }) => {
322
+ if (subModels && Id64.sizeOf(subModels) > 0) {
323
+ return this.getModelsVisibilityStatus({
324
+ modelIds: subModels,
325
+ }).pipe(map((subModelsVisibilityStatus) => subModelsVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
326
+ }
327
+ return of(createVisibilityStatus("hidden"));
328
+ }))
329
+ : EMPTY,
330
+ // For visible models we need to check all categories
331
+ visibleModels.length > 0
332
+ ? from(visibleModels).pipe(mergeMap((modelId) => this.getVisibleModelCategoriesVisibilityStatus({
333
+ modelId,
334
+ categoryIds: categoryId,
335
+ })))
336
+ : EMPTY,
337
+ // We need to check subCategories as well
338
+ this.getSubCategories({ categoryIds: categoryId }).pipe(mergeMap(({ subCategories }) => {
339
+ if (subCategories && Id64.sizeOf(subCategories) > 0) {
340
+ return this.getSubCategoriesVisibilityStatus({ categoryId, modelId: modelIdFromProps, subCategoryIds: subCategories });
341
+ }
342
+ return EMPTY;
343
+ }))).pipe(defaultIfEmpty(createVisibilityStatus(this._props.viewport.view.viewsCategory(categoryId) ? "visible" : "hidden")));
344
+ }), mergeVisibilityStatuses);
379
345
  });
380
- return createVisibilityHandlerResult(this, props, result, undefined);
346
+ return createVisibilityHandlerResult(this, { categoryIds, modelId: modelIdFromProps }, result, undefined);
381
347
  }
382
- getClassGroupingNodeDisplayStatus(node) {
348
+ getGroupedElementsVisibilityStatus(props) {
383
349
  const result = defer(() => {
384
- const info = this.getGroupingNodeInfo(node);
385
- const { modelElementsMap, categoryId } = info;
386
- return from(modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => {
387
- if (!this._props.viewport.view.viewsModel(modelId)) {
388
- return of([...elementIds]).pipe(filterSubModeledElementIds({ doesSubModelExist: async (id) => this._idsCache.hasSubModel(id) }), getSubModeledElementsVisibilityStatus({
389
- parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
390
- getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
391
- }));
392
- }
393
- return this.getVisibilityFromAlwaysAndNeverDrawnElements({
394
- elements: elementIds,
395
- defaultStatus: () => this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId }),
396
- }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
397
- return of([...elementIds]).pipe(filterSubModeledElementIds({ doesSubModelExist: async (id) => this._idsCache.hasSubModel(id) }), getSubModeledElementsVisibilityStatus({
398
- parentNodeVisibilityStatus: visibilityStatusAlwaysAndNeverDraw,
399
- getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
400
- }));
401
- }));
402
- }), mergeVisibilityStatuses);
350
+ const { modelElementsMap, categoryId } = props;
351
+ return from(modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => this.getElementsVisibilityStatus({ elementIds, modelId, categoryId })), mergeVisibilityStatuses);
403
352
  });
404
- return createVisibilityHandlerResult(this, { node }, result, undefined);
353
+ return createVisibilityHandlerResult(this, props, result, undefined);
405
354
  }
406
- getElementDisplayStatus(props) {
355
+ getElementsVisibilityStatus(props) {
407
356
  const result = defer(() => {
408
- const viewport = this._props.viewport;
409
- const { elementId, modelId, categoryId } = props;
410
- const viewsModel = viewport.view.viewsModel(modelId);
411
- const elementStatus = getElementOverriddenVisibility({
412
- elementId,
413
- viewport,
414
- });
415
- return from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((hasSubModel) => (hasSubModel ? this.getModelVisibilityStatus({ modelIds: [elementId] }) : of(undefined))), map((subModelVisibilityStatus) => getElementVisibility(viewsModel, elementStatus, this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId }), subModelVisibilityStatus)));
357
+ const { elementIds, modelId, categoryId } = props;
358
+ // TODO: check child elements that are subModels
359
+ if (!this._props.viewport.view.viewsModel(modelId)) {
360
+ return from(elementIds).pipe(mergeMap((elementId) => from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((isSubModel) => {
361
+ if (isSubModel) {
362
+ return this.getModelsVisibilityStatus({
363
+ modelIds: elementId,
364
+ }).pipe(map((subModelVisibilityStatus) => subModelVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
365
+ }
366
+ return of(createVisibilityStatus("hidden"));
367
+ }))), mergeVisibilityStatuses);
368
+ }
369
+ // TODO: check child elements
370
+ // TODO: check child element categories
371
+ // TODO: check child elements that are subModels
372
+ return this.getVisibilityFromAlwaysAndNeverDrawnElements({
373
+ elements: elementIds,
374
+ defaultStatus: () => this.getVisibleModelDefaultCategoriesVisibilityStatus({ categoryIds: categoryId, modelId }),
375
+ }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
376
+ return from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) => from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((isSubModel) => {
377
+ if (isSubModel) {
378
+ return this.getModelsVisibilityStatus({
379
+ modelIds: elementId,
380
+ }).pipe(map((subModelVisibilityStatus) => subModelVisibilityStatus.state !== visibilityStatusAlwaysAndNeverDraw.state
381
+ ? createVisibilityStatus("partial")
382
+ : visibilityStatusAlwaysAndNeverDraw));
383
+ }
384
+ return of(visibilityStatusAlwaysAndNeverDraw);
385
+ }))), mergeVisibilityStatuses);
386
+ }));
416
387
  });
417
388
  return createVisibilityHandlerResult(this, props, result, undefined);
418
389
  }
@@ -422,29 +393,29 @@ class CategoriesTreeVisibilityHandlerImpl {
422
393
  return this.changeFilteredNodeVisibility({ node, on });
423
394
  }
424
395
  if (HierarchyNode.isClassGroupingNode(node)) {
425
- return this.changeElementGroupingNodeState(node, on);
396
+ const nodeInfo = this.getGroupingNodeInfo(node);
397
+ return this.changeGroupedElementsVisibilityStatus({ categoryId: nodeInfo.categoryId, modelElementsMap: nodeInfo.modelElementsMap, on });
426
398
  }
427
399
  if (!HierarchyNode.isInstancesNode(node)) {
428
400
  return EMPTY;
429
401
  }
430
402
  if (CategoriesTreeNode.isDefinitionContainerNode(node)) {
431
- return this.changeDefinitionContainerState({
403
+ return this.changeDefinitionContainersVisibilityStatus({
432
404
  definitionContainerIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
433
405
  on,
434
406
  });
435
407
  }
436
408
  if (CategoriesTreeNode.isModelNode(node)) {
437
- return this.changeModelState({
438
- ids: node.key.instanceKeys.map(({ id }) => id),
409
+ return this.changeModelsVisibilityStatus({
410
+ modelIds: node.key.instanceKeys.map(({ id }) => id),
439
411
  on,
440
412
  });
441
413
  }
442
414
  if (CategoriesTreeNode.isCategoryNode(node)) {
443
- return this.changeCategoryState({
415
+ return this.changeCategoriesVisibilityStatus({
444
416
  categoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
445
417
  modelId: CategoriesTreeNode.getModelId(node),
446
418
  on,
447
- ignoreSubCategories: node.extendedData?.isCategoryOfSubModel,
448
419
  });
449
420
  }
450
421
  const categoryId = CategoriesTreeNode.getCategoryId(node);
@@ -452,24 +423,18 @@ class CategoriesTreeVisibilityHandlerImpl {
452
423
  return EMPTY;
453
424
  }
454
425
  if (CategoriesTreeNode.isSubCategoryNode(node)) {
455
- if (this._props.hierarchyConfig.hideSubCategories) {
456
- return EMPTY;
457
- }
458
- return this.changeSubCategoryState({
426
+ return this.changeSubCategoriesVisibilityStatus({
459
427
  categoryId,
460
428
  subCategoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
461
429
  on,
462
430
  });
463
431
  }
464
- if (!this._props.hierarchyConfig.showElements) {
465
- return EMPTY;
466
- }
467
432
  const modelId = CategoriesTreeNode.getModelId(node);
468
433
  if (!modelId) {
469
434
  return EMPTY;
470
435
  }
471
- return this.changeElementsState({
472
- elementIds: new Set([...node.key.instanceKeys.map(({ id }) => id)]),
436
+ return this.changeElementsVisibilityStatus({
437
+ elementIds: node.key.instanceKeys.map(({ id }) => id),
473
438
  modelId,
474
439
  categoryId,
475
440
  on,
@@ -483,63 +448,73 @@ class CategoriesTreeVisibilityHandlerImpl {
483
448
  return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ definitionContainerIds: definitionContainers, subCategories, modelIds: models, categories, elements }) => {
484
449
  const observables = new Array();
485
450
  if (definitionContainers?.size) {
486
- observables.push(this.changeDefinitionContainerState({ definitionContainerIds: [...definitionContainers], on }));
451
+ observables.push(this.changeDefinitionContainersVisibilityStatus({ definitionContainerIds: definitionContainers, on }));
487
452
  }
488
453
  if (models?.size) {
489
- observables.push(this.changeModelState({ ids: models, on }));
454
+ observables.push(this.changeModelsVisibilityStatus({ modelIds: models, on }));
490
455
  }
491
456
  if (categories?.size) {
492
457
  observables.push(from(categories).pipe(mergeMap((key) => {
493
458
  const { modelId, categoryId } = parseCategoryKey(key);
494
- return this.changeCategoryState({ modelId, categoryIds: [categoryId], ignoreSubCategories: false, on });
459
+ return this.changeCategoriesVisibilityStatus({ modelId, categoryIds: categoryId, on });
495
460
  })));
496
461
  }
497
462
  if (subCategories?.size) {
498
463
  observables.push(from(subCategories).pipe(mergeMap((key) => {
499
464
  const { subCategoryId, categoryId } = parseSubCategoryKey(key);
500
- return this.changeSubCategoryState({ categoryId, subCategoryIds: [subCategoryId], on });
465
+ return this.changeSubCategoriesVisibilityStatus({ categoryId, subCategoryIds: subCategoryId, on });
501
466
  })));
502
467
  }
503
468
  if (elements?.size) {
504
469
  observables.push(from(elements).pipe(mergeMap(([categoryKey, elementIds]) => {
505
470
  const { modelId, categoryId } = parseCategoryKey(categoryKey);
506
471
  assert(modelId !== undefined);
507
- return this.changeElementsState({ modelId, categoryId, elementIds, on });
472
+ return this.changeElementsVisibilityStatus({ modelId, categoryId, elementIds, on });
508
473
  })));
509
474
  }
510
475
  return merge(...observables);
511
476
  }));
512
477
  }
513
- changeModelState(props) {
514
- const { ids, on } = props;
515
- if (Id64.sizeOf(ids) === 0) {
478
+ changeModelsVisibilityStatus(props) {
479
+ const { modelIds, on } = props;
480
+ if (Id64.sizeOf(modelIds) === 0) {
516
481
  return EMPTY;
517
482
  }
518
483
  const result = defer(() => {
519
484
  const viewport = this._props.viewport;
520
- viewport.perModelCategoryVisibility.clearOverrides(ids);
521
- const idsObs = from(Id64.iterable(ids));
485
+ viewport.perModelCategoryVisibility.clearOverrides(modelIds);
522
486
  if (!on) {
523
- viewport.changeModelDisplay(ids, false);
524
- return idsObs.pipe(mergeMap(async (modelId) => ({ modelId, categoryIds: await this._idsCache.getModelCategoryIds(modelId) })), mergeMap(({ modelId, categoryIds }) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
487
+ viewport.changeModelDisplay(modelIds, false);
488
+ return this.getSubModels({ modelIds }).pipe(mergeMap(({ subModels }) => (subModels ? this.changeModelsVisibilityStatus({ modelIds: subModels, on }) : EMPTY)));
525
489
  }
526
- return concat(from(viewport.addViewedModels(ids)), idsObs.pipe(mergeMap((modelId) => {
527
- return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeAll(), mergeMap((categoryId) => this.changeCategoryState({ categoryIds: [categoryId], modelId, on, ignoreSubCategories: true })));
490
+ return concat(from(viewport.addViewedModels(modelIds)), this.getCategories({ modelIds }).pipe(mergeMap(({ id, drawingCategories, spatialCategories }) => {
491
+ return merge(drawingCategories ? this.changeCategoriesVisibilityStatus({ categoryIds: drawingCategories, modelId: id, on }) : EMPTY, spatialCategories ? this.changeCategoriesVisibilityStatus({ categoryIds: spatialCategories, modelId: id, on }) : EMPTY);
528
492
  })));
529
493
  });
530
494
  return createVisibilityHandlerResult(this, props, result, undefined);
531
495
  }
532
- showModelWithoutAnyCategoriesOrElements(modelId) {
496
+ showModelWithoutAnyCategoriesOrElements(modelId, categoriesToNotOverride) {
533
497
  const viewport = this._props.viewport;
534
498
  return forkJoin({
535
- categories: this._idsCache.getModelCategoryIds(modelId),
536
- alwaysDrawnElements: this._alwaysAndNeverDrawnElements.getAlwaysDrawnElements({ modelId }),
537
- }).pipe(mergeMap(async ({ categories, alwaysDrawnElements }) => {
499
+ allModelCategories: this.getCategories({ modelIds: modelId }).pipe(reduce((acc, { drawingCategories, spatialCategories }) => {
500
+ for (const category of Id64.iterable(drawingCategories ?? [])) {
501
+ acc.add(category);
502
+ }
503
+ for (const category of Id64.iterable(spatialCategories ?? [])) {
504
+ acc.add(category);
505
+ }
506
+ return acc;
507
+ }, new Set())),
508
+ modelAlwaysDrawnElements: this._alwaysAndNeverDrawnElements.getAlwaysDrawnElements({ modelId }),
509
+ }).pipe(mergeMap(async ({ allModelCategories, modelAlwaysDrawnElements }) => {
538
510
  const alwaysDrawn = this._props.viewport.alwaysDrawn;
539
- if (alwaysDrawn && alwaysDrawnElements) {
540
- viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
511
+ if (alwaysDrawn && modelAlwaysDrawnElements) {
512
+ viewport.setAlwaysDrawn(setDifference(alwaysDrawn, modelAlwaysDrawnElements));
541
513
  }
542
- categories.forEach((categoryId) => {
514
+ const categoriesToOverride = categoriesToNotOverride
515
+ ? setDifference(allModelCategories, getSetFromId64Arg(categoriesToNotOverride))
516
+ : allModelCategories;
517
+ categoriesToOverride.forEach((categoryId) => {
543
518
  this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false);
544
519
  });
545
520
  await viewport.addViewedModels(modelId);
@@ -560,90 +535,131 @@ class CategoriesTreeVisibilityHandlerImpl {
560
535
  viewport.changeCategoryDisplay(categoryId, true, changeSubCategories);
561
536
  }
562
537
  }
563
- changeSubCategoryState(props) {
538
+ changeSubCategoriesVisibilityStatus(props) {
564
539
  const result = defer(() => {
565
540
  return concat(
566
541
  // make sure parent category and models are enabled
567
542
  props.on
568
- ? concat(from(enableCategoryDisplay(this._props.viewport, [props.categoryId], props.on, false)), from(this.enableCategoriesElementModelsVisibility([props.categoryId])))
543
+ ? concat(from(enableCategoryDisplay(this._props.viewport, props.categoryId, props.on, false)), this.enableCategoriesElementModelsVisibility(props.categoryId))
569
544
  : EMPTY, from(props.subCategoryIds).pipe(map((subCategoryId) => enableSubCategoryDisplay(this._props.viewport, subCategoryId, props.on))));
570
545
  });
571
546
  return createVisibilityHandlerResult(this, props, result, undefined);
572
547
  }
573
- async enableCategoriesElementModelsVisibility(categoryIds) {
574
- const categoriesModelsMap = await this._idsCache.getCategoriesElementModels(categoryIds, true);
575
- const modelIds = [...categoriesModelsMap.values()].flat();
576
- const hiddenModels = modelIds.filter((modelId) => !this._props.viewport.view.viewsModel(modelId));
577
- if (hiddenModels.length > 0) {
578
- this._props.viewport.changeModelDisplay(hiddenModels, true);
579
- }
548
+ enableCategoriesElementModelsVisibility(categoryIds) {
549
+ return from(this._idsCache.getCategoriesElementModels(categoryIds, true)).pipe(mergeMap((categoriesModelsMap) => categoriesModelsMap.values()), reduce((acc, modelIds) => {
550
+ modelIds.forEach((modelId) => {
551
+ if (!this._props.viewport.view.viewsModel(modelId)) {
552
+ acc.add(modelId);
553
+ }
554
+ });
555
+ return acc;
556
+ }, new Set()), map((hiddenModels) => {
557
+ if (hiddenModels.size > 0) {
558
+ this._props.viewport.changeModelDisplay(hiddenModels, true);
559
+ }
560
+ }));
580
561
  }
581
- changeDefinitionContainerState(props) {
562
+ changeDefinitionContainersVisibilityStatus(props) {
582
563
  const result = defer(() => {
583
- return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeMap((categoryIds) => {
584
- return this.changeCategoryState({ categoryIds, on: props.on });
585
- }));
564
+ return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeMap((categoryIds) => this.changeCategoriesVisibilityStatus({ categoryIds, modelId: undefined, on: props.on })));
586
565
  });
587
566
  return createVisibilityHandlerResult(this, props, result, undefined);
588
567
  }
589
- changeCategoryState(props) {
568
+ changeCategoriesVisibilityStatus(props) {
590
569
  const result = defer(() => {
591
- const { modelId, categoryIds, on, ignoreSubCategories } = props;
570
+ const { modelId: modelIdFromProps, categoryIds, on } = props;
592
571
  const viewport = this._props.viewport;
593
- if (!this._props.hierarchyConfig.showElements) {
594
- return concat(from(enableCategoryDisplay(viewport, categoryIds, on, on)), on ? from(this.enableCategoriesElementModelsVisibility(categoryIds)) : EMPTY);
595
- }
596
- const modelIdsObservable = modelId
597
- ? of(new Map(categoryIds.map((id) => [id, [modelId]])))
598
- : from(this._idsCache.getCategoriesElementModels(categoryIds, true));
599
- return concat(modelId ? EMPTY : from(enableCategoryDisplay(viewport, categoryIds, on, ignoreSubCategories ? false : on)), on
600
- ? modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.values())), mergeAll(), filter((modelIdToCheck) => !viewport.view.viewsModel(modelIdToCheck)), mergeMap((modelIdToCheck) => this.showModelWithoutAnyCategoriesOrElements(modelIdToCheck)))
601
- : EMPTY, modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.entries())), mergeMap(([categoryId, modelIds]) => {
602
- return from(modelIds).pipe(mergeMap((modelOfCategory) => {
603
- this.changeCategoryStateInViewportAccordingToModelVisibility(modelOfCategory, categoryId, on, !!ignoreSubCategories);
604
- return this._alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ modelId: modelOfCategory, categoryIds: [categoryId] });
605
- }));
606
- })), modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.entries())), mergeMap(([categoryId, modelIds]) => {
607
- return from(modelIds).pipe(mergeMap((modelOfCategory) => from(this._idsCache.getCategoriesModeledElements(modelOfCategory, [categoryId])).pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })))));
608
- })));
572
+ const modelIdsObservable = (modelIdFromProps
573
+ ? of(new Map([[modelIdFromProps, getSetFromId64Arg(categoryIds)]]))
574
+ : this.getModels({ categoryIds }).pipe(reduce((acc, { id, models }) => {
575
+ if (!models) {
576
+ return acc;
577
+ }
578
+ for (const modelId of Id64.iterable(models)) {
579
+ let entry = acc.get(modelId);
580
+ if (!entry) {
581
+ entry = new Set();
582
+ acc.set(modelId, entry);
583
+ }
584
+ entry.add(id);
585
+ }
586
+ return acc;
587
+ }, new Map()))).pipe(mergeMap((modelCategoriesMap) => modelCategoriesMap.entries()), shareReplay());
588
+ return concat(
589
+ // If modelId was provided: add override
590
+ // If modelId was not provided: change categoryDisplay and remove categories per model overrides
591
+ modelIdFromProps
592
+ ? of(viewport.perModelCategoryVisibility.setOverride(modelIdFromProps, categoryIds, on ? PerModelCategoryVisibility.Override.Show : PerModelCategoryVisibility.Override.Hide))
593
+ : concat(from(enableCategoryDisplay(viewport, categoryIds, on, on)), modelIdsObservable.pipe(map(([modelId, modelCategories]) => {
594
+ viewport.perModelCategoryVisibility.setOverride(modelId, modelCategories, PerModelCategoryVisibility.Override.None);
595
+ }))),
596
+ // If categories visibility needs to be turned on, we need to turn on models without turning on unrelated elements or categories for that model
597
+ on
598
+ ? modelIdsObservable.pipe(mergeMap(([modelId, categories]) => {
599
+ if (!viewport.view.viewsModel(modelId)) {
600
+ return this.showModelWithoutAnyCategoriesOrElements(modelId, categories);
601
+ }
602
+ return EMPTY;
603
+ }))
604
+ : EMPTY, this._alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ categoryIds, modelId: modelIdFromProps }), this.getSubModels({ categoryIds, modelId: modelIdFromProps }).pipe(mergeMap(({ subModels }) => (subModels ? this.changeModelsVisibilityStatus({ modelIds: subModels, on }) : EMPTY))));
609
605
  });
610
606
  return createVisibilityHandlerResult(this, props, result, undefined);
611
607
  }
612
- doChangeElementsState(props) {
613
- return defer(() => {
614
- const { modelId, categoryId, elementIds, on } = props;
615
- const viewport = this._props.viewport;
616
- return concat(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
617
- const categoryVisibility = this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId });
618
- const isDisplayedByDefault = categoryVisibility.state === "visible";
619
- return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
620
- }), from(elementIds).pipe(mergeMap(async (elementId) => ({ elementId, isSubModel: await this._idsCache.hasSubModel(elementId) })), filter(({ isSubModel }) => isSubModel), map(({ elementId }) => elementId), toArray(), mergeMap((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
621
- });
622
- }
623
608
  /**
624
609
  * Updates visibility of all grouping node's elements.
625
610
  * @see `changeElementState`
626
611
  */
627
- changeElementGroupingNodeState(node, on) {
628
- const info = this.getGroupingNodeInfo(node);
629
- const result = from(info.modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => {
630
- return this.doChangeElementsState({ modelId, elementIds, categoryId: info.categoryId, on });
631
- }));
632
- return createVisibilityHandlerResult(this, { node, on }, result, undefined);
612
+ changeGroupedElementsVisibilityStatus(props) {
613
+ const result = defer(() => {
614
+ return from(props.modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => {
615
+ return this.changeElementsVisibilityStatus({ modelId, elementIds, categoryId: props.categoryId, on: props.on });
616
+ }));
617
+ });
618
+ return createVisibilityHandlerResult(this, props, result, undefined);
633
619
  }
634
620
  /**
635
621
  * Updates visibility of an element and all its child elements by adding them to the always/never drawn list.
636
622
  * @note If element is to be enabled and model is hidden, it will be enabled.
637
623
  */
638
- changeElementsState(props) {
639
- const result = this.doChangeElementsState(props);
624
+ changeElementsVisibilityStatus(props) {
625
+ const result = defer(() => {
626
+ const { modelId, categoryId, elementIds, on } = props;
627
+ const viewport = this._props.viewport;
628
+ // TODO: change child elements
629
+ // TODO: change child element categories
630
+ // TODO: change child subModels
631
+ return concat(
632
+ // Change elements state
633
+ defer(() => {
634
+ if (!viewport.view.viewsModel(modelId)) {
635
+ if (!on) {
636
+ return this.queueElementsVisibilityChange(elementIds, on, false);
637
+ }
638
+ return this.showModelWithoutAnyCategoriesOrElements(modelId).pipe(mergeMap(() => {
639
+ const defaultVisibility = this.getVisibleModelDefaultCategoriesVisibilityStatus({ categoryIds: categoryId, modelId });
640
+ const displayedByDefault = defaultVisibility.state === "visible";
641
+ return this.queueElementsVisibilityChange(elementIds, on, displayedByDefault);
642
+ }));
643
+ }
644
+ const categoryVisibility = this.getVisibleModelDefaultCategoriesVisibilityStatus({ categoryIds: categoryId, modelId });
645
+ const isDisplayedByDefault = categoryVisibility.state === "visible";
646
+ return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
647
+ }),
648
+ // Change visibility of elements that are models
649
+ from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) => from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((isSubModel) => {
650
+ if (isSubModel) {
651
+ return this.changeModelsVisibilityStatus({ modelIds: elementId, on });
652
+ }
653
+ return EMPTY;
654
+ })))));
655
+ });
640
656
  return createVisibilityHandlerResult(this, props, result, undefined);
641
657
  }
642
658
  queueElementsVisibilityChange(elementIds, on, visibleByDefault) {
643
659
  const finishedSubject = new Subject();
644
660
  // observable to track if visibility change is finished/cancelled
645
661
  const changeFinished = finishedSubject.pipe(startWith(false), shareReplay(1), filter((finished) => finished));
646
- const changeObservable = from(elementIds).pipe(
662
+ const changeObservable = from(Id64.iterable(elementIds)).pipe(
647
663
  // check if visibility change is not finished (cancelled) due to change overall change request being cancelled
648
664
  takeUntil(changeFinished), changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault, viewport: this._props.viewport }), tap({
649
665
  next: () => {
@@ -674,18 +690,16 @@ class CategoriesTreeVisibilityHandlerImpl {
674
690
  if ("elements" in props) {
675
691
  return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
676
692
  ...props,
677
- alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
678
- neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
679
- totalCount: props.elements.size,
693
+ alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(Id64.iterable(props.elements), viewport.alwaysDrawn) : undefined,
694
+ neverDrawn: viewport.neverDrawn?.size ? setIntersection(Id64.iterable(props.elements), viewport.neverDrawn) : undefined,
695
+ totalCount: Id64.sizeOf(props.elements),
680
696
  viewport,
681
697
  }));
682
698
  }
683
699
  const { modelId, categoryIds } = props.queryProps;
684
- const totalCount = (modelId ? of(new Map(categoryIds.map((categoryId) => [categoryId, [modelId]]))) : from(this._idsCache.getCategoriesElementModels(categoryIds))).pipe(mergeMap((categoriesMap) => from(categoriesMap)), mergeMap(([categoryId, modelIds]) => {
685
- return from(modelIds).pipe(mergeMap((modelOfCategory) => from(this._idsCache.getCategoryElementsCount(modelOfCategory, categoryId))), reduce((acc, specificModelCategoryCount) => {
686
- return acc + specificModelCategoryCount;
687
- }, 0));
688
- }));
700
+ const totalCount = from(Id64.iterable(categoryIds)).pipe(mergeMap((categoryId) => this.getElementsCount({ modelId, categoryId })), reduce((acc, specificModelCategoryCount) => {
701
+ return acc + specificModelCategoryCount;
702
+ }, 0));
689
703
  return forkJoin({
690
704
  totalCount,
691
705
  alwaysDrawn: this._alwaysAndNeverDrawnElements.getAlwaysDrawnElements(props.queryProps),
@@ -698,6 +712,33 @@ class CategoriesTreeVisibilityHandlerImpl {
698
712
  });
699
713
  }));
700
714
  }
715
+ getCategories(props) {
716
+ return from(Id64.iterable(props.modelIds)).pipe(mergeMap((modelId) => from(this._props.idsCache.getModelCategoryIds(modelId)).pipe(map((categories) => ({ id: modelId, ...(this._props.viewport.view.is2d() ? { drawingCategories: categories } : { spatialCategories: categories }) })))));
717
+ }
718
+ getElementsCount(props) {
719
+ return from(this._props.idsCache.getCategoryElementsCount(props.modelId, props.categoryId));
720
+ }
721
+ getModels(props) {
722
+ return from(Id64.iterable(props.categoryIds)).pipe(mergeMap((categoryId) => from(this._props.idsCache.getCategoriesElementModels(categoryId, true)).pipe(mergeMap((categoryModelsMap) => (categoryModelsMap.size > 0 ? categoryModelsMap.values() : of(undefined))), map((categoryModels) => ({ id: categoryId, models: categoryModels })))));
723
+ }
724
+ getSubCategories(props) {
725
+ return from(Id64.iterable(props.categoryIds)).pipe(mergeMap((categoryId) => from(this._props.idsCache.getSubCategories(categoryId)).pipe(mergeMap((categorySubCategoriesMap) => (categorySubCategoriesMap.size > 0 ? categorySubCategoriesMap.values() : of(undefined))), map((subCategories) => ({ id: categoryId, subCategories })))));
726
+ }
727
+ getSubModels(props) {
728
+ if ("modelIds" in props) {
729
+ return from(Id64.iterable(props.modelIds)).pipe(mergeMap((modelId) => from(this._props.idsCache.getModelCategoryIds(modelId)).pipe(mergeMap((categoryIds) => from(this._props.idsCache.getCategoriesModeledElements(modelId, categoryIds))), map((subModels) => ({ id: modelId, subModels })))));
730
+ }
731
+ if (props.modelId) {
732
+ return from(Id64.iterable(props.categoryIds)).pipe(mergeMap((categoryId) => from(this._props.idsCache.getCategoriesModeledElements(props.modelId, categoryId)).pipe(map((subModels) => ({ id: categoryId, subModels })))));
733
+ }
734
+ return from(Id64.iterable(props.categoryIds)).pipe(mergeMap((categoryId) => from(this._props.idsCache.getCategoriesElementModels(categoryId)).pipe(mergeMap((categoryModelsMap) => {
735
+ const models = categoryModelsMap.get(categoryId);
736
+ if (!models) {
737
+ return of({ id: categoryId, subModels: undefined });
738
+ }
739
+ return from(models).pipe(mergeMap((modelId) => from(this._props.idsCache.getCategoriesModeledElements(modelId, categoryId))), map((subModels) => ({ id: categoryId, subModels })));
740
+ }))));
741
+ }
701
742
  getGroupingNodeInfo(node) {
702
743
  const modelElementsMap = node.extendedData?.modelElementsMap;
703
744
  const categoryId = node.extendedData?.categoryId;