@particle-academy/fancy-flow 0.42.0 → 0.43.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/index.cjs +84 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -1
- package/dist/index.d.ts +79 -1
- package/dist/index.js +75 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -11033,11 +11033,11 @@ function NoteNodeInner(props) {
|
|
|
11033
11033
|
const config = data.config ?? {};
|
|
11034
11034
|
const api = useFlowEditorOptional();
|
|
11035
11035
|
const hasConfigText = typeof config.text === "string" && config.text.length > 0;
|
|
11036
|
-
const
|
|
11036
|
+
const text2 = hasConfigText ? String(config.text) : typeof data.body === "string" ? data.body : typeof data.text === "string" ? data.text : "";
|
|
11037
11037
|
const title = typeof config.title === "string" && config.title || (!hasConfigText && typeof data.body === "string" && typeof data.label === "string" ? data.label : "");
|
|
11038
11038
|
const skin = NOTE_COLORS[coerceColor(config.color)];
|
|
11039
11039
|
const [editing, setEditing] = ReactExports.useState(false);
|
|
11040
|
-
const [draft, setDraft] = ReactExports.useState(
|
|
11040
|
+
const [draft, setDraft] = ReactExports.useState(text2);
|
|
11041
11041
|
const areaRef = ReactExports.useRef(null);
|
|
11042
11042
|
ReactExports.useEffect(() => {
|
|
11043
11043
|
if (editing && areaRef.current) {
|
|
@@ -11048,7 +11048,7 @@ function NoteNodeInner(props) {
|
|
|
11048
11048
|
}, [editing]);
|
|
11049
11049
|
const commit = () => {
|
|
11050
11050
|
setEditing(false);
|
|
11051
|
-
if (!api || draft ===
|
|
11051
|
+
if (!api || draft === text2) return;
|
|
11052
11052
|
const current = api.nodes.find((n) => n.id === props.id);
|
|
11053
11053
|
if (!current) return;
|
|
11054
11054
|
api.updateNode({
|
|
@@ -11062,7 +11062,7 @@ function NoteNodeInner(props) {
|
|
|
11062
11062
|
className: ["ff-note", props.selected ? "ff-note--selected" : ""].filter(Boolean).join(" "),
|
|
11063
11063
|
style: { background: skin.bg, borderColor: skin.border },
|
|
11064
11064
|
onDoubleClick: api ? () => {
|
|
11065
|
-
setDraft(
|
|
11065
|
+
setDraft(text2);
|
|
11066
11066
|
setEditing(true);
|
|
11067
11067
|
} : void 0,
|
|
11068
11068
|
children: [
|
|
@@ -11081,7 +11081,7 @@ function NoteNodeInner(props) {
|
|
|
11081
11081
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) commit();
|
|
11082
11082
|
}
|
|
11083
11083
|
}
|
|
11084
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-note__body", children:
|
|
11084
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-note__body", children: text2 || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-note__placeholder", children: api ? "Double-click to write a note\u2026" : "Note" }) })
|
|
11085
11085
|
]
|
|
11086
11086
|
}
|
|
11087
11087
|
);
|
|
@@ -12898,8 +12898,8 @@ function describeExpressionGrammar() {
|
|
|
12898
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
12899
|
};
|
|
12900
12900
|
}
|
|
12901
|
-
function findTrigger(
|
|
12902
|
-
const before =
|
|
12901
|
+
function findTrigger(text2, caret) {
|
|
12902
|
+
const before = text2.slice(0, caret);
|
|
12903
12903
|
const open = before.lastIndexOf("{{");
|
|
12904
12904
|
if (open === -1) return null;
|
|
12905
12905
|
if (before.indexOf("}}", open) !== -1) return null;
|
|
@@ -12910,9 +12910,9 @@ function filterVariables(vars, query) {
|
|
|
12910
12910
|
if (q2 === "") return vars;
|
|
12911
12911
|
return vars.filter((v2) => v2.path.toLowerCase().includes(q2));
|
|
12912
12912
|
}
|
|
12913
|
-
function applyCompletion(
|
|
12914
|
-
const head =
|
|
12915
|
-
const tail =
|
|
12913
|
+
function applyCompletion(text2, caret, trigger, variable) {
|
|
12914
|
+
const head = text2.slice(0, trigger.open);
|
|
12915
|
+
const tail = text2.slice(caret);
|
|
12916
12916
|
return { value: `${head}${variable.expression}${tail}`, caret: head.length + variable.expression.length };
|
|
12917
12917
|
}
|
|
12918
12918
|
function ExpressionField({
|
|
@@ -13436,7 +13436,7 @@ function JsonField({
|
|
|
13436
13436
|
return "";
|
|
13437
13437
|
}
|
|
13438
13438
|
}, [value]);
|
|
13439
|
-
const [
|
|
13439
|
+
const [text2, setText] = ReactExports.useState(serialized);
|
|
13440
13440
|
const [error, setError] = ReactExports.useState(null);
|
|
13441
13441
|
const [touched, setTouched] = ReactExports.useState(false);
|
|
13442
13442
|
const lastProps = ReactExports.useRef(serialized);
|
|
@@ -13474,7 +13474,7 @@ function JsonField({
|
|
|
13474
13474
|
...handle,
|
|
13475
13475
|
className: "ff-panel__input ff-panel__input--json",
|
|
13476
13476
|
rows: rows ?? 6,
|
|
13477
|
-
value:
|
|
13477
|
+
value: text2,
|
|
13478
13478
|
spellCheck: false,
|
|
13479
13479
|
"aria-invalid": showError || void 0,
|
|
13480
13480
|
"aria-describedby": showError ? errorId : void 0,
|
|
@@ -14903,8 +14903,8 @@ function FlowEditorInner({
|
|
|
14903
14903
|
x: labelEdit.x,
|
|
14904
14904
|
y: labelEdit.y,
|
|
14905
14905
|
initial: flow.edges.find((e) => e.id === labelEdit.edgeId)?.label ?? "",
|
|
14906
|
-
onCommit: (
|
|
14907
|
-
api.setEdgeLabel(labelEdit.edgeId,
|
|
14906
|
+
onCommit: (text2) => {
|
|
14907
|
+
api.setEdgeLabel(labelEdit.edgeId, text2);
|
|
14908
14908
|
setLabelEdit(null);
|
|
14909
14909
|
},
|
|
14910
14910
|
onCancel: () => setLabelEdit(null)
|
|
@@ -15009,7 +15009,7 @@ function EdgeLabelEditor({
|
|
|
15009
15009
|
onCommit,
|
|
15010
15010
|
onCancel
|
|
15011
15011
|
}) {
|
|
15012
|
-
const [
|
|
15012
|
+
const [text2, setText] = ReactExports.useState(initial);
|
|
15013
15013
|
const ref = ReactExports.useRef(null);
|
|
15014
15014
|
ReactExports.useEffect(() => {
|
|
15015
15015
|
ref.current?.focus();
|
|
@@ -15026,17 +15026,17 @@ function EdgeLabelEditor({
|
|
|
15026
15026
|
{
|
|
15027
15027
|
ref,
|
|
15028
15028
|
className: "ff-panel__input",
|
|
15029
|
-
value:
|
|
15029
|
+
value: text2,
|
|
15030
15030
|
placeholder: "Label this connection",
|
|
15031
15031
|
"aria-label": "Connection label",
|
|
15032
15032
|
"data-action": "edge-label-input",
|
|
15033
15033
|
onChange: (e) => setText(e.target.value),
|
|
15034
15034
|
onKeyDown: (e) => {
|
|
15035
15035
|
e.stopPropagation();
|
|
15036
|
-
if (e.key === "Enter") onCommit(
|
|
15036
|
+
if (e.key === "Enter") onCommit(text2);
|
|
15037
15037
|
if (e.key === "Escape") onCancel();
|
|
15038
15038
|
},
|
|
15039
|
-
onBlur: () => onCommit(
|
|
15039
|
+
onBlur: () => onCommit(text2)
|
|
15040
15040
|
}
|
|
15041
15041
|
)
|
|
15042
15042
|
}
|
|
@@ -15271,6 +15271,67 @@ var flowKeys = {
|
|
|
15271
15271
|
run: (runId) => ["flow", "runs", runId]
|
|
15272
15272
|
};
|
|
15273
15273
|
|
|
15274
|
+
// src/expressions/expr.ts
|
|
15275
|
+
var WHOLE = /^\{\{\s*([\s\S]*?)\s*\}\}$/;
|
|
15276
|
+
var EACH = /\{\{\s*([\s\S]*?)\s*\}\}/g;
|
|
15277
|
+
var FALSY_STRINGS = /* @__PURE__ */ new Set(["", "0", "false", "no", "off", "null"]);
|
|
15278
|
+
function resolvePath(path, context) {
|
|
15279
|
+
const trimmed = path.trim();
|
|
15280
|
+
if (trimmed === "") return null;
|
|
15281
|
+
const segments = trimmed.split(".");
|
|
15282
|
+
let cursor;
|
|
15283
|
+
const head = segments[0];
|
|
15284
|
+
if (head === "$json" || head === "$input") {
|
|
15285
|
+
cursor = context !== null && typeof context === "object" && "in" in context ? context.in : context;
|
|
15286
|
+
segments.shift();
|
|
15287
|
+
} else {
|
|
15288
|
+
cursor = context;
|
|
15289
|
+
}
|
|
15290
|
+
for (const segment of segments) {
|
|
15291
|
+
if (cursor === null || cursor === void 0) return null;
|
|
15292
|
+
if (typeof cursor !== "object") return null;
|
|
15293
|
+
const next = cursor[segment];
|
|
15294
|
+
if (next === void 0) return null;
|
|
15295
|
+
cursor = next;
|
|
15296
|
+
}
|
|
15297
|
+
return cursor === void 0 ? null : cursor;
|
|
15298
|
+
}
|
|
15299
|
+
function evaluateExpression(template, context) {
|
|
15300
|
+
if (typeof template !== "string") return template;
|
|
15301
|
+
const whole = WHOLE.exec(template.trim());
|
|
15302
|
+
if (whole) return resolvePath(whole[1] ?? "", context);
|
|
15303
|
+
return template.replace(EACH, (_m, path) => stringify(resolvePath(path, context)));
|
|
15304
|
+
}
|
|
15305
|
+
function truthy(value) {
|
|
15306
|
+
if (typeof value === "boolean") return value;
|
|
15307
|
+
if (value === null || value === void 0) return false;
|
|
15308
|
+
if (typeof value === "string") return !FALSY_STRINGS.has(value.trim().toLowerCase());
|
|
15309
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
15310
|
+
if (typeof value === "number") return value !== 0;
|
|
15311
|
+
return Boolean(value);
|
|
15312
|
+
}
|
|
15313
|
+
function text(value) {
|
|
15314
|
+
return stringify(value);
|
|
15315
|
+
}
|
|
15316
|
+
function stringify(value) {
|
|
15317
|
+
if (typeof value === "string") return value;
|
|
15318
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
15319
|
+
if (value === null || value === void 0) return "";
|
|
15320
|
+
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
15321
|
+
try {
|
|
15322
|
+
return JSON.stringify(value) ?? "";
|
|
15323
|
+
} catch {
|
|
15324
|
+
return "";
|
|
15325
|
+
}
|
|
15326
|
+
}
|
|
15327
|
+
function evaluateConfig(config, context) {
|
|
15328
|
+
const out = {};
|
|
15329
|
+
for (const [key, value] of Object.entries(config)) {
|
|
15330
|
+
out[key] = Array.isArray(value) ? value.map((v2) => evaluateExpression(v2, context)) : value !== null && typeof value === "object" ? evaluateConfig(value, context) : evaluateExpression(value, context);
|
|
15331
|
+
}
|
|
15332
|
+
return out;
|
|
15333
|
+
}
|
|
15334
|
+
|
|
15274
15335
|
// src/index.ts
|
|
15275
15336
|
registerBuiltinKinds();
|
|
15276
15337
|
/*! Bundled license information:
|
|
@@ -15324,6 +15385,8 @@ exports.defineNode = defineNode;
|
|
|
15324
15385
|
exports.describeExpressionGrammar = describeExpressionGrammar;
|
|
15325
15386
|
exports.distributeNodes = distributeNodes;
|
|
15326
15387
|
exports.encodePause = encodePause;
|
|
15388
|
+
exports.evaluateConfig = evaluateConfig;
|
|
15389
|
+
exports.evaluateExpression = evaluateExpression;
|
|
15327
15390
|
exports.exportWorkflow = exportWorkflow;
|
|
15328
15391
|
exports.flowKeys = flowKeys;
|
|
15329
15392
|
exports.flowLive = flowLive;
|
|
@@ -15345,9 +15408,12 @@ exports.registerBuiltinKinds = registerBuiltinKinds;
|
|
|
15345
15408
|
exports.registerNodeKind = registerNodeKind;
|
|
15346
15409
|
exports.registerRichInputAdapter = registerRichInputAdapter;
|
|
15347
15410
|
exports.resolveNodePorts = resolveNodePorts;
|
|
15411
|
+
exports.resolvePath = resolvePath;
|
|
15348
15412
|
exports.resolvePortSpec = resolvePortSpec;
|
|
15349
15413
|
exports.runCohort = runCohort;
|
|
15350
15414
|
exports.runFlow = runFlow;
|
|
15415
|
+
exports.text = text;
|
|
15416
|
+
exports.truthy = truthy;
|
|
15351
15417
|
exports.useFlowEditor = useFlowEditor;
|
|
15352
15418
|
exports.useFlowEditorOptional = useFlowEditorOptional;
|
|
15353
15419
|
exports.useFlowHistory = useFlowHistory;
|