@itwin/tree-widget-react 3.15.1 → 3.16.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 (126) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/lib/cjs/tree-widget-react/TreeWidget.d.ts +1 -2
  3. package/lib/cjs/tree-widget-react/TreeWidget.js +12 -12
  4. package/lib/cjs/tree-widget-react/TreeWidget.js.map +1 -1
  5. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +2 -3
  6. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +5 -4
  7. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +4 -7
  9. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +39 -31
  10. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +6 -2
  12. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  13. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -11
  14. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +45 -36
  15. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  16. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +1 -3
  17. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +30 -30
  18. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  19. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +2 -7
  20. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +8 -21
  21. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  22. package/lib/cjs/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +3 -0
  23. package/lib/cjs/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +7 -7
  24. package/lib/cjs/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  25. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.d.ts +2 -0
  26. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.js +14 -0
  27. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.js.map +1 -0
  28. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +4 -1
  29. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  30. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +4 -6
  31. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +31 -26
  32. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  33. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +1 -1
  34. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +4 -2
  35. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  36. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +1 -5
  37. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +44 -44
  38. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  39. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +3 -6
  40. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +20 -16
  41. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  42. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +3 -1
  43. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  44. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +6 -10
  45. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +107 -64
  46. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  47. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +18 -8
  48. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  49. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +24 -0
  50. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +46 -0
  51. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  52. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +40 -9
  53. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +68 -39
  54. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  55. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +13 -5
  56. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +20 -14
  57. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  58. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +4 -13
  59. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +66 -60
  60. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  61. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +6 -2
  62. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +155 -177
  63. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  64. package/lib/esm/tree-widget-react/TreeWidget.d.ts +1 -2
  65. package/lib/esm/tree-widget-react/TreeWidget.js +12 -12
  66. package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
  67. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +2 -3
  68. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +5 -3
  69. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  70. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +4 -7
  71. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +39 -31
  72. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  73. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +6 -2
  74. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  75. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -11
  76. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +45 -36
  77. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +1 -3
  79. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +30 -30
  80. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  81. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +2 -7
  82. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +8 -20
  83. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  84. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +3 -0
  85. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +7 -7
  86. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/common/useGuid.d.ts +2 -0
  88. package/lib/esm/tree-widget-react/components/trees/common/useGuid.js +11 -0
  89. package/lib/esm/tree-widget-react/components/trees/common/useGuid.js.map +1 -0
  90. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +4 -1
  91. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  92. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +4 -6
  93. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +31 -26
  94. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  95. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +4 -2
  97. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  98. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +1 -5
  99. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +44 -44
  100. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  101. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +3 -6
  102. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +21 -17
  103. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  104. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +3 -1
  105. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  106. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +6 -10
  107. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +107 -64
  108. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  109. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +18 -8
  110. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +24 -0
  112. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +44 -0
  113. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  114. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +40 -9
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +70 -41
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +13 -5
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +22 -16
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  120. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +4 -13
  121. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +67 -61
  122. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  123. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +6 -2
  124. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +157 -179
  125. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  126. package/package.json +8 -8
@@ -6,11 +6,11 @@ import { concat, concatAll, defaultIfEmpty, defer, distinct, EMPTY, filter, firs
6
6
  import { assert, Id64 } from "@itwin/core-bentley";
7
7
  import { PerModelCategoryVisibility } from "@itwin/core-frontend";
8
8
  import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
9
- import { toggleAllCategories } from "../../common/CategoriesVisibilityUtils.js";
9
+ import { enableCategoryDisplay, loadCategoriesFromViewport } from "../../common/CategoriesVisibilityUtils.js";
10
10
  import { reduceWhile, toVoidPromise } from "../../common/Rxjs.js";
11
11
  import { createVisibilityStatus } from "../../common/Tooltip.js";
12
12
  import { createVisibilityHandlerResult } from "../../common/UseHierarchyVisibility.js";
13
- import { releaseMainThreadOnItemsCount } from "../Utils.js";
13
+ import { getIdsFromChildrenTree, releaseMainThreadOnItemsCount } from "../Utils.js";
14
14
  import { AlwaysAndNeverDrawnElementInfo } from "./AlwaysAndNeverDrawnElementInfo.js";
15
15
  import { createFilteredTree, parseCategoryKey } from "./FilteredTree.js";
16
16
  import { ModelsTreeNode } from "./ModelsTreeNode.js";
@@ -23,49 +23,49 @@ export function createModelsTreeVisibilityHandler(props) {
23
23
  return new ModelsTreeVisibilityHandlerImpl(props);
24
24
  }
25
25
  class ModelsTreeVisibilityHandlerImpl {
26
- _props;
27
- _eventListener;
28
- _alwaysAndNeverDrawnElements;
29
- _idsCache;
30
- _filteredTree;
31
- _elementChangeQueue = new Subject();
32
- _subscriptions = [];
33
- _changeRequest = new Subject();
34
- constructor(_props) {
35
- this._props = _props;
36
- this._eventListener = createVisibilityChangeEventListener(_props.viewport);
37
- this._alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(_props.viewport);
38
- this._idsCache = this._props.idsCache;
39
- this._filteredTree = _props.filteredPaths ? createFilteredTree(this._props.imodelAccess, _props.filteredPaths) : undefined;
40
- this._subscriptions.push(this._elementChangeQueue.pipe(concatAll()).subscribe());
26
+ #eventListener;
27
+ #alwaysAndNeverDrawnElements;
28
+ #idsCache;
29
+ #filteredTree;
30
+ #elementChangeQueue = new Subject();
31
+ #subscriptions = [];
32
+ #changeRequest = new Subject();
33
+ #props;
34
+ constructor(props) {
35
+ this.#props = props;
36
+ this.#eventListener = createVisibilityChangeEventListener(this.#props.viewport);
37
+ this.#alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(this.#props.viewport, this.#props.componentId);
38
+ this.#idsCache = this.#props.idsCache;
39
+ this.#filteredTree = this.#props.filteredPaths ? createFilteredTree(this.#props.imodelAccess, this.#props.filteredPaths) : undefined;
40
+ this.#subscriptions.push(this.#elementChangeQueue.pipe(concatAll()).subscribe());
41
41
  }
42
42
  get onVisibilityChange() {
43
- return this._eventListener.onVisibilityChange;
43
+ return this.#eventListener.onVisibilityChange;
44
44
  }
45
45
  async getVisibilityStatus(node) {
46
46
  return firstValueFrom(this.getVisibilityStatusObs(node).pipe(
47
47
  // unsubscribe from the observable if the change request for this node is received
48
- takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),
48
+ takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),
49
49
  // unsubscribe if visibility changes
50
50
  takeUntil(fromEventPattern((handler) => {
51
- this._eventListener.onVisibilityChange.addListener(handler);
51
+ this.#eventListener.onVisibilityChange.addListener(handler);
52
52
  }, (handler) => {
53
- this._eventListener.onVisibilityChange.removeListener(handler);
53
+ this.#eventListener.onVisibilityChange.removeListener(handler);
54
54
  })), defaultIfEmpty(createVisibilityStatus("hidden"))));
55
55
  }
56
56
  async changeVisibility(node, shouldDisplay) {
57
57
  // notify about new change request
58
- this._changeRequest.next({ key: node.key, depth: node.parentKeys.length });
58
+ this.#changeRequest.next({ key: node.key, depth: node.parentKeys.length });
59
59
  const changeObservable = this.changeVisibilityObs(node, shouldDisplay).pipe(
60
60
  // unsubscribe from the observable if the change request for this node is received
61
- takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))), tap({
61
+ takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))), tap({
62
62
  subscribe: () => {
63
- this._eventListener.suppressChangeEvents();
64
- this._alwaysAndNeverDrawnElements.suppressChangeEvents();
63
+ this.#eventListener.suppressChangeEvents();
64
+ this.#alwaysAndNeverDrawnElements.suppressChangeEvents();
65
65
  },
66
66
  finalize: () => {
67
- this._eventListener.resumeChangeEvents();
68
- this._alwaysAndNeverDrawnElements.resumeChangeEvents();
67
+ this.#eventListener.resumeChangeEvents();
68
+ this.#alwaysAndNeverDrawnElements.resumeChangeEvents();
69
69
  },
70
70
  }));
71
71
  return toVoidPromise(changeObservable);
@@ -74,20 +74,23 @@ class ModelsTreeVisibilityHandlerImpl {
74
74
  this[Symbol.dispose]();
75
75
  }
76
76
  [Symbol.dispose]() {
77
- this._eventListener[Symbol.dispose]();
78
- this._alwaysAndNeverDrawnElements[Symbol.dispose]();
79
- this._subscriptions.forEach((x) => x.unsubscribe());
77
+ this.#eventListener[Symbol.dispose]();
78
+ this.#alwaysAndNeverDrawnElements[Symbol.dispose]();
79
+ this.#subscriptions.forEach((x) => x.unsubscribe());
80
80
  }
81
81
  getVisibilityStatusObs(node) {
82
- if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
83
- return this.getFilteredNodeVisibility({ node });
84
- }
85
82
  if (HierarchyNode.isClassGroupingNode(node)) {
83
+ if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {
84
+ return this.getFilteredNodeVisibility({ node });
85
+ }
86
86
  return this.getClassGroupingNodeDisplayStatus(node);
87
87
  }
88
88
  if (!HierarchyNode.isInstancesNode(node)) {
89
89
  return of(createVisibilityStatus("disabled"));
90
90
  }
91
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
92
+ return this.getFilteredNodeVisibility({ node });
93
+ }
91
94
  if (ModelsTreeNode.isSubjectNode(node)) {
92
95
  // note: subject nodes may be merged to represent multiple subject instances
93
96
  return this.getSubjectNodeVisibilityStatus({ subjectIds: node.key.instanceKeys.map((key) => key.id) });
@@ -110,13 +113,14 @@ class ModelsTreeVisibilityHandlerImpl {
110
113
  return of(createVisibilityStatus("disabled"));
111
114
  }
112
115
  return this.getElementDisplayStatus({
113
- elementId: node.key.instanceKeys[0].id,
116
+ elementIds: node.key.instanceKeys.map(({ id }) => id),
114
117
  modelId,
115
118
  categoryId,
116
119
  });
117
120
  }
118
121
  getFilteredNodeVisibility(props) {
119
- return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ subjects, models, categories, elements }) => {
122
+ assert(this.#filteredTree !== undefined);
123
+ return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), mergeMap(({ subjects, models, categories, elements }) => {
120
124
  const observables = new Array();
121
125
  if (subjects?.size) {
122
126
  observables.push(this.getSubjectNodeVisibilityStatus({ subjectIds: [...subjects], ignoreTooltip: true }));
@@ -131,9 +135,13 @@ class ModelsTreeVisibilityHandlerImpl {
131
135
  })));
132
136
  }
133
137
  if (elements?.size) {
134
- observables.push(from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementIds]) => {
138
+ observables.push(from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementsMap]) => {
135
139
  const { modelId, categoryId } = parseCategoryKey(categoryKey);
136
- return from(elementIds).pipe(releaseMainThreadOnItemsCount(1000), mergeMap((elementId) => this.getElementDisplayStatus({ modelId, categoryId, elementId, ignoreTooltip: true })));
140
+ return this.getElementsDisplayStatus({
141
+ elementIds: [...elementsMap.keys()],
142
+ modelId,
143
+ categoryId,
144
+ });
137
145
  })));
138
146
  }
139
147
  return merge(...observables);
@@ -141,49 +149,49 @@ class ModelsTreeVisibilityHandlerImpl {
141
149
  }
142
150
  getSubjectNodeVisibilityStatus({ subjectIds, ignoreTooltip }) {
143
151
  const result = defer(() => {
144
- if (!this._props.viewport.view.isSpatialView()) {
152
+ if (!this.#props.viewport.view.isSpatialView()) {
145
153
  return of(createVisibilityStatus("disabled", getTooltipOptions("modelsTree.subject.nonSpatialView", ignoreTooltip)));
146
154
  }
147
- return from(this._idsCache.getSubjectModelIds(subjectIds)).pipe(mergeMap((modelIds) => this.getModelVisibilityStatus({ modelIds, ignoreTooltip: true })), mergeVisibilityStatuses({
155
+ return from(this.#idsCache.getSubjectModelIds(subjectIds)).pipe(mergeMap((modelIds) => this.getModelVisibilityStatus({ modelIds, ignoreTooltip: true })), mergeVisibilityStatuses({
148
156
  visible: "modelsTree.subject.allModelsVisible",
149
157
  hidden: "modelsTree.subject.allModelsHidden",
150
158
  partial: "modelsTree.subject.someModelsHidden",
151
159
  }, ignoreTooltip));
152
160
  });
153
- return createVisibilityHandlerResult(this, { ids: subjectIds }, result, this._props.overrides?.getSubjectNodeVisibility);
161
+ return createVisibilityHandlerResult(this, { ids: subjectIds }, result, this.#props.overrides?.getSubjectNodeVisibility);
154
162
  }
155
163
  getModelVisibilityStatus({ modelIds, ignoreTooltip }) {
156
164
  const result = defer(() => {
157
- const viewport = this._props.viewport;
165
+ const viewport = this.#props.viewport;
158
166
  if (!viewport.view.isSpatialView()) {
159
167
  return of(createVisibilityStatus("disabled", getTooltipOptions("modelsTree.model.nonSpatialView", ignoreTooltip)));
160
168
  }
161
- return from(modelIds).pipe(distinct(), mergeMap((modelId) => {
169
+ return from(Id64.iterable(modelIds)).pipe(distinct(), mergeMap((modelId) => {
162
170
  if (!viewport.view.viewsModel(modelId)) {
163
- return from(this._idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), this.getSubModeledElementsVisibilityStatus({
171
+ return from(this.#idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => from(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds))), this.getSubModeledElementsVisibilityStatus({
164
172
  ignoreTooltips: ignoreTooltip,
165
173
  haveSubModel: "yes",
166
174
  tooltips: { visible: undefined, hidden: "modelsTree.model.hiddenThroughModelSelector", partial: "modelsTree.model.someSubModelsVisible" },
167
175
  parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
168
176
  }));
169
177
  }
170
- return from(this._idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => categoryIds.length === 0 ? of(createVisibilityStatus("visible")) : this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true })), mergeVisibilityStatuses({
178
+ return from(this.#idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => categoryIds.length === 0 ? of(createVisibilityStatus("visible")) : this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true })), mergeVisibilityStatuses({
171
179
  visible: "modelsTree.model.allCategoriesVisible",
172
180
  partial: "modelsTree.model.someCategoriesHidden",
173
181
  hidden: "modelsTree.model.allCategoriesHidden",
174
182
  }));
175
183
  }), mergeVisibilityStatuses());
176
184
  });
177
- return createVisibilityHandlerResult(this, { ids: modelIds }, result, this._props.overrides?.getModelDisplayStatus);
185
+ return createVisibilityHandlerResult(this, { ids: modelIds }, result, this.#props.overrides?.getModelDisplayStatus);
178
186
  }
179
187
  getDefaultCategoryVisibilityStatus({ modelId, categoryIds, ignoreTooltip, }) {
180
- const viewport = this._props.viewport;
188
+ const viewport = this.#props.viewport;
181
189
  if (!viewport.view.viewsModel(modelId) || Id64.sizeOf(categoryIds) === 0) {
182
190
  return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.category.hiddenThroughModel", ignoreTooltip));
183
191
  }
184
192
  let visibility = "unknown";
185
193
  for (const categoryId of Id64.iterable(categoryIds)) {
186
- const override = this._props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId);
194
+ const override = this.#props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId);
187
195
  if (override === PerModelCategoryVisibility.Override.Show) {
188
196
  if (visibility === "hidden") {
189
197
  return createVisibilityStatus("partial");
@@ -212,8 +220,8 @@ class ModelsTreeVisibilityHandlerImpl {
212
220
  }
213
221
  getCategoryDisplayStatus({ ignoreTooltip, ...props }) {
214
222
  const result = defer(() => {
215
- if (!this._props.viewport.view.viewsModel(props.modelId)) {
216
- return from(this._idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
223
+ if (!this.#props.viewport.view.viewsModel(props.modelId)) {
224
+ return from(this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
217
225
  ignoreTooltips: ignoreTooltip,
218
226
  parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
219
227
  tooltips: {
@@ -237,7 +245,7 @@ class ModelsTreeVisibilityHandlerImpl {
237
245
  : this.getDefaultCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds }),
238
246
  ignoreTooltip,
239
247
  }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
240
- return from(this._idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
248
+ return from(this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds)).pipe(this.getSubModeledElementsVisibilityStatus({
241
249
  tooltips: {
242
250
  visible: undefined,
243
251
  hidden: "modelsTree.category.allElementsAndSubModelsHidden",
@@ -249,14 +257,30 @@ class ModelsTreeVisibilityHandlerImpl {
249
257
  }));
250
258
  }));
251
259
  });
252
- return createVisibilityHandlerResult(this, props, result, this._props.overrides?.getCategoryDisplayStatus);
260
+ return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.getCategoryDisplayStatus);
253
261
  }
254
262
  getClassGroupingNodeDisplayStatus(node) {
255
- const result = defer(() => {
256
- const info = this.getGroupingNodeInfo(node);
257
- const { modelId, categoryId, elementIds } = info;
258
- if (!this._props.viewport.view.viewsModel(modelId)) {
259
- return of([...elementIds]).pipe(this.getSubModeledElementsVisibilityStatus({
263
+ const { elementIds, modelId, categoryId } = this.getGroupingNodeInfo(node);
264
+ const result = this.getElementsDisplayStatus({
265
+ elementIds,
266
+ modelId,
267
+ categoryId,
268
+ });
269
+ return createVisibilityHandlerResult(this, { node }, result, this.#props.overrides?.getElementGroupingNodeDisplayStatus);
270
+ }
271
+ getElementDisplayStatus({ elementIds, modelId, categoryId, }) {
272
+ const result = this.getElementsDisplayStatus({
273
+ elementIds,
274
+ modelId,
275
+ categoryId,
276
+ });
277
+ return createVisibilityHandlerResult(this, { elementId: elementIds[0], modelId, categoryId }, result, this.#props.overrides?.getElementDisplayStatus);
278
+ }
279
+ getElementsDisplayStatus(props) {
280
+ return defer(() => {
281
+ const { modelId, categoryId, elementIds } = props;
282
+ if (!this.#props.viewport.view.viewsModel(modelId)) {
283
+ return of(elementIds).pipe(this.getSubModeledElementsVisibilityStatus({
260
284
  tooltips: {
261
285
  visible: undefined,
262
286
  hidden: undefined,
@@ -279,7 +303,7 @@ class ModelsTreeVisibilityHandlerImpl {
279
303
  noElementsInExclusiveAlwaysDrawnList: "modelsTree.groupingNode.allElementsHidden",
280
304
  },
281
305
  }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
282
- return of([...elementIds]).pipe(this.getSubModeledElementsVisibilityStatus({
306
+ return of(elementIds).pipe(this.getSubModeledElementsVisibilityStatus({
283
307
  tooltips: {
284
308
  visible: undefined,
285
309
  hidden: "modelsTree.groupingNode.allElementsAndSubModelsHidden",
@@ -290,80 +314,22 @@ class ModelsTreeVisibilityHandlerImpl {
290
314
  }));
291
315
  }));
292
316
  });
293
- return createVisibilityHandlerResult(this, { node }, result, this._props.overrides?.getElementGroupingNodeDisplayStatus);
294
- }
295
- getElementOverriddenVisibility(elementId, ignoreTooltip) {
296
- const viewport = this._props.viewport;
297
- if (viewport.neverDrawn?.has(elementId)) {
298
- return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughNeverDrawnList", ignoreTooltip));
299
- }
300
- if (viewport.alwaysDrawn?.size) {
301
- if (viewport.alwaysDrawn.has(elementId)) {
302
- return createVisibilityStatus("visible", getTooltipOptions("modelsTree.element.displayedThroughAlwaysDrawnList", ignoreTooltip));
303
- }
304
- if (viewport.isAlwaysDrawnExclusive) {
305
- return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenDueToOtherElementsExclusivelyAlwaysDrawn", ignoreTooltip));
306
- }
307
- }
308
- return undefined;
309
- }
310
- getElementVisibility(ignoreTooltip, viewsModel, overriddenVisibility, categoryVisibility, subModelVisibilityStatus) {
311
- if (subModelVisibilityStatus === undefined) {
312
- if (!viewsModel) {
313
- return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughModel", ignoreTooltip));
314
- }
315
- if (overriddenVisibility) {
316
- return overriddenVisibility;
317
- }
318
- return createVisibilityStatus(categoryVisibility.state, getTooltipOptions(categoryVisibility.state === "visible" ? undefined : "modelsTree.element.hiddenThroughCategory", ignoreTooltip));
319
- }
320
- if (subModelVisibilityStatus.state === "partial") {
321
- return createVisibilityStatus("partial", getTooltipOptions("modelsTree.element.someElementsAreHidden", ignoreTooltip));
322
- }
323
- if (subModelVisibilityStatus.state === "visible") {
324
- if (!viewsModel || overriddenVisibility?.state === "hidden" || (categoryVisibility.state === "hidden" && !overriddenVisibility)) {
325
- return createVisibilityStatus("partial", getTooltipOptions("modelsTree.element.partialThroughSubModel", ignoreTooltip));
326
- }
327
- return createVisibilityStatus("visible", getTooltipOptions(undefined, ignoreTooltip));
328
- }
329
- if (!viewsModel) {
330
- return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughModel", ignoreTooltip));
331
- }
332
- if (overriddenVisibility) {
333
- if (overriddenVisibility.state === "hidden") {
334
- return overriddenVisibility;
335
- }
336
- return createVisibilityStatus("partial", getTooltipOptions("modelsTree.element.partialThroughElement", ignoreTooltip));
337
- }
338
- if (categoryVisibility.state === "visible") {
339
- return createVisibilityStatus("partial", getTooltipOptions("modelsTree.element.partialThroughCategory", ignoreTooltip));
340
- }
341
- return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughCategory", ignoreTooltip));
342
- }
343
- getElementDisplayStatus({ ignoreTooltip, ...props }) {
344
- const result = defer(() => {
345
- const viewport = this._props.viewport;
346
- const { elementId, modelId, categoryId } = props;
347
- const viewsModel = viewport.view.viewsModel(modelId);
348
- const elementStatus = this.getElementOverriddenVisibility(elementId, ignoreTooltip);
349
- return from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((hasSubModel) => (hasSubModel ? this.getModelVisibilityStatus({ modelIds: [elementId] }) : of(undefined))), map((subModelVisibilityStatus) => this.getElementVisibility(ignoreTooltip, viewsModel, elementStatus,
350
- // Single category will always return "visible" or "hidden"
351
- this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true }), subModelVisibilityStatus)));
352
- });
353
- return createVisibilityHandlerResult(this, props, result, this._props.overrides?.getElementDisplayStatus);
354
317
  }
355
318
  /** Changes visibility of the items represented by the tree node. */
356
319
  changeVisibilityObs(node, on) {
357
320
  const changeObs = defer(() => {
358
- if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
359
- return this.changeFilteredNodeVisibility({ node, on });
360
- }
361
321
  if (HierarchyNode.isClassGroupingNode(node)) {
322
+ if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {
323
+ return this.changeFilteredNodeVisibility({ node, on });
324
+ }
362
325
  return this.changeElementGroupingNodeState(node, on);
363
326
  }
364
327
  if (!HierarchyNode.isInstancesNode(node)) {
365
328
  return EMPTY;
366
329
  }
330
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
331
+ return this.changeFilteredNodeVisibility({ node, on });
332
+ }
367
333
  if (ModelsTreeNode.isSubjectNode(node)) {
368
334
  return this.changeSubjectNodeState(node.key.instanceKeys.map((key) => key.id), on);
369
335
  }
@@ -392,17 +358,14 @@ class ModelsTreeVisibilityHandlerImpl {
392
358
  on,
393
359
  });
394
360
  });
395
- if (this._props.viewport.isAlwaysDrawnExclusive) {
361
+ if (this.#props.viewport.isAlwaysDrawnExclusive) {
396
362
  return concat(this.removeAlwaysDrawnExclusive(), changeObs);
397
363
  }
398
364
  return changeObs;
399
365
  }
400
- async getVisibilityChangeTargets({ node }) {
401
- const filteredTree = await this._filteredTree;
402
- return filteredTree ? filteredTree.getVisibilityChangeTargets(node) : {};
403
- }
404
366
  changeFilteredNodeVisibility({ on, ...props }) {
405
- return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ subjects, models, categories, elements }) => {
367
+ assert(this.#filteredTree !== undefined);
368
+ return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), mergeMap(({ subjects, models, categories, elements }) => {
406
369
  const observables = new Array();
407
370
  if (subjects?.size) {
408
371
  observables.push(this.changeSubjectNodeState([...subjects], on));
@@ -417,30 +380,30 @@ class ModelsTreeVisibilityHandlerImpl {
417
380
  })));
418
381
  }
419
382
  if (elements?.size) {
420
- observables.push(from(elements).pipe(mergeMap(([categoryKey, elementIds]) => {
383
+ observables.push(from(elements).pipe(mergeMap(([categoryKey, elementsMap]) => {
421
384
  const { modelId, categoryId } = parseCategoryKey(categoryKey);
422
- return this.changeElementsState({ modelId, categoryId, elementIds, on });
385
+ return this.changeElementsState({ modelId, categoryId, elementIds: new Set([...elementsMap.keys()]), on });
423
386
  })));
424
387
  }
425
388
  return merge(...observables);
426
389
  }));
427
390
  }
428
391
  removeAlwaysDrawnExclusive() {
429
- return from(this._idsCache.getAllCategories()).pipe(map((categoryIds) => {
430
- this._props.viewport.changeCategoryDisplay(categoryIds, false, false);
431
- this._props.viewport.clearNeverDrawn();
432
- this._props.viewport.perModelCategoryVisibility.clearOverrides();
433
- this._props.viewport.setAlwaysDrawn(this._props.viewport.alwaysDrawn ?? new Set());
392
+ return from(this.#idsCache.getAllCategories()).pipe(map((categoryIds) => {
393
+ this.#props.viewport.changeCategoryDisplay(categoryIds, false, false);
394
+ this.#props.viewport.clearNeverDrawn();
395
+ this.#props.viewport.perModelCategoryVisibility.clearOverrides();
396
+ this.#props.viewport.setAlwaysDrawn(this.#props.viewport.alwaysDrawn ?? new Set());
434
397
  }));
435
398
  }
436
399
  changeSubjectNodeState(ids, on) {
437
400
  const result = defer(() => {
438
- if (!this._props.viewport.view.isSpatialView()) {
401
+ if (!this.#props.viewport.view.isSpatialView()) {
439
402
  return EMPTY;
440
403
  }
441
- return from(this._idsCache.getSubjectModelIds(ids)).pipe(mergeMap((modelIds) => this.changeModelState({ ids: modelIds, on })));
404
+ return from(this.#idsCache.getSubjectModelIds(ids)).pipe(mergeMap((modelIds) => this.changeModelState({ ids: modelIds, on })));
442
405
  });
443
- return createVisibilityHandlerResult(this, { ids, on }, result, this._props.overrides?.changeSubjectNodeState);
406
+ return createVisibilityHandlerResult(this, { ids, on }, result, this.#props.overrides?.changeSubjectNodeState);
444
407
  }
445
408
  changeModelState(props) {
446
409
  const { ids, on } = props;
@@ -448,31 +411,31 @@ class ModelsTreeVisibilityHandlerImpl {
448
411
  return EMPTY;
449
412
  }
450
413
  const result = defer(() => {
451
- const viewport = this._props.viewport;
414
+ const viewport = this.#props.viewport;
452
415
  if (!viewport.view.isSpatialView()) {
453
416
  return EMPTY;
454
417
  }
455
418
  const idsObs = from(Id64.iterable(ids));
456
419
  if (!on) {
457
420
  viewport.changeModelDisplay(ids, false);
458
- return idsObs.pipe(mergeMap(async (modelId) => ({ modelId, categoryIds: await this._idsCache.getModelCategories(modelId) })), mergeMap(({ modelId, categoryIds }) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
421
+ return idsObs.pipe(mergeMap(async (modelId) => ({ modelId, categoryIds: await this.#idsCache.getModelCategories(modelId) })), mergeMap(({ modelId, categoryIds }) => from(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds))), mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
459
422
  }
460
423
  return concat(defer(() => {
461
424
  viewport.perModelCategoryVisibility.clearOverrides(ids);
462
425
  return from(viewport.addViewedModels(ids));
463
426
  }), idsObs.pipe(mergeMap((modelId) => {
464
- return from(this._idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => this.changeCategoryState({ categoryIds, modelId, on: true })));
427
+ return from(this.#idsCache.getModelCategories(modelId)).pipe(mergeMap((categoryIds) => this.changeCategoryState({ categoryIds, modelId, on: true })));
465
428
  })));
466
429
  });
467
- return createVisibilityHandlerResult(this, props, result, this._props.overrides?.changeModelState);
430
+ return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.changeModelState);
468
431
  }
469
432
  showModelWithoutAnyCategoriesOrElements(modelId) {
470
- const viewport = this._props.viewport;
433
+ const viewport = this.#props.viewport;
471
434
  return forkJoin({
472
- categories: this._idsCache.getModelCategories(modelId),
473
- alwaysDrawnElements: this.getAlwaysDrawnElements({ modelId }),
435
+ categories: this.#idsCache.getModelCategories(modelId),
436
+ alwaysDrawnElements: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
474
437
  }).pipe(mergeMap(async ({ categories, alwaysDrawnElements }) => {
475
- const alwaysDrawn = this._props.viewport.alwaysDrawn;
438
+ const alwaysDrawn = this.#props.viewport.alwaysDrawn;
476
439
  if (alwaysDrawn && alwaysDrawnElements) {
477
440
  viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
478
441
  }
@@ -483,7 +446,7 @@ class ModelsTreeVisibilityHandlerImpl {
483
446
  }));
484
447
  }
485
448
  changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on) {
486
- const viewport = this._props.viewport;
449
+ const viewport = this.#props.viewport;
487
450
  const isDisplayedInSelector = viewport.view.viewsCategory(categoryId);
488
451
  const override = on === isDisplayedInSelector
489
452
  ? PerModelCategoryVisibility.Override.None
@@ -499,26 +462,26 @@ class ModelsTreeVisibilityHandlerImpl {
499
462
  }
500
463
  changeCategoryState(props) {
501
464
  const result = defer(() => {
502
- const viewport = this._props.viewport;
465
+ const viewport = this.#props.viewport;
503
466
  const { modelId, categoryIds, on } = props;
504
467
  return concat(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
505
468
  for (const categoryId of Id64.iterable(categoryIds)) {
506
469
  this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on);
507
470
  }
508
471
  return this.clearAlwaysAndNeverDrawnElements(props);
509
- }), from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds)).pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
472
+ }), from(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)).pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
510
473
  });
511
- return createVisibilityHandlerResult(this, props, result, this._props.overrides?.changeCategoryState);
474
+ return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.changeCategoryState);
512
475
  }
513
476
  doChangeElementsState(props) {
514
477
  return defer(() => {
515
478
  const { modelId, categoryId, elementIds, on } = props;
516
- const viewport = this._props.viewport;
479
+ const viewport = this.#props.viewport;
517
480
  return concat(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
518
481
  const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
519
482
  const isDisplayedByDefault = categoryVisibility.state === "visible";
520
483
  return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
521
- }), from(elementIds).pipe(mergeMap(async (elementId) => ({ elementId, isSubModel: await this._idsCache.hasSubModel(elementId) })), filter(({ isSubModel }) => isSubModel), map(({ elementId }) => elementId), toArray(), mergeMap((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
484
+ }), from(elementIds).pipe(mergeMap(async (elementId) => ({ elementId, isSubModel: await this.#idsCache.hasSubModel(elementId) })), filter(({ isSubModel }) => isSubModel), map(({ elementId }) => elementId), toArray(), mergeMap((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
522
485
  });
523
486
  }
524
487
  /**
@@ -527,7 +490,7 @@ class ModelsTreeVisibilityHandlerImpl {
527
490
  */
528
491
  changeElementGroupingNodeState(node, on) {
529
492
  const result = this.doChangeElementsState({ ...this.getGroupingNodeInfo(node), on });
530
- return createVisibilityHandlerResult(this, { node, on }, result, this._props.overrides?.changeElementGroupingNodeState);
493
+ return createVisibilityHandlerResult(this, { node, on }, result, this.#props.overrides?.changeElementGroupingNodeState);
531
494
  }
532
495
  /**
533
496
  * Updates visibility of an element and all its child elements by adding them to the always/never drawn list.
@@ -535,7 +498,7 @@ class ModelsTreeVisibilityHandlerImpl {
535
498
  */
536
499
  changeElementsState(props) {
537
500
  const result = this.doChangeElementsState(props);
538
- return createVisibilityHandlerResult(this, props, result, this._props.overrides?.changeElementsState);
501
+ return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.changeElementsState);
539
502
  }
540
503
  queueElementsVisibilityChange(elementIds, on, visibleByDefault) {
541
504
  const finishedSubject = new Subject();
@@ -550,7 +513,7 @@ class ModelsTreeVisibilityHandlerImpl {
550
513
  },
551
514
  }));
552
515
  // queue visibility change. `changeObservable` will be subscribed to when other queue changes are finished
553
- this._elementChangeQueue.next(changeObservable);
516
+ this.#elementChangeQueue.next(changeObservable);
554
517
  // return observable that will emit when visibility change is finished
555
518
  return changeFinished.pipe(take(1), tap({
556
519
  unsubscribe: () => {
@@ -562,11 +525,11 @@ class ModelsTreeVisibilityHandlerImpl {
562
525
  changeElementStateNoChildrenOperator(props) {
563
526
  return (elementIds) => {
564
527
  const { on, isDisplayedByDefault } = props;
565
- const isAlwaysDrawnExclusive = this._props.viewport.isAlwaysDrawnExclusive;
528
+ const isAlwaysDrawnExclusive = this.#props.viewport.isAlwaysDrawnExclusive;
566
529
  return elementIds.pipe(releaseMainThreadOnItemsCount(500), reduce((acc, elementId) => {
567
530
  if (acc.alwaysDrawn === undefined || acc.neverDrawn === undefined) {
568
- acc.alwaysDrawn = new Set(this._props.viewport.alwaysDrawn || []);
569
- acc.neverDrawn = new Set(this._props.viewport.neverDrawn || []);
531
+ acc.alwaysDrawn = new Set(this.#props.viewport.alwaysDrawn || []);
532
+ acc.neverDrawn = new Set(this.#props.viewport.neverDrawn || []);
570
533
  }
571
534
  if (on) {
572
535
  const wasRemoved = acc.neverDrawn.delete(elementId);
@@ -593,8 +556,8 @@ class ModelsTreeVisibilityHandlerImpl {
593
556
  neverDrawn: undefined,
594
557
  alwaysDrawn: undefined,
595
558
  }), map((state) => {
596
- state.changedNeverDrawn && state.neverDrawn && this._props.viewport.setNeverDrawn(state.neverDrawn);
597
- state.changedAlwaysDrawn && state.alwaysDrawn && this._props.viewport.setAlwaysDrawn(state.alwaysDrawn, this._props.viewport.isAlwaysDrawnExclusive);
559
+ state.changedNeverDrawn && state.neverDrawn && this.#props.viewport.setNeverDrawn(state.neverDrawn);
560
+ state.changedAlwaysDrawn && state.alwaysDrawn && this.#props.viewport.setAlwaysDrawn(state.alwaysDrawn, this.#props.viewport.isAlwaysDrawnExclusive);
598
561
  }));
599
562
  };
600
563
  }
@@ -609,7 +572,7 @@ class ModelsTreeVisibilityHandlerImpl {
609
572
  if (alwaysDrawn?.size === totalCount) {
610
573
  return createVisibilityStatus("visible", getTooltipOptions(props.tooltips.allElementsInAlwaysDrawnList, ignoreTooltip));
611
574
  }
612
- const viewport = this._props.viewport;
575
+ const viewport = this.#props.viewport;
613
576
  if (viewport.isAlwaysDrawnExclusive && viewport.alwaysDrawn?.size) {
614
577
  return alwaysDrawn?.size
615
578
  ? createVisibilityStatus("partial", getTooltipOptions(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
@@ -622,7 +585,7 @@ class ModelsTreeVisibilityHandlerImpl {
622
585
  return status;
623
586
  }
624
587
  getVisibilityFromAlwaysAndNeverDrawnElements({ ignoreTooltip, ...props }) {
625
- const viewport = this._props.viewport;
588
+ const viewport = this.#props.viewport;
626
589
  if (viewport.isAlwaysDrawnExclusive) {
627
590
  if (!viewport?.alwaysDrawn?.size) {
628
591
  return of(createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip)));
@@ -636,17 +599,17 @@ class ModelsTreeVisibilityHandlerImpl {
636
599
  ...props,
637
600
  alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
638
601
  neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
639
- totalCount: props.elements.size,
602
+ totalCount: Id64.sizeOf(props.elements),
640
603
  ignoreTooltip,
641
604
  }));
642
605
  }
643
606
  const { modelId, categoryIds } = props.categoryProps;
644
607
  return from(Id64.iterable(categoryIds)).pipe(mergeMap((categoryId) => {
645
- const totalCount = this._idsCache.getCategoryElementsCount(modelId, categoryId);
608
+ const totalCount = this.#idsCache.getCategoryElementsCount(modelId, categoryId);
646
609
  return forkJoin({
647
610
  totalCount,
648
- alwaysDrawn: this.getAlwaysDrawnElements({ categoryIds: categoryId, modelId }),
649
- neverDrawn: this.getNeverDrawnElements({ categoryIds: categoryId, modelId }),
611
+ alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
612
+ neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
650
613
  }).pipe(
651
614
  // There is a known bug:
652
615
  // Categories that don't have root elements will make visibility result incorrect
@@ -666,18 +629,17 @@ class ModelsTreeVisibilityHandlerImpl {
666
629
  }));
667
630
  }), mergeVisibilityStatuses());
668
631
  }
669
- getAlwaysDrawnElements(props) {
670
- return this._alwaysAndNeverDrawnElements.getElements({ modelId: props.modelId, categoryIds: props.categoryIds, setType: "always" });
671
- }
672
- getNeverDrawnElements(props) {
673
- return this._alwaysAndNeverDrawnElements.getElements({ modelId: props.modelId, categoryIds: props.categoryIds, setType: "never" });
632
+ getAlwaysOrNeverDrawnElements(props) {
633
+ return this.#alwaysAndNeverDrawnElements
634
+ .getElementsTree(props)
635
+ .pipe(map((childrenTree) => getIdsFromChildrenTree({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
674
636
  }
675
637
  clearAlwaysAndNeverDrawnElements(props) {
676
638
  return forkJoin({
677
- alwaysDrawn: this.getAlwaysDrawnElements(props),
678
- neverDrawn: this.getNeverDrawnElements(props),
639
+ alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: props.modelId, categoryIds: props.categoryIds, setType: "always" }),
640
+ neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: props.modelId, categoryIds: props.categoryIds, setType: "never" }),
679
641
  }).pipe(map(({ alwaysDrawn, neverDrawn }) => {
680
- const viewport = this._props.viewport;
642
+ const viewport = this.#props.viewport;
681
643
  if (viewport.alwaysDrawn?.size && alwaysDrawn.size) {
682
644
  viewport.setAlwaysDrawn(setDifference(viewport.alwaysDrawn, alwaysDrawn));
683
645
  }
@@ -701,11 +663,11 @@ class ModelsTreeVisibilityHandlerImpl {
701
663
  if (haveSubModel === "yes") {
702
664
  return of(modeledElementIds);
703
665
  }
704
- return from(modeledElementIds).pipe(mergeMap(async (elementId) => ({ elementId, hasSubModel: await this._idsCache.hasSubModel(elementId) })), filter(({ hasSubModel }) => hasSubModel), map(({ elementId }) => elementId), toArray());
666
+ return from(Id64.iterable(modeledElementIds)).pipe(mergeMap(async (elementId) => ({ elementId, hasSubModel: await this.#idsCache.hasSubModel(elementId) })), filter(({ hasSubModel }) => hasSubModel), map(({ elementId }) => elementId), toArray());
705
667
  }),
706
668
  // combine visibility status of sub-models with visibility status of parent node
707
669
  mergeMap((modeledElementIds) => {
708
- if (modeledElementIds.length === 0) {
670
+ if (Id64.sizeOf(modeledElementIds) === 0) {
709
671
  return of(parentNodeVisibilityStatus);
710
672
  }
711
673
  return this.getModelVisibilityStatus({ modelIds: modeledElementIds }).pipe(startWith(parentNodeVisibilityStatus), mergeVisibilityStatuses(tooltips, ignoreTooltips));
@@ -737,24 +699,40 @@ function mergeVisibilityStatuses(tooltipMap, ignoreTooltip) {
737
699
  }
738
700
  function setDifference(lhs, rhs) {
739
701
  const result = new Set();
740
- lhs.forEach((x) => !rhs.has(x) && result.add(x));
702
+ for (const x of lhs) {
703
+ if (!rhs.has(x)) {
704
+ result.add(x);
705
+ }
706
+ }
741
707
  return result;
742
708
  }
743
709
  function setIntersection(lhs, rhs) {
744
710
  const result = new Set();
745
- lhs.forEach((x) => rhs.has(x) && result.add(x));
711
+ for (const x of lhs) {
712
+ if (rhs.has(x)) {
713
+ result.add(x);
714
+ }
715
+ }
746
716
  return result;
747
717
  }
748
718
  /**
749
719
  * Enables display of all given models. Also enables display of all categories and clears always and
750
720
  * never drawn lists in the viewport.
721
+ *
722
+ * @param componentId Optional unique id of the component that consumes this function.
723
+ * It can be any string, as long as it is not shared across different components.
751
724
  * @public
752
725
  */
753
- export async function showAllModels(models, viewport) {
726
+ export async function showAllModels(models, viewport, componentId) {
754
727
  await viewport.addViewedModels(models);
755
728
  viewport.clearNeverDrawn();
756
729
  viewport.clearAlwaysDrawn();
757
- await toggleAllCategories(viewport, true);
730
+ const categories = await loadCategoriesFromViewport(viewport, componentId);
731
+ if (categories.length === 0) {
732
+ return;
733
+ }
734
+ const ids = categories.map((category) => category.categoryId);
735
+ await enableCategoryDisplay(viewport, ids, true);
758
736
  }
759
737
  /**
760
738
  * Disables display of all given models.