@itwin/tree-widget-react 3.17.0 → 3.17.2

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 (64) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +3 -2
  3. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  4. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -3
  5. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +22 -21
  6. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  7. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +57 -107
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  9. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +22 -12
  10. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  12. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js +83 -0
  13. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  14. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  15. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +78 -23
  16. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  17. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -3
  18. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +5 -14
  19. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  20. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +5 -4
  21. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  22. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  23. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  24. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  25. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +15 -0
  26. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +134 -3
  27. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  28. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +247 -123
  29. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  30. package/lib/cjs/tree-widget-react-internal.d.ts +1 -1
  31. package/lib/cjs/tree-widget-react-internal.js +1 -1
  32. package/lib/cjs/tree-widget-react-internal.js.map +1 -1
  33. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +3 -2
  34. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  35. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -3
  36. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +23 -22
  37. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  38. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +59 -109
  39. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  40. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +23 -13
  41. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  42. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  43. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +74 -0
  44. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  45. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  46. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +74 -19
  47. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  48. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -3
  49. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +4 -13
  50. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  51. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +4 -3
  52. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  53. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  54. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  55. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  56. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +15 -0
  57. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +133 -2
  58. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  59. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +230 -106
  60. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  61. package/lib/esm/tree-widget-react-internal.d.ts +1 -1
  62. package/lib/esm/tree-widget-react-internal.js +1 -1
  63. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  64. 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 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,7 +219,7 @@ 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)) {
@@ -187,19 +234,19 @@ class ModelsTreeVisibilityHandlerImpl {
187
234
  return categoryIds.length === 0
188
235
  ? (0, rxjs_1.of)((0, Tooltip_js_1.createVisibilityStatus)("visible"))
189
236
  : this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true });
190
- }), mergeVisibilityStatuses({
237
+ }), (0, Utils_js_1.mergeVisibilityStatuses)({
191
238
  visible: "modelsTree.model.allCategoriesVisible",
192
239
  partial: "modelsTree.model.someCategoriesHidden",
193
240
  hidden: "modelsTree.model.allCategoriesHidden",
194
241
  }));
195
- }), mergeVisibilityStatuses());
242
+ }), (0, Utils_js_1.mergeVisibilityStatuses)());
196
243
  });
197
244
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { ids: modelIds }, result, this.#props.overrides?.getModelDisplayStatus);
198
245
  }
199
246
  getDefaultCategoryVisibilityStatus({ modelId, categoryIds, ignoreTooltip, }) {
200
247
  const viewport = this.#props.viewport;
201
248
  if (!viewport.view.viewsModel(modelId) || core_bentley_1.Id64.sizeOf(categoryIds) === 0) {
202
- 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));
203
250
  }
204
251
  let visibility = "unknown";
205
252
  for (const categoryId of core_bentley_1.Id64.iterable(categoryIds)) {
@@ -272,25 +319,33 @@ class ModelsTreeVisibilityHandlerImpl {
272
319
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, props, result, this.#props.overrides?.getCategoryDisplayStatus);
273
320
  }
274
321
  getClassGroupingNodeDisplayStatus(node) {
275
- 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);
276
325
  const result = this.getElementsDisplayStatus({
277
326
  elementIds,
278
327
  modelId,
279
328
  categoryId,
329
+ rootCategoryIds,
330
+ parentElementIdsPath: getParentElementsIdsPath({ parentKeys: node.parentKeys, modelId }),
331
+ childrenCount: childrenCount ?? 0,
280
332
  });
281
333
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { node }, result, this.#props.overrides?.getElementGroupingNodeDisplayStatus);
282
334
  }
283
- getElementDisplayStatus({ elementIds, modelId, categoryId, }) {
335
+ getElementDisplayStatus({ parentKeys, totalChildrenCount, elementIds, modelId, rootCategoryIds, categoryId, }) {
284
336
  const result = this.getElementsDisplayStatus({
337
+ rootCategoryIds,
285
338
  elementIds,
286
339
  modelId,
287
340
  categoryId,
341
+ parentElementIdsPath: getParentElementsIdsPath({ parentKeys, modelId }),
342
+ childrenCount: totalChildrenCount,
288
343
  });
289
344
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { elementId: elementIds[0], modelId, categoryId }, result, this.#props.overrides?.getElementDisplayStatus);
290
345
  }
291
346
  getElementsDisplayStatus(props) {
292
347
  return (0, rxjs_1.defer)(() => {
293
- const { modelId, categoryId, elementIds } = props;
348
+ const { modelId, categoryId, elementIds, parentElementIdsPath, childrenCount, rootCategoryIds } = props;
294
349
  if (!this.#props.viewport.view.viewsModel(modelId)) {
295
350
  return (0, rxjs_1.of)(elementIds).pipe(this.getSubModeledElementsVisibilityStatus({
296
351
  tooltips: {
@@ -304,9 +359,13 @@ class ModelsTreeVisibilityHandlerImpl {
304
359
  }
305
360
  return this.getVisibilityFromAlwaysAndNeverDrawnElements({
306
361
  elements: elementIds,
362
+ parentElementIdsPath,
363
+ modelIds: modelId,
364
+ rootCategoryIds,
365
+ childrenCount,
307
366
  defaultStatus: () => {
308
367
  const status = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
309
- 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`));
310
369
  },
311
370
  tooltips: {
312
371
  allElementsInAlwaysDrawnList: "modelsTree.groupingNode.allElementsVisible",
@@ -339,7 +398,9 @@ class ModelsTreeVisibilityHandlerImpl {
339
398
  if (!presentation_hierarchies_1.HierarchyNode.isInstancesNode(node)) {
340
399
  return rxjs_1.EMPTY;
341
400
  }
342
- 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) {
343
404
  return this.changeFilteredNodeVisibility({ node, on });
344
405
  }
345
406
  if (ModelsTreeNode_js_1.ModelsTreeNode.isSubjectNode(node)) {
@@ -363,12 +424,18 @@ class ModelsTreeVisibilityHandlerImpl {
363
424
  if (!categoryId) {
364
425
  return rxjs_1.EMPTY;
365
426
  }
366
- return this.changeElementsState({
367
- 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,
368
434
  modelId,
435
+ children: children.size > 0 ? children : undefined,
369
436
  categoryId,
370
437
  on,
371
- });
438
+ })));
372
439
  });
373
440
  if (this.#props.viewport.isAlwaysDrawnExclusive) {
374
441
  return (0, rxjs_1.concat)(this.removeAlwaysDrawnExclusive(), changeObs);
@@ -377,7 +444,7 @@ class ModelsTreeVisibilityHandlerImpl {
377
444
  }
378
445
  changeFilteredNodeVisibility({ on, ...props }) {
379
446
  (0, core_bentley_1.assert)(this.#filteredTree !== undefined);
380
- 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 }) => {
381
448
  const observables = new Array();
382
449
  if (subjects?.size) {
383
450
  observables.push(this.changeSubjectNodeState([...subjects], on));
@@ -392,10 +459,24 @@ class ModelsTreeVisibilityHandlerImpl {
392
459
  })));
393
460
  }
394
461
  if (elements?.size) {
395
- 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]) => {
396
471
  const { modelId, categoryId } = (0, FilteredTree_js_1.parseCategoryKey)(categoryKey);
397
- return this.changeElementsState({ modelId, categoryId, elementIds: new Set([...elementsMap.keys()]), on });
398
- })));
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
+ })))));
399
480
  }
400
481
  return (0, rxjs_1.merge)(...observables);
401
482
  }));
@@ -430,9 +511,7 @@ class ModelsTreeVisibilityHandlerImpl {
430
511
  const idsObs = (0, rxjs_1.from)(core_bentley_1.Id64.iterable(ids));
431
512
  if (!on) {
432
513
  viewport.changeModelDisplay(ids, false);
433
- return idsObs.pipe((0, rxjs_1.mergeMap)((modelId) => this.#idsCache.getModelCategories(modelId).pipe((0, rxjs_1.map)((categoryIds) => {
434
- return { modelId, categoryIds };
435
- }))), (0, rxjs_1.mergeMap)(({ modelId, categoryIds }) => 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 })));
436
515
  }
437
516
  return (0, rxjs_1.concat)((0, rxjs_1.defer)(() => {
438
517
  viewport.perModelCategoryVisibility.clearOverrides(ids);
@@ -448,15 +527,12 @@ class ModelsTreeVisibilityHandlerImpl {
448
527
  return (0, rxjs_1.forkJoin)({
449
528
  categories: this.#idsCache.getModelCategories(modelId),
450
529
  alwaysDrawnElements: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
451
- }).pipe((0, rxjs_1.mergeMap)(async ({ categories, alwaysDrawnElements }) => {
530
+ }).pipe((0, rxjs_1.mergeMap)(({ categories, alwaysDrawnElements }) => {
452
531
  const alwaysDrawn = this.#props.viewport.alwaysDrawn;
453
532
  if (alwaysDrawn && alwaysDrawnElements) {
454
- viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
533
+ viewport.setAlwaysDrawn((0, Utils_js_1.setDifference)(alwaysDrawn, alwaysDrawnElements));
455
534
  }
456
- categories.forEach((categoryId) => {
457
- this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false);
458
- });
459
- 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)));
460
536
  }));
461
537
  }
462
538
  changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on) {
@@ -478,12 +554,7 @@ class ModelsTreeVisibilityHandlerImpl {
478
554
  const result = (0, rxjs_1.defer)(() => {
479
555
  const viewport = this.#props.viewport;
480
556
  const { modelId, categoryIds, on } = props;
481
- return (0, rxjs_1.concat)(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : rxjs_1.EMPTY, (0, rxjs_1.defer)(() => {
482
- for (const categoryId of core_bentley_1.Id64.iterable(categoryIds)) {
483
- this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on);
484
- }
485
- return this.clearAlwaysAndNeverDrawnElements(props);
486
- }), this.#idsCache
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
487
558
  .getCategoriesModeledElements(modelId, categoryIds)
488
559
  .pipe((0, rxjs_1.mergeMap)((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
489
560
  });
@@ -491,12 +562,25 @@ class ModelsTreeVisibilityHandlerImpl {
491
562
  }
492
563
  doChangeElementsState(props) {
493
564
  return (0, rxjs_1.defer)(() => {
494
- const { modelId, categoryId, elementIds, on } = props;
565
+ const { modelId, categoryId, elementIds, on, children } = props;
495
566
  const viewport = this.#props.viewport;
496
567
  return (0, rxjs_1.concat)(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : rxjs_1.EMPTY, (0, rxjs_1.defer)(() => {
497
568
  const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
498
- const isDisplayedByDefault = categoryVisibility.state === "visible";
499
- return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
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);
500
584
  }), (0, rxjs_1.from)(elementIds).pipe((0, rxjs_1.mergeMap)((elementId) => (0, rxjs_1.forkJoin)({
501
585
  elementId: (0, rxjs_1.of)(elementId),
502
586
  isSubModel: this.#idsCache.hasSubModel(elementId),
@@ -508,7 +592,14 @@ class ModelsTreeVisibilityHandlerImpl {
508
592
  * @see `changeElementState`
509
593
  */
510
594
  changeElementGroupingNodeState(node, on) {
511
- 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
+ })));
512
603
  return (0, UseHierarchyVisibility_js_1.createVisibilityHandlerResult)(this, { node, on }, result, this.#props.overrides?.changeElementGroupingNodeState);
513
604
  }
514
605
  /**
@@ -523,7 +614,7 @@ class ModelsTreeVisibilityHandlerImpl {
523
614
  const finishedSubject = new rxjs_1.Subject();
524
615
  // observable to track if visibility change is finished/cancelled
525
616
  const changeFinished = finishedSubject.pipe((0, rxjs_1.startWith)(false), (0, rxjs_1.shareReplay)(1), (0, rxjs_1.filter)((finished) => finished));
526
- const changeObservable = (0, rxjs_1.from)(elementIds).pipe(
617
+ const changeObservable = (0, rxjs_1.from)(core_bentley_1.Id64.iterable(elementIds)).pipe(
527
618
  // check if visibility change is not finished (cancelled) due to change overall change request being cancelled
528
619
  (0, rxjs_1.takeUntil)(changeFinished), this.changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault }), (0, rxjs_1.tap)({
529
620
  next: () => {
@@ -554,7 +645,7 @@ class ModelsTreeVisibilityHandlerImpl {
554
645
  const wasRemoved = acc.neverDrawn.delete(elementId);
555
646
  acc.changedNeverDrawn ||= wasRemoved;
556
647
  // If exclusive mode is enabled, we must add the element to the always drawn list.
557
- if ((!isDisplayedByDefault || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
648
+ if ((!isDisplayedByDefault(elementId) || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
558
649
  acc.alwaysDrawn.add(elementId);
559
650
  acc.changedAlwaysDrawn = true;
560
651
  }
@@ -563,7 +654,7 @@ class ModelsTreeVisibilityHandlerImpl {
563
654
  const wasRemoved = acc.alwaysDrawn.delete(elementId);
564
655
  acc.changedAlwaysDrawn ||= wasRemoved;
565
656
  // If exclusive mode is not enabled, we have to add the element to the never drawn list.
566
- if (isDisplayedByDefault && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
657
+ if (isDisplayedByDefault(elementId) && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
567
658
  acc.neverDrawn.add(elementId);
568
659
  acc.changedNeverDrawn = true;
569
660
  }
@@ -585,21 +676,23 @@ class ModelsTreeVisibilityHandlerImpl {
585
676
  if (totalCount === 0) {
586
677
  return props.defaultStatus();
587
678
  }
588
- if (neverDrawn?.size === totalCount) {
589
- 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));
590
683
  }
591
- if (alwaysDrawn?.size === totalCount) {
592
- 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));
593
686
  }
594
687
  const viewport = this.#props.viewport;
595
688
  if (viewport.isAlwaysDrawnExclusive && viewport.alwaysDrawn?.size) {
596
- return alwaysDrawn?.size
597
- ? (0, Tooltip_js_1.createVisibilityStatus)("partial", getTooltipOptions(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
598
- : (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));
599
692
  }
600
693
  const status = props.defaultStatus();
601
- if ((status.state === "visible" && neverDrawn?.size) || (status.state === "hidden" && alwaysDrawn?.size)) {
602
- 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));
603
696
  }
604
697
  return status;
605
698
  }
@@ -607,28 +700,48 @@ class ModelsTreeVisibilityHandlerImpl {
607
700
  const viewport = this.#props.viewport;
608
701
  if (viewport.isAlwaysDrawnExclusive) {
609
702
  if (!viewport?.alwaysDrawn?.size) {
610
- 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)));
611
704
  }
612
705
  }
613
706
  else if (!viewport?.neverDrawn?.size && !viewport?.alwaysDrawn?.size) {
614
707
  return (0, rxjs_1.of)(props.defaultStatus());
615
708
  }
616
709
  if ("elements" in props) {
617
- return (0, rxjs_1.of)(this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
618
- ...props,
619
- alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
620
- neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
621
- totalCount: core_bentley_1.Id64.sizeOf(props.elements),
622
- ignoreTooltip,
710
+ const parentElementIdsPath = [...props.parentElementIdsPath, props.elements];
711
+ return (0, rxjs_1.forkJoin)({
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) : [])]);
727
+ return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
728
+ ...props,
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),
732
+ ignoreTooltip,
733
+ });
623
734
  }));
624
735
  }
625
736
  const { modelId, categoryIds } = props.categoryProps;
626
- return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(categoryIds)).pipe((0, rxjs_1.mergeMap)((categoryId) => (0, rxjs_1.forkJoin)({
627
- categoryId: (0, rxjs_1.of)(categoryId),
628
- totalCount: this.#idsCache.getCategoryElementsCount(modelId, categoryId),
629
- alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
630
- neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
631
- })),
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
+ }),
632
745
  // There is a known bug:
633
746
  // Categories that don't have root elements will make visibility result incorrect
634
747
  // E.g.:
@@ -637,19 +750,44 @@ class ModelsTreeVisibilityHandlerImpl {
637
750
  // - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
638
751
  // Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
639
752
  // TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
640
- (0, rxjs_1.map)((state) => {
641
- return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
753
+ (0, rxjs_1.mergeMap)((state) => {
754
+ if (this.#props.viewport.isAlwaysDrawnExclusive && state.totalCount === 0) {
755
+ return rxjs_1.EMPTY;
756
+ }
757
+ return (0, rxjs_1.of)(this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
642
758
  ...props,
643
759
  ...state,
644
760
  defaultStatus: () => props.defaultStatus(state.categoryId),
645
761
  ignoreTooltip,
646
- });
647
- }), mergeVisibilityStatuses());
762
+ }));
763
+ }), (0, Utils_js_1.mergeVisibilityStatuses)());
648
764
  }
649
765
  getAlwaysOrNeverDrawnElements(props) {
650
- return this.#alwaysAndNeverDrawnElements
651
- .getElementsTree(props)
652
- .pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_1.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
766
+ if (!this.#filteredTree) {
767
+ return this.#alwaysAndNeverDrawnElements
768
+ .getElementsTree(props)
769
+ .pipe((0, rxjs_1.map)((childrenTree) => (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
770
+ }
771
+ // When filtered tree is present, children tree retrieved from alwaysAndNeverDrawnElements may include elements that are not present in filtered tree.
772
+ // Need to filter out such elements.
773
+ return (0, rxjs_1.forkJoin)({
774
+ filteredTree: (0, rxjs_1.from)(this.#filteredTree),
775
+ childrenTree: this.#alwaysAndNeverDrawnElements.getElementsTree(props),
776
+ }).pipe((0, rxjs_1.map)(({ filteredTree, childrenTree }) => {
777
+ const parentIdsPath = [props.modelIds];
778
+ if ("categoryIds" in props) {
779
+ parentIdsPath.push(props.categoryIds);
780
+ if ("parentElementIdsPath" in props) {
781
+ props.parentElementIdsPath.forEach((parentElementIds) => parentIdsPath.push(parentElementIds));
782
+ }
783
+ }
784
+ // Get all ids that exist in filtered tree.
785
+ const elements = filteredTree.getElementsFromUnfilteredChildrenTree({ parentIdsPath, childrenTree });
786
+ return elements
787
+ ? // Need to filter elements that are in always/never drawn set.
788
+ (0, Utils_js_1.setIntersection)(elements, (0, Utils_js_2.getIdsFromChildrenTree)({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet }))
789
+ : new Set();
790
+ }));
653
791
  }
654
792
  clearAlwaysAndNeverDrawnElements(props) {
655
793
  return (0, rxjs_1.forkJoin)({
@@ -658,10 +796,10 @@ class ModelsTreeVisibilityHandlerImpl {
658
796
  }).pipe((0, rxjs_1.map)(({ alwaysDrawn, neverDrawn }) => {
659
797
  const viewport = this.#props.viewport;
660
798
  if (viewport.alwaysDrawn?.size && alwaysDrawn.size) {
661
- viewport.setAlwaysDrawn(setDifference(viewport.alwaysDrawn, alwaysDrawn));
799
+ viewport.setAlwaysDrawn((0, Utils_js_1.setDifference)(viewport.alwaysDrawn, alwaysDrawn));
662
800
  }
663
801
  if (viewport.neverDrawn?.size && neverDrawn.size) {
664
- viewport.setNeverDrawn(setDifference(viewport.neverDrawn, neverDrawn));
802
+ viewport.setNeverDrawn((0, Utils_js_1.setDifference)(viewport.neverDrawn, neverDrawn));
665
803
  }
666
804
  }));
667
805
  }
@@ -670,7 +808,9 @@ class ModelsTreeVisibilityHandlerImpl {
670
808
  const categoryId = ModelsTreeNode_js_1.ModelsTreeNode.getCategoryId(node);
671
809
  (0, core_bentley_1.assert)(!!modelId && !!categoryId);
672
810
  const elementIds = new Set(node.groupedInstanceKeys.map((key) => key.id));
673
- return { modelId, categoryId, elementIds };
811
+ const childrenCount = node.extendedData?.childrenCount;
812
+ const isFiltered = node.extendedData?.isFiltered;
813
+ return { modelId, categoryId, elementIds, childrenCount, isFiltered };
674
814
  }
675
815
  getSubModeledElementsVisibilityStatus({ parentNodeVisibilityStatus, haveSubModel, tooltips, ignoreTooltips, }) {
676
816
  return (obs) => {
@@ -680,7 +820,7 @@ class ModelsTreeVisibilityHandlerImpl {
680
820
  if (haveSubModel === "yes") {
681
821
  return (0, rxjs_1.of)(modeledElementIds);
682
822
  }
683
- return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(modeledElementIds)).pipe((0, rxjs_1.mergeMap)((elementId) => (0, rxjs_1.forkJoin)({
823
+ 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)({
684
824
  hasSubModel: this.#idsCache.hasSubModel(elementId),
685
825
  elementId: (0, rxjs_1.of)(elementId),
686
826
  })), (0, rxjs_1.filter)(({ hasSubModel }) => hasSubModel), (0, rxjs_1.map)(({ elementId }) => elementId), (0, rxjs_1.toArray)());
@@ -690,51 +830,11 @@ class ModelsTreeVisibilityHandlerImpl {
690
830
  if (core_bentley_1.Id64.sizeOf(modeledElementIds) === 0) {
691
831
  return (0, rxjs_1.of)(parentNodeVisibilityStatus);
692
832
  }
693
- return this.getModelVisibilityStatus({ modelIds: modeledElementIds }).pipe((0, rxjs_1.startWith)(parentNodeVisibilityStatus), mergeVisibilityStatuses(tooltips, ignoreTooltips));
833
+ return this.getModelVisibilityStatus({ modelIds: typeof modeledElementIds === "string" ? [modeledElementIds] : modeledElementIds }).pipe((0, rxjs_1.startWith)(parentNodeVisibilityStatus), (0, Utils_js_1.mergeVisibilityStatuses)(tooltips, ignoreTooltips));
694
834
  }));
695
835
  };
696
836
  }
697
837
  }
698
- function mergeVisibilities(obs) {
699
- return obs.pipe((0, Rxjs_js_1.reduceWhile)((x) => x.allVisible || x.allHidden, (acc, val) => {
700
- acc.allVisible &&= val === "visible";
701
- acc.allHidden &&= val === "hidden";
702
- return acc;
703
- }, { allVisible: true, allHidden: true }), (0, rxjs_1.map)((x) => {
704
- if (!x) {
705
- return "empty";
706
- }
707
- return x.allVisible ? "visible" : x.allHidden ? "hidden" : "partial";
708
- }));
709
- }
710
- function mergeVisibilityStatuses(tooltipMap, ignoreTooltip) {
711
- return (obs) => {
712
- return obs.pipe((0, rxjs_1.map)((visibilityStatus) => visibilityStatus.state), mergeVisibilities, (0, rxjs_1.map)((visibility) => {
713
- if (visibility === "empty") {
714
- visibility = "visible";
715
- }
716
- return (0, Tooltip_js_1.createVisibilityStatus)(visibility, getTooltipOptions(tooltipMap?.[visibility], ignoreTooltip));
717
- }));
718
- };
719
- }
720
- function setDifference(lhs, rhs) {
721
- const result = new Set();
722
- for (const x of lhs) {
723
- if (!rhs.has(x)) {
724
- result.add(x);
725
- }
726
- }
727
- return result;
728
- }
729
- function setIntersection(lhs, rhs) {
730
- const result = new Set();
731
- for (const x of lhs) {
732
- if (rhs.has(x)) {
733
- result.add(x);
734
- }
735
- }
736
- return result;
737
- }
738
838
  /**
739
839
  * Enables display of all given models. Also enables display of all categories and clears always and
740
840
  * never drawn lists in the viewport.
@@ -801,9 +901,33 @@ async function toggleModels(models, enable, viewport) {
801
901
  function areAllModelsVisible(models, viewport) {
802
902
  return models.length !== 0 ? models.every((id) => viewport.viewsModel(id)) : false;
803
903
  }
804
- function getTooltipOptions(key, ignoreTooltip) {
805
- return {
806
- useTooltip: ignoreTooltip ? false : key,
807
- };
904
+ function getParentElementsIdsPath(props) {
905
+ const parentElementIdsPath = new Array();
906
+ const modelIndex = props.parentKeys.findIndex((parentKey) => presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
907
+ if (modelIndex === -1) {
908
+ return parentElementIdsPath;
909
+ }
910
+ // Hierarchy is model -> category -> root elements.
911
+ // Root elements index is 2 more than models'.
912
+ const firstParentIndex = modelIndex + 2;
913
+ for (let i = firstParentIndex; i < props.parentKeys.length; ++i) {
914
+ const parentKey = props.parentKeys[i];
915
+ if (!presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey)) {
916
+ continue;
917
+ }
918
+ parentElementIdsPath.push(parentKey.instanceKeys.map(({ id }) => id));
919
+ }
920
+ return parentElementIdsPath;
921
+ }
922
+ function getRootCategoryIds(props) {
923
+ const modelIndex = props.parentKeys.findIndex((parentKey) => presentation_hierarchies_1.HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
924
+ if (modelIndex === -1 || modelIndex + 1 === props.parentKeys.length) {
925
+ return undefined;
926
+ }
927
+ const rootCategoryKeys = props.parentKeys[modelIndex + 1];
928
+ if (!presentation_hierarchies_1.HierarchyNodeKey.isInstances(rootCategoryKeys)) {
929
+ return undefined;
930
+ }
931
+ return rootCategoryKeys.instanceKeys.map(({ id }) => id);
808
932
  }
809
933
  //# sourceMappingURL=ModelsTreeVisibilityHandler.js.map