@itwin/presentation-hierarchies-react 2.0.0-alpha.60 → 2.0.0-alpha.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/lib/presentation-hierarchies-react/FlatTreeNode.d.ts +1 -1
- package/lib/presentation-hierarchies-react/FlatTreeNode.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/FlatTreeNode.js +11 -8
- package/lib/presentation-hierarchies-react/FlatTreeNode.js.map +1 -1
- package/lib/presentation-hierarchies-react/TreeNode.d.ts +2 -2
- package/lib/presentation-hierarchies-react/TreeNode.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/UseTree.d.ts +4 -4
- package/lib/presentation-hierarchies-react/UseTree.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/UseTree.js +11 -10
- package/lib/presentation-hierarchies-react/UseTree.js.map +1 -1
- package/lib/presentation-hierarchies-react/internal/TreeModel.js +2 -7
- package/lib/presentation-hierarchies-react/internal/TreeModel.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.d.ts +8 -6
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.js +123 -116
- package/lib/presentation-hierarchies-react/stratakit/ErrorItemRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.d.ts +1 -7
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.d.ts.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/RootErrorRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeErrorRenderer.d.ts +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js +49 -35
- package/lib/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js.map +1 -1
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js +14 -8
- package/lib/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @itwin/presentation-hierarchies-react
|
|
2
2
|
|
|
3
|
+
## 2.0.0-alpha.61
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1267](https://github.com/iTwin/presentation/pull/1267): `TreeNode` now supports multiple errors via `errors: ErrorInfo[]`, allowing both internal errors and custom errors provided through `getTreeNodeErrors` to be combined and displayed.
|
|
8
|
+
|
|
9
|
+
**Breaking changes:**
|
|
10
|
+
|
|
11
|
+
- `TreeNode.error?: ErrorInfo` replaced by `TreeNode.errors: ErrorInfo[]`.
|
|
12
|
+
- `UseTreeProps.getTreeNodeError` renamed to `getTreeNodeErrors` and now returns `ErrorInfo[]` instead of `ErrorInfo | undefined`.
|
|
13
|
+
- `ErrorItemRendererProps` now provides `treeNode` without `errors` and `error` instead of `errorNode`.
|
|
14
|
+
- `TreeErrorRenderer`'s `renderError` callback is now called once per error (instead of once per node), receiving the updated `ErrorItemRendererProps`.
|
|
15
|
+
- `scrollToNode` callback in `ErrorItemRendererProps` now receives `Omit<TreeNode, "errors">` instead of `TreeNode`.
|
|
16
|
+
|
|
3
17
|
## 2.0.0-alpha.60
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
|
@@ -43,7 +43,7 @@ declare function useFlatTreeItems(rootNodes: TreeNode[]): FlatTreeItem[];
|
|
|
43
43
|
*
|
|
44
44
|
* @alpha
|
|
45
45
|
*/
|
|
46
|
-
declare function useErrorNodes(rootNodes: TreeNode[]):
|
|
46
|
+
declare function useErrorNodes(rootNodes: TreeNode[]): TreeNode[];
|
|
47
47
|
//#endregion
|
|
48
48
|
export { FlatTreeItem, useErrorNodes, useFlatTreeItems };
|
|
49
49
|
//# sourceMappingURL=FlatTreeNode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlatTreeNode.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/FlatTreeNode.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"FlatTreeNode.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/FlatTreeNode.ts"],"mappings":";;;;;AAOyD;;;UAO/C,mBAAA;EACR,EAAA;EACA,KAAA;EACA,WAAA;AAAA;;AAQF;;;;UAAiB,gBAAA;EACf,EAAA;EACA,KAAA;EACA,SAAA;EACA,UAAA;EACA,IAAA,EAAM,QAAA;AAAA;;AASR;;;;;KAAY,YAAA,GAAe,gBAAA,GAAmB,mBAAA;;;;;;;AAkD9C;iBApCgB,gBAAA,CAAiB,SAAA,EAAW,QAAA,KAAU,YAAA;;;;;;iBAoCtC,aAAA,CAAc,SAAA,EAAW,QAAA,KAAa,QAAA"}
|
|
@@ -32,7 +32,7 @@ function getFlatItems(nodes, level) {
|
|
|
32
32
|
posInLevel: index + 1
|
|
33
33
|
});
|
|
34
34
|
if (!node.isExpanded) return;
|
|
35
|
-
if (node.
|
|
35
|
+
if (node.errors.some(isErrorBlockingExpansion)) return;
|
|
36
36
|
if (node.children !== true) {
|
|
37
37
|
const childNodes = getFlatItems(node.children, level + 1);
|
|
38
38
|
flatItems.push(...childNodes);
|
|
@@ -62,11 +62,11 @@ function useErrorNodes(rootNodes) {
|
|
|
62
62
|
return t0;
|
|
63
63
|
}
|
|
64
64
|
function _temp(rootNode) {
|
|
65
|
-
const
|
|
66
|
-
if (rootNode.children === true) return
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
return
|
|
65
|
+
const errorNodes = isErrorNode(rootNode) ? [rootNode] : [];
|
|
66
|
+
if (rootNode.children === true) return errorNodes;
|
|
67
|
+
if (errorNodes.length === 1 && errorNodes[0].errors.some(isErrorBlockingExpansion)) return errorNodes;
|
|
68
|
+
errorNodes.push(...getErrorNodes(rootNode));
|
|
69
|
+
return errorNodes;
|
|
70
70
|
}
|
|
71
71
|
function getErrorNodes(parent) {
|
|
72
72
|
const errorList = [];
|
|
@@ -74,7 +74,7 @@ function getErrorNodes(parent) {
|
|
|
74
74
|
parent.children.forEach((node) => {
|
|
75
75
|
if (isErrorNode(node)) {
|
|
76
76
|
errorList.push(node);
|
|
77
|
-
if (node.
|
|
77
|
+
if (node.errors.some(isErrorBlockingExpansion)) return;
|
|
78
78
|
}
|
|
79
79
|
if (node.children !== true) {
|
|
80
80
|
const childErrorList = getErrorNodes(node);
|
|
@@ -85,7 +85,10 @@ function getErrorNodes(parent) {
|
|
|
85
85
|
return errorList;
|
|
86
86
|
}
|
|
87
87
|
function isErrorNode(node) {
|
|
88
|
-
return node.
|
|
88
|
+
return node.errors.length > 0;
|
|
89
|
+
}
|
|
90
|
+
function isErrorBlockingExpansion(error) {
|
|
91
|
+
return error.type !== "Unknown" || !error.isNodeExpandable;
|
|
89
92
|
}
|
|
90
93
|
//#endregion
|
|
91
94
|
export { isPlaceholderItem, useErrorNodes, useFlatTreeItems };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlatTreeNode.js","names":["useMemo","TreeNode","FlatPlaceholderItem","id","level","placeholder","FlatTreeNodeItem","levelSize","posInLevel","node","FlatTreeItem","isPlaceholderItem","item","useFlatTreeItems","rootNodes","$","_c","t0","getFlatItems","nodes","flatItems","forEach","index","push","length","isExpanded","
|
|
1
|
+
{"version":3,"file":"FlatTreeNode.js","names":["useMemo","ErrorInfo","TreeNode","FlatPlaceholderItem","id","level","placeholder","FlatTreeNodeItem","levelSize","posInLevel","node","FlatTreeItem","isPlaceholderItem","item","useFlatTreeItems","rootNodes","$","_c","t0","getFlatItems","nodes","flatItems","forEach","index","push","length","isExpanded","errors","some","isErrorBlockingExpansion","children","childNodes","useErrorNodes","flatMap","_temp","rootNode","errorNodes","isErrorNode","getErrorNodes","parent","errorList","childErrorList","error","type","isNodeExpandable"],"sources":["../../src/presentation-hierarchies-react/FlatTreeNode.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 { useMemo } from \"react\";\n\nimport type { ErrorInfo, TreeNode } from \"./TreeNode.js\";\n\n/**\n * Placeholder item that is added to hierarchy as a child for a parent item while its child items are loading.\n *\n * @alpha\n */\ninterface FlatPlaceholderItem {\n id: string;\n level: number;\n placeholder: true;\n}\n\n/**\n * An item containing `TreeNode` node with properties needed for a flat tree structure.\n *\n * @alpha\n */\nexport interface FlatTreeNodeItem {\n id: string;\n level: number;\n levelSize: number;\n posInLevel: number;\n node: TreeNode;\n}\n\n/**\n * An Item describing single tree item position and its content inside tree.\n * Returned by `useFlatTreeNodeList` hook.\n *\n * @alpha\n */\nexport type FlatTreeItem = FlatTreeNodeItem | FlatPlaceholderItem;\n\n/** @alpha */\nexport function isPlaceholderItem(item: FlatTreeItem): item is FlatPlaceholderItem {\n return \"placeholder\" in item;\n}\n\n/**\n * Used to get a list of `FlatTreeItem` objects for the given list of `TreeNode` objects that represent\n * a hierarchical structure. The resulting items can be used to render the hierarchy in a flat manner, e.g. using a\n * virtualized list.\n *\n * @alpha\n */\nexport function useFlatTreeItems(rootNodes: TreeNode[]) {\n return useMemo(() => getFlatItems(rootNodes, 1), [rootNodes]);\n}\n\nfunction getFlatItems(nodes: TreeNode[], level: number) {\n const flatItems: FlatTreeItem[] = [];\n nodes.forEach((node, index) => {\n flatItems.push({ node, id: node.id, level, levelSize: nodes.length, posInLevel: index + 1 });\n if (!node.isExpanded) {\n return;\n }\n\n if (node.errors.some(isErrorBlockingExpansion)) {\n return;\n }\n\n if (node.children !== true) {\n const childNodes = getFlatItems(node.children, level + 1);\n flatItems.push(...childNodes);\n return;\n }\n\n flatItems.push({\n id: `${node.id}-children-placeholder`,\n level: level + 1,\n placeholder: true,\n } satisfies FlatPlaceholderItem);\n });\n return flatItems;\n}\n\n/**\n * Finds and returns all nodes containing errors in a given hierarchy.\n *\n * @alpha\n */\nexport function useErrorNodes(rootNodes: TreeNode[]): TreeNode[] {\n return useMemo(\n () =>\n rootNodes.flatMap((rootNode) => {\n const errorNodes = isErrorNode(rootNode) ? [rootNode] : [];\n if (rootNode.children === true) {\n return errorNodes;\n }\n\n if (errorNodes.length === 1 && errorNodes[0].errors.some(isErrorBlockingExpansion)) {\n return errorNodes;\n }\n errorNodes.push(...getErrorNodes(rootNode));\n return errorNodes;\n }),\n [rootNodes],\n );\n}\n\nfunction getErrorNodes(parent: TreeNode) {\n const errorList: TreeNode[] = [];\n\n if (parent.children === true) {\n return [];\n }\n\n parent.children.forEach((node) => {\n if (isErrorNode(node)) {\n errorList.push(node);\n if (node.errors.some(isErrorBlockingExpansion)) {\n return;\n }\n }\n\n if (node.children !== true) {\n const childErrorList = getErrorNodes(node);\n errorList.push(...childErrorList);\n return;\n }\n });\n return errorList;\n}\n\nfunction isErrorNode(node: TreeNode): boolean {\n return node.errors.length > 0;\n}\n\nfunction isErrorBlockingExpansion(error: ErrorInfo): boolean {\n return error.type !== \"Unknown\" || !error.isNodeExpandable;\n}\n"],"mappings":";;;AA0CA,SAAgBY,kBAAkBC,MAAiD;AACjF,QAAO,iBAAiBA;;;;;;;;;AAU1B,SAAOC,iBAAAC,WAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAC;AAAA,KAAAF,EAAA,OAAAD,WAAA;AACgBG,OAAAC,aAAaJ,WAAW,EAAE;AAAAC,IAAA,KAAAD;AAAAC,IAAA,KAAAE;OAAAA,MAAAF,EAAA;AAAA,QAA1BE;;AAGvB,SAASC,aAAaC,OAAmBf,OAAe;CACtD,MAAMgB,YAA4B,EAAE;AACpCD,OAAME,SAASZ,MAAMa,UAAU;AAC7BF,YAAUG,KAAK;GAAEd;GAAMN,IAAIM,KAAKN;GAAIC;GAAOG,WAAWY,MAAMK;GAAQhB,YAAYc,QAAQ;GAAG,CAAC;AAC5F,MAAI,CAACb,KAAKgB,WACR;AAGF,MAAIhB,KAAKiB,OAAOC,KAAKC,yBAAyB,CAC5C;AAGF,MAAInB,KAAKoB,aAAa,MAAM;GAC1B,MAAMC,aAAaZ,aAAaT,KAAKoB,UAAUzB,QAAQ,EAAE;AACzDgB,aAAUG,KAAK,GAAGO,WAAW;AAC7B;;AAGFV,YAAUG,KAAK;GACbpB,IAAI,GAAGM,KAAKN,GAAE;GACdC,OAAOA,QAAQ;GACfC,aAAa;GACd,CAA+B;GAChC;AACF,QAAOe;;;;;;;AAQT,SAAOW,cAAAjB,WAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAC;AAAA,KAAAF,EAAA,OAAAD,WAAA;AAGDG,OAAAH,UAASkB,QAASC,MAWhB;AAAAlB,IAAA,KAAAD;AAAAC,IAAA,KAAAE;OAAAA,MAAAF,EAAA;AAAA,QAXFE;;AAHC,SAAAgB,MAAAC,UAAA;CAIC,MAAAC,aAAmBC,YAAYF,SAA2B,GAAvC,CAAyBA,SAAc,GAAvC,EAAuC;AAC1D,KAAIA,SAAQL,aAAc,KAAI,QACrBM;AAGT,KAAIA,WAAUX,WAAY,KAAKW,WAAU,GAAGT,OAAOC,KAAMC,yBAAyB,CAAA,QACzEO;AAETA,YAAUZ,KAAK,GAAIc,cAAcH,SAAS,CAAC;AAAA,QACpCC;;AAMf,SAASE,cAAcC,QAAkB;CACvC,MAAMC,YAAwB,EAAE;AAEhC,KAAID,OAAOT,aAAa,KACtB,QAAO,EAAE;AAGXS,QAAOT,SAASR,SAASZ,SAAS;AAChC,MAAI2B,YAAY3B,KAAK,EAAE;AACrB8B,aAAUhB,KAAKd,KAAK;AACpB,OAAIA,KAAKiB,OAAOC,KAAKC,yBAAyB,CAC5C;;AAIJ,MAAInB,KAAKoB,aAAa,MAAM;GAC1B,MAAMW,iBAAiBH,cAAc5B,KAAK;AAC1C8B,aAAUhB,KAAK,GAAGiB,eAAe;AACjC;;GAEF;AACF,QAAOD;;AAGT,SAASH,YAAY3B,MAAyB;AAC5C,QAAOA,KAAKiB,OAAOF,SAAS;;AAG9B,SAASI,yBAAyBa,OAA2B;AAC3D,QAAOA,MAAMC,SAAS,aAAa,CAACD,MAAME"}
|
|
@@ -15,8 +15,8 @@ interface TreeNode {
|
|
|
15
15
|
isFiltered: boolean;
|
|
16
16
|
/** UI-agnostic source of this node object. */
|
|
17
17
|
nodeData: HierarchyNode;
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/** Errors associated with this tree node. */
|
|
19
|
+
errors: ErrorInfo[];
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* A type of `ErrorInfo` that is returned,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeNode.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/TreeNode.ts"],"mappings":";;;;;AAWA;;UAAiB,QAAA;EACf,EAAA;EACA,KAAA;EACA,QAAA,SAAiB,KAAA,CAAM,QAAA;EACvB,UAAA;EACA,SAAA;EACA,YAAA;EACA,UAAA;EALA;EAOA,QAAA,EAAU,aAAA;EANO;EAQjB,
|
|
1
|
+
{"version":3,"file":"TreeNode.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/TreeNode.ts"],"mappings":";;;;;AAWA;;UAAiB,QAAA;EACf,EAAA;EACA,KAAA;EACA,QAAA,SAAiB,KAAA,CAAM,QAAA;EACvB,UAAA;EACA,SAAA;EACA,YAAA;EACA,UAAA;EALA;EAOA,QAAA,EAAU,aAAA;EANO;EAQjB,MAAA,EAAQ,SAAA;AAAA;;;;;;;UASO,wBAAA;EACf,EAAA;EACA,IAAA;AAAA;;;;;AAUF;;;UAAiB,0BAAA;EACf,EAAA;EACA,IAAA;EACA,kBAAA;AAAA;;AAUF;;;;;;UAAiB,qBAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;AAAA;;;;;;;;;UAWe,gBAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EAaE;EAXF,gBAAA;EACA,cAAA;AAAA;;;;;;;KASU,SAAA,GACR,gBAAA,GACA,0BAAA,GACA,wBAAA,GACA,qBAAA"}
|
|
@@ -66,11 +66,11 @@ interface UseTreeProps {
|
|
|
66
66
|
type: "timeout" | "unknown";
|
|
67
67
|
error: unknown;
|
|
68
68
|
}) => void;
|
|
69
|
-
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
69
|
+
/**
|
|
70
|
+
* Callback to set custom TreeNode errors.
|
|
71
|
+
* Errors returned from this callback are combined with internal errors when populating `TreeNode.errors`.
|
|
72
72
|
*/
|
|
73
|
-
|
|
73
|
+
getTreeNodeErrors?: (node: HierarchyNode) => ErrorInfo[];
|
|
74
74
|
}
|
|
75
75
|
/** @public */
|
|
76
76
|
type UseTreeResult = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseTree.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/UseTree.ts"],"mappings":";;;;;;;;AAiCA;;;;;;;;;AAoBA;;iBApBgB,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,aAAA;;;;;;;;;;;;;;;;iBAoB9B,uBAAA,CAAA;EACd,UAAA;EACA,gBAAA;EACA,8BAAA;EAAA,GACG;AAAA,GACF,YAAA,GAAe,4BAAA,GAA+B,aAAA;;UAehC,YAAA;EAf6C;EAiB5D,oBAAA,QAA4B,iBAAA;EAFb;EAIf,cAAA;IAAoB;EAAA;IAAiB,WAAA,EAAa,WAAA;EAAA,MAAkB,OAAA,CAAQ,mBAAA;EAAxD;;;;EAKpB,qBAAA,IAAyB,MAAA,sDAA4D,QAAA;
|
|
1
|
+
{"version":3,"file":"UseTree.d.ts","names":[],"sources":["../../src/presentation-hierarchies-react/UseTree.ts"],"mappings":";;;;;;;;AAiCA;;;;;;;;;AAoBA;;iBApBgB,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,aAAA;;;;;;;;;;;;;;;;iBAoB9B,uBAAA,CAAA;EACd,UAAA;EACA,gBAAA;EACA,8BAAA;EAAA,GACG;AAAA,GACF,YAAA,GAAe,4BAAA,GAA+B,aAAA;;UAehC,YAAA;EAf6C;EAiB5D,oBAAA,QAA4B,iBAAA;EAFb;EAIf,cAAA;IAAoB;EAAA;IAAiB,WAAA,EAAa,WAAA;EAAA,MAAkB,OAAA,CAAQ,mBAAA;EAAxD;;;;EAKpB,qBAAA,IAAyB,MAAA,sDAA4D,QAAA;EAa1D;EAX3B,wBAAA,IAA4B,KAAA;IAC1B,QAAA;IACA,MAAA,GAAS,qBAAA;IACT,KAAA;EAAA;EAVF;EAaA,oBAAA,IAAwB,KAAA;IAAS,QAAA;IAAmB,IAAA;IAA6B,KAAA;EAAA;EAbL;;;;EAkB5E,iBAAA,IAAqB,IAAA,EAAM,aAAA,KAAkB,SAAA;AAAA;;KAInC,aAAA;EAZR;;;;EAiBF,WAAA;EAdiF;;;EAkBjF,OAAA,GAAU,MAAA,aAAmB,QAAA;EAbR;;;EAiBrB,YAAA,GAAe,SAAA,EAAW,wBAAA;AAAA,IACxB,aAAA;;;;KAKC,aAAA;EALD;;;;;EAYE,sBAAA,EAAwB,sBAAA;AAAA;EAb5B,8FAiBI,sBAAA;EAjBW;;;;AACC;EAsBZ,iBAAA,GAAoB,iBAAA;AAAA"}
|
|
@@ -117,7 +117,7 @@ function useUnifiedSelectionTree(t0) {
|
|
|
117
117
|
}
|
|
118
118
|
return rest;
|
|
119
119
|
}
|
|
120
|
-
function useTreeInternal({ getHierarchyProvider, getSearchPaths, onPerformanceMeasured, onHierarchyLimitExceeded, onHierarchyLoadError,
|
|
120
|
+
function useTreeInternal({ getHierarchyProvider, getSearchPaths, onPerformanceMeasured, onHierarchyLimitExceeded, onHierarchyLoadError, getTreeNodeErrors }) {
|
|
121
121
|
const [state, setState] = useState({
|
|
122
122
|
model: {
|
|
123
123
|
idToNode: /* @__PURE__ */ new Map(),
|
|
@@ -132,11 +132,11 @@ function useTreeInternal({ getHierarchyProvider, getSearchPaths, onPerformanceMe
|
|
|
132
132
|
const onPerformanceMeasuredRef = useLatest(onPerformanceMeasured);
|
|
133
133
|
const onHierarchyLimitExceededRef = useLatest(onHierarchyLimitExceeded);
|
|
134
134
|
const onHierarchyLoadErrorRef = useLatest(onHierarchyLoadError);
|
|
135
|
-
const
|
|
135
|
+
const getTreeNodeErrorsRef = useLatest(getTreeNodeErrors);
|
|
136
136
|
const [actions] = useState(() => new TreeActions((model) => {
|
|
137
137
|
setState({
|
|
138
138
|
model,
|
|
139
|
-
rootNodes: model.parentChildMap.get(void 0) !== void 0 ? generateTreeStructure(void 0, model,
|
|
139
|
+
rootNodes: model.parentChildMap.get(void 0) !== void 0 ? generateTreeStructure(void 0, model, getTreeNodeErrorsRef.current) : void 0
|
|
140
140
|
});
|
|
141
141
|
}, (actionType, duration) => onPerformanceMeasuredRef.current?.(actionType, duration), (props) => onHierarchyLimitExceededRef.current?.(props), (props_0) => onHierarchyLoadErrorRef.current?.(props_0)));
|
|
142
142
|
const currentFormatter = useRef();
|
|
@@ -194,10 +194,10 @@ function useTreeInternal({ getHierarchyProvider, getSearchPaths, onPerformanceMe
|
|
|
194
194
|
const getNode = useCallback((nodeId_0) => {
|
|
195
195
|
const node = actions.getNode(nodeId_0);
|
|
196
196
|
if (!node || node.id === void 0) return;
|
|
197
|
-
return createTreeNode(node, state.model,
|
|
197
|
+
return createTreeNode(node, state.model, getTreeNodeErrorsRef.current);
|
|
198
198
|
}, [
|
|
199
199
|
actions,
|
|
200
|
-
|
|
200
|
+
getTreeNodeErrorsRef,
|
|
201
201
|
state.model
|
|
202
202
|
]);
|
|
203
203
|
const expandNode = useCallback((nodeId_1, isExpanded) => {
|
|
@@ -267,14 +267,15 @@ function useTreeInternal({ getHierarchyProvider, getSearchPaths, onPerformanceMe
|
|
|
267
267
|
setFormatter
|
|
268
268
|
};
|
|
269
269
|
}
|
|
270
|
-
function generateTreeStructure(parentNodeId, model,
|
|
270
|
+
function generateTreeStructure(parentNodeId, model, getTreeNodeErrors) {
|
|
271
271
|
const currentChildren = model.parentChildMap.get(parentNodeId);
|
|
272
272
|
if (!currentChildren) return;
|
|
273
273
|
return currentChildren.map((childId) => model.idToNode.get(childId)).filter((node) => !!node).map((node) => {
|
|
274
|
-
return createTreeNode(node, model,
|
|
274
|
+
return createTreeNode(node, model, getTreeNodeErrors);
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
-
function createTreeNode(modelNode, model,
|
|
277
|
+
function createTreeNode(modelNode, model, getTreeNodeErrors) {
|
|
278
|
+
const allErrors = [...modelNode.error ? [modelNode.error] : [], ...getTreeNodeErrors?.(modelNode.nodeData) ?? []];
|
|
278
279
|
let children;
|
|
279
280
|
return {
|
|
280
281
|
id: modelNode.id,
|
|
@@ -284,9 +285,9 @@ function createTreeNode(modelNode, model, getTreeNodeError) {
|
|
|
284
285
|
isExpanded: !!modelNode.isExpanded,
|
|
285
286
|
isFilterable: !HierarchyNode.isGroupingNode(modelNode.nodeData) && !!modelNode.nodeData.supportsFiltering && modelNode.children,
|
|
286
287
|
isFiltered: !!modelNode.instanceFilter,
|
|
287
|
-
|
|
288
|
+
errors: allErrors,
|
|
288
289
|
get children() {
|
|
289
|
-
if (!children) children = generateTreeStructure(modelNode.id, model,
|
|
290
|
+
if (!children) children = generateTreeStructure(modelNode.id, model, getTreeNodeErrors);
|
|
290
291
|
return children ? children : modelNode.children === true ? true : [];
|
|
291
292
|
}
|
|
292
293
|
};
|
|
@@ -1 +1 @@
|
|
|
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({\n sourceName,\n selectionStorage,\n getTreeModelNode,\n createSelectableForGenericNode,\n });\n if (rest.rootErrorRendererProps === undefined && rest.treeRendererProps?.rootNodes) {\n return { ...rest, treeRendererProps: { ...rest.treeRendererProps, ...selectionProps } };\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: {\n parentId?: string;\n filter?: GenericInstanceFilter;\n limit?: number | \"unbounded\";\n }) => 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\n ? generateTreeStructure(undefined, model, getTreeNodeErrorRef.current)\n : undefined;\n setState({ model, rootNodes });\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\"]>(\n (nodeId: string) => TreeModel.isNodeSelected(state.model, nodeId),\n [state],\n );\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 { rootErrorRendererProps: { error: state.model.rootNode.error, reloadTree, getHierarchyLevelDetails } };\n }\n return {\n rootErrorRendererProps: undefined,\n treeRendererProps: state.rootNodes\n ? { rootNodes: state.rootNodes, expandNode, selectNodes, isNodeSelected, reloadTree, getHierarchyLevelDetails }\n : undefined,\n };\n }, [\n expandNode,\n getHierarchyLevelDetails,\n isNodeSelected,\n reloadTree,\n selectNodes,\n state.model.rootNode.error,\n state.rootNodes,\n ]);\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(\n modelNode: TreeModelHierarchyNode,\n model: TreeModel,\n getTreeNodeError?: (node: HierarchyNode) => ErrorInfo | undefined,\n): 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:\n !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","getTreeNodeErrors","node","UseTreeResult","isReloading","getNode","nodeId","setFormatter","formatter","RendererProps","TreeState","model","Array","state","setState","idToNode","Map","parentChildMap","rootNode","id","nodeData","onPerformanceMeasuredRef","onHierarchyLimitExceededRef","onHierarchyLoadErrorRef","getTreeNodeErrorsRef","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","allErrors","children","label","isFilterable","supportsFiltering","isFiltered","errors"],"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({\n sourceName,\n selectionStorage,\n getTreeModelNode,\n createSelectableForGenericNode,\n });\n if (rest.rootErrorRendererProps === undefined && rest.treeRendererProps?.rootNodes) {\n return { ...rest, treeRendererProps: { ...rest.treeRendererProps, ...selectionProps } };\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: {\n parentId?: string;\n filter?: GenericInstanceFilter;\n limit?: number | \"unbounded\";\n }) => void;\n /** Action to perform when an error occurs while loading hierarchy. */\n onHierarchyLoadError?: (props: { parentId?: string; type: \"timeout\" | \"unknown\"; error: unknown }) => void;\n /**\n * Callback to set custom TreeNode errors.\n * Errors returned from this callback are combined with internal errors when populating `TreeNode.errors`.\n */\n getTreeNodeErrors?: (node: HierarchyNode) => ErrorInfo[];\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 getTreeNodeErrors,\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 getTreeNodeErrorsRef = useLatest(getTreeNodeErrors);\n\n const [actions] = useState<TreeActions>(\n () =>\n new TreeActions(\n (model) => {\n const rootNodes =\n model.parentChildMap.get(undefined) !== undefined\n ? generateTreeStructure(undefined, model, getTreeNodeErrorsRef.current)\n : undefined;\n setState({ model, rootNodes });\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, getTreeNodeErrorsRef.current);\n },\n [actions, getTreeNodeErrorsRef, 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\"]>(\n (nodeId: string) => TreeModel.isNodeSelected(state.model, nodeId),\n [state],\n );\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 { rootErrorRendererProps: { error: state.model.rootNode.error, reloadTree, getHierarchyLevelDetails } };\n }\n return {\n rootErrorRendererProps: undefined,\n treeRendererProps: state.rootNodes\n ? { rootNodes: state.rootNodes, expandNode, selectNodes, isNodeSelected, reloadTree, getHierarchyLevelDetails }\n : undefined,\n };\n }, [\n expandNode,\n getHierarchyLevelDetails,\n isNodeSelected,\n reloadTree,\n selectNodes,\n state.model.rootNode.error,\n state.rootNodes,\n ]);\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 getTreeNodeErrors?: (node: HierarchyNode) => ErrorInfo[],\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, getTreeNodeErrors);\n });\n}\n\nfunction createTreeNode(\n modelNode: TreeModelHierarchyNode,\n model: TreeModel,\n getTreeNodeErrors?: (node: HierarchyNode) => ErrorInfo[],\n): TreeNode {\n const allErrors = [\n // internal errors\n ...(modelNode.error ? [modelNode.error] : []),\n // external errors\n ...(getTreeNodeErrors?.(modelNode.nodeData) ?? []),\n ];\n\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:\n !HierarchyNode.isGroupingNode(modelNode.nodeData) && !!modelNode.nodeData.supportsFiltering && modelNode.children,\n isFiltered: !!modelNode.instanceFilter,\n errors: allErrors,\n get children() {\n if (!children) {\n children = generateTreeStructure(modelNode.id, model, getTreeNodeErrors);\n }\n return children ? children : modelNode.children === true ? true : [];\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -106,13 +106,8 @@ function updateForReload(model, nodeId, update) {
|
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
108
108
|
function clearNodeError(model, parentId) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
const node = model.idToNode.get(parentId);
|
|
114
|
-
if (!node) return;
|
|
115
|
-
node.error = void 0;
|
|
109
|
+
const node = !parentId ? model.rootNode : model.idToNode.get(parentId);
|
|
110
|
+
if (node) node.error = void 0;
|
|
116
111
|
}
|
|
117
112
|
//#endregion
|
|
118
113
|
export { TreeModel };
|
|
@@ -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(\n model: TreeModel,\n nodeId: string,\n isExpanded: boolean,\n ): \"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(\n model: TreeModel,\n nodeId: string | undefined,\n limit?: number | \"unbounded\",\n ): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.hierarchyLimit = limit;\n });\n }\n\n export function setInstanceFilter(\n model: TreeModel,\n nodeId: string | undefined,\n filter?: GenericInstanceFilter,\n ): 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(\n model: TreeModel,\n nodeId: string | undefined,\n ): 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(\n model: TreeModel,\n nodeId: string | undefined,\n update: (node: TreeModelHierarchyNode | TreeModelRootNode) => void,\n) {\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
|
|
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(\n model: TreeModel,\n nodeId: string,\n isExpanded: boolean,\n ): \"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(\n model: TreeModel,\n nodeId: string | undefined,\n limit?: number | \"unbounded\",\n ): boolean {\n return updateForReload(model, nodeId, (node) => {\n node.hierarchyLimit = limit;\n });\n }\n\n export function setInstanceFilter(\n model: TreeModel,\n nodeId: string | undefined,\n filter?: GenericInstanceFilter,\n ): 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(\n model: TreeModel,\n nodeId: string | undefined,\n ): 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(\n model: TreeModel,\n nodeId: string | undefined,\n update: (node: TreeModelHierarchyNode | TreeModelRootNode) => void,\n) {\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 const node = !parentId ? model.rootNode : model.idToNode.get(parentId);\n if (node) {\n node.error = undefined;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { TreeNode } from "../TreeNode.js";
|
|
1
|
+
import { ErrorInfo, TreeNode } from "../TreeNode.js";
|
|
2
2
|
import { HierarchyLevelDetails, TreeRendererProps } from "../Renderers.js";
|
|
3
|
-
import { useErrorNodes } from "../FlatTreeNode.js";
|
|
4
3
|
import { JSX } from "react";
|
|
5
4
|
|
|
6
5
|
//#region src/presentation-hierarchies-react/stratakit/ErrorItemRenderer.d.ts
|
|
7
6
|
/** @alpha */
|
|
8
7
|
interface ErrorItemRendererProps extends Pick<TreeRendererProps, "getHierarchyLevelDetails"> {
|
|
9
|
-
/**
|
|
10
|
-
|
|
8
|
+
/** The tree node associated with the error. Used for displaying the node label in error messages and for scrolling to the node. */
|
|
9
|
+
treeNode: Omit<TreeNode, "errors">;
|
|
10
|
+
/** The error to render. */
|
|
11
|
+
error: ErrorInfo;
|
|
11
12
|
/** A callback to reload a hierarchy level when an error occurs and `retry` button is clicked. */
|
|
12
13
|
reloadTree: (options: {
|
|
13
14
|
parentNodeId: string | undefined;
|
|
14
15
|
}) => void;
|
|
15
16
|
/** A callback to scroll to the node associated with the error. */
|
|
16
|
-
scrollToNode: (
|
|
17
|
+
scrollToNode: (treeNode: Omit<TreeNode, "errors">) => void;
|
|
17
18
|
/** A callback to initiate filtering of the given hierarchy level. */
|
|
18
19
|
filterHierarchyLevel?: (hierarchyLevelDetails: HierarchyLevelDetails) => void;
|
|
19
20
|
}
|
|
@@ -27,7 +28,8 @@ interface ErrorItemRendererProps extends Pick<TreeRendererProps, "getHierarchyLe
|
|
|
27
28
|
* @alpha
|
|
28
29
|
*/
|
|
29
30
|
declare function ErrorItemRenderer({
|
|
30
|
-
|
|
31
|
+
treeNode,
|
|
32
|
+
error,
|
|
31
33
|
getHierarchyLevelDetails,
|
|
32
34
|
filterHierarchyLevel,
|
|
33
35
|
reloadTree,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorItemRenderer.d.ts","names":[],"sources":["../../../src/presentation-hierarchies-react/stratakit/ErrorItemRenderer.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ErrorItemRenderer.d.ts","names":[],"sources":["../../../src/presentation-hierarchies-react/stratakit/ErrorItemRenderer.tsx"],"mappings":";;;;;;UAeiB,sBAAA,SAA+B,IAAA,CAAK,iBAAA;EAApC;EAEf,QAAA,EAAU,IAAA,CAAK,QAAA;;EAEf,KAAA,EAAO,SAAA;EAFQ;EAIf,UAAA,GAAa,OAAA;IAAW,YAAA;EAAA;EAEC;EAAzB,YAAA,GAAe,QAAA,EAAU,IAAA,CAAK,QAAA;EARgB;EAU9C,oBAAA,IAAwB,qBAAA,EAAuB,qBAAA;AAAA;;;;;;;;;;iBAYjC,iBAAA,CAAA;EACd,QAAA;EACA,KAAA;EACA,wBAAA;EACA,oBAAA;EACA,UAAA;EACA;AAAA,GACC,sBAAA,GAAyB,GAAA,CAAI,OAAA"}
|