+
+
+ @for (var i = 0; i < Group.DelegateNode.CaptureInputs.Count; i++)
+ {
+ var capture = Group.DelegateNode.CaptureInputs[i];
+ var port = Group.GetPort(capture);
+ var top = 86 + i * 30;
+
+ }
+
+ @{
+ var delegatePort = Group.GetPort(Group.DelegateNode.DelegateOutput);
+ }
+
+
@Group.DelegateNode.DelegateOutput.Name
+
+
+
+ @if (Group.BoundaryReturn is { } boundaryReturn)
+ {
+ var execPort = Group.GetPort(boundaryReturn.ExecInput);
+ var resultPort = Group.GetPort(boundaryReturn.ResultInput);
+
+
Return
+
+
+
@boundaryReturn.ExecInput.Name
+
+
+
+
@boundaryReturn.ResultInput.Name
+ @if (boundaryReturn.ResultInput.Type.AllowTextboxEdit && resultPort.Links.Count == 0)
+ {
+
GraphCanvas.OnTextboxValueChanged(resultPort, x.Value?.ToString())"
+ @onpointerdown:stopPropagation="true" />
+ }
+
+
+ }
+
+
+
+
+@code {
+ [Parameter, EditorRequired]
+ public LambdaGroupModel Group { get; set; } = null!;
+
+ [CascadingParameter]
+ public GraphCanvas GraphCanvas { get; set; } = null!;
+
+ private void AddNode() => GraphCanvas.ShowAddNodeForScope(Group);
+
+ private void AddParameter() => Group.DelegateNode.AddParameter();
+ private void RemoveParameter(string id) => Group.DelegateNode.RemoveParameter(id);
+ private void RemoveCapture(string id) => Group.DelegateNode.RemoveCapture(id);
+
+ private void SelectResultType() =>
+ GraphCanvas.ShowLambdaTypeSelector(Group, Group.DelegateNode.SetResultType);
+
+ private void SelectParameterType(LambdaParameterDefinition parameter) =>
+ GraphCanvas.ShowLambdaTypeSelector(Group, type => Group.DelegateNode.UpdateParameter(parameter.Id, parameter.Name, type));
+
+ private void SelectCaptureType(LambdaCaptureDefinition capture) =>
+ GraphCanvas.ShowLambdaTypeSelector(Group, type => Group.DelegateNode.UpdateCapture(capture.Id, capture.Name, type));
+}
diff --git a/src/NodeDev.Blazor/wwwroot/styles.css b/src/NodeDev.Blazor/wwwroot/styles.css
index 056c6ff4..d97c415e 100644
--- a/src/NodeDev.Blazor/wwwroot/styles.css
+++ b/src/NodeDev.Blazor/wwwroot/styles.css
@@ -181,4 +181,212 @@ g.diagram-link path:not(.selection-helper) {
.debugged-path:hover {
cursor: pointer;
-}
\ No newline at end of file
+}
+
+.diagram-group:has(> .lambda-region) {
+ outline: 2px solid #26878a;
+ border-radius: 12px;
+ background: rgba(64, 186, 189, 0.10);
+}
+
+.diagram-group.selected:has(> .lambda-region) {
+ outline-color: #111827;
+ box-shadow: 0 0 0 2px rgba(64, 186, 189, 0.35);
+}
+
+.lambda-region {
+ position: absolute;
+ inset: 0;
+ border-radius: 12px;
+ pointer-events: none;
+}
+
+.lambda-region-header {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ min-height: 42px;
+ padding: 6px 8px 6px 14px;
+ border-bottom: 1px solid rgba(38, 135, 138, 0.55);
+ border-radius: 12px 12px 0 0;
+ background: rgba(64, 186, 189, 0.20);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ pointer-events: all;
+}
+
+.lambda-region-title-row,
+.lambda-signature-editor {
+ display: flex;
+ align-items: center;
+ gap: 0.3rem;
+}
+
+.lambda-region-title-row {
+ justify-content: space-between;
+ flex: 1 1 auto;
+ min-width: 0;
+}
+
+.lambda-signature-editor {
+ flex: 0 1 auto;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ font-size: 0.7rem;
+}
+
+.lambda-signature-chip {
+ display: inline-flex;
+ align-items: center;
+ border: 1px solid rgba(79, 70, 229, 0.35);
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.8);
+ overflow: hidden;
+}
+
+.lambda-signature-chip button,
+.lambda-result-chip,
+.lambda-signature-add {
+ border: 0;
+ background: transparent;
+ color: inherit;
+ cursor: pointer;
+ padding: 0.12rem 0.35rem;
+}
+
+.lambda-signature-chip button:hover,
+.lambda-signature-add:hover {
+ background: rgba(79, 70, 229, 0.12);
+}
+
+.lambda-capture-chip {
+ border-color: rgba(5, 150, 105, 0.45);
+}
+
+.lambda-result-chip,
+.lambda-signature-add {
+ border: 1px dashed rgba(79, 70, 229, 0.55);
+ border-radius: 999px;
+}
+
+.lambda-result-chip {
+ max-width: 180px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.lambda-chip-remove {
+ font-weight: 700;
+ padding-left: 0.2rem !important;
+}
+
+.lambda-region-signature {
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ color: #164e50;
+ font-weight: 700;
+}
+
+.lambda-region-add {
+ flex: none;
+}
+
+.lambda-boundary-row {
+ position: absolute;
+ min-height: 24px;
+ display: flex;
+ align-items: center;
+ gap: 7px;
+ padding: 2px 8px;
+ border-radius: 6px;
+ background: rgba(255, 255, 255, 0.88);
+ color: #164e50;
+ font-size: 0.78rem;
+ pointer-events: all;
+}
+
+.lambda-capture-row {
+ left: 0;
+ transform: translateX(-1px);
+}
+
+.lambda-delegate-row {
+ right: 0;
+ top: 50%;
+ transform: translate(1px, -50%);
+}
+
+.lambda-return-boundary {
+ position: absolute;
+ right: -1px;
+ bottom: 18px;
+ width: 156px;
+ box-sizing: border-box;
+ overflow: visible;
+ padding: 0 10px 7px 14px;
+ border: 1px solid rgba(185, 28, 28, 0.45);
+ border-right: 0;
+ border-radius: 8px 0 0 8px;
+ background: rgba(254, 242, 242, 0.94);
+ color: #7f1d1d;
+ font-size: 0.75rem;
+ pointer-events: all;
+}
+
+.lambda-return-title {
+ display: block;
+ margin: -1px -10px 5px -14px;
+ padding: 4px 10px 4px 14px;
+ border-radius: 8px 0 0 0;
+ background: #dc2626;
+ color: white;
+ font-weight: 700;
+}
+
+.lambda-return-port {
+ position: relative;
+ min-height: 24px;
+ display: flex;
+ align-items: center;
+ gap: 7px;
+}
+
+.lambda-return-port .diagram-port {
+ width: 18px;
+ height: 18px;
+ flex: none;
+ border: 1px solid #d4d4d4;
+ border-radius: 9999px;
+ cursor: pointer;
+ position: relative;
+ margin: 0;
+ pointer-events: all;
+}
+
+.lambda-return-editor {
+ width: 72px;
+ min-width: 0;
+ padding: 3px 6px;
+ border: 1px solid rgba(127, 29, 29, 0.35);
+ border-radius: 4px;
+ background: white;
+ color: #111827;
+ font: inherit;
+}
+
+.lambda-boundary-row .diagram-port {
+ width: 18px;
+ height: 18px;
+ border: 1px solid #d4d4d4;
+ border-radius: 9999px;
+ cursor: pointer;
+ position: relative;
+ margin: 0;
+ pointer-events: all;
+}
diff --git a/src/NodeDev.Core/Class/NodeClassMethod.cs b/src/NodeDev.Core/Class/NodeClassMethod.cs
index 016d7725..08051129 100644
--- a/src/NodeDev.Core/Class/NodeClassMethod.cs
+++ b/src/NodeDev.Core/Class/NodeClassMethod.cs
@@ -36,9 +36,9 @@ public NodeClassMethod(NodeClass ownerClass, string name, TypeBase returnType, b
public bool HasReturnValue => ReturnType != Class.TypeFactory.Void;
- public EntryNode? EntryNode => Graph.Nodes.Values.OfType