@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.
- package/CHANGELOG.md +25 -1
- package/README.md +133 -35
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +43 -18
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +0 -10
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +54 -132
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js +2 -6
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +20 -14
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +11 -10
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +61 -48
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +0 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js +0 -4
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js +25 -21
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +26 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +20 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +17 -0
- package/lib/esm/tree-widget-react/components/trees/{models-tree/internal → common/internal/useTreeHooks}/UseIdsCache.js +10 -11
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +27 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +28 -18
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +3 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
- package/package.json +28 -34
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.d.ts +0 -8
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js +0 -48
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseIdsCache.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.d.ts +0 -8
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.js +0 -45
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseIdsCache.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseIdsCache.d.ts +0 -8
- 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
|
|
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
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
<
|
|
221
|
-
{
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
|
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
|
|
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(
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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":"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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, 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 {
|