@itwin/tree-widget-react 4.0.0-alpha.6 → 4.0.0-alpha.8

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 (206) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +2 -1
  3. package/lib/esm/tree-widget-react/TreeWidget.d.ts +6 -1
  4. package/lib/esm/tree-widget-react/TreeWidget.js +19 -2
  5. package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
  6. package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.d.ts +6 -0
  7. package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.js +22 -23
  8. package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.js.map +1 -1
  9. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  10. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  11. package/lib/esm/tree-widget-react/components/tree-header/ErrorState.js +1 -1
  12. package/lib/esm/tree-widget-react/components/tree-header/ErrorState.js.map +1 -1
  13. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.d.ts +1 -1
  14. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js +4 -4
  15. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js.map +1 -1
  16. package/lib/esm/tree-widget-react/components/tree-header/SelectableTree.css +2 -0
  17. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.css +1 -0
  18. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.d.ts +12 -4
  19. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js +13 -9
  20. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js.map +1 -1
  21. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  22. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -2
  23. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  24. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +9 -2
  25. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +53 -7
  26. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  27. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  28. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +1 -1
  29. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  30. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +17 -3
  31. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +561 -161
  32. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  33. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +6 -2
  34. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +46 -117
  35. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  36. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +30 -15
  37. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +188 -38
  38. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  39. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.d.ts +18 -3
  40. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js +30 -3
  41. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js.map +1 -1
  42. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.d.ts +24 -0
  43. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js +701 -0
  44. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js.map +1 -0
  45. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.d.ts +39 -0
  46. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js +221 -0
  47. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js.map +1 -0
  48. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.d.ts +25 -0
  49. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js +133 -0
  50. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js.map +1 -0
  51. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.d.ts +8 -0
  52. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js +48 -0
  53. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js.map +1 -0
  54. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +5 -17
  55. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +5 -62
  56. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  57. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.d.ts +2 -2
  58. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +11 -5
  59. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  60. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.d.ts +1 -0
  61. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js +13 -11
  62. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js.map +1 -1
  63. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.d.ts +1 -0
  64. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js +2 -1
  65. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js.map +1 -1
  66. package/lib/esm/tree-widget-react/components/trees/common/Utils.d.ts +38 -23
  67. package/lib/esm/tree-widget-react/components/trees/common/Utils.js +65 -47
  68. package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
  69. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.d.ts +1 -1
  70. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js +4 -4
  71. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js.map +1 -1
  72. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.d.ts +1 -0
  73. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js +1 -0
  74. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js.map +1 -1
  75. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.d.ts +1 -0
  76. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js +1 -0
  77. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.css +2 -1
  79. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +3 -3
  80. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +15 -6
  81. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.d.ts +6 -4
  83. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js +20 -25
  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.d.ts +1 -1
  86. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +10 -4
  87. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  88. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +1 -0
  89. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js +7 -3
  90. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
  91. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js +1 -1
  92. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  93. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  94. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js +12 -11
  95. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.d.ts +44 -0
  97. package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/AlwaysAndNeverDrawnElementInfo.js +81 -31
  98. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -0
  99. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.d.ts +33 -0
  100. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js +37 -0
  101. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js.map +1 -0
  102. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.d.ts +16 -0
  103. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js +72 -0
  104. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +1 -0
  105. package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.d.ts → internal/Rxjs.d.ts} +9 -2
  106. package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.js → internal/Rxjs.js} +9 -2
  107. package/lib/esm/tree-widget-react/components/trees/common/internal/Rxjs.js.map +1 -0
  108. package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.d.ts → internal/Tooltip.d.ts} +4 -8
  109. package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.js → internal/Tooltip.js} +4 -10
  110. package/lib/esm/tree-widget-react/components/trees/common/internal/Tooltip.js.map +1 -0
  111. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +14 -0
  112. package/lib/esm/tree-widget-react/components/{tree-header/SearchBox.css → trees/common/internal/Types.js} +2 -4
  113. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -0
  114. package/lib/esm/tree-widget-react/components/trees/common/internal/UseActiveViewport.js.map +1 -0
  115. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.d.ts → internal/UseHierarchiesLocalization.d.ts} +1 -0
  116. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.js → internal/UseHierarchiesLocalization.js} +6 -2
  117. package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchiesLocalization.js.map +1 -0
  118. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.d.ts → internal/UseHierarchyFiltering.d.ts} +1 -0
  119. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.js → internal/UseHierarchyFiltering.js} +4 -3
  120. package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchyFiltering.js.map +1 -0
  121. package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.d.ts → internal/UseIModelChangeListener.d.ts} +1 -0
  122. package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.js → internal/UseIModelChangeListener.js} +1 -0
  123. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelChangeListener.js.map +1 -0
  124. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +47 -0
  125. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +101 -0
  126. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  127. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.d.ts +20 -0
  128. package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/VisibilityChangeEventListener.js +17 -9
  129. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.js.map +1 -0
  130. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +63 -0
  131. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +210 -0
  132. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -0
  133. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
  134. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +8 -8
  135. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  136. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.d.ts +1 -1
  137. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
  138. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +1 -0
  139. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +1 -0
  140. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  141. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +4 -2
  142. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +22 -18
  143. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  144. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +1 -1
  145. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js +1 -1
  146. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
  147. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +13 -0
  148. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +39 -38
  149. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  150. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +5 -5
  151. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +25 -24
  152. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  153. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +2 -2
  154. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +2 -2
  155. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  156. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +15 -11
  157. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  158. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -1
  159. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +1 -1
  160. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  161. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +7 -2
  162. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +73 -70
  163. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  164. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +36 -202
  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/FilteredTree.d.ts +7 -9
  167. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +4 -6
  168. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  169. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +4 -5
  170. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +54 -104
  171. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  172. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +0 -26
  173. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +80 -359
  174. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  175. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +27 -0
  176. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +170 -0
  177. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -0
  178. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.d.ts +8 -0
  179. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.js +47 -0
  180. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.js.map +1 -0
  181. package/lib/public/locales/en/TreeWidget.json +13 -59
  182. package/package.json +19 -20
  183. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +0 -37
  184. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +0 -214
  185. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +0 -1
  186. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.d.ts +0 -7
  187. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js +0 -11
  188. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js.map +0 -1
  189. package/lib/esm/tree-widget-react/components/trees/common/Rxjs.js.map +0 -1
  190. package/lib/esm/tree-widget-react/components/trees/common/Tooltip.js.map +0 -1
  191. package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +0 -1
  192. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.d.ts +0 -11
  193. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js +0 -24
  194. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js.map +0 -1
  195. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchiesLocalization.js.map +0 -1
  196. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyFiltering.js.map +0 -1
  197. package/lib/esm/tree-widget-react/components/trees/common/UseIModelChangeListener.js.map +0 -1
  198. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +0 -7
  199. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +0 -21
  200. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +0 -1
  201. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +0 -29
  202. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
  203. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.d.ts +0 -12
  204. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.js.map +0 -1
  205. /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.d.ts → internal/UseActiveViewport.d.ts} +0 -0
  206. /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.js → internal/UseActiveViewport.js} +0 -0
@@ -2,21 +2,23 @@
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 { defer, EMPTY, from, lastValueFrom, map, mergeMap, toArray } from "rxjs";
6
- import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition } from "@itwin/presentation-hierarchies";
5
+ import { bufferCount, defer, firstValueFrom, from, lastValueFrom, map, merge, mergeMap, of, reduce, toArray } from "rxjs";
6
+ import { assert } from "@itwin/core-bentley";
7
+ import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition, ProcessedHierarchyNode } from "@itwin/presentation-hierarchies";
7
8
  import { createBisInstanceLabelSelectClauseFactory, ECSql } from "@itwin/presentation-shared";
9
+ import { DEFINITION_CONTAINER_CLASS_NAME, INFORMATION_PARTITION_ELEMENT_CLASS_NAME, MODEL_CLASS_NAME, SUB_CATEGORY_CLASS_NAME, SUB_MODELED_ELEMENT_CLASS_NAME, } from "../common/internal/ClassNameDefinitions.js";
10
+ import { createIdsSelector, getClassesByView, getDistinctMapValues, parseIdsSelectorResult, releaseMainThreadOnItemsCount } from "../common/internal/Utils.js";
8
11
  import { FilterLimitExceededError } from "../common/TreeErrors.js";
9
- import { getClassesByView } from "./internal/CategoriesTreeIdsCache.js";
10
- import { DEFINITION_CONTAINER_CLASS, DEFINITION_ELEMENT_CLASS, SUB_CATEGORY_CLASS } from "./internal/ClassNameDefinitions.js";
11
12
  const MAX_FILTERING_INSTANCE_KEY_COUNT = 100;
12
13
  /** @internal */
13
14
  export const defaultHierarchyConfiguration = {
14
15
  hideSubCategories: false,
16
+ showElements: false,
15
17
  };
18
+ /** @internal */
16
19
  export class CategoriesTreeDefinition {
17
20
  constructor(props) {
18
21
  this._iModelAccess = props.imodelAccess;
19
- this._viewType = props.viewType;
20
22
  this._idsCache = props.idsCache;
21
23
  this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
22
24
  this._selectQueryFactory = createNodesQueryClauseFactory({
@@ -24,6 +26,40 @@ export class CategoriesTreeDefinition {
24
26
  instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,
25
27
  });
26
28
  this._hierarchyConfig = props.hierarchyConfig;
29
+ const { categoryClass, elementClass, modelClass } = getClassesByView(props.viewType);
30
+ this._categoryClass = categoryClass;
31
+ this._categoryElementClass = elementClass;
32
+ this._categoryModelClass = modelClass;
33
+ }
34
+ async postProcessNode(node) {
35
+ if (ProcessedHierarchyNode.isGroupingNode(node)) {
36
+ const modelElementsMap = new Map();
37
+ node.children.forEach((child) => {
38
+ let modelEntry = modelElementsMap.get(child.extendedData?.modelId);
39
+ if (!modelEntry) {
40
+ modelEntry = new Set();
41
+ modelElementsMap.set(child.extendedData?.modelId, modelEntry);
42
+ }
43
+ assert(child.key.type === "instances");
44
+ for (const { id } of child.key.instanceKeys) {
45
+ modelEntry.add(id);
46
+ }
47
+ });
48
+ return {
49
+ ...node,
50
+ label: node.label,
51
+ extendedData: {
52
+ ...node.extendedData,
53
+ // add `categoryId` from the first grouped element
54
+ categoryId: node.children[0].extendedData?.categoryId,
55
+ modelElementsMap,
56
+ // `imageId` is assigned to instance nodes at query time, but grouping ones need to
57
+ // be handled during post-processing
58
+ imageId: "icon-ec-class",
59
+ },
60
+ };
61
+ }
62
+ return node;
27
63
  }
28
64
  async getHierarchyDefinition() {
29
65
  this._impl ??= (async () => {
@@ -31,24 +67,37 @@ export class CategoriesTreeDefinition {
31
67
  return createPredicateBasedHierarchyDefinition({
32
68
  classHierarchyInspector: this._iModelAccess,
33
69
  hierarchy: {
34
- rootNodes: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery({ ...requestProps, viewType: this._viewType }),
70
+ rootNodes: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(requestProps),
35
71
  childNodes: [
36
- ...(this._hierarchyConfig.hideSubCategories
72
+ ...(this._hierarchyConfig.showElements
73
+ ? [
74
+ {
75
+ parentInstancesNodePredicate: this._categoryElementClass,
76
+ definitions: async (requestProps) => this.createElementChildrenQuery(requestProps),
77
+ },
78
+ {
79
+ parentInstancesNodePredicate: SUB_MODELED_ELEMENT_CLASS_NAME,
80
+ definitions: async (requestProps) => this.createISubModeledElementChildrenQuery(requestProps),
81
+ },
82
+ {
83
+ parentInstancesNodePredicate: this._categoryModelClass,
84
+ definitions: async (requestProps) => this.createGeometricModel3dChildrenQuery(requestProps),
85
+ },
86
+ ]
87
+ : []),
88
+ ...(this._hierarchyConfig.hideSubCategories && !this._hierarchyConfig.showElements
37
89
  ? []
38
90
  : [
39
91
  {
40
- parentInstancesNodePredicate: "BisCore.Category",
41
- definitions: async (requestProps) => this.createSubcategoryQuery(requestProps),
92
+ parentInstancesNodePredicate: this._categoryClass,
93
+ definitions: async (requestProps) => this.createCategoryChildrenQuery(requestProps),
42
94
  },
43
95
  ]),
44
96
  ...(isDefinitionContainerSupported
45
97
  ? [
46
98
  {
47
- parentInstancesNodePredicate: DEFINITION_CONTAINER_CLASS,
48
- definitions: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery({
49
- ...requestProps,
50
- viewType: this._viewType,
51
- }),
99
+ parentInstancesNodePredicate: DEFINITION_CONTAINER_CLASS_NAME,
100
+ definitions: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(requestProps),
52
101
  },
53
102
  ]
54
103
  : []),
@@ -61,118 +110,215 @@ export class CategoriesTreeDefinition {
61
110
  async defineHierarchyLevel(props) {
62
111
  return (await this.getHierarchyDefinition()).defineHierarchyLevel(props);
63
112
  }
113
+ async createISubModeledElementChildrenQuery({ parentNodeInstanceIds: elementIds, }) {
114
+ // note: we do not apply hierarchy level filtering on this hierarchy level, because it's always
115
+ // hidden - the filter will get applied on the child hierarchy levels
116
+ return [
117
+ {
118
+ fullClassName: this._categoryModelClass,
119
+ query: {
120
+ ecsql: `
121
+ SELECT
122
+ ${await this._selectQueryFactory.createSelectClause({
123
+ ecClassId: { selector: "this.ECClassId" },
124
+ ecInstanceId: { selector: "this.ECInstanceId" },
125
+ nodeLabel: "",
126
+ hideNodeInHierarchy: true,
127
+ hasChildren: true,
128
+ extendedData: {
129
+ isModel: true,
130
+ },
131
+ })}
132
+ FROM ${this._categoryModelClass} this
133
+ WHERE
134
+ this.ModeledElement.Id IN (${elementIds.map(() => "?").join(",")})
135
+ AND NOT this.IsPrivate
136
+ AND this.ECInstanceId IN (SELECT Model.Id FROM ${this._categoryElementClass})
137
+ `,
138
+ bindings: [...elementIds.map((id) => ({ type: "id", value: id }))],
139
+ },
140
+ },
141
+ ];
142
+ }
143
+ async createGeometricModel3dChildrenQuery({ parentNodeInstanceIds: modelIds, instanceFilter, }) {
144
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
145
+ filter: instanceFilter,
146
+ contentClass: { fullName: this._categoryClass, alias: "this" },
147
+ });
148
+ return [
149
+ {
150
+ fullClassName: this._categoryClass,
151
+ query: {
152
+ ecsql: `
153
+ SELECT
154
+ ${await this._selectQueryFactory.createSelectClause({
155
+ ecClassId: { selector: "this.ECClassId" },
156
+ ecInstanceId: { selector: "this.ECInstanceId" },
157
+ nodeLabel: {
158
+ selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
159
+ classAlias: "this",
160
+ className: this._categoryClass,
161
+ }),
162
+ },
163
+ grouping: { byLabel: { action: "merge", groupId: "category" } },
164
+ hasChildren: true,
165
+ extendedData: {
166
+ imageId: "icon-layers",
167
+ isCategory: true,
168
+ modelIds: { selector: createIdsSelector(modelIds) },
169
+ isCategoryOfSubModel: true,
170
+ },
171
+ supportsFiltering: true,
172
+ })}
173
+ FROM ${instanceFilterClauses.from} this
174
+ ${instanceFilterClauses.joins}
175
+ WHERE
176
+ EXISTS (
177
+ SELECT 1
178
+ FROM ${this._categoryElementClass} element
179
+ WHERE
180
+ element.Model.Id IN (${modelIds.join(",")})
181
+ AND element.Category.Id = +this.ECInstanceId
182
+ AND element.Parent.Id IS NULL
183
+ )
184
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
185
+ `,
186
+ },
187
+ },
188
+ ];
189
+ }
64
190
  async createDefinitionContainersAndCategoriesQuery(props) {
65
- const { parentNodeInstanceIds, instanceFilter, viewType } = props;
191
+ const { parentNodeInstanceIds, instanceFilter } = props;
66
192
  const { definitionContainers, categories } = parentNodeInstanceIds === undefined
67
193
  ? await this._idsCache.getRootDefinitionContainersAndCategories()
68
194
  : await this._idsCache.getDirectChildDefinitionContainersAndCategories(parentNodeInstanceIds);
69
- if (categories.length === 0 && definitionContainers.length === 0) {
70
- return [];
195
+ const hierarchyDefinition = new Array();
196
+ if (categories.length > 0) {
197
+ hierarchyDefinition.push(...(await this.createCategoriesQuery({ categories, instanceFilter })));
71
198
  }
72
- const categoriesWithSingleChild = new Array();
73
- const categoriesWithMultipleChildren = new Array();
74
- categories.forEach((category) => {
75
- if (category.childCount > 1) {
76
- categoriesWithMultipleChildren.push(category.id);
77
- }
78
- else {
79
- categoriesWithSingleChild.push(category.id);
80
- }
81
- });
82
- const dataToDetermineHasChildren = categoriesWithSingleChild.length > categoriesWithMultipleChildren.length
83
- ? { ids: categoriesWithMultipleChildren, ifTrue: 1, ifFalse: 0 }
84
- : { ids: categoriesWithSingleChild, ifTrue: 0, ifFalse: 1 };
85
- const { categoryClass } = getClassesByView(viewType);
86
- const [categoriesInstanceFilterClauses, definitionContainersInstanceFilterClauses] = await Promise.all([categoryClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) => this._selectQueryFactory.createFilterClauses({
199
+ if (definitionContainers.length > 0) {
200
+ hierarchyDefinition.push(...(await this.createDefinitionContainersQuery({ definitionContainerIds: definitionContainers, instanceFilter })));
201
+ }
202
+ return hierarchyDefinition;
203
+ }
204
+ async createDefinitionContainersQuery({ definitionContainerIds, instanceFilter, }) {
205
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
87
206
  filter: instanceFilter,
88
- contentClass: { fullName: className, alias: "this" },
89
- })));
90
- const definitionContainersQuery = definitionContainers.length > 0
91
- ? `
92
- SELECT
93
- ${await this._selectQueryFactory.createSelectClause({
94
- ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
95
- ecInstanceId: { selector: "this.ECInstanceId" },
96
- nodeLabel: {
97
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
98
- classAlias: "this",
99
- className: DEFINITION_CONTAINER_CLASS,
100
- }),
101
- },
102
- extendedData: {
103
- isDefinitionContainer: true,
104
- imageId: "icon-definition-container",
105
- },
106
- hasChildren: true,
107
- supportsFiltering: true,
108
- })}
109
- FROM
110
- ${definitionContainersInstanceFilterClauses.from} this
111
- ${definitionContainersInstanceFilterClauses.joins}
112
- WHERE
113
- this.ECInstanceId IN (${definitionContainers.join(", ")})
114
- ${definitionContainersInstanceFilterClauses.where ? `AND ${definitionContainersInstanceFilterClauses.where}` : ""}
115
- `
116
- : undefined;
117
- const categoriesQuery = categories.length > 0
118
- ? `
119
- SELECT
207
+ contentClass: { fullName: DEFINITION_CONTAINER_CLASS_NAME, alias: "this" },
208
+ });
209
+ return [
210
+ {
211
+ fullClassName: DEFINITION_CONTAINER_CLASS_NAME,
212
+ query: {
213
+ ecsql: `
214
+ SELECT
120
215
  ${await this._selectQueryFactory.createSelectClause({
121
- ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
122
- ecInstanceId: { selector: "this.ECInstanceId" },
123
- nodeLabel: {
124
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
125
- classAlias: "this",
126
- className: categoryClass,
127
- }),
128
- },
129
- ...(this._hierarchyConfig.hideSubCategories
130
- ? { hasChildren: false }
131
- : dataToDetermineHasChildren.ids.length > 0
132
- ? {
133
- hasChildren: {
134
- selector: `
135
- IIF(this.ECInstanceId IN (${dataToDetermineHasChildren.ids.join(",")}),
136
- ${dataToDetermineHasChildren.ifTrue},
137
- ${dataToDetermineHasChildren.ifFalse}
138
- )
139
- `,
140
- },
141
- }
142
- : { hasChildren: !!dataToDetermineHasChildren.ifFalse }),
143
- extendedData: {
144
- description: { selector: "this.Description" },
145
- isCategory: true,
146
- imageId: "icon-layers",
147
- },
148
- supportsFiltering: true,
149
- })}
216
+ ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
217
+ ecInstanceId: { selector: "this.ECInstanceId" },
218
+ nodeLabel: {
219
+ selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
220
+ classAlias: "this",
221
+ className: DEFINITION_CONTAINER_CLASS_NAME,
222
+ }),
223
+ },
224
+ extendedData: {
225
+ isDefinitionContainer: true,
226
+ imageId: "icon-definition-container",
227
+ },
228
+ hasChildren: true,
229
+ supportsFiltering: true,
230
+ })}
150
231
  FROM
151
- ${categoriesInstanceFilterClauses.from} this
152
- ${categoriesInstanceFilterClauses.joins}
232
+ ${instanceFilterClauses.from} this
233
+ ${instanceFilterClauses.joins}
153
234
  WHERE
154
- this.ECInstanceId IN (${categories.map((category) => category.id).join(", ")})
155
- ${categoriesInstanceFilterClauses.where ? `AND ${categoriesInstanceFilterClauses.where}` : ""}
156
- `
157
- : undefined;
158
- const queries = [categoriesQuery, definitionContainersQuery].filter((query) => query !== undefined);
235
+ this.ECInstanceId IN (${definitionContainerIds.join(", ")})
236
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
237
+ `,
238
+ },
239
+ },
240
+ ];
241
+ }
242
+ async createCategoriesQuery({ categories, instanceFilter, }) {
243
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
244
+ filter: instanceFilter,
245
+ contentClass: { fullName: this._categoryClass, alias: "this" },
246
+ });
247
+ const categoriesWithMultipleSubCategories = categories
248
+ .filter((categoryInfo) => categoryInfo.subCategoryChildCount > 1)
249
+ .map((categoryInfo) => categoryInfo.id);
250
+ const hasChildrenSelector = () => {
251
+ const conditions = new Array();
252
+ if (!this._hierarchyConfig.hideSubCategories && categoriesWithMultipleSubCategories.length > 0) {
253
+ conditions.push(`this.ECInstanceId IN (${categoriesWithMultipleSubCategories.join(",")})`);
254
+ }
255
+ if (this._hierarchyConfig.showElements) {
256
+ conditions.push(`
257
+ this.ECInstanceId IN (
258
+ SELECT e.Category.Id
259
+ FROM ${this._categoryElementClass} e
260
+ WHERE
261
+ e.Parent.Id IS NULL
262
+ AND e.ECInstanceId NOT IN (SELECT m.ECInstanceId FROM ${this._categoryModelClass} m)
263
+ )`);
264
+ }
265
+ return conditions.length > 0
266
+ ? {
267
+ selector: `IIF(${conditions.join(" OR ")}, 1, 0)`,
268
+ }
269
+ : false;
270
+ };
159
271
  return [
160
272
  {
161
- fullClassName: DEFINITION_ELEMENT_CLASS,
273
+ fullClassName: this._categoryClass,
162
274
  query: {
163
- ecsql: queries.join(" UNION ALL "),
275
+ ecsql: `
276
+ SELECT
277
+ ${await this._selectQueryFactory.createSelectClause({
278
+ ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
279
+ ecInstanceId: { selector: "this.ECInstanceId" },
280
+ nodeLabel: {
281
+ selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
282
+ classAlias: "this",
283
+ className: this._categoryClass,
284
+ }),
285
+ },
286
+ hasChildren: hasChildrenSelector(),
287
+ extendedData: {
288
+ description: { selector: "this.Description" },
289
+ isCategory: true,
290
+ imageId: "icon-layers",
291
+ hasSubCategories: categoriesWithMultipleSubCategories.length > 0
292
+ ? { selector: `IIF(this.ECInstanceId IN (${categoriesWithMultipleSubCategories.join(",")}), true, false) ` }
293
+ : false,
294
+ },
295
+ supportsFiltering: true,
296
+ })}
297
+ FROM
298
+ ${instanceFilterClauses.from} this
299
+ ${instanceFilterClauses.joins}
300
+ WHERE
301
+ this.ECInstanceId IN (${categories.map((category) => category.id).join(", ")})
302
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
303
+ `,
164
304
  },
165
305
  },
166
306
  ];
167
307
  }
168
- async createSubcategoryQuery({ parentNodeInstanceIds: elementIds, instanceFilter, }) {
308
+ async createCategoryChildrenQuery(props) {
309
+ return (await Promise.all([
310
+ ...(!this._hierarchyConfig.hideSubCategories && props.parentNode.extendedData?.hasSubCategories ? [this.createSubCategoriesQuery(props)] : []),
311
+ ...(this._hierarchyConfig.showElements ? [this.createCategoryElementsQuery(props)] : []),
312
+ ])).reduce((acc, levelDefinition) => acc.concat(levelDefinition), new Array());
313
+ }
314
+ async createSubCategoriesQuery({ parentNodeInstanceIds: categoryIds, instanceFilter, }) {
169
315
  const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
170
316
  filter: instanceFilter,
171
- contentClass: { fullName: SUB_CATEGORY_CLASS, alias: "this" },
317
+ contentClass: { fullName: SUB_CATEGORY_CLASS_NAME, alias: "this" },
172
318
  });
173
319
  return [
174
320
  {
175
- fullClassName: SUB_CATEGORY_CLASS,
321
+ fullClassName: SUB_CATEGORY_CLASS_NAME,
176
322
  query: {
177
323
  ecsql: `
178
324
  SELECT
@@ -182,7 +328,7 @@ export class CategoriesTreeDefinition {
182
328
  nodeLabel: {
183
329
  selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
184
330
  classAlias: "this",
185
- className: SUB_CATEGORY_CLASS,
331
+ className: SUB_CATEGORY_CLASS_NAME,
186
332
  }),
187
333
  },
188
334
  extendedData: {
@@ -195,30 +341,149 @@ export class CategoriesTreeDefinition {
195
341
  FROM ${instanceFilterClauses.from} this
196
342
  ${instanceFilterClauses.joins}
197
343
  WHERE
198
- NOT this.IsPrivate AND this.Parent.Id IN (${elementIds.map(() => "?").join(",")})
344
+ NOT this.IsPrivate AND this.Parent.Id IN (${categoryIds.join(",")})
345
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
346
+ `,
347
+ },
348
+ },
349
+ ];
350
+ }
351
+ async createCategoryElementsQuery({ parentNodeInstanceIds: categoryIds, instanceFilter, parentNode, }) {
352
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
353
+ filter: instanceFilter,
354
+ contentClass: { fullName: this._categoryElementClass, alias: "this" },
355
+ });
356
+ const modelIds = parentNode.extendedData?.isCategoryOfSubModel
357
+ ? parseIdsSelectorResult(parentNode.extendedData?.modelIds)
358
+ : [...getDistinctMapValues(await this._idsCache.getCategoriesElementModels(categoryIds))];
359
+ if (modelIds.length === 0) {
360
+ return [];
361
+ }
362
+ const modeledElements = await firstValueFrom(from(modelIds).pipe(mergeMap(async (modelId) => this._idsCache.getCategoriesModeledElements(modelId, categoryIds)), reduce((acc, foundModeledElements) => {
363
+ return acc.concat(foundModeledElements);
364
+ }, new Array())));
365
+ return [
366
+ {
367
+ fullClassName: this._categoryElementClass,
368
+ query: {
369
+ ecsql: `
370
+ SELECT
371
+ ${await this._selectQueryFactory.createSelectClause({
372
+ ecClassId: { selector: "this.ECClassId" },
373
+ ecInstanceId: { selector: "this.ECInstanceId" },
374
+ nodeLabel: {
375
+ selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
376
+ classAlias: "this",
377
+ className: this._categoryElementClass,
378
+ }),
379
+ },
380
+ hasChildren: {
381
+ selector: `
382
+ IIF(
383
+ ${modeledElements.length ? `this.ECInstanceId IN (${modeledElements.join(",")})` : `FALSE`},
384
+ 1,
385
+ IFNULL((
386
+ SELECT 1
387
+ FROM ${this._categoryElementClass} ce
388
+ WHERE ce.Parent.Id = this.ECInstanceId
389
+ LIMIT 1
390
+ ), 0)
391
+ )
392
+ `,
393
+ },
394
+ grouping: {
395
+ byClass: true,
396
+ },
397
+ extendedData: {
398
+ modelId: { selector: "IdToHex(this.Model.Id)" },
399
+ categoryId: { selector: "IdToHex(this.Category.Id)" },
400
+ imageId: "icon-item",
401
+ isElement: true,
402
+ },
403
+ supportsFiltering: true,
404
+ })}
405
+ FROM ${instanceFilterClauses.from} this
406
+ ${parentNode.extendedData?.isCategoryOfSubModel ? "" : `JOIN ${INFORMATION_PARTITION_ELEMENT_CLASS_NAME} ipe ON ipe.ECInstanceId = this.Model.Id`}
407
+ ${instanceFilterClauses.joins}
408
+ WHERE
409
+ this.Category.Id IN (${categoryIds.join(",")})
410
+ AND this.Model.Id IN (${modelIds.join(",")})
411
+ AND this.Parent.Id IS NULL
412
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
413
+ `,
414
+ },
415
+ },
416
+ ];
417
+ }
418
+ async createElementChildrenQuery({ parentNodeInstanceIds: elementIds, instanceFilter, }) {
419
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
420
+ filter: instanceFilter,
421
+ contentClass: { fullName: this._categoryElementClass, alias: "this" },
422
+ });
423
+ return [
424
+ {
425
+ fullClassName: this._categoryElementClass,
426
+ query: {
427
+ ecsql: `
428
+ SELECT
429
+ ${await this._selectQueryFactory.createSelectClause({
430
+ ecClassId: { selector: "this.ECClassId" },
431
+ ecInstanceId: { selector: "this.ECInstanceId" },
432
+ nodeLabel: {
433
+ selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
434
+ classAlias: "this",
435
+ className: this._categoryElementClass,
436
+ }),
437
+ },
438
+ hasChildren: {
439
+ selector: `
440
+ IFNULL((
441
+ SELECT 1
442
+ FROM ${this._categoryElementClass} ce
443
+ JOIN ${MODEL_CLASS_NAME} m ON ce.Model.Id = m.ECInstanceId
444
+ WHERE ce.Parent.Id = this.ECInstanceId OR (ce.Model.Id = this.ECInstanceId AND m.IsPrivate = false)
445
+ LIMIT 1
446
+ ), 0)
447
+ `,
448
+ },
449
+ grouping: {
450
+ byClass: true,
451
+ },
452
+ extendedData: {
453
+ modelId: { selector: "IdToHex(this.Model.Id)" },
454
+ categoryId: { selector: "IdToHex(this.Category.Id)" },
455
+ imageId: "icon-item",
456
+ isElement: true,
457
+ },
458
+ supportsFiltering: true,
459
+ })}
460
+ FROM ${instanceFilterClauses.from} this
461
+ ${instanceFilterClauses.joins}
462
+ WHERE
463
+ this.Parent.Id IN (${elementIds.join(",")})
199
464
  ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
200
465
  `,
201
- bindings: elementIds.map((id) => ({ type: "id", value: id })),
202
466
  },
203
467
  },
204
468
  ];
205
469
  }
206
470
  static async createInstanceKeyPaths(props) {
207
471
  const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
208
- return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory, cache: props.idsCache });
472
+ return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory });
209
473
  }
210
474
  }
211
475
  async function createInstanceKeyPathsFromInstanceLabel(props) {
212
- const { definitionContainers, categories } = await props.cache.getAllDefinitionContainersAndCategories();
476
+ const { definitionContainers, categories } = await props.idsCache.getAllDefinitionContainersAndCategories();
213
477
  if (categories.length === 0) {
214
478
  return [];
215
479
  }
216
- const { categoryClass } = getClassesByView(props.viewType);
480
+ const { categoryClass, elementClass } = getClassesByView(props.viewType);
217
481
  const adjustedLabel = props.label.replace(/[%_\\]/g, "\\$&");
218
482
  const CATEGORIES_WITH_LABELS_CTE = "CategoriesWithLabels";
483
+ const ELEMENTS_WITH_LABELS_CTE = "ElementsWithLabels";
219
484
  const SUBCATEGORIES_WITH_LABELS_CTE = "SubCategoriesWithLabels";
220
485
  const DEFINITION_CONTAINERS_WITH_LABELS_CTE = "DefinitionContainersWithLabels";
221
- const [categoryLabelSelectClause, subCategoryLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all([categoryClass, SUB_CATEGORY_CLASS, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) => props.labelsFactory.createSelectClause({ classAlias: "this", className })));
486
+ const [categoryLabelSelectClause, subCategoryLabelSelectClause, elementLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all([categoryClass, SUB_CATEGORY_CLASS_NAME, elementClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS_NAME] : [])].map(async (className) => props.labelsFactory.createSelectClause({ classAlias: "this", className })));
222
487
  return lastValueFrom(defer(() => {
223
488
  const ctes = [
224
489
  `${CATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ChildCount, DisplayLabel) AS (
@@ -229,11 +494,28 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
229
494
  ${categoryLabelSelectClause}
230
495
  FROM
231
496
  ${categoryClass} this
232
- JOIN ${SUB_CATEGORY_CLASS} sc ON sc.Parent.Id = this.ECInstanceId
497
+ JOIN ${SUB_CATEGORY_CLASS_NAME} sc ON sc.Parent.Id = this.ECInstanceId
233
498
  WHERE
234
499
  this.ECInstanceId IN (${categories.join(", ")})
235
500
  GROUP BY this.ECInstanceId
236
501
  )`,
502
+ ...(props.hierarchyConfig.showElements
503
+ ? [
504
+ `${ELEMENTS_WITH_LABELS_CTE}(ClassName, ECInstanceId, ParentId, DisplayLabel) AS (
505
+ SELECT
506
+ 'e',
507
+ this.ECInstanceId,
508
+ this.Parent.Id,
509
+ ${elementLabelSelectClause}
510
+ FROM
511
+ ${elementClass} this
512
+ JOIN ${MODEL_CLASS_NAME} m ON this.Model.Id = m.ECInstanceId
513
+ WHERE
514
+ NOT m.IsPrivate
515
+ AND this.Category.Id IN (${categories.join(", ")})
516
+ )`,
517
+ ]
518
+ : []),
237
519
  ...(props.hierarchyConfig.hideSubCategories
238
520
  ? []
239
521
  : [
@@ -244,7 +526,7 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
244
526
  this.Parent.Id,
245
527
  ${subCategoryLabelSelectClause}
246
528
  FROM
247
- ${SUB_CATEGORY_CLASS} this
529
+ ${SUB_CATEGORY_CLASS_NAME} this
248
530
  WHERE
249
531
  NOT this.IsPrivate
250
532
  AND this.Parent.Id IN (${categories.join(", ")})
@@ -258,7 +540,7 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
258
540
  this.ECInstanceId,
259
541
  ${definitionContainerLabelSelectClause}
260
542
  FROM
261
- ${DEFINITION_CONTAINER_CLASS} this
543
+ ${DEFINITION_CONTAINER_CLASS_NAME} this
262
544
  WHERE
263
545
  this.ECInstanceId IN (${definitionContainers.join(", ")})
264
546
  )`,
@@ -267,72 +549,190 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
267
549
  ];
268
550
  const ecsql = `
269
551
  SELECT * FROM (
270
- SELECT
271
- c.ClassName AS ClassName,
272
- c.ECInstanceId AS ECInstanceId
273
- FROM
274
- ${CATEGORIES_WITH_LABELS_CTE} c
275
- WHERE
276
- c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
277
- ${props.hierarchyConfig.hideSubCategories
552
+ SELECT
553
+ c.ClassName AS ClassName,
554
+ c.ECInstanceId AS ECInstanceId
555
+ FROM
556
+ ${CATEGORIES_WITH_LABELS_CTE} c
557
+ WHERE
558
+ c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
559
+ ${props.hierarchyConfig.showElements
560
+ ? `
561
+ UNION ALL
562
+ SELECT
563
+ e.ClassName AS ClassName,
564
+ e.ECInstanceId AS ECInstanceId
565
+ FROM
566
+ ${ELEMENTS_WITH_LABELS_CTE} e
567
+ WHERE
568
+ e.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
569
+ `
570
+ : ""}
571
+ ${props.hierarchyConfig.hideSubCategories
278
572
  ? ""
279
573
  : `
280
- UNION ALL
281
- SELECT
282
- sc.ClassName AS ClassName,
283
- sc.ECInstanceId AS ECInstanceId
284
- FROM
285
- ${CATEGORIES_WITH_LABELS_CTE} c
286
- JOIN ${SUBCATEGORIES_WITH_LABELS_CTE} sc ON sc.ParentId = c.ECInstanceId
287
- WHERE
288
- c.ChildCount > 1
289
- AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
290
- `}
291
- ${definitionContainers.length > 0
574
+ UNION ALL
575
+ SELECT
576
+ sc.ClassName AS ClassName,
577
+ sc.ECInstanceId AS ECInstanceId
578
+ FROM
579
+ ${CATEGORIES_WITH_LABELS_CTE} c
580
+ JOIN ${SUBCATEGORIES_WITH_LABELS_CTE} sc ON sc.ParentId = c.ECInstanceId
581
+ WHERE
582
+ c.ChildCount > 1
583
+ AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
584
+ `}
585
+ ${definitionContainers.length > 0
292
586
  ? `
293
- UNION ALL
294
- SELECT
295
- dc.ClassName AS ClassName,
296
- dc.ECInstanceId AS ECInstanceId
297
- FROM
298
- ${DEFINITION_CONTAINERS_WITH_LABELS_CTE} dc
299
- WHERE
300
- dc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
301
- `
587
+ UNION ALL
588
+ SELECT
589
+ dc.ClassName AS ClassName,
590
+ dc.ECInstanceId AS ECInstanceId
591
+ FROM
592
+ ${DEFINITION_CONTAINERS_WITH_LABELS_CTE} dc
593
+ WHERE
594
+ dc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
595
+ `
302
596
  : ""}
303
597
  )
304
598
  ${props.limit === undefined ? `LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}` : props.limit !== "unbounded" ? `LIMIT ${props.limit}` : ""}
305
599
  `;
306
600
  const bindings = [
307
601
  { type: "string", value: adjustedLabel },
602
+ ...(props.hierarchyConfig.showElements ? [{ type: "string", value: adjustedLabel }] : []),
308
603
  ...(props.hierarchyConfig.hideSubCategories ? [] : [{ type: "string", value: adjustedLabel }]),
309
604
  ...(definitionContainers.length > 0 ? [{ type: "string", value: adjustedLabel }] : []),
310
605
  ];
311
606
  return props.imodelAccess.createQueryReader({ ctes, ecsql, bindings }, { restartToken: "tree-widget/categories-tree/filter-by-label-query", limit: props.limit });
312
- }).pipe(map((row) => ({
313
- className: row.ClassName === "c" ? categoryClass : row.ClassName === "sc" ? SUB_CATEGORY_CLASS : DEFINITION_CONTAINER_CLASS,
314
- id: row.ECInstanceId,
315
- })), toArray(), mergeMap((targetItems) => createInstanceKeyPathsFromTargetItems({ ...props, targetItems })), toArray()));
607
+ }).pipe(map((row) => {
608
+ let className;
609
+ switch (row.ClassName) {
610
+ case "c":
611
+ className = categoryClass;
612
+ break;
613
+ case "sc":
614
+ className = SUB_CATEGORY_CLASS_NAME;
615
+ break;
616
+ case "e":
617
+ className = elementClass;
618
+ break;
619
+ default:
620
+ className = DEFINITION_CONTAINER_CLASS_NAME;
621
+ break;
622
+ }
623
+ return {
624
+ className,
625
+ id: row.ECInstanceId,
626
+ };
627
+ }), toArray(), mergeMap((targetItems) => createInstanceKeyPathsFromTargetItems({ ...props, targetItems })), toArray()));
316
628
  }
317
- function createInstanceKeyPathsFromTargetItems(props) {
318
- const { limit, targetItems, viewType, idsCache, hierarchyConfig } = props;
629
+ function createInstanceKeyPathsFromTargetItems({ targetItems, imodelAccess, viewType, hierarchyConfig, idsCache, limit, }) {
319
630
  if (limit !== "unbounded" && targetItems.length > (limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT)) {
320
631
  throw new FilterLimitExceededError(limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT);
321
632
  }
322
- if (targetItems.length === 0) {
323
- return EMPTY;
324
- }
325
633
  const { categoryClass } = getClassesByView(viewType);
326
- return from(targetItems).pipe(mergeMap(async (targetItem) => {
327
- if (targetItem.className === DEFINITION_CONTAINER_CLASS) {
328
- return { path: await idsCache.getInstanceKeyPaths({ definitionContainerId: targetItem.id }), options: { autoExpand: true } };
634
+ return from(targetItems).pipe(releaseMainThreadOnItemsCount(2000), reduce((acc, { id, className }) => {
635
+ if (className === categoryClass) {
636
+ acc.categoryIds.push(id);
637
+ return acc;
329
638
  }
330
- if (targetItem.className === categoryClass) {
331
- return { path: await idsCache.getInstanceKeyPaths({ categoryId: targetItem.id }), options: { autoExpand: true } };
639
+ if (className === DEFINITION_CONTAINER_CLASS_NAME) {
640
+ acc.definitionContainerIds.push(id);
641
+ return acc;
642
+ }
643
+ if (className === SUB_CATEGORY_CLASS_NAME) {
644
+ if (hierarchyConfig.hideSubCategories) {
645
+ return acc;
646
+ }
647
+ acc.subCategoryIds.push(id);
648
+ return acc;
332
649
  }
333
- return hierarchyConfig.hideSubCategories
334
- ? []
335
- : { path: await idsCache.getInstanceKeyPaths({ subCategoryId: targetItem.id }), options: { autoExpand: true } };
650
+ if (!hierarchyConfig.showElements) {
651
+ return acc;
652
+ }
653
+ acc.elementIds.push(id);
654
+ return acc;
655
+ }, {
656
+ definitionContainerIds: new Array(),
657
+ categoryIds: new Array(),
658
+ subCategoryIds: new Array(),
659
+ elementIds: new Array(),
660
+ }), mergeMap((ids) => {
661
+ const elementsLength = ids.elementIds.length;
662
+ return merge(from(ids.definitionContainerIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ definitionContainerId: id }), options: { autoExpand: true } }))), from(ids.categoryIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ categoryId: id }), options: { autoExpand: true } }))), from(ids.subCategoryIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ subCategoryId: id }), options: { autoExpand: true } }))), from(ids.elementIds).pipe(bufferCount(Math.ceil(elementsLength / Math.ceil(elementsLength / 5000))), releaseMainThreadOnItemsCount(1), mergeMap((block) => createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, viewType, block), 10)));
663
+ }));
664
+ }
665
+ function createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, viewType, targetItems) {
666
+ const separator = ";";
667
+ const { categoryClass, elementClass, modelClass } = getClassesByView(viewType);
668
+ if (targetItems.length === 0 || !hierarchyConfig.showElements) {
669
+ return of([]);
670
+ }
671
+ return defer(() => {
672
+ const ctes = [
673
+ `CategoriesElementsHierarchy(ECInstanceId, ParentId, ModelId, Path) AS (
674
+ SELECT
675
+ e.ECInstanceId,
676
+ e.Parent.Id,
677
+ e.Model.Id,
678
+ IIF(e.Parent.Id IS NULL,
679
+ 'm${separator}' || CAST(IdToHex([m].[ECInstanceId]) AS TEXT) || '${separator}c${separator}' || CAST(IdToHex([c].[ECInstanceId]) AS TEXT) || '${separator}e${separator}' || CAST(IdToHex([e].[ECInstanceId]) AS TEXT),
680
+ 'e${separator}' || CAST(IdToHex([e].[ECInstanceId]) AS TEXT)
681
+ )
682
+ FROM ${elementClass} e
683
+ LEFT JOIN ${modelClass} m ON (e.Parent.Id IS NULL AND m.ECInstanceId = e.Model.Id)
684
+ LEFT JOIN ${categoryClass} c ON (e.Parent.Id IS NULL AND c.ECInstanceId = e.Category.Id)
685
+ WHERE e.ECInstanceId IN (${targetItems.join(",")})
686
+
687
+ UNION ALL
688
+
689
+ SELECT
690
+ pe.ECInstanceId,
691
+ pe.Parent.Id,
692
+ pe.Model.Id,
693
+ IIF(pe.Parent.Id IS NULL,
694
+ 'm${separator}' || CAST(IdToHex([m].[ECInstanceId]) AS TEXT) || '${separator}c${separator}' || CAST(IdToHex([c].[ECInstanceId]) AS TEXT) || '${separator}e${separator}' || CAST(IdToHex([pe].[ECInstanceId]) AS TEXT) || '${separator}' || ce.Path,
695
+ 'e${separator}' || CAST(IdToHex([pe].[ECInstanceId]) AS TEXT) || '${separator}' || ce.Path
696
+ )
697
+ FROM CategoriesElementsHierarchy ce
698
+ JOIN ${elementClass} pe ON (pe.ECInstanceId = ce.ParentId OR pe.ECInstanceId = ce.ModelId AND ce.ParentId IS NULL)
699
+ LEFT JOIN ${modelClass} m ON (pe.Parent.Id IS NULL AND m.ECInstanceId = pe.Model.Id)
700
+ LEFT JOIN ${categoryClass} c ON (pe.Parent.Id IS NULL AND c.ECInstanceId = pe.Category.Id)
701
+ )`,
702
+ ];
703
+ const ecsql = `
704
+ SELECT mce.Path
705
+ FROM CategoriesElementsHierarchy mce
706
+ WHERE mce.ParentId IS NULL
707
+ `;
708
+ return imodelAccess.createQueryReader({ ctes, ecsql }, { rowFormat: "Indexes", limit: "unbounded", restartToken: "tree-widget/categories-tree/elements-filter-paths-query" });
709
+ }).pipe(releaseMainThreadOnItemsCount(300), map((row) => parseQueryRow(row, separator, elementClass, categoryClass, modelClass)), mergeMap(async (elementHierarchyPath) => {
710
+ const pathToCategory = await idsCache.getInstanceKeyPaths({ categoryId: elementHierarchyPath[0].id });
711
+ pathToCategory.pop(); // category is already included in the element hierarchy path
712
+ const path = [...pathToCategory, ...elementHierarchyPath];
713
+ return { path, options: { autoExpand: true } };
336
714
  }));
337
715
  }
716
+ function parseQueryRow(row, separator, elementClassName, categoryClassName, modelClassName) {
717
+ const rowElements = row[0].split(separator);
718
+ const path = new Array();
719
+ for (let i = 0; i < rowElements.length; i += 2) {
720
+ switch (rowElements[i]) {
721
+ case "e":
722
+ path.push({ className: elementClassName, id: rowElements[i + 1] });
723
+ break;
724
+ case "c":
725
+ path.push({ className: categoryClassName, id: rowElements[i + 1] });
726
+ break;
727
+ case "m":
728
+ // Ignore first model since it isn't in hierarchy
729
+ if (i === 0) {
730
+ break;
731
+ }
732
+ path.push({ className: modelClassName, id: rowElements[i + 1] });
733
+ break;
734
+ }
735
+ }
736
+ return path;
737
+ }
338
738
  //# sourceMappingURL=CategoriesTreeDefinition.js.map