@particle-academy/fancy-flow 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ATQXZEVD.js → chunk-YOFCVO2W.js} +3 -2
- package/dist/chunk-YOFCVO2W.js.map +1 -0
- package/dist/index.cjs +194 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +196 -14
- package/dist/index.js.map +1 -1
- package/dist/registry.cjs +1 -0
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +1 -1
- package/dist/styles.css +658 -549
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-ATQXZEVD.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -538,10 +538,19 @@ declare function FlowRunControls({ running, onRun, onCancel, onReset, className,
|
|
|
538
538
|
|
|
539
539
|
type FlowRunFeedProps = {
|
|
540
540
|
entries: FlowRunFeedEntry[];
|
|
541
|
+
/** Show the header bar (title + running badge + event count). Default true. */
|
|
542
|
+
showHeader?: boolean;
|
|
543
|
+
/** Header title. Default "Run feed". */
|
|
544
|
+
title?: string;
|
|
545
|
+
/** When true, a "running" badge shows in the header. */
|
|
546
|
+
running?: boolean;
|
|
541
547
|
className?: string;
|
|
542
548
|
style?: CSSProperties;
|
|
543
549
|
};
|
|
544
|
-
/**
|
|
545
|
-
|
|
550
|
+
/**
|
|
551
|
+
* FlowRunFeed — scrolling run log with a header (title + live event count).
|
|
552
|
+
* Auto-scrolls its body to the bottom on new entries.
|
|
553
|
+
*/
|
|
554
|
+
declare function FlowRunFeed({ entries, showHeader, title, running, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
546
555
|
|
|
547
556
|
export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
package/dist/index.d.ts
CHANGED
|
@@ -538,10 +538,19 @@ declare function FlowRunControls({ running, onRun, onCancel, onReset, className,
|
|
|
538
538
|
|
|
539
539
|
type FlowRunFeedProps = {
|
|
540
540
|
entries: FlowRunFeedEntry[];
|
|
541
|
+
/** Show the header bar (title + running badge + event count). Default true. */
|
|
542
|
+
showHeader?: boolean;
|
|
543
|
+
/** Header title. Default "Run feed". */
|
|
544
|
+
title?: string;
|
|
545
|
+
/** When true, a "running" badge shows in the header. */
|
|
546
|
+
running?: boolean;
|
|
541
547
|
className?: string;
|
|
542
548
|
style?: CSSProperties;
|
|
543
549
|
};
|
|
544
|
-
/**
|
|
545
|
-
|
|
550
|
+
/**
|
|
551
|
+
* FlowRunFeed — scrolling run log with a header (title + live event count).
|
|
552
|
+
* Auto-scrolls its body to the bottom on new entries.
|
|
553
|
+
*/
|
|
554
|
+
declare function FlowRunFeed({ entries, showHeader, title, running, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
546
555
|
|
|
547
556
|
export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useFlowState, useFlowRun, useFlowHistory, applyOutputsToNodes, applyStatusesToNodes } from './chunk-OFW7GN3Y.js';
|
|
2
2
|
export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-OFW7GN3Y.js';
|
|
3
|
-
import { buildNodeTypes, FlowEditorProvider, registerBuiltinKinds, NoteNode, createConnectionValidator } from './chunk-
|
|
4
|
-
export { ANY_PORT_TYPE, BUILTIN_KINDS, LaneNode, NoteNode, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds, useFlowEditor, useFlowEditorOptional } from './chunk-
|
|
3
|
+
import { buildNodeTypes, FlowEditorProvider, registerBuiltinKinds, NoteNode, createConnectionValidator } from './chunk-YOFCVO2W.js';
|
|
4
|
+
export { ANY_PORT_TYPE, BUILTIN_KINDS, LaneNode, NoteNode, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds, useFlowEditor, useFlowEditorOptional } from './chunk-YOFCVO2W.js';
|
|
5
5
|
import { ReactFlowProvider, useReactFlow, addEdge, applyEdgeChanges, applyNodeChanges, Position, Handle, reconnectEdge, index, BackgroundVariant, Background, Controls, MiniMap, ViewportPortal } from './chunk-OWENS2H5.js';
|
|
6
6
|
export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
|
|
7
7
|
import './chunk-USL4FMFU.js';
|
|
@@ -13,7 +13,7 @@ import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, valid
|
|
|
13
13
|
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-Q6IPK64P.js';
|
|
14
14
|
import { getRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
15
15
|
export { RichInputPreview, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
16
|
-
import { memo, forwardRef, useState,
|
|
16
|
+
import { memo, forwardRef, useState, useMemo, useEffect, useCallback, useRef, useImperativeHandle } from 'react';
|
|
17
17
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
18
18
|
|
|
19
19
|
function NodeShellInner({
|
|
@@ -969,9 +969,13 @@ function NodeConfigPanel({
|
|
|
969
969
|
return /* @__PURE__ */ jsxs("aside", { className: ["ff-panel", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
970
970
|
header,
|
|
971
971
|
/* @__PURE__ */ jsxs("header", { className: "ff-panel__header", children: [
|
|
972
|
-
/* @__PURE__ */ jsx("span", { className: "ff-
|
|
973
|
-
|
|
972
|
+
/* @__PURE__ */ jsx("span", { className: "ff-panel__head-icon", style: { background: kind.accent ?? categoryAccent(kind.category) }, "aria-hidden": true, children: kind.icon }),
|
|
973
|
+
/* @__PURE__ */ jsxs("span", { className: "ff-panel__head-text", children: [
|
|
974
|
+
/* @__PURE__ */ jsx("span", { className: "ff-panel__head-kind", children: kind.label }),
|
|
975
|
+
/* @__PURE__ */ jsx("span", { className: "ff-panel__head-name", children: node.data.label || kind.label })
|
|
976
|
+
] })
|
|
974
977
|
] }),
|
|
978
|
+
kind.description && /* @__PURE__ */ jsx("p", { className: "ff-panel__kind-desc", children: kind.description }),
|
|
975
979
|
/* @__PURE__ */ jsxs("div", { className: "ff-panel__field", children: [
|
|
976
980
|
/* @__PURE__ */ jsx("label", { className: "ff-panel__label", children: "Label" }),
|
|
977
981
|
/* @__PURE__ */ jsx(
|
|
@@ -1046,22 +1050,161 @@ function FlowRunControls({ running, onRun, onCancel, onReset, className, style }
|
|
|
1046
1050
|
onReset && /* @__PURE__ */ jsx("button", { type: "button", className: "ff-run-controls__btn ff-run-controls__btn--reset", onClick: onReset, disabled: running, children: "Reset" })
|
|
1047
1051
|
] });
|
|
1048
1052
|
}
|
|
1049
|
-
function FlowRunFeed({ entries, className, style }) {
|
|
1053
|
+
function FlowRunFeed({ entries, showHeader = true, title = "Run feed", running, className, style }) {
|
|
1050
1054
|
const scrollRef = useRef(null);
|
|
1051
1055
|
useEffect(() => {
|
|
1052
1056
|
const el = scrollRef.current;
|
|
1053
1057
|
if (el) el.scrollTop = el.scrollHeight;
|
|
1054
1058
|
}, [entries.length]);
|
|
1055
|
-
return /* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1059
|
+
return /* @__PURE__ */ jsxs("div", { className: ["ff-run-feed", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
1060
|
+
showHeader && /* @__PURE__ */ jsxs("div", { className: "ff-run-feed__header", children: [
|
|
1061
|
+
/* @__PURE__ */ jsx("span", { className: "ff-run-feed__title", "aria-hidden": true, children: "\u25B8" }),
|
|
1062
|
+
/* @__PURE__ */ jsx("span", { className: "ff-run-feed__title-text", children: title }),
|
|
1063
|
+
running && /* @__PURE__ */ jsx("span", { className: "ff-run-feed__badge", children: "running" }),
|
|
1064
|
+
/* @__PURE__ */ jsxs("span", { className: "ff-run-feed__count", children: [
|
|
1065
|
+
entries.length,
|
|
1066
|
+
" ",
|
|
1067
|
+
entries.length === 1 ? "event" : "events"
|
|
1068
|
+
] })
|
|
1069
|
+
] }),
|
|
1070
|
+
/* @__PURE__ */ jsx("div", { className: "ff-run-feed__body", ref: scrollRef, children: entries.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ff-run-feed__empty", children: "No run events yet." }) : entries.map((e) => /* @__PURE__ */ jsxs("div", { className: `ff-run-feed__row ff-run-feed__row--${e.level}`, children: [
|
|
1071
|
+
/* @__PURE__ */ jsx("span", { className: "ff-run-feed__time", children: formatTime(e.at) }),
|
|
1072
|
+
e.nodeId && /* @__PURE__ */ jsx("span", { className: "ff-run-feed__node", children: e.nodeId }),
|
|
1073
|
+
/* @__PURE__ */ jsx("span", { className: "ff-run-feed__text", children: e.text })
|
|
1074
|
+
] }, e.id)) })
|
|
1075
|
+
] });
|
|
1060
1076
|
}
|
|
1061
1077
|
function formatTime(at) {
|
|
1062
1078
|
const d = new Date(at);
|
|
1063
1079
|
return `${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}.${Math.floor(d.getMilliseconds() / 100)}`;
|
|
1064
1080
|
}
|
|
1081
|
+
function humanInputFields(config) {
|
|
1082
|
+
const raw = Array.isArray(config?.fields) ? config.fields : [];
|
|
1083
|
+
const fields = raw.filter((f) => f && typeof f === "object" && typeof f.key === "string" && f.key).map((f) => ({
|
|
1084
|
+
key: f.key,
|
|
1085
|
+
label: typeof f.label === "string" && f.label ? f.label : f.key,
|
|
1086
|
+
type: ["text", "textarea", "number", "select", "switch"].includes(f.type) ? f.type : "text",
|
|
1087
|
+
required: !!f.required,
|
|
1088
|
+
placeholder: typeof f.placeholder === "string" ? f.placeholder : void 0,
|
|
1089
|
+
options: Array.isArray(f.options) ? f.options : void 0,
|
|
1090
|
+
default: f.default
|
|
1091
|
+
}));
|
|
1092
|
+
if (fields.length) return fields;
|
|
1093
|
+
const title = typeof config?.title === "string" && config.title ? config.title : "Your answer";
|
|
1094
|
+
return [{ key: "value", label: title, type: "textarea", required: true }];
|
|
1095
|
+
}
|
|
1096
|
+
function initialValues(fields) {
|
|
1097
|
+
const v = {};
|
|
1098
|
+
for (const f of fields) v[f.key] = f.type === "switch" ? !!f.default : f.default ?? "";
|
|
1099
|
+
return v;
|
|
1100
|
+
}
|
|
1101
|
+
function HumanPrompt({ request, onCancel }) {
|
|
1102
|
+
const firstRef = useRef(null);
|
|
1103
|
+
useEffect(() => {
|
|
1104
|
+
firstRef.current?.focus();
|
|
1105
|
+
const onKey = (e) => {
|
|
1106
|
+
if (e.key === "Escape") onCancel();
|
|
1107
|
+
};
|
|
1108
|
+
window.addEventListener("keydown", onKey);
|
|
1109
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
1110
|
+
}, [onCancel]);
|
|
1111
|
+
return /* @__PURE__ */ jsx("div", { className: "ff-prompt-overlay", role: "dialog", "aria-modal": "true", "aria-label": request.title, children: /* @__PURE__ */ jsxs("div", { className: "ff-prompt", onClick: (e) => e.stopPropagation(), children: [
|
|
1112
|
+
/* @__PURE__ */ jsx("div", { className: "ff-prompt__title", children: request.title }),
|
|
1113
|
+
request.kind === "approval" ? /* @__PURE__ */ jsx(ApprovalBody, { request, onCancel }) : /* @__PURE__ */ jsx(InputBody, { request, onCancel, firstRef })
|
|
1114
|
+
] }) });
|
|
1115
|
+
}
|
|
1116
|
+
function ApprovalBody({ request, onCancel }) {
|
|
1117
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1118
|
+
request.description && /* @__PURE__ */ jsx("p", { className: "ff-prompt__desc", children: request.description }),
|
|
1119
|
+
/* @__PURE__ */ jsxs("div", { className: "ff-prompt__actions", children: [
|
|
1120
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "ff-prompt__btn ff-prompt__btn--ghost", onClick: onCancel, children: "Cancel" }),
|
|
1121
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "ff-prompt__btn ff-prompt__btn--danger", onClick: () => request.resolve(false), children: "Deny" }),
|
|
1122
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "ff-prompt__btn ff-prompt__btn--primary", onClick: () => request.resolve(true), children: "Approve" })
|
|
1123
|
+
] })
|
|
1124
|
+
] });
|
|
1125
|
+
}
|
|
1126
|
+
function InputBody({
|
|
1127
|
+
request,
|
|
1128
|
+
onCancel,
|
|
1129
|
+
firstRef
|
|
1130
|
+
}) {
|
|
1131
|
+
const [values, setValues] = useState(() => initialValues(request.fields));
|
|
1132
|
+
const set = (k, v) => setValues((prev) => ({ ...prev, [k]: v }));
|
|
1133
|
+
const missing = request.fields.filter((f) => f.required && (values[f.key] === void 0 || values[f.key] === ""));
|
|
1134
|
+
const submit = () => {
|
|
1135
|
+
if (missing.length === 0) request.resolve(values);
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ jsxs(
|
|
1138
|
+
"form",
|
|
1139
|
+
{
|
|
1140
|
+
onSubmit: (e) => {
|
|
1141
|
+
e.preventDefault();
|
|
1142
|
+
submit();
|
|
1143
|
+
},
|
|
1144
|
+
onKeyDown: (e) => {
|
|
1145
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1146
|
+
e.preventDefault();
|
|
1147
|
+
submit();
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
children: [
|
|
1151
|
+
/* @__PURE__ */ jsx("div", { className: "ff-prompt__fields", children: request.fields.map((f, i) => /* @__PURE__ */ jsxs("label", { className: "ff-prompt__field", children: [
|
|
1152
|
+
/* @__PURE__ */ jsxs("span", { className: "ff-prompt__label", children: [
|
|
1153
|
+
f.label ?? f.key,
|
|
1154
|
+
f.required && /* @__PURE__ */ jsx("span", { className: "ff-prompt__req", children: " *" })
|
|
1155
|
+
] }),
|
|
1156
|
+
renderControl(f, values[f.key], (v) => set(f.key, v), i === 0 ? firstRef : void 0)
|
|
1157
|
+
] }, f.key)) }),
|
|
1158
|
+
/* @__PURE__ */ jsxs("div", { className: "ff-prompt__actions", children: [
|
|
1159
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "ff-prompt__btn ff-prompt__btn--ghost", onClick: onCancel, children: "Cancel" }),
|
|
1160
|
+
/* @__PURE__ */ jsx("button", { type: "submit", className: "ff-prompt__btn ff-prompt__btn--primary", disabled: missing.length > 0, children: request.submitLabel || "Continue" })
|
|
1161
|
+
] })
|
|
1162
|
+
]
|
|
1163
|
+
}
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
function renderControl(f, value, onChange, ref) {
|
|
1167
|
+
const common = { className: "ff-prompt__input", placeholder: f.placeholder };
|
|
1168
|
+
if (f.type === "textarea") {
|
|
1169
|
+
return /* @__PURE__ */ jsx(
|
|
1170
|
+
"textarea",
|
|
1171
|
+
{
|
|
1172
|
+
...common,
|
|
1173
|
+
ref,
|
|
1174
|
+
rows: 3,
|
|
1175
|
+
value: String(value ?? ""),
|
|
1176
|
+
onChange: (e) => onChange(e.target.value)
|
|
1177
|
+
}
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
if (f.type === "switch") {
|
|
1181
|
+
return /* @__PURE__ */ jsx(
|
|
1182
|
+
"input",
|
|
1183
|
+
{
|
|
1184
|
+
type: "checkbox",
|
|
1185
|
+
className: "ff-prompt__switch",
|
|
1186
|
+
checked: !!value,
|
|
1187
|
+
onChange: (e) => onChange(e.target.checked)
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
if (f.type === "select" && f.options && f.options.length) {
|
|
1192
|
+
return /* @__PURE__ */ jsxs("select", { className: "ff-prompt__input", value: String(value ?? ""), onChange: (e) => onChange(e.target.value), children: [
|
|
1193
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Choose\u2026" }),
|
|
1194
|
+
f.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1195
|
+
] });
|
|
1196
|
+
}
|
|
1197
|
+
return /* @__PURE__ */ jsx(
|
|
1198
|
+
"input",
|
|
1199
|
+
{
|
|
1200
|
+
...common,
|
|
1201
|
+
ref,
|
|
1202
|
+
type: f.type === "number" ? "number" : "text",
|
|
1203
|
+
value: String(value ?? ""),
|
|
1204
|
+
onChange: (e) => onChange(f.type === "number" ? e.target.value === "" ? "" : Number(e.target.value) : e.target.value)
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1065
1208
|
var FlowEditor = forwardRef(function FlowEditor2(props, ref) {
|
|
1066
1209
|
return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(
|
|
1067
1210
|
"div",
|
|
@@ -1095,6 +1238,41 @@ function FlowEditorInner({
|
|
|
1095
1238
|
const internal = useFlowState(initial);
|
|
1096
1239
|
const runner = useFlowRun();
|
|
1097
1240
|
const rf = useReactFlow();
|
|
1241
|
+
const [prompt, setPrompt] = useState(null);
|
|
1242
|
+
const humanExecutors = useMemo(
|
|
1243
|
+
() => ({
|
|
1244
|
+
user_input: ({ node }) => new Promise((resolve) => {
|
|
1245
|
+
const cfg = node.data?.config ?? {};
|
|
1246
|
+
setPrompt({
|
|
1247
|
+
kind: "input",
|
|
1248
|
+
title: typeof cfg.title === "string" && cfg.title || "Your input",
|
|
1249
|
+
submitLabel: typeof cfg.submitLabel === "string" ? cfg.submitLabel : void 0,
|
|
1250
|
+
fields: humanInputFields(cfg),
|
|
1251
|
+
resolve: (values) => {
|
|
1252
|
+
setPrompt(null);
|
|
1253
|
+
resolve(values);
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
}),
|
|
1257
|
+
human_approval: ({ node }) => new Promise((resolve) => {
|
|
1258
|
+
const cfg = node.data?.config ?? {};
|
|
1259
|
+
setPrompt({
|
|
1260
|
+
kind: "approval",
|
|
1261
|
+
title: typeof cfg.title === "string" && cfg.title || "Approve action",
|
|
1262
|
+
description: typeof cfg.description === "string" ? cfg.description : void 0,
|
|
1263
|
+
resolve: (approved) => {
|
|
1264
|
+
setPrompt(null);
|
|
1265
|
+
resolve({ branch: approved ? "approved" : "denied" });
|
|
1266
|
+
}
|
|
1267
|
+
});
|
|
1268
|
+
})
|
|
1269
|
+
}),
|
|
1270
|
+
[]
|
|
1271
|
+
);
|
|
1272
|
+
const runExecutors = useMemo(() => ({ ...humanExecutors, ...executors }), [humanExecutors, executors]);
|
|
1273
|
+
useEffect(() => {
|
|
1274
|
+
if (!runner.running) setPrompt(null);
|
|
1275
|
+
}, [runner.running]);
|
|
1098
1276
|
const controlled = value !== void 0;
|
|
1099
1277
|
const baseFlow = controlled ? makeControlledFlowAdapter(value, onChange) : internal;
|
|
1100
1278
|
const hist = useFlowHistory(baseFlow);
|
|
@@ -1404,7 +1582,7 @@ function FlowEditorInner({
|
|
|
1404
1582
|
({ autoLayout }) => flow.setGraph({ nodes: autoLayout({ nodes: flow.nodes, edges: flow.edges }, { scope: laneId }), edges: flow.edges })
|
|
1405
1583
|
);
|
|
1406
1584
|
},
|
|
1407
|
-
run: () => runner.run({ nodes: flow.nodes, edges: flow.edges },
|
|
1585
|
+
run: () => runner.run({ nodes: flow.nodes, edges: flow.edges }, runExecutors),
|
|
1408
1586
|
cancel: runner.cancel,
|
|
1409
1587
|
reset: runner.reset,
|
|
1410
1588
|
toWorkflow,
|
|
@@ -1416,7 +1594,7 @@ function FlowEditorInner({
|
|
|
1416
1594
|
canUndo: hist.canUndo,
|
|
1417
1595
|
canRedo: hist.canRedo
|
|
1418
1596
|
};
|
|
1419
|
-
}, [flow, selectedId, selected, selectedEdgeId, selectedEdge, selectedIds, selectedNodes, runner,
|
|
1597
|
+
}, [flow, selectedId, selected, selectedEdgeId, selectedEdge, selectedIds, selectedNodes, runner, runExecutors, metadata, addNode, deleteNodes, deleteEdges, duplicateSelected, alignSelected, distributeSelected, copySelection, pasteClipboard, addLane, hist, rf]);
|
|
1420
1598
|
useImperativeHandle(apiRef, () => api, [api]);
|
|
1421
1599
|
const dropHandlers = paletteDropHandlers((kindName, evt) => {
|
|
1422
1600
|
const point = rf.screenToFlowPosition({ x: evt.clientX, y: evt.clientY });
|
|
@@ -1590,7 +1768,11 @@ function FlowEditorInner({
|
|
|
1590
1768
|
onCancel: () => setLabelEdit(null)
|
|
1591
1769
|
}
|
|
1592
1770
|
),
|
|
1593
|
-
showFeed && (slots.feed ? slots.feed(api) : /* @__PURE__ */ jsx(FlowRunFeed, { entries: runner.feed, className: "ff-editor__feed" }))
|
|
1771
|
+
showFeed && (slots.feed ? slots.feed(api) : /* @__PURE__ */ jsx(FlowRunFeed, { entries: runner.feed, running: api.running, className: "ff-editor__feed" })),
|
|
1772
|
+
prompt && /* @__PURE__ */ jsx(HumanPrompt, { request: prompt, onCancel: () => {
|
|
1773
|
+
setPrompt(null);
|
|
1774
|
+
runner.cancel();
|
|
1775
|
+
} })
|
|
1594
1776
|
] }),
|
|
1595
1777
|
showPanel && (slots.panel ? slots.panel(api) : /* @__PURE__ */ jsxs("div", { className: "ff-editor__panel-wrap", children: [
|
|
1596
1778
|
/* @__PURE__ */ jsx(
|