@particle-academy/fancy-flow 0.40.4 → 0.42.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/ConfigFieldRenderer-BHQDZer6.d.ts +92 -0
- package/dist/ConfigFieldRenderer-LotNHeG8.d.cts +92 -0
- package/dist/{chunk-UX65ML3J.js → chunk-55KQS3LK.js} +25 -2
- package/dist/chunk-55KQS3LK.js.map +1 -0
- package/dist/{chunk-WOO4B7M5.js → chunk-T3VQX3XB.js} +3 -3
- package/dist/{chunk-WOO4B7M5.js.map → chunk-T3VQX3XB.js.map} +1 -1
- package/dist/engine.d.cts +3 -3
- package/dist/engine.d.ts +3 -3
- package/dist/fields/react-fancy.cjs +40 -0
- package/dist/fields/react-fancy.cjs.map +1 -0
- package/dist/fields/react-fancy.d.cts +20 -0
- package/dist/fields/react-fancy.d.ts +20 -0
- package/dist/fields/react-fancy.js +37 -0
- package/dist/fields/react-fancy.js.map +1 -0
- package/dist/index.cjs +343 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -127
- package/dist/index.d.ts +105 -127
- package/dist/index.js +320 -38
- package/dist/index.js.map +1 -1
- package/dist/registry/index.d.cts +3 -3
- package/dist/registry/index.d.ts +3 -3
- package/dist/{registry-BADFn97n.d.cts → registry-C9KMVpn7.d.cts} +1 -1
- package/dist/{registry-DYbFLEcW.d.ts → registry-FGCBprcn.d.ts} +1 -1
- package/dist/registry.cjs +23 -0
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +1 -1
- package/dist/screens.js +3 -3
- package/dist/styles.css +99 -0
- package/dist/styles.css.map +1 -1
- package/dist/{types-D8Dezh9v.d.cts → types-B78Rm69S.d.cts} +94 -2
- package/dist/{types-D6lsIGoe.d.ts → types-JViq8reb.d.ts} +94 -2
- package/dist/ux.d.cts +1 -1
- package/dist/ux.d.ts +1 -1
- package/package.json +12 -2
- package/dist/chunk-UX65ML3J.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -11496,6 +11496,9 @@ var KINDS = [
|
|
|
11496
11496
|
},
|
|
11497
11497
|
{
|
|
11498
11498
|
name: "@particle-academy/user_input",
|
|
11499
|
+
// The keys an author declared on THIS node — the case a static list cannot
|
|
11500
|
+
// express, and the one issue #5 named.
|
|
11501
|
+
outputShape: (config) => (config.fields ?? []).filter((f) => typeof f.key === "string" && f.key !== "").map((f) => ({ path: f.key, type: "string", description: f.label })),
|
|
11499
11502
|
aliases: ["user_input", "@fancy/user_input"],
|
|
11500
11503
|
pausesForHuman: "input",
|
|
11501
11504
|
category: "human",
|
|
@@ -11716,6 +11719,10 @@ var KINDS = [
|
|
|
11716
11719
|
},
|
|
11717
11720
|
{
|
|
11718
11721
|
name: "@particle-academy/for_each",
|
|
11722
|
+
outputShape: [
|
|
11723
|
+
{ path: "items", type: "array" },
|
|
11724
|
+
{ path: "count", type: "number" }
|
|
11725
|
+
],
|
|
11719
11726
|
aliases: ["for_each", "@fancy/for_each"],
|
|
11720
11727
|
category: "logic",
|
|
11721
11728
|
label: "For Each",
|
|
@@ -11879,6 +11886,12 @@ var KINDS = [
|
|
|
11879
11886
|
// ───────────── AI ─────────────
|
|
11880
11887
|
{
|
|
11881
11888
|
name: "@particle-academy/llm_call",
|
|
11889
|
+
// LlmClient::complete() -> array{text:string,usage?:array,raw?:mixed}
|
|
11890
|
+
outputShape: [
|
|
11891
|
+
{ path: "text", type: "string", description: "The model's completion." },
|
|
11892
|
+
{ path: "usage", type: "object", description: "Token counts, when the provider reports them." },
|
|
11893
|
+
{ path: "raw", type: "unknown", description: "The provider's untouched response." }
|
|
11894
|
+
],
|
|
11882
11895
|
aliases: ["llm_call", "@fancy/llm_call"],
|
|
11883
11896
|
category: "ai",
|
|
11884
11897
|
label: "LLM Call",
|
|
@@ -12013,6 +12026,10 @@ var KINDS = [
|
|
|
12013
12026
|
},
|
|
12014
12027
|
{
|
|
12015
12028
|
name: "@particle-academy/embed_search",
|
|
12029
|
+
outputShape: [
|
|
12030
|
+
{ path: "query", type: "string" },
|
|
12031
|
+
{ path: "matches", type: "array", description: "Ranked results from the vector store." }
|
|
12032
|
+
],
|
|
12016
12033
|
aliases: ["embed_search", "@fancy/embed_search"],
|
|
12017
12034
|
category: "ai",
|
|
12018
12035
|
label: "Embed & Search",
|
|
@@ -12027,6 +12044,12 @@ var KINDS = [
|
|
|
12027
12044
|
// ───────────── IO ─────────────
|
|
12028
12045
|
{
|
|
12029
12046
|
name: "@particle-academy/api_request",
|
|
12047
|
+
// HttpClient::send() -> array{status:int,headers:array,body:mixed}
|
|
12048
|
+
outputShape: [
|
|
12049
|
+
{ path: "status", type: "number", description: "HTTP status code." },
|
|
12050
|
+
{ path: "headers", type: "object" },
|
|
12051
|
+
{ path: "body", type: "unknown", description: "Decoded JSON when the response is JSON, otherwise the raw body." }
|
|
12052
|
+
],
|
|
12030
12053
|
aliases: ["api_request", "@fancy/api_request"],
|
|
12031
12054
|
category: "io",
|
|
12032
12055
|
label: "API Request",
|
|
@@ -12811,6 +12834,230 @@ function paletteDropHandlers(onDrop) {
|
|
|
12811
12834
|
}
|
|
12812
12835
|
};
|
|
12813
12836
|
}
|
|
12837
|
+
|
|
12838
|
+
// src/expressions/variables.ts
|
|
12839
|
+
var ROOT = "$json";
|
|
12840
|
+
function expr(path) {
|
|
12841
|
+
return `{{ ${path} }}`;
|
|
12842
|
+
}
|
|
12843
|
+
function outputFieldsFor(node) {
|
|
12844
|
+
const kindName = node.data?.kind ?? node.type;
|
|
12845
|
+
if (!kindName) return [];
|
|
12846
|
+
const kind = getNodeKind(kindName);
|
|
12847
|
+
const shape = kind?.outputShape;
|
|
12848
|
+
if (!shape) return [];
|
|
12849
|
+
if (typeof shape === "function") {
|
|
12850
|
+
try {
|
|
12851
|
+
const config = node.data?.config ?? {};
|
|
12852
|
+
return shape(config) ?? [];
|
|
12853
|
+
} catch {
|
|
12854
|
+
return [];
|
|
12855
|
+
}
|
|
12856
|
+
}
|
|
12857
|
+
return shape;
|
|
12858
|
+
}
|
|
12859
|
+
function baseVariables() {
|
|
12860
|
+
return [
|
|
12861
|
+
{ expression: expr(ROOT), path: ROOT, type: "unknown", description: "The whole incoming value." }
|
|
12862
|
+
];
|
|
12863
|
+
}
|
|
12864
|
+
function availableVariables(graph, nodeId) {
|
|
12865
|
+
const out = baseVariables();
|
|
12866
|
+
const seen = /* @__PURE__ */ new Set([ROOT]);
|
|
12867
|
+
const byId = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
12868
|
+
const upstreamIds = graph.edges.filter((e) => e.target === nodeId).map((e) => e.source);
|
|
12869
|
+
for (const id2 of upstreamIds) {
|
|
12870
|
+
if (id2 === nodeId) continue;
|
|
12871
|
+
const upstream = byId.get(id2);
|
|
12872
|
+
if (!upstream) continue;
|
|
12873
|
+
const kindName = upstream.data?.kind ?? upstream.type;
|
|
12874
|
+
const label = upstream.data?.label ?? (kindName ? getNodeKind(kindName)?.label : void 0);
|
|
12875
|
+
for (const field of outputFieldsFor(upstream)) {
|
|
12876
|
+
const path = `${ROOT}.${field.path}`;
|
|
12877
|
+
if (seen.has(path)) continue;
|
|
12878
|
+
seen.add(path);
|
|
12879
|
+
out.push({
|
|
12880
|
+
expression: expr(path),
|
|
12881
|
+
path,
|
|
12882
|
+
type: field.type,
|
|
12883
|
+
description: field.description,
|
|
12884
|
+
source: label
|
|
12885
|
+
});
|
|
12886
|
+
}
|
|
12887
|
+
}
|
|
12888
|
+
return out;
|
|
12889
|
+
}
|
|
12890
|
+
function describeExpressionGrammar() {
|
|
12891
|
+
return {
|
|
12892
|
+
forms: [
|
|
12893
|
+
{ syntax: "{{ $json }}", meaning: "The whole value arriving on this node's input." },
|
|
12894
|
+
{ syntax: "{{ $json.field }}", meaning: "One key of that value. Dot-paths nest: $json.user.email." },
|
|
12895
|
+
{ syntax: "{{ $input.field }}", meaning: "An alias for $json \u2014 the same value, either spelling." },
|
|
12896
|
+
{ syntax: "{{ in }}", meaning: "The input by its context key, rather than through the alias." }
|
|
12897
|
+
],
|
|
12898
|
+
note: "Dot-paths only \u2014 no arithmetic, comparisons or function calls; anything else resolves to nothing. A field that is exactly one expression keeps the resolved value's type; mixed text interpolates as a string. fancy-flow's own runFlow does not interpolate: it hands config to your executor verbatim, and the fancy-flow-php runtime is what resolves these."
|
|
12899
|
+
};
|
|
12900
|
+
}
|
|
12901
|
+
function findTrigger(text, caret) {
|
|
12902
|
+
const before = text.slice(0, caret);
|
|
12903
|
+
const open = before.lastIndexOf("{{");
|
|
12904
|
+
if (open === -1) return null;
|
|
12905
|
+
if (before.indexOf("}}", open) !== -1) return null;
|
|
12906
|
+
return { open, query: before.slice(open + 2).trim() };
|
|
12907
|
+
}
|
|
12908
|
+
function filterVariables(vars, query) {
|
|
12909
|
+
const q2 = query.trim().toLowerCase();
|
|
12910
|
+
if (q2 === "") return vars;
|
|
12911
|
+
return vars.filter((v2) => v2.path.toLowerCase().includes(q2));
|
|
12912
|
+
}
|
|
12913
|
+
function applyCompletion(text, caret, trigger, variable) {
|
|
12914
|
+
const head = text.slice(0, trigger.open);
|
|
12915
|
+
const tail = text.slice(caret);
|
|
12916
|
+
return { value: `${head}${variable.expression}${tail}`, caret: head.length + variable.expression.length };
|
|
12917
|
+
}
|
|
12918
|
+
function ExpressionField({
|
|
12919
|
+
value,
|
|
12920
|
+
onChange,
|
|
12921
|
+
placeholder,
|
|
12922
|
+
rows = 2,
|
|
12923
|
+
handle,
|
|
12924
|
+
graph,
|
|
12925
|
+
nodeId
|
|
12926
|
+
}) {
|
|
12927
|
+
const ref = ReactExports.useRef(null);
|
|
12928
|
+
const [trigger, setTrigger] = ReactExports.useState(null);
|
|
12929
|
+
const [active, setActive] = ReactExports.useState(0);
|
|
12930
|
+
const [showHelp, setShowHelp] = ReactExports.useState(false);
|
|
12931
|
+
const variables = ReactExports.useMemo(
|
|
12932
|
+
() => graph && nodeId ? availableVariables(graph, nodeId) : baseVariables(),
|
|
12933
|
+
[graph, nodeId]
|
|
12934
|
+
);
|
|
12935
|
+
const matches = ReactExports.useMemo(
|
|
12936
|
+
() => trigger ? filterVariables(variables, trigger.query) : [],
|
|
12937
|
+
[trigger, variables]
|
|
12938
|
+
);
|
|
12939
|
+
const help = ReactExports.useMemo(() => describeExpressionGrammar(), []);
|
|
12940
|
+
const open = trigger !== null && matches.length > 0;
|
|
12941
|
+
const sync = (el) => {
|
|
12942
|
+
const next = findTrigger(el.value, el.selectionStart ?? el.value.length);
|
|
12943
|
+
setTrigger(next);
|
|
12944
|
+
setActive(0);
|
|
12945
|
+
};
|
|
12946
|
+
const choose = (variable) => {
|
|
12947
|
+
const el = ref.current;
|
|
12948
|
+
if (!el || !trigger) return;
|
|
12949
|
+
const { value: next, caret } = applyCompletion(
|
|
12950
|
+
el.value,
|
|
12951
|
+
el.selectionStart ?? el.value.length,
|
|
12952
|
+
trigger,
|
|
12953
|
+
variable
|
|
12954
|
+
);
|
|
12955
|
+
onChange(next);
|
|
12956
|
+
setTrigger(null);
|
|
12957
|
+
requestAnimationFrame(() => {
|
|
12958
|
+
el.focus();
|
|
12959
|
+
el.setSelectionRange(caret, caret);
|
|
12960
|
+
});
|
|
12961
|
+
};
|
|
12962
|
+
const onKeyDown = (e) => {
|
|
12963
|
+
if (!open) return;
|
|
12964
|
+
if (e.key === "ArrowDown") {
|
|
12965
|
+
e.preventDefault();
|
|
12966
|
+
setActive((i) => (i + 1) % matches.length);
|
|
12967
|
+
} else if (e.key === "ArrowUp") {
|
|
12968
|
+
e.preventDefault();
|
|
12969
|
+
setActive((i) => (i - 1 + matches.length) % matches.length);
|
|
12970
|
+
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
12971
|
+
e.preventDefault();
|
|
12972
|
+
choose(matches[active] ?? matches[0]);
|
|
12973
|
+
} else if (e.key === "Escape") {
|
|
12974
|
+
e.preventDefault();
|
|
12975
|
+
setTrigger(null);
|
|
12976
|
+
}
|
|
12977
|
+
};
|
|
12978
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-expression", "data-ff-expression": handle["data-ff-field"], children: [
|
|
12979
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12980
|
+
"textarea",
|
|
12981
|
+
{
|
|
12982
|
+
...handle,
|
|
12983
|
+
ref,
|
|
12984
|
+
className: "ff-panel__input ff-panel__input--expression",
|
|
12985
|
+
rows,
|
|
12986
|
+
value: value ?? "",
|
|
12987
|
+
placeholder: placeholder ?? "{{ $json.field }}",
|
|
12988
|
+
spellCheck: false,
|
|
12989
|
+
role: "combobox",
|
|
12990
|
+
"aria-expanded": open,
|
|
12991
|
+
"aria-autocomplete": "list",
|
|
12992
|
+
"aria-controls": open ? `${handle.id ?? handle["data-ff-field"]}-vars` : void 0,
|
|
12993
|
+
onChange: (e) => {
|
|
12994
|
+
onChange(e.target.value);
|
|
12995
|
+
sync(e.target);
|
|
12996
|
+
},
|
|
12997
|
+
onKeyDown,
|
|
12998
|
+
onClick: (e) => sync(e.currentTarget),
|
|
12999
|
+
onBlur: () => {
|
|
13000
|
+
window.setTimeout(() => setTrigger(null), 120);
|
|
13001
|
+
}
|
|
13002
|
+
}
|
|
13003
|
+
),
|
|
13004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-expression__bar", children: [
|
|
13005
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13006
|
+
"button",
|
|
13007
|
+
{
|
|
13008
|
+
type: "button",
|
|
13009
|
+
className: "ff-expression__helpbtn",
|
|
13010
|
+
"aria-expanded": showHelp,
|
|
13011
|
+
onClick: () => setShowHelp((s) => !s),
|
|
13012
|
+
children: [
|
|
13013
|
+
"{{ }}",
|
|
13014
|
+
" reference"
|
|
13015
|
+
]
|
|
13016
|
+
}
|
|
13017
|
+
),
|
|
13018
|
+
variables.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ff-expression__hint", children: [
|
|
13019
|
+
"type ",
|
|
13020
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "{{" }),
|
|
13021
|
+
" for ",
|
|
13022
|
+
variables.length,
|
|
13023
|
+
" variables"
|
|
13024
|
+
] })
|
|
13025
|
+
] }),
|
|
13026
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13027
|
+
"ul",
|
|
13028
|
+
{
|
|
13029
|
+
className: "ff-expression__menu",
|
|
13030
|
+
id: `${handle.id ?? handle["data-ff-field"]}-vars`,
|
|
13031
|
+
role: "listbox",
|
|
13032
|
+
"data-ff-expression-menu": handle["data-ff-field"],
|
|
13033
|
+
children: matches.map((v2, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { role: "option", "aria-selected": i === active, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13034
|
+
"button",
|
|
13035
|
+
{
|
|
13036
|
+
type: "button",
|
|
13037
|
+
className: `ff-expression__option${i === active ? " is-active" : ""}`,
|
|
13038
|
+
"data-ff-expression-option": v2.path,
|
|
13039
|
+
onMouseDown: (e) => {
|
|
13040
|
+
e.preventDefault();
|
|
13041
|
+
choose(v2);
|
|
13042
|
+
},
|
|
13043
|
+
children: [
|
|
13044
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "ff-expression__path", children: v2.path }),
|
|
13045
|
+
v2.source && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-expression__source", children: v2.source }),
|
|
13046
|
+
v2.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-expression__desc", children: v2.description })
|
|
13047
|
+
]
|
|
13048
|
+
}
|
|
13049
|
+
) }, v2.expression))
|
|
13050
|
+
}
|
|
13051
|
+
),
|
|
13052
|
+
showHelp && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-expression__help", role: "note", "data-ff-expression-help": true, children: [
|
|
13053
|
+
/* @__PURE__ */ jsxRuntime.jsx("dl", { children: help.forms.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
13054
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: f.syntax }) }),
|
|
13055
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: f.meaning })
|
|
13056
|
+
] }, f.syntax)) }),
|
|
13057
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "ff-expression__note", children: help.note })
|
|
13058
|
+
] })
|
|
13059
|
+
] });
|
|
13060
|
+
}
|
|
12814
13061
|
function ConfigFieldRenderer({
|
|
12815
13062
|
field,
|
|
12816
13063
|
value,
|
|
@@ -12818,7 +13065,9 @@ function ConfigFieldRenderer({
|
|
|
12818
13065
|
id: id2,
|
|
12819
13066
|
renderCredentialField,
|
|
12820
13067
|
renderDocumentField,
|
|
12821
|
-
fieldRenderers
|
|
13068
|
+
fieldRenderers,
|
|
13069
|
+
graph,
|
|
13070
|
+
nodeId
|
|
12822
13071
|
}) {
|
|
12823
13072
|
const handle = { id: id2, "data-ff-field": field.key };
|
|
12824
13073
|
const custom = fieldRenderers?.[field.type];
|
|
@@ -12897,18 +13146,17 @@ function ConfigFieldRenderer({
|
|
|
12897
13146
|
}
|
|
12898
13147
|
);
|
|
12899
13148
|
case "json":
|
|
12900
|
-
return /* @__PURE__ */ jsxRuntime.jsx(JsonField, { value, onChange, rows: field.rows });
|
|
13149
|
+
return /* @__PURE__ */ jsxRuntime.jsx(JsonField, { value, onChange, rows: field.rows, handle });
|
|
12901
13150
|
case "expression":
|
|
12902
13151
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12903
|
-
|
|
13152
|
+
ExpressionField,
|
|
12904
13153
|
{
|
|
12905
|
-
|
|
12906
|
-
className: "ff-panel__input ff-panel__input--expression",
|
|
12907
|
-
rows: 2,
|
|
13154
|
+
handle,
|
|
12908
13155
|
value: value ?? "",
|
|
13156
|
+
onChange,
|
|
12909
13157
|
placeholder: field.example ?? "{{ $json.field }}",
|
|
12910
|
-
|
|
12911
|
-
|
|
13158
|
+
graph,
|
|
13159
|
+
nodeId
|
|
12912
13160
|
}
|
|
12913
13161
|
);
|
|
12914
13162
|
case "credential":
|
|
@@ -12929,16 +13177,19 @@ function ConfigFieldRenderer({
|
|
|
12929
13177
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12930
13178
|
RepeaterField,
|
|
12931
13179
|
{
|
|
13180
|
+
id: id2,
|
|
12932
13181
|
field,
|
|
12933
13182
|
value,
|
|
12934
13183
|
onChange,
|
|
12935
13184
|
renderCredentialField,
|
|
12936
13185
|
renderDocumentField,
|
|
12937
|
-
fieldRenderers
|
|
13186
|
+
fieldRenderers,
|
|
13187
|
+
graph,
|
|
13188
|
+
nodeId
|
|
12938
13189
|
}
|
|
12939
13190
|
);
|
|
12940
13191
|
case "keyvalue":
|
|
12941
|
-
return /* @__PURE__ */ jsxRuntime.jsx(KeyValueField, { field, value, onChange });
|
|
13192
|
+
return /* @__PURE__ */ jsxRuntime.jsx(KeyValueField, { id: id2, field, value, onChange });
|
|
12942
13193
|
case "document":
|
|
12943
13194
|
if (renderDocumentField) {
|
|
12944
13195
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderDocumentField({ documentType: field.documentType, value, onChange }) });
|
|
@@ -12983,9 +13234,12 @@ function ChoiceField({
|
|
|
12983
13234
|
);
|
|
12984
13235
|
}
|
|
12985
13236
|
function RepeaterField({
|
|
13237
|
+
id: id2,
|
|
12986
13238
|
field,
|
|
12987
13239
|
value,
|
|
12988
13240
|
onChange,
|
|
13241
|
+
graph,
|
|
13242
|
+
nodeId,
|
|
12989
13243
|
renderCredentialField,
|
|
12990
13244
|
renderDocumentField,
|
|
12991
13245
|
fieldRenderers
|
|
@@ -13017,7 +13271,7 @@ function RepeaterField({
|
|
|
13017
13271
|
if (typeof raw === "number" || typeof raw === "boolean") return String(raw);
|
|
13018
13272
|
return `Item ${i + 1}`;
|
|
13019
13273
|
};
|
|
13020
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-repeater", "data-ff-repeater": field.key, children: [
|
|
13274
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { id: id2, role: "group", className: "ff-repeater", "data-ff-repeater": field.key, "data-ff-field": field.key, children: [
|
|
13021
13275
|
rows.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ff-repeater__empty", children: "None yet." }),
|
|
13022
13276
|
rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-repeater__row", "data-ff-repeater-row": i, children: [
|
|
13023
13277
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-repeater__row-head", children: [
|
|
@@ -13066,6 +13320,8 @@ function RepeaterField({
|
|
|
13066
13320
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13067
13321
|
ConfigFieldRenderer,
|
|
13068
13322
|
{
|
|
13323
|
+
graph,
|
|
13324
|
+
nodeId,
|
|
13069
13325
|
field: sub,
|
|
13070
13326
|
value: row[sub.key],
|
|
13071
13327
|
onChange: (cell) => setCell(i, sub.key, cell),
|
|
@@ -13092,6 +13348,7 @@ function RepeaterField({
|
|
|
13092
13348
|
] });
|
|
13093
13349
|
}
|
|
13094
13350
|
function KeyValueField({
|
|
13351
|
+
id: id2,
|
|
13095
13352
|
field,
|
|
13096
13353
|
value,
|
|
13097
13354
|
onChange
|
|
@@ -13110,7 +13367,7 @@ function KeyValueField({
|
|
|
13110
13367
|
const setVal = (i, val) => commit(entries.map(([k2, v2], idx) => idx === i ? [k2, val] : [k2, v2]));
|
|
13111
13368
|
const remove2 = (i) => commit(entries.filter((_2, idx) => idx !== i));
|
|
13112
13369
|
const add = () => commit([...entries, ["", ""]]);
|
|
13113
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-keyvalue", "data-ff-keyvalue": field.key, children: [
|
|
13370
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { id: id2, role: "group", className: "ff-keyvalue", "data-ff-keyvalue": field.key, "data-ff-field": field.key, children: [
|
|
13114
13371
|
entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-keyvalue__head", children: [
|
|
13115
13372
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: field.keyLabel ?? "Key" }),
|
|
13116
13373
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: field.valueLabel ?? "Value" }),
|
|
@@ -13166,34 +13423,76 @@ function KeyValueField({
|
|
|
13166
13423
|
] })
|
|
13167
13424
|
] });
|
|
13168
13425
|
}
|
|
13169
|
-
function JsonField({
|
|
13170
|
-
|
|
13426
|
+
function JsonField({
|
|
13427
|
+
value,
|
|
13428
|
+
onChange,
|
|
13429
|
+
rows,
|
|
13430
|
+
handle
|
|
13431
|
+
}) {
|
|
13432
|
+
const serialized = ReactExports.useMemo(() => {
|
|
13171
13433
|
try {
|
|
13172
13434
|
return value === void 0 ? "" : JSON.stringify(value, null, 2);
|
|
13173
13435
|
} catch {
|
|
13174
13436
|
return "";
|
|
13175
13437
|
}
|
|
13176
13438
|
}, [value]);
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13439
|
+
const [text, setText] = ReactExports.useState(serialized);
|
|
13440
|
+
const [error, setError] = ReactExports.useState(null);
|
|
13441
|
+
const [touched, setTouched] = ReactExports.useState(false);
|
|
13442
|
+
const lastProps = ReactExports.useRef(serialized);
|
|
13443
|
+
const committed = ReactExports.useRef(null);
|
|
13444
|
+
if (serialized !== lastProps.current) {
|
|
13445
|
+
lastProps.current = serialized;
|
|
13446
|
+
if (serialized !== committed.current) {
|
|
13447
|
+
setText(serialized);
|
|
13448
|
+
setError(null);
|
|
13449
|
+
setTouched(false);
|
|
13450
|
+
}
|
|
13451
|
+
}
|
|
13452
|
+
const commit = (next) => {
|
|
13453
|
+
const trimmed = next.trim();
|
|
13454
|
+
if (trimmed === "") {
|
|
13455
|
+
committed.current = "";
|
|
13456
|
+
onChange(void 0);
|
|
13457
|
+
return null;
|
|
13458
|
+
}
|
|
13459
|
+
try {
|
|
13460
|
+
const parsed = JSON.parse(trimmed);
|
|
13461
|
+
committed.current = JSON.stringify(parsed, null, 2);
|
|
13462
|
+
onChange(parsed);
|
|
13463
|
+
return null;
|
|
13464
|
+
} catch (e) {
|
|
13465
|
+
return e instanceof Error ? e.message : "Invalid JSON";
|
|
13466
|
+
}
|
|
13467
|
+
};
|
|
13468
|
+
const errorId = handle.id ? `${handle.id}-error` : void 0;
|
|
13469
|
+
const showError = touched && error !== null;
|
|
13470
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
13471
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13472
|
+
"textarea",
|
|
13473
|
+
{
|
|
13474
|
+
...handle,
|
|
13475
|
+
className: "ff-panel__input ff-panel__input--json",
|
|
13476
|
+
rows: rows ?? 6,
|
|
13477
|
+
value: text,
|
|
13478
|
+
spellCheck: false,
|
|
13479
|
+
"aria-invalid": showError || void 0,
|
|
13480
|
+
"aria-describedby": showError ? errorId : void 0,
|
|
13481
|
+
onChange: (e) => {
|
|
13482
|
+
setText(e.target.value);
|
|
13483
|
+
setError(commit(e.target.value));
|
|
13484
|
+
},
|
|
13485
|
+
onBlur: (e) => {
|
|
13486
|
+
setTouched(true);
|
|
13487
|
+
setError(commit(e.target.value));
|
|
13193
13488
|
}
|
|
13194
13489
|
}
|
|
13195
|
-
|
|
13196
|
-
|
|
13490
|
+
),
|
|
13491
|
+
showError && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ff-panel__issue ff-panel__issue--field", id: errorId, role: "alert", children: [
|
|
13492
|
+
"\u26A0 ",
|
|
13493
|
+
error
|
|
13494
|
+
] })
|
|
13495
|
+
] });
|
|
13197
13496
|
}
|
|
13198
13497
|
function NodeConfigPanel({
|
|
13199
13498
|
node,
|
|
@@ -13204,6 +13503,7 @@ function NodeConfigPanel({
|
|
|
13204
13503
|
renderCredentialField,
|
|
13205
13504
|
renderDocumentField,
|
|
13206
13505
|
fieldRenderers,
|
|
13506
|
+
graph,
|
|
13207
13507
|
className,
|
|
13208
13508
|
style: style2
|
|
13209
13509
|
}) {
|
|
@@ -13309,7 +13609,9 @@ function NodeConfigPanel({
|
|
|
13309
13609
|
onChange: (v2) => setConfigValue(field.key, v2),
|
|
13310
13610
|
renderCredentialField,
|
|
13311
13611
|
renderDocumentField: documentField,
|
|
13312
|
-
fieldRenderers
|
|
13612
|
+
fieldRenderers,
|
|
13613
|
+
graph,
|
|
13614
|
+
nodeId: node.id
|
|
13313
13615
|
}
|
|
13314
13616
|
)
|
|
13315
13617
|
] }, field.key))
|
|
@@ -14061,6 +14363,7 @@ function FlowEditorInner({
|
|
|
14061
14363
|
metadata,
|
|
14062
14364
|
showPalette = true,
|
|
14063
14365
|
showPanel = true,
|
|
14366
|
+
fieldRenderers,
|
|
14064
14367
|
showFeed = true,
|
|
14065
14368
|
extraToolbar,
|
|
14066
14369
|
actions = [],
|
|
@@ -14620,6 +14923,8 @@ function FlowEditorInner({
|
|
|
14620
14923
|
className: "ff-editor__panel",
|
|
14621
14924
|
node: api.selected,
|
|
14622
14925
|
onChange: api.updateNode,
|
|
14926
|
+
fieldRenderers,
|
|
14927
|
+
graph: flow,
|
|
14623
14928
|
onDelete: builtins.delete === false ? void 0 : (n) => api.deleteNodes([n.id])
|
|
14624
14929
|
}
|
|
14625
14930
|
),
|
|
@@ -14979,6 +15284,7 @@ exports.ActionNode = ActionNode;
|
|
|
14979
15284
|
exports.BUILTIN_KINDS = BUILTIN_KINDS;
|
|
14980
15285
|
exports.ConfigFieldRenderer = ConfigFieldRenderer;
|
|
14981
15286
|
exports.DecisionNode = DecisionNode;
|
|
15287
|
+
exports.ExpressionField = ExpressionField;
|
|
14982
15288
|
exports.FlowCanvas = FlowCanvas;
|
|
14983
15289
|
exports.FlowEditor = FlowEditor;
|
|
14984
15290
|
exports.FlowRunControls = FlowRunControls;
|
|
@@ -15002,6 +15308,8 @@ exports.WORKFLOW_SCHEMA_VERSION = WORKFLOW_SCHEMA_VERSION;
|
|
|
15002
15308
|
exports.alignNodes = alignNodes;
|
|
15003
15309
|
exports.applyOutputsToNodes = applyOutputsToNodes;
|
|
15004
15310
|
exports.applyStatusesToNodes = applyStatusesToNodes;
|
|
15311
|
+
exports.availableVariables = availableVariables;
|
|
15312
|
+
exports.baseVariables = baseVariables;
|
|
15005
15313
|
exports.buildNodeTypes = buildNodeTypes;
|
|
15006
15314
|
exports.categoryAccent = categoryAccent;
|
|
15007
15315
|
exports.clearNodeKindOverrides = clearNodeKindOverrides;
|
|
@@ -15013,6 +15321,7 @@ exports.defaultConfigFor = defaultConfigFor;
|
|
|
15013
15321
|
exports.defaultNodeTypes = defaultNodeTypes;
|
|
15014
15322
|
exports.defaultPortCompatibility = defaultPortCompatibility;
|
|
15015
15323
|
exports.defineNode = defineNode;
|
|
15324
|
+
exports.describeExpressionGrammar = describeExpressionGrammar;
|
|
15016
15325
|
exports.distributeNodes = distributeNodes;
|
|
15017
15326
|
exports.encodePause = encodePause;
|
|
15018
15327
|
exports.exportWorkflow = exportWorkflow;
|
|
@@ -15027,6 +15336,7 @@ exports.listNodeKinds = listNodeKinds;
|
|
|
15027
15336
|
exports.migrateSchema = migrateSchema;
|
|
15028
15337
|
exports.onNodeKindsChanged = onNodeKindsChanged;
|
|
15029
15338
|
exports.onRichInputAdapterChanged = onRichInputAdapterChanged;
|
|
15339
|
+
exports.outputFieldsFor = outputFieldsFor;
|
|
15030
15340
|
exports.overrideNodeKind = overrideNodeKind;
|
|
15031
15341
|
exports.paletteDropHandlers = paletteDropHandlers;
|
|
15032
15342
|
exports.pauseForHuman = pauseForHuman;
|