@particle-academy/fancy-flow 0.52.0 → 0.53.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-JOXMAWAI.js → chunk-CIBW5ATA.js} +148 -5
- package/dist/chunk-CIBW5ATA.js.map +1 -0
- package/dist/{chunk-PEX3ZGCO.js → chunk-FG3C7LIG.js} +3 -3
- package/dist/{chunk-PEX3ZGCO.js.map → chunk-FG3C7LIG.js.map} +1 -1
- package/dist/{chunk-PU3CLTAG.js → chunk-FH6MWLKD.js} +3 -3
- package/dist/{chunk-PU3CLTAG.js.map → chunk-FH6MWLKD.js.map} +1 -1
- package/dist/{chunk-PWIHOR57.js → chunk-FTGVVKWX.js} +4 -4
- package/dist/{chunk-PWIHOR57.js.map → chunk-FTGVVKWX.js.map} +1 -1
- package/dist/{chunk-I7ZDPY7C.js → chunk-VWANLNL5.js} +3 -3
- package/dist/{chunk-I7ZDPY7C.js.map → chunk-VWANLNL5.js.map} +1 -1
- package/dist/{chunk-RR7A6IUW.js → chunk-WCFRKXH5.js} +3 -3
- package/dist/{chunk-RR7A6IUW.js.map → chunk-WCFRKXH5.js.map} +1 -1
- package/dist/durable.cjs +103 -2
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +1 -1
- package/dist/engine.cjs +103 -2
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.js +3 -3
- package/dist/index.cjs +218 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +84 -46
- package/dist/index.js.map +1 -1
- package/dist/registry.cjs +103 -2
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/runtime.cjs +103 -2
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema.cjs +103 -2
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/screens.cjs +103 -2
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.js +4 -4
- package/dist/ux.cjs +103 -2
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-JOXMAWAI.js.map +0 -1
package/dist/engine.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { runCohort } from './chunk-
|
|
1
|
+
export { runCohort } from './chunk-WCFRKXH5.js';
|
|
2
2
|
import { decodePause } from './chunk-UEOE6B52.js';
|
|
3
3
|
export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
|
|
4
|
-
import { runFlow, getNodeKind, resolveNodePorts } from './chunk-
|
|
5
|
-
export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-
|
|
4
|
+
import { runFlow, getNodeKind, resolveNodePorts } from './chunk-CIBW5ATA.js';
|
|
5
|
+
export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-CIBW5ATA.js';
|
|
6
6
|
import './chunk-F5RPRB7A.js';
|
|
7
7
|
import { isResolutionFailure, registerLlmClient, registerWorkflowResolver } from './chunk-USL4FMFU.js';
|
|
8
8
|
|
package/dist/index.cjs
CHANGED
|
@@ -1719,6 +1719,101 @@ var init_layout = __esm({
|
|
|
1719
1719
|
init_dagre_esm();
|
|
1720
1720
|
}
|
|
1721
1721
|
});
|
|
1722
|
+
|
|
1723
|
+
// src/components/FlowEditor/human-fields.ts
|
|
1724
|
+
var HUMAN_FIELD_TYPE_ALIASES = {
|
|
1725
|
+
text: "text",
|
|
1726
|
+
string: "text",
|
|
1727
|
+
str: "text",
|
|
1728
|
+
input: "text",
|
|
1729
|
+
textarea: "textarea",
|
|
1730
|
+
long_text: "textarea",
|
|
1731
|
+
longtext: "textarea",
|
|
1732
|
+
"long-text": "textarea",
|
|
1733
|
+
multiline: "textarea",
|
|
1734
|
+
paragraph: "textarea",
|
|
1735
|
+
markdown: "textarea",
|
|
1736
|
+
number: "number",
|
|
1737
|
+
numeric: "number",
|
|
1738
|
+
integer: "number",
|
|
1739
|
+
int: "number",
|
|
1740
|
+
float: "number",
|
|
1741
|
+
decimal: "number",
|
|
1742
|
+
select: "select",
|
|
1743
|
+
enum: "select",
|
|
1744
|
+
choice: "select",
|
|
1745
|
+
choices: "select",
|
|
1746
|
+
dropdown: "select",
|
|
1747
|
+
options: "select",
|
|
1748
|
+
radio: "select",
|
|
1749
|
+
switch: "switch",
|
|
1750
|
+
bool: "switch",
|
|
1751
|
+
boolean: "switch",
|
|
1752
|
+
checkbox: "switch",
|
|
1753
|
+
toggle: "switch",
|
|
1754
|
+
date: "date",
|
|
1755
|
+
datetime: "datetime",
|
|
1756
|
+
"datetime-local": "datetime",
|
|
1757
|
+
datetimelocal: "datetime",
|
|
1758
|
+
timestamp: "datetime",
|
|
1759
|
+
time: "time",
|
|
1760
|
+
email: "email",
|
|
1761
|
+
"e-mail": "email",
|
|
1762
|
+
url: "url",
|
|
1763
|
+
uri: "url",
|
|
1764
|
+
link: "url",
|
|
1765
|
+
tel: "tel",
|
|
1766
|
+
phone: "tel",
|
|
1767
|
+
telephone: "tel",
|
|
1768
|
+
password: "password",
|
|
1769
|
+
secret: "password"
|
|
1770
|
+
};
|
|
1771
|
+
function humanFieldType(raw) {
|
|
1772
|
+
if (typeof raw !== "string") return "text";
|
|
1773
|
+
return HUMAN_FIELD_TYPE_ALIASES[raw.trim().toLowerCase()] ?? "text";
|
|
1774
|
+
}
|
|
1775
|
+
function humanFieldOptions(raw) {
|
|
1776
|
+
const entries = [];
|
|
1777
|
+
if (Array.isArray(raw)) {
|
|
1778
|
+
for (const item of raw) {
|
|
1779
|
+
if (typeof item === "string" || typeof item === "number") {
|
|
1780
|
+
const value = String(item);
|
|
1781
|
+
if (value !== "") entries.push({ value, label: value });
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
if (item && typeof item === "object") {
|
|
1785
|
+
const value = item.value;
|
|
1786
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
1787
|
+
const label = item.label;
|
|
1788
|
+
entries.push({
|
|
1789
|
+
value: String(value),
|
|
1790
|
+
label: typeof label === "string" && label !== "" ? label : String(value)
|
|
1791
|
+
});
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
} else if (raw && typeof raw === "object") {
|
|
1795
|
+
for (const [value, label] of Object.entries(raw)) {
|
|
1796
|
+
if (value === "") continue;
|
|
1797
|
+
entries.push({ value, label: typeof label === "string" && label !== "" ? label : value });
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return entries.length ? entries : void 0;
|
|
1801
|
+
}
|
|
1802
|
+
function humanInputFields(config) {
|
|
1803
|
+
const raw = Array.isArray(config?.fields) ? config.fields : [];
|
|
1804
|
+
const fields = raw.filter((f) => f && typeof f === "object" && typeof f.key === "string" && f.key).map((f) => ({
|
|
1805
|
+
key: f.key,
|
|
1806
|
+
label: typeof f.label === "string" && f.label ? f.label : f.key,
|
|
1807
|
+
type: humanFieldType(f.type),
|
|
1808
|
+
required: !!f.required,
|
|
1809
|
+
placeholder: typeof f.placeholder === "string" ? f.placeholder : void 0,
|
|
1810
|
+
options: humanFieldOptions(f.options ?? f.choices),
|
|
1811
|
+
default: f.default
|
|
1812
|
+
}));
|
|
1813
|
+
if (fields.length) return fields;
|
|
1814
|
+
const title = typeof config?.title === "string" && config.title ? config.title : "Your answer";
|
|
1815
|
+
return [{ key: "value", label: title, type: "textarea", required: true }];
|
|
1816
|
+
}
|
|
1722
1817
|
var adapter = null;
|
|
1723
1818
|
var listeners = /* @__PURE__ */ new Set();
|
|
1724
1819
|
function registerRichInputAdapter(next) {
|
|
@@ -11448,6 +11543,20 @@ var subflowExecutor = async (ctx) => {
|
|
|
11448
11543
|
};
|
|
11449
11544
|
|
|
11450
11545
|
// src/registry/builtin.ts
|
|
11546
|
+
var HUMAN_FIELD_OUTPUT_TYPE = {
|
|
11547
|
+
text: "string",
|
|
11548
|
+
textarea: "string",
|
|
11549
|
+
select: "string",
|
|
11550
|
+
date: "string",
|
|
11551
|
+
datetime: "string",
|
|
11552
|
+
time: "string",
|
|
11553
|
+
email: "string",
|
|
11554
|
+
url: "string",
|
|
11555
|
+
tel: "string",
|
|
11556
|
+
password: "string",
|
|
11557
|
+
number: "number",
|
|
11558
|
+
switch: "boolean"
|
|
11559
|
+
};
|
|
11451
11560
|
function casePorts(cases) {
|
|
11452
11561
|
const byPort = /* @__PURE__ */ new Map();
|
|
11453
11562
|
if (cases && typeof cases === "object" && !Array.isArray(cases)) {
|
|
@@ -11545,7 +11654,17 @@ var KINDS = [
|
|
|
11545
11654
|
name: "@particle-academy/user_input",
|
|
11546
11655
|
// The keys an author declared on THIS node — the case a static list cannot
|
|
11547
11656
|
// express, and the one issue #5 named.
|
|
11548
|
-
|
|
11657
|
+
//
|
|
11658
|
+
// The TYPE comes from the same normalizer the form renders with, so the
|
|
11659
|
+
// variable picker agrees with what the run actually resolves. It used to say
|
|
11660
|
+
// `string` for every field, which was wrong the moment a field was a number
|
|
11661
|
+
// or a switch — the picker told an author `{{ $json.age }}` was text while
|
|
11662
|
+
// the form handed the next node a number.
|
|
11663
|
+
outputShape: (config) => (config.fields ?? []).filter((f) => typeof f.key === "string" && f.key !== "").map((f) => ({
|
|
11664
|
+
path: f.key,
|
|
11665
|
+
type: HUMAN_FIELD_OUTPUT_TYPE[humanFieldType(f.type)],
|
|
11666
|
+
description: f.label
|
|
11667
|
+
})),
|
|
11549
11668
|
aliases: ["user_input", "@fancy/user_input"],
|
|
11550
11669
|
pausesForHuman: "input",
|
|
11551
11670
|
category: "human",
|
|
@@ -11572,14 +11691,38 @@ var KINDS = [
|
|
|
11572
11691
|
key: "type",
|
|
11573
11692
|
label: "Type",
|
|
11574
11693
|
default: "text",
|
|
11694
|
+
// Every control `HumanPrompt` can render. A type the form supports
|
|
11695
|
+
// but the panel cannot select is reachable only by hand-editing the
|
|
11696
|
+
// workflow JSON — which is the audience this panel exists for.
|
|
11575
11697
|
options: [
|
|
11576
11698
|
{ value: "text", label: "Text" },
|
|
11577
11699
|
{ value: "textarea", label: "Long text" },
|
|
11578
11700
|
{ value: "number", label: "Number" },
|
|
11579
11701
|
{ value: "select", label: "Select" },
|
|
11580
|
-
{ value: "switch", label: "Switch" }
|
|
11702
|
+
{ value: "switch", label: "Switch (yes / no)" },
|
|
11703
|
+
{ value: "date", label: "Date" },
|
|
11704
|
+
{ value: "datetime", label: "Date + time" },
|
|
11705
|
+
{ value: "time", label: "Time" },
|
|
11706
|
+
{ value: "email", label: "Email" },
|
|
11707
|
+
{ value: "url", label: "URL" },
|
|
11708
|
+
{ value: "tel", label: "Phone" },
|
|
11709
|
+
{ value: "password", label: "Password" }
|
|
11581
11710
|
]
|
|
11582
11711
|
},
|
|
11712
|
+
{
|
|
11713
|
+
// Without this a panel-authored select had nothing to choose from,
|
|
11714
|
+
// so it rendered an empty dropdown — the type was declarable and
|
|
11715
|
+
// unusable in the same breath.
|
|
11716
|
+
type: "keyvalue",
|
|
11717
|
+
key: "options",
|
|
11718
|
+
label: "Choices",
|
|
11719
|
+
description: "Select fields only. Left is the value the flow receives, right is what the person sees.",
|
|
11720
|
+
keyLabel: "Value",
|
|
11721
|
+
valueLabel: "Label",
|
|
11722
|
+
keyPlaceholder: "small",
|
|
11723
|
+
valuePlaceholder: "Small",
|
|
11724
|
+
addLabel: "Add choice"
|
|
11725
|
+
},
|
|
11583
11726
|
{ type: "switch", key: "required", label: "Required", default: false }
|
|
11584
11727
|
],
|
|
11585
11728
|
default: [{ key: "answer", label: "Your answer", type: "textarea", required: true }]
|
|
@@ -14529,24 +14672,28 @@ function buildNodeTypes() {
|
|
|
14529
14672
|
}
|
|
14530
14673
|
return map;
|
|
14531
14674
|
}
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
if (fields.length) return fields;
|
|
14544
|
-
const title = typeof config?.title === "string" && config.title ? config.title : "Your answer";
|
|
14545
|
-
return [{ key: "value", label: title, type: "textarea", required: true }];
|
|
14546
|
-
}
|
|
14675
|
+
var INPUT_TYPE = {
|
|
14676
|
+
text: "text",
|
|
14677
|
+
number: "number",
|
|
14678
|
+
date: "date",
|
|
14679
|
+
datetime: "datetime-local",
|
|
14680
|
+
time: "time",
|
|
14681
|
+
email: "email",
|
|
14682
|
+
url: "url",
|
|
14683
|
+
tel: "tel",
|
|
14684
|
+
password: "password"
|
|
14685
|
+
};
|
|
14547
14686
|
function initialValues(fields) {
|
|
14548
14687
|
const v2 = {};
|
|
14549
|
-
for (const f of fields)
|
|
14688
|
+
for (const f of fields) {
|
|
14689
|
+
if (f.type === "switch") {
|
|
14690
|
+
v2[f.key] = !!f.default;
|
|
14691
|
+
} else if (f.type === "number") {
|
|
14692
|
+
v2[f.key] = typeof f.default === "number" ? f.default : f.default === void 0 || f.default === "" ? "" : Number(f.default);
|
|
14693
|
+
} else {
|
|
14694
|
+
v2[f.key] = f.default ?? "";
|
|
14695
|
+
}
|
|
14696
|
+
}
|
|
14550
14697
|
return v2;
|
|
14551
14698
|
}
|
|
14552
14699
|
function HumanPrompt({ request, onCancel }) {
|
|
@@ -14581,6 +14728,8 @@ function InputBody({
|
|
|
14581
14728
|
}) {
|
|
14582
14729
|
const [values, setValues] = ReactExports.useState(() => initialValues(request.fields));
|
|
14583
14730
|
const set3 = (k2, v2) => setValues((prev) => ({ ...prev, [k2]: v2 }));
|
|
14731
|
+
const uid = ReactExports.useId();
|
|
14732
|
+
const fieldId = (key) => `${uid}-${key}`;
|
|
14584
14733
|
const missing = request.fields.filter((f) => f.required && (values[f.key] === void 0 || values[f.key] === ""));
|
|
14585
14734
|
const submit = () => {
|
|
14586
14735
|
if (missing.length === 0) request.resolve(values);
|
|
@@ -14599,12 +14748,21 @@ function InputBody({
|
|
|
14599
14748
|
}
|
|
14600
14749
|
},
|
|
14601
14750
|
children: [
|
|
14602
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-prompt__fields", children: request.fields.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("
|
|
14603
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
14751
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-prompt__fields", children: request.fields.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-prompt__field", children: [
|
|
14752
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "ff-prompt__label", htmlFor: fieldId(f.key), children: [
|
|
14604
14753
|
f.label ?? f.key,
|
|
14605
|
-
f.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-prompt__req", children: " *" })
|
|
14754
|
+
f.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-prompt__req", "aria-hidden": "true", children: " *" })
|
|
14606
14755
|
] }),
|
|
14607
|
-
|
|
14756
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14757
|
+
FieldControl,
|
|
14758
|
+
{
|
|
14759
|
+
field: f,
|
|
14760
|
+
id: fieldId(f.key),
|
|
14761
|
+
value: values[f.key],
|
|
14762
|
+
onChange: (v2) => set3(f.key, v2),
|
|
14763
|
+
autoFocusRef: i === 0 ? firstRef : void 0
|
|
14764
|
+
}
|
|
14765
|
+
)
|
|
14608
14766
|
] }, f.key)) }),
|
|
14609
14767
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-prompt__actions", children: [
|
|
14610
14768
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ff-prompt__btn ff-prompt__btn--ghost", onClick: onCancel, children: "Cancel" }),
|
|
@@ -14614,45 +14772,68 @@ function InputBody({
|
|
|
14614
14772
|
}
|
|
14615
14773
|
);
|
|
14616
14774
|
}
|
|
14617
|
-
function
|
|
14618
|
-
|
|
14619
|
-
|
|
14775
|
+
function FieldControl({
|
|
14776
|
+
field,
|
|
14777
|
+
id: id2,
|
|
14778
|
+
value,
|
|
14779
|
+
onChange,
|
|
14780
|
+
autoFocusRef
|
|
14781
|
+
}) {
|
|
14782
|
+
const handle = { id: id2, "data-ff-field": field.key };
|
|
14783
|
+
if (field.type === "textarea") {
|
|
14620
14784
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14621
14785
|
"textarea",
|
|
14622
14786
|
{
|
|
14623
|
-
...
|
|
14624
|
-
|
|
14787
|
+
...handle,
|
|
14788
|
+
className: "ff-prompt__input",
|
|
14789
|
+
placeholder: field.placeholder,
|
|
14790
|
+
ref: autoFocusRef,
|
|
14625
14791
|
rows: 3,
|
|
14626
14792
|
value: String(value ?? ""),
|
|
14627
14793
|
onChange: (e) => onChange(e.target.value)
|
|
14628
14794
|
}
|
|
14629
14795
|
);
|
|
14630
14796
|
}
|
|
14631
|
-
if (
|
|
14797
|
+
if (field.type === "switch") {
|
|
14632
14798
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14633
14799
|
"input",
|
|
14634
14800
|
{
|
|
14801
|
+
...handle,
|
|
14635
14802
|
type: "checkbox",
|
|
14636
14803
|
className: "ff-prompt__switch",
|
|
14804
|
+
ref: autoFocusRef,
|
|
14637
14805
|
checked: !!value,
|
|
14638
14806
|
onChange: (e) => onChange(e.target.checked)
|
|
14639
14807
|
}
|
|
14640
14808
|
);
|
|
14641
14809
|
}
|
|
14642
|
-
if (
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14810
|
+
if (field.type === "select") {
|
|
14811
|
+
const options = field.options ?? [];
|
|
14812
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14813
|
+
"select",
|
|
14814
|
+
{
|
|
14815
|
+
...handle,
|
|
14816
|
+
className: "ff-prompt__input",
|
|
14817
|
+
ref: autoFocusRef,
|
|
14818
|
+
value: String(value ?? ""),
|
|
14819
|
+
onChange: (e) => onChange(e.target.value),
|
|
14820
|
+
children: [
|
|
14821
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: options.length ? "Choose\u2026" : "No choices configured" }),
|
|
14822
|
+
options.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
14823
|
+
]
|
|
14824
|
+
}
|
|
14825
|
+
);
|
|
14647
14826
|
}
|
|
14648
14827
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14649
14828
|
"input",
|
|
14650
14829
|
{
|
|
14651
|
-
...
|
|
14652
|
-
|
|
14653
|
-
|
|
14830
|
+
...handle,
|
|
14831
|
+
className: "ff-prompt__input",
|
|
14832
|
+
placeholder: field.placeholder,
|
|
14833
|
+
ref: autoFocusRef,
|
|
14834
|
+
type: INPUT_TYPE[field.type ?? "text"] ?? "text",
|
|
14654
14835
|
value: String(value ?? ""),
|
|
14655
|
-
onChange: (e) => onChange(
|
|
14836
|
+
onChange: (e) => onChange(field.type === "number" ? e.target.value === "" ? "" : Number(e.target.value) : e.target.value)
|
|
14656
14837
|
}
|
|
14657
14838
|
);
|
|
14658
14839
|
}
|