@itwin/presentation-hierarchies-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/LICENSE.md +9 -0
- package/README.md +303 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts +75 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.js +16 -0
- package/lib/cjs/presentation-hierarchies-react/TreeNode.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js +28 -0
- package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js +102 -0
- package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts +85 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.js +214 -0
- package/lib/cjs/presentation-hierarchies-react/UseTree.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js +236 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js +71 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js +154 -0
- package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js +96 -0
- package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js +45 -0
- package/lib/cjs/presentation-hierarchies-react/internal/Utils.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js +35 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +101 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js +83 -0
- package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
- package/lib/cjs/presentation-hierarchies-react.d.ts +10 -0
- package/lib/cjs/presentation-hierarchies-react.d.ts.map +1 -0
- package/lib/cjs/presentation-hierarchies-react.js +27 -0
- package/lib/cjs/presentation-hierarchies-react.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts +75 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.js +12 -0
- package/lib/esm/presentation-hierarchies-react/TreeNode.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js +23 -0
- package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js +98 -0
- package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts +85 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.js +209 -0
- package/lib/esm/presentation-hierarchies-react/UseTree.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js +232 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js +67 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js +149 -0
- package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js +92 -0
- package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js +40 -0
- package/lib/esm/presentation-hierarchies-react/internal/Utils.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js +30 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +94 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js +78 -0
- package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
- package/lib/esm/presentation-hierarchies-react.d.ts +10 -0
- package/lib/esm/presentation-hierarchies-react.d.ts.map +1 -0
- package/lib/esm/presentation-hierarchies-react.js +13 -0
- package/lib/esm/presentation-hierarchies-react.js.map +1 -0
- package/package.json +103 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SelectionChangeType } from "../UseSelectionHandler";
|
|
2
|
+
import { TreeModelNode, TreeModelRootNode } from "./TreeModel";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export interface TreeSelectionOptions {
|
|
5
|
+
isNodeSelected: (nodeId: string) => boolean;
|
|
6
|
+
selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;
|
|
7
|
+
}
|
|
8
|
+
/** @internal */
|
|
9
|
+
export interface UseUnifiedTreeSelectionProps {
|
|
10
|
+
imodelKey: string;
|
|
11
|
+
sourceName: string;
|
|
12
|
+
getNode: (nodeId: string) => TreeModelNode | TreeModelRootNode | undefined;
|
|
13
|
+
}
|
|
14
|
+
/** @internal */
|
|
15
|
+
export declare function useUnifiedTreeSelection({ imodelKey, sourceName, getNode }: UseUnifiedTreeSelectionProps): TreeSelectionOptions;
|
|
16
|
+
//# sourceMappingURL=UseUnifiedSelection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UseUnifiedSelection.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/UseUnifiedSelection.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAA4B,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEzF,gBAAgB;AAChB,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAChF;AAED,gBAAgB;AAChB,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,aAAa,GAAG,iBAAiB,GAAG,SAAS,CAAC;CAC5E;AAED,gBAAgB;AAChB,wBAAgB,uBAAuB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,4BAA4B,GAAG,oBAAoB,CA2B9H"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
7
|
+
import { Selectables } from "@itwin/unified-selection";
|
|
8
|
+
import { useUnifiedSelectionContext } from "../UnifiedSelectionContext";
|
|
9
|
+
import { isTreeModelHierarchyNode } from "./TreeModel";
|
|
10
|
+
/** @internal */
|
|
11
|
+
export function useUnifiedTreeSelection({ imodelKey, sourceName, getNode }) {
|
|
12
|
+
const [options, setOptions] = useState(() => ({
|
|
13
|
+
isNodeSelected: /* istanbul ignore next */ () => false,
|
|
14
|
+
selectNodes: /* istanbul ignore next */ () => { },
|
|
15
|
+
}));
|
|
16
|
+
const selectionStorage = useUnifiedSelectionContext();
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!selectionStorage) {
|
|
19
|
+
setOptions({
|
|
20
|
+
isNodeSelected: () => false,
|
|
21
|
+
selectNodes: () => { },
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
setOptions(createOptions(imodelKey, sourceName, selectionStorage, getNode));
|
|
26
|
+
return selectionStorage.selectionChangeEvent.addListener((args) => {
|
|
27
|
+
if (imodelKey !== args.imodelKey || args.level > 0) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
setOptions(createOptions(imodelKey, sourceName, selectionStorage, getNode));
|
|
31
|
+
});
|
|
32
|
+
}, [selectionStorage, getNode, imodelKey, sourceName]);
|
|
33
|
+
return options;
|
|
34
|
+
}
|
|
35
|
+
function createOptions(key, source, storage, getNode) {
|
|
36
|
+
return {
|
|
37
|
+
isNodeSelected: (nodeId) => {
|
|
38
|
+
const node = getNode(nodeId);
|
|
39
|
+
if (!node || !isTreeModelHierarchyNode(node)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const selectables = storage.getSelection({ imodelKey: key, level: 0 });
|
|
43
|
+
const hierarchyNode = node.nodeData;
|
|
44
|
+
if (HierarchyNode.isInstancesNode(hierarchyNode)) {
|
|
45
|
+
return Selectables.hasAny(selectables, hierarchyNode.key.instanceKeys);
|
|
46
|
+
}
|
|
47
|
+
return Selectables.has(selectables, { identifier: node.id });
|
|
48
|
+
},
|
|
49
|
+
selectNodes: (nodeIds, changeType) => {
|
|
50
|
+
let selectables = [];
|
|
51
|
+
for (const nodeId of nodeIds) {
|
|
52
|
+
const node = getNode(nodeId);
|
|
53
|
+
if (!node || !isTreeModelHierarchyNode(node)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
selectables = [...selectables, ...createSelectables(node.id, node.nodeData)];
|
|
57
|
+
}
|
|
58
|
+
const actionProps = { imodelKey: key, source, selectables, level: 0 };
|
|
59
|
+
switch (changeType) {
|
|
60
|
+
case "add":
|
|
61
|
+
storage.addToSelection(actionProps);
|
|
62
|
+
return;
|
|
63
|
+
case "remove":
|
|
64
|
+
storage.removeFromSelection(actionProps);
|
|
65
|
+
return;
|
|
66
|
+
case "replace":
|
|
67
|
+
storage.replaceSelection(actionProps);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function createSelectables(nodeId, node) {
|
|
74
|
+
if (HierarchyNode.isInstancesNode(node)) {
|
|
75
|
+
return node.key.instanceKeys;
|
|
76
|
+
}
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
identifier: nodeId,
|
|
80
|
+
async *loadInstanceKeys() {
|
|
81
|
+
if (!HierarchyNode.isGroupingNode(node)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const key of node.groupedInstanceKeys) {
|
|
85
|
+
yield key;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
data: node,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=UseUnifiedSelection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UseUnifiedSelection.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/UseUnifiedSelection.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useEffect, useState } from \"react\";\nimport { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport { Selectable, Selectables, SelectionStorage } from \"@itwin/unified-selection\";\nimport { useUnifiedSelectionContext } from \"../UnifiedSelectionContext\";\nimport { SelectionChangeType } from \"../UseSelectionHandler\";\nimport { isTreeModelHierarchyNode, TreeModelNode, TreeModelRootNode } from \"./TreeModel\";\n\n/** @internal */\nexport interface TreeSelectionOptions {\n isNodeSelected: (nodeId: string) => boolean;\n selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => void;\n}\n\n/** @internal */\nexport interface UseUnifiedTreeSelectionProps {\n imodelKey: string;\n sourceName: string;\n getNode: (nodeId: string) => TreeModelNode | TreeModelRootNode | undefined;\n}\n\n/** @internal */\nexport function useUnifiedTreeSelection({ imodelKey, sourceName, getNode }: UseUnifiedTreeSelectionProps): TreeSelectionOptions {\n const [options, setOptions] = useState<TreeSelectionOptions>(() => ({\n isNodeSelected: /* istanbul ignore next */ () => false,\n selectNodes: /* istanbul ignore next */ () => {},\n }));\n\n const selectionStorage = useUnifiedSelectionContext();\n useEffect(() => {\n if (!selectionStorage) {\n setOptions({\n isNodeSelected: () => false,\n selectNodes: () => {},\n });\n return;\n }\n\n setOptions(createOptions(imodelKey, sourceName, selectionStorage, getNode));\n return selectionStorage.selectionChangeEvent.addListener((args) => {\n if (imodelKey !== args.imodelKey || args.level > 0) {\n return;\n }\n\n setOptions(createOptions(imodelKey, sourceName, selectionStorage, getNode));\n });\n }, [selectionStorage, getNode, imodelKey, sourceName]);\n\n return options;\n}\n\nfunction createOptions(\n key: string,\n source: string,\n storage: SelectionStorage,\n getNode: (nodeId: string) => TreeModelNode | TreeModelRootNode | undefined,\n): TreeSelectionOptions {\n return {\n isNodeSelected: (nodeId: string) => {\n const node = getNode(nodeId);\n if (!node || !isTreeModelHierarchyNode(node)) {\n return false;\n }\n\n const selectables = storage.getSelection({ imodelKey: key, level: 0 });\n\n const hierarchyNode = node.nodeData;\n if (HierarchyNode.isInstancesNode(hierarchyNode)) {\n return Selectables.hasAny(selectables, hierarchyNode.key.instanceKeys);\n }\n\n return Selectables.has(selectables, { identifier: node.id });\n },\n\n selectNodes: (nodeIds: Array<string>, changeType: SelectionChangeType) => {\n let selectables: Selectable[] = [];\n\n for (const nodeId of nodeIds) {\n const node = getNode(nodeId);\n if (!node || !isTreeModelHierarchyNode(node)) {\n return;\n }\n selectables = [...selectables, ...createSelectables(node.id, node.nodeData)];\n }\n\n const actionProps = { imodelKey: key, source, selectables, level: 0 };\n\n switch (changeType) {\n case \"add\":\n storage.addToSelection(actionProps);\n return;\n case \"remove\":\n storage.removeFromSelection(actionProps);\n return;\n case \"replace\":\n storage.replaceSelection(actionProps);\n return;\n }\n },\n };\n}\n\nfunction createSelectables(nodeId: string, node: HierarchyNode): Selectable[] {\n if (HierarchyNode.isInstancesNode(node)) {\n return node.key.instanceKeys;\n }\n\n return [\n {\n identifier: nodeId,\n async *loadInstanceKeys() {\n if (!HierarchyNode.isGroupingNode(node)) {\n return;\n }\n\n for (const key of node.groupedInstanceKeys) {\n yield key;\n }\n },\n data: node,\n },\n ];\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export declare function createNodeId(node: Pick<HierarchyNode, "key" | "parentKeys">): string;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare function sameNodes(lhs: HierarchyNode, rhs: HierarchyNode): boolean;
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare const MAX_LIMIT_OVERRIDE = 10000;
|
|
8
|
+
//# sourceMappingURL=Utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAoB,MAAM,iCAAiC,CAAC;AAElF,gBAAgB;AAChB,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,YAAY,CAAC,UAE3E;AAiBD,gBAAgB;AAChB,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAezE;AAED,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,QAAQ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { HierarchyNodeKey } from "@itwin/presentation-hierarchies";
|
|
6
|
+
/** @internal */
|
|
7
|
+
export function createNodeId(node) {
|
|
8
|
+
return [...node.parentKeys.map(serializeNodeKey), serializeNodeKey(node.key)].join(";");
|
|
9
|
+
}
|
|
10
|
+
function serializeNodeKey(key) {
|
|
11
|
+
return HierarchyNodeKey.isCustom(key) ? key : convertObjectValuesToString(key);
|
|
12
|
+
}
|
|
13
|
+
function convertObjectValuesToString(obj) {
|
|
14
|
+
return Object.entries(obj)
|
|
15
|
+
.map(([, value]) => {
|
|
16
|
+
if (typeof value === "object") {
|
|
17
|
+
return convertObjectValuesToString(value);
|
|
18
|
+
}
|
|
19
|
+
return String(value);
|
|
20
|
+
})
|
|
21
|
+
.join(",");
|
|
22
|
+
}
|
|
23
|
+
/** @internal */
|
|
24
|
+
export function sameNodes(lhs, rhs) {
|
|
25
|
+
if (HierarchyNodeKey.compare(lhs.key, rhs.key) !== 0) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (lhs.parentKeys.length !== rhs.parentKeys.length) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
for (let i = lhs.parentKeys.length - 1; i >= 0; --i) {
|
|
32
|
+
if (HierarchyNodeKey.compare(lhs.parentKeys[i], rhs.parentKeys[i]) !== 0) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
/** @internal */
|
|
39
|
+
export const MAX_LIMIT_OVERRIDE = 10000;
|
|
40
|
+
//# sourceMappingURL=Utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/internal/Utils.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAiB,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAElF,gBAAgB;AAChB,MAAM,UAAU,YAAY,CAAC,IAA+C;IAC1E,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAqB;IAC7C,OAAO,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,2BAA2B,CAAC,GAAW;IAC9C,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE;QACjB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,2BAA2B,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,SAAS,CAAC,GAAkB,EAAE,GAAkB;IAC9D,IAAI,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACpD,IAAI,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gBAAgB;AAChB,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { HierarchyNode, HierarchyNodeKey } from \"@itwin/presentation-hierarchies\";\n\n/** @internal */\nexport function createNodeId(node: Pick<HierarchyNode, \"key\" | \"parentKeys\">) {\n return [...node.parentKeys.map(serializeNodeKey), serializeNodeKey(node.key)].join(\";\");\n}\n\nfunction serializeNodeKey(key: HierarchyNodeKey): string {\n return HierarchyNodeKey.isCustom(key) ? key : convertObjectValuesToString(key);\n}\n\nfunction convertObjectValuesToString(obj: object): string {\n return Object.entries(obj)\n .map(([, value]) => {\n if (typeof value === \"object\") {\n return convertObjectValuesToString(value);\n }\n return String(value);\n })\n .join(\",\");\n}\n\n/** @internal */\nexport function sameNodes(lhs: HierarchyNode, rhs: HierarchyNode): boolean {\n if (HierarchyNodeKey.compare(lhs.key, rhs.key) !== 0) {\n return false;\n }\n\n if (lhs.parentKeys.length !== rhs.parentKeys.length) {\n return false;\n }\n\n for (let i = lhs.parentKeys.length - 1; i >= 0; --i) {\n if (HierarchyNodeKey.compare(lhs.parentKeys[i], rhs.parentKeys[i]) !== 0) {\n return false;\n }\n }\n return true;\n}\n\n/** @internal */\nexport const MAX_LIMIT_OVERRIDE = 10000;\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { PropsWithChildren } from "react";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export interface LocalizedStrings {
|
|
4
|
+
/**
|
|
5
|
+
* Message displayed when nodes are loading.
|
|
6
|
+
* Default value: `Loading...`.
|
|
7
|
+
*/
|
|
8
|
+
loading: string;
|
|
9
|
+
/**
|
|
10
|
+
* Title for apply hierarchy filter button.
|
|
11
|
+
* Default value: `Apply filter`.
|
|
12
|
+
*/
|
|
13
|
+
filterHierarchyLevel: string;
|
|
14
|
+
/**
|
|
15
|
+
* Title for clear hierarchy filter button.
|
|
16
|
+
* Default value: `Clear active filter`.
|
|
17
|
+
*/
|
|
18
|
+
clearHierarchyLevelFilter: string;
|
|
19
|
+
/**
|
|
20
|
+
* Message displayed when no nodes matching filter are found.
|
|
21
|
+
* Default value: `No child nodes match current filter`.
|
|
22
|
+
*/
|
|
23
|
+
noFilteredChildren: string;
|
|
24
|
+
/**
|
|
25
|
+
* Message displayed when result limit exceeds hierarchy size limit.
|
|
26
|
+
* Default value: `There are more items than allowed limit of {{limit}}.`.
|
|
27
|
+
*/
|
|
28
|
+
resultLimitExceeded: string;
|
|
29
|
+
/**
|
|
30
|
+
* Message displayed when result limit exceeds hierarchy size limit and hierarchy filtering is enabled.
|
|
31
|
+
* Default value: `Please provide <link>additional filtering</link> - there are more items than allowed limit of {{limit}}.`.
|
|
32
|
+
*/
|
|
33
|
+
resultLimitExceededWithFiltering: string;
|
|
34
|
+
/**
|
|
35
|
+
* Message displayed when hierarchy size limit can be overridden.
|
|
36
|
+
* Default value: `<link>Increase the hierarchy level size limit to {{limit}}.</link>`.
|
|
37
|
+
*/
|
|
38
|
+
increaseHierarchyLimit: string;
|
|
39
|
+
/**
|
|
40
|
+
* Message displayed when hierarchy size limit can be overridden and hierarchy filtering is enabled.
|
|
41
|
+
* Default value: `Or, <link>increase the hierarchy level size limit to {{limit}}.</link>`.
|
|
42
|
+
*/
|
|
43
|
+
increaseHierarchyLimitWithFiltering: string;
|
|
44
|
+
}
|
|
45
|
+
/** @internal */
|
|
46
|
+
export interface LocalizationContext {
|
|
47
|
+
localizedStrings: LocalizedStrings;
|
|
48
|
+
}
|
|
49
|
+
interface LocalizationContextProviderProps {
|
|
50
|
+
localizedStrings?: Partial<LocalizedStrings>;
|
|
51
|
+
}
|
|
52
|
+
/** @beta */
|
|
53
|
+
export declare function LocalizationContextProvider({ localizedStrings, children }: PropsWithChildren<LocalizationContextProviderProps>): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
/** @internal */
|
|
55
|
+
export declare function useLocalizationContext(): LocalizationContext;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=LocalizationContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalizationContext.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/itwinui/LocalizationContext.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAiB,iBAAiB,EAAmC,MAAM,OAAO,CAAC;AAE1F,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,yBAAyB,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gCAAgC,EAAE,MAAM,CAAC;IACzC;;;OAGG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,mCAAmC,EAAE,MAAM,CAAC;CAC7C;AAED,gBAAgB;AAChB,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAeD,UAAU,gCAAgC;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9C;AAED,YAAY;AACZ,wBAAgB,2BAA2B,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,iBAAiB,CAAC,gCAAgC,CAAC,2CAQ9H;AAED,gBAAgB;AAChB,wBAAgB,sBAAsB,wBAErC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
7
|
+
const defaultLocalizedStrings = {
|
|
8
|
+
loading: "Loading...",
|
|
9
|
+
filterHierarchyLevel: "Apply filter",
|
|
10
|
+
clearHierarchyLevelFilter: "Clear active filter",
|
|
11
|
+
noFilteredChildren: "No child nodes match current filter",
|
|
12
|
+
resultLimitExceeded: "There are more items than allowed limit of {{limit}}.",
|
|
13
|
+
resultLimitExceededWithFiltering: "Please provide <link>additional filtering</link> - there are more items than allowed limit of {{limit}}.",
|
|
14
|
+
increaseHierarchyLimit: "<link>Increase the hierarchy level size limit to {{limit}}.</link>",
|
|
15
|
+
increaseHierarchyLimitWithFiltering: "Or, <link>increase the hierarchy level size limit to {{limit}}.</link>",
|
|
16
|
+
};
|
|
17
|
+
const localizationContext = createContext({ localizedStrings: defaultLocalizedStrings });
|
|
18
|
+
/** @beta */
|
|
19
|
+
export function LocalizationContextProvider({ localizedStrings, children }) {
|
|
20
|
+
const [state, setState] = useState({ localizedStrings: { ...defaultLocalizedStrings, ...localizedStrings } });
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
setState({ localizedStrings: { ...defaultLocalizedStrings, ...localizedStrings } });
|
|
23
|
+
}, [localizedStrings]);
|
|
24
|
+
return _jsx(localizationContext.Provider, { value: state, children: children });
|
|
25
|
+
}
|
|
26
|
+
/** @internal */
|
|
27
|
+
export function useLocalizationContext() {
|
|
28
|
+
return useContext(localizationContext);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=LocalizationContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalizationContext.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/itwinui/LocalizationContext.tsx"],"names":[],"mappings":";AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,aAAa,EAAqB,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAmD1F,MAAM,uBAAuB,GAAqB;IAChD,OAAO,EAAE,YAAY;IACrB,oBAAoB,EAAE,cAAc;IACpC,yBAAyB,EAAE,qBAAqB;IAChD,kBAAkB,EAAE,qCAAqC;IACzD,mBAAmB,EAAE,uDAAuD;IAC5E,gCAAgC,EAAE,0GAA0G;IAC5I,sBAAsB,EAAE,oEAAoE;IAC5F,mCAAmC,EAAE,wEAAwE;CAC9G,CAAC;AAEF,MAAM,mBAAmB,GAAG,aAAa,CAAsB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,CAAC,CAAC;AAM9G,YAAY;AACZ,MAAM,UAAU,2BAA2B,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAuD;IAC7H,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,gBAAgB,EAAE,EAAE,GAAG,uBAAuB,EAAE,GAAG,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAE9G,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,EAAE,gBAAgB,EAAE,EAAE,GAAG,uBAAuB,EAAE,GAAG,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvB,OAAO,KAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAgC,CAAC;AAC/F,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,sBAAsB;IACpC,OAAO,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACzC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { createContext, PropsWithChildren, useContext, useEffect, useState } from \"react\";\n\n/** @internal */\nexport interface LocalizedStrings {\n /**\n * Message displayed when nodes are loading.\n * Default value: `Loading...`.\n */\n loading: string;\n /**\n * Title for apply hierarchy filter button.\n * Default value: `Apply filter`.\n */\n filterHierarchyLevel: string;\n /**\n * Title for clear hierarchy filter button.\n * Default value: `Clear active filter`.\n */\n clearHierarchyLevelFilter: string;\n /**\n * Message displayed when no nodes matching filter are found.\n * Default value: `No child nodes match current filter`.\n */\n noFilteredChildren: string;\n /**\n * Message displayed when result limit exceeds hierarchy size limit.\n * Default value: `There are more items than allowed limit of {{limit}}.`.\n */\n resultLimitExceeded: string;\n /**\n * Message displayed when result limit exceeds hierarchy size limit and hierarchy filtering is enabled.\n * Default value: `Please provide <link>additional filtering</link> - there are more items than allowed limit of {{limit}}.`.\n */\n resultLimitExceededWithFiltering: string;\n /**\n * Message displayed when hierarchy size limit can be overridden.\n * Default value: `<link>Increase the hierarchy level size limit to {{limit}}.</link>`.\n */\n increaseHierarchyLimit: string;\n /**\n * Message displayed when hierarchy size limit can be overridden and hierarchy filtering is enabled.\n * Default value: `Or, <link>increase the hierarchy level size limit to {{limit}}.</link>`.\n */\n increaseHierarchyLimitWithFiltering: string;\n}\n\n/** @internal */\nexport interface LocalizationContext {\n localizedStrings: LocalizedStrings;\n}\n\nconst defaultLocalizedStrings: LocalizedStrings = {\n loading: \"Loading...\",\n filterHierarchyLevel: \"Apply filter\",\n clearHierarchyLevelFilter: \"Clear active filter\",\n noFilteredChildren: \"No child nodes match current filter\",\n resultLimitExceeded: \"There are more items than allowed limit of {{limit}}.\",\n resultLimitExceededWithFiltering: \"Please provide <link>additional filtering</link> - there are more items than allowed limit of {{limit}}.\",\n increaseHierarchyLimit: \"<link>Increase the hierarchy level size limit to {{limit}}.</link>\",\n increaseHierarchyLimitWithFiltering: \"Or, <link>increase the hierarchy level size limit to {{limit}}.</link>\",\n};\n\nconst localizationContext = createContext<LocalizationContext>({ localizedStrings: defaultLocalizedStrings });\n\ninterface LocalizationContextProviderProps {\n localizedStrings?: Partial<LocalizedStrings>;\n}\n\n/** @beta */\nexport function LocalizationContextProvider({ localizedStrings, children }: PropsWithChildren<LocalizationContextProviderProps>) {\n const [state, setState] = useState({ localizedStrings: { ...defaultLocalizedStrings, ...localizedStrings } });\n\n useEffect(() => {\n setState({ localizedStrings: { ...defaultLocalizedStrings, ...localizedStrings } });\n }, [localizedStrings]);\n\n return <localizationContext.Provider value={state}>{children}</localizationContext.Provider>;\n}\n\n/** @internal */\nexport function useLocalizationContext() {\n return useContext(localizationContext);\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
|
|
6
|
+
.stateless-tree-node {
|
|
7
|
+
user-select: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.stateless-tree-node .action-buttons {
|
|
11
|
+
visibility: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.stateless-tree-node:hover .action-buttons,
|
|
15
|
+
.stateless-tree-node.filtered .action-buttons {
|
|
16
|
+
visibility: visible;
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import "./TreeNodeRenderer.css";
|
|
2
|
+
import { ComponentPropsWithoutRef, ReactElement } from "react";
|
|
3
|
+
import { TreeNode } from "@itwin/itwinui-react";
|
|
4
|
+
import { PresentationHierarchyNode } from "../TreeNode";
|
|
5
|
+
import { useTree } from "../UseTree";
|
|
6
|
+
import { RenderedTreeNode } from "./TreeRenderer";
|
|
7
|
+
type TreeNodeProps = ComponentPropsWithoutRef<typeof TreeNode>;
|
|
8
|
+
interface TreeNodeRendererOwnProps {
|
|
9
|
+
node: RenderedTreeNode;
|
|
10
|
+
onFilterClick?: (nodeId: string | undefined) => void;
|
|
11
|
+
getIcon?: (node: PresentationHierarchyNode) => ReactElement | undefined;
|
|
12
|
+
getSublabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;
|
|
13
|
+
onNodeClick?: (nodeId: string, isSelected: boolean, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
14
|
+
onNodeKeyDown?: (nodeId: string, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => void;
|
|
15
|
+
actionButtonsClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
type TreeNodeRendererProps = Pick<ReturnType<typeof useTree>, "expandNode"> & Partial<Pick<ReturnType<typeof useTree>, "getHierarchyLevelDetails">> & Omit<TreeNodeProps, "label" | "onExpanded" | "onSelected" | "icon"> & TreeNodeRendererOwnProps;
|
|
18
|
+
/**
|
|
19
|
+
* A component that renders `RenderedTreeNode` using the `TreeNode` component from `@itwin/itwinui-react`.
|
|
20
|
+
*
|
|
21
|
+
* @see `TreeRenderer`
|
|
22
|
+
* @see https://itwinui.bentley.com/docs/tree
|
|
23
|
+
* @beta
|
|
24
|
+
*/
|
|
25
|
+
export declare function TreeNodeRenderer({ node, expandNode, getIcon, getSublabel, onFilterClick, onNodeClick, onNodeKeyDown, isSelected, isDisabled, actionButtonsClassName, getHierarchyLevelDetails, ...nodeProps }: TreeNodeRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=TreeNodeRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeNodeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/itwinui/TreeNodeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE/D,OAAO,EAA+D,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE7G,OAAO,EAA+B,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,KAAK,aAAa,GAAG,wBAAwB,CAAC,OAAO,QAAQ,CAAC,CAAC;AAE/D,UAAU,wBAAwB;IAChC,IAAI,EAAE,gBAAgB,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,YAAY,GAAG,SAAS,CAAC;IACxE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,YAAY,GAAG,SAAS,CAAC;IAC5E,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;IAC9G,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACvG,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,KAAK,qBAAqB,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,EAAE,YAAY,CAAC,GACzE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,EAAE,0BAA0B,CAAC,CAAC,GACrE,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC,GACnE,wBAAwB,CAAC;AAE3B;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,UAAU,EACV,OAAO,EACP,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,UAAU,EACV,UAAU,EACV,sBAAsB,EACtB,wBAAwB,EACxB,GAAG,SAAS,EACb,EAAE,qBAAqB,2CAuFvB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
import "./TreeNodeRenderer.css";
|
|
7
|
+
import cx from "classnames";
|
|
8
|
+
import { SvgFilter, SvgFilterHollow, SvgRemove } from "@itwin/itwinui-icons-react";
|
|
9
|
+
import { Anchor, ButtonGroup, Flex, IconButton, ProgressRadial, Text, TreeNode } from "@itwin/itwinui-react";
|
|
10
|
+
import { MAX_LIMIT_OVERRIDE } from "../internal/Utils";
|
|
11
|
+
import { isPresentationHierarchyNode } from "../TreeNode";
|
|
12
|
+
import { useLocalizationContext } from "./LocalizationContext";
|
|
13
|
+
/**
|
|
14
|
+
* A component that renders `RenderedTreeNode` using the `TreeNode` component from `@itwin/itwinui-react`.
|
|
15
|
+
*
|
|
16
|
+
* @see `TreeRenderer`
|
|
17
|
+
* @see https://itwinui.bentley.com/docs/tree
|
|
18
|
+
* @beta
|
|
19
|
+
*/
|
|
20
|
+
export function TreeNodeRenderer({ node, expandNode, getIcon, getSublabel, onFilterClick, onNodeClick, onNodeKeyDown, isSelected, isDisabled, actionButtonsClassName, getHierarchyLevelDetails, ...nodeProps }) {
|
|
21
|
+
const { localizedStrings } = useLocalizationContext();
|
|
22
|
+
if ("type" in node && node.type === "ChildrenPlaceholder") {
|
|
23
|
+
return _jsx(PlaceholderNode, { ...nodeProps });
|
|
24
|
+
}
|
|
25
|
+
if (isPresentationHierarchyNode(node)) {
|
|
26
|
+
return (
|
|
27
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
28
|
+
_jsx("div", { onClick: (event) => !isDisabled && onNodeClick?.(node.id, !isSelected, event), onKeyDown: (event) => {
|
|
29
|
+
// Ignore if it is called on the element inside, e.g. checkbox or expander
|
|
30
|
+
if (!isDisabled && event.target instanceof HTMLElement && event.target.classList.contains("stateless-tree-node")) {
|
|
31
|
+
onNodeKeyDown?.(node.id, !isSelected, event);
|
|
32
|
+
}
|
|
33
|
+
}, children: _jsx(TreeNode, { ...nodeProps, isSelected: isSelected, isDisabled: isDisabled, className: cx(nodeProps.className, "stateless-tree-node", { filtered: node.isFiltered }), label: node.label, onExpanded: (_, isExpanded) => {
|
|
34
|
+
expandNode(node.id, isExpanded);
|
|
35
|
+
}, icon: getIcon ? getIcon(node) : undefined, sublabel: getSublabel ? getSublabel(node) : undefined, children: _jsxs(ButtonGroup, { className: cx("action-buttons", actionButtonsClassName), children: [getHierarchyLevelDetails && node.isFiltered ? (_jsx(IconButton, { className: "filtering-action-button", styleType: "borderless", size: "small", title: localizedStrings.clearHierarchyLevelFilter, onClick: (e) => {
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
getHierarchyLevelDetails(node.id)?.setInstanceFilter(undefined);
|
|
38
|
+
}, children: _jsx(SvgRemove, {}) })) : null, onFilterClick && node.isFilterable ? (_jsx(IconButton, { className: "filtering-action-button", styleType: "borderless", size: "small", title: localizedStrings.filterHierarchyLevel, onClick: (e) => {
|
|
39
|
+
e.stopPropagation();
|
|
40
|
+
onFilterClick(node.id);
|
|
41
|
+
}, children: node.isFiltered ? _jsx(SvgFilter, {}) : _jsx(SvgFilterHollow, {}) })) : null] }) }) }));
|
|
42
|
+
}
|
|
43
|
+
if (node.type === "ResultSetTooLarge") {
|
|
44
|
+
return (_jsx(ResultSetTooLargeNode, { ...nodeProps, limit: node.resultSetSizeLimit, onOverrideLimit: getHierarchyLevelDetails ? (limit) => getHierarchyLevelDetails(node.parentNodeId)?.setSizeLimit(limit) : undefined, onFilterClick: onFilterClick
|
|
45
|
+
? () => {
|
|
46
|
+
onFilterClick(node.parentNodeId);
|
|
47
|
+
}
|
|
48
|
+
: undefined }));
|
|
49
|
+
}
|
|
50
|
+
if (node.type === "NoFilterMatches") {
|
|
51
|
+
return _jsx(TreeNode, { ...nodeProps, label: localizedStrings.noFilteredChildren, isDisabled: true, onExpanded: /* istanbul ignore next */ () => { } });
|
|
52
|
+
}
|
|
53
|
+
return _jsx(TreeNode, { ...nodeProps, label: node.message, isDisabled: true, onExpanded: /* istanbul ignore next */ () => { } });
|
|
54
|
+
}
|
|
55
|
+
function PlaceholderNode(props) {
|
|
56
|
+
const { localizedStrings } = useLocalizationContext();
|
|
57
|
+
return (_jsx(TreeNode, { ...props, label: localizedStrings.loading, icon: _jsx(ProgressRadial, { size: "x-small", indeterminate: true, title: localizedStrings.loading }), onExpanded: /* istanbul ignore next */ () => { } }));
|
|
58
|
+
}
|
|
59
|
+
function ResultSetTooLargeNode({ onFilterClick, onOverrideLimit, limit, ...props }) {
|
|
60
|
+
return (_jsx(TreeNode, { ...props, className: "stateless-tree-node", label: _jsx(ResultSetTooLargeNodeLabel, { limit: limit, onFilterClick: onFilterClick, onOverrideLimit: onOverrideLimit }), onExpanded: /* istanbul ignore next */ () => { } }));
|
|
61
|
+
}
|
|
62
|
+
function ResultSetTooLargeNodeLabel({ onFilterClick, onOverrideLimit, limit }) {
|
|
63
|
+
const { localizedStrings } = useLocalizationContext();
|
|
64
|
+
const supportsFiltering = !!onFilterClick;
|
|
65
|
+
const supportsLimitOverride = !!onOverrideLimit && limit < MAX_LIMIT_OVERRIDE;
|
|
66
|
+
const limitExceededMessage = createLocalizedMessage(supportsFiltering ? localizedStrings.resultLimitExceededWithFiltering : localizedStrings.resultLimitExceeded, limit, onFilterClick);
|
|
67
|
+
const increaseLimitMessage = supportsLimitOverride
|
|
68
|
+
? createLocalizedMessage(supportsFiltering ? localizedStrings.increaseHierarchyLimitWithFiltering : localizedStrings.increaseHierarchyLimit, MAX_LIMIT_OVERRIDE, () => onOverrideLimit(MAX_LIMIT_OVERRIDE))
|
|
69
|
+
: { title: "", element: null };
|
|
70
|
+
const title = `${limitExceededMessage.title} ${increaseLimitMessage.title}`;
|
|
71
|
+
return (_jsxs(Flex, { flexDirection: "column", gap: "3xs", title: title, alignItems: "start", children: [limitExceededMessage.element, increaseLimitMessage.element] }));
|
|
72
|
+
}
|
|
73
|
+
function createLocalizedMessage(message, limit, onClick) {
|
|
74
|
+
const limitStr = limit.toLocaleString(undefined, { useGrouping: true });
|
|
75
|
+
const messageWithLimit = message.replace("{{limit}}", limitStr);
|
|
76
|
+
const exp = new RegExp("<link>(.*)</link>");
|
|
77
|
+
const match = messageWithLimit.match(exp);
|
|
78
|
+
if (!match) {
|
|
79
|
+
return {
|
|
80
|
+
title: messageWithLimit,
|
|
81
|
+
element: (_jsx(Flex, { flexDirection: "row", gap: "3xs", children: _jsx(Text, { children: messageWithLimit }) })),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const [fullText, innerText] = match;
|
|
85
|
+
const [textBefore, textAfter] = messageWithLimit.split(fullText);
|
|
86
|
+
return {
|
|
87
|
+
title: messageWithLimit.replace(fullText, innerText),
|
|
88
|
+
element: (_jsxs(Flex, { flexDirection: "row", gap: "3xs", children: [textBefore ? _jsx(Text, { children: textBefore }) : null, _jsx(Anchor, { underline: true, onClick: (e) => {
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
onClick?.();
|
|
91
|
+
}, children: innerText }), textAfter ? _jsx(Text, { children: textAfter }) : null] })),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=TreeNodeRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeNodeRenderer.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/itwinui/TreeNodeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport \"./TreeNodeRenderer.css\";\nimport cx from \"classnames\";\nimport { ComponentPropsWithoutRef, ReactElement } from \"react\";\nimport { SvgFilter, SvgFilterHollow, SvgRemove } from \"@itwin/itwinui-icons-react\";\nimport { Anchor, ButtonGroup, Flex, IconButton, ProgressRadial, Text, TreeNode } from \"@itwin/itwinui-react\";\nimport { MAX_LIMIT_OVERRIDE } from \"../internal/Utils\";\nimport { isPresentationHierarchyNode, PresentationHierarchyNode } from \"../TreeNode\";\nimport { useTree } from \"../UseTree\";\nimport { useLocalizationContext } from \"./LocalizationContext\";\nimport { RenderedTreeNode } from \"./TreeRenderer\";\n\ntype TreeNodeProps = ComponentPropsWithoutRef<typeof TreeNode>;\n\ninterface TreeNodeRendererOwnProps {\n node: RenderedTreeNode;\n onFilterClick?: (nodeId: string | undefined) => void;\n getIcon?: (node: PresentationHierarchyNode) => ReactElement | undefined;\n getSublabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;\n onNodeClick?: (nodeId: string, isSelected: boolean, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n onNodeKeyDown?: (nodeId: string, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => void;\n actionButtonsClassName?: string;\n}\n\ntype TreeNodeRendererProps = Pick<ReturnType<typeof useTree>, \"expandNode\"> &\n Partial<Pick<ReturnType<typeof useTree>, \"getHierarchyLevelDetails\">> &\n Omit<TreeNodeProps, \"label\" | \"onExpanded\" | \"onSelected\" | \"icon\"> &\n TreeNodeRendererOwnProps;\n\n/**\n * A component that renders `RenderedTreeNode` using the `TreeNode` component from `@itwin/itwinui-react`.\n *\n * @see `TreeRenderer`\n * @see https://itwinui.bentley.com/docs/tree\n * @beta\n */\nexport function TreeNodeRenderer({\n node,\n expandNode,\n getIcon,\n getSublabel,\n onFilterClick,\n onNodeClick,\n onNodeKeyDown,\n isSelected,\n isDisabled,\n actionButtonsClassName,\n getHierarchyLevelDetails,\n ...nodeProps\n}: TreeNodeRendererProps) {\n const { localizedStrings } = useLocalizationContext();\n if (\"type\" in node && node.type === \"ChildrenPlaceholder\") {\n return <PlaceholderNode {...nodeProps} />;\n }\n\n if (isPresentationHierarchyNode(node)) {\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions\n <div\n onClick={(event) => !isDisabled && onNodeClick?.(node.id, !isSelected, event)}\n onKeyDown={(event) => {\n // Ignore if it is called on the element inside, e.g. checkbox or expander\n if (!isDisabled && event.target instanceof HTMLElement && event.target.classList.contains(\"stateless-tree-node\")) {\n onNodeKeyDown?.(node.id, !isSelected, event);\n }\n }}\n >\n <TreeNode\n {...nodeProps}\n isSelected={isSelected}\n isDisabled={isDisabled}\n className={cx(nodeProps.className, \"stateless-tree-node\", { filtered: node.isFiltered })}\n label={node.label}\n onExpanded={(_, isExpanded) => {\n expandNode(node.id, isExpanded);\n }}\n icon={getIcon ? getIcon(node) : undefined}\n sublabel={getSublabel ? getSublabel(node) : undefined}\n >\n <ButtonGroup className={cx(\"action-buttons\", actionButtonsClassName)}>\n {getHierarchyLevelDetails && node.isFiltered ? (\n <IconButton\n className=\"filtering-action-button\"\n styleType=\"borderless\"\n size=\"small\"\n title={localizedStrings.clearHierarchyLevelFilter}\n onClick={(e) => {\n e.stopPropagation();\n getHierarchyLevelDetails(node.id)?.setInstanceFilter(undefined);\n }}\n >\n <SvgRemove />\n </IconButton>\n ) : null}\n {onFilterClick && node.isFilterable ? (\n <IconButton\n className=\"filtering-action-button\"\n styleType=\"borderless\"\n size=\"small\"\n title={localizedStrings.filterHierarchyLevel}\n onClick={(e) => {\n e.stopPropagation();\n onFilterClick(node.id);\n }}\n >\n {node.isFiltered ? <SvgFilter /> : <SvgFilterHollow />}\n </IconButton>\n ) : null}\n </ButtonGroup>\n </TreeNode>\n </div>\n );\n }\n\n if (node.type === \"ResultSetTooLarge\") {\n return (\n <ResultSetTooLargeNode\n {...nodeProps}\n limit={node.resultSetSizeLimit}\n onOverrideLimit={getHierarchyLevelDetails ? (limit) => getHierarchyLevelDetails(node.parentNodeId)?.setSizeLimit(limit) : undefined}\n onFilterClick={\n onFilterClick\n ? () => {\n onFilterClick(node.parentNodeId);\n }\n : undefined\n }\n />\n );\n }\n\n if (node.type === \"NoFilterMatches\") {\n return <TreeNode {...nodeProps} label={localizedStrings.noFilteredChildren} isDisabled={true} onExpanded={/* istanbul ignore next */ () => {}} />;\n }\n\n return <TreeNode {...nodeProps} label={node.message} isDisabled={true} onExpanded={/* istanbul ignore next */ () => {}} />;\n}\n\nfunction PlaceholderNode(props: Omit<TreeNodeProps, \"onExpanded\" | \"label\">) {\n const { localizedStrings } = useLocalizationContext();\n return (\n <TreeNode\n {...props}\n label={localizedStrings.loading}\n icon={<ProgressRadial size=\"x-small\" indeterminate title={localizedStrings.loading} />}\n onExpanded={/* istanbul ignore next */ () => {}}\n ></TreeNode>\n );\n}\n\nfunction ResultSetTooLargeNode({\n onFilterClick,\n onOverrideLimit,\n limit,\n ...props\n}: Omit<TreeNodeProps, \"onExpanded\" | \"label\"> & ResultSetTooLargeNodeLabelProps) {\n return (\n <TreeNode\n {...props}\n className=\"stateless-tree-node\"\n label={<ResultSetTooLargeNodeLabel limit={limit} onFilterClick={onFilterClick} onOverrideLimit={onOverrideLimit} />}\n onExpanded={/* istanbul ignore next */ () => {}}\n />\n );\n}\n\ninterface ResultSetTooLargeNodeLabelProps {\n limit: number;\n onFilterClick?: () => void;\n onOverrideLimit?: (limit: number) => void;\n}\n\nfunction ResultSetTooLargeNodeLabel({ onFilterClick, onOverrideLimit, limit }: ResultSetTooLargeNodeLabelProps) {\n const { localizedStrings } = useLocalizationContext();\n const supportsFiltering = !!onFilterClick;\n const supportsLimitOverride = !!onOverrideLimit && limit < MAX_LIMIT_OVERRIDE;\n\n const limitExceededMessage = createLocalizedMessage(\n supportsFiltering ? localizedStrings.resultLimitExceededWithFiltering : localizedStrings.resultLimitExceeded,\n limit,\n onFilterClick,\n );\n const increaseLimitMessage = supportsLimitOverride\n ? createLocalizedMessage(\n supportsFiltering ? localizedStrings.increaseHierarchyLimitWithFiltering : localizedStrings.increaseHierarchyLimit,\n MAX_LIMIT_OVERRIDE,\n () => onOverrideLimit(MAX_LIMIT_OVERRIDE),\n )\n : { title: \"\", element: null };\n\n const title = `${limitExceededMessage.title} ${increaseLimitMessage.title}`;\n\n return (\n <Flex flexDirection=\"column\" gap=\"3xs\" title={title} alignItems=\"start\">\n {limitExceededMessage.element}\n {increaseLimitMessage.element}\n </Flex>\n );\n}\n\nfunction createLocalizedMessage(message: string, limit: number, onClick?: () => void) {\n const limitStr = limit.toLocaleString(undefined, { useGrouping: true });\n const messageWithLimit = message.replace(\"{{limit}}\", limitStr);\n const exp = new RegExp(\"<link>(.*)</link>\");\n const match = messageWithLimit.match(exp);\n\n if (!match) {\n return {\n title: messageWithLimit,\n element: (\n <Flex flexDirection=\"row\" gap=\"3xs\">\n <Text>{messageWithLimit}</Text>\n </Flex>\n ),\n };\n }\n\n const [fullText, innerText] = match;\n const [textBefore, textAfter] = messageWithLimit.split(fullText);\n\n return {\n title: messageWithLimit.replace(fullText, innerText),\n element: (\n <Flex flexDirection=\"row\" gap=\"3xs\">\n {textBefore ? <Text>{textBefore}</Text> : null}\n <Anchor\n underline\n onClick={(e) => {\n e.stopPropagation();\n onClick?.();\n }}\n >\n {innerText}\n </Anchor>\n {textAfter ? <Text>{textAfter}</Text> : null}\n </Flex>\n ),\n };\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import { NodeData, Tree } from "@itwin/itwinui-react";
|
|
3
|
+
import { PresentationTreeNode } from "../TreeNode";
|
|
4
|
+
import { SelectionMode } from "../UseSelectionHandler";
|
|
5
|
+
import { useTree } from "../UseTree";
|
|
6
|
+
import { LocalizedStrings } from "./LocalizationContext";
|
|
7
|
+
import { TreeNodeRenderer } from "./TreeNodeRenderer";
|
|
8
|
+
type TreeProps = ComponentPropsWithoutRef<typeof Tree<RenderedTreeNode>>;
|
|
9
|
+
type TreeNodeRendererProps = ComponentPropsWithoutRef<typeof TreeNodeRenderer>;
|
|
10
|
+
interface TreeRendererOwnProps {
|
|
11
|
+
rootNodes: PresentationTreeNode[];
|
|
12
|
+
selectionMode?: SelectionMode;
|
|
13
|
+
localizedStrings?: Partial<LocalizedStrings>;
|
|
14
|
+
}
|
|
15
|
+
type TreeRendererProps = Pick<ReturnType<typeof useTree>, "rootNodes" | "expandNode"> & Partial<Pick<ReturnType<typeof useTree>, "selectNodes" | "isNodeSelected" | "getHierarchyLevelDetails">> & Pick<TreeNodeRendererProps, "onFilterClick" | "getIcon" | "getSublabel"> & TreeRendererOwnProps & Omit<TreeProps, "data" | "nodeRenderer" | "getNode" | "enableVirtualization">;
|
|
16
|
+
/**
|
|
17
|
+
* A component that renders a tree using the `Tree` component from `@itwin/itwinui-react`. The tree nodes
|
|
18
|
+
* are rendered using `TreeNodeRenderer` component from this package.
|
|
19
|
+
*
|
|
20
|
+
* @see https://itwinui.bentley.com/docs/tree
|
|
21
|
+
* @beta
|
|
22
|
+
*/
|
|
23
|
+
export declare function TreeRenderer({ rootNodes, expandNode, selectNodes, isNodeSelected, onFilterClick, getIcon, getSublabel, getHierarchyLevelDetails, selectionMode, localizedStrings, ...treeProps }: TreeRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* A data structure for a tree node that is rendered using the `TreeRenderer` component.
|
|
26
|
+
*
|
|
27
|
+
* In addition to the `PresentationTreeNode` union, this type may have one additional variation - an informational
|
|
28
|
+
* type of node with `ChildrenPlaceholder` type. This type of node is returned as the single child node of a parent
|
|
29
|
+
* while its children are being loaded. This allows the node renderer to show a placeholder under the parent during
|
|
30
|
+
* the process.
|
|
31
|
+
*
|
|
32
|
+
* @beta
|
|
33
|
+
*/
|
|
34
|
+
export type RenderedTreeNode = PresentationTreeNode | {
|
|
35
|
+
id: string;
|
|
36
|
+
parentNodeId: string | undefined;
|
|
37
|
+
type: "ChildrenPlaceholder";
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* An utility function that creates an `@itwin/itwinui-react` `NodeData` object for the `Tree` component from a
|
|
41
|
+
* `RenderedTreeNode` object.
|
|
42
|
+
*
|
|
43
|
+
* Usage example:
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function MyComponent({ rootNodes, nodeRenderer }: MyComponentProps) {
|
|
46
|
+
* const getNode = useCallback<TreeProps["getNode"]>((node) => createRenderedTreeNodeData(node, () => false), []);
|
|
47
|
+
* return <Tree<RenderedTreeNode> data={rootNodes} getNode={getNode} nodeRenderer={nodeRenderer} />;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @beta
|
|
52
|
+
*/
|
|
53
|
+
export declare function createRenderedTreeNodeData(node: RenderedTreeNode, isNodeSelected: (nodeId: string) => boolean): NodeData<RenderedTreeNode>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=TreeRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/itwinui/TreeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAe,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAuB,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAA+B,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,KAAK,SAAS,GAAG,wBAAwB,CAAC,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACzE,KAAK,qBAAqB,GAAG,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/E,UAAU,oBAAoB;IAC5B,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9C;AAED,KAAK,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC,GACnF,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,EAAE,aAAa,GAAG,gBAAgB,GAAG,0BAA0B,CAAC,CAAC,GACxG,IAAI,CAAC,qBAAqB,EAAE,eAAe,GAAG,SAAS,GAAG,aAAa,CAAC,GACxE,oBAAoB,GACpB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,sBAAsB,CAAC,CAAC;AAEhF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,OAAO,EACP,WAAW,EACX,wBAAwB,EACxB,aAAa,EACb,gBAAgB,EAChB,GAAG,SAAS,EACb,EAAE,iBAAiB,2CA+BnB;AAOD;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GACxB,oBAAoB,GACpB;IACE,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,qBAAqB,CAAC;CAC7B,CAAC;AAEN;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CA6B1I"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
import { useCallback } from "react";
|
|
7
|
+
import { Tree } from "@itwin/itwinui-react";
|
|
8
|
+
import { useSelectionHandler } from "../UseSelectionHandler";
|
|
9
|
+
import { LocalizationContextProvider } from "./LocalizationContext";
|
|
10
|
+
import { TreeNodeRenderer } from "./TreeNodeRenderer";
|
|
11
|
+
/**
|
|
12
|
+
* A component that renders a tree using the `Tree` component from `@itwin/itwinui-react`. The tree nodes
|
|
13
|
+
* are rendered using `TreeNodeRenderer` component from this package.
|
|
14
|
+
*
|
|
15
|
+
* @see https://itwinui.bentley.com/docs/tree
|
|
16
|
+
* @beta
|
|
17
|
+
*/
|
|
18
|
+
export function TreeRenderer({ rootNodes, expandNode, selectNodes, isNodeSelected, onFilterClick, getIcon, getSublabel, getHierarchyLevelDetails, selectionMode, localizedStrings, ...treeProps }) {
|
|
19
|
+
const { onNodeClick, onNodeKeyDown } = useSelectionHandler({
|
|
20
|
+
rootNodes,
|
|
21
|
+
selectNodes: selectNodes ?? noopSelectNodes,
|
|
22
|
+
selectionMode: selectionMode ?? "single",
|
|
23
|
+
});
|
|
24
|
+
const nodeRenderer = useCallback((nodeProps) => {
|
|
25
|
+
return (_jsx(TreeNodeRenderer, { ...nodeProps, expandNode: expandNode, getHierarchyLevelDetails: getHierarchyLevelDetails, onFilterClick: onFilterClick, onNodeClick: onNodeClick, onNodeKeyDown: onNodeKeyDown, getIcon: getIcon, getSublabel: getSublabel }));
|
|
26
|
+
}, [expandNode, getHierarchyLevelDetails, onFilterClick, onNodeClick, onNodeKeyDown, getIcon, getSublabel]);
|
|
27
|
+
const getNode = useCallback((node) => createRenderedTreeNodeData(node, isNodeSelected ?? noopIsNodeSelected), [isNodeSelected]);
|
|
28
|
+
return (_jsx(LocalizationContextProvider, { localizedStrings: localizedStrings, children: _jsx(Tree, { ...treeProps, data: rootNodes, nodeRenderer: nodeRenderer, getNode: getNode, enableVirtualization: true }) }));
|
|
29
|
+
}
|
|
30
|
+
function noopSelectNodes() { }
|
|
31
|
+
function noopIsNodeSelected() {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* An utility function that creates an `@itwin/itwinui-react` `NodeData` object for the `Tree` component from a
|
|
36
|
+
* `RenderedTreeNode` object.
|
|
37
|
+
*
|
|
38
|
+
* Usage example:
|
|
39
|
+
* ```tsx
|
|
40
|
+
* function MyComponent({ rootNodes, nodeRenderer }: MyComponentProps) {
|
|
41
|
+
* const getNode = useCallback<TreeProps["getNode"]>((node) => createRenderedTreeNodeData(node, () => false), []);
|
|
42
|
+
* return <Tree<RenderedTreeNode> data={rootNodes} getNode={getNode} nodeRenderer={nodeRenderer} />;
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @beta
|
|
47
|
+
*/
|
|
48
|
+
export function createRenderedTreeNodeData(node, isNodeSelected) {
|
|
49
|
+
if ("type" in node) {
|
|
50
|
+
return {
|
|
51
|
+
nodeId: node.id,
|
|
52
|
+
node,
|
|
53
|
+
hasSubNodes: false,
|
|
54
|
+
isExpanded: false,
|
|
55
|
+
isSelected: false,
|
|
56
|
+
isDisabled: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
nodeId: node.id,
|
|
61
|
+
node,
|
|
62
|
+
hasSubNodes: node.children === true || node.children.length > 0,
|
|
63
|
+
subNodes:
|
|
64
|
+
// returns placeholder node to show as child while children is loading.
|
|
65
|
+
node.children === true
|
|
66
|
+
? [
|
|
67
|
+
{
|
|
68
|
+
id: `Loading-${node.id}`,
|
|
69
|
+
parentNodeId: node.id,
|
|
70
|
+
type: "ChildrenPlaceholder",
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
: node.children,
|
|
74
|
+
isExpanded: node.isExpanded,
|
|
75
|
+
isSelected: isNodeSelected(node.id),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=TreeRenderer.js.map
|