@itwin/tree-widget-react 4.0.0-alpha.11 → 4.0.0-alpha.13

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 (40) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +133 -35
  3. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +43 -18
  4. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  5. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +0 -10
  6. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +54 -132
  7. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
  8. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js +2 -6
  9. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
  10. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +20 -14
  11. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
  12. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +11 -10
  13. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +61 -48
  14. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
  15. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +0 -1
  16. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js +0 -4
  17. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +1 -1
  18. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js +25 -21
  19. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js.map +1 -1
  20. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +26 -0
  21. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +20 -0
  22. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -0
  23. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +17 -0
  24. package/lib/esm/tree-widget-react/components/trees/{models-tree/internal → common/internal/useTreeHooks}/UseIdsCache.js +10 -11
  25. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -0
  26. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +27 -0
  27. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +28 -18
  28. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  29. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +3 -0
  30. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +1 -0
  31. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
  32. package/package.json +28 -34
  33. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.d.ts +0 -8
  34. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js +0 -48
  35. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js.map +0 -1
  36. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.d.ts +0 -8
  37. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.js +0 -45
  38. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.js.map +0 -1
  39. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.d.ts +0 -8
  40. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,9 +1,33 @@
1
1
  # Change Log - @itwin/tree-widget-react
2
2
 
3
- This log was last generated on Thu, 15 May 2025 05:33:32 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 20 Jun 2025 17:05:06 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.10.1
8
+
9
+ Fri, 20 Jun 2025 17:05:06 GMT
10
+
11
+ ### Patches
12
+
13
+ - Update itwinjs-core dependencies to v5.0.0 ([#1349](https://github.com/iTwin/viewer-components-react/pull/1349))
14
+
15
+ ## 3.10.0
16
+
17
+ Mon, 02 Jun 2025 13:19:21 GMT
18
+
19
+ ### Minor changes
20
+
21
+ - `useModelsTree`: The `getFilteredPaths` callback prop now has a `filter` prop, which matches the value of `filter` prop passed to `useModelsTree` hook. This make it more convenient for consumers to filter by instance keys and label at the same time. ([#1335](https://github.com/iTwin/viewer-components-react/pull/1335))
22
+
23
+ ## 3.9.0
24
+
25
+ Mon, 19 May 2025 16:58:21 GMT
26
+
27
+ ### Minor changes
28
+
29
+ - Add support for iTwin.js v5.0 ([#1326](https://github.com/iTwin/viewer-components-react/pull/1326))
30
+
7
31
  ## 3.8.0
8
32
 
9
33
  Thu, 15 May 2025 05:33:32 GMT
package/README.md CHANGED
@@ -191,41 +191,139 @@ function CustomModelsTreeComponent({ imodel, viewport, selectionStorage }: Custo
191
191
 
192
192
  #### Displaying a subset of the tree
193
193
 
194
- Models tree allows displaying a subset of all nodes by providing a `getFilteredPaths` function, which receives a `createInstanceKeyPaths` function for creating hierarchy node paths from instance keys or an instance label and returns a list of hierarchy node paths targeting some nodes. When these paths are provided, the displayed hierarchy consists only of the targeted nodes, their ancestors, and their children. Example implementation of `getFilteredPaths`:
195
-
196
- ```tsx
197
- type UseModelsTreeProps = Parameters<typeof useModelsTree>[0];
198
- type GetFilteredPathsType = Exclude<UseModelsTreeProps["getFilteredPaths"], undefined>;
199
- interface CustomModelsTreeProps {
200
- viewport: Viewport;
201
- selectionStorage: SelectionStorage;
202
- imodel: IModelConnection;
203
- targetItems: InstanceKey[];
204
- }
205
-
206
- function CustomModelsTreeComponent({ viewport, selectionStorage, imodel, targetItems }: CustomModelsTreeProps) {
207
- const getFilteredPaths = useCallback<GetFilteredPathsType>(
208
- async ({ createInstanceKeyPaths }) => {
209
- return createInstanceKeyPaths({
210
- // list of instance keys representing nodes that should be displayed in the hierarchy
211
- targetItems,
212
- });
213
- },
214
- [targetItems],
215
- );
216
-
217
- const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
218
-
219
- return (
220
- <VisibilityTree
221
- {...modelsTreeProps}
222
- selectionStorage={selectionStorage}
223
- imodel={imodel}
224
- treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
225
- />
226
- );
227
- }
228
- ```
194
+ Models tree allows displaying a subset of all nodes by providing a `getFilteredPaths` function. This function receives a helper function called `createInstanceKeyPaths`, which can generate paths from either:
195
+
196
+ - a list of instance keys (`targetItems`)
197
+ - a label string
198
+
199
+ Based on the returned paths, the displayed hierarchy consists only of the targeted nodes, their ancestors, and their children.
200
+
201
+ Use `getFilteredPaths` when you need more control over which nodes are shown. Here are some example use cases:
202
+
203
+ - **Filter by known instance keys**: You already have a list of `InstanceKey` items that should remain in the tree. Pass them as `targetItems` to `createInstanceKeyPaths`.
204
+
205
+ ```tsx
206
+ type UseModelsTreeProps = Parameters<typeof useModelsTree>[0];
207
+ type GetFilteredPathsType = Exclude<UseModelsTreeProps["getFilteredPaths"], undefined>;
208
+
209
+ function CustomModelsTreeComponentWithTargetItems({
210
+ viewport,
211
+ selectionStorage,
212
+ imodel,
213
+ targetItems,
214
+ }: {
215
+ viewport: Viewport;
216
+ selectionStorage: SelectionStorage;
217
+ imodel: IModelConnection;
218
+ targetItems: InstanceKey[];
219
+ }) {
220
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(
221
+ async ({ createInstanceKeyPaths }) => {
222
+ return createInstanceKeyPaths({
223
+ // list of instance keys representing nodes that should be displayed in the hierarchy
224
+ targetItems,
225
+ });
226
+ },
227
+ [targetItems],
228
+ );
229
+
230
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
231
+
232
+ return (
233
+ <VisibilityTree
234
+ {...modelsTreeProps}
235
+ getSchemaContext={getSchemaContext}
236
+ selectionStorage={selectionStorage}
237
+ imodel={imodel}
238
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
239
+ />
240
+ );
241
+ }
242
+ ```
243
+
244
+ - **Post-process the paths created `createInstanceKeyPaths`**: Use `filter` string to generate the paths, then apply additional filtering - e.g., remove paths that are too long.
245
+
246
+ ```tsx
247
+ function CustomModelsTreeComponentWithPostProcessing({
248
+ viewport,
249
+ selectionStorage,
250
+ imodel,
251
+ }: {
252
+ viewport: Viewport;
253
+ selectionStorage: SelectionStorage;
254
+ imodel: IModelConnection;
255
+ }) {
256
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(async ({ createInstanceKeyPaths, filter }) => {
257
+ const defaultPaths = await createInstanceKeyPaths({ label: filter ?? "test" });
258
+ const result = new Array<HierarchyFilteringPath>();
259
+ for (const path of defaultPaths) {
260
+ const normalizedPath = HierarchyFilteringPath.normalize(path);
261
+ if (normalizedPath.path.length < 5) {
262
+ normalizedPath.options = { autoExpand: true };
263
+ result.push(normalizedPath);
264
+ }
265
+ }
266
+ return result;
267
+ }, []);
268
+
269
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
270
+
271
+ return (
272
+ <VisibilityTree
273
+ {...modelsTreeProps}
274
+ getSchemaContext={getSchemaContext}
275
+ selectionStorage={selectionStorage}
276
+ imodel={imodel}
277
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
278
+ />
279
+ );
280
+ }
281
+ ```
282
+
283
+ - **Apply custom logic to generate instance keys**: Generate instance keys using custom implementation. For example: query elements that have specified filter in their user label and provide them as targetItems.
284
+
285
+ ```tsx
286
+ function CustomModelsTreeComponentWithFilterAndTargetItems({
287
+ viewport,
288
+ selectionStorage,
289
+ imodel,
290
+ }: {
291
+ viewport: Viewport;
292
+ selectionStorage: SelectionStorage;
293
+ imodel: IModelConnection;
294
+ }) {
295
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(
296
+ async ({ createInstanceKeyPaths, filter }) => {
297
+ const targetItems = new Array<InstanceKey>();
298
+ for await (const row of imodel.createQueryReader(
299
+ `
300
+ SELECT ec_classname(e.ECClassId, 's.c') className, e.ECInstanceId id
301
+ FROM BisCore.Element e
302
+ WHERE UserLabel LIKE '%${filter ?? ""}%'
303
+ `,
304
+ undefined,
305
+ { rowFormat: QueryRowFormat.UseJsPropertyNames },
306
+ )) {
307
+ targetItems.push({ id: row.id, className: row.className });
308
+ }
309
+ return createInstanceKeyPaths({ targetItems });
310
+ },
311
+ [imodel],
312
+ );
313
+
314
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths, filter: "test" });
315
+
316
+ return (
317
+ <VisibilityTree
318
+ {...modelsTreeProps}
319
+ getSchemaContext={getSchemaContext}
320
+ selectionStorage={selectionStorage}
321
+ imodel={imodel}
322
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
323
+ />
324
+ );
325
+ }
326
+ ```
229
327
 
230
328
  ### Categories tree
231
329
 
@@ -3,7 +3,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
5
5
  *--------------------------------------------------------------------------------------------*/
6
- import { useCallback, useEffect, useMemo, useState } from "react";
6
+ import { useCallback, useEffect, useMemo } from "react";
7
+ import { createECSqlQueryExecutor } from "@itwin/presentation-core-interop";
7
8
  import { Icon } from "@stratakit/foundations";
8
9
  import categorySvg from "@stratakit/icons/bis-category-3d.svg";
9
10
  import subcategorySvg from "@stratakit/icons/bis-category-subcategory.svg";
@@ -11,10 +12,12 @@ import classSvg from "@stratakit/icons/bis-class.svg";
11
12
  import definitionContainerSvg from "@stratakit/icons/bis-definitions-container.svg";
12
13
  import elementSvg from "@stratakit/icons/bis-element.svg";
13
14
  import { EmptyTreeContent, FilterUnknownError, NoFilterMatches, TooManyFilterMatches } from "../common/components/EmptyTree.js";
15
+ import { useCachedVisibility } from "../common/internal/useTreeHooks/UseCachedVisibility.js";
16
+ import { useIdsCache } from "../common/internal/useTreeHooks/UseIdsCache.js";
14
17
  import { CategoriesTreeDefinition, defaultHierarchyConfiguration } from "./CategoriesTreeDefinition.js";
18
+ import { CategoriesTreeIdsCache } from "./internal/CategoriesTreeIdsCache.js";
15
19
  import { createCategoriesTreeVisibilityHandler } from "./internal/CategoriesTreeVisibilityHandler.js";
16
20
  import { useFilteredPaths } from "./internal/UseFilteredPaths.js";
17
- import { useIdsCache } from "./internal/UseIdsCache.js";
18
21
  /**
19
22
  * Custom hook to create and manage state for the categories tree.
20
23
  * @beta
@@ -27,7 +30,16 @@ export function useCategoriesTree({ filter, activeView, onCategoriesFiltered, em
27
30
  // eslint-disable-next-line react-hooks/exhaustive-deps
28
31
  Object.values(hierarchyConfig ?? {}));
29
32
  const viewType = activeView.view.is2d() ? "2d" : "3d";
30
- const { getCategoriesTreeIdsCache, visibilityHandlerFactory, onFilteredPathsChanged } = useCachedVisibility(activeView, hierarchyConfiguration, viewType);
33
+ const { getCache: getCategoriesTreeIdsCache } = useIdsCache({
34
+ imodel: activeView.iModel,
35
+ createCache,
36
+ cacheSpecificProps: useMemo(() => ({ viewType }), [viewType]),
37
+ });
38
+ const { visibilityHandlerFactory, onFilteredPathsChanged } = useCategoriesCachedVisibility({
39
+ activeView,
40
+ getCache: getCategoriesTreeIdsCache,
41
+ hierarchyConfig: hierarchyConfiguration,
42
+ });
31
43
  const getHierarchyDefinition = useCallback((props) => {
32
44
  return new CategoriesTreeDefinition({ ...props, viewType, idsCache: getCategoriesTreeIdsCache(), hierarchyConfig: hierarchyConfiguration });
33
45
  }, [viewType, getCategoriesTreeIdsCache, hierarchyConfiguration]);
@@ -54,21 +66,15 @@ export function useCategoriesTree({ filter, activeView, onCategoriesFiltered, em
54
66
  },
55
67
  };
56
68
  }
57
- function createVisibilityHandlerFactory(activeView, idsCacheGetter, hierarchyConfig, filteredPaths) {
58
- return ({ imodelAccess }) => createCategoriesTreeVisibilityHandler({ viewport: activeView, idsCache: idsCacheGetter(), imodelAccess, filteredPaths, hierarchyConfig });
59
- }
60
- function useCachedVisibility(activeView, hierarchyConfig, viewType) {
61
- const [filteredPaths, setFilteredPaths] = useState();
62
- const { getCache: getCategoriesTreeIdsCache } = useIdsCache(activeView.iModel, viewType, filteredPaths);
63
- const [visibilityHandlerFactory, setVisibilityHandlerFactory] = useState(() => createVisibilityHandlerFactory(activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths));
64
- useEffect(() => {
65
- setVisibilityHandlerFactory(() => createVisibilityHandlerFactory(activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths));
66
- }, [activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths]);
67
- return {
68
- getCategoriesTreeIdsCache,
69
- visibilityHandlerFactory,
70
- onFilteredPathsChanged: useCallback((paths) => setFilteredPaths(paths), []),
71
- };
69
+ function createVisibilityHandlerFactory(props) {
70
+ const { activeView, factoryProps, idsCacheGetter, filteredPaths } = props;
71
+ return ({ imodelAccess }) => createCategoriesTreeVisibilityHandler({
72
+ viewport: activeView,
73
+ idsCache: idsCacheGetter(),
74
+ imodelAccess,
75
+ filteredPaths,
76
+ hierarchyConfig: factoryProps.hierarchyConfig,
77
+ });
72
78
  }
73
79
  function getEmptyTreeContentComponent(filter, error, emptyTreeContent) {
74
80
  if (error) {
@@ -111,4 +117,23 @@ export function CategoriesTreeIcon({ node }) {
111
117
  function getSublabel(node) {
112
118
  return node.nodeData.extendedData?.description;
113
119
  }
120
+ function useCategoriesCachedVisibility(props) {
121
+ const { activeView, getCache, hierarchyConfig } = props;
122
+ const { visibilityHandlerFactory, filteredPaths, onFilteredPathsChanged } = useCachedVisibility({
123
+ activeView,
124
+ getCache,
125
+ factoryProps: useMemo(() => ({ hierarchyConfig }), [hierarchyConfig]),
126
+ createFactory: createVisibilityHandlerFactory,
127
+ });
128
+ useEffect(() => {
129
+ getCache().clearFilteredElementsModels();
130
+ }, [filteredPaths, getCache]);
131
+ return {
132
+ visibilityHandlerFactory,
133
+ onFilteredPathsChanged,
134
+ };
135
+ }
136
+ function createCache(props) {
137
+ return new CategoriesTreeIdsCache(createECSqlQueryExecutor(props.imodel), props.specificProps.viewType);
138
+ }
114
139
  //# sourceMappingURL=UseCategoriesTree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UseCategoriesTree.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.tsx"],"names":[],"mappings":";AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,WAAW,MAAM,sCAAsC,CAAC;AAC/D,OAAO,cAAc,MAAM,+CAA+C,CAAC;AAC3E,OAAO,QAAQ,MAAM,gCAAgC,CAAC;AACtD,OAAO,sBAAsB,MAAM,gDAAgD,CAAC;AACpF,OAAO,UAAU,MAAM,kCAAkC,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAChI,OAAO,EAAE,wBAAwB,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AACxG,OAAO,EAAE,qCAAqC,EAAE,MAAM,+CAA+C,CAAC;AACtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAgCxD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,MAAM,EACN,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GACQ;IACvB,MAAM,sBAAsB,GAAG,OAAO,CACpC,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,6BAA6B;QAChC,GAAG,eAAe;KACnB,CAAC;IACF,uDAAuD;IACvD,MAAM,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,CACrC,CAAC;IACF,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAEtD,MAAM,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,GAAG,mBAAmB,CAAC,UAAU,EAAE,sBAAsB,EAAE,QAAQ,CAAC,CAAC;IAE1J,MAAM,sBAAsB,GAAG,WAAW,CACxC,CAAC,KAAK,EAAE,EAAE;QACR,OAAO,IAAI,wBAAwB,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,yBAAyB,EAAE,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC,CAAC;IAC9I,CAAC,EACD,CAAC,QAAQ,EAAE,yBAAyB,EAAE,sBAAsB,CAAC,CAC9D,CAAC;IAEF,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,gBAAgB,CAAC;QACpD,sBAAsB;QACtB,MAAM;QACN,yBAAyB;QACzB,sBAAsB;QACtB,QAAQ;QACR,oBAAoB;KACrB,CAAC,CAAC;IAEH,OAAO;QACL,mBAAmB,EAAE;YACnB,QAAQ,EAAE,oBAAoB;YAC9B,sBAAsB;YACtB,gBAAgB,EAAE,QAAQ;YAC1B,wBAAwB;YACxB,gBAAgB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,MAAM,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;YACnJ,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;SAC5E;QACD,aAAa,EAAE;YACb,cAAc,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAC,kBAAkB,IAAC,IAAI,EAAE,IAAI,GAAI,EAAE,EAAE,CAAC;YAC7E,WAAW;SACZ;KACF,CAAC;AACJ,CAAC;AAED,SAAS,8BAA8B,CACrC,UAAoB,EACpB,cAA4C,EAC5C,eAAqD,EACrD,aAAwC;IAExC,OAAO,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAC1B,qCAAqC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,CAAC;AAC9I,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAoB,EAAE,eAAqD,EAAE,QAAqB;IAC7H,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,EAA4B,CAAC;IAC/E,MAAM,EAAE,QAAQ,EAAE,yBAAyB,EAAE,GAAG,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAExG,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,GAAG,QAAQ,CAAkD,GAAG,EAAE,CAC7H,8BAA8B,CAAC,UAAU,EAAE,yBAAyB,EAAE,eAAe,EAAE,aAAa,CAAC,CACtG,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,2BAA2B,CAAC,GAAG,EAAE,CAAC,8BAA8B,CAAC,UAAU,EAAE,yBAAyB,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3I,CAAC,EAAE,CAAC,UAAU,EAAE,yBAAyB,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;IAE5E,OAAO;QACL,yBAAyB;QACzB,wBAAwB;QACxB,sBAAsB,EAAE,WAAW,CAAC,CAAC,KAA2C,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;KAClH,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CAAC,MAAe,EAAE,KAAoC,EAAE,gBAAkC;IAC7H,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,KAAK,KAAK,sBAAsB,EAAE,CAAC;YACrC,OAAO,KAAC,oBAAoB,IAAC,IAAI,EAAE,gBAAgB,GAAI,CAAC;QAC1D,CAAC;QACD,OAAO,KAAC,kBAAkB,IAAC,IAAI,EAAE,gBAAgB,GAAI,CAAC;IACxD,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,KAAC,eAAe,IAAC,IAAI,EAAE,gBAAgB,GAAI,CAAC;IACrD,CAAC;IACD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,OAAO,KAAC,gBAAgB,IAAC,IAAI,EAAE,WAAW,GAAI,CAAC;AACjD,CAAC;AAED,YAAY;AACZ,MAAM,UAAU,kBAAkB,CAAC,EAAE,IAAI,EAAuC;IAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,QAAQ,IAAI,CAAC,QAAQ,CAAC,YAAa,CAAC,OAAO,EAAE,CAAC;YAC5C,KAAK,aAAa;gBAChB,OAAO,WAAW,CAAC;YACrB,KAAK,qBAAqB;gBACxB,OAAO,cAAc,CAAC;YACxB,KAAK,2BAA2B;gBAC9B,OAAO,sBAAsB,CAAC;YAChC,KAAK,WAAW;gBACd,OAAO,UAAU,CAAC;YACpB,KAAK,eAAe;gBAClB,OAAO,QAAQ,CAAC;YAClB;gBACE,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,KAAC,IAAI,IAAC,IAAI,EAAE,OAAO,EAAE,GAAI,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,IAA+B;IAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;AACjD,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { Icon } from \"@stratakit/foundations\";\nimport categorySvg from \"@stratakit/icons/bis-category-3d.svg\";\nimport subcategorySvg from \"@stratakit/icons/bis-category-subcategory.svg\";\nimport classSvg from \"@stratakit/icons/bis-class.svg\";\nimport definitionContainerSvg from \"@stratakit/icons/bis-definitions-container.svg\";\nimport elementSvg from \"@stratakit/icons/bis-element.svg\";\nimport { EmptyTreeContent, FilterUnknownError, NoFilterMatches, TooManyFilterMatches } from \"../common/components/EmptyTree.js\";\nimport { CategoriesTreeDefinition, defaultHierarchyConfiguration } from \"./CategoriesTreeDefinition.js\";\nimport { createCategoriesTreeVisibilityHandler } from \"./internal/CategoriesTreeVisibilityHandler.js\";\nimport { useFilteredPaths } from \"./internal/UseFilteredPaths.js\";\nimport { useIdsCache } from \"./internal/UseIdsCache.js\";\n\nimport type { CategoriesTreeFilteringError } from \"./internal/UseFilteredPaths.js\";\nimport type { HierarchyFilteringPath } from \"@itwin/presentation-hierarchies\";\nimport type { CategoriesTreeIdsCache } from \"./internal/CategoriesTreeIdsCache.js\";\nimport type { ReactNode } from \"react\";\nimport type { Id64Array } from \"@itwin/core-bentley\";\nimport type { Viewport } from \"@itwin/core-frontend\";\nimport type { PresentationHierarchyNode } from \"@itwin/presentation-hierarchies-react\";\nimport type { VisibilityTreeProps } from \"../common/components/VisibilityTree.js\";\nimport type { VisibilityTreeRendererProps } from \"../common/components/VisibilityTreeRenderer.js\";\nimport type { CategoryInfo } from \"../common/CategoriesVisibilityUtils.js\";\nimport type { CategoriesTreeHierarchyConfiguration } from \"./CategoriesTreeDefinition.js\";\n\n/** @beta */\nexport interface UseCategoriesTreeProps {\n activeView: Viewport;\n onCategoriesFiltered?: (props: { categories: CategoryInfo[] | undefined; models?: Id64Array }) => void;\n filter?: string;\n emptyTreeContent?: ReactNode;\n hierarchyConfig?: Partial<CategoriesTreeHierarchyConfiguration>;\n}\n\n/** @beta */\ninterface UseCategoriesTreeResult {\n categoriesTreeProps: Pick<\n VisibilityTreeProps,\n \"treeName\" | \"getHierarchyDefinition\" | \"getFilteredPaths\" | \"visibilityHandlerFactory\" | \"highlight\" | \"emptyTreeContent\"\n >;\n rendererProps: Required<Pick<VisibilityTreeRendererProps, \"getDecorations\" | \"getSublabel\">>;\n}\n\n/**\n * Custom hook to create and manage state for the categories tree.\n * @beta\n */\nexport function useCategoriesTree({\n filter,\n activeView,\n onCategoriesFiltered,\n emptyTreeContent,\n hierarchyConfig,\n}: UseCategoriesTreeProps): UseCategoriesTreeResult {\n const hierarchyConfiguration = useMemo<CategoriesTreeHierarchyConfiguration>(\n () => ({\n ...defaultHierarchyConfiguration,\n ...hierarchyConfig,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n Object.values(hierarchyConfig ?? {}),\n );\n const viewType = activeView.view.is2d() ? \"2d\" : \"3d\";\n\n const { getCategoriesTreeIdsCache, visibilityHandlerFactory, onFilteredPathsChanged } = useCachedVisibility(activeView, hierarchyConfiguration, viewType);\n\n const getHierarchyDefinition = useCallback<VisibilityTreeProps[\"getHierarchyDefinition\"]>(\n (props) => {\n return new CategoriesTreeDefinition({ ...props, viewType, idsCache: getCategoriesTreeIdsCache(), hierarchyConfig: hierarchyConfiguration });\n },\n [viewType, getCategoriesTreeIdsCache, hierarchyConfiguration],\n );\n\n const { getPaths, filteringError } = useFilteredPaths({\n hierarchyConfiguration,\n filter,\n getCategoriesTreeIdsCache,\n onFilteredPathsChanged,\n viewType,\n onCategoriesFiltered,\n });\n\n return {\n categoriesTreeProps: {\n treeName: \"categories-tree-v2\",\n getHierarchyDefinition,\n getFilteredPaths: getPaths,\n visibilityHandlerFactory,\n emptyTreeContent: useMemo(() => getEmptyTreeContentComponent(filter, filteringError, emptyTreeContent), [filter, filteringError, emptyTreeContent]),\n highlight: useMemo(() => (filter ? { text: filter } : undefined), [filter]),\n },\n rendererProps: {\n getDecorations: useCallback((node) => <CategoriesTreeIcon node={node} />, []),\n getSublabel,\n },\n };\n}\n\nfunction createVisibilityHandlerFactory(\n activeView: Viewport,\n idsCacheGetter: () => CategoriesTreeIdsCache,\n hierarchyConfig: CategoriesTreeHierarchyConfiguration,\n filteredPaths?: HierarchyFilteringPath[],\n): VisibilityTreeProps[\"visibilityHandlerFactory\"] {\n return ({ imodelAccess }) =>\n createCategoriesTreeVisibilityHandler({ viewport: activeView, idsCache: idsCacheGetter(), imodelAccess, filteredPaths, hierarchyConfig });\n}\n\nfunction useCachedVisibility(activeView: Viewport, hierarchyConfig: CategoriesTreeHierarchyConfiguration, viewType: \"2d\" | \"3d\") {\n const [filteredPaths, setFilteredPaths] = useState<HierarchyFilteringPath[]>();\n const { getCache: getCategoriesTreeIdsCache } = useIdsCache(activeView.iModel, viewType, filteredPaths);\n\n const [visibilityHandlerFactory, setVisibilityHandlerFactory] = useState<VisibilityTreeProps[\"visibilityHandlerFactory\"]>(() =>\n createVisibilityHandlerFactory(activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths),\n );\n\n useEffect(() => {\n setVisibilityHandlerFactory(() => createVisibilityHandlerFactory(activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths));\n }, [activeView, getCategoriesTreeIdsCache, hierarchyConfig, filteredPaths]);\n\n return {\n getCategoriesTreeIdsCache,\n visibilityHandlerFactory,\n onFilteredPathsChanged: useCallback((paths: HierarchyFilteringPath[] | undefined) => setFilteredPaths(paths), []),\n };\n}\n\nfunction getEmptyTreeContentComponent(filter?: string, error?: CategoriesTreeFilteringError, emptyTreeContent?: React.ReactNode) {\n if (error) {\n if (error === \"tooManyFilterMatches\") {\n return <TooManyFilterMatches base={\"categoriesTree\"} />;\n }\n return <FilterUnknownError base={\"categoriesTree\"} />;\n }\n if (filter) {\n return <NoFilterMatches base={\"categoriesTree\"} />;\n }\n if (emptyTreeContent) {\n return emptyTreeContent;\n }\n return <EmptyTreeContent icon={categorySvg} />;\n}\n\n/** @beta */\nexport function CategoriesTreeIcon({ node }: { node: PresentationHierarchyNode }) {\n if (node.nodeData.extendedData?.imageId === undefined) {\n return undefined;\n }\n\n const getIcon = () => {\n switch (node.nodeData.extendedData!.imageId) {\n case \"icon-layers\":\n return categorySvg;\n case \"icon-layers-isolate\":\n return subcategorySvg;\n case \"icon-definition-container\":\n return definitionContainerSvg;\n case \"icon-item\":\n return elementSvg;\n case \"icon-ec-class\":\n return classSvg;\n default:\n return undefined;\n }\n };\n\n return <Icon href={getIcon()} />;\n}\n\nfunction getSublabel(node: PresentationHierarchyNode) {\n return node.nodeData.extendedData?.description;\n}\n"]}
1
+ {"version":3,"file":"UseCategoriesTree.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { createECSqlQueryExecutor } from \"@itwin/presentation-core-interop\";\nimport { Icon } from \"@stratakit/foundations\";\nimport categorySvg from \"@stratakit/icons/bis-category-3d.svg\";\nimport subcategorySvg from \"@stratakit/icons/bis-category-subcategory.svg\";\nimport classSvg from \"@stratakit/icons/bis-class.svg\";\nimport definitionContainerSvg from \"@stratakit/icons/bis-definitions-container.svg\";\nimport elementSvg from \"@stratakit/icons/bis-element.svg\";\nimport { EmptyTreeContent, FilterUnknownError, NoFilterMatches, TooManyFilterMatches } from \"../common/components/EmptyTree.js\";\nimport { useCachedVisibility } from \"../common/internal/useTreeHooks/UseCachedVisibility.js\";\nimport { useIdsCache } from \"../common/internal/useTreeHooks/UseIdsCache.js\";\nimport { CategoriesTreeDefinition, defaultHierarchyConfiguration } from \"./CategoriesTreeDefinition.js\";\nimport { CategoriesTreeIdsCache } from \"./internal/CategoriesTreeIdsCache.js\";\nimport { createCategoriesTreeVisibilityHandler } from \"./internal/CategoriesTreeVisibilityHandler.js\";\nimport { useFilteredPaths } from \"./internal/UseFilteredPaths.js\";\n\nimport type { CreateCacheProps } from \"../common/internal/useTreeHooks/UseIdsCache.js\";\nimport type { CreateFactoryProps } from \"../common/internal/useTreeHooks/UseCachedVisibility.js\";\nimport type { CategoriesTreeFilteringError } from \"./internal/UseFilteredPaths.js\";\nimport type { ReactNode } from \"react\";\nimport type { Id64Array } from \"@itwin/core-bentley\";\nimport type { Viewport } from \"@itwin/core-frontend\";\nimport type { PresentationHierarchyNode } from \"@itwin/presentation-hierarchies-react\";\nimport type { VisibilityTreeProps } from \"../common/components/VisibilityTree.js\";\nimport type { VisibilityTreeRendererProps } from \"../common/components/VisibilityTreeRenderer.js\";\nimport type { CategoryInfo } from \"../common/CategoriesVisibilityUtils.js\";\nimport type { CategoriesTreeHierarchyConfiguration } from \"./CategoriesTreeDefinition.js\";\n\n/** @beta */\nexport interface UseCategoriesTreeProps {\n activeView: Viewport;\n onCategoriesFiltered?: (props: { categories: CategoryInfo[] | undefined; models?: Id64Array }) => void;\n filter?: string;\n emptyTreeContent?: ReactNode;\n hierarchyConfig?: Partial<CategoriesTreeHierarchyConfiguration>;\n}\n\n/** @beta */\ninterface UseCategoriesTreeResult {\n categoriesTreeProps: Pick<\n VisibilityTreeProps,\n \"treeName\" | \"getHierarchyDefinition\" | \"getFilteredPaths\" | \"visibilityHandlerFactory\" | \"highlight\" | \"emptyTreeContent\"\n >;\n rendererProps: Required<Pick<VisibilityTreeRendererProps, \"getDecorations\" | \"getSublabel\">>;\n}\n\n/**\n * Custom hook to create and manage state for the categories tree.\n * @beta\n */\nexport function useCategoriesTree({\n filter,\n activeView,\n onCategoriesFiltered,\n emptyTreeContent,\n hierarchyConfig,\n}: UseCategoriesTreeProps): UseCategoriesTreeResult {\n const hierarchyConfiguration = useMemo<CategoriesTreeHierarchyConfiguration>(\n () => ({\n ...defaultHierarchyConfiguration,\n ...hierarchyConfig,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n Object.values(hierarchyConfig ?? {}),\n );\n const viewType = activeView.view.is2d() ? \"2d\" : \"3d\";\n\n const { getCache: getCategoriesTreeIdsCache } = useIdsCache<CategoriesTreeIdsCache, { viewType: \"2d\" | \"3d\" }>({\n imodel: activeView.iModel,\n createCache,\n cacheSpecificProps: useMemo(() => ({ viewType }), [viewType]),\n });\n\n const { visibilityHandlerFactory, onFilteredPathsChanged } = useCategoriesCachedVisibility({\n activeView,\n getCache: getCategoriesTreeIdsCache,\n hierarchyConfig: hierarchyConfiguration,\n });\n\n const getHierarchyDefinition = useCallback<VisibilityTreeProps[\"getHierarchyDefinition\"]>(\n (props) => {\n return new CategoriesTreeDefinition({ ...props, viewType, idsCache: getCategoriesTreeIdsCache(), hierarchyConfig: hierarchyConfiguration });\n },\n [viewType, getCategoriesTreeIdsCache, hierarchyConfiguration],\n );\n\n const { getPaths, filteringError } = useFilteredPaths({\n hierarchyConfiguration,\n filter,\n getCategoriesTreeIdsCache,\n onFilteredPathsChanged,\n viewType,\n onCategoriesFiltered,\n });\n\n return {\n categoriesTreeProps: {\n treeName: \"categories-tree-v2\",\n getHierarchyDefinition,\n getFilteredPaths: getPaths,\n visibilityHandlerFactory,\n emptyTreeContent: useMemo(() => getEmptyTreeContentComponent(filter, filteringError, emptyTreeContent), [filter, filteringError, emptyTreeContent]),\n highlight: useMemo(() => (filter ? { text: filter } : undefined), [filter]),\n },\n rendererProps: {\n getDecorations: useCallback((node) => <CategoriesTreeIcon node={node} />, []),\n getSublabel,\n },\n };\n}\n\nfunction createVisibilityHandlerFactory(\n props: CreateFactoryProps<CategoriesTreeIdsCache, { hierarchyConfig: CategoriesTreeHierarchyConfiguration }>,\n): VisibilityTreeProps[\"visibilityHandlerFactory\"] {\n const { activeView, factoryProps, idsCacheGetter, filteredPaths } = props;\n return ({ imodelAccess }) =>\n createCategoriesTreeVisibilityHandler({\n viewport: activeView,\n idsCache: idsCacheGetter(),\n imodelAccess,\n filteredPaths,\n hierarchyConfig: factoryProps.hierarchyConfig,\n });\n}\n\nfunction getEmptyTreeContentComponent(filter?: string, error?: CategoriesTreeFilteringError, emptyTreeContent?: React.ReactNode) {\n if (error) {\n if (error === \"tooManyFilterMatches\") {\n return <TooManyFilterMatches base={\"categoriesTree\"} />;\n }\n return <FilterUnknownError base={\"categoriesTree\"} />;\n }\n if (filter) {\n return <NoFilterMatches base={\"categoriesTree\"} />;\n }\n if (emptyTreeContent) {\n return emptyTreeContent;\n }\n return <EmptyTreeContent icon={categorySvg} />;\n}\n\n/** @beta */\nexport function CategoriesTreeIcon({ node }: { node: PresentationHierarchyNode }) {\n if (node.nodeData.extendedData?.imageId === undefined) {\n return undefined;\n }\n\n const getIcon = () => {\n switch (node.nodeData.extendedData!.imageId) {\n case \"icon-layers\":\n return categorySvg;\n case \"icon-layers-isolate\":\n return subcategorySvg;\n case \"icon-definition-container\":\n return definitionContainerSvg;\n case \"icon-item\":\n return elementSvg;\n case \"icon-ec-class\":\n return classSvg;\n default:\n return undefined;\n }\n };\n\n return <Icon href={getIcon()} />;\n}\n\nfunction getSublabel(node: PresentationHierarchyNode) {\n return node.nodeData.extendedData?.description;\n}\n\nfunction useCategoriesCachedVisibility(props: {\n activeView: Viewport;\n getCache: () => CategoriesTreeIdsCache;\n hierarchyConfig: CategoriesTreeHierarchyConfiguration;\n}) {\n const { activeView, getCache, hierarchyConfig } = props;\n const { visibilityHandlerFactory, filteredPaths, onFilteredPathsChanged } = useCachedVisibility<\n CategoriesTreeIdsCache,\n { hierarchyConfig: CategoriesTreeHierarchyConfiguration }\n >({\n activeView,\n getCache,\n factoryProps: useMemo(() => ({ hierarchyConfig }), [hierarchyConfig]),\n createFactory: createVisibilityHandlerFactory,\n });\n\n useEffect(() => {\n getCache().clearFilteredElementsModels();\n }, [filteredPaths, getCache]);\n\n return {\n visibilityHandlerFactory,\n onFilteredPathsChanged,\n };\n}\n\nfunction createCache(props: CreateCacheProps<{ viewType: \"2d\" | \"3d\" }>) {\n return new CategoriesTreeIdsCache(createECSqlQueryExecutor(props.imodel), props.specificProps.viewType);\n}\n"]}
@@ -13,16 +13,6 @@ export interface ClassificationsTreeHierarchyConfiguration {
13
13
  * root `ClassificationSystem`.
14
14
  */
15
15
  rootClassificationSystemCode: string;
16
- /**
17
- * In case consumer knows the name of relationship between a `Classification` and a `Category`, it can be provided
18
- * here. With this relationship, Categories for a given Classification can be loaded directly, without going through
19
- * geometric elements. That has a couple of effects:
20
- * - Performance is better, as it allows us to avoid scanning all elements under specific Classification.
21
- * - Categories related to a Classification are displayed, even if they don't have any elements assigned to them.
22
- *
23
- * It's expected that source of the relationship is `BisCore.Category` and target - `ClassificationSystems.Classification`.
24
- */
25
- categorySymbolizesClassificationRelationshipName?: string;
26
16
  }
27
17
  /** @internal */
28
18
  export declare class ClassificationsTreeDefinition implements HierarchyDefinition {