@itwin/tree-widget-react 4.0.0-alpha.25 → 4.0.0-alpha.26

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 (192) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +2 -1
  3. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  4. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js +1 -1
  5. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js.map +1 -1
  6. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +4 -1
  7. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +4 -1
  8. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  9. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +1 -0
  10. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +36 -47
  11. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +2 -0
  13. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +4 -1
  14. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  15. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +2 -1
  16. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +75 -38
  17. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  18. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.d.ts +3 -1
  19. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.js.map +1 -1
  20. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +4 -2
  21. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +38 -23
  22. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  23. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +11 -21
  24. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +16 -168
  25. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  26. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.d.ts +65 -0
  27. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js +22 -0
  28. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js.map +1 -0
  29. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.d.ts +2 -2
  30. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js +4 -4
  31. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js.map +1 -1
  32. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.d.ts +6 -10
  33. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js +180 -88
  34. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js.map +1 -1
  35. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.d.ts +14 -5
  36. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js +43 -24
  37. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js.map +1 -1
  38. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.d.ts +3 -1
  39. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js +78 -17
  40. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  41. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.d.ts +2 -0
  42. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js +4 -1
  43. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js.map +1 -1
  44. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +91 -114
  45. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
  46. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.d.ts +2 -2
  47. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
  48. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.d.ts +1 -3
  49. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js +2 -4
  50. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js.map +1 -1
  51. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.d.ts +13 -1
  52. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +62 -32
  53. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
  54. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.d.ts +12 -9
  55. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js +42 -38
  56. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js.map +1 -1
  57. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +15 -38
  58. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +59 -242
  59. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
  60. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.d.ts +29 -0
  61. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js +19 -0
  62. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js.map +1 -0
  63. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.d.ts +4 -8
  64. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js +154 -78
  65. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js.map +1 -1
  66. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js +20 -6
  67. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js.map +1 -1
  68. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.d.ts +6 -10
  69. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js +104 -63
  70. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  71. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.d.ts +7 -0
  72. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js +14 -0
  73. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js.map +1 -0
  74. package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js +1 -1
  75. package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js.map +1 -1
  76. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +2 -2
  77. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/common/Utils.js +2 -2
  79. package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
  80. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +4 -4
  81. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  83. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.d.ts +4 -4
  84. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
  85. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +7 -5
  86. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +2 -2
  88. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
  89. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js +5 -5
  90. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  91. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.d.ts +20 -0
  92. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js +44 -0
  93. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js.map +1 -0
  94. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +4 -0
  95. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.d.ts +12 -0
  97. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js +2 -1
  98. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js.map +1 -1
  99. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +17 -6
  100. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +58 -29
  101. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -1
  102. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +8 -14
  103. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +22 -26
  104. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.d.ts → caches/AlwaysAndNeverDrawnElementInfoCache.d.ts} +15 -21
  106. package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.js → caches/AlwaysAndNeverDrawnElementInfoCache.js} +40 -38
  107. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/AlwaysAndNeverDrawnElementInfoCache.js.map +1 -0
  108. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.d.ts +68 -0
  109. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js +148 -0
  110. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js.map +1 -0
  111. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.d.ts +30 -0
  112. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js +151 -0
  113. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js.map +1 -0
  114. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.d.ts +32 -0
  115. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js +106 -0
  116. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js.map +1 -0
  117. package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.d.ts → caches/ModelCategoryElementsCountCache.d.ts} +9 -2
  118. package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.js → caches/ModelCategoryElementsCountCache.js} +17 -21
  119. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModelCategoryElementsCountCache.js.map +1 -0
  120. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.d.ts +27 -0
  121. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js +106 -0
  122. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js.map +1 -0
  123. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.d.ts +23 -0
  124. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js +56 -0
  125. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js.map +1 -0
  126. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +6 -6
  127. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +27 -17
  128. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -1
  129. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +7 -13
  130. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +36 -35
  131. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  132. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.d.ts +18 -0
  133. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js +14 -1
  134. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js.map +1 -1
  135. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.d.ts +46 -70
  136. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js +229 -361
  137. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js.map +1 -1
  138. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
  139. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  140. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
  141. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +2 -2
  142. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  143. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
  144. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +1 -1
  145. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  146. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +32 -19
  147. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  148. package/lib/esm/tree-widget-react/components/trees/index.d.ts +2 -1
  149. package/lib/esm/tree-widget-react/components/trees/index.js +2 -1
  150. package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
  151. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +4 -1
  152. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +4 -1
  153. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  154. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.d.ts +7 -3
  155. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +36 -35
  156. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  157. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -0
  158. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +3 -1
  159. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  160. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  161. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +56 -26
  162. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  163. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +5 -3
  164. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +25 -12
  165. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  166. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +11 -23
  167. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +56 -189
  168. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  169. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.d.ts +52 -0
  170. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js +22 -0
  171. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js.map +1 -0
  172. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.d.ts +2 -2
  173. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js +8 -8
  174. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js.map +1 -1
  175. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.d.ts +6 -10
  176. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js +179 -72
  177. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js.map +1 -1
  178. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.d.ts +6 -0
  179. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js +20 -8
  180. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js.map +1 -1
  181. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.d.ts +4 -2
  182. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js +73 -13
  183. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  184. package/lib/esm/tree-widget-react-internal.d.ts +1 -0
  185. package/lib/esm/tree-widget-react-internal.js +1 -0
  186. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  187. package/package.json +77 -82
  188. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.d.ts +0 -20
  189. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js +0 -53
  190. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js.map +0 -1
  191. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
  192. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +0 -1
@@ -2,11 +2,11 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- import { concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, forkJoin, from, identity, map, merge, mergeAll, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeLast, takeUntil, tap, } from "rxjs";
5
+ import { bufferCount, concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, forkJoin, from, identity, map, merge, mergeAll, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeLast, takeUntil, tap, } from "rxjs";
6
6
  import { assert, Id64 } from "@itwin/core-bentley";
7
7
  import { createVisibilityStatus } from "../Tooltip.js";
8
- import { fromWithRelease, getSetFromId64Arg, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../Utils.js";
9
- import { changeElementStateNoChildrenOperator, enableCategoryDisplay, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses, } from "../VisibilityUtils.js";
8
+ import { countInSet, fromWithRelease, getOptimalBatchSize, releaseMainThreadOnItemsCount, setDifference } from "../Utils.js";
9
+ import { changeElementStateNoChildrenOperator, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses } from "../VisibilityUtils.js";
10
10
  /**
11
11
  * Base class for visibility status getters and modifiers.
12
12
  *
@@ -32,13 +32,12 @@ export class BaseVisibilityHelper {
32
32
  * This is achieved by:
33
33
  * - Resets `alwaysDrawn` exclusive flag to `false`;
34
34
  * - Turns off all categories;
35
- * - Clears always drawn list;
35
+ * - Clears never drawn list;
36
36
  * - Removes all per-model category overrides. */
37
37
  removeAlwaysDrawnExclusive() {
38
- return from(this.#props.baseIdsCache.getAllCategories()).pipe(map(({ drawingCategories, spatialCategories }) => {
39
- const categoriesToTurnOff = this.#props.viewport.viewType === "2d" ? drawingCategories : spatialCategories;
40
- if (categoriesToTurnOff) {
41
- this.#props.viewport.changeCategoryDisplay({ categoryIds: categoriesToTurnOff, display: false, enableAllSubCategories: false });
38
+ return from(this.#props.baseIdsCache.getAllCategoriesOfElements()).pipe(map((categories) => {
39
+ if (categories.size) {
40
+ this.#props.viewport.changeCategoryDisplay({ categoryIds: categories, display: false, enableAllSubCategories: false });
42
41
  }
43
42
  this.#props.viewport.clearNeverDrawn();
44
43
  this.#props.viewport.clearPerModelCategoryOverrides();
@@ -55,27 +54,18 @@ export class BaseVisibilityHelper {
55
54
  */
56
55
  getModelsVisibilityStatus(props) {
57
56
  const result = defer(() => {
58
- const { modelIds, type } = props;
59
- if ((type === "GeometricModel3d" && this.#props.viewport.viewType !== "3d") || (type === "GeometricModel2d" && this.#props.viewport.viewType !== "2d")) {
60
- return of(createVisibilityStatus("disabled"));
61
- }
57
+ const { modelIds } = props;
62
58
  return from(Id64.iterable(modelIds)).pipe(mergeMap((modelId) => {
63
59
  // For hidden models we only need to check subModels
64
60
  if (!this.#props.viewport.viewsModel(modelId)) {
65
- return this.#props.baseIdsCache.getSubModels({ modelIds: modelId }).pipe(mergeMap(({ subModels }) => {
66
- if (subModels && Id64.sizeOf(subModels) > 0) {
67
- return this.getModelsVisibilityStatus({ modelIds: subModels, type }).pipe(map((subModelsVisibilityStatus) => subModelsVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
68
- }
69
- return of(createVisibilityStatus("hidden"));
70
- }));
61
+ return this.#props.baseIdsCache.getSubModels({ modelId }).pipe(mergeMap((subModels) => this.getModelsVisibilityStatus({ modelIds: subModels }).pipe(map((subModelsVisibilityStatus) => subModelsVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : subModelsVisibilityStatus))), defaultIfEmpty(createVisibilityStatus("hidden")));
71
62
  }
72
- // For visible models we need to check all categories
73
- return this.#props.baseIdsCache.getCategories({ modelIds: modelId }).pipe(mergeMap(({ drawingCategories, spatialCategories }) => merge(drawingCategories
74
- ? of(drawingCategories).pipe(mergeMap((categoryIds) => this.getCategoriesVisibilityStatus({ modelId, categoryIds, type: "DrawingCategory" })))
75
- : EMPTY, spatialCategories
76
- ? of(spatialCategories).pipe(mergeMap((categoryIds) => this.getCategoriesVisibilityStatus({ modelId, categoryIds, type: "SpatialCategory" })))
77
- : EMPTY)), defaultIfEmpty(createVisibilityStatus("visible")));
78
- }), mergeVisibilityStatuses);
63
+ // For visible models we need to check all categories.
64
+ // getCategoriesVisibilityStatus already checks subModels, no need to do that
65
+ // Take top most element categories when always drawn exclusive mode is on, because only top most categories are used to get always/never drawn elements.
66
+ // This means that non top most categories should not affect visibility in any way until https://github.com/iTwin/viewer-components-react/issues/1100 is resolved.
67
+ return this.#props.baseIdsCache.getCategories({ modelId, includeOnlyIfCategoryOfTopMostElement: this.#props.viewport.isAlwaysDrawnExclusive }).pipe(mergeMap((categories) => this.getCategoriesVisibilityStatus({ modelId, categoryIds: categories })), defaultIfEmpty(createVisibilityStatus("visible")));
68
+ }), mergeVisibilityStatuses());
79
69
  });
80
70
  return this.#props.overrideHandler
81
71
  ? this.#props.overrideHandler.createVisibilityHandlerResult({
@@ -86,98 +76,32 @@ export class BaseVisibilityHelper {
86
76
  : result;
87
77
  }
88
78
  /**
89
- * Gets visibility status of a model's categories, assuming model is visible.
79
+ * Gets visibility status of sub-categories.
90
80
  *
91
81
  * Determines visibility status by checking:
92
- * - Elements in the viewports' always/never drawn lists;
93
- * - Default categories visibility status in the viewport;
94
- * - SubModels that are related to the modelId and categoryIds
82
+ * - Category selector visibility in the viewport.
83
+ * - Sub-categories visibility in the viewport.
95
84
  */
96
- getVisibleModelCategoriesVisibilityStatus({ modelId, categoryIds, type, }) {
97
- return merge(this.getVisibilityFromAlwaysAndNeverDrawnElements({
98
- queryProps: { modelId, categoryIds },
99
- defaultStatus: () => this.getVisibleModelCategoriesDirectVisibilityStatus({ modelId, categoryIds }),
100
- }), this.#props.baseIdsCache.getSubModels({ modelId, categoryIds }).pipe(mergeMap(({ subModels }) => {
101
- if (subModels && Id64.sizeOf(subModels) > 0) {
102
- return this.getModelsVisibilityStatus({ modelIds: subModels, type });
103
- }
85
+ getSubCategoriesVisibilityStatus(props) {
86
+ if (Id64.sizeOf(props.subCategoryIds) === 0) {
104
87
  return EMPTY;
105
- }))).pipe(mergeVisibilityStatuses);
106
- }
107
- /** Gets visibility status of sub-categories, assuming category is visible. */
108
- getVisibleCategorySubCategoriesVisibilityStatus(props) {
109
- const { subCategoryIds } = props;
88
+ }
89
+ if (!this.#props.viewport.viewsCategory(props.categoryId)) {
90
+ return of(createVisibilityStatus("hidden"));
91
+ }
110
92
  let subCategoryVisibility = "unknown";
111
- for (const subCategoryId of Id64.iterable(subCategoryIds)) {
93
+ for (const subCategoryId of Id64.iterable(props.subCategoryIds)) {
112
94
  const isSubCategoryVisible = this.#props.viewport.viewsSubCategory(subCategoryId);
113
95
  if (isSubCategoryVisible && subCategoryVisibility === "hidden") {
114
- return createVisibilityStatus("partial");
96
+ return of(createVisibilityStatus("partial"));
115
97
  }
116
98
  if (!isSubCategoryVisible && subCategoryVisibility === "visible") {
117
- return createVisibilityStatus("partial");
99
+ return of(createVisibilityStatus("partial"));
118
100
  }
119
101
  subCategoryVisibility = isSubCategoryVisible ? "visible" : "hidden";
120
102
  }
121
- // If visibility is unknown, no subCategories were provided,
122
- // Since category is visible we return visible
123
- return createVisibilityStatus(subCategoryVisibility === "unknown" ? "visible" : subCategoryVisibility);
124
- }
125
- /**
126
- * Gets visibility status of sub-categories.
127
- *
128
- * Determines visibility status by checking:
129
- * - Models that contain the category visibility;
130
- * - Per model category visibility overrides;
131
- * - Category selector visibility in the viewport.
132
- * - Sub-categories visibility in the viewport.
133
- */
134
- getSubCategoriesVisibilityStatus(props) {
135
- return this.#props.baseIdsCache.getModels({ categoryIds: props.categoryId }).pipe(map(({ models }) => {
136
- let visibility = "unknown";
137
- let nonDefaultModelDisplayStatesCount = 0;
138
- for (const modelId of Id64.iterable(models ?? [])) {
139
- if (!this.#props.viewport.viewsModel(modelId)) {
140
- if (visibility === "visible") {
141
- return createVisibilityStatus("partial");
142
- }
143
- visibility = "hidden";
144
- ++nonDefaultModelDisplayStatesCount;
145
- continue;
146
- }
147
- const override = this.#props.viewport.getPerModelCategoryOverride({ modelId, categoryId: props.categoryId });
148
- if (override === "show") {
149
- if (visibility === "hidden") {
150
- return createVisibilityStatus("partial");
151
- }
152
- visibility = "visible";
153
- ++nonDefaultModelDisplayStatesCount;
154
- continue;
155
- }
156
- if (override === "hide") {
157
- if (visibility === "visible") {
158
- return createVisibilityStatus("partial");
159
- }
160
- visibility = "hidden";
161
- ++nonDefaultModelDisplayStatesCount;
162
- continue;
163
- }
164
- }
165
- if (models && Id64.sizeOf(models) > 0 && nonDefaultModelDisplayStatesCount === Id64.sizeOf(models)) {
166
- assert(visibility === "visible" || visibility === "hidden");
167
- return createVisibilityStatus(visibility);
168
- }
169
- if (!this.#props.viewport.viewsCategory(props.categoryId)) {
170
- return createVisibilityStatus(visibility === "visible" ? "partial" : "hidden");
171
- }
172
- if (Id64.sizeOf(props.subCategoryIds) === 0) {
173
- if (visibility === "hidden") {
174
- return createVisibilityStatus("partial");
175
- }
176
- return createVisibilityStatus("visible");
177
- }
178
- const subCategoriesVisibility = this.getVisibleCategorySubCategoriesVisibilityStatus({ subCategoryIds: props.subCategoryIds });
179
- return subCategoriesVisibility.state === visibility || visibility === "unknown" ? subCategoriesVisibility : createVisibilityStatus("partial");
180
- }), mergeVisibilityStatuses);
103
+ assert(subCategoryVisibility !== "unknown");
104
+ return of(createVisibilityStatus(subCategoryVisibility));
181
105
  }
182
106
  /**
183
107
  * Gets visibility status of categories.
@@ -189,80 +113,23 @@ export class BaseVisibilityHelper {
189
113
  */
190
114
  getCategoriesVisibilityStatus(props) {
191
115
  const result = defer(() => {
192
- const { categoryIds, modelId: modelIdFromProps, type } = props;
193
- if (Id64.sizeOf(categoryIds) === 0 || this.#props.viewport.viewType === "other") {
194
- return EMPTY;
116
+ const { categoryIds, modelId: modelIdFromProps } = props;
117
+ if (modelIdFromProps) {
118
+ return fromWithRelease({ source: categoryIds, releaseOnCount: 100 }).pipe(mergeMap((categoryId) => this.getModelWithCategoryVisibilityStatus({ modelId: modelIdFromProps, categoryId })), mergeVisibilityStatuses());
195
119
  }
196
- const isSupportedInView = (this.#props.viewport.viewType === "3d" && type === "SpatialCategory") || (this.#props.viewport.viewType === "2d" && type === "DrawingCategory");
197
- if (!isSupportedInView) {
198
- return of(createVisibilityStatus("disabled"));
199
- }
200
- const categoryModelsObs = modelIdFromProps
201
- ? from(Id64.iterable(categoryIds)).pipe(map((categoryId) => ({ id: categoryId, models: modelIdFromProps })))
202
- : this.#props.baseIdsCache.getModels({ categoryIds });
203
- return (Id64.sizeOf(categoryIds) > 100 ? categoryModelsObs.pipe(releaseMainThreadOnItemsCount(100)) : categoryModelsObs).pipe(mergeMap(({ id, models }) => {
204
- if (!this.#props.viewport.isAlwaysDrawnExclusive) {
205
- return of({ id, models });
206
- }
207
- // Ignore categories that don't have root geometric elements in always drawn exclusive mode
208
- if (!models) {
209
- return EMPTY;
210
- }
211
- return from(Id64.iterable(models)).pipe(mergeMap((modelId) => forkJoin({
212
- modelId: of(modelId),
213
- elementCount: this.#props.baseIdsCache.getElementsCount({ modelId, categoryId: id }),
214
- })), reduce((acc, { modelId, elementCount }) => {
215
- if (elementCount > 0) {
216
- acc.models.push(modelId);
217
- }
218
- return acc;
219
- }, { id, models: new Array() }), filter(({ models: modelsWithElements }) => modelsWithElements.length > 0));
220
- }), map(({ id, models }) => {
221
- const acc = { categoryId: id, visibleModels: new Array(), hiddenModels: new Array() };
222
- if (!models) {
223
- return acc;
224
- }
225
- for (const modelId of Id64.iterable(models)) {
226
- if (this.#props.viewport.viewsModel(modelId)) {
227
- acc.visibleModels.push(modelId);
228
- }
229
- else {
230
- acc.hiddenModels.push(modelId);
231
- }
232
- }
233
- return acc;
234
- }), mergeMap(({ categoryId, visibleModels, hiddenModels }) => {
235
- return merge(
236
- // For hidden models we only need to check subModels
237
- hiddenModels.length > 0
238
- ? this.#props.baseIdsCache.getSubModels({ modelIds: hiddenModels, categoryId }).pipe(mergeMap(({ subModels }) => {
239
- if (subModels && Id64.sizeOf(subModels) > 0) {
240
- return this.getModelsVisibilityStatus({
241
- modelIds: subModels,
242
- type: this.#props.viewport.viewType === "2d" ? "GeometricModel2d" : "GeometricModel3d",
243
- }).pipe(map((subModelsVisibilityStatus) => subModelsVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
244
- }
245
- return of(createVisibilityStatus("hidden"));
246
- }))
247
- : EMPTY,
248
- // For visible models we need to check all categories
249
- visibleModels.length > 0
250
- ? from(visibleModels).pipe(mergeMap((modelId) => this.getVisibleModelCategoriesVisibilityStatus({
251
- modelId,
252
- categoryIds: categoryId,
253
- type: this.#props.viewport.viewType === "2d" ? "GeometricModel2d" : "GeometricModel3d",
254
- })))
255
- : EMPTY,
256
- // We need to check subCategories as well
257
- !modelIdFromProps
258
- ? this.#props.baseIdsCache.getSubCategories({ categoryId }).pipe(mergeMap((subCategoryIds) => {
259
- if (subCategoryIds.length > 0) {
260
- return this.getSubCategoriesVisibilityStatus({ categoryId, subCategoryIds });
261
- }
262
- return EMPTY;
263
- }))
264
- : EMPTY).pipe(defaultIfEmpty(createVisibilityStatus(!this.#props.viewport.isAlwaysDrawnExclusive && this.#props.viewport.viewsCategory(categoryId) ? "visible" : "hidden")));
265
- }), mergeVisibilityStatuses);
120
+ return fromWithRelease({ source: categoryIds, releaseOnCount: 100 }).pipe(mergeMap((categoryId) =>
121
+ // When always drawn exclusive mode is enabled need to get only models for which category has top most element.
122
+ // This is because always/never drawn elements can be retrieved using top most category.
123
+ // TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
124
+ this.#props.baseIdsCache
125
+ .getModels({ categoryId, includeOnlyIfCategoryOfTopMostElement: this.#props.viewport.isAlwaysDrawnExclusive, includeSubModels: true })
126
+ .pipe(mergeMap((models) => merge(from(Id64.iterable(models)).pipe(mergeMap((modelId) => this.getModelWithCategoryVisibilityStatus({ modelId, categoryId })), mergeVisibilityStatuses()),
127
+ // For category not under specific model, need to check subCategories as well
128
+ this.#props.baseIdsCache
129
+ .getSubCategories({ categoryId })
130
+ .pipe(mergeMap((subCategoryIds) => this.getSubCategoriesVisibilityStatus({ categoryId, subCategoryIds })))).pipe(
131
+ // This can happen when category does not have any geometric elements or sub-categories
132
+ defaultIfEmpty(createVisibilityStatus(!this.#props.viewport.isAlwaysDrawnExclusive && this.#props.viewport.viewsCategory(categoryId) ? "visible" : "hidden")))))), mergeVisibilityStatuses());
266
133
  });
267
134
  return this.#props.overrideHandler
268
135
  ? this.#props.overrideHandler.createVisibilityHandlerResult({
@@ -273,26 +140,40 @@ export class BaseVisibilityHelper {
273
140
  : result;
274
141
  }
275
142
  /**
276
- * Gets visibility status of categories, assuming model is visible.
143
+ * Gets visibility status of a model's category.
144
+ *
145
+ * Determines visibility status by checking:
146
+ * - Elements in the viewports' always/never drawn lists;
147
+ * - Default categories visibility status in the viewport;
148
+ * - SubModels that are related to the modelId and categoryId.
149
+ */
150
+ getModelWithCategoryVisibilityStatus({ modelId, categoryId }) {
151
+ const modelVisibilityStatus = this.#props.viewport.viewsModel(modelId)
152
+ ? // For visible model need to check category and always/never drawn elements
153
+ this.getVisibilityFromAlwaysAndNeverDrawnElements({
154
+ modelId,
155
+ categoryId,
156
+ defaultStatus: this.getVisibleModelCategoryDirectVisibilityStatus({ modelId, categoryId }),
157
+ })
158
+ : of(createVisibilityStatus("hidden"));
159
+ const subModelsVisibilityStatus = this.#props.baseIdsCache
160
+ .getSubModels({ modelId, categoryId })
161
+ .pipe(mergeMap((subModels) => this.getModelsVisibilityStatus({ modelIds: subModels })));
162
+ return merge(modelVisibilityStatus, subModelsVisibilityStatus).pipe(mergeVisibilityStatuses());
163
+ }
164
+ /**
165
+ * Gets visibility status of category, assuming model is visible.
277
166
  *
278
167
  * Determines visibility status by checking:
279
168
  * - Per model category visibility overrides;
280
169
  * - Category selector visibility in the viewport.
281
170
  */
282
- getVisibleModelCategoriesDirectVisibilityStatus({ modelId, categoryIds }) {
283
- const viewport = this.#props.viewport;
284
- let visibleCount = 0;
285
- for (const categoryId of Id64.iterable(categoryIds)) {
286
- const override = this.#props.viewport.getPerModelCategoryOverride({ modelId, categoryId });
287
- if (override === "show" || (override === "none" && viewport.viewsCategory(categoryId))) {
288
- ++visibleCount;
289
- continue;
290
- }
291
- if (visibleCount > 0) {
292
- return createVisibilityStatus("partial");
293
- }
171
+ getVisibleModelCategoryDirectVisibilityStatus({ modelId, categoryId }) {
172
+ const override = this.#props.viewport.getPerModelCategoryOverride({ modelId, categoryId });
173
+ if (override === "show" || (override === "none" && this.#props.viewport.viewsCategory(categoryId))) {
174
+ return createVisibilityStatus("visible");
294
175
  }
295
- return visibleCount > 0 ? createVisibilityStatus("visible") : createVisibilityStatus("hidden");
176
+ return createVisibilityStatus("hidden");
296
177
  }
297
178
  /**
298
179
  * Gets visibility status of elements.
@@ -304,45 +185,20 @@ export class BaseVisibilityHelper {
304
185
  */
305
186
  getElementsVisibilityStatus(props) {
306
187
  const result = defer(() => {
307
- const { elementIds, modelId, categoryId, type } = props;
308
- if (this.#props.viewport.viewType === "other") {
309
- return EMPTY;
310
- }
311
- const isSupportedInView = (this.#props.viewport.viewType === "3d" && type === "GeometricElement3d") || (this.#props.viewport.viewType === "2d" && type === "GeometricElement2d");
312
- if (!isSupportedInView) {
313
- return of(createVisibilityStatus("disabled"));
314
- }
315
- // TODO: check child elements that are subModels
316
- if (!this.#props.viewport.viewsModel(modelId)) {
317
- return fromWithRelease({ source: elementIds, releaseOnCount: 100 }).pipe(mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
318
- if (isSubModel) {
319
- return this.getModelsVisibilityStatus({
320
- modelIds: elementId,
321
- type: this.#props.viewport.viewType === "2d" ? "GeometricModel2d" : "GeometricModel3d",
322
- }).pipe(map((subModelVisibilityStatus) => subModelVisibilityStatus.state !== "hidden" ? createVisibilityStatus("partial") : createVisibilityStatus("hidden")));
323
- }
324
- return of(createVisibilityStatus("hidden"));
325
- }))), mergeVisibilityStatuses);
326
- }
327
- // TODO: check child elements
328
- // TODO: check child element categories
329
- // TODO: check child elements that are subModels
330
- return this.getVisibilityFromAlwaysAndNeverDrawnElements({
331
- elements: elementIds,
332
- defaultStatus: () => this.getVisibleModelCategoriesDirectVisibilityStatus({ categoryIds: categoryId, modelId }),
333
- }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
334
- return from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
335
- if (isSubModel) {
336
- return this.getModelsVisibilityStatus({
337
- modelIds: elementId,
338
- type: this.#props.viewport.viewType === "2d" ? "GeometricModel2d" : "GeometricModel3d",
339
- }).pipe(map((subModelVisibilityStatus) => subModelVisibilityStatus.state !== visibilityStatusAlwaysAndNeverDraw.state
340
- ? createVisibilityStatus("partial")
341
- : visibilityStatusAlwaysAndNeverDraw));
342
- }
343
- return of(visibilityStatusAlwaysAndNeverDraw);
344
- }))), mergeVisibilityStatuses);
345
- }));
188
+ const { elementIds, modelId, categoryId, parentElementsIdsPath, childrenCount, categoryOfTopMostParentElement } = props;
189
+ const elementsVisibilityStatus = this.#props.viewport.viewsModel(modelId)
190
+ ? // For visible model need to check category and always/never drawn elements
191
+ this.getVisibilityFromAlwaysAndNeverDrawnElements({
192
+ elements: elementIds,
193
+ defaultStatus: this.getVisibleModelCategoryDirectVisibilityStatus({ categoryId, modelId }),
194
+ parentElementsIdsPath,
195
+ modelId,
196
+ categoryOfTopMostParentElement,
197
+ childrenCount,
198
+ })
199
+ : of(createVisibilityStatus("hidden"));
200
+ const subModelsVisibilityStatus = fromWithRelease({ source: elementIds, releaseOnCount: 100 }).pipe(mergeMap((elementId) => this.#props.baseIdsCache.getSubModelsUnderElement(elementId)), mergeMap((subModelsUnderElement) => this.getModelsVisibilityStatus({ modelIds: subModelsUnderElement })));
201
+ return merge(elementsVisibilityStatus, subModelsVisibilityStatus).pipe(mergeVisibilityStatuses());
346
202
  });
347
203
  return this.#props.overrideHandler
348
204
  ? this.#props.overrideHandler.createVisibilityHandlerResult({
@@ -353,34 +209,50 @@ export class BaseVisibilityHelper {
353
209
  : result;
354
210
  }
355
211
  /** Gets visibility status of elements based on viewport's always/never drawn elements and related categories and models. */
356
- getVisibilityFromAlwaysAndNeverDrawnElements(props) {
357
- const viewport = this.#props.viewport;
358
- if (viewport.isAlwaysDrawnExclusive) {
359
- if (!viewport?.alwaysDrawn?.size) {
360
- return of(createVisibilityStatus("hidden"));
361
- }
362
- }
363
- else if (!viewport?.neverDrawn?.size && !viewport?.alwaysDrawn?.size) {
364
- return of(props.defaultStatus());
212
+ getVisibilityFromAlwaysAndNeverDrawnElements({ modelId, ...props }) {
213
+ const defaultStatus = this.#props.viewport.isAlwaysDrawnExclusive ? createVisibilityStatus("hidden") : props.defaultStatus;
214
+ const { oppositeSet, setType } = defaultStatus.state === "visible"
215
+ ? { oppositeSet: this.#props.viewport.neverDrawn, setType: "never" }
216
+ : { oppositeSet: this.#props.viewport.alwaysDrawn, setType: "always" };
217
+ if (!oppositeSet?.size) {
218
+ return of(defaultStatus);
365
219
  }
366
220
  if ("elements" in props) {
367
- return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
368
- ...props,
369
- alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(Id64.iterable(props.elements), viewport.alwaysDrawn) : undefined,
370
- neverDrawn: viewport.neverDrawn?.size ? setIntersection(Id64.iterable(props.elements), viewport.neverDrawn) : undefined,
371
- totalCount: Id64.sizeOf(props.elements),
372
- viewport,
373
- }));
221
+ const { childrenCount } = props;
222
+ // When elements children count is 0 or undefined, no need to query for child always/never drawn elements.
223
+ if (!childrenCount) {
224
+ return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
225
+ defaultStatus,
226
+ numberOfElementsInOppositeSet: countInSet(props.elements, oppositeSet),
227
+ totalCount: Id64.sizeOf(props.elements),
228
+ }));
229
+ }
230
+ const parentElementIdsPath = [...props.parentElementsIdsPath, props.elements];
231
+ // Get child always/never drawn elements.
232
+ return this.#alwaysAndNeverDrawnElements
233
+ .getAlwaysOrNeverDrawnElements({
234
+ modelId,
235
+ categoryIds: props.categoryOfTopMostParentElement,
236
+ parentElementIdsPath,
237
+ setType,
238
+ })
239
+ .pipe(map((childElementsInOppositeSet) =>
240
+ // Combine child always/never drawn count with the props.elements count in always/never drawn sets.
241
+ getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
242
+ defaultStatus,
243
+ numberOfElementsInOppositeSet: countInSet(props.elements, oppositeSet) + childElementsInOppositeSet.size,
244
+ totalCount: childrenCount + Id64.sizeOf(props.elements),
245
+ })));
374
246
  }
375
- const { modelId, categoryIds } = props.queryProps;
376
- return fromWithRelease({ source: categoryIds, releaseOnCount: 100 }).pipe(mergeMap((categoryId) => {
377
- return forkJoin({
378
- categoryId: of(categoryId),
379
- totalCount: this.#props.baseIdsCache.getElementsCount({ modelId, categoryId }),
380
- alwaysDrawn: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
381
- neverDrawn: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
382
- });
383
- }),
247
+ const { categoryId } = props;
248
+ return forkJoin({
249
+ totalCount: this.#props.baseIdsCache.getElementsCount({ modelId, categoryId }),
250
+ relatedElementsInOppositeSet: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({
251
+ modelId,
252
+ categoryIds: categoryId,
253
+ setType,
254
+ }),
255
+ }).pipe(
384
256
  // There is a known bug:
385
257
  // Categories that don't have root elements will make visibility result incorrect
386
258
  // E.g.:
@@ -389,17 +261,11 @@ export class BaseVisibilityHelper {
389
261
  // - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
390
262
  // Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
391
263
  // TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
392
- mergeMap((state) => {
393
- if (this.#props.viewport.isAlwaysDrawnExclusive && state.totalCount === 0) {
394
- return EMPTY;
395
- }
396
- return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
397
- ...props,
398
- ...state,
399
- viewport,
400
- defaultStatus: () => props.defaultStatus(state.categoryId),
401
- }));
402
- }), defaultIfEmpty(createVisibilityStatus("hidden")), mergeVisibilityStatuses);
264
+ map((state) => getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
265
+ defaultStatus,
266
+ totalCount: state.totalCount,
267
+ numberOfElementsInOppositeSet: state.relatedElementsInOppositeSet.size,
268
+ })));
403
269
  }
404
270
  /**
405
271
  * Changes visibility status of models.
@@ -412,18 +278,13 @@ export class BaseVisibilityHelper {
412
278
  if (Id64.sizeOf(modelIds) === 0) {
413
279
  return EMPTY;
414
280
  }
415
- const viewport = this.#props.viewport;
416
- viewport.clearPerModelCategoryOverrides({ modelIds });
281
+ this.#props.viewport.clearPerModelCategoryOverrides({ modelIds });
417
282
  if (!on) {
418
- viewport.changeModelDisplay({ modelIds, display: false });
419
- return this.#props.baseIdsCache
420
- .getSubModels({ modelIds })
421
- .pipe(mergeMap(({ subModels }) => (subModels ? this.changeModelsVisibilityStatus({ modelIds: subModels, on }) : EMPTY)));
283
+ this.#props.viewport.changeModelDisplay({ modelIds, display: false });
284
+ return from(Id64.iterable(modelIds)).pipe(mergeMap((modelId) => this.#props.baseIdsCache.getSubModels({ modelId })), mergeMap((subModels) => this.changeModelsVisibilityStatus({ modelIds: subModels, on })));
422
285
  }
423
- viewport.changeModelDisplay({ modelIds, display: true });
424
- return this.#props.baseIdsCache.getCategories({ modelIds }).pipe(mergeMap(({ id, drawingCategories, spatialCategories }) => {
425
- return merge(drawingCategories ? this.changeCategoriesVisibilityStatus({ categoryIds: drawingCategories, modelId: id, on }) : EMPTY, spatialCategories ? this.changeCategoriesVisibilityStatus({ categoryIds: spatialCategories, modelId: id, on }) : EMPTY);
426
- }));
286
+ this.#props.viewport.changeModelDisplay({ modelIds, display: true });
287
+ return from(Id64.iterable(modelIds)).pipe(mergeMap((modelId) => forkJoin({ categoryIds: this.#props.baseIdsCache.getCategories({ modelId }), modelId: of(modelId) })), mergeMap(({ categoryIds, modelId }) => this.changeCategoriesVisibilityStatus({ categoryIds, modelId, on })));
427
288
  });
428
289
  return this.#props.overrideHandler
429
290
  ? this.#props.overrideHandler.createVisibilityHandlerResult({
@@ -435,99 +296,79 @@ export class BaseVisibilityHelper {
435
296
  }
436
297
  /** Turns model on and turns off elements with categories related to that model. */
437
298
  showModelWithoutAnyCategoriesOrElements(modelId, categoriesToNotOverride) {
438
- const viewport = this.#props.viewport;
439
299
  return forkJoin({
440
- allModelCategories: this.#props.baseIdsCache.getCategories({ modelIds: modelId }).pipe(reduce((acc, { drawingCategories, spatialCategories }) => {
441
- for (const category of Id64.iterable(drawingCategories ?? [])) {
442
- acc.add(category);
443
- }
444
- for (const category of Id64.iterable(spatialCategories ?? [])) {
445
- acc.add(category);
446
- }
447
- return acc;
448
- }, new Set())),
449
- modelAlwaysDrawnElements: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
300
+ allModelCategories: this.#props.baseIdsCache.getCategories({ modelId }),
301
+ modelAlwaysDrawnElements: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelId, setType: "always" }),
450
302
  }).pipe(mergeMap(({ allModelCategories, modelAlwaysDrawnElements }) => {
451
303
  const alwaysDrawn = this.#props.viewport.alwaysDrawn;
452
304
  if (alwaysDrawn && modelAlwaysDrawnElements) {
453
- viewport.setAlwaysDrawn({ elementIds: setDifference(alwaysDrawn, modelAlwaysDrawnElements) });
305
+ this.#props.viewport.setAlwaysDrawn({ elementIds: setDifference(alwaysDrawn, modelAlwaysDrawnElements) });
454
306
  }
455
- viewport.changeModelDisplay({ modelIds: modelId, display: true });
456
- return from(Id64.iterable(allModelCategories)).pipe(categoriesToNotOverride ? filter((modelCategory) => !Id64.has(categoriesToNotOverride, modelCategory)) : identity, map((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false)), takeLast(1), defaultIfEmpty(undefined));
307
+ this.#props.viewport.changeModelDisplay({ modelIds: modelId, display: true });
308
+ return from(Id64.iterable(allModelCategories)).pipe(categoriesToNotOverride ? filter((modelCategory) => !categoriesToNotOverride.has(modelCategory)) : identity, map((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false)), takeLast(1), defaultIfEmpty(undefined));
457
309
  }));
458
310
  }
459
311
  /** Adds per-model category overrides based on category visibility in category selector. */
460
312
  changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on, changeSubCategories) {
461
- const viewport = this.#props.viewport;
462
- const isDisplayedInSelector = viewport.viewsCategory(categoryId);
313
+ const isDisplayedInSelector = this.#props.viewport.viewsCategory(categoryId);
463
314
  const override = on === isDisplayedInSelector ? "none" : on ? "show" : "hide";
464
- viewport.setPerModelCategoryOverride({ modelIds: modelId, categoryIds: categoryId, override });
315
+ this.#props.viewport.setPerModelCategoryOverride({ modelIds: modelId, categoryIds: categoryId, override });
465
316
  if (override === "none" && on) {
466
317
  // we took off the override which means the category is displayed in selector, but
467
318
  // doesn't mean all its subcategories are displayed - this call ensures that
468
- viewport.changeCategoryDisplay({ categoryIds: categoryId, display: true, enableAllSubCategories: changeSubCategories });
319
+ this.#props.viewport.changeCategoryDisplay({ categoryIds: categoryId, display: true, enableAllSubCategories: changeSubCategories });
469
320
  }
470
321
  }
471
322
  /**
472
323
  * Changes categories visibility status.
473
324
  *
474
- * Also:
475
- * - Turns on models in cases where categories need to be turned on and models are not already on.
476
- * - Removed related elements from always/never drawn elements.
477
- * - changes visibility of sub-models that are related to the specified categories.
325
+ * - Changes category selector for specified categories
326
+ * - Removes per-model category overrides
327
+ * - Clears always and never drawn elements related to those categories
328
+ * - Changes sub-models visibility status that are related to specified categories.
329
+ * - If `on` is set to true:
330
+ * - Turns on models of those categories without affecting any visibilities
331
+ * - Turns on sub-categories visibility status of specified categories.
478
332
  */
479
333
  changeCategoriesVisibilityStatus(props) {
480
334
  const result = defer(() => {
481
- const { modelId: modelIdFromProps, categoryIds, on } = props;
482
- const viewport = this.#props.viewport;
483
- const modelIdsObservable = (modelIdFromProps
484
- ? of(new Map([[modelIdFromProps, getSetFromId64Arg(categoryIds)]]))
485
- : this.#props.baseIdsCache.getModels({ categoryIds }).pipe(reduce((acc, { id, models }) => {
486
- if (!models) {
487
- return acc;
488
- }
489
- for (const modelId of Id64.iterable(models)) {
490
- let entry = acc.get(modelId);
491
- if (!entry) {
492
- entry = new Set();
493
- acc.set(modelId, entry);
494
- }
495
- entry.add(id);
335
+ const { categoryIds, on } = props;
336
+ if (Id64.sizeOf(categoryIds) === 0) {
337
+ return EMPTY;
338
+ }
339
+ if (props.modelId) {
340
+ return this.changeCategoriesUnderModelVisibilityStatus({ categoryIds, modelId: props.modelId, on });
341
+ }
342
+ const changeCategoriesObs = fromWithRelease({ source: categoryIds, releaseOnCount: 500 }).pipe(bufferCount(getOptimalBatchSize({ totalSize: Id64.sizeOf(categoryIds), maximumBatchSize: 500 })), map((categoryIdsBatch) => this.#props.viewport.changeCategoryDisplay({ categoryIds: categoryIdsBatch, display: on, enableAllSubCategories: false })));
343
+ const categoryModelsObs = from(Id64.iterable(categoryIds)).pipe(mergeMap((categoryId) => forkJoin({ categoryId: of(categoryId), models: this.#props.baseIdsCache.getModels({ categoryId, includeSubModels: true }) })), reduce((acc, { models, categoryId }) => {
344
+ for (const modelId of Id64.iterable(models)) {
345
+ let entry = acc.get(modelId);
346
+ if (!entry) {
347
+ entry = new Set();
348
+ acc.set(modelId, entry);
496
349
  }
497
- return acc;
498
- }, new Map()))).pipe(mergeMap((modelCategoriesMap) => modelCategoriesMap.entries()), shareReplay());
499
- return concat(
500
- // If modelId was provided: add override
501
- // If modelId was not provided: change categoryDisplay and remove categories per model overrides
502
- modelIdFromProps
503
- ? of(viewport.setPerModelCategoryOverride({
504
- modelIds: modelIdFromProps,
505
- categoryIds,
506
- override: on ? "show" : "hide",
507
- }))
508
- : merge(
509
- // In case of turning categories on, need to change sub-categories separately as enableCategoryDisplay
510
- // takes a long time to get sub-categories for each category
511
- on
512
- ? fromWithRelease({ source: categoryIds, releaseOnCount: 200 }).pipe(mergeMap((categoryId) => this.#props.baseIdsCache.getSubCategories({ categoryId })), mergeAll(), releaseMainThreadOnItemsCount(200), map((subCategoryId) => {
513
- if (!this.#props.viewport.viewsSubCategory(subCategoryId)) {
514
- this.#props.viewport.changeSubCategoryDisplay({ subCategoryId, display: true });
515
- }
516
- }))
517
- : EMPTY, from(enableCategoryDisplay(viewport, categoryIds, on, false)), modelIdsObservable.pipe(map(([modelId, modelCategories]) => {
518
- viewport.setPerModelCategoryOverride({ modelIds: modelId, categoryIds: modelCategories, override: "none" });
519
- }))),
520
- // If categories visibility needs to be turned on, we need to turn on models without turning on unrelated elements or categories for that model
521
- on
522
- ? modelIdsObservable.pipe(mergeMap(([modelId, categories]) => {
523
- if (!viewport.viewsModel(modelId)) {
524
- return this.showModelWithoutAnyCategoriesOrElements(modelId, categories);
350
+ entry.add(categoryId);
351
+ }
352
+ return acc;
353
+ }, new Map()), mergeMap((modelCategoriesMap) => modelCategoriesMap.entries()), shareReplay());
354
+ const changeSubModelsObs = categoryModelsObs.pipe(mergeMap(([modelId, modelCategories]) => from(modelCategories).pipe(mergeMap((modelCategoryId) => this.#props.baseIdsCache.getSubModels({ categoryId: modelCategoryId, modelId })))), mergeMap((subModels) => this.changeModelsVisibilityStatus({ modelIds: subModels, on })));
355
+ const changeModelsObs = on
356
+ ? categoryModelsObs.pipe(mergeMap(([modelId, modelCategories]) => this.#props.viewport.viewsModel(modelId) ? EMPTY : this.showModelWithoutAnyCategoriesOrElements(modelId, modelCategories)))
357
+ : EMPTY;
358
+ const removeCategoriesOverridesObs = categoryModelsObs.pipe(map(([modelId, modelCategories]) => this.#props.viewport.setPerModelCategoryOverride({
359
+ modelIds: modelId,
360
+ categoryIds: modelCategories,
361
+ override: "none",
362
+ })));
363
+ const changeAlwaysAndNeverDrawnElementsObs = categoryModelsObs.pipe(mergeMap(([modelId, modelCategories]) => this.#alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ categoryIds: modelCategories, modelId })));
364
+ const changeSubCategoriesObs = on
365
+ ? fromWithRelease({ source: categoryIds, releaseOnCount: 200 }).pipe(mergeMap((categoryId) => this.#props.baseIdsCache.getSubCategories({ categoryId })), mergeAll(), releaseMainThreadOnItemsCount(200), map((subCategoryId) => {
366
+ if (!this.#props.viewport.viewsSubCategory(subCategoryId)) {
367
+ this.#props.viewport.changeSubCategoryDisplay({ subCategoryId, display: true });
525
368
  }
526
- return EMPTY;
527
369
  }))
528
- : EMPTY, this.#alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ categoryIds, modelId: modelIdFromProps }), this.#props.baseIdsCache
529
- .getSubModels({ categoryIds, modelId: modelIdFromProps })
530
- .pipe(mergeMap(({ subModels }) => (subModels ? this.changeModelsVisibilityStatus({ modelIds: subModels, on }) : EMPTY))));
370
+ : EMPTY;
371
+ return merge(changeCategoriesObs, changeSubModelsObs, changeModelsObs, removeCategoriesOverridesObs, changeAlwaysAndNeverDrawnElementsObs, changeSubCategoriesObs);
531
372
  });
532
373
  return this.#props.overrideHandler
533
374
  ? this.#props.overrideHandler.createVisibilityHandlerResult({
@@ -537,6 +378,25 @@ export class BaseVisibilityHelper {
537
378
  })
538
379
  : result;
539
380
  }
381
+ /**
382
+ * Changes categories under specific model visibility status.
383
+ *
384
+ * - Turns on model without affecting it's elements or categories
385
+ * - sets per-model category overrides for specified categories.
386
+ * - Clears always and never drawn elements related to those categories
387
+ * - Changes sub-models visibility status that are related to specified categories in the model.
388
+ */
389
+ changeCategoriesUnderModelVisibilityStatus({ modelId, categoryIds, on, }) {
390
+ const changeModelsVisibilityStatusObs = on && !this.#props.viewport.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId, Id64.toIdSet(categoryIds)) : EMPTY;
391
+ const changeCategoriesVisibilityStatusObs = of(this.#props.viewport.setPerModelCategoryOverride({
392
+ modelIds: modelId,
393
+ categoryIds,
394
+ override: on ? "show" : "hide",
395
+ }));
396
+ const changeAlwaysAndNeverDrawnElementsObs = this.#alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ categoryIds, modelId });
397
+ const changeSubModelsObs = fromWithRelease({ source: categoryIds, releaseOnCount: 200 }).pipe(mergeMap((categoryId) => this.#props.baseIdsCache.getSubModels({ categoryId, modelId })), mergeMap((subModels) => this.changeModelsVisibilityStatus({ modelIds: subModels, on })));
398
+ return merge(changeModelsVisibilityStatusObs, changeCategoriesVisibilityStatusObs, changeAlwaysAndNeverDrawnElementsObs, changeSubModelsObs);
399
+ }
540
400
  /**
541
401
  * Changes visibility status of elements by adding them to the viewport's always/never drawn elements.
542
402
  *
@@ -544,35 +404,43 @@ export class BaseVisibilityHelper {
544
404
  */
545
405
  changeElementsVisibilityStatus(props) {
546
406
  const result = defer(() => {
547
- const { modelId, categoryId, elementIds, on } = props;
407
+ const { modelId, categoryId, elementIds, on, children } = props;
548
408
  const viewport = this.#props.viewport;
549
- // TODO: change child elements
550
- // TODO: change child element categories
551
- // TODO: change child subModels
409
+ // TODO: determine which child elements to change based on their categories https://github.com/iTwin/viewer-components-react/issues/1561
552
410
  return concat(
553
411
  // Change elements state
554
412
  defer(() => {
413
+ const elementsToChange = children ? [...elementIds, ...(typeof children === "string" ? [children] : children)] : elementIds;
414
+ const isDisplayedByDefault = (isCategoryVisible) =>
415
+ // When category is visible and elements need to be turned off, or when category is hidden and elements need to be turned on,
416
+ // We can set isDisplayedByDefault to isCategoryVisible. This allows to not check if each element is in the elementIds list or not.
417
+ isCategoryVisible === !on
418
+ ? () => isCategoryVisible
419
+ : (elementId) => {
420
+ if (Id64.has(elementIds, elementId)) {
421
+ return isCategoryVisible;
422
+ }
423
+ return !on;
424
+ };
555
425
  if (!viewport.viewsModel(modelId)) {
556
426
  if (!on) {
557
- return this.queueElementsVisibilityChange(elementIds, on, false);
427
+ return this.queueElementsVisibilityChange(elementsToChange, on, () => false);
558
428
  }
559
429
  return this.showModelWithoutAnyCategoriesOrElements(modelId).pipe(mergeMap(() => {
560
- const defaultVisibility = this.getVisibleModelCategoriesDirectVisibilityStatus({
561
- categoryIds: categoryId,
430
+ const defaultVisibility = this.getVisibleModelCategoryDirectVisibilityStatus({
431
+ categoryId,
562
432
  modelId,
563
433
  });
564
- const displayedByDefault = defaultVisibility.state === "visible";
565
- return this.queueElementsVisibilityChange(elementIds, on, displayedByDefault);
434
+ return this.queueElementsVisibilityChange(elementsToChange, on, isDisplayedByDefault(defaultVisibility.state === "visible"));
566
435
  }));
567
436
  }
568
- const categoryVisibility = this.getVisibleModelCategoriesDirectVisibilityStatus({ categoryIds: categoryId, modelId });
569
- const isDisplayedByDefault = categoryVisibility.state === "visible";
570
- return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
437
+ const categoryVisibility = this.getVisibleModelCategoryDirectVisibilityStatus({ categoryId, modelId });
438
+ return this.queueElementsVisibilityChange(elementsToChange, on, isDisplayedByDefault(categoryVisibility.state === "visible"));
571
439
  }),
572
440
  // Change visibility of elements that are models
573
- fromWithRelease({ source: elementIds, releaseOnCount: 100 }).pipe(mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
574
- if (isSubModel) {
575
- return this.changeModelsVisibilityStatus({ modelIds: elementId, on });
441
+ fromWithRelease({ source: elementIds, releaseOnCount: 100 }).pipe(mergeMap((elementId) => this.#props.baseIdsCache.getSubModelsUnderElement(elementId).pipe(mergeMap((subModelsUnderElement) => {
442
+ if (subModelsUnderElement.length > 0) {
443
+ return this.changeModelsVisibilityStatus({ modelIds: subModelsUnderElement, on });
576
444
  }
577
445
  return EMPTY;
578
446
  })))));