@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.
Files changed (110) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +303 -0
  4. package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts +75 -0
  5. package/lib/cjs/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
  6. package/lib/cjs/presentation-hierarchies-react/TreeNode.js +16 -0
  7. package/lib/cjs/presentation-hierarchies-react/TreeNode.js.map +1 -0
  8. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
  9. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
  10. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js +28 -0
  11. package/lib/cjs/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
  12. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
  13. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
  14. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js +102 -0
  15. package/lib/cjs/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
  16. package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts +85 -0
  17. package/lib/cjs/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
  18. package/lib/cjs/presentation-hierarchies-react/UseTree.js +214 -0
  19. package/lib/cjs/presentation-hierarchies-react/UseTree.js.map +1 -0
  20. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
  21. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
  22. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js +236 -0
  23. package/lib/cjs/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
  24. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
  25. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
  26. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js +71 -0
  27. package/lib/cjs/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
  28. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
  29. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
  30. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js +154 -0
  31. package/lib/cjs/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
  32. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
  33. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
  34. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js +96 -0
  35. package/lib/cjs/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
  36. package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
  37. package/lib/cjs/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
  38. package/lib/cjs/presentation-hierarchies-react/internal/Utils.js +45 -0
  39. package/lib/cjs/presentation-hierarchies-react/internal/Utils.js.map +1 -0
  40. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
  41. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
  42. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js +35 -0
  43. package/lib/cjs/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
  44. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
  45. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
  46. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
  47. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +101 -0
  48. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
  49. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
  50. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
  51. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js +83 -0
  52. package/lib/cjs/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
  53. package/lib/cjs/presentation-hierarchies-react.d.ts +10 -0
  54. package/lib/cjs/presentation-hierarchies-react.d.ts.map +1 -0
  55. package/lib/cjs/presentation-hierarchies-react.js +27 -0
  56. package/lib/cjs/presentation-hierarchies-react.js.map +1 -0
  57. package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts +75 -0
  58. package/lib/esm/presentation-hierarchies-react/TreeNode.d.ts.map +1 -0
  59. package/lib/esm/presentation-hierarchies-react/TreeNode.js +12 -0
  60. package/lib/esm/presentation-hierarchies-react/TreeNode.js.map +1 -0
  61. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts +18 -0
  62. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.d.ts.map +1 -0
  63. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js +23 -0
  64. package/lib/esm/presentation-hierarchies-react/UnifiedSelectionContext.js.map +1 -0
  65. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts +33 -0
  66. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.d.ts.map +1 -0
  67. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js +98 -0
  68. package/lib/esm/presentation-hierarchies-react/UseSelectionHandler.js.map +1 -0
  69. package/lib/esm/presentation-hierarchies-react/UseTree.d.ts +85 -0
  70. package/lib/esm/presentation-hierarchies-react/UseTree.d.ts.map +1 -0
  71. package/lib/esm/presentation-hierarchies-react/UseTree.js +209 -0
  72. package/lib/esm/presentation-hierarchies-react/UseTree.js.map +1 -0
  73. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts +27 -0
  74. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.d.ts.map +1 -0
  75. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js +232 -0
  76. package/lib/esm/presentation-hierarchies-react/internal/TreeActions.js.map +1 -0
  77. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts +33 -0
  78. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.d.ts.map +1 -0
  79. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js +67 -0
  80. package/lib/esm/presentation-hierarchies-react/internal/TreeLoader.js.map +1 -0
  81. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts +70 -0
  82. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.d.ts.map +1 -0
  83. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js +149 -0
  84. package/lib/esm/presentation-hierarchies-react/internal/TreeModel.js.map +1 -0
  85. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts +16 -0
  86. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.d.ts.map +1 -0
  87. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js +92 -0
  88. package/lib/esm/presentation-hierarchies-react/internal/UseUnifiedSelection.js.map +1 -0
  89. package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts +8 -0
  90. package/lib/esm/presentation-hierarchies-react/internal/Utils.d.ts.map +1 -0
  91. package/lib/esm/presentation-hierarchies-react/internal/Utils.js +40 -0
  92. package/lib/esm/presentation-hierarchies-react/internal/Utils.js.map +1 -0
  93. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts +57 -0
  94. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.d.ts.map +1 -0
  95. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js +30 -0
  96. package/lib/esm/presentation-hierarchies-react/itwinui/LocalizationContext.js.map +1 -0
  97. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.css +17 -0
  98. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts +27 -0
  99. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.d.ts.map +1 -0
  100. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js +94 -0
  101. package/lib/esm/presentation-hierarchies-react/itwinui/TreeNodeRenderer.js.map +1 -0
  102. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts +55 -0
  103. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.d.ts.map +1 -0
  104. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js +78 -0
  105. package/lib/esm/presentation-hierarchies-react/itwinui/TreeRenderer.js.map +1 -0
  106. package/lib/esm/presentation-hierarchies-react.d.ts +10 -0
  107. package/lib/esm/presentation-hierarchies-react.d.ts.map +1 -0
  108. package/lib/esm/presentation-hierarchies-react.js +13 -0
  109. package/lib/esm/presentation-hierarchies-react.js.map +1 -0
  110. 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