@itwin/presentation-hierarchies-react 1.1.3 → 1.3.0
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 +90 -0
- package/README.md +15 -7
- package/lib/cjs/presentation-hierarchies-react/UseIModelTree.d.ts +2 -1
- package/lib/cjs/presentation-hierarchies-react/UseIModelTree.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/UseIModelTree.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts +3 -1
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/UseTree.js +37 -21
- package/lib/cjs/presentation-hierarchies-react/UseTree.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts +2 -2
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js +7 -7
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +2 -2
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js +4 -4
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts +14 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js +18 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +5 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +2 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +5 -5
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +1 -1
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js +4 -4
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/UseIModelTree.d.ts +2 -1
- package/lib/esm/presentation-hierarchies-react/UseIModelTree.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/UseIModelTree.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts +3 -1
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/UseTree.js +37 -21
- package/lib/esm/presentation-hierarchies-react/UseTree.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts +2 -2
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js +7 -7
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +2 -2
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js +4 -4
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts +14 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js +17 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +5 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +2 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +5 -5
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -1
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +1 -1
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js +4 -4
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,95 @@
|
|
|
1
1
|
# @itwin/presentation-hierarchies-react
|
|
2
2
|
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#807](https://github.com/iTwin/presentation/pull/807): Added `getNode` function to tree state hooks to allow getting a node by id.
|
|
8
|
+
|
|
9
|
+
Example usage:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
function MyTreeComponentInternal({ imodelAccess }: { imodelAccess: IModelAccess }) {
|
|
13
|
+
const {
|
|
14
|
+
rootNodes,
|
|
15
|
+
getNode,
|
|
16
|
+
expandNode: doExpandNode,
|
|
17
|
+
...state
|
|
18
|
+
} = useTree({
|
|
19
|
+
// tree props
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// enhance the default `expandNode` handler to log the action to console
|
|
23
|
+
const expandNode = React.useCallback(
|
|
24
|
+
async (nodeId: string, isExpanded: boolean) => {
|
|
25
|
+
const node = getNode(nodeId);
|
|
26
|
+
if (node) {
|
|
27
|
+
console.log(`${isExpanded ? "Expanding" : "Collapsing"} node: ${node.label}`);
|
|
28
|
+
}
|
|
29
|
+
doExpandNode(nodeId, isExpanded);
|
|
30
|
+
},
|
|
31
|
+
[getNode, doExpandNode],
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// render the tree
|
|
35
|
+
if (!rootNodes || !rootNodes.length) {
|
|
36
|
+
return "No data to display";
|
|
37
|
+
}
|
|
38
|
+
return <TreeRenderer {...state} expandNode={expandNode} rootNodes={rootNodes} />;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- [#802](https://github.com/iTwin/presentation/pull/802): Prefer `Symbol.dispose` over `dispose` for disposable objects.
|
|
43
|
+
|
|
44
|
+
The package contained a number of types for disposable objects, that had a requirement of `dispose` method being called on them after they are no longer needed. In conjunction with the `using` utility from `@itwin/core-bentley`, usage of such objects looked like this:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
class MyDisposable() {
|
|
48
|
+
dispose() {
|
|
49
|
+
// do some cleanup
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
using(new MyDisposable(), (obj) => {
|
|
53
|
+
// do something with obj, it'll get disposed when the callback returns
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
In version `5.2`, TypeScript [introduced](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management) `Disposable` type and `using` declarations (from the upcoming [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) feature in ECMAScript). Now we're making use of those new utilities in this package (while still supporting the old `dispose` method), which allows using `MyDisposable` from the above snippet like this:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
using obj = new MyDisposable();
|
|
61
|
+
// do something with obj, it'll get disposed when it goes out of scope
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Patch Changes
|
|
65
|
+
|
|
66
|
+
- Updated dependencies:
|
|
67
|
+
- @itwin/unified-selection@1.2.0
|
|
68
|
+
- @itwin/presentation-hierarchies@1.4.0
|
|
69
|
+
|
|
70
|
+
## 1.2.0
|
|
71
|
+
|
|
72
|
+
### Minor Changes
|
|
73
|
+
|
|
74
|
+
- [#795](https://github.com/iTwin/presentation/pull/795): Added `size` property to `TreeNodeRenderer` to improve styling of `small` tree.
|
|
75
|
+
- [#791](https://github.com/iTwin/presentation/pull/791): Unify hierarchy updates' handling.
|
|
76
|
+
|
|
77
|
+
Previously, we'd only raise the `HierarchyProvider.hierarchyChanged` event on data source changes. The tree state hooks would listen to this event and trigger a hierarchy update. However, there are a few other reasons for the hierarchy to change - changing formatter or active hierarchy filter. In those situations the event was not raised, but tree state hooks still had to trigger hierarchy update. So we ended up with a mix of event-driven and manual hierarchy updates.
|
|
78
|
+
|
|
79
|
+
With this change we're clearly stating that a hierarchy provider should trigger its `hierarchyChanged` event whenever something happens that causes the hierarchy to change. That means, the event will be raised when formatter or hierarchy filter is set, and tree state hooks can initiate hierarchy reload from a single place - the `hierarchyChanged` event listener.
|
|
80
|
+
|
|
81
|
+
To let event listeners know what caused the hierarchy change, the event now has event arguments, which should be set by the hierarchy provider when raising the event. This allows listeners to customize hierarchy reload logic - for example, our tree state hooks always keep existing tree state except when a new hierarchy filter is set, in which case the existing state is discarded.
|
|
82
|
+
|
|
83
|
+
### Patch Changes
|
|
84
|
+
|
|
85
|
+
- [#795](https://github.com/iTwin/presentation/pull/795): Fix tree node loading indicator to match other icons size.
|
|
86
|
+
- [#786](https://github.com/iTwin/presentation/pull/786): Bump package dependencies.
|
|
87
|
+
- [#794](https://github.com/iTwin/presentation/pull/794): Add missing `ref` to the placeholder and error nodes to have correct styling in virtualized small tree.
|
|
88
|
+
- Updated dependencies:
|
|
89
|
+
- @itwin/presentation-shared@1.2.0
|
|
90
|
+
- @itwin/presentation-hierarchies@1.3.0
|
|
91
|
+
- @itwin/unified-selection@1.1.2
|
|
92
|
+
|
|
3
93
|
## 1.1.3
|
|
4
94
|
|
|
5
95
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ All these hooks return the same state object, which contains properties and func
|
|
|
28
28
|
|
|
29
29
|
- `isNodeSelected` and `selectNodes` function to inspect and change tree selection.
|
|
30
30
|
|
|
31
|
+
- `getNode` function to get node by its id.
|
|
32
|
+
|
|
31
33
|
- `getHierarchyLevelDetails` function to access details of a specific hierarchy level. The returned object provides access to:
|
|
32
34
|
|
|
33
35
|
- hierarchy level size limit,
|
|
@@ -113,7 +115,7 @@ The hook also relies on unified selection storage being provided to it through a
|
|
|
113
115
|
|
|
114
116
|
#### Providing unified selection context
|
|
115
117
|
|
|
116
|
-
|
|
118
|
+
Tree state hooks that support unified selection integration (`useUnifiedSelectionTree` & `useIModelUnifiedSelectionTree`), rely on unified selection storage being provided to them through a React context. For that, the package delivers the `UnifiedSelectionProvider` component, that should wrap the tree component using the hooks:
|
|
117
119
|
|
|
118
120
|
<!-- [[include: [Presentation.HierarchiesReact.SelectionStorage.Imports, Presentation.HierarchiesReact.SelectionStorage], tsx]] -->
|
|
119
121
|
<!-- BEGIN EXTRACTION -->
|
|
@@ -221,7 +223,7 @@ import { createCachingECClassHierarchyInspector } from "@itwin/presentation-shar
|
|
|
221
223
|
import { createECSchemaProvider, createECSqlQueryExecutor } from "@itwin/presentation-core-interop";
|
|
222
224
|
import { createLimitingECSqlQueryExecutor, createNodesQueryClauseFactory, HierarchyDefinition } from "@itwin/presentation-hierarchies";
|
|
223
225
|
|
|
224
|
-
import { createBisInstanceLabelSelectClauseFactory } from "@itwin/presentation-shared";
|
|
226
|
+
import { createBisInstanceLabelSelectClauseFactory, Props } from "@itwin/presentation-shared";
|
|
225
227
|
|
|
226
228
|
import { TreeRenderer, UnifiedSelectionProvider, useIModelUnifiedSelectionTree } from "@itwin/presentation-hierarchies-react";
|
|
227
229
|
import { createStorage } from "@itwin/unified-selection";
|
|
@@ -277,7 +279,7 @@ function MyTreeComponent({ imodel }: { imodel: IModelConnection }) {
|
|
|
277
279
|
);
|
|
278
280
|
}
|
|
279
281
|
|
|
280
|
-
type IModelAccess =
|
|
282
|
+
type IModelAccess = Props<typeof useIModelUnifiedSelectionTree>["imodelAccess"];
|
|
281
283
|
|
|
282
284
|
// The hierarchy definition describes the hierarchy using ECSQL queries; here it just returns all `BisCore.PhysicalModel` instances
|
|
283
285
|
function getHierarchyDefinition({ imodelAccess }: { imodelAccess: IModelAccess }): HierarchyDefinition {
|
|
@@ -333,13 +335,15 @@ Localization can be enabled for `TreeRenderer` component and [tree state hooks](
|
|
|
333
335
|
|
|
334
336
|
Example:
|
|
335
337
|
|
|
336
|
-
<!-- [[include: [Presentation.HierarchiesReact.Localization.Tree.Imports, Presentation.HierarchiesReact.Localization.Strings, Presentation.HierarchiesReact.Localization.Tree], tsx]] -->
|
|
338
|
+
<!-- [[include: [Presentation.HierarchiesReact.Localization.CommonImports, Presentation.HierarchiesReact.Localization.Tree.Imports, Presentation.HierarchiesReact.Localization.Strings, Presentation.HierarchiesReact.Localization.Tree], tsx]] -->
|
|
337
339
|
<!-- BEGIN EXTRACTION -->
|
|
338
340
|
|
|
339
341
|
```tsx
|
|
342
|
+
import { Props } from "@itwin/presentation-shared";
|
|
343
|
+
|
|
340
344
|
import { useIModelUnifiedSelectionTree } from "@itwin/presentation-hierarchies-react";
|
|
341
345
|
|
|
342
|
-
type IModelAccess =
|
|
346
|
+
type IModelAccess = Props<typeof useIModelUnifiedSelectionTree>["imodelAccess"];
|
|
343
347
|
|
|
344
348
|
const localizedStrings = {
|
|
345
349
|
// strings for the `useIModelUnifiedSelectionTree` hook
|
|
@@ -375,10 +379,14 @@ function MyTreeComponent({ imodelAccess }: { imodelAccess: IModelAccess }) {
|
|
|
375
379
|
|
|
376
380
|
In case the `TreeNodeRenderer` component is used within a custom tree renderer, the tree component should supply localized strings through `LocalizationContextProvider`:
|
|
377
381
|
|
|
378
|
-
<!-- [[include: [Presentation.HierarchiesReact.Localization.TreeRenderer.Imports, Presentation.HierarchiesReact.Localization.TreeRenderer], tsx]] -->
|
|
382
|
+
<!-- [[include: [Presentation.HierarchiesReact.Localization.CommonImports, Presentation.HierarchiesReact.Localization.TreeRenderer.Imports, Presentation.HierarchiesReact.Localization.TreeRenderer], tsx]] -->
|
|
379
383
|
<!-- BEGIN EXTRACTION -->
|
|
380
384
|
|
|
381
385
|
```tsx
|
|
386
|
+
import { Props } from "@itwin/presentation-shared";
|
|
387
|
+
|
|
388
|
+
import { ComponentPropsWithoutRef, useCallback } from "react";
|
|
389
|
+
import { Tree } from "@itwin/itwinui-react";
|
|
382
390
|
import {
|
|
383
391
|
createRenderedTreeNodeData,
|
|
384
392
|
LocalizationContextProvider,
|
|
@@ -388,7 +396,7 @@ import {
|
|
|
388
396
|
} from "@itwin/presentation-hierarchies-react";
|
|
389
397
|
|
|
390
398
|
type TreeProps = ComponentPropsWithoutRef<typeof Tree<RenderedTreeNode>>;
|
|
391
|
-
type TreeRendererProps =
|
|
399
|
+
type TreeRendererProps = Props<typeof TreeRenderer>;
|
|
392
400
|
|
|
393
401
|
function MyTreeRenderer(props: TreeRendererProps) {
|
|
394
402
|
const nodeRenderer = useCallback<TreeProps["nodeRenderer"]>((nodeProps) => {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createIModelHierarchyProvider, HierarchyDefinition, HierarchyFilteringPath } from "@itwin/presentation-hierarchies";
|
|
2
|
+
import { Props } from "@itwin/presentation-shared";
|
|
2
3
|
import { UseUnifiedTreeSelectionProps } from "./internal/UseUnifiedSelection.js";
|
|
3
4
|
import { UseTreeProps, UseTreeResult } from "./UseTree.js";
|
|
4
5
|
/** @public */
|
|
5
|
-
type IModelHierarchyProviderProps =
|
|
6
|
+
type IModelHierarchyProviderProps = Props<typeof createIModelHierarchyProvider>;
|
|
6
7
|
/** @public */
|
|
7
8
|
type IModelAccess = IModelHierarchyProviderProps["imodelAccess"];
|
|
8
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseIModelTree.d.ts","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseIModelTree.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC7H,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAW,YAAY,EAAE,aAAa,EAA2B,MAAM,cAAc,CAAC;AAE7F,cAAc;AACd,KAAK,4BAA4B,GAAG,
|
|
1
|
+
{"version":3,"file":"UseIModelTree.d.ts","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseIModelTree.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC7H,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAW,YAAY,EAAE,aAAa,EAA2B,MAAM,cAAc,CAAC;AAE7F,cAAc;AACd,KAAK,4BAA4B,GAAG,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEhF,cAAc;AACd,KAAK,YAAY,GAAG,4BAA4B,CAAC,cAAc,CAAC,CAAC;AAEjE;;;GAGG;AACH,KAAK,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,sBAAsB,GAAG,kBAAkB,CAAC,GACvF,IAAI,CAAC,4BAA4B,EAAE,kBAAkB,GAAG,cAAc,GAAG,eAAe,CAAC,GAAG;IAC1F,sDAAsD;IACtD,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,YAAY,CAAA;KAAE,KAAK,mBAAmB,CAAC;IAEvF,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QACzB,+FAA+F;QAC/F,YAAY,EAAE,YAAY,CAAC;KAC5B,KAAK,OAAO,CAAC,sBAAsB,EAAE,GAAG,SAAS,CAAC,CAAC;CACrD,CAAC;AAEJ;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAMtE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,kBAAkB,GAAG,4BAA4B,GAAG,aAAa,CAMrH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseIModelTree.js","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseIModelTree.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;
|
|
1
|
+
{"version":3,"file":"UseIModelTree.js","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseIModelTree.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;AA2ChG,sCAMC;AAgBD,sEAMC;AArED,iCAAoC;AACpC,8EAA6H;AAG7H,6CAA6F;AAwB7F;;;;;;;;;;;;GAYG;AACH,SAAgB,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACnH,OAAO,IAAA,oBAAO,EAAC;QACb,GAAG,IAAI;QACP,GAAG,kBAAkB,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;KACnH,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,6BAA6B,CAAC,KAAwD;IACpG,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACnH,OAAO,IAAA,oCAAuB,EAAC;QAC7B,GAAG,IAAI;QACP,GAAG,kBAAkB,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;KACnH,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAsI;IAEtI,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAC1G,OAAO;QACL,oBAAoB,EAAE,IAAA,mBAAW,EAC/B,GAAG,EAAE,CACH,IAAA,wDAA6B,EAAC;YAC5B,YAAY;YACZ,aAAa;YACb,mBAAmB,EAAE,sBAAsB,CAAC,EAAE,YAAY,EAAE,CAAC;YAC7D,gBAAgB;SACjB,CAAC,EACJ,CAAC,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,gBAAgB,CAAC,CACxE;QACD,gBAAgB,EAAE,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE,CAAC,gBAAgB,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;KAClH,CAAC;AACJ,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 } from \"react\";\nimport { createIModelHierarchyProvider, HierarchyDefinition, HierarchyFilteringPath } from \"@itwin/presentation-hierarchies\";\nimport { Props } from \"@itwin/presentation-shared\";\nimport { UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection.js\";\nimport { useTree, UseTreeProps, UseTreeResult, useUnifiedSelectionTree } from \"./UseTree.js\";\n\n/** @public */\ntype IModelHierarchyProviderProps = Props<typeof createIModelHierarchyProvider>;\n\n/** @public */\ntype IModelAccess = IModelHierarchyProviderProps[\"imodelAccess\"];\n\n/**\n * Props for `useIModelTree` and `useIModelUnifiedSelectionTree` hooks.\n * @public\n */\ntype UseIModelTreeProps = Omit<UseTreeProps, \"getHierarchyProvider\" | \"getFilteredPaths\"> &\n Pick<IModelHierarchyProviderProps, \"localizedStrings\" | \"imodelAccess\" | \"imodelChanged\"> & {\n /** Provides the hierarchy definition for the tree. */\n getHierarchyDefinition: (props: { imodelAccess: IModelAccess }) => HierarchyDefinition;\n\n /** Provides paths to filtered nodes. */\n getFilteredPaths?: (props: {\n /** Object that provides access to the iModel schema and can run queries against the iModel. */\n imodelAccess: IModelAccess;\n }) => Promise<HierarchyFilteringPath[] | undefined>;\n };\n\n/**\n * A React hook that creates state for a tree component whose displayed hierarchy is based on\n * iModel data.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useTree`\n * @see `useIModelUnifiedSelectionTree`\n * @public\n */\nexport function useIModelTree(props: UseIModelTreeProps): UseTreeResult {\n const { imodelAccess, imodelChanged, getHierarchyDefinition, getFilteredPaths, localizedStrings, ...rest } = props;\n return useTree({\n ...rest,\n ...useIModelTreeProps({ imodelAccess, imodelChanged, getHierarchyDefinition, getFilteredPaths, localizedStrings }),\n });\n}\n\n/**\n * A React hook that creates state for a tree component whose displayed hierarchy is based on\n * iModel data and that is integrated with unified selection through context provided by `UnifiedSelectionProvider`.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useIModelTree`\n * @see `useUnifiedSelectionTree`\n * @see `UnifiedSelectionProvider`\n * @public\n */\nexport function useIModelUnifiedSelectionTree(props: UseIModelTreeProps & UseUnifiedTreeSelectionProps): UseTreeResult {\n const { imodelAccess, imodelChanged, getHierarchyDefinition, getFilteredPaths, localizedStrings, ...rest } = props;\n return useUnifiedSelectionTree({\n ...rest,\n ...useIModelTreeProps({ imodelAccess, imodelChanged, getHierarchyDefinition, getFilteredPaths, localizedStrings }),\n });\n}\n\nfunction useIModelTreeProps(\n props: Pick<UseIModelTreeProps, \"imodelAccess\" | \"imodelChanged\" | \"getHierarchyDefinition\" | \"getFilteredPaths\" | \"localizedStrings\">,\n): Pick<UseTreeProps, \"getHierarchyProvider\" | \"getFilteredPaths\"> {\n const { imodelAccess, imodelChanged, getHierarchyDefinition, getFilteredPaths, localizedStrings } = props;\n return {\n getHierarchyProvider: useCallback(\n () =>\n createIModelHierarchyProvider({\n imodelAccess,\n imodelChanged,\n hierarchyDefinition: getHierarchyDefinition({ imodelAccess }),\n localizedStrings,\n }),\n [imodelAccess, imodelChanged, getHierarchyDefinition, localizedStrings],\n ),\n getFilteredPaths: useCallback(async () => getFilteredPaths?.({ imodelAccess }), [imodelAccess, getFilteredPaths]),\n };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GenericInstanceFilter, HierarchyFilteringPath, HierarchyNode, HierarchyProvider } from "@itwin/presentation-hierarchies";
|
|
2
2
|
import { InstanceKey, IPrimitiveValueFormatter } from "@itwin/presentation-shared";
|
|
3
3
|
import { UseUnifiedTreeSelectionProps } from "./internal/UseUnifiedSelection.js";
|
|
4
|
-
import { PresentationTreeNode } from "./TreeNode.js";
|
|
4
|
+
import { PresentationHierarchyNode, PresentationTreeNode } from "./TreeNode.js";
|
|
5
5
|
import { SelectionChangeType } from "./UseSelectionHandler.js";
|
|
6
6
|
/**
|
|
7
7
|
* A data structure that contains information about a single hierarchy level.
|
|
@@ -119,6 +119,8 @@ export interface UseTreeResult {
|
|
|
119
119
|
selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;
|
|
120
120
|
/** Determines whether a given node is selected. */
|
|
121
121
|
isNodeSelected: (nodeId: string) => boolean;
|
|
122
|
+
/** Get a tree node by id */
|
|
123
|
+
getNode: (nodeId: string) => PresentationHierarchyNode | undefined;
|
|
122
124
|
/** Returns hierarchy level details for a given node ID. */
|
|
123
125
|
getHierarchyLevelDetails: (nodeId: string | undefined) => HierarchyLevelDetails | undefined;
|
|
124
126
|
/** Sets a formatter for the primitive values that are displayed in the hierarchy. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseTree.d.ts","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseTree.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UseTree.d.ts","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,11 +7,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.useTree = useTree;
|
|
8
8
|
exports.useUnifiedSelectionTree = useUnifiedSelectionTree;
|
|
9
9
|
const react_1 = require("react");
|
|
10
|
-
const core_bentley_1 = require("@itwin/core-bentley");
|
|
11
10
|
const presentation_hierarchies_1 = require("@itwin/presentation-hierarchies");
|
|
12
11
|
const TreeActions_js_1 = require("./internal/TreeActions.js");
|
|
13
12
|
const TreeModel_js_1 = require("./internal/TreeModel.js");
|
|
14
13
|
const UseUnifiedSelection_js_1 = require("./internal/UseUnifiedSelection.js");
|
|
14
|
+
const Utils_js_1 = require("./internal/Utils.js");
|
|
15
15
|
/**
|
|
16
16
|
* A React hook that creates state for a tree component.
|
|
17
17
|
*
|
|
@@ -25,7 +25,7 @@ const UseUnifiedSelection_js_1 = require("./internal/UseUnifiedSelection.js");
|
|
|
25
25
|
* @public
|
|
26
26
|
*/
|
|
27
27
|
function useTree(props) {
|
|
28
|
-
const {
|
|
28
|
+
const { getTreeModelNode: _, ...rest } = useTreeInternal(props);
|
|
29
29
|
return rest;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
@@ -43,8 +43,11 @@ function useTree(props) {
|
|
|
43
43
|
* @public
|
|
44
44
|
*/
|
|
45
45
|
function useUnifiedSelectionTree({ sourceName, ...props }) {
|
|
46
|
-
const {
|
|
47
|
-
return {
|
|
46
|
+
const { getTreeModelNode, ...rest } = useTreeInternal(props);
|
|
47
|
+
return {
|
|
48
|
+
...rest,
|
|
49
|
+
...(0, UseUnifiedSelection_js_1.useUnifiedTreeSelection)({ sourceName, getTreeModelNode }),
|
|
50
|
+
};
|
|
48
51
|
}
|
|
49
52
|
function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformanceMeasured, onHierarchyLimitExceeded, onHierarchyLoadError, }) {
|
|
50
53
|
const [state, setState] = (0, react_1.useState)({
|
|
@@ -66,15 +69,16 @@ function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformance
|
|
|
66
69
|
(0, react_1.useEffect)(() => {
|
|
67
70
|
const provider = getHierarchyProvider();
|
|
68
71
|
provider.setFormatter(currentFormatter.current);
|
|
69
|
-
const removeHierarchyChangedListener = provider.hierarchyChanged.addListener(() =>
|
|
72
|
+
const removeHierarchyChangedListener = provider.hierarchyChanged.addListener((hierarchyChangeArgs) => {
|
|
73
|
+
const shouldDiscardState = hierarchyChangeArgs?.filterChange?.newFilter !== undefined;
|
|
74
|
+
actions.reloadTree({ state: shouldDiscardState ? "discard" : "keep" });
|
|
75
|
+
});
|
|
70
76
|
actions.setHierarchyProvider(provider);
|
|
71
77
|
setHierarchyProvider(provider);
|
|
72
78
|
return () => {
|
|
73
79
|
removeHierarchyChangedListener();
|
|
74
|
-
actions.
|
|
75
|
-
|
|
76
|
-
provider.dispose();
|
|
77
|
-
}
|
|
80
|
+
actions.reset();
|
|
81
|
+
(0, Utils_js_1.safeDispose)(provider);
|
|
78
82
|
};
|
|
79
83
|
}, [actions, getHierarchyProvider]);
|
|
80
84
|
const [isFiltering, setIsFiltering] = (0, react_1.useState)(false);
|
|
@@ -83,7 +87,6 @@ function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformance
|
|
|
83
87
|
void (async () => {
|
|
84
88
|
if (!getFilteredPaths || !hierarchyProvider) {
|
|
85
89
|
hierarchyProvider?.setHierarchyFilter(undefined);
|
|
86
|
-
actions.reloadTree({ state: "keep" });
|
|
87
90
|
setIsFiltering(false);
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
@@ -97,19 +100,24 @@ function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformance
|
|
|
97
100
|
finally {
|
|
98
101
|
if (!disposed) {
|
|
99
102
|
hierarchyProvider.setHierarchyFilter(paths ? { paths } : undefined);
|
|
100
|
-
actions.reloadTree({ state: paths ? "discard" : "keep" });
|
|
101
103
|
setIsFiltering(false);
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
})();
|
|
105
107
|
return () => {
|
|
106
108
|
disposed = true;
|
|
107
|
-
actions.dispose();
|
|
108
109
|
};
|
|
109
|
-
}, [
|
|
110
|
-
const
|
|
110
|
+
}, [hierarchyProvider, getFilteredPaths]);
|
|
111
|
+
const getTreeModelNode = (0, react_1.useCallback)((nodeId) => {
|
|
111
112
|
return actions.getNode(nodeId);
|
|
112
113
|
}, [actions]);
|
|
114
|
+
const getNode = (0, react_1.useCallback)((nodeId) => {
|
|
115
|
+
const node = actions.getNode(nodeId);
|
|
116
|
+
if (!node || !(0, TreeModel_js_1.isTreeModelHierarchyNode)(node)) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return createPresentationHierarchyNode(node, state.model);
|
|
120
|
+
}, [actions, state.model]);
|
|
113
121
|
const expandNode = (0, react_1.useCallback)((nodeId, isExpanded) => {
|
|
114
122
|
actions.expandNode(nodeId, isExpanded);
|
|
115
123
|
}, [actions]);
|
|
@@ -127,8 +135,7 @@ function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformance
|
|
|
127
135
|
return;
|
|
128
136
|
}
|
|
129
137
|
hierarchyProvider.setFormatter(formatter);
|
|
130
|
-
|
|
131
|
-
}, [hierarchyProvider, actions]);
|
|
138
|
+
}, [hierarchyProvider]);
|
|
132
139
|
const getHierarchyLevelDetails = (0, react_1.useCallback)((nodeId) => {
|
|
133
140
|
const node = actions.getNode(nodeId);
|
|
134
141
|
if (!hierarchyProvider || !node || (0, TreeModel_js_1.isTreeModelInfoNode)(node)) {
|
|
@@ -158,6 +165,7 @@ function useTreeInternal({ getHierarchyProvider, getFilteredPaths, onPerformance
|
|
|
158
165
|
reloadTree,
|
|
159
166
|
selectNodes,
|
|
160
167
|
isNodeSelected,
|
|
168
|
+
getTreeModelNode,
|
|
161
169
|
getNode,
|
|
162
170
|
getHierarchyLevelDetails,
|
|
163
171
|
setFormatter,
|
|
@@ -173,11 +181,7 @@ function generateTreeStructure(parentNodeId, model) {
|
|
|
173
181
|
.filter((node) => !!node)
|
|
174
182
|
.map((node) => {
|
|
175
183
|
if ((0, TreeModel_js_1.isTreeModelHierarchyNode)(node)) {
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
...toPresentationHierarchyNodeBase(node),
|
|
179
|
-
children: children ? children : node.children === true ? true : [],
|
|
180
|
-
};
|
|
184
|
+
return createPresentationHierarchyNode(node, model);
|
|
181
185
|
}
|
|
182
186
|
if (node.type === "ResultSetTooLarge") {
|
|
183
187
|
return {
|
|
@@ -202,6 +206,18 @@ function generateTreeStructure(parentNodeId, model) {
|
|
|
202
206
|
};
|
|
203
207
|
});
|
|
204
208
|
}
|
|
209
|
+
function createPresentationHierarchyNode(modelNode, model) {
|
|
210
|
+
let children;
|
|
211
|
+
return {
|
|
212
|
+
...toPresentationHierarchyNodeBase(modelNode),
|
|
213
|
+
get children() {
|
|
214
|
+
if (!children) {
|
|
215
|
+
children = generateTreeStructure(modelNode.id, model);
|
|
216
|
+
}
|
|
217
|
+
return children ? children : modelNode.children === true ? true : [];
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
205
221
|
function toPresentationHierarchyNodeBase(node) {
|
|
206
222
|
return {
|
|
207
223
|
id: node.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseTree.js","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseTree.ts"],"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, useRef, useState } from \"react\";\nimport { isIDisposable } from \"@itwin/core-bentley\";\nimport { GenericInstanceFilter, HierarchyFilteringPath, HierarchyNode, HierarchyProvider } from \"@itwin/presentation-hierarchies\";\nimport { InstanceKey, IPrimitiveValueFormatter } from \"@itwin/presentation-shared\";\nimport { TreeActions } from \"./internal/TreeActions.js\";\nimport { isTreeModelHierarchyNode, isTreeModelInfoNode, TreeModel, TreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from \"./internal/TreeModel.js\";\nimport { useUnifiedTreeSelection, UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection.js\";\nimport { PresentationHierarchyNode, PresentationTreeNode } from \"./TreeNode.js\";\nimport { SelectionChangeType } from \"./UseSelectionHandler.js\";\n\n/**\n * A data structure that contains information about a single hierarchy level.\n * @public\n */\nexport interface HierarchyLevelDetails {\n /** The parent node whose hierarchy level's information is contained in this data structure */\n hierarchyNode: HierarchyNode | undefined;\n\n /** A function to get instance keys of the hierarchy level. */\n getInstanceKeysIterator: (props?: {\n instanceFilter?: GenericInstanceFilter;\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n }) => AsyncIterableIterator<InstanceKey>;\n\n /** Get the limit of how many nodes can be loaded in this hierarchy level. */\n sizeLimit?: number | \"unbounded\";\n /** Set the limit of how many nodes can be loaded in this hierarchy level. */\n setSizeLimit: (value: undefined | number | \"unbounded\") => void;\n\n /** Get the active instance filter applied to this hierarchy level. */\n instanceFilter?: GenericInstanceFilter;\n /** Set the instance filter to apply to this hierarchy level */\n setInstanceFilter: (filter: GenericInstanceFilter | undefined) => void;\n}\n\n/**\n * A React hook that creates state for a tree component.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useUnifiedSelectionTree`\n * @see `useIModelTree`\n * @public\n */\nexport function useTree(props: UseTreeProps): UseTreeResult {\n const { getNode: _, ...rest } = useTreeInternal(props);\n return rest;\n}\n\n/**\n * A React hook that creates state for a tree component, that is integrated with unified selection\n * through context provided by `UnifiedSelectionProvider`.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useTree`\n * @see `useIModelUnifiedSelectionTree`\n * @see `UnifiedSelectionProvider`\n * @public\n */\nexport function useUnifiedSelectionTree({ sourceName, ...props }: UseTreeProps & UseUnifiedTreeSelectionProps): UseTreeResult {\n const { getNode, ...rest } = useTreeInternal(props);\n return { ...rest, ...useUnifiedTreeSelection({ sourceName, getNode }) };\n}\n\n/** @public */\nexport interface UseTreeProps {\n /** Provides the hierarchy provider for the tree. */\n getHierarchyProvider: () => HierarchyProvider;\n /** Provides paths to filtered nodes. */\n getFilteredPaths?: () => Promise<HierarchyFilteringPath[] | undefined>;\n /**\n * Callback that is called just after a certain action is finished.\n * Can be used for performance tracking.\n */\n onPerformanceMeasured?: (action: \"initial-load\" | \"hierarchy-level-load\" | \"reload\", duration: number) => void;\n /** Action to perform when hierarchy level contains more items that the specified limit. */\n onHierarchyLimitExceeded?: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void;\n /** Action to perform when an error occurs while loading hierarchy. */\n onHierarchyLoadError?: (props: { parentId?: string; type: \"timeout\" | \"unknown\" }) => void;\n}\n\n/**\n * Options for doing either full or a sub tree reload.\n * @public\n */\ninterface ReloadTreeOptions {\n /** Specifies parent node under which sub tree should be reloaded. */\n parentNodeId: string | undefined;\n\n /**\n * Specifies how current tree state should be handled:\n * - `keep` - try to keep current tree state (expanded/collapsed nodes, instance filters, etc.).\n * - `discard` - do not try to keep current tree state. Tree model will be update after nodes are reloaded.\n * - `reset` - remove subtree from the model before reloading and reload nodes ignoring cache.\n *\n * Defaults to `\"keep\"`.\n */\n state?: \"keep\" | \"discard\" | \"reset\";\n}\n\n/** @public */\nexport interface UseTreeResult {\n /**\n * Array containing root tree nodes. It is `undefined` on initial render until any nodes are loaded.\n */\n rootNodes: PresentationTreeNode[] | undefined;\n /**\n * Specifies whether tree is loading or not. It is set to `true` when initial tree load is in progress\n * or tree is reloading.\n */\n isLoading: boolean;\n /**\n * A function that should be called to reload the tree.\n */\n reloadTree: (options?: ReloadTreeOptions) => void;\n /**\n * A function that should be called to either expand or collapse the given node.\n */\n expandNode: (nodeId: string, isExpanded: boolean) => void;\n /**\n * A function that should be called to select nodes in the tree.\n * @param nodeIds Ids of the nodes that are selected.\n * @param changeType Type of change that occurred for the selection.\n */\n selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;\n /** Determines whether a given node is selected. */\n isNodeSelected: (nodeId: string) => boolean;\n /** Returns hierarchy level details for a given node ID. */\n getHierarchyLevelDetails: (nodeId: string | undefined) => HierarchyLevelDetails | undefined;\n /** Sets a formatter for the primitive values that are displayed in the hierarchy. */\n setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;\n}\n\ninterface TreeState {\n model: TreeModel;\n rootNodes: Array<PresentationTreeNode> | undefined;\n}\n\nfunction useTreeInternal({\n getHierarchyProvider,\n getFilteredPaths,\n onPerformanceMeasured,\n onHierarchyLimitExceeded,\n onHierarchyLoadError,\n}: UseTreeProps): UseTreeResult & { getNode: (nodeId: string) => TreeModelRootNode | TreeModelNode | undefined } {\n const [state, setState] = useState<TreeState>({\n model: { idToNode: new Map(), parentChildMap: new Map(), rootNode: { id: undefined, nodeData: undefined } },\n rootNodes: undefined,\n });\n const onPerformanceMeasuredRef = useLatest(onPerformanceMeasured);\n const onHierarchyLimitExceededRef = useLatest(onHierarchyLimitExceeded);\n const onHierarchyLoadErrorRef = useLatest(onHierarchyLoadError);\n\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions(\n (model) => {\n const rootNodes = model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model) : undefined;\n setState({\n model,\n rootNodes,\n });\n },\n (actionType, duration) => onPerformanceMeasuredRef.current?.(actionType, duration),\n (props) => onHierarchyLimitExceededRef.current?.(props),\n (props) => onHierarchyLoadErrorRef.current?.(props),\n ),\n );\n const currentFormatter = useRef<IPrimitiveValueFormatter>();\n\n const [hierarchyProvider, setHierarchyProvider] = useState<HierarchyProvider | undefined>();\n useEffect(() => {\n const provider = getHierarchyProvider();\n provider.setFormatter(currentFormatter.current);\n const removeHierarchyChangedListener = provider.hierarchyChanged.addListener(() => actions.reloadTree());\n actions.setHierarchyProvider(provider);\n setHierarchyProvider(provider);\n return () => {\n removeHierarchyChangedListener();\n actions.dispose();\n if (isIDisposable(provider)) {\n provider.dispose();\n }\n };\n }, [actions, getHierarchyProvider]);\n\n const [isFiltering, setIsFiltering] = useState(false);\n useEffect(() => {\n let disposed = false;\n void (async () => {\n if (!getFilteredPaths || !hierarchyProvider) {\n hierarchyProvider?.setHierarchyFilter(undefined);\n actions.reloadTree({ state: \"keep\" });\n setIsFiltering(false);\n return;\n }\n\n setIsFiltering(true);\n let paths: HierarchyFilteringPath[] | undefined;\n try {\n paths = await getFilteredPaths();\n } catch {\n } finally {\n if (!disposed) {\n hierarchyProvider.setHierarchyFilter(paths ? { paths } : undefined);\n actions.reloadTree({ state: paths ? \"discard\" : \"keep\" });\n setIsFiltering(false);\n }\n }\n })();\n return () => {\n disposed = true;\n actions.dispose();\n };\n }, [actions, hierarchyProvider, getFilteredPaths]);\n\n const getNode = useCallback<(nodeId: string) => TreeModelRootNode | TreeModelNode | undefined>(\n (nodeId: string) => {\n return actions.getNode(nodeId);\n },\n [actions],\n );\n\n const expandNode = useCallback<UseTreeResult[\"expandNode\"]>(\n (nodeId: string, isExpanded: boolean) => {\n actions.expandNode(nodeId, isExpanded);\n },\n [actions],\n );\n\n const reloadTree = useCallback<UseTreeResult[\"reloadTree\"]>(\n (options) => {\n actions.reloadTree(options);\n },\n [actions],\n );\n\n const selectNodes = useCallback<UseTreeResult[\"selectNodes\"]>(\n (nodeIds: Array<string>, changeType: SelectionChangeType) => {\n actions.selectNodes(nodeIds, changeType);\n },\n [actions],\n );\n\n const isNodeSelected = useCallback<UseTreeResult[\"isNodeSelected\"]>((nodeId: string) => TreeModel.isNodeSelected(state.model, nodeId), [state]);\n\n const setFormatter = useCallback<UseTreeResult[\"setFormatter\"]>(\n (formatter: IPrimitiveValueFormatter | undefined) => {\n currentFormatter.current = formatter;\n /* c8 ignore next 3 */\n if (!hierarchyProvider) {\n return;\n }\n\n hierarchyProvider.setFormatter(formatter);\n actions.reloadTree();\n },\n [hierarchyProvider, actions],\n );\n\n const getHierarchyLevelDetails = useCallback<UseTreeResult[\"getHierarchyLevelDetails\"]>(\n (nodeId) => {\n const node = actions.getNode(nodeId);\n if (!hierarchyProvider || !node || isTreeModelInfoNode(node)) {\n return undefined;\n }\n const hierarchyNode = node.nodeData;\n if (hierarchyNode && HierarchyNode.isGroupingNode(hierarchyNode)) {\n return undefined;\n }\n\n return {\n hierarchyNode,\n getInstanceKeysIterator: (props) =>\n hierarchyProvider.getNodeInstanceKeys({\n parentNode: hierarchyNode,\n instanceFilter: props?.instanceFilter,\n hierarchyLevelSizeLimit: props?.hierarchyLevelSizeLimit,\n }),\n instanceFilter: node.instanceFilter,\n setInstanceFilter: (filter) => actions.setInstanceFilter(nodeId, filter),\n sizeLimit: node.hierarchyLimit,\n setSizeLimit: (value) => actions.setHierarchyLimit(nodeId, value),\n };\n },\n [actions, hierarchyProvider],\n );\n\n return {\n rootNodes: state.rootNodes,\n isLoading: !!state.model.rootNode.isLoading || isFiltering,\n expandNode,\n reloadTree,\n selectNodes,\n isNodeSelected,\n getNode,\n getHierarchyLevelDetails,\n setFormatter,\n };\n}\n\nfunction generateTreeStructure(parentNodeId: string | undefined, model: TreeModel): Array<PresentationTreeNode> | undefined {\n const currentChildren = model.parentChildMap.get(parentNodeId);\n if (!currentChildren) {\n return undefined;\n }\n\n return currentChildren\n .map((childId) => model.idToNode.get(childId))\n .filter((node): node is TreeModelNode => !!node)\n .map<PresentationTreeNode>((node) => {\n if (isTreeModelHierarchyNode(node)) {\n const children = generateTreeStructure(node.id, model);\n return {\n ...toPresentationHierarchyNodeBase(node),\n children: children ? children : node.children === true ? true : [],\n };\n }\n\n if (node.type === \"ResultSetTooLarge\") {\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n resultSetSizeLimit: node.resultSetSizeLimit,\n };\n }\n\n if (node.type === \"NoFilterMatches\") {\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n };\n }\n\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n message: node.message,\n };\n });\n}\n\nfunction toPresentationHierarchyNodeBase(node: TreeModelHierarchyNode): Omit<PresentationHierarchyNode, \"children\"> {\n return {\n id: node.id,\n label: node.label,\n nodeData: node.nodeData,\n isLoading: !!node.isLoading,\n isExpanded: !!node.isExpanded,\n isFilterable: !HierarchyNode.isGroupingNode(node.nodeData) && !!node.nodeData.supportsFiltering && node.children,\n isFiltered: !!node.instanceFilter,\n extendedData: node.nodeData.extendedData,\n };\n}\n\nfunction useLatest<T>(value: T) {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"UseTree.js","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseTree.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;AAiDhG,0BAGC;AAgBD,0DAMC;AAxED,iCAAiE;AACjE,8EAAkI;AAElI,8DAAwD;AACxD,0DAA6J;AAC7J,8EAA0G;AAC1G,kDAAkD;AA6BlD;;;;;;;;;;;GAWG;AACH,SAAgB,OAAO,CAAC,KAAmB;IACzC,MAAM,EAAE,gBAAgB,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,uBAAuB,CAAC,EAAE,UAAU,EAAE,GAAG,KAAK,EAA+C;IAC3G,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC7D,OAAO;QACL,GAAG,IAAI;QACP,GAAG,IAAA,gDAAuB,EAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC;AA8ED,SAAS,eAAe,CAAC,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,GACP;IAGb,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAY;QAC5C,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;QAC3G,SAAS,EAAE,SAAS;KACrB,CAAC,CAAC;IACH,MAAM,wBAAwB,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;IAClE,MAAM,2BAA2B,GAAG,SAAS,CAAC,wBAAwB,CAAC,CAAC;IACxE,MAAM,uBAAuB,GAAG,SAAS,CAAC,oBAAoB,CAAC,CAAC;IAEhE,MAAM,CAAC,OAAO,CAAC,GAAG,IAAA,gBAAQ,EACxB,GAAG,EAAE,CACH,IAAI,4BAAW,CACb,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1H,QAAQ,CAAC;YACP,KAAK;YACL,SAAS;SACV,CAAC,CAAC;IACL,CAAC,EACD,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,wBAAwB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,EAClF,CAAC,KAAK,EAAE,EAAE,CAAC,2BAA2B,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,EACvD,CAAC,KAAK,EAAE,EAAE,CAAC,uBAAuB,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CACpD,CACJ,CAAC;IACF,MAAM,gBAAgB,GAAG,IAAA,cAAM,GAA4B,CAAC;IAE5D,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,IAAA,gBAAQ,GAAiC,CAAC;IAC5F,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;QACxC,QAAQ,CAAC,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,8BAA8B,GAAG,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,mBAAmB,EAAE,EAAE;YACnG,MAAM,kBAAkB,GAAG,mBAAmB,EAAE,YAAY,EAAE,SAAS,KAAK,SAAS,CAAC;YACtF,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QACvC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC/B,OAAO,GAAG,EAAE;YACV,8BAA8B,EAAE,CAAC;YACjC,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,IAAA,sBAAW,EAAC,QAAQ,CAAC,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAEpC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IACtD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC,gBAAgB,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC5C,iBAAiB,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;gBACjD,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,IAAI,KAA2C,CAAC;YAChD,IAAI,CAAC;gBACH,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;YACT,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,iBAAiB,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;oBACpE,cAAc,CAAC,KAAK,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,GAAG,EAAE;YACV,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE1C,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAClC,CAAC,MAAc,EAAE,EAAE;QACjB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,OAAO,GAAG,IAAA,mBAAW,EACzB,CAAC,MAAc,EAAyC,EAAE;QACxD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAA,uCAAwB,EAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,+BAA+B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC,EACD,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CACvB,CAAC;IAEF,MAAM,UAAU,GAAG,IAAA,mBAAW,EAC5B,CAAC,MAAc,EAAE,UAAmB,EAAE,EAAE;QACtC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,UAAU,GAAG,IAAA,mBAAW,EAC5B,CAAC,OAAO,EAAE,EAAE;QACV,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,WAAW,GAAG,IAAA,mBAAW,EAC7B,CAAC,OAAsB,EAAE,UAA+B,EAAE,EAAE;QAC1D,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,cAAc,GAAG,IAAA,mBAAW,EAAkC,CAAC,MAAc,EAAE,EAAE,CAAC,wBAAS,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEhJ,MAAM,YAAY,GAAG,IAAA,mBAAW,EAC9B,CAAC,SAA+C,EAAE,EAAE;QAClD,gBAAgB,CAAC,OAAO,GAAG,SAAS,CAAC;QACrC,sBAAsB;QACtB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,iBAAiB,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC,EACD,CAAC,iBAAiB,CAAC,CACpB,CAAC;IAEF,MAAM,wBAAwB,GAAG,IAAA,mBAAW,EAC1C,CAAC,MAAM,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,IAAI,IAAA,kCAAmB,EAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpC,IAAI,aAAa,IAAI,wCAAa,CAAC,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC;YACjE,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO;YACL,aAAa;YACb,uBAAuB,EAAE,CAAC,KAAK,EAAE,EAAE,CACjC,iBAAiB,CAAC,mBAAmB,CAAC;gBACpC,UAAU,EAAE,aAAa;gBACzB,cAAc,EAAE,KAAK,EAAE,cAAc;gBACrC,uBAAuB,EAAE,KAAK,EAAE,uBAAuB;aACxD,CAAC;YACJ,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC;YACxE,SAAS,EAAE,IAAI,CAAC,cAAc;YAC9B,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC;SAClE,CAAC;IACJ,CAAC,EACD,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAC7B,CAAC;IAEF,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,IAAI,WAAW;QAC1D,UAAU;QACV,UAAU;QACV,WAAW;QACX,cAAc;QACd,gBAAgB;QAChB,OAAO;QACP,wBAAwB;QACxB,YAAY;KACb,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,YAAgC,EAAE,KAAgB;IAC/E,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/D,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,eAAe;SACnB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;SAC7C,MAAM,CAAC,CAAC,IAAI,EAAyB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAC/C,GAAG,CAAuB,CAAC,IAAI,EAAE,EAAE;QAClC,IAAI,IAAA,uCAAwB,EAAC,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,+BAA+B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACtC,OAAO;gBACL,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,YAAY;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;aAC5C,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACpC,OAAO;gBACL,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,YAAY;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,YAAY;YACZ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,+BAA+B,CAAC,SAAiC,EAAE,KAAgB;IAC1F,IAAI,QAAiD,CAAC;IACtD,OAAO;QACL,GAAG,+BAA+B,CAAC,SAAS,CAAC;QAC7C,IAAI,QAAQ;YACV,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,IAA4B;IACnE,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS;QAC3B,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU;QAC7B,YAAY,EAAE,CAAC,wCAAa,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,IAAI,IAAI,CAAC,QAAQ;QAChH,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc;QACjC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;KACzC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAI,KAAQ;IAC5B,MAAM,GAAG,GAAG,IAAA,cAAM,EAAC,KAAK,CAAC,CAAC;IAC1B,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,GAAG,CAAC;AACb,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, useRef, useState } from \"react\";\nimport { GenericInstanceFilter, HierarchyFilteringPath, HierarchyNode, HierarchyProvider } from \"@itwin/presentation-hierarchies\";\nimport { InstanceKey, IPrimitiveValueFormatter } from \"@itwin/presentation-shared\";\nimport { TreeActions } from \"./internal/TreeActions.js\";\nimport { isTreeModelHierarchyNode, isTreeModelInfoNode, TreeModel, TreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from \"./internal/TreeModel.js\";\nimport { useUnifiedTreeSelection, UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection.js\";\nimport { safeDispose } from \"./internal/Utils.js\";\nimport { PresentationHierarchyNode, PresentationTreeNode } from \"./TreeNode.js\";\nimport { SelectionChangeType } from \"./UseSelectionHandler.js\";\n\n/**\n * A data structure that contains information about a single hierarchy level.\n * @public\n */\nexport interface HierarchyLevelDetails {\n /** The parent node whose hierarchy level's information is contained in this data structure */\n hierarchyNode: HierarchyNode | undefined;\n\n /** A function to get instance keys of the hierarchy level. */\n getInstanceKeysIterator: (props?: {\n instanceFilter?: GenericInstanceFilter;\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n }) => AsyncIterableIterator<InstanceKey>;\n\n /** Get the limit of how many nodes can be loaded in this hierarchy level. */\n sizeLimit?: number | \"unbounded\";\n /** Set the limit of how many nodes can be loaded in this hierarchy level. */\n setSizeLimit: (value: undefined | number | \"unbounded\") => void;\n\n /** Get the active instance filter applied to this hierarchy level. */\n instanceFilter?: GenericInstanceFilter;\n /** Set the instance filter to apply to this hierarchy level */\n setInstanceFilter: (filter: GenericInstanceFilter | undefined) => void;\n}\n\n/**\n * A React hook that creates state for a tree component.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useUnifiedSelectionTree`\n * @see `useIModelTree`\n * @public\n */\nexport function useTree(props: UseTreeProps): UseTreeResult {\n const { getTreeModelNode: _, ...rest } = useTreeInternal(props);\n return rest;\n}\n\n/**\n * A React hook that creates state for a tree component, that is integrated with unified selection\n * through context provided by `UnifiedSelectionProvider`.\n *\n * The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a\n * component-agnostic result which may be used to render the hierarchy using any UI framework.\n *\n * See `README.md` for an example\n *\n * @see `useTree`\n * @see `useIModelUnifiedSelectionTree`\n * @see `UnifiedSelectionProvider`\n * @public\n */\nexport function useUnifiedSelectionTree({ sourceName, ...props }: UseTreeProps & UseUnifiedTreeSelectionProps): UseTreeResult {\n const { getTreeModelNode, ...rest } = useTreeInternal(props);\n return {\n ...rest,\n ...useUnifiedTreeSelection({ sourceName, getTreeModelNode }),\n };\n}\n\n/** @public */\nexport interface UseTreeProps {\n /** Provides the hierarchy provider for the tree. */\n getHierarchyProvider: () => HierarchyProvider;\n /** Provides paths to filtered nodes. */\n getFilteredPaths?: () => Promise<HierarchyFilteringPath[] | undefined>;\n /**\n * Callback that is called just after a certain action is finished.\n * Can be used for performance tracking.\n */\n onPerformanceMeasured?: (action: \"initial-load\" | \"hierarchy-level-load\" | \"reload\", duration: number) => void;\n /** Action to perform when hierarchy level contains more items that the specified limit. */\n onHierarchyLimitExceeded?: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void;\n /** Action to perform when an error occurs while loading hierarchy. */\n onHierarchyLoadError?: (props: { parentId?: string; type: \"timeout\" | \"unknown\" }) => void;\n}\n\n/**\n * Options for doing either full or a sub tree reload.\n * @public\n */\ninterface ReloadTreeOptions {\n /** Specifies parent node under which sub tree should be reloaded. */\n parentNodeId: string | undefined;\n\n /**\n * Specifies how current tree state should be handled:\n * - `keep` - try to keep current tree state (expanded/collapsed nodes, instance filters, etc.).\n * - `discard` - do not try to keep current tree state. Tree model will be update after nodes are reloaded.\n * - `reset` - remove subtree from the model before reloading and reload nodes ignoring cache.\n *\n * Defaults to `\"keep\"`.\n */\n state?: \"keep\" | \"discard\" | \"reset\";\n}\n\n/** @public */\nexport interface UseTreeResult {\n /**\n * Array containing root tree nodes. It is `undefined` on initial render until any nodes are loaded.\n */\n rootNodes: PresentationTreeNode[] | undefined;\n /**\n * Specifies whether tree is loading or not. It is set to `true` when initial tree load is in progress\n * or tree is reloading.\n */\n isLoading: boolean;\n /**\n * A function that should be called to reload the tree.\n */\n reloadTree: (options?: ReloadTreeOptions) => void;\n /**\n * A function that should be called to either expand or collapse the given node.\n */\n expandNode: (nodeId: string, isExpanded: boolean) => void;\n /**\n * A function that should be called to select nodes in the tree.\n * @param nodeIds Ids of the nodes that are selected.\n * @param changeType Type of change that occurred for the selection.\n */\n selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;\n /** Determines whether a given node is selected. */\n isNodeSelected: (nodeId: string) => boolean;\n /** Get a tree node by id */\n getNode: (nodeId: string) => PresentationHierarchyNode | undefined;\n /** Returns hierarchy level details for a given node ID. */\n getHierarchyLevelDetails: (nodeId: string | undefined) => HierarchyLevelDetails | undefined;\n /** Sets a formatter for the primitive values that are displayed in the hierarchy. */\n setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;\n}\n\ninterface TreeState {\n model: TreeModel;\n rootNodes: Array<PresentationTreeNode> | undefined;\n}\n\nfunction useTreeInternal({\n getHierarchyProvider,\n getFilteredPaths,\n onPerformanceMeasured,\n onHierarchyLimitExceeded,\n onHierarchyLoadError,\n}: UseTreeProps): UseTreeResult & {\n getTreeModelNode: (nodeId: string) => TreeModelRootNode | TreeModelNode | undefined;\n} {\n const [state, setState] = useState<TreeState>({\n model: { idToNode: new Map(), parentChildMap: new Map(), rootNode: { id: undefined, nodeData: undefined } },\n rootNodes: undefined,\n });\n const onPerformanceMeasuredRef = useLatest(onPerformanceMeasured);\n const onHierarchyLimitExceededRef = useLatest(onHierarchyLimitExceeded);\n const onHierarchyLoadErrorRef = useLatest(onHierarchyLoadError);\n\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions(\n (model) => {\n const rootNodes = model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model) : undefined;\n setState({\n model,\n rootNodes,\n });\n },\n (actionType, duration) => onPerformanceMeasuredRef.current?.(actionType, duration),\n (props) => onHierarchyLimitExceededRef.current?.(props),\n (props) => onHierarchyLoadErrorRef.current?.(props),\n ),\n );\n const currentFormatter = useRef<IPrimitiveValueFormatter>();\n\n const [hierarchyProvider, setHierarchyProvider] = useState<HierarchyProvider | undefined>();\n useEffect(() => {\n const provider = getHierarchyProvider();\n provider.setFormatter(currentFormatter.current);\n const removeHierarchyChangedListener = provider.hierarchyChanged.addListener((hierarchyChangeArgs) => {\n const shouldDiscardState = hierarchyChangeArgs?.filterChange?.newFilter !== undefined;\n actions.reloadTree({ state: shouldDiscardState ? \"discard\" : \"keep\" });\n });\n actions.setHierarchyProvider(provider);\n setHierarchyProvider(provider);\n return () => {\n removeHierarchyChangedListener();\n actions.reset();\n safeDispose(provider);\n };\n }, [actions, getHierarchyProvider]);\n\n const [isFiltering, setIsFiltering] = useState(false);\n useEffect(() => {\n let disposed = false;\n void (async () => {\n if (!getFilteredPaths || !hierarchyProvider) {\n hierarchyProvider?.setHierarchyFilter(undefined);\n setIsFiltering(false);\n return;\n }\n\n setIsFiltering(true);\n let paths: HierarchyFilteringPath[] | undefined;\n try {\n paths = await getFilteredPaths();\n } catch {\n } finally {\n if (!disposed) {\n hierarchyProvider.setHierarchyFilter(paths ? { paths } : undefined);\n setIsFiltering(false);\n }\n }\n })();\n return () => {\n disposed = true;\n };\n }, [hierarchyProvider, getFilteredPaths]);\n\n const getTreeModelNode = useCallback<(nodeId: string) => TreeModelRootNode | TreeModelNode | undefined>(\n (nodeId: string) => {\n return actions.getNode(nodeId);\n },\n [actions],\n );\n\n const getNode = useCallback(\n (nodeId: string): PresentationHierarchyNode | undefined => {\n const node = actions.getNode(nodeId);\n if (!node || !isTreeModelHierarchyNode(node)) {\n return undefined;\n }\n return createPresentationHierarchyNode(node, state.model);\n },\n [actions, state.model],\n );\n\n const expandNode = useCallback<UseTreeResult[\"expandNode\"]>(\n (nodeId: string, isExpanded: boolean) => {\n actions.expandNode(nodeId, isExpanded);\n },\n [actions],\n );\n\n const reloadTree = useCallback<UseTreeResult[\"reloadTree\"]>(\n (options) => {\n actions.reloadTree(options);\n },\n [actions],\n );\n\n const selectNodes = useCallback<UseTreeResult[\"selectNodes\"]>(\n (nodeIds: Array<string>, changeType: SelectionChangeType) => {\n actions.selectNodes(nodeIds, changeType);\n },\n [actions],\n );\n\n const isNodeSelected = useCallback<UseTreeResult[\"isNodeSelected\"]>((nodeId: string) => TreeModel.isNodeSelected(state.model, nodeId), [state]);\n\n const setFormatter = useCallback<UseTreeResult[\"setFormatter\"]>(\n (formatter: IPrimitiveValueFormatter | undefined) => {\n currentFormatter.current = formatter;\n /* c8 ignore next 3 */\n if (!hierarchyProvider) {\n return;\n }\n\n hierarchyProvider.setFormatter(formatter);\n },\n [hierarchyProvider],\n );\n\n const getHierarchyLevelDetails = useCallback<UseTreeResult[\"getHierarchyLevelDetails\"]>(\n (nodeId) => {\n const node = actions.getNode(nodeId);\n if (!hierarchyProvider || !node || isTreeModelInfoNode(node)) {\n return undefined;\n }\n const hierarchyNode = node.nodeData;\n if (hierarchyNode && HierarchyNode.isGroupingNode(hierarchyNode)) {\n return undefined;\n }\n\n return {\n hierarchyNode,\n getInstanceKeysIterator: (props) =>\n hierarchyProvider.getNodeInstanceKeys({\n parentNode: hierarchyNode,\n instanceFilter: props?.instanceFilter,\n hierarchyLevelSizeLimit: props?.hierarchyLevelSizeLimit,\n }),\n instanceFilter: node.instanceFilter,\n setInstanceFilter: (filter) => actions.setInstanceFilter(nodeId, filter),\n sizeLimit: node.hierarchyLimit,\n setSizeLimit: (value) => actions.setHierarchyLimit(nodeId, value),\n };\n },\n [actions, hierarchyProvider],\n );\n\n return {\n rootNodes: state.rootNodes,\n isLoading: !!state.model.rootNode.isLoading || isFiltering,\n expandNode,\n reloadTree,\n selectNodes,\n isNodeSelected,\n getTreeModelNode,\n getNode,\n getHierarchyLevelDetails,\n setFormatter,\n };\n}\n\nfunction generateTreeStructure(parentNodeId: string | undefined, model: TreeModel): Array<PresentationTreeNode> | undefined {\n const currentChildren = model.parentChildMap.get(parentNodeId);\n if (!currentChildren) {\n return undefined;\n }\n\n return currentChildren\n .map((childId) => model.idToNode.get(childId))\n .filter((node): node is TreeModelNode => !!node)\n .map<PresentationTreeNode>((node) => {\n if (isTreeModelHierarchyNode(node)) {\n return createPresentationHierarchyNode(node, model);\n }\n\n if (node.type === \"ResultSetTooLarge\") {\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n resultSetSizeLimit: node.resultSetSizeLimit,\n };\n }\n\n if (node.type === \"NoFilterMatches\") {\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n };\n }\n\n return {\n id: node.id,\n parentNodeId,\n type: node.type,\n message: node.message,\n };\n });\n}\n\nfunction createPresentationHierarchyNode(modelNode: TreeModelHierarchyNode, model: TreeModel): PresentationHierarchyNode {\n let children: Array<PresentationTreeNode> | undefined;\n return {\n ...toPresentationHierarchyNodeBase(modelNode),\n get children() {\n if (!children) {\n children = generateTreeStructure(modelNode.id, model);\n }\n return children ? children : modelNode.children === true ? true : [];\n },\n };\n}\n\nfunction toPresentationHierarchyNodeBase(node: TreeModelHierarchyNode): Omit<PresentationHierarchyNode, \"children\"> {\n return {\n id: node.id,\n label: node.label,\n nodeData: node.nodeData,\n isLoading: !!node.isLoading,\n isExpanded: !!node.isExpanded,\n isFilterable: !HierarchyNode.isGroupingNode(node.nodeData) && !!node.nodeData.supportsFiltering && node.children,\n isFiltered: !!node.instanceFilter,\n extendedData: node.nodeData.extendedData,\n };\n}\n\nfunction useLatest<T>(value: T) {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n"]}
|
|
@@ -10,7 +10,7 @@ export declare class TreeActions {
|
|
|
10
10
|
private _loader;
|
|
11
11
|
private _nodeIdFactory;
|
|
12
12
|
private _currentModel;
|
|
13
|
-
private
|
|
13
|
+
private _reset;
|
|
14
14
|
constructor(_onModelChanged: (model: TreeModel) => void, _onLoad: (actionType: "initial-load" | "hierarchy-level-load" | "reload", duration: number) => void, _onHierarchyLimitExceeded: (props: {
|
|
15
15
|
parentId?: string;
|
|
16
16
|
filter?: GenericInstanceFilter;
|
|
@@ -26,7 +26,7 @@ export declare class TreeActions {
|
|
|
26
26
|
private loadSubTree;
|
|
27
27
|
private loadNodes;
|
|
28
28
|
private reloadSubTree;
|
|
29
|
-
|
|
29
|
+
reset(): void;
|
|
30
30
|
setHierarchyProvider(provider?: HierarchyProvider): void;
|
|
31
31
|
getNode(nodeId: string | undefined): TreeModelNode | TreeModelRootNode | undefined;
|
|
32
32
|
selectNodes(nodeIds: Array<string>, changeType: SelectionChangeType): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeActions.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeActions.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,EAAiD,SAAS,EAA0B,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKpJ,gBAAgB;AAChB,qBAAa,WAAW;IAOpB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,yBAAyB;IACjC,OAAO,CAAC,qBAAqB;IAT/B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,cAAc,CAA8D;IACpF,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"TreeActions.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeActions.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,EAAiD,SAAS,EAA0B,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKpJ,gBAAgB;AAChB,qBAAa,WAAW;IAOpB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,yBAAyB;IACjC,OAAO,CAAC,qBAAqB;IAT/B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,cAAc,CAA8D;IACpF,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,MAAM,CAAuB;gBAG3B,eAAe,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,EAC3C,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,GAAG,sBAAsB,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,EACnG,yBAAyB,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;KAAE,KAAK,IAAI,EAC/H,qBAAqB,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,EAClG,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,YAAY,CAAC,KAAK,MAAM,EAC3E,IAAI,CAAC,EAAE,SAAS;IAWlB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,aAAa;IAuCd,KAAK;IAIL,oBAAoB,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAiBjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,iBAAiB,GAAG,SAAS;IAIlF,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,mBAAmB;IAMnE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO;IAa9C,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW;IAc1E,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,qBAAqB;IAc5E,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;KAAE;CAa5F"}
|
|
@@ -21,7 +21,7 @@ class TreeActions {
|
|
|
21
21
|
_loader;
|
|
22
22
|
_nodeIdFactory;
|
|
23
23
|
_currentModel;
|
|
24
|
-
|
|
24
|
+
_reset = new rxjs_1.Subject();
|
|
25
25
|
constructor(_onModelChanged, _onLoad, _onHierarchyLimitExceeded, _onHierarchyLoadError, nodeIdFactory, seed) {
|
|
26
26
|
this._onModelChanged = _onModelChanged;
|
|
27
27
|
this._onLoad = _onLoad;
|
|
@@ -62,7 +62,7 @@ class TreeActions {
|
|
|
62
62
|
const parentId = options.parent.id;
|
|
63
63
|
this._loader
|
|
64
64
|
.loadNodes(options)
|
|
65
|
-
.pipe(collectTreePartsUntil(this.
|
|
65
|
+
.pipe(collectTreePartsUntil(this._reset, initialRootNode))
|
|
66
66
|
.subscribe({
|
|
67
67
|
next: (newModel) => {
|
|
68
68
|
const childNodes = newModel.parentChildMap.get(parentId);
|
|
@@ -75,7 +75,7 @@ class TreeActions {
|
|
|
75
75
|
},
|
|
76
76
|
complete: () => {
|
|
77
77
|
this.onLoadingComplete(parentId);
|
|
78
|
-
timeTracker.dispose();
|
|
78
|
+
timeTracker[Symbol.dispose]();
|
|
79
79
|
},
|
|
80
80
|
});
|
|
81
81
|
}
|
|
@@ -120,12 +120,12 @@ class TreeActions {
|
|
|
120
120
|
}
|
|
121
121
|
if (parentId === undefined) {
|
|
122
122
|
// cancel all ongoing requests
|
|
123
|
-
this.
|
|
123
|
+
this._reset.next();
|
|
124
124
|
}
|
|
125
125
|
this.loadSubTree({ parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode, ignoreCache: options?.ignoreCache }, !!options?.discardState ? undefined : { ...currModel.rootNode });
|
|
126
126
|
}
|
|
127
|
-
|
|
128
|
-
this.
|
|
127
|
+
reset() {
|
|
128
|
+
this._reset.next();
|
|
129
129
|
}
|
|
130
130
|
setHierarchyProvider(provider) {
|
|
131
131
|
this._loader = provider
|
|
@@ -269,7 +269,7 @@ class TimeTracker {
|
|
|
269
269
|
this._onFinish = _onFinish;
|
|
270
270
|
this._start = Date.now();
|
|
271
271
|
}
|
|
272
|
-
dispose() {
|
|
272
|
+
[Symbol.dispose]() {
|
|
273
273
|
this._stopped = true;
|
|
274
274
|
}
|
|
275
275
|
finish() {
|