@itwin/presentation-hierarchies-react 0.1.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 +14 -0
- package/LICENSE.md +9 -0
- package/README.md +303 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts +75 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.js +16 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js +28 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js +102 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts +85 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.js +214 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js +236 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js +71 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js +154 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js +96 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js +45 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js +35 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +101 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js +83 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react.d.ts +10 -0
- package/lib/cjs/presentation-hierarchies-react.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react.js +27 -0
- package/lib/cjs/presentation-hierarchies-react.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts +75 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.js +12 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js +23 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js +98 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts +85 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.js +209 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js +232 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js +67 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js +149 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js +92 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js +40 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js +30 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +94 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js +78 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react.d.ts +10 -0
- package/lib/esm/presentation-hierarchies-react.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react.js +13 -0
- package/lib/esm/presentation-hierarchies-react.js.map +1 -0
- package/package.json +103 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UseSelectionHandler.js","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseSelectionHandler.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 { useEffect, useRef } from \"react\";\nimport { isPresentationHierarchyNode, PresentationTreeNode } from \"./TreeNode\";\nimport { useTree } from \"./UseTree\";\n\n/**\n * A union of different supported selection modes in a tree component:\n * - `none` - no selection is allowed,\n * - `single` - only one node can be selected at a time,\n * - `extended` - multiple nodes can be selected using shift and ctrl keys,\n * - `multiple` - multiple nodes can be selected without using shift or ctrl keys.\n *\n * @internal\n */\nexport type SelectionMode = \"none\" | \"single\" | \"extended\" | \"multiple\";\n\n/** @internal */\nexport type SelectionChangeType = \"add\" | \"replace\" | \"remove\";\n\n/** Props for `useSelectionHandler` hook. */\ntype UseSelectionHandlerProps = Pick<ReturnType<typeof useTree>, \"rootNodes\" | \"selectNodes\"> & {\n /** Selection mode that the component is working in. */\n selectionMode: SelectionMode;\n};\n\n/** Result of `useSelectionHandler` hook. */\ninterface UseSelectionHandlerResult {\n /** Should be called by node renderer when a node component is clicked. */\n onNodeClick: (nodeId: string, isSelected: boolean, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n /** Should be called by node renderer when a keyboard event happens on a node. */\n onNodeKeyDown: (nodeId: string, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => void;\n}\n\ninterface FlatTreeState {\n flatNodeList: Array<string>;\n nodeIdToIndexMap: Map<string, number>;\n}\n\n/**\n * A react hook that helps implement different selection modes in a tree component created using `useTree` hook.\n * @beta\n */\nexport function useSelectionHandler(props: UseSelectionHandlerProps): UseSelectionHandlerResult {\n const { rootNodes, selectionMode, selectNodes } = props;\n const previousSelectionRef = useRef<string | undefined>(undefined);\n const state = useRef<FlatTreeState>({\n flatNodeList: [],\n nodeIdToIndexMap: new Map(),\n });\n\n useEffect(() => {\n if (!rootNodes) {\n return;\n }\n state.current = computeFlatNodeList(rootNodes);\n }, [rootNodes]);\n\n const getNodeRange = (firstId?: string, secondId?: string) => {\n const getIndex = (nodeId?: string) => {\n return nodeId ? state.current.nodeIdToIndexMap.get(nodeId) : 0;\n };\n const firstIndex = getIndex(firstId);\n const secondIndex = getIndex(secondId);\n if (firstIndex === undefined || secondIndex === undefined) {\n return [];\n }\n\n const startingIndex = Math.min(firstIndex, secondIndex);\n const endIndex = Math.max(firstIndex, secondIndex);\n return state.current.flatNodeList.slice(startingIndex, endIndex + 1);\n };\n\n const onNodeSelect = (nodeId: string, isSelected: boolean, shiftDown: boolean, ctrlDown: boolean) => {\n const selection = getSelectionAction(selectionMode, isSelected, shiftDown, ctrlDown);\n if (selection.type === \"disabled\") {\n return;\n }\n\n const nodes = selection.select === \"range\" ? getNodeRange(previousSelectionRef.current, nodeId) : [nodeId];\n if (!nodes.length) {\n return;\n }\n\n selection.select !== \"range\" && (previousSelectionRef.current = nodeId);\n selectNodes(nodes, selection.type);\n };\n\n const onNodeClick = (nodeId: string, isSelected: boolean, event: React.MouseEvent<HTMLElement, MouseEvent>) => {\n return onNodeSelect(nodeId, isSelected, event.shiftKey, event.ctrlKey);\n };\n\n const onNodeKeyDown = (nodeId: string, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === \" \" || event.key === \"Spacebar\" || event.key === \"Enter\") {\n return onNodeSelect(nodeId, isSelected, event.shiftKey, event.ctrlKey);\n }\n };\n\n return { onNodeClick, onNodeKeyDown };\n}\n\ninterface SelectionAction {\n select: \"node\" | \"range\";\n type: SelectionChangeType | \"disabled\";\n}\n\nfunction getSelectionAction(selectionMode: SelectionMode, isSelected: boolean, shiftDown: boolean, ctrlDown: boolean): SelectionAction {\n switch (selectionMode) {\n case \"none\":\n return { select: \"node\", type: \"disabled\" };\n case \"single\":\n return { select: \"node\", type: isSelected ? \"replace\" : \"remove\" };\n case \"multiple\":\n return { select: \"node\", type: isSelected ? \"add\" : \"remove\" };\n case \"extended\":\n return getExtendedSelectionAction(isSelected, shiftDown, ctrlDown);\n }\n}\n\nfunction getExtendedSelectionAction(isSelected: boolean, shiftDown: boolean, ctrlDown: boolean): SelectionAction {\n if (shiftDown) {\n return { select: \"range\", type: \"replace\" };\n }\n if (!isSelected) {\n return { select: \"node\", type: \"remove\" };\n }\n\n return { select: \"node\", type: ctrlDown ? \"add\" : \"replace\" };\n}\n\nfunction computeFlatNodeList(rootNodes: Array<PresentationTreeNode>): FlatTreeState {\n const flatNodeList: Array<string> = [];\n const nodeIdToIndexMap: Map<string, number> = new Map();\n\n const flattenNodeRecursively = (nodes: Array<PresentationTreeNode>) => {\n nodes.forEach((node) => {\n if (!isPresentationHierarchyNode(node)) {\n return;\n }\n nodeIdToIndexMap.set(node.id, flatNodeList.length);\n flatNodeList.push(node.id);\n if (node.isExpanded && typeof node.children !== \"boolean\") {\n flattenNodeRecursively(node.children);\n }\n });\n };\n\n flattenNodeRecursively(rootNodes);\n return { flatNodeList, nodeIdToIndexMap };\n}\n"]}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createHierarchyProvider, GenericInstanceFilter, HierarchyDefinition, HierarchyNode, HierarchyNodeIdentifiersPath, LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
|
|
2
|
+
import { ECClassHierarchyInspector, ECSchemaProvider, InstanceKey, IPrimitiveValueFormatter } from "@itwin/presentation-shared";
|
|
3
|
+
import { UseUnifiedTreeSelectionProps } from "./internal/UseUnifiedSelection";
|
|
4
|
+
import { PresentationTreeNode } from "./TreeNode";
|
|
5
|
+
import { SelectionChangeType } from "./UseSelectionHandler";
|
|
6
|
+
/**
|
|
7
|
+
* A data structure that contains information about a single hierarchy level.
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
export interface HierarchyLevelDetails {
|
|
11
|
+
/** The parent node whose hierarchy level's information is contained in this data structure */
|
|
12
|
+
hierarchyNode: HierarchyNode | undefined;
|
|
13
|
+
/** A function to get instance keys of the hierarchy level. */
|
|
14
|
+
getInstanceKeysIterator: (props?: {
|
|
15
|
+
instanceFilter?: GenericInstanceFilter;
|
|
16
|
+
hierarchyLevelSizeLimit?: number | "unbounded";
|
|
17
|
+
}) => AsyncIterableIterator<InstanceKey>;
|
|
18
|
+
/** Get the limit of how many nodes can be loaded in this hierarchy level. */
|
|
19
|
+
sizeLimit?: number | "unbounded";
|
|
20
|
+
/** Set the limit of how many nodes can be loaded in this hierarchy level. */
|
|
21
|
+
setSizeLimit: (value: undefined | number | "unbounded") => void;
|
|
22
|
+
/** Get the active instance filter applied to this hierarchy level. */
|
|
23
|
+
instanceFilter?: GenericInstanceFilter;
|
|
24
|
+
/** Set the instance filter to apply to this hierarchy level */
|
|
25
|
+
setInstanceFilter: (filter: GenericInstanceFilter | undefined) => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A React hook that creates state for a tree component.
|
|
29
|
+
*
|
|
30
|
+
* The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a
|
|
31
|
+
* component-agnostic result which may be used to render the hierarchy using any UI framework.
|
|
32
|
+
*
|
|
33
|
+
* See `README.md` for an example
|
|
34
|
+
*
|
|
35
|
+
* @see `useUnifiedSelectionTree`
|
|
36
|
+
* @beta
|
|
37
|
+
*/
|
|
38
|
+
export declare function useTree(props: UseTreeProps): UseTreeResult;
|
|
39
|
+
/**
|
|
40
|
+
* A React hook that creates state for a tree component, that is integrated with unified selection
|
|
41
|
+
* through context provided by `UnifiedSelectionProvider`.
|
|
42
|
+
*
|
|
43
|
+
* The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a
|
|
44
|
+
* component-agnostic result which may be used to render the hierarchy using any UI framework.
|
|
45
|
+
*
|
|
46
|
+
* See `README.md` for an example
|
|
47
|
+
*
|
|
48
|
+
* @see `useTree`
|
|
49
|
+
* @see `UnifiedSelectionProvider`
|
|
50
|
+
* @beta
|
|
51
|
+
*/
|
|
52
|
+
export declare function useUnifiedSelectionTree({ imodelKey, sourceName, ...props }: UseTreeProps & Omit<UseUnifiedTreeSelectionProps, "getNode">): UseTreeResult;
|
|
53
|
+
type IModelAccess = ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;
|
|
54
|
+
interface GetFilteredPathsProps {
|
|
55
|
+
imodelAccess: IModelAccess;
|
|
56
|
+
}
|
|
57
|
+
interface UseTreeProps {
|
|
58
|
+
imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;
|
|
59
|
+
getHierarchyDefinition: (props: {
|
|
60
|
+
imodelAccess: IModelAccess;
|
|
61
|
+
}) => HierarchyDefinition;
|
|
62
|
+
getFilteredPaths?: (props: GetFilteredPathsProps) => Promise<HierarchyNodeIdentifiersPath[] | undefined>;
|
|
63
|
+
localizedStrings?: Parameters<typeof createHierarchyProvider>[0]["localizedStrings"];
|
|
64
|
+
}
|
|
65
|
+
interface UseTreeResult {
|
|
66
|
+
/**
|
|
67
|
+
* Array containing root tree nodes. It is `undefined` on initial render until any nodes are loaded.
|
|
68
|
+
*/
|
|
69
|
+
rootNodes: PresentationTreeNode[] | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Specifies whether tree is loading or not. It is set to `true` when initial tree load is in progress
|
|
72
|
+
* or tree is reloading.
|
|
73
|
+
*/
|
|
74
|
+
isLoading: boolean;
|
|
75
|
+
reloadTree: (options?: {
|
|
76
|
+
discardState?: boolean;
|
|
77
|
+
}) => void;
|
|
78
|
+
expandNode: (nodeId: string, isExpanded: boolean) => void;
|
|
79
|
+
selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;
|
|
80
|
+
isNodeSelected: (nodeId: string) => boolean;
|
|
81
|
+
getHierarchyLevelDetails: (nodeId: string | undefined) => HierarchyLevelDetails | undefined;
|
|
82
|
+
setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;
|
|
83
|
+
}
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=UseTree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UseTree.d.ts","sourceRoot":"","sources":["../../../src/presentation-hierarchies-react/UseTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.useUnifiedSelectionTree = exports.useTree = void 0;
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const presentation_hierarchies_1 = require("@itwin/presentation-hierarchies");
|
|
10
|
+
const TreeActions_1 = require("./internal/TreeActions");
|
|
11
|
+
const TreeModel_1 = require("./internal/TreeModel");
|
|
12
|
+
const UseUnifiedSelection_1 = require("./internal/UseUnifiedSelection");
|
|
13
|
+
/**
|
|
14
|
+
* A React hook that creates state for a tree component.
|
|
15
|
+
*
|
|
16
|
+
* The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a
|
|
17
|
+
* component-agnostic result which may be used to render the hierarchy using any UI framework.
|
|
18
|
+
*
|
|
19
|
+
* See `README.md` for an example
|
|
20
|
+
*
|
|
21
|
+
* @see `useUnifiedSelectionTree`
|
|
22
|
+
* @beta
|
|
23
|
+
*/
|
|
24
|
+
function useTree(props) {
|
|
25
|
+
const { getNode: _, ...rest } = useTreeInternal(props);
|
|
26
|
+
return rest;
|
|
27
|
+
}
|
|
28
|
+
exports.useTree = useTree;
|
|
29
|
+
/**
|
|
30
|
+
* A React hook that creates state for a tree component, that is integrated with unified selection
|
|
31
|
+
* through context provided by `UnifiedSelectionProvider`.
|
|
32
|
+
*
|
|
33
|
+
* The hook uses `@itwin/presentation-hierarchies` package to load the hierarchy data and returns a
|
|
34
|
+
* component-agnostic result which may be used to render the hierarchy using any UI framework.
|
|
35
|
+
*
|
|
36
|
+
* See `README.md` for an example
|
|
37
|
+
*
|
|
38
|
+
* @see `useTree`
|
|
39
|
+
* @see `UnifiedSelectionProvider`
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
function useUnifiedSelectionTree({ imodelKey, sourceName, ...props }) {
|
|
43
|
+
const { getNode, ...rest } = useTreeInternal(props);
|
|
44
|
+
return { ...rest, ...(0, UseUnifiedSelection_1.useUnifiedTreeSelection)({ imodelKey, sourceName, getNode }) };
|
|
45
|
+
}
|
|
46
|
+
exports.useUnifiedSelectionTree = useUnifiedSelectionTree;
|
|
47
|
+
function useTreeInternal({ imodelAccess, getHierarchyDefinition, getFilteredPaths, localizedStrings, }) {
|
|
48
|
+
const [state, setState] = (0, react_1.useState)({
|
|
49
|
+
model: { idToNode: new Map(), parentChildMap: new Map(), rootNode: { id: undefined, nodeData: undefined } },
|
|
50
|
+
rootNodes: undefined,
|
|
51
|
+
});
|
|
52
|
+
const [hierarchySource, setHierarchySource] = (0, react_1.useState)({ isFiltering: false });
|
|
53
|
+
const [actions] = (0, react_1.useState)(() => new TreeActions_1.TreeActions((model) => {
|
|
54
|
+
const rootNodes = model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model) : undefined;
|
|
55
|
+
setState({
|
|
56
|
+
model,
|
|
57
|
+
rootNodes,
|
|
58
|
+
});
|
|
59
|
+
}));
|
|
60
|
+
const currentFormatter = (0, react_1.useRef)();
|
|
61
|
+
(0, react_1.useEffect)(() => {
|
|
62
|
+
const updateHierarchyProvider = (provider) => {
|
|
63
|
+
actions.setHierarchyProvider(provider);
|
|
64
|
+
actions.reloadTree(undefined);
|
|
65
|
+
setHierarchySource({ hierarchyProvider: provider, isFiltering: false });
|
|
66
|
+
};
|
|
67
|
+
const createProvider = (paths) => {
|
|
68
|
+
return (0, presentation_hierarchies_1.createHierarchyProvider)({
|
|
69
|
+
imodelAccess,
|
|
70
|
+
hierarchyDefinition: getHierarchyDefinition({ imodelAccess }),
|
|
71
|
+
localizedStrings,
|
|
72
|
+
formatter: currentFormatter.current,
|
|
73
|
+
filtering: paths !== undefined
|
|
74
|
+
? {
|
|
75
|
+
paths,
|
|
76
|
+
}
|
|
77
|
+
: undefined,
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const loadHierarchyProvider = async () => {
|
|
81
|
+
if (!getFilteredPaths) {
|
|
82
|
+
return createProvider(undefined);
|
|
83
|
+
}
|
|
84
|
+
setHierarchySource((prev) => ({ ...prev, isFiltering: true }));
|
|
85
|
+
try {
|
|
86
|
+
const filteredPaths = await getFilteredPaths({ imodelAccess });
|
|
87
|
+
return createProvider(filteredPaths);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return createProvider(undefined);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
let disposed = false;
|
|
94
|
+
void (async () => {
|
|
95
|
+
const provider = await loadHierarchyProvider();
|
|
96
|
+
if (disposed) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
updateHierarchyProvider(provider);
|
|
100
|
+
})();
|
|
101
|
+
return () => {
|
|
102
|
+
disposed = true;
|
|
103
|
+
actions.dispose();
|
|
104
|
+
};
|
|
105
|
+
}, [actions, imodelAccess, localizedStrings, getHierarchyDefinition, getFilteredPaths]);
|
|
106
|
+
const getNode = (0, react_1.useRef)((nodeId) => {
|
|
107
|
+
return actions.getNode(nodeId);
|
|
108
|
+
}).current;
|
|
109
|
+
const expandNode = (0, react_1.useRef)((nodeId, isExpanded) => {
|
|
110
|
+
actions.expandNode(nodeId, isExpanded);
|
|
111
|
+
}).current;
|
|
112
|
+
const reloadTree = (0, react_1.useRef)((options) => {
|
|
113
|
+
actions.reloadTree(options);
|
|
114
|
+
}).current;
|
|
115
|
+
const selectNodes = (0, react_1.useRef)((nodeIds, changeType) => {
|
|
116
|
+
actions.selectNodes(nodeIds, changeType);
|
|
117
|
+
}).current;
|
|
118
|
+
const isNodeSelected = (0, react_1.useCallback)((nodeId) => TreeModel_1.TreeModel.isNodeSelected(state.model, nodeId), [state]);
|
|
119
|
+
const setFormatter = (0, react_1.useCallback)((formatter) => {
|
|
120
|
+
currentFormatter.current = formatter;
|
|
121
|
+
// istanbul ignore if
|
|
122
|
+
if (!hierarchySource.hierarchyProvider) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
hierarchySource.hierarchyProvider.setFormatter(formatter);
|
|
126
|
+
actions.reloadTree();
|
|
127
|
+
}, [hierarchySource.hierarchyProvider, actions]);
|
|
128
|
+
const getHierarchyLevelDetails = (0, react_1.useCallback)((nodeId) => {
|
|
129
|
+
const node = actions.getNode(nodeId);
|
|
130
|
+
const hierarchyProvider = hierarchySource.hierarchyProvider;
|
|
131
|
+
if (!hierarchyProvider || !node || (0, TreeModel_1.isTreeModelInfoNode)(node)) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
const hierarchyNode = node.nodeData;
|
|
135
|
+
if (hierarchyNode && presentation_hierarchies_1.HierarchyNode.isGroupingNode(hierarchyNode)) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
hierarchyNode,
|
|
140
|
+
getInstanceKeysIterator: (props) => hierarchyProvider.getNodeInstanceKeys({
|
|
141
|
+
parentNode: hierarchyNode,
|
|
142
|
+
instanceFilter: props?.instanceFilter,
|
|
143
|
+
hierarchyLevelSizeLimit: props?.hierarchyLevelSizeLimit,
|
|
144
|
+
}),
|
|
145
|
+
instanceFilter: node.instanceFilter,
|
|
146
|
+
setInstanceFilter: (filter) => actions.setInstanceFilter(nodeId, filter),
|
|
147
|
+
sizeLimit: node.hierarchyLimit,
|
|
148
|
+
setSizeLimit: (value) => actions.setHierarchyLimit(nodeId, value),
|
|
149
|
+
};
|
|
150
|
+
}, [actions, hierarchySource.hierarchyProvider]);
|
|
151
|
+
return {
|
|
152
|
+
rootNodes: state.rootNodes,
|
|
153
|
+
isLoading: !!state.model.rootNode.isLoading || hierarchySource.isFiltering,
|
|
154
|
+
expandNode,
|
|
155
|
+
reloadTree,
|
|
156
|
+
selectNodes,
|
|
157
|
+
isNodeSelected,
|
|
158
|
+
getNode,
|
|
159
|
+
getHierarchyLevelDetails,
|
|
160
|
+
setFormatter,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function generateTreeStructure(parentNodeId, model) {
|
|
164
|
+
const currentChildren = model.parentChildMap.get(parentNodeId);
|
|
165
|
+
if (!currentChildren) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
return currentChildren
|
|
169
|
+
.map((childId) => model.idToNode.get(childId))
|
|
170
|
+
.filter((node) => !!node)
|
|
171
|
+
.map((node) => {
|
|
172
|
+
if ((0, TreeModel_1.isTreeModelHierarchyNode)(node)) {
|
|
173
|
+
const children = generateTreeStructure(node.id, model);
|
|
174
|
+
return {
|
|
175
|
+
...toPresentationHierarchyNodeBase(node),
|
|
176
|
+
children: children ? children : node.children === true ? true : [],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (node.type === "ResultSetTooLarge") {
|
|
180
|
+
return {
|
|
181
|
+
id: node.id,
|
|
182
|
+
parentNodeId,
|
|
183
|
+
type: node.type,
|
|
184
|
+
resultSetSizeLimit: node.resultSetSizeLimit,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (node.type === "NoFilterMatches") {
|
|
188
|
+
return {
|
|
189
|
+
id: node.id,
|
|
190
|
+
parentNodeId,
|
|
191
|
+
type: node.type,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
id: node.id,
|
|
196
|
+
parentNodeId,
|
|
197
|
+
type: node.type,
|
|
198
|
+
message: node.message,
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function toPresentationHierarchyNodeBase(node) {
|
|
203
|
+
return {
|
|
204
|
+
id: node.id,
|
|
205
|
+
label: node.label,
|
|
206
|
+
nodeData: node.nodeData,
|
|
207
|
+
isLoading: !!node.isLoading,
|
|
208
|
+
isExpanded: !!node.isExpanded,
|
|
209
|
+
isFilterable: !presentation_hierarchies_1.HierarchyNode.isGroupingNode(node.nodeData) && !!node.nodeData.supportsFiltering && node.children,
|
|
210
|
+
isFiltered: !!node.instanceFilter,
|
|
211
|
+
extendedData: node.nodeData.extendedData,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=UseTree.js.map
|
|
@@ -0,0 +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 {\n createHierarchyProvider,\n GenericInstanceFilter,\n HierarchyDefinition,\n HierarchyNode,\n HierarchyNodeIdentifiersPath,\n HierarchyProvider,\n LimitingECSqlQueryExecutor,\n} from \"@itwin/presentation-hierarchies\";\nimport { ECClassHierarchyInspector, ECSchemaProvider, InstanceKey, IPrimitiveValueFormatter } from \"@itwin/presentation-shared\";\nimport { TreeActions } from \"./internal/TreeActions\";\nimport { isTreeModelHierarchyNode, isTreeModelInfoNode, TreeModel, TreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from \"./internal/TreeModel\";\nimport { useUnifiedTreeSelection, UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection\";\nimport { PresentationHierarchyNode, PresentationTreeNode } from \"./TreeNode\";\nimport { SelectionChangeType } from \"./UseSelectionHandler\";\n\n/**\n * A data structure that contains information about a single hierarchy level.\n * @beta\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 * @beta\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 `UnifiedSelectionProvider`\n * @beta\n */\nexport function useUnifiedSelectionTree({ imodelKey, sourceName, ...props }: UseTreeProps & Omit<UseUnifiedTreeSelectionProps, \"getNode\">): UseTreeResult {\n const { getNode, ...rest } = useTreeInternal(props);\n return { ...rest, ...useUnifiedTreeSelection({ imodelKey, sourceName, getNode }) };\n}\n\ntype IModelAccess = ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n\ninterface GetFilteredPathsProps {\n imodelAccess: IModelAccess;\n}\n\ninterface UseTreeProps {\n imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n getHierarchyDefinition: (props: { imodelAccess: IModelAccess }) => HierarchyDefinition;\n getFilteredPaths?: (props: GetFilteredPathsProps) => Promise<HierarchyNodeIdentifiersPath[] | undefined>;\n localizedStrings?: Parameters<typeof createHierarchyProvider>[0][\"localizedStrings\"];\n}\n\ninterface 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 reloadTree: (options?: { discardState?: boolean }) => void;\n expandNode: (nodeId: string, isExpanded: boolean) => void;\n selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;\n isNodeSelected: (nodeId: string) => boolean;\n getHierarchyLevelDetails: (nodeId: string | undefined) => HierarchyLevelDetails | undefined;\n setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;\n}\n\ninterface TreeState {\n model: TreeModel;\n rootNodes: Array<PresentationTreeNode> | undefined;\n}\n\nfunction useTreeInternal({\n imodelAccess,\n getHierarchyDefinition,\n getFilteredPaths,\n localizedStrings,\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 [hierarchySource, setHierarchySource] = useState<{ hierarchyProvider?: HierarchyProvider; isFiltering: boolean }>({ isFiltering: false });\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions((model) => {\n const rootNodes = model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model) : undefined;\n setState({\n model,\n rootNodes,\n });\n }),\n );\n const currentFormatter = useRef<IPrimitiveValueFormatter>();\n\n useEffect(() => {\n const updateHierarchyProvider = (provider: HierarchyProvider) => {\n actions.setHierarchyProvider(provider);\n actions.reloadTree(undefined);\n setHierarchySource({ hierarchyProvider: provider, isFiltering: false });\n };\n\n const createProvider = (paths: HierarchyNodeIdentifiersPath[] | undefined) => {\n return createHierarchyProvider({\n imodelAccess,\n hierarchyDefinition: getHierarchyDefinition({ imodelAccess }),\n localizedStrings,\n formatter: currentFormatter.current,\n filtering:\n paths !== undefined\n ? {\n paths,\n }\n : undefined,\n });\n };\n\n const loadHierarchyProvider = async () => {\n if (!getFilteredPaths) {\n return createProvider(undefined);\n }\n\n setHierarchySource((prev) => ({ ...prev, isFiltering: true }));\n try {\n const filteredPaths = await getFilteredPaths({ imodelAccess });\n return createProvider(filteredPaths);\n } catch {\n return createProvider(undefined);\n }\n };\n\n let disposed = false;\n void (async () => {\n const provider = await loadHierarchyProvider();\n if (disposed) {\n return;\n }\n updateHierarchyProvider(provider);\n })();\n\n return () => {\n disposed = true;\n actions.dispose();\n };\n }, [actions, imodelAccess, localizedStrings, getHierarchyDefinition, getFilteredPaths]);\n\n const getNode = useRef((nodeId: string) => {\n return actions.getNode(nodeId);\n }).current;\n\n const expandNode = useRef((nodeId: string, isExpanded: boolean) => {\n actions.expandNode(nodeId, isExpanded);\n }).current;\n\n const reloadTree = useRef((options?: { discardState?: boolean }) => {\n actions.reloadTree(options);\n }).current;\n\n const selectNodes = useRef((nodeIds: Array<string>, changeType: SelectionChangeType) => {\n actions.selectNodes(nodeIds, changeType);\n }).current;\n\n const isNodeSelected = useCallback((nodeId: string) => TreeModel.isNodeSelected(state.model, nodeId), [state]);\n\n const setFormatter = useCallback(\n (formatter: IPrimitiveValueFormatter | undefined) => {\n currentFormatter.current = formatter;\n // istanbul ignore if\n if (!hierarchySource.hierarchyProvider) {\n return;\n }\n\n hierarchySource.hierarchyProvider.setFormatter(formatter);\n actions.reloadTree();\n },\n [hierarchySource.hierarchyProvider, actions],\n );\n\n const getHierarchyLevelDetails = useCallback<UseTreeResult[\"getHierarchyLevelDetails\"]>(\n (nodeId) => {\n const node = actions.getNode(nodeId);\n const hierarchyProvider = hierarchySource.hierarchyProvider;\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, hierarchySource.hierarchyProvider],\n );\n\n return {\n rootNodes: state.rootNodes,\n isLoading: !!state.model.rootNode.isLoading || hierarchySource.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"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GenericInstanceFilter, HierarchyProvider } from "@itwin/presentation-hierarchies";
|
|
2
|
+
import { SelectionChangeType } from "../UseSelectionHandler";
|
|
3
|
+
import { TreeModel, TreeModelNode, TreeModelRootNode } from "./TreeModel";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare class TreeActions {
|
|
6
|
+
private _onModelChanged;
|
|
7
|
+
private _loader;
|
|
8
|
+
private _currentModel;
|
|
9
|
+
private _disposed;
|
|
10
|
+
constructor(_onModelChanged: (model: TreeModel) => void, seed?: TreeModel);
|
|
11
|
+
private updateTreeModel;
|
|
12
|
+
private handleLoadedHierarchy;
|
|
13
|
+
private onLoadingComplete;
|
|
14
|
+
private loadNodes;
|
|
15
|
+
private reloadSubTree;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
setHierarchyProvider(provider?: HierarchyProvider): void;
|
|
18
|
+
getNode(nodeId: string | undefined): TreeModelNode | TreeModelRootNode | undefined;
|
|
19
|
+
selectNodes(nodeIds: Array<string>, changeType: SelectionChangeType): void;
|
|
20
|
+
expandNode(nodeId: string, isExpanded: boolean): void;
|
|
21
|
+
setHierarchyLimit(nodeId: string | undefined, limit?: number | "unbounded"): void;
|
|
22
|
+
setInstanceFilter(nodeId: string | undefined, filter?: GenericInstanceFilter): void;
|
|
23
|
+
reloadTree(options?: {
|
|
24
|
+
discardState?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=TreeActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeActions.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/TreeActions.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAiB,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAiD,SAAS,EAA0B,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKjJ,gBAAgB;AAChB,qBAAa,WAAW;IAMpB,OAAO,CAAC,eAAe;IALzB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAuB;gBAG9B,eAAe,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,EACnD,IAAI,CAAC,EAAE,SAAS;IAUlB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,aAAa;IA8Cd,OAAO;IAIP,oBAAoB,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAIjD,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,OAAO,CAAA;KAAE;CAQvD"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TreeActions = void 0;
|
|
8
|
+
const immer_1 = require("immer");
|
|
9
|
+
const rxjs_1 = require("rxjs");
|
|
10
|
+
const presentation_hierarchies_1 = require("@itwin/presentation-hierarchies");
|
|
11
|
+
const TreeLoader_1 = require("./TreeLoader");
|
|
12
|
+
const TreeModel_1 = require("./TreeModel");
|
|
13
|
+
const Utils_1 = require("./Utils");
|
|
14
|
+
(0, immer_1.enableMapSet)();
|
|
15
|
+
/** @internal */
|
|
16
|
+
class TreeActions {
|
|
17
|
+
_onModelChanged;
|
|
18
|
+
_loader;
|
|
19
|
+
_currentModel;
|
|
20
|
+
_disposed = new rxjs_1.Subject();
|
|
21
|
+
constructor(_onModelChanged, seed) {
|
|
22
|
+
this._onModelChanged = _onModelChanged;
|
|
23
|
+
this._loader = new NoopTreeLoader();
|
|
24
|
+
this._currentModel = seed ?? /* istanbul ignore next */ {
|
|
25
|
+
idToNode: new Map(),
|
|
26
|
+
parentChildMap: new Map(),
|
|
27
|
+
rootNode: { id: undefined, nodeData: undefined },
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
updateTreeModel(updater) {
|
|
31
|
+
const newModel = (0, immer_1.produce)(this._currentModel, updater);
|
|
32
|
+
if (this._currentModel === newModel) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this._currentModel = newModel;
|
|
36
|
+
this._onModelChanged(this._currentModel);
|
|
37
|
+
}
|
|
38
|
+
handleLoadedHierarchy(parentId, loadedHierarchy) {
|
|
39
|
+
this.updateTreeModel((model) => {
|
|
40
|
+
TreeModel_1.TreeModel.addHierarchyPart(model, parentId, loadedHierarchy);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
onLoadingComplete(parentId) {
|
|
44
|
+
this.updateTreeModel((model) => {
|
|
45
|
+
TreeModel_1.TreeModel.setIsLoading(model, parentId, false);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
loadNodes(parentId, ignoreCache) {
|
|
49
|
+
const parentNode = this._currentModel.idToNode.get(parentId);
|
|
50
|
+
// istanbul ignore if
|
|
51
|
+
if (!parentNode || !(0, TreeModel_1.isTreeModelHierarchyNode)(parentNode)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this._loader
|
|
55
|
+
.loadNodes({
|
|
56
|
+
parent: parentNode,
|
|
57
|
+
getHierarchyLevelOptions: (node) => createHierarchyLevelOptions(this._currentModel, getNonGroupedParentId(node)),
|
|
58
|
+
shouldLoadChildren: (node) => !!node.nodeData.autoExpand,
|
|
59
|
+
ignoreCache,
|
|
60
|
+
})
|
|
61
|
+
.pipe(collectTreePartsUntil(this._disposed))
|
|
62
|
+
.subscribe({
|
|
63
|
+
next: (loadedHierarchy) => {
|
|
64
|
+
this.handleLoadedHierarchy(parentId, loadedHierarchy);
|
|
65
|
+
},
|
|
66
|
+
complete: () => {
|
|
67
|
+
this.onLoadingComplete(parentId);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
reloadSubTree(parentId, oldModel, options) {
|
|
72
|
+
const currModel = this._currentModel;
|
|
73
|
+
const expandedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === true);
|
|
74
|
+
const collapsedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === false);
|
|
75
|
+
const getHierarchyLevelOptions = (node) => {
|
|
76
|
+
if (!!options?.discardState) {
|
|
77
|
+
return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };
|
|
78
|
+
}
|
|
79
|
+
const filteredNodeId = getNonGroupedParentId(node);
|
|
80
|
+
return createHierarchyLevelOptions(filteredNodeId === parentId ? currModel : oldModel, filteredNodeId);
|
|
81
|
+
};
|
|
82
|
+
const shouldLoadChildren = (node) => {
|
|
83
|
+
if (expandedNodes.findIndex((expandedNode) => (0, Utils_1.sameNodes)(expandedNode.nodeData, node.nodeData)) !== -1) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (collapsedNodes.findIndex((collapsedNode) => (0, Utils_1.sameNodes)(collapsedNode.nodeData, node.nodeData)) !== -1) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return !!node.nodeData.autoExpand;
|
|
90
|
+
};
|
|
91
|
+
const buildNode = (node) => (!!options?.discardState || node.id === parentId ? node : addAttributes(node, oldModel));
|
|
92
|
+
const rootNode = parentId !== undefined ? this.getNode(parentId) : currModel.rootNode;
|
|
93
|
+
// istanbul ignore if
|
|
94
|
+
if (!rootNode || (0, TreeModel_1.isTreeModelInfoNode)(rootNode)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (parentId === undefined) {
|
|
98
|
+
// cancel all ongoing requests
|
|
99
|
+
this._disposed.next();
|
|
100
|
+
}
|
|
101
|
+
this._loader
|
|
102
|
+
.loadNodes({ parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode })
|
|
103
|
+
.pipe(collectTreePartsUntil(this._disposed, !!options?.discardState ? undefined : { ...currModel.rootNode }))
|
|
104
|
+
.subscribe({
|
|
105
|
+
next: (newModel) => {
|
|
106
|
+
this.handleLoadedHierarchy(parentId, newModel);
|
|
107
|
+
},
|
|
108
|
+
complete: () => {
|
|
109
|
+
this.onLoadingComplete(parentId);
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
dispose() {
|
|
114
|
+
this._disposed.next();
|
|
115
|
+
}
|
|
116
|
+
setHierarchyProvider(provider) {
|
|
117
|
+
this._loader = provider ? new TreeLoader_1.TreeLoader(provider) : /* istanbul ignore next */ new NoopTreeLoader();
|
|
118
|
+
}
|
|
119
|
+
getNode(nodeId) {
|
|
120
|
+
return TreeModel_1.TreeModel.getNode(this._currentModel, nodeId);
|
|
121
|
+
}
|
|
122
|
+
selectNodes(nodeIds, changeType) {
|
|
123
|
+
this.updateTreeModel((model) => {
|
|
124
|
+
TreeModel_1.TreeModel.selectNodes(model, nodeIds, changeType);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
expandNode(nodeId, isExpanded) {
|
|
128
|
+
let childrenAction = "none";
|
|
129
|
+
this.updateTreeModel((model) => {
|
|
130
|
+
childrenAction = TreeModel_1.TreeModel.expandNode(model, nodeId, isExpanded);
|
|
131
|
+
});
|
|
132
|
+
if (childrenAction === "none") {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.loadNodes(nodeId, childrenAction === "reloadChildren");
|
|
136
|
+
}
|
|
137
|
+
setHierarchyLimit(nodeId, limit) {
|
|
138
|
+
const oldModel = this._currentModel;
|
|
139
|
+
let loadChildren = false;
|
|
140
|
+
this.updateTreeModel((model) => {
|
|
141
|
+
loadChildren = TreeModel_1.TreeModel.setHierarchyLimit(model, nodeId, limit);
|
|
142
|
+
});
|
|
143
|
+
if (!loadChildren) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.reloadSubTree(nodeId, oldModel);
|
|
147
|
+
}
|
|
148
|
+
setInstanceFilter(nodeId, filter) {
|
|
149
|
+
const oldModel = this._currentModel;
|
|
150
|
+
let loadChildren = false;
|
|
151
|
+
this.updateTreeModel((model) => {
|
|
152
|
+
loadChildren = TreeModel_1.TreeModel.setInstanceFilter(model, nodeId, filter);
|
|
153
|
+
});
|
|
154
|
+
if (!loadChildren) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.reloadSubTree(nodeId, oldModel);
|
|
158
|
+
}
|
|
159
|
+
reloadTree(options) {
|
|
160
|
+
const oldModel = this._currentModel;
|
|
161
|
+
this.updateTreeModel((model) => {
|
|
162
|
+
model.rootNode.isLoading = true;
|
|
163
|
+
});
|
|
164
|
+
this.reloadSubTree(undefined, oldModel, { ...options });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.TreeActions = TreeActions;
|
|
168
|
+
function collectTreePartsUntil(untilNotifier, rootNode) {
|
|
169
|
+
return (source) => source.pipe((0, rxjs_1.reduce)((treeModel, loadedPart) => {
|
|
170
|
+
addNodesToModel(treeModel, loadedPart);
|
|
171
|
+
return treeModel;
|
|
172
|
+
}, {
|
|
173
|
+
idToNode: new Map(),
|
|
174
|
+
parentChildMap: new Map(),
|
|
175
|
+
rootNode: rootNode ?? { id: undefined, nodeData: undefined },
|
|
176
|
+
}), (0, rxjs_1.takeUntil)(untilNotifier));
|
|
177
|
+
}
|
|
178
|
+
function addNodesToModel(model, hierarchyPart) {
|
|
179
|
+
model.parentChildMap.set(hierarchyPart.parentId, hierarchyPart.loadedNodes.map((node) => node.id));
|
|
180
|
+
for (const node of hierarchyPart.loadedNodes) {
|
|
181
|
+
model.idToNode.set(node.id, node);
|
|
182
|
+
}
|
|
183
|
+
const parentNode = hierarchyPart.parentId ? model.idToNode.get(hierarchyPart.parentId) : undefined;
|
|
184
|
+
if (parentNode && (0, TreeModel_1.isTreeModelHierarchyNode)(parentNode)) {
|
|
185
|
+
parentNode.isExpanded = true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function addAttributes(node, oldModel) {
|
|
189
|
+
const oldNode = oldModel.idToNode.get(node.id);
|
|
190
|
+
if (oldNode && (0, TreeModel_1.isTreeModelHierarchyNode)(oldNode)) {
|
|
191
|
+
node.hierarchyLimit = oldNode.hierarchyLimit;
|
|
192
|
+
node.instanceFilter = oldNode.instanceFilter;
|
|
193
|
+
node.isSelected = oldNode.isSelected;
|
|
194
|
+
}
|
|
195
|
+
return node;
|
|
196
|
+
}
|
|
197
|
+
function collectNodes(parentId, model, pred) {
|
|
198
|
+
const currentChildren = model.parentChildMap.get(parentId);
|
|
199
|
+
if (!currentChildren) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
if (parentId === undefined) {
|
|
203
|
+
return currentChildren.flatMap((child) => collectNodes(child, model, pred));
|
|
204
|
+
}
|
|
205
|
+
const currNode = model.idToNode.get(parentId);
|
|
206
|
+
if (!currNode || !(0, TreeModel_1.isTreeModelHierarchyNode)(currNode) || !pred(currNode)) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
return [currNode, ...currentChildren.flatMap((child) => collectNodes(child, model, pred))];
|
|
210
|
+
}
|
|
211
|
+
function getNonGroupedParentId(node) {
|
|
212
|
+
if (!node.nodeData || !presentation_hierarchies_1.HierarchyNode.isGroupingNode(node.nodeData)) {
|
|
213
|
+
return node.id;
|
|
214
|
+
}
|
|
215
|
+
if (!node.nodeData.nonGroupingAncestor) {
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
return (0, Utils_1.createNodeId)(node.nodeData.nonGroupingAncestor);
|
|
219
|
+
}
|
|
220
|
+
function createHierarchyLevelOptions(model, nodeId) {
|
|
221
|
+
if (nodeId === undefined) {
|
|
222
|
+
return { instanceFilter: model.rootNode.instanceFilter, hierarchyLevelSizeLimit: model.rootNode.hierarchyLimit };
|
|
223
|
+
}
|
|
224
|
+
const modelNode = model.idToNode.get(nodeId);
|
|
225
|
+
if (!modelNode || (0, TreeModel_1.isTreeModelInfoNode)(modelNode)) {
|
|
226
|
+
return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };
|
|
227
|
+
}
|
|
228
|
+
return { instanceFilter: modelNode.instanceFilter, hierarchyLevelSizeLimit: modelNode.hierarchyLimit };
|
|
229
|
+
}
|
|
230
|
+
// istanbul ignore next
|
|
231
|
+
class NoopTreeLoader {
|
|
232
|
+
loadNodes() {
|
|
233
|
+
return rxjs_1.EMPTY;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=TreeActions.js.map
|