@itwin/presentation-hierarchies-react 2.0.0-alpha.56 → 2.0.0-alpha.58
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 +178 -36
- package/lib/presentation-hierarchies-react/UseIModelTree.d.ts +2 -2
- package/lib/presentation-hierarchies-react/UseIModelTree.js +1 -2
- package/lib/presentation-hierarchies-react/UseIModelTree.js.map +1 -1
- package/lib/presentation-hierarchies-react/UseNodeHighlighting.js +1 -2
- package/lib/presentation-hierarchies-react/UseNodeHighlighting.js.map +1 -1
- package/lib/presentation-hierarchies-react/UseSelectionHandler.d.ts +0 -2
- package/lib/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/UseSelectionHandler.js +1 -2
- package/lib/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -1
- package/lib/presentation-hierarchies-react/UseTree.d.ts +2 -2
- package/lib/presentation-hierarchies-react/UseTree.js +1 -2
- package/lib/presentation-hierarchies-react/UseTree.js.map +1 -1
- package/lib/presentation-hierarchies-react/Utils.js +1 -1
- package/lib/presentation-hierarchies-react/Utils.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/DisposePolyfill.js +2 -2
- package/lib/presentation-hierarchies-react/internal/DisposePolyfill.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/LocalizedStrings.js +1 -1
- package/lib/presentation-hierarchies-react/internal/TreeActions.js +1 -2
- package/lib/presentation-hierarchies-react/internal/TreeActions.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/TreeLoader.js +1 -2
- package/lib/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/TreeModel.d.ts +0 -2
- package/lib/presentation-hierarchies-react/internal/TreeModel.js +1 -1
- package/lib/presentation-hierarchies-react/internal/TreeModel.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +0 -2
- package/lib/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/internal/UseUnifiedSelection.js +1 -2
- package/lib/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/Utils.js +1 -2
- package/lib/presentation-hierarchies-react/internal/Utils.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/FlatTreeNode.js +2 -3
- package/lib/presentation-hierarchies-react/stratakit/FlatTreeNode.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/LocalizationContext.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/LocalizationContext.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeAction.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeAction.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeFilterAction.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeFilterAction.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeFilterAction.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.d.ts +0 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.d.ts +0 -4
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeRenderer.js +1 -2
- package/lib/presentation-hierarchies-react/stratakit/TreeRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react.js +1 -2
- package/package.json +12 -10
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { c } from "react-compiler-runtime";
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
|
-
|
|
4
3
|
//#region src/presentation-hierarchies-react/UseSelectionHandler.ts
|
|
5
4
|
/**
|
|
6
5
|
* A react hook that helps implement different selection modes in a tree component created using `useTree` hook.
|
|
@@ -119,7 +118,7 @@ function computeFlatNodeList(rootNodes) {
|
|
|
119
118
|
nodeIdToIndexMap
|
|
120
119
|
};
|
|
121
120
|
}
|
|
122
|
-
|
|
123
121
|
//#endregion
|
|
124
122
|
export { useSelectionHandler };
|
|
123
|
+
|
|
125
124
|
//# sourceMappingURL=UseSelectionHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseSelectionHandler.js","names":["useCallback","useEffect","useRef","TreeRendererProps","TreeNode","SelectionMode","SelectionChangeType","UseSelectionHandlerProps","Pick","selectionMode","UseSelectionHandlerResult","handleNodeSelect","props","nodeId","isSelected","shiftDown","ctrlDown","FlatTreeState","flatNodeList","Array","nodeIdToIndexMap","Map","useSelectionHandler","$","_c","rootNodes","selectNodes","previousSelectionRef","undefined","t0","Symbol","for","state","t1","t2","current","computeFlatNodeList","t3","firstId","secondId","getIndex","get","firstIndex","secondIndex","startingIndex","Math","min","endIndex","max","slice","getNodeRange","t4","t5","nodeId_0","selection","getSelectionAction","type","nodes","select","length","SelectionAction","getExtendedSelectionAction","flattenNodeRecursively","forEach","node","set","id","push","isExpanded","children"],"sources":["../../src/presentation-hierarchies-react/UseSelectionHandler.ts"],"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 } from \"react\";\n\nimport type { TreeRendererProps } from \"./Renderers.js\";\nimport type { TreeNode } from \"./TreeNode.js\";\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 * @public\n */\nexport type SelectionMode = \"none\" | \"single\" | \"extended\" | \"multiple\";\n\n/**\n * Type of selection change.\n * - `add` - a node was added to the selection,\n * - `replace` - a selected node was replaced with a different one,\n * - `remove` - a node was removed from the selection.\n *\n * @public\n */\nexport type SelectionChangeType = \"add\" | \"replace\" | \"remove\";\n\n/**\n * Props for `useSelectionHandler` hook.\n * @alpha\n */\ntype UseSelectionHandlerProps = Pick<TreeRendererProps, \"selectNodes\" | \"rootNodes\"> & {\n /**\n * Selection mode that the component is working in.\n */\n selectionMode: SelectionMode;\n};\n\n/**\n * Result of `useSelectionHandler` hook.\n * @internal\n */\ninterface UseSelectionHandlerResult {\n /** Updates nodes selection based on current node state and modifier keys used. */\n handleNodeSelect: (props: { nodeId: string; isSelected: boolean; shiftDown: boolean; ctrlDown: boolean }) => 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 * @internal\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 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 handleNodeSelect = useCallback<UseSelectionHandlerResult[\"handleNodeSelect\"]>(\n ({ nodeId, isSelected, shiftDown, ctrlDown }) => {\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 [selectionMode, selectNodes],\n );\n\n return { handleNodeSelect };\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 ? \"remove\" : \"replace\" };\n case \"multiple\":\n return { select: \"node\", type: isSelected ? \"remove\" : \"add\" };\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 (ctrlDown) {\n return { select: \"node\", type: isSelected ? \"remove\" : \"add\" };\n }\n return { select: \"node\", type: \"replace\" };\n}\n\nfunction computeFlatNodeList(rootNodes: Array<TreeNode>): FlatTreeState {\n const flatNodeList: Array<string> = [];\n const nodeIdToIndexMap: Map<string, number> = new Map();\n\n const flattenNodeRecursively = (nodes: Array<TreeNode>) => {\n nodes.forEach((node) => {\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"],"mappings":"
|
|
1
|
+
{"version":3,"file":"UseSelectionHandler.js","names":["useCallback","useEffect","useRef","TreeRendererProps","TreeNode","SelectionMode","SelectionChangeType","UseSelectionHandlerProps","Pick","selectionMode","UseSelectionHandlerResult","handleNodeSelect","props","nodeId","isSelected","shiftDown","ctrlDown","FlatTreeState","flatNodeList","Array","nodeIdToIndexMap","Map","useSelectionHandler","$","_c","rootNodes","selectNodes","previousSelectionRef","undefined","t0","Symbol","for","state","t1","t2","current","computeFlatNodeList","t3","firstId","secondId","getIndex","get","firstIndex","secondIndex","startingIndex","Math","min","endIndex","max","slice","getNodeRange","t4","t5","nodeId_0","selection","getSelectionAction","type","nodes","select","length","SelectionAction","getExtendedSelectionAction","flattenNodeRecursively","forEach","node","set","id","push","isExpanded","children"],"sources":["../../src/presentation-hierarchies-react/UseSelectionHandler.ts"],"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 } from \"react\";\n\nimport type { TreeRendererProps } from \"./Renderers.js\";\nimport type { TreeNode } from \"./TreeNode.js\";\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 * @public\n */\nexport type SelectionMode = \"none\" | \"single\" | \"extended\" | \"multiple\";\n\n/**\n * Type of selection change.\n * - `add` - a node was added to the selection,\n * - `replace` - a selected node was replaced with a different one,\n * - `remove` - a node was removed from the selection.\n *\n * @public\n */\nexport type SelectionChangeType = \"add\" | \"replace\" | \"remove\";\n\n/**\n * Props for `useSelectionHandler` hook.\n * @alpha\n */\ntype UseSelectionHandlerProps = Pick<TreeRendererProps, \"selectNodes\" | \"rootNodes\"> & {\n /**\n * Selection mode that the component is working in.\n */\n selectionMode: SelectionMode;\n};\n\n/**\n * Result of `useSelectionHandler` hook.\n * @internal\n */\ninterface UseSelectionHandlerResult {\n /** Updates nodes selection based on current node state and modifier keys used. */\n handleNodeSelect: (props: { nodeId: string; isSelected: boolean; shiftDown: boolean; ctrlDown: boolean }) => 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 * @internal\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 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 handleNodeSelect = useCallback<UseSelectionHandlerResult[\"handleNodeSelect\"]>(\n ({ nodeId, isSelected, shiftDown, ctrlDown }) => {\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 [selectionMode, selectNodes],\n );\n\n return { handleNodeSelect };\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 ? \"remove\" : \"replace\" };\n case \"multiple\":\n return { select: \"node\", type: isSelected ? \"remove\" : \"add\" };\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 (ctrlDown) {\n return { select: \"node\", type: isSelected ? \"remove\" : \"add\" };\n }\n return { select: \"node\", type: \"replace\" };\n}\n\nfunction computeFlatNodeList(rootNodes: Array<TreeNode>): FlatTreeState {\n const flatNodeList: Array<string> = [];\n const nodeIdToIndexMap: Map<string, number> = new Map();\n\n const flattenNodeRecursively = (nodes: Array<TreeNode>) => {\n nodes.forEach((node) => {\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"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ErrorInfo, TreeNode } from "./TreeNode.js";
|
|
2
2
|
import { RootErrorRendererProps, TreeRendererProps } from "./Renderers.js";
|
|
3
3
|
import { UseUnifiedTreeSelectionProps } from "./internal/UseUnifiedSelection.js";
|
|
4
|
-
import { GenericInstanceFilter, HierarchyNode, HierarchyProvider,
|
|
4
|
+
import { GenericInstanceFilter, HierarchyNode, HierarchyProvider, HierarchySearchTree } from "@itwin/presentation-hierarchies";
|
|
5
5
|
import { IPrimitiveValueFormatter } from "@itwin/presentation-shared";
|
|
6
6
|
|
|
7
7
|
//#region src/presentation-hierarchies-react/UseTree.d.ts
|
|
@@ -48,7 +48,7 @@ interface UseTreeProps {
|
|
|
48
48
|
abortSignal
|
|
49
49
|
}: {
|
|
50
50
|
abortSignal: AbortSignal;
|
|
51
|
-
}) => Promise<
|
|
51
|
+
}) => Promise<HierarchySearchTree[] | undefined>;
|
|
52
52
|
/**
|
|
53
53
|
* Callback that is called just after a certain action is finished.
|
|
54
54
|
* Can be used for performance tracking.
|
|
@@ -6,7 +6,6 @@ import { useLatest } from "./Utils.js";
|
|
|
6
6
|
import { c } from "react-compiler-runtime";
|
|
7
7
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
8
|
import { HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
9
|
-
|
|
10
9
|
//#region src/presentation-hierarchies-react/UseTree.ts
|
|
11
10
|
/**
|
|
12
11
|
* A React hook that creates state for a tree component.
|
|
@@ -292,7 +291,7 @@ function createTreeNode(modelNode, model, getTreeNodeError) {
|
|
|
292
291
|
}
|
|
293
292
|
};
|
|
294
293
|
}
|
|
295
|
-
|
|
296
294
|
//#endregion
|
|
297
295
|
export { useTree, useUnifiedSelectionTree };
|
|
296
|
+
|
|
298
297
|
//# sourceMappingURL=UseTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseTree.js","names":["useCallback","useEffect","useMemo","useRef","useState","HierarchyNode","TreeActions","TreeModel","useUnifiedTreeSelection","safeDispose","useLatest","GenericInstanceFilter","HierarchyProvider","HierarchySearchPath","IPrimitiveValueFormatter","TreeModelHierarchyNode","TreeModelRootNode","UseUnifiedTreeSelectionProps","RootErrorRendererProps","TreeRendererProps","ErrorInfo","TreeNode","SelectionChangeType","useTree","props","$","_c","t0","useTreeInternal","rest","getTreeModelNode","_","t1","useUnifiedSelectionTree","createSelectableForGenericNode","selectionStorage","sourceName","t2","selectionProps","rootErrorRendererProps","undefined","treeRendererProps","rootNodes","t3","t4","UseTreeProps","getHierarchyProvider","getSearchPaths","abortSignal","AbortSignal","Promise","onPerformanceMeasured","action","duration","onHierarchyLimitExceeded","parentId","filter","limit","onHierarchyLoadError","type","error","getTreeNodeError","node","UseTreeResult","isReloading","getNode","nodeId","setFormatter","formatter","RendererProps","TreeState","model","Array","state","setState","idToNode","Map","parentChildMap","rootNode","id","nodeData","onPerformanceMeasuredRef","onHierarchyLimitExceededRef","onHierarchyLoadErrorRef","getTreeNodeErrorRef","actions","get","generateTreeStructure","current","actionType","currentFormatter","hierarchyProvider","setHierarchyProvider","provider","removeHierarchyChangedListener","hierarchyChanged","addListener","hierarchyChangeArgs","shouldDiscardState","searchChange","newSearch","reloadTree","reset","isSearching","setIsSearching","disposed","controller","AbortController","setHierarchySearch","paths","signal","abort","createTreeNode","expandNode","isExpanded","options","selectNodes","nodeIds","changeType","isNodeSelected","getHierarchyLevelDetails","hierarchyNode","isGroupingNode","getInstanceKeysIterator","getNodeInstanceKeys","parentNode","instanceFilter","hierarchyLevelSizeLimit","setInstanceFilter","sizeLimit","hierarchyLimit","setSizeLimit","value","setHierarchyLimit","renderProps","isLoading","parentNodeId","currentChildren","map","childId","modelNode","children","label","isFilterable","supportsFiltering","isFiltered"],"sources":["../../src/presentation-hierarchies-react/UseTree.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { TreeActions } from \"./internal/TreeActions.js\";\nimport { TreeModel } from \"./internal/TreeModel.js\";\nimport { useUnifiedTreeSelection } from \"./internal/UseUnifiedSelection.js\";\nimport { safeDispose } from \"./internal/Utils.js\";\nimport { useLatest } from \"./Utils.js\";\n\nimport type { GenericInstanceFilter, HierarchyProvider, HierarchySearchPath } from \"@itwin/presentation-hierarchies\";\nimport type { IPrimitiveValueFormatter } from \"@itwin/presentation-shared\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./internal/TreeModel.js\";\nimport type { UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection.js\";\nimport type { RootErrorRendererProps, TreeRendererProps } from \"./Renderers.js\";\nimport type { ErrorInfo, TreeNode } from \"./TreeNode.js\";\nimport type { SelectionChangeType } from \"./UseSelectionHandler.js\";\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 the given selection storage (previously the storage was provided through the, now\n * deprecated, `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({\n sourceName,\n selectionStorage,\n createSelectableForGenericNode,\n ...props\n}: UseTreeProps & UseUnifiedTreeSelectionProps): UseTreeResult {\n const { getTreeModelNode, ...rest } = useTreeInternal(props);\n const selectionProps = useUnifiedTreeSelection({ sourceName, selectionStorage, getTreeModelNode, createSelectableForGenericNode });\n if (rest.rootErrorRendererProps === undefined && rest.treeRendererProps?.rootNodes) {\n return {\n ...rest,\n treeRendererProps: {\n ...rest.treeRendererProps,\n ...selectionProps,\n },\n };\n }\n return rest;\n}\n\n/** @public */\nexport interface UseTreeProps {\n /** Provides the hierarchy provider for the tree. */\n getHierarchyProvider: () => HierarchyProvider;\n /** Provides paths to search nodes. */\n getSearchPaths?: ({ abortSignal }: { abortSignal: AbortSignal }) => Promise<HierarchySearchPath[] | 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\"; error: unknown }) => void;\n /** Callback to set custom TreeNode errors.\n *\n * **Note:** Internal errors take precedence over custom ones.\n */\n getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined;\n}\n\n/** @public */\nexport type UseTreeResult = {\n /**\n * Specifies whether tree is reloading or not. It is set to `false` when initial tree load is in progress to check if\n * or tree is reloading.\n */\n isReloading: boolean;\n /**\n * Get a tree node by id\n */\n getNode: (nodeId: string) => TreeNode | undefined;\n /**\n * Sets a formatter for the primitive values that are displayed in the hierarchy.\n */\n setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;\n} & RendererProps;\n\n/**.\n * @alpha\n */\ntype RendererProps =\n | {\n /**\n * An object containing information used to render root error handling UI.\n * Use in combination with `RootErrorRenderer` or your custom implementation.\n * Defined when root nodes fail to load.\n */\n rootErrorRendererProps: RootErrorRendererProps;\n }\n | {\n /** Is undefined when rootNodes were successfully loaded or are in initial loading process. */\n rootErrorRendererProps: undefined;\n /**\n * An object containing information used to render tree.\n * Use with `TreeRenderer` or your custom implementation.\n * Is undefined on initial loading process.\n */\n treeRendererProps?: TreeRendererProps;\n };\n\ninterface TreeState {\n model: TreeModel;\n rootNodes: Array<TreeNode> | undefined;\n}\n\nfunction useTreeInternal({\n getHierarchyProvider,\n getSearchPaths,\n onPerformanceMeasured,\n onHierarchyLimitExceeded,\n onHierarchyLoadError,\n getTreeNodeError,\n}: UseTreeProps): UseTreeResult & {\n getTreeModelNode: (nodeId: string) => TreeModelRootNode | TreeModelHierarchyNode | 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 const getTreeNodeErrorRef = useLatest(getTreeNodeError);\n\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions(\n (model) => {\n const rootNodes =\n model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model, getTreeNodeErrorRef.current) : 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.searchChange?.newSearch !== 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 [isSearching, setIsSearching] = useState(false);\n useEffect(() => {\n let disposed = false as boolean;\n const controller = new AbortController();\n void (async () => {\n if (!hierarchyProvider) {\n return;\n }\n\n if (!getSearchPaths) {\n hierarchyProvider.setHierarchySearch(undefined);\n // reload tree in case hierarchy provider does not use hierarchy search to load initial nodes\n actions.reloadTree({ state: \"keep\" });\n setIsSearching(false);\n return;\n }\n\n setIsSearching(true);\n let paths: HierarchySearchPath[] | undefined;\n try {\n paths = await getSearchPaths({ abortSignal: controller.signal });\n } catch {\n } finally {\n if (!disposed) {\n hierarchyProvider.setHierarchySearch(paths ? { paths } : undefined);\n setIsSearching(false);\n }\n }\n })();\n return () => {\n controller.abort();\n disposed = true;\n };\n }, [hierarchyProvider, getSearchPaths, actions]);\n\n const getTreeModelNode = useCallback<(nodeId: string) => TreeModelRootNode | TreeModelHierarchyNode | undefined>(\n (nodeId: string) => {\n return actions.getNode(nodeId);\n },\n [actions],\n );\n\n const getNode = useCallback(\n (nodeId: string): TreeNode | undefined => {\n const node = actions.getNode(nodeId);\n if (!node || node.id === undefined) {\n return undefined;\n }\n return createTreeNode(node, state.model, getTreeNodeErrorRef.current);\n },\n [actions, getTreeNodeErrorRef, state.model],\n );\n\n const expandNode = useCallback<TreeRendererProps[\"expandNode\"]>(\n (nodeId: string, isExpanded: boolean) => {\n actions.expandNode(nodeId, isExpanded);\n },\n [actions],\n );\n\n const reloadTree = useCallback<TreeRendererProps[\"reloadTree\"]>(\n (options) => {\n actions.reloadTree(options);\n },\n [actions],\n );\n\n const selectNodes = useCallback<TreeRendererProps[\"selectNodes\"]>(\n (nodeIds: Array<string>, changeType: SelectionChangeType) => {\n actions.selectNodes(nodeIds, changeType);\n },\n [actions],\n );\n\n const isNodeSelected = useCallback<TreeRendererProps[\"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<TreeRendererProps[\"getHierarchyLevelDetails\"]>(\n (nodeId) => {\n const node = actions.getNode(nodeId);\n if (!hierarchyProvider || !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 const renderProps: RendererProps = useMemo(() => {\n if (state.model.rootNode.error) {\n return {\n rootErrorRendererProps: {\n error: state.model.rootNode.error,\n reloadTree,\n getHierarchyLevelDetails,\n },\n };\n }\n return {\n rootErrorRendererProps: undefined,\n treeRendererProps: state.rootNodes\n ? {\n rootNodes: state.rootNodes,\n expandNode,\n selectNodes,\n isNodeSelected,\n reloadTree,\n getHierarchyLevelDetails,\n }\n : undefined,\n };\n }, [expandNode, getHierarchyLevelDetails, isNodeSelected, reloadTree, selectNodes, state.model.rootNode.error, state.rootNodes]);\n\n return {\n ...renderProps,\n isReloading: !!state.model.rootNode.isLoading || isSearching,\n getTreeModelNode,\n getNode,\n setFormatter,\n };\n}\n\nfunction generateTreeStructure(\n parentNodeId: string | undefined,\n model: TreeModel,\n getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined,\n): Array<TreeNode> | 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 TreeModelHierarchyNode => !!node)\n .map<TreeNode>((node) => {\n return createTreeNode(node, model, getTreeNodeError);\n });\n}\n\nfunction createTreeNode(modelNode: TreeModelHierarchyNode, model: TreeModel, getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined): TreeNode {\n let children: Array<TreeNode> | undefined;\n return {\n id: modelNode.id,\n label: modelNode.label,\n nodeData: modelNode.nodeData,\n isLoading: !!modelNode.isLoading,\n isExpanded: !!modelNode.isExpanded,\n isFilterable: !HierarchyNode.isGroupingNode(modelNode.nodeData) && !!modelNode.nodeData.supportsFiltering && modelNode.children,\n isFiltered: !!modelNode.instanceFilter,\n error: modelNode.error ?? getTreeNodeError?.(modelNode.nodeData),\n get children() {\n if (!children) {\n children = generateTreeStructure(modelNode.id, model, getTreeNodeError);\n }\n return children ? children : modelNode.children === true ? true : [];\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UseTree.js","names":["useCallback","useEffect","useMemo","useRef","useState","HierarchyNode","TreeActions","TreeModel","useUnifiedTreeSelection","safeDispose","useLatest","GenericInstanceFilter","HierarchyProvider","HierarchySearchTree","IPrimitiveValueFormatter","TreeModelHierarchyNode","TreeModelRootNode","UseUnifiedTreeSelectionProps","RootErrorRendererProps","TreeRendererProps","ErrorInfo","TreeNode","SelectionChangeType","useTree","props","$","_c","t0","useTreeInternal","rest","getTreeModelNode","_","t1","useUnifiedSelectionTree","createSelectableForGenericNode","selectionStorage","sourceName","t2","selectionProps","rootErrorRendererProps","undefined","treeRendererProps","rootNodes","t3","t4","UseTreeProps","getHierarchyProvider","getSearchPaths","abortSignal","AbortSignal","Promise","onPerformanceMeasured","action","duration","onHierarchyLimitExceeded","parentId","filter","limit","onHierarchyLoadError","type","error","getTreeNodeError","node","UseTreeResult","isReloading","getNode","nodeId","setFormatter","formatter","RendererProps","TreeState","model","Array","state","setState","idToNode","Map","parentChildMap","rootNode","id","nodeData","onPerformanceMeasuredRef","onHierarchyLimitExceededRef","onHierarchyLoadErrorRef","getTreeNodeErrorRef","actions","get","generateTreeStructure","current","actionType","currentFormatter","hierarchyProvider","setHierarchyProvider","provider","removeHierarchyChangedListener","hierarchyChanged","addListener","hierarchyChangeArgs","shouldDiscardState","searchChange","newSearch","reloadTree","reset","isSearching","setIsSearching","disposed","controller","AbortController","setHierarchySearch","paths","signal","abort","createTreeNode","expandNode","isExpanded","options","selectNodes","nodeIds","changeType","isNodeSelected","getHierarchyLevelDetails","hierarchyNode","isGroupingNode","getInstanceKeysIterator","getNodeInstanceKeys","parentNode","instanceFilter","hierarchyLevelSizeLimit","setInstanceFilter","sizeLimit","hierarchyLimit","setSizeLimit","value","setHierarchyLimit","renderProps","isLoading","parentNodeId","currentChildren","map","childId","modelNode","children","label","isFilterable","supportsFiltering","isFiltered"],"sources":["../../src/presentation-hierarchies-react/UseTree.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { TreeActions } from \"./internal/TreeActions.js\";\nimport { TreeModel } from \"./internal/TreeModel.js\";\nimport { useUnifiedTreeSelection } from \"./internal/UseUnifiedSelection.js\";\nimport { safeDispose } from \"./internal/Utils.js\";\nimport { useLatest } from \"./Utils.js\";\n\nimport type { GenericInstanceFilter, HierarchyProvider, HierarchySearchTree } from \"@itwin/presentation-hierarchies\";\nimport type { IPrimitiveValueFormatter } from \"@itwin/presentation-shared\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./internal/TreeModel.js\";\nimport type { UseUnifiedTreeSelectionProps } from \"./internal/UseUnifiedSelection.js\";\nimport type { RootErrorRendererProps, TreeRendererProps } from \"./Renderers.js\";\nimport type { ErrorInfo, TreeNode } from \"./TreeNode.js\";\nimport type { SelectionChangeType } from \"./UseSelectionHandler.js\";\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 the given selection storage (previously the storage was provided through the, now\n * deprecated, `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({\n sourceName,\n selectionStorage,\n createSelectableForGenericNode,\n ...props\n}: UseTreeProps & UseUnifiedTreeSelectionProps): UseTreeResult {\n const { getTreeModelNode, ...rest } = useTreeInternal(props);\n const selectionProps = useUnifiedTreeSelection({ sourceName, selectionStorage, getTreeModelNode, createSelectableForGenericNode });\n if (rest.rootErrorRendererProps === undefined && rest.treeRendererProps?.rootNodes) {\n return {\n ...rest,\n treeRendererProps: {\n ...rest.treeRendererProps,\n ...selectionProps,\n },\n };\n }\n return rest;\n}\n\n/** @public */\nexport interface UseTreeProps {\n /** Provides the hierarchy provider for the tree. */\n getHierarchyProvider: () => HierarchyProvider;\n /** Provides paths to search nodes. */\n getSearchPaths?: ({ abortSignal }: { abortSignal: AbortSignal }) => Promise<HierarchySearchTree[] | 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\"; error: unknown }) => void;\n /** Callback to set custom TreeNode errors.\n *\n * **Note:** Internal errors take precedence over custom ones.\n */\n getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined;\n}\n\n/** @public */\nexport type UseTreeResult = {\n /**\n * Specifies whether tree is reloading or not. It is set to `false` when initial tree load is in progress to check if\n * or tree is reloading.\n */\n isReloading: boolean;\n /**\n * Get a tree node by id\n */\n getNode: (nodeId: string) => TreeNode | undefined;\n /**\n * Sets a formatter for the primitive values that are displayed in the hierarchy.\n */\n setFormatter: (formatter: IPrimitiveValueFormatter | undefined) => void;\n} & RendererProps;\n\n/**.\n * @alpha\n */\ntype RendererProps =\n | {\n /**\n * An object containing information used to render root error handling UI.\n * Use in combination with `RootErrorRenderer` or your custom implementation.\n * Defined when root nodes fail to load.\n */\n rootErrorRendererProps: RootErrorRendererProps;\n }\n | {\n /** Is undefined when rootNodes were successfully loaded or are in initial loading process. */\n rootErrorRendererProps: undefined;\n /**\n * An object containing information used to render tree.\n * Use with `TreeRenderer` or your custom implementation.\n * Is undefined on initial loading process.\n */\n treeRendererProps?: TreeRendererProps;\n };\n\ninterface TreeState {\n model: TreeModel;\n rootNodes: Array<TreeNode> | undefined;\n}\n\nfunction useTreeInternal({\n getHierarchyProvider,\n getSearchPaths,\n onPerformanceMeasured,\n onHierarchyLimitExceeded,\n onHierarchyLoadError,\n getTreeNodeError,\n}: UseTreeProps): UseTreeResult & {\n getTreeModelNode: (nodeId: string) => TreeModelRootNode | TreeModelHierarchyNode | 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 const getTreeNodeErrorRef = useLatest(getTreeNodeError);\n\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions(\n (model) => {\n const rootNodes =\n model.parentChildMap.get(undefined) !== undefined ? generateTreeStructure(undefined, model, getTreeNodeErrorRef.current) : 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.searchChange?.newSearch !== 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 [isSearching, setIsSearching] = useState(false);\n useEffect(() => {\n let disposed = false as boolean;\n const controller = new AbortController();\n void (async () => {\n if (!hierarchyProvider) {\n return;\n }\n\n if (!getSearchPaths) {\n hierarchyProvider.setHierarchySearch(undefined);\n // reload tree in case hierarchy provider does not use hierarchy search to load initial nodes\n actions.reloadTree({ state: \"keep\" });\n setIsSearching(false);\n return;\n }\n\n setIsSearching(true);\n let paths: HierarchySearchTree[] | undefined;\n try {\n paths = await getSearchPaths({ abortSignal: controller.signal });\n } catch {\n } finally {\n if (!disposed) {\n hierarchyProvider.setHierarchySearch(paths ? { paths } : undefined);\n setIsSearching(false);\n }\n }\n })();\n return () => {\n controller.abort();\n disposed = true;\n };\n }, [hierarchyProvider, getSearchPaths, actions]);\n\n const getTreeModelNode = useCallback<(nodeId: string) => TreeModelRootNode | TreeModelHierarchyNode | undefined>(\n (nodeId: string) => {\n return actions.getNode(nodeId);\n },\n [actions],\n );\n\n const getNode = useCallback(\n (nodeId: string): TreeNode | undefined => {\n const node = actions.getNode(nodeId);\n if (!node || node.id === undefined) {\n return undefined;\n }\n return createTreeNode(node, state.model, getTreeNodeErrorRef.current);\n },\n [actions, getTreeNodeErrorRef, state.model],\n );\n\n const expandNode = useCallback<TreeRendererProps[\"expandNode\"]>(\n (nodeId: string, isExpanded: boolean) => {\n actions.expandNode(nodeId, isExpanded);\n },\n [actions],\n );\n\n const reloadTree = useCallback<TreeRendererProps[\"reloadTree\"]>(\n (options) => {\n actions.reloadTree(options);\n },\n [actions],\n );\n\n const selectNodes = useCallback<TreeRendererProps[\"selectNodes\"]>(\n (nodeIds: Array<string>, changeType: SelectionChangeType) => {\n actions.selectNodes(nodeIds, changeType);\n },\n [actions],\n );\n\n const isNodeSelected = useCallback<TreeRendererProps[\"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<TreeRendererProps[\"getHierarchyLevelDetails\"]>(\n (nodeId) => {\n const node = actions.getNode(nodeId);\n if (!hierarchyProvider || !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 const renderProps: RendererProps = useMemo(() => {\n if (state.model.rootNode.error) {\n return {\n rootErrorRendererProps: {\n error: state.model.rootNode.error,\n reloadTree,\n getHierarchyLevelDetails,\n },\n };\n }\n return {\n rootErrorRendererProps: undefined,\n treeRendererProps: state.rootNodes\n ? {\n rootNodes: state.rootNodes,\n expandNode,\n selectNodes,\n isNodeSelected,\n reloadTree,\n getHierarchyLevelDetails,\n }\n : undefined,\n };\n }, [expandNode, getHierarchyLevelDetails, isNodeSelected, reloadTree, selectNodes, state.model.rootNode.error, state.rootNodes]);\n\n return {\n ...renderProps,\n isReloading: !!state.model.rootNode.isLoading || isSearching,\n getTreeModelNode,\n getNode,\n setFormatter,\n };\n}\n\nfunction generateTreeStructure(\n parentNodeId: string | undefined,\n model: TreeModel,\n getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined,\n): Array<TreeNode> | 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 TreeModelHierarchyNode => !!node)\n .map<TreeNode>((node) => {\n return createTreeNode(node, model, getTreeNodeError);\n });\n}\n\nfunction createTreeNode(modelNode: TreeModelHierarchyNode, model: TreeModel, getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined): TreeNode {\n let children: Array<TreeNode> | undefined;\n return {\n id: modelNode.id,\n label: modelNode.label,\n nodeData: modelNode.nodeData,\n isLoading: !!modelNode.isLoading,\n isExpanded: !!modelNode.isExpanded,\n isFilterable: !HierarchyNode.isGroupingNode(modelNode.nodeData) && !!modelNode.nodeData.supportsFiltering && modelNode.children,\n isFiltered: !!modelNode.instanceFilter,\n error: modelNode.error ?? getTreeNodeError?.(modelNode.nodeData),\n get children() {\n if (!children) {\n children = generateTreeStructure(modelNode.id, model, getTreeNodeError);\n }\n return children ? children : modelNode.children === true ? true : [];\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { c } from "react-compiler-runtime";
|
|
2
2
|
import { useCallback, useInsertionEffect, useRef } from "react";
|
|
3
|
-
|
|
4
3
|
//#region src/presentation-hierarchies-react/Utils.ts
|
|
5
4
|
/** @internal */
|
|
6
5
|
function useLatest(value) {
|
|
@@ -53,4 +52,5 @@ function useMergedRefs(...refs) {
|
|
|
53
52
|
/* c8 ignore end */
|
|
54
53
|
//#endregion
|
|
55
54
|
export { useEvent, useLatest, useMergedRefs };
|
|
55
|
+
|
|
56
56
|
//# sourceMappingURL=Utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.js","names":["useCallback","useInsertionEffect","useRef","LegacyRef","MutableRefObject","Ref","useLatest","value","$","_c","ref","t0","t1","current","useEvent","callback","latestCallback","args","useMergedRefs","refs","ReadonlyArray","T","instance","forEach"],"sources":["../../src/presentation-hierarchies-react/Utils.ts"],"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, useInsertionEffect, useRef } from \"react\";\n\nimport type { LegacyRef, MutableRefObject, Ref } from \"react\";\n\n/** @internal */\nexport function useLatest<T>(value: T) {\n const ref = useRef(value);\n\n useInsertionEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n\n/* c8 ignore start */\n/** @internal */\nexport function useEvent<TCallback extends (...args: any[]) => void>(callback: TCallback) {\n const latestCallback = useLatest(callback);\n\n return useCallback(\n (...args: Parameters<TCallback>) => {\n latestCallback.current(...args);\n },\n [latestCallback],\n );\n}\n/* c8 ignore end */\n\n/* c8 ignore start */\n/** @internal */\nexport function useMergedRefs<T>(...refs: ReadonlyArray<Ref<T> | LegacyRef<T> | undefined | null>) {\n return useCallback(\n (instance: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(instance);\n } else if (ref) {\n (ref as MutableRefObject<T | null>).current = instance;\n }\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...refs],\n );\n}\n/* c8 ignore end */\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Utils.js","names":["useCallback","useInsertionEffect","useRef","LegacyRef","MutableRefObject","Ref","useLatest","value","$","_c","ref","t0","t1","current","useEvent","callback","latestCallback","args","useMergedRefs","refs","ReadonlyArray","T","instance","forEach"],"sources":["../../src/presentation-hierarchies-react/Utils.ts"],"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, useInsertionEffect, useRef } from \"react\";\n\nimport type { LegacyRef, MutableRefObject, Ref } from \"react\";\n\n/** @internal */\nexport function useLatest<T>(value: T) {\n const ref = useRef(value);\n\n useInsertionEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n\n/* c8 ignore start */\n/** @internal */\nexport function useEvent<TCallback extends (...args: any[]) => void>(callback: TCallback) {\n const latestCallback = useLatest(callback);\n\n return useCallback(\n (...args: Parameters<TCallback>) => {\n latestCallback.current(...args);\n },\n [latestCallback],\n );\n}\n/* c8 ignore end */\n\n/* c8 ignore start */\n/** @internal */\nexport function useMergedRefs<T>(...refs: ReadonlyArray<Ref<T> | LegacyRef<T> | undefined | null>) {\n return useCallback(\n (instance: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(instance);\n } else if (ref) {\n (ref as MutableRefObject<T | null>).current = instance;\n }\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...refs],\n );\n}\n/* c8 ignore end */\n"],"mappings":";;;;AAUA,SAAOM,UAAAC,OAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CACL,MAAAC,MAAYR,OAAOK,MAAM;CAAC,IAAAI;CAAA,IAAAC;AAAA,KAAAJ,EAAA,OAAAD,OAAA;AAEPI,aAAA;AACjBD,OAAGG,UAAWN;;AACbK,OAAA,CAACL,MAAM;AAAAC,IAAA,KAAAD;AAAAC,IAAA,KAAAG;AAAAH,IAAA,KAAAI;QAAA;AAAAD,OAAAH,EAAA;AAAAI,OAAAJ,EAAA;;AAFVP,oBAAmBU,IAEhBC,GAAQ;AAAA,QAEJF;;;;AAKT,SAAOI,SAAAC,UAAA;CAAA,MAAAP,IAAAC,EAAA,EAAA;CACL,MAAAO,iBAAuBV,UAAUS,SAAS;CAAC,IAAAJ;AAAA,KAAAH,EAAA,OAAAQ,gBAAA;AAGzCL,QAAA,GAAAC,OAAA;GAAC,MAAAK,OAAAL;AACCI,kBAAcH,QAAQ,GAAII,KAAK;;AAChCT,IAAA,KAAAQ;AAAAR,IAAA,KAAAG;OAAAA,MAAAH,EAAA;AAAA,QAHIG;;;;;AAWT,SAAgBO,cAAiB,GAAGC,MAA+D;AACjG,QAAOnB,aACJsB,aAAuB;AACtBH,OAAKI,SAASb,QAAQ;AACpB,OAAI,OAAOA,QAAQ,WACjBA,KAAIY,SAAS;YACJZ,IACRA,KAAmCG,UAAUS;IAEhD;IAEJ,CAAC,GAAGH,KACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DisposePolyfill.js","names":["Symbol","dispose","asyncDispose"],"sources":["../../../src/presentation-hierarchies-react/internal/DisposePolyfill.ts"],"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\n/**\n * Polyfill for upcoming resource management feature: https://github.com/tc39/proposal-explicit-resource-management\n */\n(Symbol as any).dispose ??= Symbol(\"Symbol.dispose\");\n(Symbol as any).asyncDispose ??= Symbol(\"Symbol.asyncDispose\");\n"],"mappings":";;;;AAQA,
|
|
1
|
+
{"version":3,"file":"DisposePolyfill.js","names":["Symbol","dispose","asyncDispose"],"sources":["../../../src/presentation-hierarchies-react/internal/DisposePolyfill.ts"],"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\n/**\n * Polyfill for upcoming resource management feature: https://github.com/tc39/proposal-explicit-resource-management\n */\n(Symbol as any).dispose ??= Symbol(\"Symbol.dispose\");\n(Symbol as any).asyncDispose ??= Symbol(\"Symbol.asyncDispose\");\n"],"mappings":";;;;AAQA,OAAgBC,YAAYD,OAAO,iBAAiB;AACpD,OAAgBE,iBAAiBF,OAAO,sBAAsB"}
|
|
@@ -6,7 +6,7 @@ const LOCALIZATION_NAMESPACE = "PresentationHierarchies_1.0";
|
|
|
6
6
|
* @alpha
|
|
7
7
|
*/
|
|
8
8
|
const LOCALIZATION_NAMESPACES = [LOCALIZATION_NAMESPACE];
|
|
9
|
-
|
|
10
9
|
//#endregion
|
|
11
10
|
export { LOCALIZATION_NAMESPACE, LOCALIZATION_NAMESPACES };
|
|
11
|
+
|
|
12
12
|
//# sourceMappingURL=LocalizedStrings.js.map
|
|
@@ -5,7 +5,6 @@ import { TreeModel } from "./TreeModel.js";
|
|
|
5
5
|
import { HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
6
6
|
import { enableMapSet, produce } from "immer";
|
|
7
7
|
import { EMPTY, Subject, buffer, debounceTime, groupBy, map, mergeMap, reduce, switchMap, takeUntil, tap } from "rxjs";
|
|
8
|
-
|
|
9
8
|
//#region src/presentation-hierarchies-react/internal/TreeActions.ts
|
|
10
9
|
enableMapSet();
|
|
11
10
|
/** @internal */
|
|
@@ -289,7 +288,7 @@ var TimeTracker = class {
|
|
|
289
288
|
this._onFinish(elapsedTime);
|
|
290
289
|
}
|
|
291
290
|
};
|
|
292
|
-
|
|
293
291
|
//#endregion
|
|
294
292
|
export { TreeActions };
|
|
293
|
+
|
|
295
294
|
//# sourceMappingURL=TreeActions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeActions.js","names":["enableMapSet","produce","buffer","debounceTime","EMPTY","groupBy","map","mergeMap","reduce","Subject","switchMap","takeUntil","tap","HierarchyNode","TreeLoader","TreeModel","createNodeId","sameNodes","Draft","Observable","GenericInstanceFilter","HierarchyProvider","ErrorInfo","SelectionChangeType","HierarchyLevelOptions","ITreeLoader","LoadedTreePart","LoadNodesOptions","TreeModelHierarchyNode","TreeModelRootNode","LoadDebouncedNodesOptions","loadOptions","onComplete","timeTracker","TimeTracker","initialRootNode","parentId","discardState","TreeActions","_loader","_nodeIdFactory","node","Pick","_currentModel","_reset","_nodeLoader","constructor","_onModelChanged","model","_onLoad","actionType","duration","_onHierarchyLimitExceeded","props","filter","limit","_onHierarchyLoadError","type","error","nodeIdFactory","seed","NoopTreeLoader","idToNode","Map","parentChildMap","rootNode","id","undefined","nodeData","createNodeLoader","subject","pipe","item","group","groupArr","returnIndex","length","forEach","member","index","Symbol","dispose","loadNodes","collectTreePartsUntil","next","newModel","parentNode","get","handleLoadedHierarchy","finish","complete","onLoadingComplete","subscribe","updateTreeModel","updater","loadedHierarchy","addHierarchyPart","setIsLoading","getLoadAction","size","loadSubTree","options","loadAction","parent","time","Promise","resolve","ignoreCache","getHierarchyLevelOptions","createHierarchyLevelOptions","getNonGroupedParentId","shouldLoadChildren","autoExpand","reloadSubTree","oldModel","currModel","expandedNodes","collectNodes","isExpanded","collapsedNodes","instanceFilter","hierarchyLevelSizeLimit","filteredNodeId","findIndex","expandedNode","collapsedNode","buildNode","addAttributes","getNode","reset","setHierarchyProvider","provider","Number","MAX_SAFE_INTEGER","nodeId","selectNodes","nodeIds","Array","changeType","expandNode","childrenAction","ReturnType","setHierarchyLimit","loadChildren","setInstanceFilter","reloadTree","parentNodeId","state","removeSubTree","untilNotifier","source","treeModel","loadedPart","addTreePartToModel","addNodesToModel","addErrorToModel","set","loadedNodes","oldNode","hierarchyLimit","isSelected","pred","currentChildren","flatMap","child","currNode","isGroupingNode","nonGroupingAncestor","modelNode","_start","_stopped","_onFinish","Date","now","elapsedTime"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeActions.ts"],"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 \"./DisposePolyfill.js\";\n\nimport { enableMapSet, produce } from \"immer\";\nimport { buffer, debounceTime, EMPTY, groupBy, map, mergeMap, reduce, Subject, switchMap, takeUntil, tap } from \"rxjs\";\nimport { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { TreeLoader } from \"./TreeLoader.js\";\nimport { TreeModel } from \"./TreeModel.js\";\nimport { createNodeId, sameNodes } from \"./Utils.js\";\n\nimport type { Draft } from \"immer\";\nimport type { Observable } from \"rxjs\";\nimport type { GenericInstanceFilter, HierarchyProvider } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { SelectionChangeType } from \"../UseSelectionHandler.js\";\nimport type { HierarchyLevelOptions, ITreeLoader, LoadedTreePart, LoadNodesOptions } from \"./TreeLoader.js\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./TreeModel.js\";\n\nenableMapSet();\n\ninterface LoadDebouncedNodesOptions {\n loadOptions: LoadNodesOptions;\n onComplete: () => void;\n timeTracker?: TimeTracker;\n initialRootNode?: TreeModelRootNode;\n parentId?: string;\n discardState?: boolean;\n}\n\n/** @internal */\nexport class TreeActions {\n private _loader: ITreeLoader;\n private _nodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n private _currentModel: TreeModel;\n private _reset = new Subject<void>();\n private _nodeLoader: Subject<LoadDebouncedNodesOptions>;\n\n constructor(\n private _onModelChanged: (model: TreeModel) => void,\n private _onLoad: (actionType: \"initial-load\" | \"hierarchy-level-load\" | \"reload\", duration: number) => void,\n private _onHierarchyLimitExceeded: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void,\n private _onHierarchyLoadError: (props: { parentId?: string; type: \"timeout\" | \"unknown\"; error: unknown }) => void,\n nodeIdFactory?: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string,\n seed?: TreeModel,\n ) {\n this._loader = new NoopTreeLoader();\n this._nodeIdFactory = nodeIdFactory ?? createNodeId;\n this._currentModel = seed ?? /* c8 ignore next */ {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: { id: undefined, nodeData: undefined },\n };\n\n this._nodeLoader = this.createNodeLoader();\n }\n\n private createNodeLoader() {\n const subject = new Subject<LoadDebouncedNodesOptions>();\n subject\n .pipe(\n groupBy((item) => item.parentId),\n mergeMap((group) =>\n group.pipe(\n buffer(group.pipe(debounceTime(0))),\n map((groupArr) => {\n let returnIndex = groupArr.length - 1;\n\n groupArr.forEach((member, index) => {\n if (member.discardState) {\n returnIndex = index;\n }\n });\n\n groupArr.forEach((member, index) => {\n if (index === returnIndex) {\n return;\n }\n member.timeTracker?.[Symbol.dispose];\n member.onComplete();\n });\n return groupArr[returnIndex];\n }),\n switchMap((props) =>\n this._loader.loadNodes(props.loadOptions).pipe(\n collectTreePartsUntil(this._reset, props.initialRootNode),\n tap({\n next: (newModel: TreeModel) => {\n const parentNode = props.parentId ? newModel.idToNode.get(props.parentId) : newModel.rootNode;\n this.handleLoadedHierarchy(props.parentId, newModel);\n // only report load duration if children were loaded\n if (!(parentNode && parentNode.error)) {\n props.timeTracker?.finish();\n }\n },\n complete: () => {\n this.onLoadingComplete(props.parentId);\n props.timeTracker?.[Symbol.dispose]();\n props.onComplete();\n },\n }),\n ),\n ),\n ),\n ),\n )\n .subscribe();\n\n return subject;\n }\n\n private updateTreeModel(updater: (model: Draft<TreeModel>) => void) {\n const newModel = produce(this._currentModel, updater);\n if (this._currentModel === newModel) {\n return;\n }\n\n this._currentModel = newModel;\n this._onModelChanged(this._currentModel);\n }\n\n private handleLoadedHierarchy(parentId: string | undefined, loadedHierarchy: TreeModel) {\n this.updateTreeModel((model) => {\n TreeModel.addHierarchyPart(model, parentId, loadedHierarchy);\n });\n }\n\n private onLoadingComplete(parentId: string | undefined) {\n this.updateTreeModel((model) => {\n TreeModel.setIsLoading(model, parentId, false);\n });\n }\n\n private getLoadAction(parentId: string | undefined) {\n return this._currentModel.idToNode.size === 0 ? \"initial-load\" : parentId === undefined ? \"reload\" : \"hierarchy-level-load\";\n }\n\n private loadSubTree(options: LoadNodesOptions, initialRootNode?: TreeModelRootNode, discardState?: boolean) {\n const loadAction = this.getLoadAction(options.parent.id);\n const timeTracker = new TimeTracker((time) => this._onLoad(loadAction, time));\n\n return {\n complete: new Promise<void>((resolve) => {\n this._nodeLoader.next({ loadOptions: options, onComplete: resolve, timeTracker, parentId: options.parent.id, initialRootNode, discardState });\n }),\n };\n }\n\n private loadNodes(parentId: string, ignoreCache?: boolean) {\n const parentNode = this._currentModel.idToNode.get(parentId);\n /* c8 ignore next 3 */\n if (!parentNode) {\n return { complete: Promise.resolve() };\n }\n return this.loadSubTree({\n parent: parentNode,\n getHierarchyLevelOptions: (node) => createHierarchyLevelOptions(this._currentModel, getNonGroupedParentId(node, this._nodeIdFactory)),\n shouldLoadChildren: (node) => !!node.nodeData.autoExpand,\n ignoreCache,\n });\n }\n\n private reloadSubTree(parentId: string | undefined, oldModel: TreeModel, options?: { discardState?: boolean; ignoreCache?: boolean }) {\n const currModel = this._currentModel;\n const expandedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === true);\n const collapsedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === false);\n const getHierarchyLevelOptions = (node: TreeModelRootNode | TreeModelHierarchyNode) => {\n if (!!options?.discardState) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n const filteredNodeId = getNonGroupedParentId(node, this._nodeIdFactory);\n return createHierarchyLevelOptions(filteredNodeId === parentId ? currModel : oldModel, filteredNodeId);\n };\n const shouldLoadChildren = (node: TreeModelHierarchyNode) => {\n if (expandedNodes.findIndex((expandedNode) => sameNodes(expandedNode.nodeData, node.nodeData)) !== -1) {\n return true;\n }\n if (collapsedNodes.findIndex((collapsedNode) => sameNodes(collapsedNode.nodeData, node.nodeData)) !== -1) {\n return false;\n }\n return !!node.nodeData.autoExpand;\n };\n const buildNode = (node: TreeModelHierarchyNode) => (!!options?.discardState || node.id === parentId ? node : addAttributes(node, oldModel));\n\n const rootNode = parentId !== undefined ? this.getNode(parentId) : currModel.rootNode;\n /* c8 ignore next 3 */\n if (!rootNode) {\n return { complete: Promise.resolve() };\n }\n\n if (parentId === undefined) {\n // cancel all ongoing requests\n this._reset.next();\n }\n\n return this.loadSubTree(\n { parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode, ignoreCache: options?.ignoreCache },\n !!options?.discardState ? undefined : { ...currModel.rootNode },\n options?.discardState,\n );\n }\n\n public reset() {\n this._reset.next();\n }\n\n public setHierarchyProvider(provider?: HierarchyProvider) {\n this._loader = provider\n ? new TreeLoader(\n provider,\n this._onHierarchyLimitExceeded,\n ({ parentId, type, error }) => {\n if (type === \"timeout\") {\n const loadAction = this.getLoadAction(parentId);\n this._onLoad(loadAction, Number.MAX_SAFE_INTEGER);\n }\n this._onHierarchyLoadError({ parentId, type, error });\n },\n this._nodeIdFactory,\n )\n : /* c8 ignore next */ new NoopTreeLoader();\n }\n\n public getNode(nodeId: string | undefined): TreeModelHierarchyNode | TreeModelRootNode | undefined {\n return TreeModel.getNode(this._currentModel, nodeId);\n }\n\n public selectNodes(nodeIds: Array<string>, changeType: SelectionChangeType) {\n this.updateTreeModel((model) => {\n TreeModel.selectNodes(model, nodeIds, changeType);\n });\n }\n\n public expandNode(nodeId: string, isExpanded: boolean) {\n let childrenAction = \"none\" as ReturnType<typeof TreeModel.expandNode>;\n this.updateTreeModel((model) => {\n childrenAction = TreeModel.expandNode(model, nodeId, isExpanded);\n });\n\n if (childrenAction === \"none\") {\n return { complete: Promise.resolve() };\n }\n\n return this.loadNodes(nodeId, childrenAction === \"reloadChildren\");\n }\n\n public setHierarchyLimit(nodeId: string | undefined, limit?: number | \"unbounded\") {\n const oldModel = this._currentModel;\n let loadChildren = false as boolean;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setHierarchyLimit(model, nodeId, limit);\n });\n\n if (!loadChildren) {\n return { complete: Promise.resolve() };\n }\n\n return this.reloadSubTree(nodeId, oldModel);\n }\n\n public setInstanceFilter(nodeId: string | undefined, filter?: GenericInstanceFilter) {\n const oldModel = this._currentModel;\n let loadChildren = false as boolean;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setInstanceFilter(model, nodeId, filter);\n });\n\n if (!loadChildren) {\n return { complete: Promise.resolve() };\n }\n\n return this.reloadSubTree(nodeId, oldModel);\n }\n\n public reloadTree(options?: { parentNodeId?: string; state?: \"keep\" | \"discard\" | \"reset\" }) {\n const oldModel = this._currentModel;\n this.updateTreeModel((model) => {\n TreeModel.setIsLoading(model, options?.parentNodeId, true);\n if (options?.state === \"reset\") {\n TreeModel.removeSubTree(model, options.parentNodeId);\n }\n });\n\n const discardState = options?.state === \"discard\" || options?.state === \"reset\";\n const ignoreCache = options?.state === \"reset\";\n return this.reloadSubTree(options?.parentNodeId, oldModel, { discardState, ignoreCache });\n }\n}\n\nfunction collectTreePartsUntil(untilNotifier: Observable<void>, rootNode?: TreeModelRootNode) {\n return (source: Observable<LoadedTreePart>) =>\n source.pipe(\n reduce<LoadedTreePart, TreeModel>(\n (treeModel, loadedPart) => {\n addTreePartToModel(treeModel, loadedPart);\n return treeModel;\n },\n {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: rootNode ?? { id: undefined, nodeData: undefined },\n },\n ),\n takeUntil(untilNotifier),\n );\n}\n\nfunction addTreePartToModel(treeModel: TreeModel, loadedPart: LoadedTreePart) {\n if (\"loadedNodes\" in loadedPart) {\n addNodesToModel(treeModel, loadedPart);\n } else {\n addErrorToModel(treeModel, loadedPart);\n }\n}\n\nfunction addErrorToModel(model: TreeModel, loadedPart: { parent: TreeModelHierarchyNode | TreeModelRootNode; error: ErrorInfo }) {\n if (loadedPart.parent.id === undefined) {\n model.rootNode.error = loadedPart.error;\n } else {\n model.idToNode.set(loadedPart.parent.id, { ...loadedPart.parent, error: loadedPart.error });\n }\n}\n\nfunction addNodesToModel(model: TreeModel, loadedPart: { parent: TreeModelHierarchyNode | TreeModelRootNode; loadedNodes: TreeModelHierarchyNode[] }) {\n model.parentChildMap.set(\n loadedPart.parent.id,\n loadedPart.loadedNodes.map((node) => node.id),\n );\n for (const node of loadedPart.loadedNodes) {\n model.idToNode.set(node.id, node);\n }\n const parentNode = loadedPart.parent.id ? model.idToNode.get(loadedPart.parent.id) : undefined;\n if (parentNode && loadedPart.loadedNodes.length !== 0) {\n parentNode.isExpanded = true;\n }\n}\n\nfunction addAttributes(node: TreeModelHierarchyNode, oldModel: TreeModel) {\n const oldNode = oldModel.idToNode.get(node.id);\n if (oldNode) {\n node.hierarchyLimit = oldNode.hierarchyLimit;\n node.instanceFilter = oldNode.instanceFilter;\n node.isSelected = oldNode.isSelected;\n }\n return node;\n}\n\nfunction collectNodes(parentId: string | undefined, model: TreeModel, pred: (node: TreeModelHierarchyNode) => boolean): TreeModelHierarchyNode[] {\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return [];\n }\n\n if (parentId === undefined) {\n return currentChildren.flatMap((child) => collectNodes(child, model, pred));\n }\n\n const currNode = model.idToNode.get(parentId);\n if (!currNode || !pred(currNode)) {\n return [];\n }\n\n return [currNode, ...currentChildren.flatMap((child) => collectNodes(child, model, pred))];\n}\n\nfunction getNonGroupedParentId(node: TreeModelHierarchyNode | TreeModelRootNode, nodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string) {\n if (!node.nodeData || !HierarchyNode.isGroupingNode(node.nodeData)) {\n return node.id;\n }\n\n if (!node.nodeData.nonGroupingAncestor) {\n return undefined;\n }\n\n return nodeIdFactory(node.nodeData.nonGroupingAncestor);\n}\n\nfunction createHierarchyLevelOptions(model: TreeModel, nodeId: string | undefined): HierarchyLevelOptions {\n if (nodeId === undefined) {\n return { instanceFilter: model.rootNode.instanceFilter, hierarchyLevelSizeLimit: model.rootNode.hierarchyLimit };\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n return { instanceFilter: modelNode.instanceFilter, hierarchyLevelSizeLimit: modelNode.hierarchyLimit };\n}\n\n/* c8 ignore start */\nclass NoopTreeLoader implements ITreeLoader {\n public loadNodes(): Observable<LoadedTreePart> {\n return EMPTY;\n }\n}\n/* c8 ignore end */\n\nclass TimeTracker {\n private _start: number;\n private _stopped: boolean = false;\n\n constructor(private _onFinish: (time: number) => void) {\n this._start = Date.now();\n }\n\n public [Symbol.dispose]() {\n this._stopped = true;\n }\n\n public finish() {\n /* c8 ignore next 3 */\n if (this._stopped) {\n return;\n }\n\n this._stopped = true;\n const elapsedTime = Date.now() - this._start;\n this._onFinish(elapsedTime);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreeActions.js","names":["enableMapSet","produce","buffer","debounceTime","EMPTY","groupBy","map","mergeMap","reduce","Subject","switchMap","takeUntil","tap","HierarchyNode","TreeLoader","TreeModel","createNodeId","sameNodes","Draft","Observable","GenericInstanceFilter","HierarchyProvider","ErrorInfo","SelectionChangeType","HierarchyLevelOptions","ITreeLoader","LoadedTreePart","LoadNodesOptions","TreeModelHierarchyNode","TreeModelRootNode","LoadDebouncedNodesOptions","loadOptions","onComplete","timeTracker","TimeTracker","initialRootNode","parentId","discardState","TreeActions","_loader","_nodeIdFactory","node","Pick","_currentModel","_reset","_nodeLoader","constructor","_onModelChanged","model","_onLoad","actionType","duration","_onHierarchyLimitExceeded","props","filter","limit","_onHierarchyLoadError","type","error","nodeIdFactory","seed","NoopTreeLoader","idToNode","Map","parentChildMap","rootNode","id","undefined","nodeData","createNodeLoader","subject","pipe","item","group","groupArr","returnIndex","length","forEach","member","index","Symbol","dispose","loadNodes","collectTreePartsUntil","next","newModel","parentNode","get","handleLoadedHierarchy","finish","complete","onLoadingComplete","subscribe","updateTreeModel","updater","loadedHierarchy","addHierarchyPart","setIsLoading","getLoadAction","size","loadSubTree","options","loadAction","parent","time","Promise","resolve","ignoreCache","getHierarchyLevelOptions","createHierarchyLevelOptions","getNonGroupedParentId","shouldLoadChildren","autoExpand","reloadSubTree","oldModel","currModel","expandedNodes","collectNodes","isExpanded","collapsedNodes","instanceFilter","hierarchyLevelSizeLimit","filteredNodeId","findIndex","expandedNode","collapsedNode","buildNode","addAttributes","getNode","reset","setHierarchyProvider","provider","Number","MAX_SAFE_INTEGER","nodeId","selectNodes","nodeIds","Array","changeType","expandNode","childrenAction","ReturnType","setHierarchyLimit","loadChildren","setInstanceFilter","reloadTree","parentNodeId","state","removeSubTree","untilNotifier","source","treeModel","loadedPart","addTreePartToModel","addNodesToModel","addErrorToModel","set","loadedNodes","oldNode","hierarchyLimit","isSelected","pred","currentChildren","flatMap","child","currNode","isGroupingNode","nonGroupingAncestor","modelNode","_start","_stopped","_onFinish","Date","now","elapsedTime"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeActions.ts"],"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 \"./DisposePolyfill.js\";\n\nimport { enableMapSet, produce } from \"immer\";\nimport { buffer, debounceTime, EMPTY, groupBy, map, mergeMap, reduce, Subject, switchMap, takeUntil, tap } from \"rxjs\";\nimport { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { TreeLoader } from \"./TreeLoader.js\";\nimport { TreeModel } from \"./TreeModel.js\";\nimport { createNodeId, sameNodes } from \"./Utils.js\";\n\nimport type { Draft } from \"immer\";\nimport type { Observable } from \"rxjs\";\nimport type { GenericInstanceFilter, HierarchyProvider } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { SelectionChangeType } from \"../UseSelectionHandler.js\";\nimport type { HierarchyLevelOptions, ITreeLoader, LoadedTreePart, LoadNodesOptions } from \"./TreeLoader.js\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./TreeModel.js\";\n\nenableMapSet();\n\ninterface LoadDebouncedNodesOptions {\n loadOptions: LoadNodesOptions;\n onComplete: () => void;\n timeTracker?: TimeTracker;\n initialRootNode?: TreeModelRootNode;\n parentId?: string;\n discardState?: boolean;\n}\n\n/** @internal */\nexport class TreeActions {\n private _loader: ITreeLoader;\n private _nodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n private _currentModel: TreeModel;\n private _reset = new Subject<void>();\n private _nodeLoader: Subject<LoadDebouncedNodesOptions>;\n\n constructor(\n private _onModelChanged: (model: TreeModel) => void,\n private _onLoad: (actionType: \"initial-load\" | \"hierarchy-level-load\" | \"reload\", duration: number) => void,\n private _onHierarchyLimitExceeded: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void,\n private _onHierarchyLoadError: (props: { parentId?: string; type: \"timeout\" | \"unknown\"; error: unknown }) => void,\n nodeIdFactory?: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string,\n seed?: TreeModel,\n ) {\n this._loader = new NoopTreeLoader();\n this._nodeIdFactory = nodeIdFactory ?? createNodeId;\n this._currentModel = seed ?? /* c8 ignore next */ {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: { id: undefined, nodeData: undefined },\n };\n\n this._nodeLoader = this.createNodeLoader();\n }\n\n private createNodeLoader() {\n const subject = new Subject<LoadDebouncedNodesOptions>();\n subject\n .pipe(\n groupBy((item) => item.parentId),\n mergeMap((group) =>\n group.pipe(\n buffer(group.pipe(debounceTime(0))),\n map((groupArr) => {\n let returnIndex = groupArr.length - 1;\n\n groupArr.forEach((member, index) => {\n if (member.discardState) {\n returnIndex = index;\n }\n });\n\n groupArr.forEach((member, index) => {\n if (index === returnIndex) {\n return;\n }\n member.timeTracker?.[Symbol.dispose];\n member.onComplete();\n });\n return groupArr[returnIndex];\n }),\n switchMap((props) =>\n this._loader.loadNodes(props.loadOptions).pipe(\n collectTreePartsUntil(this._reset, props.initialRootNode),\n tap({\n next: (newModel: TreeModel) => {\n const parentNode = props.parentId ? newModel.idToNode.get(props.parentId) : newModel.rootNode;\n this.handleLoadedHierarchy(props.parentId, newModel);\n // only report load duration if children were loaded\n if (!(parentNode && parentNode.error)) {\n props.timeTracker?.finish();\n }\n },\n complete: () => {\n this.onLoadingComplete(props.parentId);\n props.timeTracker?.[Symbol.dispose]();\n props.onComplete();\n },\n }),\n ),\n ),\n ),\n ),\n )\n .subscribe();\n\n return subject;\n }\n\n private updateTreeModel(updater: (model: Draft<TreeModel>) => void) {\n const newModel = produce(this._currentModel, updater);\n if (this._currentModel === newModel) {\n return;\n }\n\n this._currentModel = newModel;\n this._onModelChanged(this._currentModel);\n }\n\n private handleLoadedHierarchy(parentId: string | undefined, loadedHierarchy: TreeModel) {\n this.updateTreeModel((model) => {\n TreeModel.addHierarchyPart(model, parentId, loadedHierarchy);\n });\n }\n\n private onLoadingComplete(parentId: string | undefined) {\n this.updateTreeModel((model) => {\n TreeModel.setIsLoading(model, parentId, false);\n });\n }\n\n private getLoadAction(parentId: string | undefined) {\n return this._currentModel.idToNode.size === 0 ? \"initial-load\" : parentId === undefined ? \"reload\" : \"hierarchy-level-load\";\n }\n\n private loadSubTree(options: LoadNodesOptions, initialRootNode?: TreeModelRootNode, discardState?: boolean) {\n const loadAction = this.getLoadAction(options.parent.id);\n const timeTracker = new TimeTracker((time) => this._onLoad(loadAction, time));\n\n return {\n complete: new Promise<void>((resolve) => {\n this._nodeLoader.next({ loadOptions: options, onComplete: resolve, timeTracker, parentId: options.parent.id, initialRootNode, discardState });\n }),\n };\n }\n\n private loadNodes(parentId: string, ignoreCache?: boolean) {\n const parentNode = this._currentModel.idToNode.get(parentId);\n /* c8 ignore next 3 */\n if (!parentNode) {\n return { complete: Promise.resolve() };\n }\n return this.loadSubTree({\n parent: parentNode,\n getHierarchyLevelOptions: (node) => createHierarchyLevelOptions(this._currentModel, getNonGroupedParentId(node, this._nodeIdFactory)),\n shouldLoadChildren: (node) => !!node.nodeData.autoExpand,\n ignoreCache,\n });\n }\n\n private reloadSubTree(parentId: string | undefined, oldModel: TreeModel, options?: { discardState?: boolean; ignoreCache?: boolean }) {\n const currModel = this._currentModel;\n const expandedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === true);\n const collapsedNodes = !!options?.discardState ? [] : collectNodes(parentId, oldModel, (node) => node.isExpanded === false);\n const getHierarchyLevelOptions = (node: TreeModelRootNode | TreeModelHierarchyNode) => {\n if (!!options?.discardState) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n const filteredNodeId = getNonGroupedParentId(node, this._nodeIdFactory);\n return createHierarchyLevelOptions(filteredNodeId === parentId ? currModel : oldModel, filteredNodeId);\n };\n const shouldLoadChildren = (node: TreeModelHierarchyNode) => {\n if (expandedNodes.findIndex((expandedNode) => sameNodes(expandedNode.nodeData, node.nodeData)) !== -1) {\n return true;\n }\n if (collapsedNodes.findIndex((collapsedNode) => sameNodes(collapsedNode.nodeData, node.nodeData)) !== -1) {\n return false;\n }\n return !!node.nodeData.autoExpand;\n };\n const buildNode = (node: TreeModelHierarchyNode) => (!!options?.discardState || node.id === parentId ? node : addAttributes(node, oldModel));\n\n const rootNode = parentId !== undefined ? this.getNode(parentId) : currModel.rootNode;\n /* c8 ignore next 3 */\n if (!rootNode) {\n return { complete: Promise.resolve() };\n }\n\n if (parentId === undefined) {\n // cancel all ongoing requests\n this._reset.next();\n }\n\n return this.loadSubTree(\n { parent: rootNode, getHierarchyLevelOptions, shouldLoadChildren, buildNode, ignoreCache: options?.ignoreCache },\n !!options?.discardState ? undefined : { ...currModel.rootNode },\n options?.discardState,\n );\n }\n\n public reset() {\n this._reset.next();\n }\n\n public setHierarchyProvider(provider?: HierarchyProvider) {\n this._loader = provider\n ? new TreeLoader(\n provider,\n this._onHierarchyLimitExceeded,\n ({ parentId, type, error }) => {\n if (type === \"timeout\") {\n const loadAction = this.getLoadAction(parentId);\n this._onLoad(loadAction, Number.MAX_SAFE_INTEGER);\n }\n this._onHierarchyLoadError({ parentId, type, error });\n },\n this._nodeIdFactory,\n )\n : /* c8 ignore next */ new NoopTreeLoader();\n }\n\n public getNode(nodeId: string | undefined): TreeModelHierarchyNode | TreeModelRootNode | undefined {\n return TreeModel.getNode(this._currentModel, nodeId);\n }\n\n public selectNodes(nodeIds: Array<string>, changeType: SelectionChangeType) {\n this.updateTreeModel((model) => {\n TreeModel.selectNodes(model, nodeIds, changeType);\n });\n }\n\n public expandNode(nodeId: string, isExpanded: boolean) {\n let childrenAction = \"none\" as ReturnType<typeof TreeModel.expandNode>;\n this.updateTreeModel((model) => {\n childrenAction = TreeModel.expandNode(model, nodeId, isExpanded);\n });\n\n if (childrenAction === \"none\") {\n return { complete: Promise.resolve() };\n }\n\n return this.loadNodes(nodeId, childrenAction === \"reloadChildren\");\n }\n\n public setHierarchyLimit(nodeId: string | undefined, limit?: number | \"unbounded\") {\n const oldModel = this._currentModel;\n let loadChildren = false as boolean;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setHierarchyLimit(model, nodeId, limit);\n });\n\n if (!loadChildren) {\n return { complete: Promise.resolve() };\n }\n\n return this.reloadSubTree(nodeId, oldModel);\n }\n\n public setInstanceFilter(nodeId: string | undefined, filter?: GenericInstanceFilter) {\n const oldModel = this._currentModel;\n let loadChildren = false as boolean;\n this.updateTreeModel((model) => {\n loadChildren = TreeModel.setInstanceFilter(model, nodeId, filter);\n });\n\n if (!loadChildren) {\n return { complete: Promise.resolve() };\n }\n\n return this.reloadSubTree(nodeId, oldModel);\n }\n\n public reloadTree(options?: { parentNodeId?: string; state?: \"keep\" | \"discard\" | \"reset\" }) {\n const oldModel = this._currentModel;\n this.updateTreeModel((model) => {\n TreeModel.setIsLoading(model, options?.parentNodeId, true);\n if (options?.state === \"reset\") {\n TreeModel.removeSubTree(model, options.parentNodeId);\n }\n });\n\n const discardState = options?.state === \"discard\" || options?.state === \"reset\";\n const ignoreCache = options?.state === \"reset\";\n return this.reloadSubTree(options?.parentNodeId, oldModel, { discardState, ignoreCache });\n }\n}\n\nfunction collectTreePartsUntil(untilNotifier: Observable<void>, rootNode?: TreeModelRootNode) {\n return (source: Observable<LoadedTreePart>) =>\n source.pipe(\n reduce<LoadedTreePart, TreeModel>(\n (treeModel, loadedPart) => {\n addTreePartToModel(treeModel, loadedPart);\n return treeModel;\n },\n {\n idToNode: new Map(),\n parentChildMap: new Map(),\n rootNode: rootNode ?? { id: undefined, nodeData: undefined },\n },\n ),\n takeUntil(untilNotifier),\n );\n}\n\nfunction addTreePartToModel(treeModel: TreeModel, loadedPart: LoadedTreePart) {\n if (\"loadedNodes\" in loadedPart) {\n addNodesToModel(treeModel, loadedPart);\n } else {\n addErrorToModel(treeModel, loadedPart);\n }\n}\n\nfunction addErrorToModel(model: TreeModel, loadedPart: { parent: TreeModelHierarchyNode | TreeModelRootNode; error: ErrorInfo }) {\n if (loadedPart.parent.id === undefined) {\n model.rootNode.error = loadedPart.error;\n } else {\n model.idToNode.set(loadedPart.parent.id, { ...loadedPart.parent, error: loadedPart.error });\n }\n}\n\nfunction addNodesToModel(model: TreeModel, loadedPart: { parent: TreeModelHierarchyNode | TreeModelRootNode; loadedNodes: TreeModelHierarchyNode[] }) {\n model.parentChildMap.set(\n loadedPart.parent.id,\n loadedPart.loadedNodes.map((node) => node.id),\n );\n for (const node of loadedPart.loadedNodes) {\n model.idToNode.set(node.id, node);\n }\n const parentNode = loadedPart.parent.id ? model.idToNode.get(loadedPart.parent.id) : undefined;\n if (parentNode && loadedPart.loadedNodes.length !== 0) {\n parentNode.isExpanded = true;\n }\n}\n\nfunction addAttributes(node: TreeModelHierarchyNode, oldModel: TreeModel) {\n const oldNode = oldModel.idToNode.get(node.id);\n if (oldNode) {\n node.hierarchyLimit = oldNode.hierarchyLimit;\n node.instanceFilter = oldNode.instanceFilter;\n node.isSelected = oldNode.isSelected;\n }\n return node;\n}\n\nfunction collectNodes(parentId: string | undefined, model: TreeModel, pred: (node: TreeModelHierarchyNode) => boolean): TreeModelHierarchyNode[] {\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return [];\n }\n\n if (parentId === undefined) {\n return currentChildren.flatMap((child) => collectNodes(child, model, pred));\n }\n\n const currNode = model.idToNode.get(parentId);\n if (!currNode || !pred(currNode)) {\n return [];\n }\n\n return [currNode, ...currentChildren.flatMap((child) => collectNodes(child, model, pred))];\n}\n\nfunction getNonGroupedParentId(node: TreeModelHierarchyNode | TreeModelRootNode, nodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string) {\n if (!node.nodeData || !HierarchyNode.isGroupingNode(node.nodeData)) {\n return node.id;\n }\n\n if (!node.nodeData.nonGroupingAncestor) {\n return undefined;\n }\n\n return nodeIdFactory(node.nodeData.nonGroupingAncestor);\n}\n\nfunction createHierarchyLevelOptions(model: TreeModel, nodeId: string | undefined): HierarchyLevelOptions {\n if (nodeId === undefined) {\n return { instanceFilter: model.rootNode.instanceFilter, hierarchyLevelSizeLimit: model.rootNode.hierarchyLimit };\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return { instanceFilter: undefined, hierarchyLevelSizeLimit: undefined };\n }\n return { instanceFilter: modelNode.instanceFilter, hierarchyLevelSizeLimit: modelNode.hierarchyLimit };\n}\n\n/* c8 ignore start */\nclass NoopTreeLoader implements ITreeLoader {\n public loadNodes(): Observable<LoadedTreePart> {\n return EMPTY;\n }\n}\n/* c8 ignore end */\n\nclass TimeTracker {\n private _start: number;\n private _stopped: boolean = false;\n\n constructor(private _onFinish: (time: number) => void) {\n this._start = Date.now();\n }\n\n public [Symbol.dispose]() {\n this._stopped = true;\n }\n\n public finish() {\n /* c8 ignore next 3 */\n if (this._stopped) {\n return;\n }\n\n this._stopped = true;\n const elapsedTime = Date.now() - this._start;\n this._onFinish(elapsedTime);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createNodeId } from "./Utils.js";
|
|
2
2
|
import { EMPTY, catchError, expand, filter, from, map, mergeMap, of, toArray } from "rxjs";
|
|
3
|
-
|
|
4
3
|
//#region src/presentation-hierarchies-react/internal/TreeLoader.ts
|
|
5
4
|
/** @internal */
|
|
6
5
|
var TreeLoader = class {
|
|
@@ -93,7 +92,7 @@ function isRowsLimitError(error) {
|
|
|
93
92
|
function isTimeoutError(error) {
|
|
94
93
|
return error.message.includes("query too long to execute or server is too busy");
|
|
95
94
|
}
|
|
96
|
-
|
|
97
95
|
//#endregion
|
|
98
96
|
export { TreeLoader };
|
|
97
|
+
|
|
99
98
|
//# sourceMappingURL=TreeLoader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeLoader.js","names":["catchError","EMPTY","expand","filter","from","map","mergeMap","of","toArray","createNodeId","Observable","GenericInstanceFilter","HierarchyNode","HierarchyProvider","RowsLimitExceededError","ErrorInfo","TreeModelHierarchyNode","TreeModelRootNode","LoadedTreePart","parent","loadedNodes","error","HierarchyLevelOptions","instanceFilter","hierarchyLevelSizeLimit","LoadNodesOptions","getHierarchyLevelOptions","node","shouldLoadChildren","buildNode","ignoreCache","ITreeLoader","loadNodes","options","TreeLoader","_treeNodeIdFactory","Pick","constructor","_hierarchyProvider","_onHierarchyLimitExceeded","props","parentId","limit","_onHierarchyLoadError","type","treeNodeIdFactory","loadChildren","Omit","infoNodeIdBase","id","treeModelNodesFactory","createTreeModelNodesFactory","getNodes","parentNode","nodeData","pipe","childNodes","length","const","err","hierarchyLoadErrorType","Error","isRowsLimitError","message","resultSetSizeLimit","isTimeoutError","loadedPart","modelNode","children","label","includes"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeLoader.ts"],"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 { catchError, EMPTY, expand, filter, from, map, mergeMap, of, toArray } from \"rxjs\";\nimport { createNodeId } from \"./Utils.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GenericInstanceFilter, HierarchyNode, HierarchyProvider, RowsLimitExceededError } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./TreeModel.js\";\n\n/** @internal */\nexport type LoadedTreePart = {\n parent: TreeModelHierarchyNode | TreeModelRootNode;\n} & (\n | {\n loadedNodes: TreeModelHierarchyNode[];\n }\n | {\n error: ErrorInfo;\n }\n);\n\n/** @internal */\nexport interface HierarchyLevelOptions {\n instanceFilter?: GenericInstanceFilter;\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n}\n\n/** @internal */\nexport interface LoadNodesOptions {\n parent: TreeModelHierarchyNode | TreeModelRootNode;\n getHierarchyLevelOptions: (node: TreeModelRootNode | TreeModelHierarchyNode) => HierarchyLevelOptions;\n shouldLoadChildren: (node: TreeModelHierarchyNode) => boolean;\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;\n ignoreCache?: boolean;\n}\n\n/** @internal */\nexport interface ITreeLoader {\n loadNodes(options: LoadNodesOptions): Observable<LoadedTreePart>;\n}\n\n/** @internal */\nexport class TreeLoader implements ITreeLoader {\n private _treeNodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n\n constructor(\n private _hierarchyProvider: HierarchyProvider,\n private _onHierarchyLimitExceeded: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void,\n private _onHierarchyLoadError: (props: { parentId?: string; type: \"timeout\" | \"unknown\"; error: unknown }) => void,\n treeNodeIdFactory?: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string,\n ) {\n this._treeNodeIdFactory = treeNodeIdFactory ?? /* c8 ignore next */ createNodeId;\n }\n\n private loadChildren({ parent, getHierarchyLevelOptions, buildNode, ignoreCache }: Omit<LoadNodesOptions, \"shouldLoadChildren\">) {\n const { instanceFilter, hierarchyLevelSizeLimit } = getHierarchyLevelOptions(parent);\n const infoNodeIdBase = `${parent.id ?? \"<root>\"}`;\n const treeModelNodesFactory = createTreeModelNodesFactory({ buildNode, treeNodeIdFactory: this._treeNodeIdFactory });\n return from(\n this._hierarchyProvider.getNodes({\n parentNode: parent.nodeData,\n hierarchyLevelSizeLimit,\n instanceFilter,\n ignoreCache,\n }),\n ).pipe(\n toArray(),\n map((childNodes): LoadedTreePart => {\n return instanceFilter && childNodes.length === 0\n ? {\n parent,\n error: {\n id: `${infoNodeIdBase}-no-filter-matches`,\n type: \"NoFilterMatches\" as const,\n },\n }\n : {\n parent,\n loadedNodes: childNodes.map(treeModelNodesFactory),\n };\n }),\n catchError((err) => {\n let hierarchyLoadErrorType: \"unknown\" | \"timeout\" = \"unknown\";\n if (err instanceof Error) {\n if (isRowsLimitError(err)) {\n this._onHierarchyLimitExceeded({ parentId: parent.id, filter: instanceFilter, limit: err.limit });\n return of({\n parent,\n error: { id: `${infoNodeIdBase}-${err.message}`, type: \"ResultSetTooLarge\" as const, resultSetSizeLimit: err.limit },\n });\n }\n if (isTimeoutError(err)) {\n hierarchyLoadErrorType = \"timeout\";\n }\n }\n\n this._onHierarchyLoadError({ parentId: parent.id, type: hierarchyLoadErrorType, error: err });\n return of({\n parent,\n error: {\n id: `${infoNodeIdBase}-ChildrenLoad`,\n type: \"ChildrenLoad\" as const,\n message: \"Failed to create hierarchy level\",\n },\n });\n }),\n );\n }\n\n public loadNodes({ shouldLoadChildren, ...options }: LoadNodesOptions) {\n return this.loadChildren(options).pipe(\n expand((loadedPart) =>\n \"loadedNodes\" in loadedPart\n ? from(loadedPart.loadedNodes).pipe(\n filter((node) => shouldLoadChildren(node)),\n mergeMap((node) => this.loadChildren({ ...options, parent: node })),\n )\n : EMPTY,\n ),\n );\n }\n}\n\nfunction createTreeModelNodesFactory({\n buildNode,\n treeNodeIdFactory,\n}: {\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;\n treeNodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n}): (node: HierarchyNode) => TreeModelHierarchyNode {\n return (node: HierarchyNode) => {\n const modelNode: TreeModelHierarchyNode = {\n id: treeNodeIdFactory(node),\n children: node.children,\n label: node.label,\n nodeData: node,\n };\n return buildNode ? buildNode(modelNode) : modelNode;\n };\n}\n\nfunction isRowsLimitError(error: Error): error is RowsLimitExceededError {\n return \"limit\" in error && error.message.includes(\"Query rows limit of\");\n}\n\nfunction isTimeoutError(error: Error) {\n return error.message.includes(\"query too long to execute or server is too busy\");\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TreeLoader.js","names":["catchError","EMPTY","expand","filter","from","map","mergeMap","of","toArray","createNodeId","Observable","GenericInstanceFilter","HierarchyNode","HierarchyProvider","RowsLimitExceededError","ErrorInfo","TreeModelHierarchyNode","TreeModelRootNode","LoadedTreePart","parent","loadedNodes","error","HierarchyLevelOptions","instanceFilter","hierarchyLevelSizeLimit","LoadNodesOptions","getHierarchyLevelOptions","node","shouldLoadChildren","buildNode","ignoreCache","ITreeLoader","loadNodes","options","TreeLoader","_treeNodeIdFactory","Pick","constructor","_hierarchyProvider","_onHierarchyLimitExceeded","props","parentId","limit","_onHierarchyLoadError","type","treeNodeIdFactory","loadChildren","Omit","infoNodeIdBase","id","treeModelNodesFactory","createTreeModelNodesFactory","getNodes","parentNode","nodeData","pipe","childNodes","length","const","err","hierarchyLoadErrorType","Error","isRowsLimitError","message","resultSetSizeLimit","isTimeoutError","loadedPart","modelNode","children","label","includes"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeLoader.ts"],"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 { catchError, EMPTY, expand, filter, from, map, mergeMap, of, toArray } from \"rxjs\";\nimport { createNodeId } from \"./Utils.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GenericInstanceFilter, HierarchyNode, HierarchyProvider, RowsLimitExceededError } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { TreeModelHierarchyNode, TreeModelRootNode } from \"./TreeModel.js\";\n\n/** @internal */\nexport type LoadedTreePart = {\n parent: TreeModelHierarchyNode | TreeModelRootNode;\n} & (\n | {\n loadedNodes: TreeModelHierarchyNode[];\n }\n | {\n error: ErrorInfo;\n }\n);\n\n/** @internal */\nexport interface HierarchyLevelOptions {\n instanceFilter?: GenericInstanceFilter;\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n}\n\n/** @internal */\nexport interface LoadNodesOptions {\n parent: TreeModelHierarchyNode | TreeModelRootNode;\n getHierarchyLevelOptions: (node: TreeModelRootNode | TreeModelHierarchyNode) => HierarchyLevelOptions;\n shouldLoadChildren: (node: TreeModelHierarchyNode) => boolean;\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;\n ignoreCache?: boolean;\n}\n\n/** @internal */\nexport interface ITreeLoader {\n loadNodes(options: LoadNodesOptions): Observable<LoadedTreePart>;\n}\n\n/** @internal */\nexport class TreeLoader implements ITreeLoader {\n private _treeNodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n\n constructor(\n private _hierarchyProvider: HierarchyProvider,\n private _onHierarchyLimitExceeded: (props: { parentId?: string; filter?: GenericInstanceFilter; limit?: number | \"unbounded\" }) => void,\n private _onHierarchyLoadError: (props: { parentId?: string; type: \"timeout\" | \"unknown\"; error: unknown }) => void,\n treeNodeIdFactory?: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string,\n ) {\n this._treeNodeIdFactory = treeNodeIdFactory ?? /* c8 ignore next */ createNodeId;\n }\n\n private loadChildren({ parent, getHierarchyLevelOptions, buildNode, ignoreCache }: Omit<LoadNodesOptions, \"shouldLoadChildren\">) {\n const { instanceFilter, hierarchyLevelSizeLimit } = getHierarchyLevelOptions(parent);\n const infoNodeIdBase = `${parent.id ?? \"<root>\"}`;\n const treeModelNodesFactory = createTreeModelNodesFactory({ buildNode, treeNodeIdFactory: this._treeNodeIdFactory });\n return from(\n this._hierarchyProvider.getNodes({\n parentNode: parent.nodeData,\n hierarchyLevelSizeLimit,\n instanceFilter,\n ignoreCache,\n }),\n ).pipe(\n toArray(),\n map((childNodes): LoadedTreePart => {\n return instanceFilter && childNodes.length === 0\n ? {\n parent,\n error: {\n id: `${infoNodeIdBase}-no-filter-matches`,\n type: \"NoFilterMatches\" as const,\n },\n }\n : {\n parent,\n loadedNodes: childNodes.map(treeModelNodesFactory),\n };\n }),\n catchError((err) => {\n let hierarchyLoadErrorType: \"unknown\" | \"timeout\" = \"unknown\";\n if (err instanceof Error) {\n if (isRowsLimitError(err)) {\n this._onHierarchyLimitExceeded({ parentId: parent.id, filter: instanceFilter, limit: err.limit });\n return of({\n parent,\n error: { id: `${infoNodeIdBase}-${err.message}`, type: \"ResultSetTooLarge\" as const, resultSetSizeLimit: err.limit },\n });\n }\n if (isTimeoutError(err)) {\n hierarchyLoadErrorType = \"timeout\";\n }\n }\n\n this._onHierarchyLoadError({ parentId: parent.id, type: hierarchyLoadErrorType, error: err });\n return of({\n parent,\n error: {\n id: `${infoNodeIdBase}-ChildrenLoad`,\n type: \"ChildrenLoad\" as const,\n message: \"Failed to create hierarchy level\",\n },\n });\n }),\n );\n }\n\n public loadNodes({ shouldLoadChildren, ...options }: LoadNodesOptions) {\n return this.loadChildren(options).pipe(\n expand((loadedPart) =>\n \"loadedNodes\" in loadedPart\n ? from(loadedPart.loadedNodes).pipe(\n filter((node) => shouldLoadChildren(node)),\n mergeMap((node) => this.loadChildren({ ...options, parent: node })),\n )\n : EMPTY,\n ),\n );\n }\n}\n\nfunction createTreeModelNodesFactory({\n buildNode,\n treeNodeIdFactory,\n}: {\n buildNode?: (node: TreeModelHierarchyNode) => TreeModelHierarchyNode;\n treeNodeIdFactory: (node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) => string;\n}): (node: HierarchyNode) => TreeModelHierarchyNode {\n return (node: HierarchyNode) => {\n const modelNode: TreeModelHierarchyNode = {\n id: treeNodeIdFactory(node),\n children: node.children,\n label: node.label,\n nodeData: node,\n };\n return buildNode ? buildNode(modelNode) : modelNode;\n };\n}\n\nfunction isRowsLimitError(error: Error): error is RowsLimitExceededError {\n return \"limit\" in error && error.message.includes(\"Query rows limit of\");\n}\n\nfunction isTimeoutError(error: Error) {\n return error.message.includes(\"query too long to execute or server is too busy\");\n}\n"],"mappings":";;;;AA8CA,IAAakC,aAAb,MAA+C;CAC7C;CAEAG,YACE,oBACA,2BACA,uBACAQ,mBACA;AAJQP,OAAAA,qBAAAA;AACAC,OAAAA,4BAAAA;AACAI,OAAAA,wBAAAA;AAGR,OAAKR,qBAAqBU,qBAA0CpC;;CAGtE,aAAqB,EAAEU,QAAQO,0BAA0BG,WAAWC,eAA6D;EAC/H,MAAM,EAAEP,gBAAgBC,4BAA4BE,yBAAyBP,OAAO;EACpF,MAAM6B,iBAAiB,GAAG7B,OAAO8B,MAAM;EACvC,MAAMC,wBAAwBC,4BAA4B;GAAEtB;GAAWgB,mBAAmB,KAAKV;GAAoB,CAAC;AACpH,SAAO/B,KACL,KAAKkC,mBAAmBc,SAAS;GAC/BC,YAAYlC,OAAOmC;GACnB9B;GACAD;GACAO;GACD,CACH,CAAC,CAACyB,KACA/C,SAAS,EACTH,KAAKmD,eAA+B;AAClC,UAAOjC,kBAAkBiC,WAAWC,WAAW,IAC3C;IACEtC;IACAE,OAAO;KACL4B,IAAI,GAAGD,eAAc;KACrBJ,MAAM;KACR;IACD,GACD;IACEzB;IACAC,aAAaoC,WAAWnD,IAAI6C,sBAAqB;IAClD;IACL,EACFlD,YAAY2D,QAAQ;GAClB,IAAIC,yBAAgD;AACpD,OAAID,eAAeE,OAAO;AACxB,QAAIC,iBAAiBH,IAAI,EAAE;AACzB,UAAKpB,0BAA0B;MAAEE,UAAUtB,OAAO8B;MAAI9C,QAAQoB;MAAgBmB,OAAOiB,IAAIjB;MAAO,CAAC;AACjG,YAAOnC,GAAG;MACRY;MACAE,OAAO;OAAE4B,IAAI,GAAGD,eAAc,GAAIW,IAAII;OAAWnB,MAAM;OAA8BoB,oBAAoBL,IAAIjB;OAAM;MACpH,CAAC;;AAEJ,QAAIuB,eAAeN,IAAI,CACrBC,0BAAyB;;AAI7B,QAAKjB,sBAAsB;IAAEF,UAAUtB,OAAO8B;IAAIL,MAAMgB;IAAwBvC,OAAOsC;IAAK,CAAC;AAC7F,UAAOpD,GAAG;IACRY;IACAE,OAAO;KACL4B,IAAI,GAAGD,eAAc;KACrBJ,MAAM;KACNmB,SAAS;KACX;IACD,CAAC;IAEN,CAAC;;CAGH,UAAiB,EAAEnC,oBAAoB,GAAGK,WAA6B;AACrE,SAAO,KAAKa,aAAab,QAAQ,CAACsB,KAChCrD,QAAQgE,eACN,iBAAiBA,aACb9D,KAAK8D,WAAW9C,YAAY,CAACmC,KAC3BpD,QAAQwB,SAASC,mBAAmBD,KAAK,CAAC,EAC1CrB,UAAUqB,SAAS,KAAKmB,aAAa;GAAE,GAAGb;GAASd,QAAQQ;GAAM,CAAC,CACpE,CAAC,GACD1B,MAER,CAAC;;;AAIL,SAASkD,4BAA4B,EACnCtB,WACAgB,qBAIkD;AAClD,SAAQlB,SAAwB;EAC9B,MAAMwC,YAAoC;GACxClB,IAAIJ,kBAAkBlB,KAAK;GAC3ByC,UAAUzC,KAAKyC;GACfC,OAAO1C,KAAK0C;GACZf,UAAU3B;GACX;AACD,SAAOE,YAAYA,UAAUsC,UAAU,GAAGA;;;AAI9C,SAASL,iBAAiBzC,OAA+C;AACvE,QAAO,WAAWA,SAASA,MAAM0C,QAAQO,SAAS,sBAAsB;;AAG1E,SAASL,eAAe5C,OAAc;AACpC,QAAOA,MAAM0C,QAAQO,SAAS,kDAAkD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeModel.js","names":["GenericInstanceFilter","HierarchyNode","ErrorInfo","SelectionChangeType","TreeModelRootNode","id","nodeData","hierarchyLimit","instanceFilter","isLoading","error","TreeModelHierarchyNode","label","children","isExpanded","isSelected","TreeModel","parentChildMap","Map","idToNode","rootNode","expandNode","model","nodeId","node","get","type","removeSubTree","addHierarchyPart","rootId","hierarchyPart","parentId","set","parentNode","undefined","clearNodeError","currentChildren","delete","childId","childNode","setHierarchyLimit","limit","updateForReload","setInstanceFilter","filter","selectNodes","nodeIds","Array","changeType","find","modelNode","isNodeSelected","currentNode","getNode","setIsLoading","update"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeModel.ts"],"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 type { GenericInstanceFilter, HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { SelectionChangeType } from \"../UseSelectionHandler.js\";\n\n/** @internal */\nexport interface TreeModelRootNode {\n id: undefined;\n nodeData: undefined;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n isLoading?: boolean;\n error?: ErrorInfo;\n}\n\n/** @internal */\nexport interface TreeModelHierarchyNode {\n id: string;\n nodeData: HierarchyNode;\n label: string;\n children: boolean;\n isLoading?: boolean;\n isExpanded?: boolean;\n isSelected?: boolean;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n error?: ErrorInfo;\n}\n\n/** @internal */\nexport interface TreeModel {\n parentChildMap: Map<string | undefined, string[]>;\n idToNode: Map<string, TreeModelHierarchyNode>;\n rootNode: TreeModelRootNode;\n}\n\n/** @internal */\nexport namespace TreeModel {\n export function expandNode(model: TreeModel, nodeId: string, isExpanded: boolean): \"none\" | \"loadChildren\" | \"reloadChildren\" {\n const node = model.idToNode.get(nodeId);\n if (!node) {\n return \"none\";\n }\n\n node.isExpanded = isExpanded;\n if (!isExpanded) {\n return \"none\";\n }\n\n if (node.error?.type === \"ChildrenLoad\") {\n node.isLoading = true;\n // remove subtree if there `ChildrenLoad` error info in order to attempt reloading children\n TreeModel.removeSubTree(model, nodeId);\n return \"reloadChildren\";\n }\n\n if (!node.children) {\n return \"none\";\n }\n\n const children = model.parentChildMap.get(node.id);\n if (!children) {\n node.isLoading = true;\n return \"loadChildren\";\n }\n\n return \"none\";\n }\n\n /** @internal */\n export function addHierarchyPart(model: TreeModel, rootId: string | undefined, hierarchyPart: TreeModel): void {\n removeSubTree(model, rootId);\n model.rootNode.error = hierarchyPart.rootNode.error;\n\n for (const [parentId, children] of hierarchyPart.parentChildMap) {\n model.parentChildMap.set(parentId, children);\n }\n\n for (const [nodeId, node] of hierarchyPart.idToNode) {\n model.idToNode.set(nodeId, node);\n }\n\n const parentNode = rootId !== undefined ? model.idToNode.get(rootId) : model.rootNode;\n /* c8 ignore next 3*/\n if (!parentNode) {\n return;\n }\n parentNode.isLoading = false;\n }\n\n export function removeSubTree(model: TreeModel, parentId: string | undefined): void {\n clearNodeError(model, parentId);\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return;\n }\n model.parentChildMap.delete(parentId);\n\n for (const childId of currentChildren) {\n const childNode = model.idToNode.get(childId);\n if (childNode) {\n removeSubTree(model, childNode.id);\n }\n model.idToNode.delete(childId);\n }\n }\n\n export function setHierarchyLimit(model: TreeModel, nodeId: string | undefined, limit?: number | \"unbounded\"): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.hierarchyLimit = limit;\n });\n }\n\n export function setInstanceFilter(model: TreeModel, nodeId: string | undefined, filter?: GenericInstanceFilter): boolean {\n return updateForReload(model, nodeId, (node) => {\n if (filter && node.id !== undefined) {\n node.isExpanded = true;\n }\n node.instanceFilter = filter;\n });\n }\n\n export function selectNodes(model: TreeModel, nodeIds: Array<string>, changeType: SelectionChangeType) {\n if (changeType === \"replace\") {\n for (const [nodeId, node] of model.idToNode) {\n node.isSelected = !!nodeIds.find((id) => id === nodeId);\n }\n return;\n }\n for (const nodeId of nodeIds) {\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return;\n }\n modelNode.isSelected = changeType === \"add\";\n }\n }\n\n export function isNodeSelected(model: TreeModel, nodeId: string): boolean {\n const currentNode = model.idToNode.get(nodeId);\n return !!currentNode && !!currentNode.isSelected;\n }\n\n export function getNode(model: TreeModel, nodeId: string | undefined): TreeModelHierarchyNode | TreeModelRootNode | undefined {\n if (!nodeId) {\n return model.rootNode;\n }\n return model.idToNode.get(nodeId);\n }\n\n export function setIsLoading(model: TreeModel, nodeId: string | undefined, isLoading: boolean) {\n if (nodeId === undefined) {\n model.rootNode.isLoading = isLoading;\n return;\n }\n const modelNode = model.idToNode.get(nodeId);\n /* c8 ignore next 3*/\n if (!modelNode) {\n return;\n }\n modelNode.isLoading = isLoading;\n }\n}\n\nfunction updateForReload(model: TreeModel, nodeId: string | undefined, update: (node: TreeModelHierarchyNode | TreeModelRootNode) => void) {\n TreeModel.removeSubTree(model, nodeId);\n if (nodeId === undefined) {\n update(model.rootNode);\n model.rootNode.isLoading = true;\n return true;\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return false;\n }\n\n update(modelNode);\n if (modelNode.isExpanded) {\n modelNode.isLoading = true;\n return true;\n }\n return false;\n}\n\nfunction clearNodeError(model: TreeModel, parentId: string | undefined) {\n if (!parentId) {\n return (model.rootNode.error = undefined);\n }\n const node = model.idToNode.get(parentId);\n if (!node) {\n return;\n }\n node.error = undefined;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TreeModel.js","names":["GenericInstanceFilter","HierarchyNode","ErrorInfo","SelectionChangeType","TreeModelRootNode","id","nodeData","hierarchyLimit","instanceFilter","isLoading","error","TreeModelHierarchyNode","label","children","isExpanded","isSelected","TreeModel","parentChildMap","Map","idToNode","rootNode","expandNode","model","nodeId","node","get","type","removeSubTree","addHierarchyPart","rootId","hierarchyPart","parentId","set","parentNode","undefined","clearNodeError","currentChildren","delete","childId","childNode","setHierarchyLimit","limit","updateForReload","setInstanceFilter","filter","selectNodes","nodeIds","Array","changeType","find","modelNode","isNodeSelected","currentNode","getNode","setIsLoading","update"],"sources":["../../../src/presentation-hierarchies-react/internal/TreeModel.ts"],"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 type { GenericInstanceFilter, HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport type { ErrorInfo } from \"../TreeNode.js\";\nimport type { SelectionChangeType } from \"../UseSelectionHandler.js\";\n\n/** @internal */\nexport interface TreeModelRootNode {\n id: undefined;\n nodeData: undefined;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n isLoading?: boolean;\n error?: ErrorInfo;\n}\n\n/** @internal */\nexport interface TreeModelHierarchyNode {\n id: string;\n nodeData: HierarchyNode;\n label: string;\n children: boolean;\n isLoading?: boolean;\n isExpanded?: boolean;\n isSelected?: boolean;\n hierarchyLimit?: number | \"unbounded\";\n instanceFilter?: GenericInstanceFilter;\n error?: ErrorInfo;\n}\n\n/** @internal */\nexport interface TreeModel {\n parentChildMap: Map<string | undefined, string[]>;\n idToNode: Map<string, TreeModelHierarchyNode>;\n rootNode: TreeModelRootNode;\n}\n\n/** @internal */\nexport namespace TreeModel {\n export function expandNode(model: TreeModel, nodeId: string, isExpanded: boolean): \"none\" | \"loadChildren\" | \"reloadChildren\" {\n const node = model.idToNode.get(nodeId);\n if (!node) {\n return \"none\";\n }\n\n node.isExpanded = isExpanded;\n if (!isExpanded) {\n return \"none\";\n }\n\n if (node.error?.type === \"ChildrenLoad\") {\n node.isLoading = true;\n // remove subtree if there `ChildrenLoad` error info in order to attempt reloading children\n TreeModel.removeSubTree(model, nodeId);\n return \"reloadChildren\";\n }\n\n if (!node.children) {\n return \"none\";\n }\n\n const children = model.parentChildMap.get(node.id);\n if (!children) {\n node.isLoading = true;\n return \"loadChildren\";\n }\n\n return \"none\";\n }\n\n /** @internal */\n export function addHierarchyPart(model: TreeModel, rootId: string | undefined, hierarchyPart: TreeModel): void {\n removeSubTree(model, rootId);\n model.rootNode.error = hierarchyPart.rootNode.error;\n\n for (const [parentId, children] of hierarchyPart.parentChildMap) {\n model.parentChildMap.set(parentId, children);\n }\n\n for (const [nodeId, node] of hierarchyPart.idToNode) {\n model.idToNode.set(nodeId, node);\n }\n\n const parentNode = rootId !== undefined ? model.idToNode.get(rootId) : model.rootNode;\n /* c8 ignore next 3*/\n if (!parentNode) {\n return;\n }\n parentNode.isLoading = false;\n }\n\n export function removeSubTree(model: TreeModel, parentId: string | undefined): void {\n clearNodeError(model, parentId);\n const currentChildren = model.parentChildMap.get(parentId);\n if (!currentChildren) {\n return;\n }\n model.parentChildMap.delete(parentId);\n\n for (const childId of currentChildren) {\n const childNode = model.idToNode.get(childId);\n if (childNode) {\n removeSubTree(model, childNode.id);\n }\n model.idToNode.delete(childId);\n }\n }\n\n export function setHierarchyLimit(model: TreeModel, nodeId: string | undefined, limit?: number | \"unbounded\"): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.hierarchyLimit = limit;\n });\n }\n\n export function setInstanceFilter(model: TreeModel, nodeId: string | undefined, filter?: GenericInstanceFilter): boolean {\n return updateForReload(model, nodeId, (node) => {\n if (filter && node.id !== undefined) {\n node.isExpanded = true;\n }\n node.instanceFilter = filter;\n });\n }\n\n export function selectNodes(model: TreeModel, nodeIds: Array<string>, changeType: SelectionChangeType) {\n if (changeType === \"replace\") {\n for (const [nodeId, node] of model.idToNode) {\n node.isSelected = !!nodeIds.find((id) => id === nodeId);\n }\n return;\n }\n for (const nodeId of nodeIds) {\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return;\n }\n modelNode.isSelected = changeType === \"add\";\n }\n }\n\n export function isNodeSelected(model: TreeModel, nodeId: string): boolean {\n const currentNode = model.idToNode.get(nodeId);\n return !!currentNode && !!currentNode.isSelected;\n }\n\n export function getNode(model: TreeModel, nodeId: string | undefined): TreeModelHierarchyNode | TreeModelRootNode | undefined {\n if (!nodeId) {\n return model.rootNode;\n }\n return model.idToNode.get(nodeId);\n }\n\n export function setIsLoading(model: TreeModel, nodeId: string | undefined, isLoading: boolean) {\n if (nodeId === undefined) {\n model.rootNode.isLoading = isLoading;\n return;\n }\n const modelNode = model.idToNode.get(nodeId);\n /* c8 ignore next 3*/\n if (!modelNode) {\n return;\n }\n modelNode.isLoading = isLoading;\n }\n}\n\nfunction updateForReload(model: TreeModel, nodeId: string | undefined, update: (node: TreeModelHierarchyNode | TreeModelRootNode) => void) {\n TreeModel.removeSubTree(model, nodeId);\n if (nodeId === undefined) {\n update(model.rootNode);\n model.rootNode.isLoading = true;\n return true;\n }\n\n const modelNode = model.idToNode.get(nodeId);\n if (!modelNode) {\n return false;\n }\n\n update(modelNode);\n if (modelNode.isExpanded) {\n modelNode.isLoading = true;\n return true;\n }\n return false;\n}\n\nfunction clearNodeError(model: TreeModel, parentId: string | undefined) {\n if (!parentId) {\n return (model.rootNode.error = undefined);\n }\n const node = model.idToNode.get(parentId);\n if (!node) {\n return;\n }\n node.error = undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseUnifiedSelection.d.ts","names":[],"sources":["../../../src/presentation-hierarchies-react/internal/UseUnifiedSelection.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"UseUnifiedSelection.d.ts","names":[],"sources":["../../../src/presentation-hierarchies-react/internal/UseUnifiedSelection.ts"],"mappings":";;;;;UAuBiB,4BAAA;EAoByG;;;EAhBxH,UAAA;EAAA;;;;;;;;;;;;;;EAgBA,8BAAA,IAAkC,IAAA,EAAM,wBAAA;IAA6B,GAAA,EAAK,cAAA;EAAA,GAAkB,eAAA,aAA4B,UAAA;;;;EAKxH,gBAAA,EAAkB,gBAAA;AAAA"}
|
|
@@ -3,7 +3,6 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
4
4
|
import { assert } from "@itwin/core-bentley";
|
|
5
5
|
import { Selectables } from "@itwin/unified-selection";
|
|
6
|
-
|
|
7
6
|
//#region src/presentation-hierarchies-react/internal/UseUnifiedSelection.ts
|
|
8
7
|
/** @internal */
|
|
9
8
|
function useUnifiedTreeSelection(t0) {
|
|
@@ -136,7 +135,7 @@ function groupIModelInstanceKeys(instanceKeys) {
|
|
|
136
135
|
return imodelSelectables;
|
|
137
136
|
}, /* @__PURE__ */ new Map());
|
|
138
137
|
}
|
|
139
|
-
|
|
140
138
|
//#endregion
|
|
141
139
|
export { useUnifiedTreeSelection };
|
|
140
|
+
|
|
142
141
|
//# sourceMappingURL=UseUnifiedSelection.js.map
|