@uipath/apollo-react 4.15.0 → 4.15.1-pr556.f7e5934

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 (134) hide show
  1. package/dist/canvas/components/AddNodePanel/AddNodeManager.cjs +3 -1
  2. package/dist/canvas/components/AddNodePanel/AddNodeManager.d.ts.map +1 -1
  3. package/dist/canvas/components/AddNodePanel/AddNodeManager.js +3 -1
  4. package/dist/canvas/components/AddNodePanel/createAddNodePreview.cjs +9 -3
  5. package/dist/canvas/components/AddNodePanel/createAddNodePreview.d.ts.map +1 -1
  6. package/dist/canvas/components/AddNodePanel/createAddNodePreview.js +9 -3
  7. package/dist/canvas/components/AgentCanvas/agent-flow.manifest.d.ts +2 -1
  8. package/dist/canvas/components/AgentCanvas/agent-flow.manifest.d.ts.map +1 -1
  9. package/dist/canvas/components/BaseNode/BaseNode.cjs +5 -4
  10. package/dist/canvas/components/BaseNode/BaseNode.d.ts.map +1 -1
  11. package/dist/canvas/components/BaseNode/BaseNode.js +4 -3
  12. package/dist/canvas/components/ButtonHandle/ButtonHandle.cjs +222 -13
  13. package/dist/canvas/components/ButtonHandle/ButtonHandle.d.ts +10 -5
  14. package/dist/canvas/components/ButtonHandle/ButtonHandle.d.ts.map +1 -1
  15. package/dist/canvas/components/ButtonHandle/ButtonHandle.js +223 -14
  16. package/dist/canvas/components/ButtonHandle/ButtonHandleStyleUtils.cjs +10 -2
  17. package/dist/canvas/components/ButtonHandle/ButtonHandleStyleUtils.d.ts +2 -0
  18. package/dist/canvas/components/ButtonHandle/ButtonHandleStyleUtils.d.ts.map +1 -1
  19. package/dist/canvas/components/ButtonHandle/ButtonHandleStyleUtils.js +5 -3
  20. package/dist/canvas/components/ButtonHandle/HandleButton.cjs +13 -2
  21. package/dist/canvas/components/ButtonHandle/HandleButton.d.ts +10 -1
  22. package/dist/canvas/components/ButtonHandle/HandleButton.d.ts.map +1 -1
  23. package/dist/canvas/components/ButtonHandle/HandleButton.js +13 -2
  24. package/dist/canvas/components/ButtonHandle/useButtonHandles.cjs +4 -2
  25. package/dist/canvas/components/ButtonHandle/useButtonHandles.d.ts +2 -1
  26. package/dist/canvas/components/ButtonHandle/useButtonHandles.d.ts.map +1 -1
  27. package/dist/canvas/components/ButtonHandle/useButtonHandles.js +4 -2
  28. package/dist/canvas/components/Edges/SequenceEdge.cjs +8 -4
  29. package/dist/canvas/components/Edges/SequenceEdge.js +8 -4
  30. package/dist/canvas/components/HierarchicalCanvas/HierarchicalCanvas.cjs +24 -22
  31. package/dist/canvas/components/HierarchicalCanvas/HierarchicalCanvas.d.ts.map +1 -1
  32. package/dist/canvas/components/HierarchicalCanvas/HierarchicalCanvas.js +25 -23
  33. package/dist/canvas/components/LoopNode/LoopCanvasNode.cjs +75 -0
  34. package/dist/canvas/components/LoopNode/LoopCanvasNode.d.ts +6 -0
  35. package/dist/canvas/components/LoopNode/LoopCanvasNode.d.ts.map +1 -0
  36. package/dist/canvas/components/LoopNode/LoopCanvasNode.js +41 -0
  37. package/dist/canvas/components/LoopNode/LoopNode.cjs +432 -0
  38. package/dist/canvas/components/LoopNode/LoopNode.constants.cjs +73 -0
  39. package/dist/canvas/components/LoopNode/LoopNode.constants.d.ts +11 -0
  40. package/dist/canvas/components/LoopNode/LoopNode.constants.d.ts.map +1 -0
  41. package/dist/canvas/components/LoopNode/LoopNode.constants.js +12 -0
  42. package/dist/canvas/components/LoopNode/LoopNode.d.ts +5 -0
  43. package/dist/canvas/components/LoopNode/LoopNode.d.ts.map +1 -0
  44. package/dist/canvas/components/LoopNode/LoopNode.helpers.cjs +145 -0
  45. package/dist/canvas/components/LoopNode/LoopNode.helpers.d.ts +29 -0
  46. package/dist/canvas/components/LoopNode/LoopNode.helpers.d.ts.map +1 -0
  47. package/dist/canvas/components/LoopNode/LoopNode.helpers.js +99 -0
  48. package/dist/canvas/components/LoopNode/LoopNode.js +398 -0
  49. package/dist/canvas/components/LoopNode/LoopNode.types.cjs +18 -0
  50. package/dist/canvas/components/LoopNode/LoopNode.types.d.ts +22 -0
  51. package/dist/canvas/components/LoopNode/LoopNode.types.d.ts.map +1 -0
  52. package/dist/canvas/components/LoopNode/LoopNode.types.js +0 -0
  53. package/dist/canvas/components/LoopNode/LoopNodePreview.cjs +61 -0
  54. package/dist/canvas/components/LoopNode/LoopNodePreview.d.ts +9 -0
  55. package/dist/canvas/components/LoopNode/LoopNodePreview.d.ts.map +1 -0
  56. package/dist/canvas/components/LoopNode/LoopNodePreview.js +27 -0
  57. package/dist/canvas/components/LoopNode/index.cjs +79 -0
  58. package/dist/canvas/components/LoopNode/index.d.ts +5 -0
  59. package/dist/canvas/components/LoopNode/index.d.ts.map +1 -0
  60. package/dist/canvas/components/LoopNode/index.js +4 -0
  61. package/dist/canvas/components/NodeViewportOverlay.cjs +63 -0
  62. package/dist/canvas/components/NodeViewportOverlay.d.ts +22 -0
  63. package/dist/canvas/components/NodeViewportOverlay.d.ts.map +1 -0
  64. package/dist/canvas/components/NodeViewportOverlay.js +29 -0
  65. package/dist/canvas/components/StageNode/StageNodeHeader.cjs +3 -1
  66. package/dist/canvas/components/StageNode/StageNodeHeader.d.ts.map +1 -1
  67. package/dist/canvas/components/StageNode/StageNodeHeader.js +3 -1
  68. package/dist/canvas/components/Toolbar/EdgeToolbar/EdgeToolbar.cjs +1 -1
  69. package/dist/canvas/components/Toolbar/EdgeToolbar/EdgeToolbar.js +1 -1
  70. package/dist/canvas/components/Toolbar/EdgeToolbar/useEdgeToolbarState.cjs +25 -23
  71. package/dist/canvas/components/Toolbar/EdgeToolbar/useEdgeToolbarState.d.ts.map +1 -1
  72. package/dist/canvas/components/Toolbar/EdgeToolbar/useEdgeToolbarState.js +27 -25
  73. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.cjs +10 -3
  74. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.d.ts +1 -1
  75. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.d.ts.map +1 -1
  76. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.js +10 -3
  77. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.types.d.ts +1 -0
  78. package/dist/canvas/components/Toolbar/NodeToolbar/NodeToolbar.types.d.ts.map +1 -1
  79. package/dist/canvas/components/index.cjs +27 -20
  80. package/dist/canvas/components/index.d.ts +1 -0
  81. package/dist/canvas/components/index.d.ts.map +1 -1
  82. package/dist/canvas/components/index.js +1 -0
  83. package/dist/canvas/constants.cjs +12 -0
  84. package/dist/canvas/constants.d.ts +3 -0
  85. package/dist/canvas/constants.d.ts.map +1 -1
  86. package/dist/canvas/constants.js +4 -1
  87. package/dist/canvas/hooks/useAddNodeOnConnectEnd.cjs +22 -23
  88. package/dist/canvas/hooks/useAddNodeOnConnectEnd.d.ts.map +1 -1
  89. package/dist/canvas/hooks/useAddNodeOnConnectEnd.js +23 -24
  90. package/dist/canvas/hooks/usePreviewNode.cjs +2 -1
  91. package/dist/canvas/hooks/usePreviewNode.d.ts.map +1 -1
  92. package/dist/canvas/hooks/usePreviewNode.js +2 -1
  93. package/dist/canvas/schema/node-definition/handle.cjs +10 -2
  94. package/dist/canvas/schema/node-definition/handle.d.ts +9 -0
  95. package/dist/canvas/schema/node-definition/handle.d.ts.map +1 -1
  96. package/dist/canvas/schema/node-definition/handle.js +6 -1
  97. package/dist/canvas/schema/node-definition/index.cjs +4 -1
  98. package/dist/canvas/schema/node-definition/index.d.ts +3 -3
  99. package/dist/canvas/schema/node-definition/index.d.ts.map +1 -1
  100. package/dist/canvas/schema/node-definition/index.js +2 -2
  101. package/dist/canvas/schema/node-definition/node-manifest.cjs +2 -1
  102. package/dist/canvas/schema/node-definition/node-manifest.d.ts +7 -0
  103. package/dist/canvas/schema/node-definition/node-manifest.d.ts.map +1 -1
  104. package/dist/canvas/schema/node-definition/node-manifest.js +2 -1
  105. package/dist/canvas/schema/node-instance/base.d.ts +1 -0
  106. package/dist/canvas/schema/node-instance/base.d.ts.map +1 -1
  107. package/dist/canvas/schema/node-instance/node.d.ts +1 -0
  108. package/dist/canvas/schema/node-instance/node.d.ts.map +1 -1
  109. package/dist/canvas/storybook-utils/hooks/useCanvasStory.d.ts.map +1 -1
  110. package/dist/canvas/storybook-utils/manifests/index.d.ts +2 -1
  111. package/dist/canvas/storybook-utils/manifests/index.d.ts.map +1 -1
  112. package/dist/canvas/storybook-utils/manifests/node-definitions.d.ts.map +1 -1
  113. package/dist/canvas/styles/reactflow-reset.css +2 -2
  114. package/dist/canvas/styles/tailwind.canvas.css +1 -1
  115. package/dist/canvas/utils/NodeUtils.cjs +4 -0
  116. package/dist/canvas/utils/NodeUtils.d.ts +2 -1
  117. package/dist/canvas/utils/NodeUtils.d.ts.map +1 -1
  118. package/dist/canvas/utils/NodeUtils.js +2 -1
  119. package/dist/canvas/utils/collapse.cjs +13 -6
  120. package/dist/canvas/utils/collapse.d.ts.map +1 -1
  121. package/dist/canvas/utils/collapse.js +9 -2
  122. package/dist/canvas/utils/createPreviewGraph.cjs +126 -0
  123. package/dist/canvas/utils/createPreviewGraph.d.ts +36 -0
  124. package/dist/canvas/utils/createPreviewGraph.d.ts.map +1 -0
  125. package/dist/canvas/utils/createPreviewGraph.js +83 -0
  126. package/dist/canvas/utils/createPreviewNode.cjs +30 -11
  127. package/dist/canvas/utils/createPreviewNode.d.ts +10 -2
  128. package/dist/canvas/utils/createPreviewNode.d.ts.map +1 -1
  129. package/dist/canvas/utils/createPreviewNode.js +21 -11
  130. package/dist/canvas/utils/index.cjs +33 -26
  131. package/dist/canvas/utils/index.d.ts +2 -1
  132. package/dist/canvas/utils/index.d.ts.map +1 -1
  133. package/dist/canvas/utils/index.js +2 -1
  134. package/package.json +1 -1
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ resolveContainerHandleGroups: ()=>resolveContainerHandleGroups,
28
+ isContainerNodeManifest: ()=>isContainerNodeManifest,
29
+ resolveContainerPreviewConnectionHandles: ()=>resolveContainerPreviewConnectionHandles,
30
+ getContainerRelativeBodyCenter: ()=>getContainerRelativeBodyCenter,
31
+ getContainerBodyCenter: ()=>getContainerBodyCenter
32
+ });
33
+ const react_cjs_namespaceObject = require("../../xyflow/react.cjs");
34
+ const external_constants_cjs_namespaceObject = require("../../constants.cjs");
35
+ const createPreviewNode_cjs_namespaceObject = require("../../utils/createPreviewNode.cjs");
36
+ const manifest_resolver_cjs_namespaceObject = require("../../utils/manifest-resolver.cjs");
37
+ const NodeUtils_cjs_namespaceObject = require("../../utils/NodeUtils.cjs");
38
+ const external_LoopNode_constants_cjs_namespaceObject = require("./LoopNode.constants.cjs");
39
+ function clamp(value, min, max) {
40
+ return Math.min(Math.max(value, min), max);
41
+ }
42
+ function isContainerNodeManifest(manifest) {
43
+ return manifest?.display.shape === 'container';
44
+ }
45
+ function resolveContainerHandleGroups(groups) {
46
+ return groups.map((group)=>{
47
+ const boundary = 'inner' === group.boundary ? 'inner' : 'outer';
48
+ const position = group.position;
49
+ return {
50
+ ...group,
51
+ boundary,
52
+ connectionPosition: 'inner' === boundary ? (0, createPreviewNode_cjs_namespaceObject.getOppositePosition)(position) : position,
53
+ customPositionAndOffsets: 'inner' === boundary ? insetInnerGroup(group) : group.customPositionAndOffsets
54
+ };
55
+ });
56
+ }
57
+ function getContainerBodyCenter({ width, height, headerHeight }) {
58
+ const clampedHeaderHeight = clamp(headerHeight, 0, height);
59
+ return {
60
+ x: clamp((0, NodeUtils_cjs_namespaceObject.snapToGrid)(width / 2), 0, width),
61
+ y: clamp((0, NodeUtils_cjs_namespaceObject.snapToGrid)(clampedHeaderHeight + (height - clampedHeaderHeight) / 2), 0, height)
62
+ };
63
+ }
64
+ function getContainerRelativeBodyCenter(containerNode) {
65
+ const width = readNumericDimension(containerNode.width, containerNode.measured?.width, containerNode.style?.width);
66
+ const height = readNumericDimension(containerNode.height, containerNode.measured?.height, containerNode.style?.height);
67
+ return getContainerBodyCenter({
68
+ width: width ?? external_constants_cjs_namespaceObject.DEFAULT_CONTAINER_WIDTH,
69
+ height: height ?? external_constants_cjs_namespaceObject.DEFAULT_CONTAINER_HEIGHT,
70
+ headerHeight: external_LoopNode_constants_cjs_namespaceObject.DEFAULT_CONTAINER_HEADER_HEIGHT_PX
71
+ });
72
+ }
73
+ function insetInnerGroup(group) {
74
+ const offsets = group.customPositionAndOffsets ?? {};
75
+ switch(group.position){
76
+ case react_cjs_namespaceObject.Position.Left:
77
+ return {
78
+ ...offsets,
79
+ left: (offsets.left ?? 0) + external_LoopNode_constants_cjs_namespaceObject.CONTAINER_FRAME_INSET_PX
80
+ };
81
+ case react_cjs_namespaceObject.Position.Right:
82
+ return {
83
+ ...offsets,
84
+ right: (offsets.right ?? 0) + external_LoopNode_constants_cjs_namespaceObject.CONTAINER_FRAME_INSET_PX
85
+ };
86
+ case react_cjs_namespaceObject.Position.Top:
87
+ return {
88
+ ...offsets,
89
+ top: (offsets.top ?? 0) + external_LoopNode_constants_cjs_namespaceObject.CONTAINER_FRAME_INSET_PX
90
+ };
91
+ case react_cjs_namespaceObject.Position.Bottom:
92
+ return {
93
+ ...offsets,
94
+ bottom: (offsets.bottom ?? 0) + external_LoopNode_constants_cjs_namespaceObject.CONTAINER_FRAME_INSET_PX
95
+ };
96
+ default:
97
+ return offsets;
98
+ }
99
+ }
100
+ function readNumericDimension(...values) {
101
+ for (const value of values){
102
+ if ('number' == typeof value) return value;
103
+ if ('string' == typeof value) {
104
+ const parsedValue = Number.parseFloat(value);
105
+ if (Number.isFinite(parsedValue)) return parsedValue;
106
+ }
107
+ }
108
+ }
109
+ function resolveContainerPreviewConnectionHandles(manifest, context) {
110
+ if (!manifest) return null;
111
+ const innerGroups = (0, manifest_resolver_cjs_namespaceObject.resolveHandles)(manifest.handleConfiguration, context).filter((group)=>'inner' === group.boundary && (group.visible ?? true));
112
+ const sourceHandle = pickPreferredInnerHandle(innerGroups, 'source');
113
+ const targetHandle = pickPreferredInnerHandle(innerGroups, 'target');
114
+ if (!sourceHandle || !targetHandle) return null;
115
+ return {
116
+ sourceHandleId: sourceHandle.handle.id,
117
+ sourceHandlePosition: (0, createPreviewNode_cjs_namespaceObject.getOppositePosition)(sourceHandle.group.position),
118
+ targetHandleId: targetHandle.handle.id
119
+ };
120
+ }
121
+ function pickPreferredInnerHandle(groups, type) {
122
+ for (const group of groups){
123
+ const handle = group.handles.find((candidate)=>candidate.type === type && candidate.visible);
124
+ if (handle) return {
125
+ group,
126
+ handle
127
+ };
128
+ }
129
+ return null;
130
+ }
131
+ exports.getContainerBodyCenter = __webpack_exports__.getContainerBodyCenter;
132
+ exports.getContainerRelativeBodyCenter = __webpack_exports__.getContainerRelativeBodyCenter;
133
+ exports.isContainerNodeManifest = __webpack_exports__.isContainerNodeManifest;
134
+ exports.resolveContainerHandleGroups = __webpack_exports__.resolveContainerHandleGroups;
135
+ exports.resolveContainerPreviewConnectionHandles = __webpack_exports__.resolveContainerPreviewConnectionHandles;
136
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
137
+ "getContainerBodyCenter",
138
+ "getContainerRelativeBodyCenter",
139
+ "isContainerNodeManifest",
140
+ "resolveContainerHandleGroups",
141
+ "resolveContainerPreviewConnectionHandles"
142
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
143
+ Object.defineProperty(exports, '__esModule', {
144
+ value: true
145
+ });
@@ -0,0 +1,29 @@
1
+ import { type Node, Position } from '../../xyflow/react.ts';
2
+ import type { NodeManifest } from '../../schema/node-definition';
3
+ import type { ResolutionContext, ResolvedHandleGroup } from '../../utils/manifest-resolver';
4
+ export type ContainerHandleBoundary = 'outer' | 'inner';
5
+ export type ContainerHandleGroup = ResolvedHandleGroup & {
6
+ boundary: ContainerHandleBoundary;
7
+ connectionPosition: Position;
8
+ };
9
+ export interface ContainerPreviewConnectionHandles {
10
+ sourceHandleId: string;
11
+ sourceHandlePosition: Position;
12
+ targetHandleId: string;
13
+ }
14
+ export declare function isContainerNodeManifest(manifest: Pick<NodeManifest, 'display'> | undefined): boolean;
15
+ export declare function resolveContainerHandleGroups(groups: ResolvedHandleGroup[]): ContainerHandleGroup[];
16
+ export declare function getContainerBodyCenter({ width, height, headerHeight, }: {
17
+ width: number;
18
+ height: number;
19
+ headerHeight: number;
20
+ }): {
21
+ x: number;
22
+ y: number;
23
+ };
24
+ export declare function getContainerRelativeBodyCenter(containerNode: Pick<Node, 'width' | 'height' | 'measured' | 'style'>): {
25
+ x: number;
26
+ y: number;
27
+ };
28
+ export declare function resolveContainerPreviewConnectionHandles(manifest: Pick<NodeManifest, 'handleConfiguration'> | undefined, context: ResolutionContext): ContainerPreviewConnectionHandles | null;
29
+ //# sourceMappingURL=LoopNode.helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoopNode.helpers.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/LoopNode/LoopNode.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAK5F,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,OAAO,CAAC;AACxD,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IACvD,QAAQ,EAAE,uBAAuB,CAAC;IAClC,kBAAkB,EAAE,QAAQ,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,iCAAiC;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,QAAQ,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;CACxB;AAMD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,SAAS,GAClD,OAAO,CAET;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAAE,GAC5B,oBAAoB,EAAE,CAaxB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,MAAM,EACN,YAAY,GACb,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;;;EAOA;AAED,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;;;EAkBrE;AA+BD,wBAAgB,wCAAwC,CACtD,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,GAAG,SAAS,EAC/D,OAAO,EAAE,iBAAiB,GACzB,iCAAiC,GAAG,IAAI,CAgB1C"}
@@ -0,0 +1,99 @@
1
+ import { Position } from "../../xyflow/react.js";
2
+ import { DEFAULT_CONTAINER_HEIGHT, DEFAULT_CONTAINER_WIDTH } from "../../constants.js";
3
+ import { getOppositePosition } from "../../utils/createPreviewNode.js";
4
+ import { resolveHandles } from "../../utils/manifest-resolver.js";
5
+ import { snapToGrid } from "../../utils/NodeUtils.js";
6
+ import { CONTAINER_FRAME_INSET_PX, DEFAULT_CONTAINER_HEADER_HEIGHT_PX } from "./LoopNode.constants.js";
7
+ function clamp(value, min, max) {
8
+ return Math.min(Math.max(value, min), max);
9
+ }
10
+ function isContainerNodeManifest(manifest) {
11
+ return manifest?.display.shape === 'container';
12
+ }
13
+ function resolveContainerHandleGroups(groups) {
14
+ return groups.map((group)=>{
15
+ const boundary = 'inner' === group.boundary ? 'inner' : 'outer';
16
+ const position = group.position;
17
+ return {
18
+ ...group,
19
+ boundary,
20
+ connectionPosition: 'inner' === boundary ? getOppositePosition(position) : position,
21
+ customPositionAndOffsets: 'inner' === boundary ? insetInnerGroup(group) : group.customPositionAndOffsets
22
+ };
23
+ });
24
+ }
25
+ function getContainerBodyCenter({ width, height, headerHeight }) {
26
+ const clampedHeaderHeight = clamp(headerHeight, 0, height);
27
+ return {
28
+ x: clamp(snapToGrid(width / 2), 0, width),
29
+ y: clamp(snapToGrid(clampedHeaderHeight + (height - clampedHeaderHeight) / 2), 0, height)
30
+ };
31
+ }
32
+ function getContainerRelativeBodyCenter(containerNode) {
33
+ const width = readNumericDimension(containerNode.width, containerNode.measured?.width, containerNode.style?.width);
34
+ const height = readNumericDimension(containerNode.height, containerNode.measured?.height, containerNode.style?.height);
35
+ return getContainerBodyCenter({
36
+ width: width ?? DEFAULT_CONTAINER_WIDTH,
37
+ height: height ?? DEFAULT_CONTAINER_HEIGHT,
38
+ headerHeight: DEFAULT_CONTAINER_HEADER_HEIGHT_PX
39
+ });
40
+ }
41
+ function insetInnerGroup(group) {
42
+ const offsets = group.customPositionAndOffsets ?? {};
43
+ switch(group.position){
44
+ case Position.Left:
45
+ return {
46
+ ...offsets,
47
+ left: (offsets.left ?? 0) + CONTAINER_FRAME_INSET_PX
48
+ };
49
+ case Position.Right:
50
+ return {
51
+ ...offsets,
52
+ right: (offsets.right ?? 0) + CONTAINER_FRAME_INSET_PX
53
+ };
54
+ case Position.Top:
55
+ return {
56
+ ...offsets,
57
+ top: (offsets.top ?? 0) + CONTAINER_FRAME_INSET_PX
58
+ };
59
+ case Position.Bottom:
60
+ return {
61
+ ...offsets,
62
+ bottom: (offsets.bottom ?? 0) + CONTAINER_FRAME_INSET_PX
63
+ };
64
+ default:
65
+ return offsets;
66
+ }
67
+ }
68
+ function readNumericDimension(...values) {
69
+ for (const value of values){
70
+ if ('number' == typeof value) return value;
71
+ if ('string' == typeof value) {
72
+ const parsedValue = Number.parseFloat(value);
73
+ if (Number.isFinite(parsedValue)) return parsedValue;
74
+ }
75
+ }
76
+ }
77
+ function resolveContainerPreviewConnectionHandles(manifest, context) {
78
+ if (!manifest) return null;
79
+ const innerGroups = resolveHandles(manifest.handleConfiguration, context).filter((group)=>'inner' === group.boundary && (group.visible ?? true));
80
+ const sourceHandle = pickPreferredInnerHandle(innerGroups, 'source');
81
+ const targetHandle = pickPreferredInnerHandle(innerGroups, 'target');
82
+ if (!sourceHandle || !targetHandle) return null;
83
+ return {
84
+ sourceHandleId: sourceHandle.handle.id,
85
+ sourceHandlePosition: getOppositePosition(sourceHandle.group.position),
86
+ targetHandleId: targetHandle.handle.id
87
+ };
88
+ }
89
+ function pickPreferredInnerHandle(groups, type) {
90
+ for (const group of groups){
91
+ const handle = group.handles.find((candidate)=>candidate.type === type && candidate.visible);
92
+ if (handle) return {
93
+ group,
94
+ handle
95
+ };
96
+ }
97
+ return null;
98
+ }
99
+ export { getContainerBodyCenter, getContainerRelativeBodyCenter, isContainerNodeManifest, resolveContainerHandleGroups, resolveContainerPreviewConnectionHandles };
@@ -0,0 +1,398 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { NodeResizeControl, useStore, useUpdateNodeInternals } from "../../xyflow/react.js";
3
+ import { cn } from "@uipath/apollo-wind";
4
+ import { memo, useCallback, useEffect, useMemo, useState } from "react";
5
+ import { DEFAULT_CONTAINER_HEIGHT, DEFAULT_CONTAINER_WIDTH } from "../../constants.js";
6
+ import { useOptionalNodeTypeRegistry } from "../../core/index.js";
7
+ import { useElementValidationStatus, useNodeExecutionState } from "../../hooks/index.js";
8
+ import { resolveAdornments } from "../../utils/adornment-resolver.js";
9
+ import { CanvasIcon } from "../../utils/icon-registry.js";
10
+ import { resolveDisplay, resolveHandles } from "../../utils/manifest-resolver.js";
11
+ import { selectIsConnecting, snapToGrid } from "../../utils/NodeUtils.js";
12
+ import { resolveToolbar } from "../../utils/toolbar-resolver.js";
13
+ import { useBaseCanvasMode } from "../BaseCanvas/BaseCanvasModeProvider.js";
14
+ import { useConnectedHandles } from "../BaseCanvas/ConnectedHandlesContext.js";
15
+ import { useSelectionState } from "../BaseCanvas/SelectionStateContext.js";
16
+ import { BaseBadgeSlot } from "../BaseNode/BaseNodeBadgeSlot.js";
17
+ import { getStatusBorder } from "../BaseNode/BaseNodeContainer.js";
18
+ import { MissingManifestNode } from "../BaseNode/BaseNodeMissingManifest.js";
19
+ import { ButtonHandles } from "../ButtonHandle/index.js";
20
+ import { NodeToolbar } from "../Toolbar/index.js";
21
+ import { CONTAINER_FRAME_INSET_PX, CONTAINER_SHELL_RADIUS_PX, DEFAULT_CONTAINER_FRAME_BACKGROUND, DEFAULT_CONTAINER_FRAME_BORDER, DEFAULT_CONTAINER_MIN_HEIGHT, DEFAULT_CONTAINER_MIN_WIDTH, DEFAULT_CONTAINER_SHELL_BACKGROUND, DEFAULT_LOOP_ICON, DEFAULT_LOOP_TITLE } from "./LoopNode.constants.js";
22
+ import { resolveContainerHandleGroups } from "./LoopNode.helpers.js";
23
+ const EMPTY_DATA = {};
24
+ const RESIZE_CONTROLS = [
25
+ {
26
+ position: 'top-left',
27
+ cursor: 'nwse-resize',
28
+ indicatorClassName: 'top-[-5px] left-[-5px]'
29
+ },
30
+ {
31
+ position: 'top-right',
32
+ cursor: 'nesw-resize',
33
+ indicatorClassName: 'top-[-5px] right-[-5px]'
34
+ },
35
+ {
36
+ position: 'bottom-left',
37
+ cursor: 'nesw-resize',
38
+ indicatorClassName: 'bottom-[-5px] left-[-5px]'
39
+ },
40
+ {
41
+ position: 'bottom-right',
42
+ cursor: 'nwse-resize',
43
+ indicatorClassName: 'bottom-[-5px] right-[-5px]'
44
+ }
45
+ ];
46
+ const RESIZE_CONTROL_STYLE = {
47
+ background: 'transparent',
48
+ border: 'none',
49
+ zIndex: 100
50
+ };
51
+ const ADORNMENT_SLOT_POSITIONS = [
52
+ 'topLeft',
53
+ 'topRight',
54
+ 'bottomLeft',
55
+ 'bottomRight'
56
+ ];
57
+ const ADORNMENT_SLOT_SHAPES = {
58
+ topLeft: 'top-left',
59
+ topRight: 'top-right',
60
+ bottomLeft: 'bottom-left',
61
+ bottomRight: 'bottom-right'
62
+ };
63
+ function resolveInteractionState(dragging, selected, isHovered) {
64
+ if (dragging) return 'drag';
65
+ if (selected) return 'selected';
66
+ if (isHovered) return 'hover';
67
+ return 'default';
68
+ }
69
+ function useHasChildNodes(id, enabled) {
70
+ return useStore(useCallback((state)=>!enabled || state.nodes.some((node)=>node.parentId === id), [
71
+ id,
72
+ enabled
73
+ ]));
74
+ }
75
+ function useContainerNodeInternalsRefresh(id, handleGroups, width, height) {
76
+ const updateNodeInternals = useUpdateNodeInternals();
77
+ useEffect(()=>{
78
+ const frameId = requestAnimationFrame(()=>{
79
+ updateNodeInternals(id);
80
+ });
81
+ return ()=>{
82
+ cancelAnimationFrame(frameId);
83
+ };
84
+ }, [
85
+ id,
86
+ handleGroups,
87
+ updateNodeInternals,
88
+ width,
89
+ height
90
+ ]);
91
+ }
92
+ function LoopNodeComponent(props) {
93
+ const { id, type, data, selected = false, dragging = false, width = 0, height = 0, onAddFirstChild, onResize, toolbarConfig: toolbarConfigProp, adornments: adornmentsProp, executionStatusOverride, suggestionType: suggestionTypeProp } = props;
94
+ const nodeTypeRegistry = useOptionalNodeTypeRegistry();
95
+ const [isHovered, setIsHovered] = useState(false);
96
+ const resolvedData = data ?? EMPTY_DATA;
97
+ const isLoading = !!resolvedData.loading;
98
+ const suggestionType = suggestionTypeProp ?? resolvedData.suggestionType;
99
+ const manifest = useMemo(()=>nodeTypeRegistry?.getManifest(type), [
100
+ nodeTypeRegistry,
101
+ type
102
+ ]);
103
+ const { mode } = useBaseCanvasMode();
104
+ const isDesignMode = 'design' === mode;
105
+ const connectedHandleIds = useConnectedHandles(id);
106
+ const { multipleNodesSelected } = useSelectionState();
107
+ const isConnecting = useStore(selectIsConnecting);
108
+ const hasChildNodes = useHasChildNodes(id, isDesignMode && !!onAddFirstChild);
109
+ const executionState = useNodeExecutionState(id);
110
+ const validationState = useElementValidationStatus(id);
111
+ const statusContext = useMemo(()=>({
112
+ nodeId: id,
113
+ executionState: executionStatusOverride ?? executionState,
114
+ validationState,
115
+ isConnecting,
116
+ isSelected: selected,
117
+ isDragging: dragging,
118
+ mode
119
+ }), [
120
+ dragging,
121
+ executionStatusOverride,
122
+ executionState,
123
+ id,
124
+ isConnecting,
125
+ mode,
126
+ selected,
127
+ validationState
128
+ ]);
129
+ const executionStatus = executionStatusOverride ?? ('string' == typeof executionState ? executionState : executionState?.status);
130
+ const display = useMemo(()=>resolveDisplay(manifest?.display, {
131
+ ...resolvedData,
132
+ nodeId: id
133
+ }), [
134
+ manifest?.display,
135
+ id,
136
+ resolvedData
137
+ ]);
138
+ const displayTitle = display.label ?? DEFAULT_LOOP_TITLE;
139
+ const displayIcon = display.icon ?? DEFAULT_LOOP_ICON;
140
+ const containerWidth = width || DEFAULT_CONTAINER_WIDTH;
141
+ const containerHeight = height || DEFAULT_CONTAINER_HEIGHT;
142
+ const nodeSizeStyle = {
143
+ width: containerWidth,
144
+ height: containerHeight,
145
+ minWidth: DEFAULT_CONTAINER_MIN_WIDTH,
146
+ minHeight: DEFAULT_CONTAINER_MIN_HEIGHT
147
+ };
148
+ const toolbarConfig = useMemo(()=>{
149
+ if (void 0 !== toolbarConfigProp) return null === toolbarConfigProp ? void 0 : toolbarConfigProp;
150
+ return manifest ? resolveToolbar(manifest, statusContext, data) : void 0;
151
+ }, [
152
+ data,
153
+ manifest,
154
+ statusContext,
155
+ toolbarConfigProp
156
+ ]);
157
+ const adornments = useMemo(()=>({
158
+ ...resolveAdornments(statusContext),
159
+ ...adornmentsProp ?? {}
160
+ }), [
161
+ adornmentsProp,
162
+ statusContext
163
+ ]);
164
+ const resolvedHandleGroups = useMemo(()=>manifest ? resolveHandles(manifest.handleConfiguration, resolvedData) : [], [
165
+ manifest,
166
+ resolvedData
167
+ ]);
168
+ const containerHandleGroups = useMemo(()=>resolveContainerHandleGroups(resolvedHandleGroups), [
169
+ resolvedHandleGroups
170
+ ]);
171
+ useContainerNodeInternalsRefresh(id, containerHandleGroups, containerWidth, containerHeight);
172
+ const handleResize = useCallback((_event, params)=>{
173
+ onResize?.({
174
+ width: snapToGrid(params.width),
175
+ height: snapToGrid(params.height)
176
+ });
177
+ }, [
178
+ onResize
179
+ ]);
180
+ const handleEmptyClick = useCallback(()=>{
181
+ onAddFirstChild?.();
182
+ }, [
183
+ onAddFirstChild
184
+ ]);
185
+ const handleMouseEnter = useCallback(()=>setIsHovered(true), []);
186
+ const handleMouseLeave = useCallback(()=>setIsHovered(false), []);
187
+ const handleOuterHandleAction = useCallback((_event)=>{
188
+ setIsHovered(false);
189
+ }, []);
190
+ const shouldShowHandles = (isConnecting || selected || isHovered) && !dragging;
191
+ const showHandleAddButtons = isDesignMode && !multipleNodesSelected && !isConnecting && !dragging;
192
+ const showResizeControls = selected && !dragging && isDesignMode;
193
+ const showEmptyStateButton = isDesignMode && !hasChildNodes && !!onAddFirstChild;
194
+ const interactionState = resolveInteractionState(dragging, selected, isHovered);
195
+ if (!manifest) return /*#__PURE__*/ jsx("div", {
196
+ className: "relative",
197
+ style: nodeSizeStyle,
198
+ onMouseEnter: handleMouseEnter,
199
+ onMouseLeave: handleMouseLeave,
200
+ children: /*#__PURE__*/ jsx(MissingManifestNode, {
201
+ type: type,
202
+ isSelected: selected,
203
+ isHovered: isHovered,
204
+ interactionState: interactionState
205
+ })
206
+ });
207
+ return /*#__PURE__*/ jsxs("div", {
208
+ "data-loop-container": true,
209
+ "data-selected": selected ? 'true' : 'false',
210
+ "data-execution-status": executionStatus,
211
+ "data-interaction-state": interactionState,
212
+ "data-suggestion-type": suggestionType,
213
+ "data-validation-status": validationState?.validationStatus,
214
+ "aria-busy": resolvedData.loading || void 0,
215
+ className: cn('group/loop-shell relative flex h-full w-full flex-col overflow-visible border bg-surface-overlay', 'transition-[border-color,box-shadow,opacity] shadow-(--canvas-node-shadow-rest)', 'border-border-subtle', getStatusBorder(suggestionType ?? validationState?.validationStatus ?? executionStatus), isHovered && 'shadow-(--canvas-node-shadow-hover) border-border-hover', selected && 'outline outline-foreground-accent-muted', 'drag' === interactionState && 'cursor-grabbing shadow-(--canvas-node-shadow-lifted)'),
216
+ style: {
217
+ ...nodeSizeStyle,
218
+ borderRadius: CONTAINER_SHELL_RADIUS_PX,
219
+ background: display.background ?? DEFAULT_CONTAINER_SHELL_BACKGROUND
220
+ },
221
+ onMouseEnter: handleMouseEnter,
222
+ onMouseLeave: handleMouseLeave,
223
+ children: [
224
+ ADORNMENT_SLOT_POSITIONS.map((slot)=>adornments?.[slot] ? /*#__PURE__*/ jsx(BaseBadgeSlot, {
225
+ position: ADORNMENT_SLOT_SHAPES[slot],
226
+ shape: "rectangle",
227
+ children: adornments[slot]
228
+ }, slot) : null),
229
+ /*#__PURE__*/ jsx(ResizeCornerIndicators, {
230
+ visible: showResizeControls
231
+ }),
232
+ showResizeControls ? /*#__PURE__*/ jsx(ResizeControls, {
233
+ onResize: handleResize
234
+ }) : null,
235
+ /*#__PURE__*/ jsx(Header, {
236
+ title: displayTitle,
237
+ icon: displayIcon,
238
+ loading: isLoading
239
+ }),
240
+ /*#__PURE__*/ jsx(BodyFrame, {
241
+ isEmpty: showEmptyStateButton,
242
+ isLoading: isLoading,
243
+ onAddFirstChild: handleEmptyClick
244
+ }),
245
+ toolbarConfig && /*#__PURE__*/ jsx(NodeToolbar, {
246
+ nodeId: id,
247
+ config: toolbarConfig,
248
+ expanded: selected || isHovered,
249
+ hidden: dragging || multipleNodesSelected,
250
+ portalToNodeOverlay: true
251
+ }),
252
+ /*#__PURE__*/ jsx(HandleGroups, {
253
+ nodeId: id,
254
+ groups: containerHandleGroups,
255
+ selected: selected,
256
+ hovered: isHovered,
257
+ shouldShowHandles: shouldShowHandles,
258
+ showAddButton: showHandleAddButtons,
259
+ showNotches: shouldShowHandles,
260
+ nodeWidth: containerWidth,
261
+ nodeHeight: containerHeight,
262
+ connectedHandleIds: connectedHandleIds,
263
+ onOuterHandleAction: handleOuterHandleAction
264
+ })
265
+ ]
266
+ });
267
+ }
268
+ const LoopNode = /*#__PURE__*/ memo(LoopNodeComponent);
269
+ function Header({ title, icon, loading }) {
270
+ const titleContent = loading ? /*#__PURE__*/ jsx("div", {
271
+ className: "h-5 w-28 animate-pulse rounded bg-(--canvas-background-overlay)"
272
+ }) : /*#__PURE__*/ jsx("span", {
273
+ className: "truncate text-[14px] font-semibold tracking-normal",
274
+ children: title
275
+ });
276
+ const iconContent = loading ? /*#__PURE__*/ jsx("div", {
277
+ className: "h-4 w-4 shrink-0 animate-pulse rounded bg-(--canvas-background-overlay)"
278
+ }) : icon ? /*#__PURE__*/ jsx("span", {
279
+ className: "shrink-0 text-foreground",
280
+ "aria-hidden": true,
281
+ children: /*#__PURE__*/ jsx(CanvasIcon, {
282
+ icon: icon,
283
+ size: 16
284
+ })
285
+ }) : null;
286
+ return /*#__PURE__*/ jsx("div", {
287
+ className: "flex shrink-0 items-center justify-between gap-2.5 pl-4.5 pr-5 pt-3.5 text-foreground cursor-grab active:cursor-grabbing",
288
+ "data-testid": "loop-node-header",
289
+ children: /*#__PURE__*/ jsxs("div", {
290
+ className: "flex min-w-0 items-center gap-2",
291
+ children: [
292
+ iconContent,
293
+ titleContent
294
+ ]
295
+ })
296
+ });
297
+ }
298
+ function EmptyState({ onAddFirstChild }) {
299
+ return /*#__PURE__*/ jsx("button", {
300
+ type: "button",
301
+ onClick: onAddFirstChild,
302
+ "aria-label": "Add node to loop",
303
+ className: cn('nodrag nopan', 'pointer-events-auto flex h-8 w-8 items-center justify-center rounded-xl', 'border border-border bg-surface-overlay text-foreground', 'shadow-(--canvas-node-shadow-lifted)', 'transition-colors', 'hover:bg-surface-hover hover:border-brand'),
304
+ children: /*#__PURE__*/ jsx(CanvasIcon, {
305
+ icon: "plus",
306
+ size: 14
307
+ })
308
+ });
309
+ }
310
+ function BodyFrame({ isEmpty, isLoading, onAddFirstChild }) {
311
+ return /*#__PURE__*/ jsxs("div", {
312
+ "data-testid": "loop-body-frame",
313
+ "data-empty": isEmpty ? 'true' : 'false',
314
+ className: cn('relative flex flex-1 rounded-[26px] border border-dashed', 'pointer-events-none', isEmpty && 'items-center justify-center'),
315
+ style: {
316
+ margin: CONTAINER_FRAME_INSET_PX,
317
+ background: DEFAULT_CONTAINER_FRAME_BACKGROUND,
318
+ borderColor: DEFAULT_CONTAINER_FRAME_BORDER
319
+ },
320
+ children: [
321
+ isLoading ? /*#__PURE__*/ jsx("div", {
322
+ className: "m-6 h-14 w-full animate-pulse rounded-[18px] bg-(--canvas-background-overlay)"
323
+ }) : null,
324
+ isEmpty ? /*#__PURE__*/ jsx(EmptyState, {
325
+ onAddFirstChild: onAddFirstChild
326
+ }) : null
327
+ ]
328
+ });
329
+ }
330
+ function ResizeControls({ onResize }) {
331
+ return /*#__PURE__*/ jsx(Fragment, {
332
+ children: RESIZE_CONTROLS.map(({ position, cursor })=>/*#__PURE__*/ jsx(NodeResizeControl, {
333
+ style: RESIZE_CONTROL_STYLE,
334
+ position: position,
335
+ minWidth: DEFAULT_CONTAINER_MIN_WIDTH,
336
+ minHeight: DEFAULT_CONTAINER_MIN_HEIGHT,
337
+ onResize: onResize,
338
+ children: /*#__PURE__*/ jsx("div", {
339
+ className: "absolute bottom-0 right-0 h-5 w-5 pointer-events-auto",
340
+ style: {
341
+ cursor
342
+ }
343
+ })
344
+ }, position))
345
+ });
346
+ }
347
+ function ResizeCornerIndicators({ visible }) {
348
+ return /*#__PURE__*/ jsx(Fragment, {
349
+ children: RESIZE_CONTROLS.map(({ position, indicatorClassName })=>/*#__PURE__*/ jsx("div", {
350
+ "aria-hidden": true,
351
+ className: cn('pointer-events-none absolute h-1.5 w-1.5 rounded-[1px] border border-brand bg-background transition-opacity', indicatorClassName, visible ? 'opacity-100' : 'opacity-0')
352
+ }, position))
353
+ });
354
+ }
355
+ function HandleGroups({ groups, ...handleGroupProps }) {
356
+ if (0 === groups.length) return null;
357
+ return /*#__PURE__*/ jsx(Fragment, {
358
+ children: groups.map((group, groupIndex)=>/*#__PURE__*/ jsx(HandleGroup, {
359
+ ...handleGroupProps,
360
+ group: group
361
+ }, `${group.boundary}:${group.position}:${groupIndex}`))
362
+ });
363
+ }
364
+ function HandleGroup({ nodeId, group, selected, hovered, shouldShowHandles, showAddButton, showNotches, nodeWidth, nodeHeight, connectedHandleIds, onOuterHandleAction }) {
365
+ const groupVisible = shouldShowHandles && (group.visible ?? true);
366
+ const position = group.position;
367
+ const enhancedHandles = useMemo(()=>group.handles.map((handle)=>{
368
+ const isInnerSourceHandle = 'inner' === group.boundary && 'source' === handle.type;
369
+ const shouldResetHoverOnAction = 'outer' === group.boundary && 'source' === handle.type && handle.showButton;
370
+ return {
371
+ ...handle,
372
+ showHandle: connectedHandleIds.has(handle.id) || groupVisible,
373
+ showButton: isInnerSourceHandle ? false : handle.showButton,
374
+ onAction: handle.onAction ?? (shouldResetHoverOnAction ? onOuterHandleAction : void 0)
375
+ };
376
+ }), [
377
+ group.boundary,
378
+ group.handles,
379
+ connectedHandleIds,
380
+ groupVisible,
381
+ onOuterHandleAction
382
+ ]);
383
+ return /*#__PURE__*/ jsx(ButtonHandles, {
384
+ nodeId: nodeId,
385
+ handles: enhancedHandles,
386
+ position: position,
387
+ connectionPosition: group.connectionPosition,
388
+ selected: selected,
389
+ hovered: hovered,
390
+ showAddButton: showAddButton,
391
+ showNotches: showNotches,
392
+ customPositionAndOffsets: group.customPositionAndOffsets,
393
+ nodeWidth: nodeWidth,
394
+ nodeHeight: nodeHeight,
395
+ portalActions: 'outer' === group.boundary
396
+ });
397
+ }
398
+ export { LoopNode };