@itwin/tree-widget-react 3.0.0-dev.6 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -1
- package/README.md +358 -240
- package/lib/cjs/components/trees/categories-tree/CategoriesTree.d.ts +6 -13
- package/lib/cjs/components/trees/categories-tree/CategoriesTree.js +2 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTree.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeButtons.d.ts +20 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeButtons.js +20 -2
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeComponent.d.ts +7 -8
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeComponent.js +2 -2
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +2 -2
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeDefinition.js +6 -3
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/UseCategoriesTree.d.ts +7 -10
- package/lib/cjs/components/trees/categories-tree/UseCategoriesTree.js +30 -3
- package/lib/cjs/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/cjs/components/trees/common/UseHierarchiesLocalization.d.ts +3 -3
- package/lib/cjs/components/trees/common/UseHierarchiesLocalization.js.map +1 -1
- package/lib/cjs/components/trees/common/UseHierarchyVisibility.d.ts +20 -0
- package/lib/cjs/components/trees/common/UseHierarchyVisibility.js +11 -1
- package/lib/cjs/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/cjs/components/trees/common/UseIModelChangeListener.js +1 -1
- package/lib/cjs/components/trees/common/UseIModelChangeListener.js.map +1 -1
- package/lib/cjs/components/trees/common/Utils.d.ts +3 -0
- package/lib/cjs/components/trees/common/Utils.js +1 -0
- package/lib/cjs/components/trees/common/Utils.js.map +1 -1
- package/lib/cjs/components/trees/common/components/Tree.d.ts +8 -21
- package/lib/cjs/components/trees/common/components/Tree.js +5 -4
- package/lib/cjs/components/trees/common/components/Tree.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeNodeRenderer.d.ts +2 -5
- package/lib/cjs/components/trees/common/components/TreeNodeRenderer.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeRenderer.d.ts +3 -10
- package/lib/cjs/components/trees/common/components/TreeRenderer.js +2 -2
- package/lib/cjs/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeRenderer.scss +0 -8
- package/lib/cjs/components/trees/common/components/VisibilityTree.d.ts +7 -17
- package/lib/cjs/components/trees/common/components/VisibilityTree.js.map +1 -1
- package/lib/cjs/components/trees/common/components/VisibilityTreeRenderer.d.ts +4 -5
- package/lib/cjs/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +3 -8
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTreeComponent.d.ts +3 -3
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +8 -5
- package/lib/cjs/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTree.d.ts +3 -8
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +3 -3
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +2 -1
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +17 -14
- package/lib/cjs/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTree.d.ts +6 -12
- package/lib/cjs/components/trees/models-tree/ModelsTree.js +9 -2
- package/lib/cjs/components/trees/models-tree/ModelsTree.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeButtons.d.ts +24 -3
- package/lib/cjs/components/trees/models-tree/ModelsTreeButtons.js +23 -3
- package/lib/cjs/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.d.ts +10 -11
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.js +2 -2
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeDefinition.d.ts +5 -2
- package/lib/cjs/components/trees/models-tree/ModelsTreeDefinition.js +13 -10
- package/lib/cjs/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/UseModelsTree.d.ts +10 -13
- package/lib/cjs/components/trees/models-tree/UseModelsTree.js +42 -3
- package/lib/cjs/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +21 -45
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +12 -35
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTree.d.ts +6 -13
- package/lib/esm/components/trees/categories-tree/CategoriesTree.js +2 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTree.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTreeButtons.d.ts +20 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTreeButtons.js +21 -3
- package/lib/esm/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTreeComponent.d.ts +7 -8
- package/lib/esm/components/trees/categories-tree/CategoriesTreeComponent.js +2 -2
- package/lib/esm/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +2 -2
- package/lib/esm/components/trees/categories-tree/CategoriesTreeDefinition.js +7 -4
- package/lib/esm/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/UseCategoriesTree.d.ts +7 -10
- package/lib/esm/components/trees/categories-tree/UseCategoriesTree.js +30 -3
- package/lib/esm/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/esm/components/trees/common/UseHierarchiesLocalization.d.ts +3 -3
- package/lib/esm/components/trees/common/UseHierarchiesLocalization.js.map +1 -1
- package/lib/esm/components/trees/common/UseHierarchyVisibility.d.ts +20 -0
- package/lib/esm/components/trees/common/UseHierarchyVisibility.js +10 -1
- package/lib/esm/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/esm/components/trees/common/UseIModelChangeListener.js +1 -1
- package/lib/esm/components/trees/common/UseIModelChangeListener.js.map +1 -1
- package/lib/esm/components/trees/common/Utils.d.ts +3 -0
- package/lib/esm/components/trees/common/Utils.js +1 -0
- package/lib/esm/components/trees/common/Utils.js.map +1 -1
- package/lib/esm/components/trees/common/components/Tree.d.ts +8 -21
- package/lib/esm/components/trees/common/components/Tree.js +7 -6
- package/lib/esm/components/trees/common/components/Tree.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeNodeRenderer.d.ts +2 -5
- package/lib/esm/components/trees/common/components/TreeNodeRenderer.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeRenderer.d.ts +3 -10
- package/lib/esm/components/trees/common/components/TreeRenderer.js +2 -2
- package/lib/esm/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeRenderer.scss +0 -8
- package/lib/esm/components/trees/common/components/VisibilityTree.d.ts +7 -17
- package/lib/esm/components/trees/common/components/VisibilityTree.js.map +1 -1
- package/lib/esm/components/trees/common/components/VisibilityTreeRenderer.d.ts +4 -5
- package/lib/esm/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +3 -8
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTreeComponent.d.ts +3 -3
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +9 -6
- package/lib/esm/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTree.d.ts +3 -8
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +3 -3
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +2 -1
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +18 -15
- package/lib/esm/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTree.d.ts +6 -12
- package/lib/esm/components/trees/models-tree/ModelsTree.js +9 -2
- package/lib/esm/components/trees/models-tree/ModelsTree.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTreeButtons.d.ts +24 -3
- package/lib/esm/components/trees/models-tree/ModelsTreeButtons.js +23 -3
- package/lib/esm/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.d.ts +10 -11
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.js +2 -2
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTreeDefinition.d.ts +5 -2
- package/lib/esm/components/trees/models-tree/ModelsTreeDefinition.js +14 -11
- package/lib/esm/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/esm/components/trees/models-tree/UseModelsTree.d.ts +10 -13
- package/lib/esm/components/trees/models-tree/UseModelsTree.js +43 -4
- package/lib/esm/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +21 -45
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +13 -36
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/package.json +34 -32
package/README.md
CHANGED
|
@@ -12,9 +12,9 @@ The new `3.0` version of the package contains a few notable changes, compared to
|
|
|
12
12
|
|
|
13
13
|
- To allow easier customization of widget placement, the package now delivers a `createTreeWidget()` function that creates a tree widget definition, instead of a full `UiItemsProvider` implementation. See [Usage](#usage) section for details on how to use the new function.
|
|
14
14
|
|
|
15
|
-
- The underlying engine for building hierarchies has been changed from `@itwin/presentation-components` to `@itwin/presentation-hierarchies-react`. This is a significant change as the new library runs plain ECSQL queries and handles hierarchy creation on the frontend, as opposed to the previous version that relied on the backend to provide hierarchy data. This change allows this package to use more optimal queries and to be more flexible in terms of hierarchy creation.
|
|
15
|
+
- The underlying engine for building hierarchies has been changed from `@itwin/presentation-components` to `@itwin/presentation-hierarchies-react`. This is a significant change as the new library runs plain ECSQL queries and handles hierarchy creation on the frontend, as opposed to the previous version that relied on the backend to provide hierarchy data. This change allows this package to use more optimal queries and to be more flexible in terms of hierarchy creation. As a result, we're seeing 30-40% performance improvement for loading nodes in the Models tree when using a web backend and orders of magnitude improvement when using a local backend (desktop & mobile case).
|
|
16
16
|
|
|
17
|
-
This change adds a requirement for all tree components in this package to access iModels' metadata, which is achieved through a required `getSchemaContext` prop. See [Creating schema context](#creating-schema-context) section for an example implementation of this function.
|
|
17
|
+
This change adds a requirement for all tree components in this package to access iModels' metadata, which is achieved through a required `getSchemaContext` prop. See [Creating schema context](#creating-schema-context) section for an example implementation of this function. This also adds an `@itwin/ecschema-metadata` peer dependency on version `^4.0.0`.
|
|
18
18
|
|
|
19
19
|
In addition, the new tree components don't rely on the global selection manager provided by `@itwin/presentation-frontend` package. Instead, they require a unified selection storage object created using `createStorage()` function from `@itwin/unified-selection` package. See sections of individual tree components for how to supply it to them, and [Creating unified selection storage](#creating-unified-selection-storage) section for an example for how to create the storage.
|
|
20
20
|
|
|
@@ -24,11 +24,16 @@ The new `3.0` version of the package contains a few notable changes, compared to
|
|
|
24
24
|
| ----------------------------------------------- | ----------------------------------------------- |
|
|
25
25
|
|  |  |
|
|
26
26
|
|
|
27
|
+
This change introduces an `@itwin/itwinui-react` peer dependency on version `^3.11.0`.
|
|
28
|
+
|
|
27
29
|
- The tree components now have hierarchy level size limiting and filtering features always turned on. The features were already available in `2.x` versions, but were not enabled by default. See [Hierarchy level size limiting](#hierarchy-level-size-limiting) and [Hierarchy level filtering](#hierarchy-level-filtering) sections for more details.
|
|
28
30
|
|
|
31
|
+
- Behavior of header buttons like "Show all", "Hide all", etc. has been changed in filtered hierarchies' case. Previously they applied the visibility change on everything, no matter if the hierarchy is filtered or not. Now, when a hierarchy is filtered, only the nodes in the filtered hierarchy are affected.
|
|
32
|
+
|
|
29
33
|
- Models tree:
|
|
30
34
|
- The label filtering feature has been expanded to filter not only up to Models, but the whole hierarchy. This allows filtering the hierarchy to additionally find Category or Element nodes.
|
|
31
35
|
- [Focus mode](#focus-mode) feature has been added to allow automatic hierarchy filtering as the application selection changes.
|
|
36
|
+
- In addition to the two filtering-related improvements above, we now allow displaying a subset of the tree by providing a `getFilteredPaths` function. See [Displaying a subset of the tree](#displaying-a-subset-of-the-tree) section for more details.
|
|
32
37
|
- Display states' control has been modified to be hierarchy based. This means that changing display state of something deep in the hierarchy affects checkbox state of all its ancestors. And vice versa - changing display state of an ancestor affects all its descendants.
|
|
33
38
|
|
|
34
39
|
## Usage
|
|
@@ -37,50 +42,56 @@ Typically, the package is used with an [AppUI](https://github.com/iTwin/appui/tr
|
|
|
37
42
|
|
|
38
43
|
In any case, **before** using any APIs or components delivered with the package, it needs to be initialized:
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
<!-- [[include: [TreeWidget.TreeWidgetInitializeImports, TreeWidget.TreeWidgetInitialize], tsx]] -->
|
|
46
|
+
<!-- BEGIN EXTRACTION -->
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
42
49
|
import { TreeWidget } from "@itwin/tree-widget-react";
|
|
50
|
+
import { IModelApp } from "@itwin/core-frontend";
|
|
43
51
|
|
|
44
52
|
await TreeWidget.initialize(IModelApp.localization);
|
|
45
53
|
```
|
|
46
54
|
|
|
55
|
+
<!-- END EXTRACTION -->
|
|
56
|
+
|
|
47
57
|
In [AppUI](https://github.com/iTwin/appui/tree/master/ui/appui-react) based applications widgets are typically provided using `UiItemsProvider` implementations. The `@itwin/tree-widget-react` package delivers `createTreeWidget` function that can be used to add the tree widget to UI through a `UiItemsProvider`:
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
<!-- [[include: [TreeWidget.RegisterExampleImports, TreeWidget.RegisterExample], tsx]] -->
|
|
60
|
+
<!-- BEGIN EXTRACTION -->
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
50
63
|
import { UiItemsManager } from "@itwin/appui-react";
|
|
51
64
|
import { createTreeWidget, ModelsTreeComponent } from "@itwin/tree-widget-react";
|
|
52
65
|
|
|
53
66
|
UiItemsManager.register({
|
|
54
67
|
id: "tree-widget-provider",
|
|
55
|
-
getWidgets: () =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
id:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
}),
|
|
80
|
-
],
|
|
68
|
+
getWidgets: () =>
|
|
69
|
+
[
|
|
70
|
+
createTreeWidget({
|
|
71
|
+
trees: [
|
|
72
|
+
// add a custom component
|
|
73
|
+
{ id: "my-tree-id", startIcon: <svg />, getLabel: () => "My Custom Tree", render: () => <>This is my custom tree.</> },
|
|
74
|
+
// add the Models tree component delivered with the package
|
|
75
|
+
{
|
|
76
|
+
id: ModelsTreeComponent.id,
|
|
77
|
+
getLabel: () => ModelsTreeComponent.getLabel(),
|
|
78
|
+
render: (props) => (
|
|
79
|
+
<ModelsTreeComponent
|
|
80
|
+
// see "Creating schema context" section for example implementation
|
|
81
|
+
getSchemaContext={getSchemaContext}
|
|
82
|
+
// see "Creating unified selection storage" section for example implementation
|
|
83
|
+
selectionStorage={unifiedSelectionStorage}
|
|
84
|
+
/>
|
|
85
|
+
),
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
}),
|
|
89
|
+
] as readonly Widget[],
|
|
81
90
|
});
|
|
82
91
|
```
|
|
83
92
|
|
|
93
|
+
<!-- END EXTRACTION -->
|
|
94
|
+
|
|
84
95
|
As seen in the above code snippet, `createTreeWidget` takes a list of trees that are displayed in the widget. This package delivers a number of tree components for everyone's use (see below), but providing custom trees is also an option.
|
|
85
96
|
|
|
86
97
|
## Components
|
|
@@ -99,44 +110,30 @@ The component renders a tree that tries to replicate how a typical "Models" tree
|
|
|
99
110
|
|
|
100
111
|
Typical usage:
|
|
101
112
|
|
|
113
|
+
<!-- [[include: [TreeWidget.ModelsTreeExampleImports, TreeWidget.ModelsTreeExample], tsx]] -->
|
|
114
|
+
<!-- BEGIN EXTRACTION -->
|
|
115
|
+
|
|
102
116
|
```tsx
|
|
103
|
-
import { IModelConnection } from "@itwin/core-frontend";
|
|
104
|
-
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
105
|
-
import { SelectionStorage } from "@itwin/unified-selection";
|
|
106
117
|
import { ModelsTreeComponent } from "@itwin/tree-widget-react";
|
|
107
118
|
|
|
108
|
-
// The Models tree requires a unified selection storage to support selection synchronization with the
|
|
109
|
-
// application. The storage should be created once per application and shared across multiple selection-enabled
|
|
110
|
-
// components.
|
|
111
|
-
function getUnifiedSelectionStorage(): SelectionStorage {
|
|
112
|
-
// see "Creating unified selection storage" section for example implementation
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Schema context is used by Models tree to access iModels metadata. Similar to selection storage, it should be
|
|
116
|
-
// created once per application and shared across multiple components.
|
|
117
|
-
function getSchemaContext(imodel: IModelConnection): SchemaContext {
|
|
118
|
-
// see "Creating schema context" section for example implementation
|
|
119
|
-
}
|
|
120
|
-
|
|
121
119
|
function MyWidget() {
|
|
122
120
|
return (
|
|
123
121
|
<ModelsTreeComponent
|
|
122
|
+
// see "Creating schema context" section for example implementation
|
|
124
123
|
getSchemaContext={getSchemaContext}
|
|
125
|
-
|
|
124
|
+
// see "Creating unified selection storage" section for example implementation
|
|
125
|
+
selectionStorage={unifiedSelectionStorage}
|
|
126
126
|
headerButtons={[
|
|
127
|
-
(props) => <ModelsTreeComponent.ShowAllButton {...props} />,
|
|
128
|
-
(props) => <ModelsTreeComponent.HideAllButton {...props} />,
|
|
129
|
-
(props) => <MyCustomButton />,
|
|
127
|
+
(props) => <ModelsTreeComponent.ShowAllButton {...props} key={"ShowAllButton"} />,
|
|
128
|
+
(props) => <ModelsTreeComponent.HideAllButton {...props} key={"HideAllButton"} />,
|
|
130
129
|
]}
|
|
131
|
-
selectionMode={"extended"}
|
|
132
|
-
hierarchyConfig={{
|
|
133
|
-
elementClassGrouping: "enable",
|
|
134
|
-
}}
|
|
135
130
|
/>
|
|
136
131
|
);
|
|
137
132
|
}
|
|
138
133
|
```
|
|
139
134
|
|
|
135
|
+
<!-- END EXTRACTION -->
|
|
136
|
+
|
|
140
137
|
Available header buttons:
|
|
141
138
|
|
|
142
139
|
- `ModelsTreeComponent.ShowAllButton` makes everything in the iModel displayed.
|
|
@@ -161,13 +158,48 @@ This package provides building blocks for custom models tree:
|
|
|
161
158
|
|
|
162
159
|
Example:
|
|
163
160
|
|
|
161
|
+
<!-- [[include: [TreeWidget.CustomModelsTreeExampleImports, TreeWidget.CustomModelsTreeExample], tsx]] -->
|
|
162
|
+
<!-- BEGIN EXTRACTION -->
|
|
163
|
+
|
|
164
164
|
```tsx
|
|
165
|
+
import { TreeWithHeader, useModelsTree, useModelsTreeButtonProps, VisibilityTree, VisibilityTreeRenderer } from "@itwin/tree-widget-react";
|
|
166
|
+
import type { SelectionStorage } from "@itwin/unified-selection";
|
|
167
|
+
import type { IModelConnection, Viewport } from "@itwin/core-frontend";
|
|
168
|
+
import type { SchemaContext } from "@itwin/ecschema-metadata";
|
|
169
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
170
|
+
|
|
171
|
+
type VisibilityTreeRendererProps = ComponentPropsWithoutRef<typeof VisibilityTreeRenderer>;
|
|
172
|
+
type CustomModelsTreeRendererProps = Parameters<ComponentPropsWithoutRef<typeof VisibilityTree>["treeRenderer"]>[0];
|
|
173
|
+
function CustomModelsTreeRenderer(props: CustomModelsTreeRendererProps) {
|
|
174
|
+
const getLabel = props.getLabel;
|
|
175
|
+
const getLabelCallback = useCallback<Required<VisibilityTreeRendererProps>["getLabel"]>(
|
|
176
|
+
(node) => {
|
|
177
|
+
const originalLabel = getLabel(node);
|
|
178
|
+
return <>Custom node - {originalLabel}</>;
|
|
179
|
+
},
|
|
180
|
+
[getLabel],
|
|
181
|
+
);
|
|
182
|
+
return <VisibilityTreeRenderer {...props} getLabel={getLabelCallback} getSublabel={getSublabel} />;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface CustomModelsTreeProps {
|
|
186
|
+
imodel: IModelConnection;
|
|
187
|
+
viewport: Viewport;
|
|
188
|
+
getSchemaContext: (imodel: IModelConnection) => SchemaContext;
|
|
189
|
+
selectionStorage: SelectionStorage;
|
|
190
|
+
}
|
|
191
|
+
|
|
165
192
|
function CustomModelsTreeComponent({ imodel, viewport, getSchemaContext, selectionStorage }: CustomModelsTreeProps) {
|
|
166
|
-
const buttonProps = useModelsTreeButtonProps({ imodel, viewport });
|
|
193
|
+
const { buttonProps } = useModelsTreeButtonProps({ imodel, viewport });
|
|
167
194
|
const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport });
|
|
168
195
|
|
|
169
196
|
return (
|
|
170
|
-
<TreeWithHeader
|
|
197
|
+
<TreeWithHeader
|
|
198
|
+
buttons={[
|
|
199
|
+
<ModelsTreeComponent.ShowAllButton {...buttonProps} key={"ShowAllButton"} />,
|
|
200
|
+
<ModelsTreeComponent.HideAllButton {...buttonProps} key={"HideAllButton"} />,
|
|
201
|
+
]}
|
|
202
|
+
>
|
|
171
203
|
<VisibilityTree
|
|
172
204
|
{...modelsTreeProps}
|
|
173
205
|
getSchemaContext={getSchemaContext}
|
|
@@ -178,49 +210,54 @@ function CustomModelsTreeComponent({ imodel, viewport, getSchemaContext, selecti
|
|
|
178
210
|
</TreeWithHeader>
|
|
179
211
|
);
|
|
180
212
|
}
|
|
181
|
-
|
|
182
|
-
type VisibilityTreeRendererProps = ComponentPropsWithoutRef<typeof VisibilityTreeRenderer>;
|
|
183
|
-
type CustomModelsTreeRendererProps = Parameters<ComponentPropsWithoutRef<typeof VisibilityTree>["treeRenderer"]>[0];
|
|
184
|
-
|
|
185
|
-
function CustomModelsTreeRenderer(props: CustomModelsTreeRendererProps) {
|
|
186
|
-
const getLabel = useCallback<Required<VisibilityTreeRendererProps>["getLabel"]>(
|
|
187
|
-
(node) => {
|
|
188
|
-
const originalLabel = props.getLabel(node);
|
|
189
|
-
return <>Custom node - {originalLabel}</>;
|
|
190
|
-
},
|
|
191
|
-
[props.getLabel],
|
|
192
|
-
);
|
|
193
|
-
return <VisibilityTreeRenderer {...props} getLabel={getLabel} getSublabel={getSublabel} />;
|
|
194
|
-
}
|
|
195
213
|
```
|
|
196
214
|
|
|
215
|
+
<!-- END EXTRACTION -->
|
|
216
|
+
|
|
197
217
|
#### Displaying a subset of the tree
|
|
198
218
|
|
|
199
219
|
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`:
|
|
200
220
|
|
|
221
|
+
<!-- [[include: [TreeWidget.GetFilteredPathsComponentExample], tsx]] -->
|
|
222
|
+
<!-- BEGIN EXTRACTION -->
|
|
223
|
+
|
|
201
224
|
```tsx
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
```
|
|
225
|
+
type UseModelsTreeProps = Parameters<typeof useModelsTree>[0];
|
|
226
|
+
type GetFilteredPathsType = Exclude<UseModelsTreeProps["getFilteredPaths"], undefined>;
|
|
227
|
+
interface CustomModelsTreeProps {
|
|
228
|
+
viewport: Viewport;
|
|
229
|
+
selectionStorage: SelectionStorage;
|
|
230
|
+
imodel: IModelConnection;
|
|
231
|
+
targetItems: InstanceKey[];
|
|
232
|
+
}
|
|
211
233
|
|
|
212
|
-
|
|
234
|
+
function CustomModelsTreeComponent({ viewport, selectionStorage, imodel, targetItems }: CustomModelsTreeProps) {
|
|
235
|
+
const getFilteredPaths = useCallback<GetFilteredPathsType>(
|
|
236
|
+
async ({ createInstanceKeyPaths }) => {
|
|
237
|
+
return createInstanceKeyPaths({
|
|
238
|
+
// list of instance keys representing nodes that should be displayed in the hierarchy
|
|
239
|
+
targetItems,
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
[targetItems],
|
|
243
|
+
);
|
|
213
244
|
|
|
214
|
-
|
|
245
|
+
const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
|
|
215
246
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
247
|
+
return (
|
|
248
|
+
<VisibilityTree
|
|
249
|
+
{...modelsTreeProps}
|
|
250
|
+
getSchemaContext={getSchemaContext}
|
|
251
|
+
selectionStorage={selectionStorage}
|
|
252
|
+
imodel={imodel}
|
|
253
|
+
treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
|
|
254
|
+
/>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
222
257
|
```
|
|
223
258
|
|
|
259
|
+
<!-- END EXTRACTION -->
|
|
260
|
+
|
|
224
261
|
### Categories tree
|
|
225
262
|
|
|
226
263
|
The component, based on the active view, renders a hierarchy of either spatial (3d) or drawing (2d) categories. The hierarchy consists of two levels - the category (spatial or drawing) and its sub-categories. There's also a header that renders categories search box and various visibility control buttons.
|
|
@@ -229,40 +266,27 @@ The component, based on the active view, renders a hierarchy of either spatial (
|
|
|
229
266
|
|
|
230
267
|
Typical usage:
|
|
231
268
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
235
|
-
import { SelectionStorage } from "@itwin/unified-selection";
|
|
236
|
-
import { CategoriesTreeComponent, CategoriesTreeComponent } from "@itwin/tree-widget-react";
|
|
237
|
-
|
|
238
|
-
// The Categories tree requires a unified selection storage to support selection synchronization with the
|
|
239
|
-
// application. The storage should be created once per application and shared across multiple selection-enabled
|
|
240
|
-
// components.
|
|
241
|
-
function getUnifiedSelectionStorage(): SelectionStorage {
|
|
242
|
-
// see "Creating unified selection storage" section for example implementation
|
|
243
|
-
}
|
|
269
|
+
<!-- [[include: [TreeWidget.CategoriesTreeExampleImports, TreeWidget.CategoriesTreeExample], tsx]] -->
|
|
270
|
+
<!-- BEGIN EXTRACTION -->
|
|
244
271
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
function getSchemaContext(imodel: IModelConnection): SchemaContext {
|
|
248
|
-
// see "Creating schema context" section for example implementation
|
|
249
|
-
}
|
|
272
|
+
```tsx
|
|
273
|
+
import { CategoriesTreeComponent } from "@itwin/tree-widget-react";
|
|
250
274
|
|
|
251
275
|
function MyWidget() {
|
|
252
276
|
return (
|
|
253
277
|
<CategoriesTreeComponent
|
|
278
|
+
// see "Creating schema context" section for example implementation
|
|
254
279
|
getSchemaContext={getSchemaContext}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
(props) => <CategoriesTreeComponent.HideAllButton {...props} />,
|
|
259
|
-
(props) => <MyCustomButton />,
|
|
260
|
-
]}
|
|
280
|
+
// see "Creating unified selection storage" section for example implementation
|
|
281
|
+
selectionStorage={unifiedSelectionStorage}
|
|
282
|
+
headerButtons={[(props) => <CategoriesTreeComponent.ShowAllButton {...props} />, (props) => <CategoriesTreeComponent.HideAllButton {...props} />]}
|
|
261
283
|
/>
|
|
262
284
|
);
|
|
263
285
|
}
|
|
264
286
|
```
|
|
265
287
|
|
|
288
|
+
<!-- END EXTRACTION -->
|
|
289
|
+
|
|
266
290
|
Available header buttons:
|
|
267
291
|
|
|
268
292
|
- `ModelsTreeComponent.ShowAllButton` makes all categories and their subcategories displayed.
|
|
@@ -278,44 +302,68 @@ This package provides building blocks for custom categories tree:
|
|
|
278
302
|
|
|
279
303
|
Example:
|
|
280
304
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const buttonProps = useCategoriesTreeButtonProps({ imodel, viewport });
|
|
284
|
-
const { categoriesTreeProps, rendererProps } = useCategoriesTree({ activeView: viewport });
|
|
305
|
+
<!-- [[include: [TreeWidget.CustomCategoriesTreeExampleImports, TreeWidget.CustomCategoriesTreeExample], tsx]] -->
|
|
306
|
+
<!-- BEGIN EXTRACTION -->
|
|
285
307
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
imodel={imodel}
|
|
293
|
-
treeRenderer={(props) => <CustomCategoriesTreeRenderer {...props} {...rendererProps} />}
|
|
294
|
-
/>
|
|
295
|
-
</TreeWithHeader>
|
|
296
|
-
);
|
|
297
|
-
}
|
|
308
|
+
```tsx
|
|
309
|
+
import { TreeWithHeader, useCategoriesTree, useCategoriesTreeButtonProps, VisibilityTree, VisibilityTreeRenderer } from "@itwin/tree-widget-react";
|
|
310
|
+
import type { IModelConnection, Viewport } from "@itwin/core-frontend";
|
|
311
|
+
import type { SelectionStorage } from "@itwin/unified-selection";
|
|
312
|
+
import type { SchemaContext } from "@itwin/ecschema-metadata";
|
|
313
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
298
314
|
|
|
299
315
|
type VisibilityTreeRendererProps = ComponentPropsWithoutRef<typeof VisibilityTreeRenderer>;
|
|
300
316
|
type CustomCategoriesTreeRendererProps = Parameters<ComponentPropsWithoutRef<typeof VisibilityTree>["treeRenderer"]>[0];
|
|
301
317
|
|
|
302
318
|
function CustomCategoriesTreeRenderer(props: CustomCategoriesTreeRendererProps) {
|
|
303
|
-
const getLabel =
|
|
319
|
+
const getLabel = props.getLabel;
|
|
320
|
+
const getLabelCallback = useCallback<Required<VisibilityTreeRendererProps>["getLabel"]>(
|
|
304
321
|
(node) => {
|
|
305
|
-
const originalLabel =
|
|
322
|
+
const originalLabel = getLabel(node);
|
|
306
323
|
return <>Custom node - {originalLabel}</>;
|
|
307
324
|
},
|
|
308
|
-
[
|
|
325
|
+
[getLabel],
|
|
309
326
|
);
|
|
310
327
|
|
|
311
328
|
const getSublabel = useCallback<Required<VisibilityTreeRendererProps>["getSublabel"]>(() => {
|
|
312
329
|
return <>Custom sub label</>;
|
|
313
330
|
}, []);
|
|
314
331
|
|
|
315
|
-
return <VisibilityTreeRenderer {...props} getLabel={
|
|
332
|
+
return <VisibilityTreeRenderer {...props} getLabel={getLabelCallback} getSublabel={getSublabel} />;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
interface CustomCategoriesTreeProps {
|
|
336
|
+
imodel: IModelConnection;
|
|
337
|
+
viewport: Viewport;
|
|
338
|
+
getSchemaContext: (imodel: IModelConnection) => SchemaContext;
|
|
339
|
+
selectionStorage: SelectionStorage;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function CustomCategoriesTreeComponent({ imodel, viewport, getSchemaContext, selectionStorage }: CustomCategoriesTreeProps) {
|
|
343
|
+
const { buttonProps } = useCategoriesTreeButtonProps({ viewport });
|
|
344
|
+
const { categoriesTreeProps, rendererProps } = useCategoriesTree({ activeView: viewport, filter: "" });
|
|
345
|
+
|
|
346
|
+
return (
|
|
347
|
+
<TreeWithHeader
|
|
348
|
+
buttons={[
|
|
349
|
+
<CategoriesTreeComponent.ShowAllButton {...buttonProps} key={"ShowAllButton"} />,
|
|
350
|
+
<CategoriesTreeComponent.HideAllButton {...buttonProps} key={"HideAllButton"} />,
|
|
351
|
+
]}
|
|
352
|
+
>
|
|
353
|
+
<VisibilityTree
|
|
354
|
+
{...categoriesTreeProps}
|
|
355
|
+
getSchemaContext={getSchemaContext}
|
|
356
|
+
selectionStorage={selectionStorage}
|
|
357
|
+
imodel={imodel}
|
|
358
|
+
treeRenderer={(props) => <CustomCategoriesTreeRenderer {...props} {...rendererProps} />}
|
|
359
|
+
/>
|
|
360
|
+
</TreeWithHeader>
|
|
361
|
+
);
|
|
316
362
|
}
|
|
317
363
|
```
|
|
318
364
|
|
|
365
|
+
<!-- END EXTRACTION -->
|
|
366
|
+
|
|
319
367
|
### iModel content tree
|
|
320
368
|
|
|
321
369
|
The component renders a similar hierarchy to [Models tree](#models-tree), but with the following changes:
|
|
@@ -331,35 +379,26 @@ In general, the component is expected to be used by advanced users to inspect co
|
|
|
331
379
|
|
|
332
380
|
Typical usage:
|
|
333
381
|
|
|
382
|
+
<!-- [[include: [TreeWidget.ImodelContentTreeExampleImports, TreeWidget.ImodelContentTreeExample], tsx]] -->
|
|
383
|
+
<!-- BEGIN EXTRACTION -->
|
|
384
|
+
|
|
334
385
|
```tsx
|
|
335
|
-
import { IModelConnection } from "@itwin/core-frontend";
|
|
336
|
-
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
337
|
-
import { SelectionStorage } from "@itwin/unified-selection";
|
|
338
386
|
import { IModelContentTreeComponent } from "@itwin/tree-widget-react";
|
|
339
387
|
|
|
340
|
-
// The iModel content tree requires a unified selection storage to support selection synchronization with the
|
|
341
|
-
// application. The storage should be created once per application and shared across multiple selection-enabled
|
|
342
|
-
// components.
|
|
343
|
-
function getUnifiedSelectionStorage(): SelectionStorage {
|
|
344
|
-
// see "Creating unified selection storage" section for example implementation
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Schema context is used by iModel content tree to access iModels metadata. Similar to selection storage, it should be
|
|
348
|
-
// created once per application and shared across multiple components.
|
|
349
|
-
function getSchemaContext(imodel: IModelConnection): SchemaContext {
|
|
350
|
-
// see "Creating schema context" section for example implementation
|
|
351
|
-
}
|
|
352
|
-
|
|
353
388
|
function MyWidget() {
|
|
354
389
|
return (
|
|
355
390
|
<IModelContentTreeComponent
|
|
391
|
+
// see "Creating schema context" section for example implementation
|
|
356
392
|
getSchemaContext={getSchemaContext}
|
|
357
|
-
|
|
393
|
+
// see "Creating unified selection storage" section for example implementation
|
|
394
|
+
selectionStorage={unifiedSelectionStorage}
|
|
358
395
|
/>
|
|
359
396
|
);
|
|
360
397
|
}
|
|
361
398
|
```
|
|
362
399
|
|
|
400
|
+
<!-- END EXTRACTION -->
|
|
401
|
+
|
|
363
402
|
### Custom trees
|
|
364
403
|
|
|
365
404
|
The package delivers a set of building blocks for creating trees that look and feel similar to the tree components provided by this package.
|
|
@@ -373,40 +412,69 @@ A "basic" tree is a tree that renders the hierarchy without visibility control -
|
|
|
373
412
|
|
|
374
413
|
Example:
|
|
375
414
|
|
|
415
|
+
<!-- [[include: [TreeWidget.CustomTreeExampleImports, TreeWidget.CustomTreeExample], tsx]] -->
|
|
416
|
+
<!-- BEGIN EXTRACTION -->
|
|
417
|
+
|
|
376
418
|
```tsx
|
|
377
|
-
import { ComponentPropsWithoutRef } from "react";
|
|
378
|
-
import { IModelConnection } from "@itwin/core-frontend";
|
|
379
|
-
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
380
|
-
import { SelectionStorage } from "@itwin/unified-selection";
|
|
419
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
420
|
+
import type { IModelConnection } from "@itwin/core-frontend";
|
|
381
421
|
import { Tree, TreeRenderer } from "@itwin/tree-widget-react";
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
function getUnifiedSelectionStorage(): SelectionStorage {
|
|
385
|
-
// see "Creating unified selection storage" section for example implementation
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function getSchemaContext(imodel: IModelConnection): SchemaContext {
|
|
389
|
-
// see "Creating schema context" section for example implementation
|
|
390
|
-
}
|
|
422
|
+
import { createClassBasedHierarchyDefinition, createNodesQueryClauseFactory } from "@itwin/presentation-hierarchies";
|
|
423
|
+
import { createBisInstanceLabelSelectClauseFactory } from "@itwin/presentation-shared";
|
|
391
424
|
|
|
392
425
|
type TreeProps = ComponentPropsWithoutRef<typeof Tree>;
|
|
393
426
|
const getHierarchyDefinition: TreeProps["getHierarchyDefinition"] = ({ imodelAccess }) => {
|
|
394
427
|
// create a hierarchy definition that defines what should be shown in the tree
|
|
395
428
|
// see https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md#hierarchy-definition
|
|
429
|
+
const nodesQueryFactory = createNodesQueryClauseFactory({ imodelAccess });
|
|
430
|
+
const labelsQueryFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: imodelAccess });
|
|
431
|
+
return createClassBasedHierarchyDefinition({
|
|
432
|
+
classHierarchyInspector: imodelAccess,
|
|
433
|
+
hierarchy: {
|
|
434
|
+
// For root nodes, select all BisCore.GeometricModel3d instances
|
|
435
|
+
rootNodes: async () => [
|
|
436
|
+
{
|
|
437
|
+
fullClassName: "BisCore.GeometricModel3d",
|
|
438
|
+
query: {
|
|
439
|
+
ecsql: `
|
|
440
|
+
SELECT
|
|
441
|
+
${await nodesQueryFactory.createSelectClause({
|
|
442
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
443
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
444
|
+
nodeLabel: {
|
|
445
|
+
selector: await labelsQueryFactory.createSelectClause({ classAlias: "this", className: "BisCore.GeometricModel3d" }),
|
|
446
|
+
},
|
|
447
|
+
})}
|
|
448
|
+
FROM BisCore.GeometricModel3d this
|
|
449
|
+
`,
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
],
|
|
453
|
+
childNodes: [],
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
interface MyTreeProps {
|
|
459
|
+
imodel: IModelConnection;
|
|
396
460
|
}
|
|
397
461
|
|
|
398
462
|
function MyTree({ imodel }: MyTreeProps) {
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
463
|
+
return (
|
|
464
|
+
<Tree
|
|
465
|
+
treeName="MyTree"
|
|
466
|
+
imodel={imodel}
|
|
467
|
+
selectionStorage={unifiedSelectionStorage}
|
|
468
|
+
getSchemaContext={getSchemaContext}
|
|
469
|
+
getHierarchyDefinition={getHierarchyDefinition}
|
|
470
|
+
treeRenderer={(props) => <TreeRenderer {...props} />}
|
|
471
|
+
/>
|
|
472
|
+
);
|
|
407
473
|
}
|
|
408
474
|
```
|
|
409
475
|
|
|
476
|
+
<!-- END EXTRACTION -->
|
|
477
|
+
|
|
410
478
|
#### Custom visibility tree
|
|
411
479
|
|
|
412
480
|
A visibility tree is a tree that renders the hierarchy and allows controlling visibility control through the use of "eye" checkboxes - see [Models](#models-tree) and [Categories](#categories-tree) trees. Core components:
|
|
@@ -416,34 +484,56 @@ A visibility tree is a tree that renders the hierarchy and allows controlling vi
|
|
|
416
484
|
|
|
417
485
|
Example:
|
|
418
486
|
|
|
487
|
+
<!-- [[include: [TreeWidget.CustomVisibilityTreeExampleImports, TreeWidget.CustomVisibilityTreeExample], tsx]] -->
|
|
488
|
+
<!-- BEGIN EXTRACTION -->
|
|
489
|
+
|
|
419
490
|
```tsx
|
|
420
|
-
import { ComponentPropsWithoutRef } from "react";
|
|
421
491
|
import { BeEvent } from "@itwin/core-bentley";
|
|
422
|
-
import { IModelConnection } from "@itwin/core-frontend";
|
|
423
|
-
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
424
|
-
import { SelectionStorage } from "@itwin/unified-selection";
|
|
425
492
|
import { VisibilityTree, VisibilityTreeRenderer } from "@itwin/tree-widget-react";
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
function getSchemaContext(imodel: IModelConnection): SchemaContext {
|
|
433
|
-
// see "Creating schema context" section for example implementation
|
|
434
|
-
}
|
|
493
|
+
import { createClassBasedHierarchyDefinition, createNodesQueryClauseFactory } from "@itwin/presentation-hierarchies";
|
|
494
|
+
import { createBisInstanceLabelSelectClauseFactory } from "@itwin/presentation-shared";
|
|
495
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
496
|
+
import type { IModelConnection } from "@itwin/core-frontend";
|
|
435
497
|
|
|
436
498
|
type VisibilityTreeProps = ComponentPropsWithoutRef<typeof VisibilityTree>;
|
|
437
499
|
const getHierarchyDefinition: VisibilityTreeProps["getHierarchyDefinition"] = ({ imodelAccess }) => {
|
|
438
500
|
// create a hierarchy definition that defines what should be shown in the tree
|
|
439
501
|
// see https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md#hierarchy-definition
|
|
440
|
-
}
|
|
502
|
+
const nodesQueryFactory = createNodesQueryClauseFactory({ imodelAccess });
|
|
503
|
+
const labelsQueryFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: imodelAccess });
|
|
504
|
+
return createClassBasedHierarchyDefinition({
|
|
505
|
+
classHierarchyInspector: imodelAccess,
|
|
506
|
+
hierarchy: {
|
|
507
|
+
// For root nodes, select all BisCore.GeometricModel3d instances
|
|
508
|
+
rootNodes: async () => [
|
|
509
|
+
{
|
|
510
|
+
fullClassName: "BisCore.GeometricModel3d",
|
|
511
|
+
query: {
|
|
512
|
+
ecsql: `
|
|
513
|
+
SELECT
|
|
514
|
+
${await nodesQueryFactory.createSelectClause({
|
|
515
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
516
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
517
|
+
nodeLabel: {
|
|
518
|
+
selector: await labelsQueryFactory.createSelectClause({ classAlias: "this", className: "BisCore.GeometricModel3d" }),
|
|
519
|
+
},
|
|
520
|
+
})}
|
|
521
|
+
FROM BisCore.GeometricModel3d this
|
|
522
|
+
`,
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
childNodes: [],
|
|
527
|
+
},
|
|
528
|
+
});
|
|
529
|
+
};
|
|
441
530
|
|
|
442
|
-
const visibilityHandlerFactory: VisibilityTreeProps["visibilityHandlerFactory"] = (
|
|
531
|
+
const visibilityHandlerFactory: VisibilityTreeProps["visibilityHandlerFactory"] = () => {
|
|
443
532
|
return {
|
|
444
533
|
// event that can be used to notify tree when visibility of instances represented by tree nodes changes from outside.
|
|
445
534
|
onVisibilityChange: new BeEvent(),
|
|
446
535
|
async getVisibilityStatus(node: HierarchyNode): Promise<VisibilityStatus> {
|
|
536
|
+
return { state: "visible" };
|
|
447
537
|
// determine visibility status of the instance represented by tree node.
|
|
448
538
|
},
|
|
449
539
|
async changeVisibility(node: HierarchyNode, on: boolean): Promise<void> {
|
|
@@ -453,21 +543,29 @@ const visibilityHandlerFactory: VisibilityTreeProps["visibilityHandlerFactory"]
|
|
|
453
543
|
// if necessary, do some clean up before new visibility handler is created or component is unmounted.
|
|
454
544
|
},
|
|
455
545
|
};
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
interface MyVisibilityTreeProps {
|
|
549
|
+
imodel: IModelConnection;
|
|
456
550
|
}
|
|
457
551
|
|
|
458
552
|
function MyVisibilityTree({ imodel }: MyVisibilityTreeProps) {
|
|
459
|
-
return
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
553
|
+
return (
|
|
554
|
+
<VisibilityTree
|
|
555
|
+
treeName="MyVisibilityTree"
|
|
556
|
+
imodel={imodel}
|
|
557
|
+
selectionStorage={unifiedSelectionStorage}
|
|
558
|
+
getSchemaContext={getSchemaContext}
|
|
559
|
+
getHierarchyDefinition={getHierarchyDefinition}
|
|
560
|
+
visibilityHandlerFactory={visibilityHandlerFactory}
|
|
561
|
+
treeRenderer={(props) => <VisibilityTreeRenderer {...props} />}
|
|
562
|
+
/>
|
|
563
|
+
);
|
|
468
564
|
}
|
|
469
565
|
```
|
|
470
566
|
|
|
567
|
+
<!-- END EXTRACTION -->
|
|
568
|
+
|
|
471
569
|
### Hierarchy level size limiting
|
|
472
570
|
|
|
473
571
|
All tree components in this package enforce a hierarchy level size limit. This means that when a node is expanded, only a certain number of child nodes are loaded. The limit is enforced to prevent loading too many nodes at once and to keep the performance of the tree components at an acceptable level.
|
|
@@ -488,9 +586,13 @@ Tree components that support selection synchronization, require a unified select
|
|
|
488
586
|
|
|
489
587
|
Typically, we want one unified selection storage per application - this makes sure that selection in all application's components is synchronized. Below is an example implementation of `getUnifiedSelectionStorage` function that creates the storage and clears it when an iModel is closed:
|
|
490
588
|
|
|
491
|
-
|
|
589
|
+
<!-- [[include: [TreeWidget.SelectionStorageExampleImports, TreeWidget.SelectionStorageExample], tsx]] -->
|
|
590
|
+
<!-- BEGIN EXTRACTION -->
|
|
591
|
+
|
|
592
|
+
```tsx
|
|
492
593
|
import { IModelConnection } from "@itwin/core-frontend";
|
|
493
|
-
import { createStorage
|
|
594
|
+
import { createStorage } from "@itwin/unified-selection";
|
|
595
|
+
import type { SelectionStorage } from "@itwin/unified-selection";
|
|
494
596
|
|
|
495
597
|
let unifiedSelectionStorage: SelectionStorage | undefined;
|
|
496
598
|
function getUnifiedSelectionStorage(): SelectionStorage {
|
|
@@ -504,28 +606,34 @@ function getUnifiedSelectionStorage(): SelectionStorage {
|
|
|
504
606
|
}
|
|
505
607
|
```
|
|
506
608
|
|
|
507
|
-
|
|
609
|
+
<!-- END EXTRACTION -->
|
|
610
|
+
|
|
611
|
+
In case the application is also using components driven by APIs from `@itwin/presentation-frontend` package, which has its own selection manager, the single unified selection storage object should be passed to [`initialize`](https://www.itwinjs.org/reference/presentation-frontend/core/presentation/initializestatic/) function, e.g.:
|
|
508
612
|
|
|
509
|
-
|
|
613
|
+
<!-- [[include: [TreeWidget.SelectionStorageInitializeExampleImports, TreeWidget.SelectionStorageInitializeExample], tsx]] -->
|
|
614
|
+
<!-- BEGIN EXTRACTION -->
|
|
615
|
+
|
|
616
|
+
```tsx
|
|
510
617
|
import { Presentation } from "@itwin/presentation-frontend";
|
|
511
618
|
|
|
512
|
-
Presentation.initialize({
|
|
513
|
-
selection: {
|
|
514
|
-
selectionStorage: getUnifiedSelectionStorage(),
|
|
515
|
-
},
|
|
516
|
-
});
|
|
619
|
+
await Presentation.initialize({ selection: { selectionStorage: getUnifiedSelectionStorage() } });
|
|
517
620
|
```
|
|
518
621
|
|
|
622
|
+
<!-- END EXTRACTION -->
|
|
623
|
+
|
|
519
624
|
### Creating schema context
|
|
520
625
|
|
|
521
626
|
All tree components delivered with the package require a [`SchemaContext`](https://www.itwinjs.org/reference/ecschema-metadata/context/schemacontext/) to be able to access iModels metadata.
|
|
522
627
|
|
|
523
628
|
Typically, we want one schema context per iModel per application - this allows schema information to be shared across components, saving memory and time required to access the metadata. Below is an example implementation of `getSchemaContext` function, required by tree components:
|
|
524
629
|
|
|
525
|
-
|
|
526
|
-
|
|
630
|
+
<!-- [[include: [TreeWidget.GetSchemaContextExampleImports, TreeWidget.GetSchemaContextExample], tsx]] -->
|
|
631
|
+
<!-- BEGIN EXTRACTION -->
|
|
632
|
+
|
|
633
|
+
```tsx
|
|
527
634
|
import { SchemaContext } from "@itwin/ecschema-metadata";
|
|
528
635
|
import { ECSchemaRpcLocater } from "@itwin/ecschema-rpcinterface-common";
|
|
636
|
+
import type { IModelConnection } from "@itwin/core-frontend";
|
|
529
637
|
|
|
530
638
|
const schemaContextCache = new Map<string, SchemaContext>();
|
|
531
639
|
function getSchemaContext(imodel: IModelConnection) {
|
|
@@ -542,13 +650,15 @@ function getSchemaContext(imodel: IModelConnection) {
|
|
|
542
650
|
}
|
|
543
651
|
```
|
|
544
652
|
|
|
653
|
+
<!-- END EXTRACTION -->
|
|
654
|
+
|
|
545
655
|
## Telemetry
|
|
546
656
|
|
|
547
657
|
### Performance tracking
|
|
548
658
|
|
|
549
659
|
Components from this package allows consumers to track performance of specific features.
|
|
550
660
|
|
|
551
|
-
This can be achieved by passing `onPerformanceMeasured` function to `CategoriesTreeComponent`, `ModelsTreeComponent`, `IModelContentTreeComponent
|
|
661
|
+
This can be achieved by passing `onPerformanceMeasured` function to `CategoriesTreeComponent`, `ModelsTreeComponent`, `IModelContentTreeComponent`. The function is invoked with feature id and time elapsed as the component is being used. List of tracked features:
|
|
552
662
|
|
|
553
663
|
- `"{tree}-initial-load"` - time it takes to load initial nodes after the tree is created.
|
|
554
664
|
- `"{tree}-hierarchy-level-load"` - time it takes to load child nodes when a node is expanded.
|
|
@@ -560,7 +670,7 @@ Where `{tree}` specifies which tree component the feature is of.
|
|
|
560
670
|
|
|
561
671
|
Components from this package allows consumers to track the usage of specific features.
|
|
562
672
|
|
|
563
|
-
This can be achieved by passing `onFeatureUsed` function to `CategoriesTreeComponent`, `ModelsTreeComponent`, `IModelContentTreeComponent
|
|
673
|
+
This can be achieved by passing `onFeatureUsed` function to `CategoriesTreeComponent`, `ModelsTreeComponent`, `IModelContentTreeComponent`. The function is invoked with feature id as the component is being used. List of tracked features:
|
|
564
674
|
|
|
565
675
|
- `"choose-{tree}"` - when a tree is selected in the tree selector.
|
|
566
676
|
- `"use-{tree}"` - when an interaction with a tree hierarchy happens. This includes any kind of interaction with nodes, including them being expanded/collapsed, selected, filtered, their visibility change, etc.
|
|
@@ -585,62 +695,70 @@ Where `{tree}` specifies which tree component the feature is of.
|
|
|
585
695
|
|
|
586
696
|
### Example
|
|
587
697
|
|
|
588
|
-
```ts
|
|
589
|
-
import { UiItemsManager } from "@itwin/appui-react";
|
|
590
|
-
import { TreeWidgetUiItemsProvider } from "@itwin/tree-widget-react";
|
|
591
|
-
|
|
592
|
-
UiItemsManager.register(
|
|
593
|
-
new TreeWidgetUiItemsProvider({
|
|
594
|
-
onPerformanceMeasured={(feature, elapsedTime) => {
|
|
595
|
-
telemetryClient.log(`TreeWidget [${feature}] took ${elapsedTime} ms`);
|
|
596
|
-
}},
|
|
597
|
-
onFeatureUsed={(feature) => {
|
|
598
|
-
telemetryClient.log(`TreeWidget [${feature}] used`);
|
|
599
|
-
}},
|
|
600
|
-
})
|
|
601
|
-
);
|
|
602
|
-
```
|
|
603
|
-
|
|
604
698
|
For individual tree components the callbacks should be supplied through props:
|
|
605
699
|
|
|
700
|
+
<!-- [[include: [TreeWidget.TelemetryTreeComponentExampleImports, TreeWidget.TelemetryTreeComponentExample], tsx]] -->
|
|
701
|
+
<!-- BEGIN EXTRACTION -->
|
|
702
|
+
|
|
606
703
|
```tsx
|
|
607
|
-
import {
|
|
704
|
+
import { IModelContentTreeComponent } from "@itwin/tree-widget-react";
|
|
608
705
|
|
|
609
706
|
function MyWidget() {
|
|
610
707
|
return (
|
|
611
|
-
<
|
|
612
|
-
{...otherProps}
|
|
708
|
+
<IModelContentTreeComponent
|
|
613
709
|
onPerformanceMeasured={(feature, elapsedTime) => {
|
|
614
|
-
console.log(`TreeWidget [${feature}] took ${elapsedTime} ms`)
|
|
710
|
+
console.log(`TreeWidget [${feature}] took ${elapsedTime} ms`);
|
|
615
711
|
}}
|
|
616
712
|
onFeatureUsed={(feature) => {
|
|
617
|
-
console.log(`TreeWidget [${feature}] used`)
|
|
713
|
+
console.log(`TreeWidget [${feature}] used`);
|
|
618
714
|
}}
|
|
715
|
+
getSchemaContext={getSchemaContext}
|
|
716
|
+
selectionStorage={unifiedSelectionStorage}
|
|
619
717
|
/>
|
|
620
718
|
);
|
|
621
719
|
}
|
|
622
720
|
```
|
|
623
721
|
|
|
722
|
+
<!-- END EXTRACTION -->
|
|
723
|
+
|
|
624
724
|
For custom tree components `TelemetryContextProvider` should be used:
|
|
625
725
|
|
|
726
|
+
<!-- [[include: [TreeWidget.TelemetryCustomTreeExampleImports, TreeWidget.TelemetryCustomTreeExample], tsx]] -->
|
|
727
|
+
<!-- BEGIN EXTRACTION -->
|
|
728
|
+
|
|
626
729
|
```tsx
|
|
627
|
-
import { TelemetryContextProvider } from "@itwin/tree-widget-react";
|
|
730
|
+
import { TelemetryContextProvider, useCategoriesTree, VisibilityTree, VisibilityTreeRenderer } from "@itwin/tree-widget-react";
|
|
628
731
|
|
|
629
732
|
function MyWidget() {
|
|
630
|
-
return
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
733
|
+
return (
|
|
734
|
+
<TelemetryContextProvider
|
|
735
|
+
componentIdentifier="MyTree"
|
|
736
|
+
onPerformanceMeasured={(feature, elapsedTime) => {
|
|
737
|
+
console.log(`TreeWidget [${feature}] took ${elapsedTime} ms`);
|
|
738
|
+
}}
|
|
739
|
+
onFeatureUsed={(feature) => {
|
|
740
|
+
console.log(`TreeWidget [${feature}] used`);
|
|
741
|
+
}}
|
|
742
|
+
>
|
|
743
|
+
<MyTree />
|
|
744
|
+
</TelemetryContextProvider>
|
|
745
|
+
);
|
|
641
746
|
}
|
|
642
747
|
|
|
643
748
|
function MyTree() {
|
|
644
|
-
|
|
749
|
+
const { categoriesTreeProps, rendererProps } = useCategoriesTree({ activeView: viewport, filter: "" });
|
|
750
|
+
return (
|
|
751
|
+
// VisibilityTree will use provided telemetry context to report used features and their performance
|
|
752
|
+
<VisibilityTree
|
|
753
|
+
{...categoriesTreeProps}
|
|
754
|
+
getSchemaContext={getSchemaContext}
|
|
755
|
+
selectionStorage={unifiedSelectionStorage}
|
|
756
|
+
imodel={imodel}
|
|
757
|
+
treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
|
|
758
|
+
/>
|
|
759
|
+
);
|
|
760
|
+
// see "Custom trees" section for more example implementations
|
|
645
761
|
}
|
|
646
762
|
```
|
|
763
|
+
|
|
764
|
+
<!-- END EXTRACTION -->
|