@itwin/tree-widget-react 3.16.1 → 3.17.1

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 (142) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/lib/cjs/tree-widget-react/components/SelectableTree.js.map +1 -1
  3. package/lib/cjs/tree-widget-react/components/TreeSelector.js.map +1 -1
  4. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  5. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  6. package/lib/cjs/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  7. package/lib/cjs/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  9. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  10. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  13. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  14. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  15. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
  16. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  17. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  18. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +21 -8
  19. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  20. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  21. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +300 -251
  22. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  23. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  24. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +66 -107
  25. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  26. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +22 -12
  27. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  28. package/lib/cjs/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  29. package/lib/cjs/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  30. package/lib/cjs/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  31. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  32. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  33. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  34. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  35. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  36. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  37. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  38. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  39. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  40. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  41. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  42. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  43. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js +83 -0
  44. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  45. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  46. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  47. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  48. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  49. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  50. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +86 -28
  51. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  52. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  53. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  54. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -6
  55. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +5 -17
  56. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  57. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +5 -4
  58. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  59. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  60. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  61. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  62. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
  63. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
  64. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  65. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  66. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  67. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +272 -139
  68. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  69. package/lib/cjs/tree-widget-react-internal.d.ts +2 -1
  70. package/lib/cjs/tree-widget-react-internal.js +4 -1
  71. package/lib/cjs/tree-widget-react-internal.js.map +1 -1
  72. package/lib/esm/tree-widget-react/components/SelectableTree.js.map +1 -1
  73. package/lib/esm/tree-widget-react/components/TreeSelector.js.map +1 -1
  74. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  75. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  76. package/lib/esm/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  77. package/lib/esm/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  79. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  80. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  81. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  83. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  84. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  85. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
  86. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  88. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +22 -9
  89. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  90. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  91. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +301 -252
  92. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  93. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  94. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +67 -108
  95. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +23 -13
  97. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  98. package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  99. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  100. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  101. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  102. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  103. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  104. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  106. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  107. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  108. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  109. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  110. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  112. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  113. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +74 -0
  114. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  120. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +83 -25
  121. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  122. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  123. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  124. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -6
  125. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +4 -16
  126. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  127. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +4 -3
  128. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  129. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  130. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  131. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  132. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
  133. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
  134. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  135. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  136. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  137. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +257 -124
  138. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  139. package/lib/esm/tree-widget-react-internal.d.ts +2 -1
  140. package/lib/esm/tree-widget-react-internal.js +2 -1
  141. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  142. package/package.json +1 -1
@@ -15,10 +15,11 @@ const core_bentley_1 = require("@itwin/core-bentley");
15
15
  const core_frontend_1 = require("@itwin/core-frontend");
16
16
  const presentation_hierarchies_1 = require("@itwin/presentation-hierarchies");
17
17
  const CategoriesVisibilityUtils_js_1 = require("../../common/CategoriesVisibilityUtils.js");
18
+ const Utils_js_1 = require("../../common/internal/Utils.js");
18
19
  const Rxjs_js_1 = require("../../common/Rxjs.js");
19
20
  const Tooltip_js_1 = require("../../common/Tooltip.js");
20
21
  const UseHierarchyVisibility_js_1 = require("../../common/UseHierarchyVisibility.js");
21
- const Utils_js_1 = require("../Utils.js");
22
+ const Utils_js_2 = require("../Utils.js");
22
23
  const AlwaysAndNeverDrawnElementInfo_js_1 = require("./AlwaysAndNeverDrawnElementInfo.js");
23
24
  const FilteredTree_js_1 = require("./FilteredTree.js");
24
25
  const ModelsTreeNode_js_1 = require("./ModelsTreeNode.js");
@@ -96,7 +97,9 @@ class ModelsTreeVisibilityHandlerImpl {
96
97
  if (!presentation_hierarchies_1.HierarchyNode.isInstancesNode(node)) {
97
98
  return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled"));
98
99
  }
99
- if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
100
+ // Only call getFilteredNodeVisibility when node is not a filter target, is not a child of filter target and has filtered children.
101
+ // Otherwise, it can be handled normally.
102
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget && !node.filtering.hasFilterTargetAncestor) {
100
103
  return this.getFilteredNodeVisibility({ node });
101
104
  }
102
105
  if (ModelsTreeNode_js_1.ModelsTreeNode.isSubjectNode(node)) {
@@ -117,13 +120,18 @@ class ModelsTreeVisibilityHandlerImpl {
117
120
  });
118
121
  }
119
122
  const categoryId = ModelsTreeNode_js_1.ModelsTreeNode.getCategoryId(node);
123
+ const rootCategoryIds = getRootCategoryIds({ parentKeys: node.parentKeys, modelId });
124
+ (0, core_bentley_1.assert)(rootCategoryIds !== undefined);
120
125
  if (!categoryId) {
121
126
  return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled"));
122
127
  }
123
128
  return this.getElementDisplayStatus({
124
129
  elementIds: node.key.instanceKeys.map(({ id }) => id),
130
+ parentKeys: node.parentKeys,
131
+ rootCategoryIds,
125
132
  modelId,
126
133
  categoryId,
134
+ totalChildrenCount: node.extendedData?.childrenCount ?? 0,
127
135
  });
128
136
  }
129
137
  getFilteredNodeVisibility(props) {
@@ -143,24 +151,63 @@ class ModelsTreeVisibilityHandlerImpl {
143
151
  })));
144
152
  }
145
153
  if (elements?.size) {
146
- observables.push((0, rxjs_1.from)(elements).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(50), (0, rxjs_1.mergeMap)(([categoryKey, elementsMap]) => {
154
+ const filterTargetElements = new Array();
155
+ elements.forEach((elementsMap) => elementsMap.forEach(({ isFilterTarget }, elementId) => {
156
+ if (isFilterTarget) {
157
+ filterTargetElements.push(elementId);
158
+ }
159
+ }));
160
+ let childrenCountMapObs;
161
+ if (presentation_hierarchies_1.HierarchyNode.isClassGroupingNode(props.node)) {
162
+ const groupingNodesFilterTargets = props.node.extendedData?.filterTargets;
163
+ const nestedFilterTargetElements = filterTargetElements.filter((filterTarget) => !groupingNodesFilterTargets?.has(filterTarget));
164
+ // Only need to request children count for indirect children filter targets.
165
+ // Direct children filter targets already have children count stored in grouping nodes extended data.
166
+ childrenCountMapObs = this.#idsCache.getAllChildrenCount({ elementIds: nestedFilterTargetElements });
167
+ }
168
+ else {
169
+ childrenCountMapObs = this.#idsCache.getAllChildrenCount({ elementIds: filterTargetElements });
170
+ }
171
+ observables.push(childrenCountMapObs.pipe(
172
+ // Get children count for all filter target elements.
173
+ (0, rxjs_1.map)((elementCountMap) => {
174
+ if (!presentation_hierarchies_1.HierarchyNode.isClassGroupingNode(props.node) || !props.node.extendedData?.filterTargets) {
175
+ return elementCountMap;
176
+ }
177
+ // Need to add children count (stored in grouping nodes' extended data) of direct children filter targets.
178
+ const groupingNodesFilterTargets = props.node.extendedData.filterTargets;
179
+ groupingNodesFilterTargets.forEach((value, key) => elementCountMap.set(key, value.childrenCount));
180
+ return elementCountMap;
181
+ }), (0, rxjs_1.mergeMap)((elementCountMap) => (0, rxjs_1.from)(elements).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(50), (0, rxjs_1.mergeMap)(([categoryKey, elementsMap]) => {
147
182
  const { modelId, categoryId } = (0, FilteredTree_js_1.parseCategoryKey)(categoryKey);
183
+ let totalChildrenCount = 0;
184
+ elementsMap.forEach((_, elementId) => {
185
+ const childCount = elementCountMap.get(elementId);
186
+ if (childCount) {
187
+ totalChildrenCount += childCount;
188
+ }
189
+ });
190
+ const parentElementIdsPath = getParentElementsIdsPath({ parentKeys: props.node.parentKeys, modelId });
191
+ const rootCategoryIds = getRootCategoryIds({ parentKeys: props.node.parentKeys, modelId });
148
192
  return this.getElementsDisplayStatus({
149
193
  elementIds: [...elementsMap.keys()],
194
+ rootCategoryIds: rootCategoryIds ?? categoryId,
195
+ parentElementIdsPath,
150
196
  modelId,
151
197
  categoryId,
198
+ childrenCount: totalChildrenCount,
152
199
  });
153
- })));
200
+ })))));
154
201
  }
155
202
  return (0, rxjs_1.merge)(...observables);
156
- }), mergeVisibilityStatuses());
203
+ }), (0, Utils_js_1.mergeVisibilityStatuses)());
157
204
  }
158
205
  getSubjectNodeVisibilityStatus({ subjectIds, ignoreTooltip }) {
159
206
  const result = (0, rxjs_1.defer)(() => {
160
207
  if (!this.#props.viewport.view.isSpatialView()) {
161
- return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled", getTooltipOptions("modelsTree.subject.nonSpatialView", ignoreTooltip)));
208
+ return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled", (0, Utils_js_1.getTooltipOptions)("modelsTree.subject.nonSpatialView", ignoreTooltip)));
162
209
  }
163
- return (0, rxjs_1.from)(this.#idsCache.getSubjectModelIds(subjectIds)).pipe((0, rxjs_1.mergeMap)((modelIds) => this.getModelVisibilityStatus({ modelIds, ignoreTooltip: true })), mergeVisibilityStatuses({
210
+ return this.#idsCache.getSubjectModelIds(subjectIds).pipe((0, rxjs_1.mergeMap)((modelIds) => this.getModelVisibilityStatus({ modelIds, ignoreTooltip: true })), (0, Utils_js_1.mergeVisibilityStatuses)({
164
211
  visible: "modelsTree.subject.allModelsVisible",
165
212
  hidden: "modelsTree.subject.allModelsHidden",
166
213
  partial: "modelsTree.subject.someModelsHidden",
@@ -172,30 +219,34 @@ class ModelsTreeVisibilityHandlerImpl {
172
219
  const result = (0, rxjs_1.defer)(() => {
173
220
  const viewport = this.#props.viewport;
174
221
  if (!viewport.view.isSpatialView()) {
175
- return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled", getTooltipOptions("modelsTree.model.nonSpatialView", ignoreTooltip)));
222
+ return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("disabled", (0, Utils_js_1.getTooltipOptions)("modelsTree.model.nonSpatialView", ignoreTooltip)));
176
223
  }
177
224
  return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(modelIds)).pipe((0, rxjs_1.distinct)(), (0, rxjs_1.mergeMap)((modelId) => {
178
225
  if (!viewport.view.viewsModel(modelId)) {
179
- return (0, rxjs_1.from)(this.#idsCache.getModelCategories(modelId)).pipe((0, rxjs_1.mergeMap)((categoryIds) => (0, rxjs_1.from)(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds))), this.getSubModeledElementsVisibilityStatus({
226
+ return this.#idsCache.getModelCategories(modelId).pipe((0, rxjs_1.mergeMap)((categoryIds) => this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)), this.getSubModeledElementsVisibilityStatus({
180
227
  ignoreTooltips: ignoreTooltip,
181
228
  haveSubModel: "yes",
182
229
  tooltips: { visible: undefined, hidden: "modelsTree.model.hiddenThroughModelSelector", partial: "modelsTree.model.someSubModelsVisible" },
183
230
  parentNodeVisibilityStatus: (0, Tooltip_js_1.createVisibilityStatus)("hidden"),
184
231
  }));
185
232
  }
186
- return (0, rxjs_1.from)(this.#idsCache.getModelCategories(modelId)).pipe((0, rxjs_1.mergeMap)((categoryIds) => categoryIds.length === 0 ? (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("visible")) : this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true })), mergeVisibilityStatuses({
233
+ return this.#idsCache.getModelCategories(modelId).pipe((0, rxjs_1.mergeMap)((categoryIds) => {
234
+ return categoryIds.length === 0
235
+ ? (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("visible"))
236
+ : this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true });
237
+ }), (0, Utils_js_1.mergeVisibilityStatuses)({
187
238
  visible: "modelsTree.model.allCategoriesVisible",
188
239
  partial: "modelsTree.model.someCategoriesHidden",
189
240
  hidden: "modelsTree.model.allCategoriesHidden",
190
241
  }));
191
- }), mergeVisibilityStatuses());
242
+ }), (0, Utils_js_1.mergeVisibilityStatuses)());
192
243
  });
193
244
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { ids: modelIds }, result, this.#props.overrides?.getModelDisplayStatus);
194
245
  }
195
246
  getDefaultCategoryVisibilityStatus({ modelId, categoryIds, ignoreTooltip, }) {
196
247
  const viewport = this.#props.viewport;
197
248
  if (!viewport.view.viewsModel(modelId) || core_bentley_1.Id64.sizeOf(categoryIds) === 0) {
198
- return (0, Tooltip_js_1.createVisibilityStatus)("hidden", getTooltipOptions("modelsTree.category.hiddenThroughModel", ignoreTooltip));
249
+ return (0, Tooltip_js_1.createVisibilityStatus)("hidden", (0, Utils_js_1.getTooltipOptions)("modelsTree.category.hiddenThroughModel", ignoreTooltip));
199
250
  }
200
251
  let visibility = "unknown";
201
252
  for (const categoryId of core_bentley_1.Id64.iterable(categoryIds)) {
@@ -229,7 +280,7 @@ class ModelsTreeVisibilityHandlerImpl {
229
280
  getCategoryDisplayStatus({ ignoreTooltip, ...props }) {
230
281
  const result = (0, rxjs_1.defer)(() => {
231
282
  if (!this.#props.viewport.view.viewsModel(props.modelId)) {
232
- return (0, rxjs_1.from)(this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
283
+ return this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds).pipe(this.getSubModeledElementsVisibilityStatus({
233
284
  ignoreTooltips: ignoreTooltip,
234
285
  parentNodeVisibilityStatus: (0, Tooltip_js_1.createVisibilityStatus)("hidden"),
235
286
  tooltips: {
@@ -253,7 +304,7 @@ class ModelsTreeVisibilityHandlerImpl {
253
304
  : this.getDefaultCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds }),
254
305
  ignoreTooltip,
255
306
  }).pipe((0, rxjs_1.mergeMap)((visibilityStatusAlwaysAndNeverDraw) => {
256
- return (0, rxjs_1.from)(this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
307
+ return this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds).pipe(this.getSubModeledElementsVisibilityStatus({
257
308
  tooltips: {
258
309
  visible: undefined,
259
310
  hidden: "modelsTree.category.allElementsAndSubModelsHidden",
@@ -268,25 +319,33 @@ class ModelsTreeVisibilityHandlerImpl {
268
319
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, props, result, this.#props.overrides?.getCategoryDisplayStatus);
269
320
  }
270
321
  getClassGroupingNodeDisplayStatus(node) {
271
- const { elementIds, modelId, categoryId } = this.getGroupingNodeInfo(node);
322
+ const { elementIds, modelId, categoryId, childrenCount } = this.getGroupingNodeInfo(node);
323
+ const rootCategoryIds = getRootCategoryIds({ parentKeys: node.parentKeys, modelId });
324
+ (0, core_bentley_1.assert)(rootCategoryIds !== undefined);
272
325
  const result = this.getElementsDisplayStatus({
273
326
  elementIds,
274
327
  modelId,
275
328
  categoryId,
329
+ rootCategoryIds,
330
+ parentElementIdsPath: getParentElementsIdsPath({ parentKeys: node.parentKeys, modelId }),
331
+ childrenCount: childrenCount ?? 0,
276
332
  });
277
333
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { node }, result, this.#props.overrides?.getElementGroupingNodeDisplayStatus);
278
334
  }
279
- getElementDisplayStatus({ elementIds, modelId, categoryId, }) {
335
+ getElementDisplayStatus({ parentKeys, totalChildrenCount, elementIds, modelId, rootCategoryIds, categoryId, }) {
280
336
  const result = this.getElementsDisplayStatus({
337
+ rootCategoryIds,
281
338
  elementIds,
282
339
  modelId,
283
340
  categoryId,
341
+ parentElementIdsPath: getParentElementsIdsPath({ parentKeys, modelId }),
342
+ childrenCount: totalChildrenCount,
284
343
  });
285
344
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { elementId: elementIds[0], modelId, categoryId }, result, this.#props.overrides?.getElementDisplayStatus);
286
345
  }
287
346
  getElementsDisplayStatus(props) {
288
347
  return (0, rxjs_1.defer)(() => {
289
- const { modelId, categoryId, elementIds } = props;
348
+ const { modelId, categoryId, elementIds, parentElementIdsPath, childrenCount, rootCategoryIds } = props;
290
349
  if (!this.#props.viewport.view.viewsModel(modelId)) {
291
350
  return (0, rxjs_1.of)(elementIds).pipe(this.getSubModeledElementsVisibilityStatus({
292
351
  tooltips: {
@@ -300,9 +359,13 @@ class ModelsTreeVisibilityHandlerImpl {
300
359
  }
301
360
  return this.getVisibilityFromAlwaysAndNeverDrawnElements({
302
361
  elements: elementIds,
362
+ parentElementIdsPath,
363
+ modelIds: modelId,
364
+ rootCategoryIds,
365
+ childrenCount,
303
366
  defaultStatus: () => {
304
367
  const status = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
305
- return (0, Tooltip_js_1.createVisibilityStatus)(status.state, getTooltipOptions(`modelsTree.groupingNode.${status.state}ThroughCategory`));
368
+ return (0, Tooltip_js_1.createVisibilityStatus)(status.state, (0, Utils_js_1.getTooltipOptions)(`modelsTree.groupingNode.${status.state}ThroughCategory`));
306
369
  },
307
370
  tooltips: {
308
371
  allElementsInAlwaysDrawnList: "modelsTree.groupingNode.allElementsVisible",
@@ -335,7 +398,9 @@ class ModelsTreeVisibilityHandlerImpl {
335
398
  if (!presentation_hierarchies_1.HierarchyNode.isInstancesNode(node)) {
336
399
  return rxjs_1.EMPTY;
337
400
  }
338
- if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
401
+ // Only call changeFilteredNodeVisibility when node is not a filter target, is not a child of filter target and has filtered children.
402
+ // Otherwise, it can be handled normally.
403
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget && !node.filtering.hasFilterTargetAncestor) {
339
404
  return this.changeFilteredNodeVisibility({ node, on });
340
405
  }
341
406
  if (ModelsTreeNode_js_1.ModelsTreeNode.isSubjectNode(node)) {
@@ -359,12 +424,18 @@ class ModelsTreeVisibilityHandlerImpl {
359
424
  if (!categoryId) {
360
425
  return rxjs_1.EMPTY;
361
426
  }
362
- return this.changeElementsState({
363
- elementIds: new Set([...node.key.instanceKeys.map(({ id }) => id)]),
427
+ const elementIds = new Set(node.key.instanceKeys.map(({ id }) => id));
428
+ return this.#idsCache.getChildrenTree({ elementIds }).pipe((0, rxjs_1.map)((childrenTree) => {
429
+ // Children tree contains provided elementIds, they are at the root of this tree.
430
+ // We want to skip them and only get ids of children.
431
+ return (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ depth }) => depth > 0 });
432
+ }), (0, rxjs_1.mergeMap)((children) => this.changeElementsState({
433
+ elementIds,
364
434
  modelId,
435
+ children: children.size > 0 ? children : undefined,
365
436
  categoryId,
366
437
  on,
367
- });
438
+ })));
368
439
  });
369
440
  if (this.#props.viewport.isAlwaysDrawnExclusive) {
370
441
  return (0, rxjs_1.concat)(this.removeAlwaysDrawnExclusive(), changeObs);
@@ -373,7 +444,7 @@ class ModelsTreeVisibilityHandlerImpl {
373
444
  }
374
445
  changeFilteredNodeVisibility({ on, ...props }) {
375
446
  (0, core_bentley_1.assert)(this.#filteredTree !== undefined);
376
- return (0, rxjs_1.from)(this.#filteredTree).pipe((0, rxjs_1.map)((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), (0, rxjs_1.mergeMap)(({ subjects, models, categories, elements }) => {
447
+ return (0, rxjs_1.from)(this.#filteredTree).pipe((0, rxjs_1.map)((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), (0, rxjs_1.mergeMap)(({ subjects, categories, elements, models }) => {
377
448
  const observables = new Array();
378
449
  if (subjects?.size) {
379
450
  observables.push(this.changeSubjectNodeState([...subjects], on));
@@ -388,16 +459,30 @@ class ModelsTreeVisibilityHandlerImpl {
388
459
  })));
389
460
  }
390
461
  if (elements?.size) {
391
- observables.push((0, rxjs_1.from)(elements).pipe((0, rxjs_1.mergeMap)(([categoryKey, elementsMap]) => {
462
+ const filterTargetElements = new Array();
463
+ const elementsSet = new Set();
464
+ elements.forEach((elementsMap) => elementsMap.forEach(({ isFilterTarget }, elementId) => {
465
+ elementsSet.add(elementId);
466
+ if (isFilterTarget) {
467
+ filterTargetElements.push(elementId);
468
+ }
469
+ }));
470
+ observables.push(this.#idsCache.getChildrenTree({ elementIds: filterTargetElements }).pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree })), (0, rxjs_1.map)((childrenIds) => (0, Utils_js_1.setDifference)(childrenIds, elementsSet)), (0, rxjs_1.mergeMap)((childElementIds) => (0, rxjs_1.from)(elements).pipe((0, rxjs_1.mergeMap)(([categoryKey, elementsMap]) => {
392
471
  const { modelId, categoryId } = (0, FilteredTree_js_1.parseCategoryKey)(categoryKey);
393
- return this.changeElementsState({ modelId, categoryId, elementIds: new Set([...elementsMap.keys()]), on });
394
- })));
472
+ return this.changeElementsState({
473
+ modelId,
474
+ categoryId,
475
+ elementIds: new Set([...elementsMap.keys()]),
476
+ on,
477
+ children: childElementIds.size > 0 ? childElementIds : undefined,
478
+ });
479
+ })))));
395
480
  }
396
481
  return (0, rxjs_1.merge)(...observables);
397
482
  }));
398
483
  }
399
484
  removeAlwaysDrawnExclusive() {
400
- return (0, rxjs_1.from)(this.#idsCache.getAllCategories()).pipe((0, rxjs_1.map)((categoryIds) => {
485
+ return this.#idsCache.getAllCategories().pipe((0, rxjs_1.map)((categoryIds) => {
401
486
  this.#props.viewport.changeCategoryDisplay(categoryIds, false, false);
402
487
  this.#props.viewport.clearNeverDrawn();
403
488
  this.#props.viewport.perModelCategoryVisibility.clearOverrides();
@@ -409,7 +494,7 @@ class ModelsTreeVisibilityHandlerImpl {
409
494
  if (!this.#props.viewport.view.isSpatialView()) {
410
495
  return rxjs_1.EMPTY;
411
496
  }
412
- return (0, rxjs_1.from)(this.#idsCache.getSubjectModelIds(ids)).pipe((0, rxjs_1.mergeMap)((modelIds) => this.changeModelState({ ids: modelIds, on })));
497
+ return this.#idsCache.getSubjectModelIds(ids).pipe((0, rxjs_1.mergeMap)((modelIds) => this.changeModelState({ ids: modelIds, on })));
413
498
  });
414
499
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { ids, on }, result, this.#props.overrides?.changeSubjectNodeState);
415
500
  }
@@ -426,13 +511,13 @@ class ModelsTreeVisibilityHandlerImpl {
426
511
  const idsObs = (0, rxjs_1.from)(core_bentley_1.Id64.iterable(ids));
427
512
  if (!on) {
428
513
  viewport.changeModelDisplay(ids, false);
429
- return idsObs.pipe((0, rxjs_1.mergeMap)(async (modelId) => ({ modelId, categoryIds: await this.#idsCache.getModelCategories(modelId) })), (0, rxjs_1.mergeMap)(({ modelId, categoryIds }) => (0, rxjs_1.from)(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds))), (0, rxjs_1.mergeMap)((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
514
+ return idsObs.pipe((0, rxjs_1.mergeMap)((modelId) => (0, rxjs_1.forkJoin)({ categoryIds: this.#idsCache.getModelCategories(modelId), modelId: (0, rxjs_1.of)(modelId) })), (0, rxjs_1.mergeMap)(({ modelId, categoryIds }) => this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)), (0, rxjs_1.mergeMap)((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
430
515
  }
431
516
  return (0, rxjs_1.concat)((0, rxjs_1.defer)(() => {
432
517
  viewport.perModelCategoryVisibility.clearOverrides(ids);
433
518
  return (0, rxjs_1.from)(viewport.addViewedModels(ids));
434
519
  }), idsObs.pipe((0, rxjs_1.mergeMap)((modelId) => {
435
- return (0, rxjs_1.from)(this.#idsCache.getModelCategories(modelId)).pipe((0, rxjs_1.mergeMap)((categoryIds) => this.changeCategoryState({ categoryIds, modelId, on: true })));
520
+ return this.#idsCache.getModelCategories(modelId).pipe((0, rxjs_1.mergeMap)((categoryIds) => this.changeCategoryState({ categoryIds, modelId, on: true })));
436
521
  })));
437
522
  });
438
523
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, props, result, this.#props.overrides?.changeModelState);
@@ -442,15 +527,12 @@ class ModelsTreeVisibilityHandlerImpl {
442
527
  return (0, rxjs_1.forkJoin)({
443
528
  categories: this.#idsCache.getModelCategories(modelId),
444
529
  alwaysDrawnElements: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
445
- }).pipe((0, rxjs_1.mergeMap)(async ({ categories, alwaysDrawnElements }) => {
530
+ }).pipe((0, rxjs_1.mergeMap)(({ categories, alwaysDrawnElements }) => {
446
531
  const alwaysDrawn = this.#props.viewport.alwaysDrawn;
447
532
  if (alwaysDrawn && alwaysDrawnElements) {
448
- viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
533
+ viewport.setAlwaysDrawn((0, Utils_js_1.setDifference)(alwaysDrawn, alwaysDrawnElements));
449
534
  }
450
- categories.forEach((categoryId) => {
451
- this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false);
452
- });
453
- await viewport.addViewedModels(modelId);
535
+ return (0, rxjs_1.concat)((0, rxjs_1.from)(core_bentley_1.Id64.iterable(categories)).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(300), (0, rxjs_1.map)((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false))), (0, rxjs_1.defer)(async () => viewport.addViewedModels(modelId)));
454
536
  }));
455
537
  }
456
538
  changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on) {
@@ -472,24 +554,37 @@ class ModelsTreeVisibilityHandlerImpl {
472
554
  const result = (0, rxjs_1.defer)(() => {
473
555
  const viewport = this.#props.viewport;
474
556
  const { modelId, categoryIds, on } = props;
475
- return (0, rxjs_1.concat)(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : rxjs_1.EMPTY, (0, rxjs_1.defer)(() => {
476
- for (const categoryId of core_bentley_1.Id64.iterable(categoryIds)) {
477
- this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on);
478
- }
479
- return this.clearAlwaysAndNeverDrawnElements(props);
480
- }), (0, rxjs_1.from)(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)).pipe((0, rxjs_1.mergeMap)((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
557
+ return (0, rxjs_1.concat)(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : rxjs_1.EMPTY, (0, rxjs_1.from)(core_bentley_1.Id64.iterable(categoryIds)).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(300), (0, rxjs_1.map)((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on))), this.clearAlwaysAndNeverDrawnElements(props), this.#idsCache
558
+ .getCategoriesModeledElements(modelId, categoryIds)
559
+ .pipe((0, rxjs_1.mergeMap)((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
481
560
  });
482
561
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, props, result, this.#props.overrides?.changeCategoryState);
483
562
  }
484
563
  doChangeElementsState(props) {
485
564
  return (0, rxjs_1.defer)(() => {
486
- const { modelId, categoryId, elementIds, on } = props;
565
+ const { modelId, categoryId, elementIds, on, children } = props;
487
566
  const viewport = this.#props.viewport;
488
567
  return (0, rxjs_1.concat)(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : rxjs_1.EMPTY, (0, rxjs_1.defer)(() => {
489
568
  const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
490
- const isDisplayedByDefault = categoryVisibility.state === "visible";
491
- return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
492
- }), (0, rxjs_1.from)(elementIds).pipe((0, rxjs_1.mergeMap)(async (elementId) => ({ elementId, isSubModel: await this.#idsCache.hasSubModel(elementId) })), (0, rxjs_1.filter)(({ isSubModel }) => isSubModel), (0, rxjs_1.map)(({ elementId }) => elementId), (0, rxjs_1.toArray)(), (0, rxjs_1.mergeMap)((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
569
+ const isCategoryVisible = categoryVisibility.state === "visible";
570
+ // Make sure to add all children to always/never drawn list.
571
+ const isDisplayedByDefault =
572
+ // When category is visible and elements need to be turned off, or when category is hidden and elements need to be turned on,
573
+ // We can set isDisplayedByDefault to isCategoryVisible. This allows to not check if each element is in the elementIds list or not.
574
+ isCategoryVisible === !on
575
+ ? () => isCategoryVisible
576
+ : (elementId) => {
577
+ if (elementIds.has(elementId)) {
578
+ return isCategoryVisible;
579
+ }
580
+ return !on;
581
+ };
582
+ const elementsToChange = children ? [...elementIds, ...(typeof children === "string" ? [children] : children)] : elementIds;
583
+ return this.queueElementsVisibilityChange(elementsToChange, on, isDisplayedByDefault);
584
+ }), (0, rxjs_1.from)(elementIds).pipe((0, rxjs_1.mergeMap)((elementId) => (0, rxjs_1.forkJoin)({
585
+ elementId: (0, rxjs_1.of)(elementId),
586
+ isSubModel: this.#idsCache.hasSubModel(elementId),
587
+ })), (0, rxjs_1.filter)(({ isSubModel }) => isSubModel), (0, rxjs_1.map)(({ elementId }) => elementId), (0, rxjs_1.toArray)(), (0, rxjs_1.mergeMap)((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
493
588
  });
494
589
  }
495
590
  /**
@@ -497,7 +592,14 @@ class ModelsTreeVisibilityHandlerImpl {
497
592
  * @see `changeElementState`
498
593
  */
499
594
  changeElementGroupingNodeState(node, on) {
500
- const result = this.doChangeElementsState({ ...this.getGroupingNodeInfo(node), on });
595
+ const { modelId, categoryId, elementIds } = this.getGroupingNodeInfo(node);
596
+ const result = this.#idsCache.getChildrenTree({ elementIds }).pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ depth }) => depth > 0 })), (0, rxjs_1.mergeMap)((children) => this.doChangeElementsState({
597
+ modelId,
598
+ categoryId,
599
+ elementIds,
600
+ children: children.size > 0 ? children : undefined,
601
+ on,
602
+ })));
501
603
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { node, on }, result, this.#props.overrides?.changeElementGroupingNodeState);
502
604
  }
503
605
  /**
@@ -512,7 +614,7 @@ class ModelsTreeVisibilityHandlerImpl {
512
614
  const finishedSubject = new rxjs_1.Subject();
513
615
  // observable to track if visibility change is finished/cancelled
514
616
  const changeFinished = finishedSubject.pipe((0, rxjs_1.startWith)(false), (0, rxjs_1.shareReplay)(1), (0, rxjs_1.filter)((finished) => finished));
515
- const changeObservable = (0, rxjs_1.from)(elementIds).pipe(
617
+ const changeObservable = (0, rxjs_1.from)(core_bentley_1.Id64.iterable(elementIds)).pipe(
516
618
  // check if visibility change is not finished (cancelled) due to change overall change request being cancelled
517
619
  (0, rxjs_1.takeUntil)(changeFinished), this.changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault }), (0, rxjs_1.tap)({
518
620
  next: () => {
@@ -543,7 +645,7 @@ class ModelsTreeVisibilityHandlerImpl {
543
645
  const wasRemoved = acc.neverDrawn.delete(elementId);
544
646
  acc.changedNeverDrawn ||= wasRemoved;
545
647
  // If exclusive mode is enabled, we must add the element to the always drawn list.
546
- if ((!isDisplayedByDefault || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
648
+ if ((!isDisplayedByDefault(elementId) || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
547
649
  acc.alwaysDrawn.add(elementId);
548
650
  acc.changedAlwaysDrawn = true;
549
651
  }
@@ -552,7 +654,7 @@ class ModelsTreeVisibilityHandlerImpl {
552
654
  const wasRemoved = acc.alwaysDrawn.delete(elementId);
553
655
  acc.changedAlwaysDrawn ||= wasRemoved;
554
656
  // If exclusive mode is not enabled, we have to add the element to the never drawn list.
555
- if (isDisplayedByDefault && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
657
+ if (isDisplayedByDefault(elementId) && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
556
658
  acc.neverDrawn.add(elementId);
557
659
  acc.changedNeverDrawn = true;
558
660
  }
@@ -574,21 +676,23 @@ class ModelsTreeVisibilityHandlerImpl {
574
676
  if (totalCount === 0) {
575
677
  return props.defaultStatus();
576
678
  }
577
- if (neverDrawn?.size === totalCount) {
578
- return (0, Tooltip_js_1.createVisibilityStatus)("hidden", getTooltipOptions(props.tooltips.allElementsInNeverDrawnList, ignoreTooltip));
679
+ const neverDrawnSize = neverDrawn ? core_bentley_1.Id64.sizeOf(neverDrawn) : undefined;
680
+ const alwaysDrawnSize = alwaysDrawn ? core_bentley_1.Id64.sizeOf(alwaysDrawn) : undefined;
681
+ if (neverDrawnSize === totalCount) {
682
+ return (0, Tooltip_js_1.createVisibilityStatus)("hidden", (0, Utils_js_1.getTooltipOptions)(props.tooltips.allElementsInNeverDrawnList, ignoreTooltip));
579
683
  }
580
- if (alwaysDrawn?.size === totalCount) {
581
- return (0, Tooltip_js_1.createVisibilityStatus)("visible", getTooltipOptions(props.tooltips.allElementsInAlwaysDrawnList, ignoreTooltip));
684
+ if (alwaysDrawnSize === totalCount) {
685
+ return (0, Tooltip_js_1.createVisibilityStatus)("visible", (0, Utils_js_1.getTooltipOptions)(props.tooltips.allElementsInAlwaysDrawnList, ignoreTooltip));
582
686
  }
583
687
  const viewport = this.#props.viewport;
584
688
  if (viewport.isAlwaysDrawnExclusive && viewport.alwaysDrawn?.size) {
585
- return alwaysDrawn?.size
586
- ? (0, Tooltip_js_1.createVisibilityStatus)("partial", getTooltipOptions(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
587
- : (0, Tooltip_js_1.createVisibilityStatus)("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip));
689
+ return alwaysDrawnSize
690
+ ? (0, Tooltip_js_1.createVisibilityStatus)("partial", (0, Utils_js_1.getTooltipOptions)(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
691
+ : (0, Tooltip_js_1.createVisibilityStatus)("hidden", (0, Utils_js_1.getTooltipOptions)(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip));
588
692
  }
589
693
  const status = props.defaultStatus();
590
- if ((status.state === "visible" && neverDrawn?.size) || (status.state === "hidden" && alwaysDrawn?.size)) {
591
- return (0, Tooltip_js_1.createVisibilityStatus)("partial", getTooltipOptions(undefined, ignoreTooltip));
694
+ if ((status.state === "visible" && neverDrawnSize) || (status.state === "hidden" && alwaysDrawnSize)) {
695
+ return (0, Tooltip_js_1.createVisibilityStatus)("partial", (0, Utils_js_1.getTooltipOptions)(undefined, ignoreTooltip));
592
696
  }
593
697
  return status;
594
698
  }
@@ -596,51 +700,91 @@ class ModelsTreeVisibilityHandlerImpl {
596
700
  const viewport = this.#props.viewport;
597
701
  if (viewport.isAlwaysDrawnExclusive) {
598
702
  if (!viewport?.alwaysDrawn?.size) {
599
- return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip)));
703
+ return (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("hidden", (0, Utils_js_1.getTooltipOptions)(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip)));
600
704
  }
601
705
  }
602
706
  else if (!viewport?.neverDrawn?.size && !viewport?.alwaysDrawn?.size) {
603
707
  return (0, rxjs_1.of)(props.defaultStatus());
604
708
  }
605
709
  if ("elements" in props) {
606
- return (0, rxjs_1.of)(this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
607
- ...props,
608
- alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
609
- neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
610
- totalCount: core_bentley_1.Id64.sizeOf(props.elements),
611
- ignoreTooltip,
612
- }));
613
- }
614
- const { modelId, categoryIds } = props.categoryProps;
615
- return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(categoryIds)).pipe((0, rxjs_1.mergeMap)((categoryId) => {
616
- const totalCount = this.#idsCache.getCategoryElementsCount(modelId, categoryId);
710
+ const parentElementIdsPath = [...props.parentElementIdsPath, props.elements];
617
711
  return (0, rxjs_1.forkJoin)({
618
- totalCount,
619
- alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
620
- neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
621
- }).pipe(
622
- // There is a known bug:
623
- // Categories that don't have root elements will make visibility result incorrect
624
- // E.g.:
625
- // - CategoryA
626
- // - ElementA (CategoryA is visible)
627
- // - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
628
- // Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
629
- // TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
630
- (0, rxjs_1.map)((state) => {
712
+ childAlwaysDrawn: this.getAlwaysOrNeverDrawnElements({
713
+ modelIds: props.modelIds,
714
+ categoryIds: props.rootCategoryIds,
715
+ parentElementIdsPath,
716
+ setType: "always",
717
+ }),
718
+ childNeverDrawn: this.getAlwaysOrNeverDrawnElements({
719
+ modelIds: props.modelIds,
720
+ categoryIds: props.rootCategoryIds,
721
+ parentElementIdsPath,
722
+ setType: "never",
723
+ }),
724
+ }).pipe((0, rxjs_1.map)(({ childAlwaysDrawn, childNeverDrawn }) => {
725
+ const alwaysDrawn = new Set([...childAlwaysDrawn, ...(viewport.alwaysDrawn?.size ? (0, Utils_js_1.setIntersection)(props.elements, viewport.alwaysDrawn) : [])]);
726
+ const neverDrawn = new Set([...childNeverDrawn, ...(viewport.neverDrawn?.size ? (0, Utils_js_1.setIntersection)(props.elements, viewport.neverDrawn) : [])]);
631
727
  return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
632
728
  ...props,
633
- ...state,
634
- defaultStatus: () => props.defaultStatus(categoryId),
729
+ alwaysDrawn: alwaysDrawn.size > 0 ? alwaysDrawn : undefined,
730
+ neverDrawn: neverDrawn.size > 0 ? neverDrawn : undefined,
731
+ totalCount: props.childrenCount + core_bentley_1.Id64.sizeOf(props.elements),
635
732
  ignoreTooltip,
636
733
  });
637
734
  }));
638
- }), mergeVisibilityStatuses());
735
+ }
736
+ const { modelId, categoryIds } = props.categoryProps;
737
+ return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(categoryIds)).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(100), (0, rxjs_1.mergeMap)((categoryId) => {
738
+ return (0, rxjs_1.forkJoin)({
739
+ categoryId: (0, rxjs_1.of)(categoryId),
740
+ totalCount: this.#idsCache.getCategoryElementsCount(modelId, categoryId),
741
+ alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
742
+ neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
743
+ });
744
+ }),
745
+ // There is a known bug:
746
+ // Categories that don't have root elements will make visibility result incorrect
747
+ // E.g.:
748
+ // - CategoryA
749
+ // - ElementA (CategoryA is visible)
750
+ // - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
751
+ // Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
752
+ // TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
753
+ (0, rxjs_1.map)((state) => {
754
+ return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
755
+ ...props,
756
+ ...state,
757
+ defaultStatus: () => props.defaultStatus(state.categoryId),
758
+ ignoreTooltip,
759
+ });
760
+ }), (0, Utils_js_1.mergeVisibilityStatuses)());
639
761
  }
640
762
  getAlwaysOrNeverDrawnElements(props) {
641
- return this.#alwaysAndNeverDrawnElements
642
- .getElementsTree(props)
643
- .pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_1.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
763
+ if (!this.#filteredTree) {
764
+ return this.#alwaysAndNeverDrawnElements
765
+ .getElementsTree(props)
766
+ .pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
767
+ }
768
+ // When filtered tree is present, children tree retrieved from alwaysAndNeverDrawnElements may include elements that are not present in filtered tree.
769
+ // Need to filter out such elements.
770
+ return (0, rxjs_1.forkJoin)({
771
+ filteredTree: (0, rxjs_1.from)(this.#filteredTree),
772
+ childrenTree: this.#alwaysAndNeverDrawnElements.getElementsTree(props),
773
+ }).pipe((0, rxjs_1.map)(({ filteredTree, childrenTree }) => {
774
+ const parentIdsPath = [props.modelIds];
775
+ if ("categoryIds" in props) {
776
+ parentIdsPath.push(props.categoryIds);
777
+ if ("parentElementIdsPath" in props) {
778
+ props.parentElementIdsPath.forEach((parentElementIds) => parentIdsPath.push(parentElementIds));
779
+ }
780
+ }
781
+ // Get all ids that exist in filtered tree.
782
+ const elements = filteredTree.getElementsFromUnfilteredChildrenTree({ parentIdsPath, childrenTree });
783
+ return elements
784
+ ? // Need to filter elements that are in always/never drawn set.
785
+ (0, Utils_js_1.setIntersection)(elements, (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet }))
786
+ : new Set();
787
+ }));
644
788
  }
645
789
  clearAlwaysAndNeverDrawnElements(props) {
646
790
  return (0, rxjs_1.forkJoin)({
@@ -649,10 +793,10 @@ class ModelsTreeVisibilityHandlerImpl {
649
793
  }).pipe((0, rxjs_1.map)(({ alwaysDrawn, neverDrawn }) => {
650
794
  const viewport = this.#props.viewport;
651
795
  if (viewport.alwaysDrawn?.size && alwaysDrawn.size) {
652
- viewport.setAlwaysDrawn(setDifference(viewport.alwaysDrawn, alwaysDrawn));
796
+ viewport.setAlwaysDrawn((0, Utils_js_1.setDifference)(viewport.alwaysDrawn, alwaysDrawn));
653
797
  }
654
798
  if (viewport.neverDrawn?.size && neverDrawn.size) {
655
- viewport.setNeverDrawn(setDifference(viewport.neverDrawn, neverDrawn));
799
+ viewport.setNeverDrawn((0, Utils_js_1.setDifference)(viewport.neverDrawn, neverDrawn));
656
800
  }
657
801
  }));
658
802
  }
@@ -661,7 +805,9 @@ class ModelsTreeVisibilityHandlerImpl {
661
805
  const categoryId = ModelsTreeNode_js_1.ModelsTreeNode.getCategoryId(node);
662
806
  (0, core_bentley_1.assert)(!!modelId && !!categoryId);
663
807
  const elementIds = new Set(node.groupedInstanceKeys.map((key) => key.id));
664
- return { modelId, categoryId, elementIds };
808
+ const childrenCount = node.extendedData?.childrenCount;
809
+ const isFiltered = node.extendedData?.isFiltered;
810
+ return { modelId, categoryId, elementIds, childrenCount, isFiltered };
665
811
  }
666
812
  getSubModeledElementsVisibilityStatus({ parentNodeVisibilityStatus, haveSubModel, tooltips, ignoreTooltips, }) {
667
813
  return (obs) => {
@@ -671,58 +817,21 @@ class ModelsTreeVisibilityHandlerImpl {
671
817
  if (haveSubModel === "yes") {
672
818
  return (0, rxjs_1.of)(modeledElementIds);
673
819
  }
674
- return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(modeledElementIds)).pipe((0, rxjs_1.mergeMap)(async (elementId) => ({ elementId, hasSubModel: await this.#idsCache.hasSubModel(elementId) })), (0, rxjs_1.filter)(({ hasSubModel }) => hasSubModel), (0, rxjs_1.map)(({ elementId }) => elementId), (0, rxjs_1.toArray)());
820
+ return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(modeledElementIds)).pipe((0, Utils_js_1.releaseMainThreadOnItemsCount)(100), (0, rxjs_1.mergeMap)((elementId) => (0, rxjs_1.forkJoin)({
821
+ hasSubModel: this.#idsCache.hasSubModel(elementId),
822
+ elementId: (0, rxjs_1.of)(elementId),
823
+ })), (0, rxjs_1.filter)(({ hasSubModel }) => hasSubModel), (0, rxjs_1.map)(({ elementId }) => elementId), (0, rxjs_1.toArray)());
675
824
  }),
676
825
  // combine visibility status of sub-models with visibility status of parent node
677
826
  (0, rxjs_1.mergeMap)((modeledElementIds) => {
678
827
  if (core_bentley_1.Id64.sizeOf(modeledElementIds) === 0) {
679
828
  return (0, rxjs_1.of)(parentNodeVisibilityStatus);
680
829
  }
681
- return this.getModelVisibilityStatus({ modelIds: modeledElementIds }).pipe((0, rxjs_1.startWith)(parentNodeVisibilityStatus), mergeVisibilityStatuses(tooltips, ignoreTooltips));
830
+ return this.getModelVisibilityStatus({ modelIds: typeof modeledElementIds === "string" ? [modeledElementIds] : modeledElementIds }).pipe((0, rxjs_1.startWith)(parentNodeVisibilityStatus), (0, Utils_js_1.mergeVisibilityStatuses)(tooltips, ignoreTooltips));
682
831
  }));
683
832
  };
684
833
  }
685
834
  }
686
- function mergeVisibilities(obs) {
687
- return obs.pipe((0, Rxjs_js_1.reduceWhile)((x) => x.allVisible || x.allHidden, (acc, val) => {
688
- acc.allVisible &&= val === "visible";
689
- acc.allHidden &&= val === "hidden";
690
- return acc;
691
- }, { allVisible: true, allHidden: true }), (0, rxjs_1.map)((x) => {
692
- if (!x) {
693
- return "empty";
694
- }
695
- return x.allVisible ? "visible" : x.allHidden ? "hidden" : "partial";
696
- }));
697
- }
698
- function mergeVisibilityStatuses(tooltipMap, ignoreTooltip) {
699
- return (obs) => {
700
- return obs.pipe((0, rxjs_1.map)((visibilityStatus) => visibilityStatus.state), mergeVisibilities, (0, rxjs_1.map)((visibility) => {
701
- if (visibility === "empty") {
702
- visibility = "visible";
703
- }
704
- return (0, Tooltip_js_1.createVisibilityStatus)(visibility, getTooltipOptions(tooltipMap?.[visibility], ignoreTooltip));
705
- }));
706
- };
707
- }
708
- function setDifference(lhs, rhs) {
709
- const result = new Set();
710
- for (const x of lhs) {
711
- if (!rhs.has(x)) {
712
- result.add(x);
713
- }
714
- }
715
- return result;
716
- }
717
- function setIntersection(lhs, rhs) {
718
- const result = new Set();
719
- for (const x of lhs) {
720
- if (rhs.has(x)) {
721
- result.add(x);
722
- }
723
- }
724
- return result;
725
- }
726
835
  /**
727
836
  * Enables display of all given models. Also enables display of all categories and clears always and
728
837
  * never drawn lists in the viewport.
@@ -789,9 +898,33 @@ async function toggleModels(models, enable, viewport) {
789
898
  function areAllModelsVisible(models, viewport) {
790
899
  return models.length !== 0 ? models.every((id) => viewport.viewsModel(id)) : false;
791
900
  }
792
- function getTooltipOptions(key, ignoreTooltip) {
793
- return {
794
- useTooltip: ignoreTooltip ? false : key,
795
- };
901
+ function getParentElementsIdsPath(props) {
902
+ const parentElementIdsPath = new Array();
903
+ const modelIndex = props.parentKeys.findIndex((parentKey) => presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
904
+ if (modelIndex === -1) {
905
+ return parentElementIdsPath;
906
+ }
907
+ // Hierarchy is model -> category -> root elements.
908
+ // Root elements index is 2 more than models'.
909
+ const firstParentIndex = modelIndex + 2;
910
+ for (let i = firstParentIndex; i < props.parentKeys.length; ++i) {
911
+ const parentKey = props.parentKeys[i];
912
+ if (!presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey)) {
913
+ continue;
914
+ }
915
+ parentElementIdsPath.push(parentKey.instanceKeys.map(({ id }) => id));
916
+ }
917
+ return parentElementIdsPath;
918
+ }
919
+ function getRootCategoryIds(props) {
920
+ const modelIndex = props.parentKeys.findIndex((parentKey) => presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
921
+ if (modelIndex === -1 || modelIndex + 1 === props.parentKeys.length) {
922
+ return undefined;
923
+ }
924
+ const rootCategoryKeys = props.parentKeys[modelIndex + 1];
925
+ if (!presentation_hierarchies_1.HierarchyNodeKey.isInstances(rootCategoryKeys)) {
926
+ return undefined;
927
+ }
928
+ return rootCategoryKeys.instanceKeys.map(({ id }) => id);
796
929
  }
797
930
  //# sourceMappingURL=ModelsTreeVisibilityHandler.js.map