@particle-academy/fancy-flow 0.53.0 → 0.55.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-Bc9Txnql.d.cts → HumanPrompt-CPl-Spmp.d.cts} +75 -1
- package/dist/{ConfigFieldRenderer-Bt3RGT7Z.d.ts → HumanPrompt-DlJSFi3F.d.ts} +75 -1
- package/dist/{chunk-CIBW5ATA.js → chunk-22OJOD4X.js} +7 -3
- package/dist/chunk-22OJOD4X.js.map +1 -0
- package/dist/{chunk-VWANLNL5.js → chunk-E3AGYTHP.js} +3 -3
- package/dist/{chunk-VWANLNL5.js.map → chunk-E3AGYTHP.js.map} +1 -1
- package/dist/{chunk-FTGVVKWX.js → chunk-HMEI2LFU.js} +4 -4
- package/dist/{chunk-FTGVVKWX.js.map → chunk-HMEI2LFU.js.map} +1 -1
- package/dist/{chunk-WCFRKXH5.js → chunk-KP4TBF3A.js} +3 -3
- package/dist/{chunk-WCFRKXH5.js.map → chunk-KP4TBF3A.js.map} +1 -1
- package/dist/{chunk-FG3C7LIG.js → chunk-L4QAAGLV.js} +3 -3
- package/dist/{chunk-FG3C7LIG.js.map → chunk-L4QAAGLV.js.map} +1 -1
- package/dist/{chunk-FH6MWLKD.js → chunk-YVLOLS25.js} +3 -3
- package/dist/{chunk-FH6MWLKD.js.map → chunk-YVLOLS25.js.map} +1 -1
- package/dist/durable/index.d.cts +1 -1
- package/dist/durable/index.d.ts +1 -1
- package/dist/durable.cjs +5 -1
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +1 -1
- package/dist/engine.cjs +5 -1
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +2 -2
- package/dist/engine.d.ts +2 -2
- package/dist/engine.js +3 -3
- package/dist/fields/react-fancy.cjs +66 -0
- package/dist/fields/react-fancy.cjs.map +1 -1
- package/dist/fields/react-fancy.d.cts +35 -2
- package/dist/fields/react-fancy.d.ts +35 -2
- package/dist/fields/react-fancy.js +67 -2
- package/dist/fields/react-fancy.js.map +1 -1
- package/dist/index.cjs +34 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +40 -20
- package/dist/index.js.map +1 -1
- package/dist/registry.cjs +5 -1
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/{run-cohort-BPIOpE8A.d.ts → run-cohort-C1nRh_mi.d.ts} +1 -1
- package/dist/{run-cohort-r-L8dMED.d.cts → run-cohort-CBRAUj-z.d.cts} +1 -1
- package/dist/{run-flow-COdAOFg2.d.cts → run-flow-2XsHBwpd.d.cts} +31 -0
- package/dist/{run-flow-DJ7KYT6E.d.ts → run-flow-D7AOCcfE.d.ts} +31 -0
- package/dist/runtime/index.d.cts +3 -3
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime.cjs +5 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema.cjs +5 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/screens.cjs +5 -1
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.js +4 -4
- package/dist/ux.cjs +5 -1
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-CIBW5ATA.js.map +0 -1
package/dist/engine.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-
|
|
1
|
+
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-2XsHBwpd.cjs';
|
|
2
2
|
import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-JFYjPJAG.cjs';
|
|
3
3
|
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-JFYjPJAG.cjs';
|
|
4
|
-
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-
|
|
4
|
+
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-CBRAUj-z.cjs';
|
|
5
5
|
export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-C6TMfiD_.cjs';
|
|
6
6
|
export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-3sPauVRT.cjs';
|
|
7
7
|
import { P as PauseAwaiting } from './pause-9iT4tCEV.cjs';
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-
|
|
1
|
+
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-D7AOCcfE.js';
|
|
2
2
|
import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-JFYjPJAG.js';
|
|
3
3
|
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-JFYjPJAG.js';
|
|
4
|
-
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-
|
|
4
|
+
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-C1nRh_mi.js';
|
|
5
5
|
export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-3RkSYrMi.js';
|
|
6
6
|
export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-s643U1Hi.js';
|
|
7
7
|
import { P as PauseAwaiting } from './pause-9iT4tCEV.js';
|
package/dist/engine.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { runCohort } from './chunk-
|
|
1
|
+
export { runCohort } from './chunk-KP4TBF3A.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-22OJOD4X.js';
|
|
5
|
+
export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-22OJOD4X.js';
|
|
6
6
|
import './chunk-F5RPRB7A.js';
|
|
7
7
|
import { isResolutionFailure, registerLlmClient, registerWorkflowResolver } from './chunk-USL4FMFU.js';
|
|
8
8
|
|
|
@@ -33,7 +33,73 @@ var jsonFieldRenderer = ({
|
|
|
33
33
|
var reactFancyFieldRenderers = {
|
|
34
34
|
json: jsonFieldRenderer
|
|
35
35
|
};
|
|
36
|
+
var humanFieldRenderers = {
|
|
37
|
+
text: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
reactFancy.Input,
|
|
39
|
+
{
|
|
40
|
+
id,
|
|
41
|
+
"data-ff-field": field.key,
|
|
42
|
+
ref: autoFocusRef,
|
|
43
|
+
placeholder: field.placeholder,
|
|
44
|
+
value: String(value ?? ""),
|
|
45
|
+
onValueChange: onChange
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
textarea: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
49
|
+
reactFancy.Textarea,
|
|
50
|
+
{
|
|
51
|
+
id,
|
|
52
|
+
"data-ff-field": field.key,
|
|
53
|
+
ref: autoFocusRef,
|
|
54
|
+
placeholder: field.placeholder,
|
|
55
|
+
rows: 3,
|
|
56
|
+
value: String(value ?? ""),
|
|
57
|
+
onValueChange: onChange
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
number: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
61
|
+
reactFancy.Input,
|
|
62
|
+
{
|
|
63
|
+
id,
|
|
64
|
+
"data-ff-field": field.key,
|
|
65
|
+
ref: autoFocusRef,
|
|
66
|
+
type: "number",
|
|
67
|
+
placeholder: field.placeholder,
|
|
68
|
+
value: String(value ?? ""),
|
|
69
|
+
onValueChange: (v) => onChange(v === "" ? "" : Number(v))
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
select: ({ field, id, value, onChange }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
73
|
+
reactFancy.Select,
|
|
74
|
+
{
|
|
75
|
+
id,
|
|
76
|
+
"data-ff-field": field.key,
|
|
77
|
+
list: (field.options ?? []).map((o) => ({ value: o.value, label: o.label })),
|
|
78
|
+
value: String(value ?? ""),
|
|
79
|
+
onValueChange: onChange
|
|
80
|
+
}
|
|
81
|
+
),
|
|
82
|
+
switch: ({ field, id, value, onChange }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
83
|
+
reactFancy.Switch,
|
|
84
|
+
{
|
|
85
|
+
id,
|
|
86
|
+
"data-ff-field": field.key,
|
|
87
|
+
checked: !!value,
|
|
88
|
+
onCheckedChange: onChange
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
date: ({ field, id, value, onChange }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
92
|
+
reactFancy.DatePicker,
|
|
93
|
+
{
|
|
94
|
+
id,
|
|
95
|
+
"data-ff-field": field.key,
|
|
96
|
+
value: String(value ?? ""),
|
|
97
|
+
onValueChange: onChange
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
};
|
|
36
101
|
|
|
102
|
+
exports.humanFieldRenderers = humanFieldRenderers;
|
|
37
103
|
exports.jsonFieldRenderer = jsonFieldRenderer;
|
|
38
104
|
exports.reactFancyFieldRenderers = reactFancyFieldRenderers;
|
|
39
105
|
//# sourceMappingURL=react-fancy.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/react-fancy.tsx"],"names":["jsx","JsonEditor"],"mappings":";;;;;;AA6CO,IAAM,oBAAyC,CAAC;AAAA,EACrD,KAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAAgC;AAC9B,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ,OAAO,IAAA;AAElC,EAAA;AAAA;AAAA;AAAA;AAAA,oBAIEA,cAAA;AAAA,MAACC,qBAAA;AAAA,MAAA;AAAA,QAIC,EAAA;AAAA,QACA,iBAAe,KAAA,CAAM,GAAA;AAAA,QACrB,KAAA,EAAQ,SAAS,EAAC;AAAA,QAClB,QAAA,EAAU,CAAC,IAAA,KAAoB,QAAA,CAAS,IAAI,CAAA;AAAA,QAI5C,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,IAAA,EAAK,MAAA;AAAA,QACL,IAAA,EAAK,IAAA;AAAA,QACL,WAAW,KAAA,CAAM;AAAA;AAAA;AACnB;AAEJ;AAKO,IAAM,wBAAA,GAAgE;AAAA,EAC3E,IAAA,EAAM;AACR","file":"react-fancy.cjs","sourcesContent":["/**\n * `@particle-academy/fancy-flow/fields/react-fancy` — richer config fields for\n * hosts that already run react-fancy.\n *\n * ```tsx\n * import { reactFancyFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … fieldRenderers={reactFancyFieldRenderers} />\n * ```\n *\n * ## Why an opt-in subpath rather than the panel itself\n *\n * fancy-flow themes every surface through a `--ff-*` custom-property layer that\n * a host overrides on `.ff-editor`. react-fancy's primitives are hardcoded\n * Tailwind palette classes and read no custom properties — so building them\n * into the panel would trade the theming contract for a nicer widget, which is\n * the trade `panel-labels.test.tsx` already decided against.\n *\n * Making it a subpath keeps both: react-fancy stays an OPTIONAL peer, a\n * standalone install pays nothing, and a Tailwind host opts in with one prop.\n * Same shape as `/llm/vercel-ai` and `/rich-input`.\n *\n * ## What it currently covers\n *\n * Just `json`, because that is the only built-in whose fallback is a raw\n * textarea. The others are already purpose-built controls; replacing them would\n * be churn. This is a map, so a host can spread it and add their own:\n *\n * ```tsx\n * fieldRenderers={{ ...reactFancyFieldRenderers, \"trigger-filters\": myRenderer }}\n * ```\n */\nimport { JsonEditor, type JsonValue } from \"@particle-academy/react-fancy\";\nimport type {\n ConfigFieldRenderContext,\n ConfigFieldRenderFn,\n} from \"../components/NodeConfigPanel/ConfigFieldRenderer\";\n\n/**\n * Render a `json` config field as a react-fancy `JsonEditor`.\n *\n * Returns `null` for every other field type — the seam treats `null` as \"not\n * mine\", so this can be handed over wholesale without claiming controls it has\n * no business replacing.\n */\nexport const jsonFieldRenderer: ConfigFieldRenderFn = ({\n field,\n value,\n onChange,\n id,\n}: ConfigFieldRenderContext) => {\n if (field.type !== \"json\") return null;\n\n return (\n // JSX rather than `createElement` for one concrete reason: `data-*` props\n // are special-cased by JSX but hit excess-property checking in a\n // `createElement` object literal, so the agent handle would not typecheck.\n <JsonEditor\n // The panel's `<label htmlFor>` points at this id, and the Human+\n // contract wants a stable handle an agent can target without guessing at\n // the DOM. Both reach the editor's root element via its rest spread.\n id={id}\n data-ff-field={field.key}\n value={(value ?? {}) as JsonValue}\n onChange={(next: JsonValue) => onChange(next)}\n // `keyMap` is what makes this more than a prettier textarea: it declares\n // a type per path, which picks the control and reports contradictions. A\n // string by design, so it survives an MCP round-trip.\n keyMap={field.keyMap}\n mode=\"edit\"\n size=\"sm\"\n rootLabel={field.label}\n />\n );\n};\n\n/**\n * The full renderer map. Spread it to add your own types alongside.\n */\nexport const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn> = {\n json: jsonFieldRenderer,\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/react-fancy.tsx"],"names":["jsx","JsonEditor","Input","Textarea","Select","Switch","DatePicker"],"mappings":"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","file":"react-fancy.cjs","sourcesContent":["/**\n * `@particle-academy/fancy-flow/fields/react-fancy` — richer config fields for\n * hosts that already run react-fancy.\n *\n * ```tsx\n * import { reactFancyFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … fieldRenderers={reactFancyFieldRenderers} />\n * ```\n *\n * ## Why an opt-in subpath rather than the panel itself\n *\n * fancy-flow themes every surface through a `--ff-*` custom-property layer that\n * a host overrides on `.ff-editor`. react-fancy's primitives are hardcoded\n * Tailwind palette classes and read no custom properties — so building them\n * into the panel would trade the theming contract for a nicer widget, which is\n * the trade `panel-labels.test.tsx` already decided against.\n *\n * Making it a subpath keeps both: react-fancy stays an OPTIONAL peer, a\n * standalone install pays nothing, and a Tailwind host opts in with one prop.\n * Same shape as `/llm/vercel-ai` and `/rich-input`.\n *\n * ## What it currently covers\n *\n * Just `json`, because that is the only built-in whose fallback is a raw\n * textarea. The others are already purpose-built controls; replacing them would\n * be churn. This is a map, so a host can spread it and add their own:\n *\n * ```tsx\n * fieldRenderers={{ ...reactFancyFieldRenderers, \"trigger-filters\": myRenderer }}\n * ```\n */\nimport {\n DatePicker,\n Input,\n JsonEditor,\n Select,\n Switch,\n Textarea,\n type JsonValue,\n} from \"@particle-academy/react-fancy\";\nimport type {\n ConfigFieldRenderContext,\n ConfigFieldRenderFn,\n} from \"../components/NodeConfigPanel/ConfigFieldRenderer\";\nimport type { HumanFieldRenderers } from \"../components/FlowEditor/HumanPrompt\";\n\n/**\n * Render a `json` config field as a react-fancy `JsonEditor`.\n *\n * Returns `null` for every other field type — the seam treats `null` as \"not\n * mine\", so this can be handed over wholesale without claiming controls it has\n * no business replacing.\n */\nexport const jsonFieldRenderer: ConfigFieldRenderFn = ({\n field,\n value,\n onChange,\n id,\n}: ConfigFieldRenderContext) => {\n if (field.type !== \"json\") return null;\n\n return (\n // JSX rather than `createElement` for one concrete reason: `data-*` props\n // are special-cased by JSX but hit excess-property checking in a\n // `createElement` object literal, so the agent handle would not typecheck.\n <JsonEditor\n // The panel's `<label htmlFor>` points at this id, and the Human+\n // contract wants a stable handle an agent can target without guessing at\n // the DOM. Both reach the editor's root element via its rest spread.\n id={id}\n data-ff-field={field.key}\n value={(value ?? {}) as JsonValue}\n onChange={(next: JsonValue) => onChange(next)}\n // `keyMap` is what makes this more than a prettier textarea: it declares\n // a type per path, which picks the control and reports contradictions. A\n // string by design, so it survives an MCP round-trip.\n keyMap={field.keyMap}\n mode=\"edit\"\n size=\"sm\"\n rootLabel={field.label}\n />\n );\n};\n\n/**\n * The full renderer map. Spread it to add your own types alongside.\n */\nexport const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn> = {\n json: jsonFieldRenderer,\n};\n\n/* ------------------------------------------------------------------------- *\n * Pause-form controls\n * ------------------------------------------------------------------------- */\n\n/**\n * react-fancy controls for the `user_input` / `human_approval` pause form.\n *\n * ```tsx\n * import { humanFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … humanFieldRenderers={humanFieldRenderers} />\n * ```\n *\n * ## Why this is opt-in rather than the default\n *\n * Rule 2 of the suite says our surfaces compose react-fancy rather than\n * hand-rolling what a primitive already covers, and the pause form's built-ins\n * are native elements. That is not a gap in the kit — react-fancy has every\n * primitive needed — it is a PACKAGING constraint: react-fancy is an OPTIONAL\n * peer, `HumanPrompt` ships in the main entry, and importing it there would\n * make a standalone `npm install @particle-academy/fancy-flow` fail to resolve\n * at import time while bypassing the `--ff-*` token layer hosts theme\n * `.ff-editor` with.\n *\n * This map is how a host that HAS react-fancy gets the Fancy controls anyway,\n * with one prop and no cost to anyone else. Same shape and same reasoning as\n * `reactFancyFieldRenderers` above.\n *\n * ## What it covers, and what it deliberately does not\n *\n * `datetime` is absent: react-fancy's `DatePicker` is date-only, so claiming\n * the type here would render a control that silently drops the time half of a\n * value the field promised to collect. It falls through to the built-in\n * `<input type=\"datetime-local\">`, which does collect it. An honest gap beats a\n * control that looks right and loses data.\n */\nexport const humanFieldRenderers: HumanFieldRenderers = {\n text: ({ field, id, value, onChange, autoFocusRef }) => (\n <Input\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLInputElement> | undefined}\n placeholder={field.placeholder}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n textarea: ({ field, id, value, onChange, autoFocusRef }) => (\n <Textarea\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLTextAreaElement> | undefined}\n placeholder={field.placeholder}\n rows={3}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n number: ({ field, id, value, onChange, autoFocusRef }) => (\n <Input\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLInputElement> | undefined}\n type=\"number\"\n placeholder={field.placeholder}\n value={String(value ?? \"\")}\n // The built-in resolves a number field to a NUMBER, so this must too --\n // the value here is what resumes the paused run, and handing the next\n // node \"41\" where it resolved 41 before is a silent type change that no\n // test downstream would attribute to a renderer swap.\n onValueChange={(v) => onChange(v === \"\" ? \"\" : Number(v))}\n />\n ),\n\n select: ({ field, id, value, onChange }) => (\n <Select\n id={id}\n data-ff-field={field.key}\n list={(field.options ?? []).map((o) => ({ value: o.value, label: o.label }))}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n switch: ({ field, id, value, onChange }) => (\n <Switch\n id={id}\n data-ff-field={field.key}\n checked={!!value}\n onCheckedChange={onChange}\n />\n ),\n\n date: ({ field, id, value, onChange }) => (\n <DatePicker\n id={id}\n data-ff-field={field.key}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n};\n\n/*\n * `time` and `datetime` are ABSENT on purpose, and for different reasons.\n *\n * `datetime`: react-fancy's `DatePicker` is date-only. Claiming the type here\n * would render a control that silently drops the time half of a value the field\n * promised to collect.\n *\n * `time`: `TimePicker` accepts NO `id` and no `data-*` passthrough --\n * `TimePickerProps` is a closed interface of nine props, none of them an\n * identifier. It therefore cannot satisfy the two handles every control in this\n * form owes: the `id` its `<label htmlFor>` points at, and the `data-ff-field`\n * an agent drives the surface by. Wrapping it in a handle-bearing div would put\n * the label on a non-focusable element, which is worse than not claiming it.\n *\n * Both fall through to the built-in `<input type=\"time\">` /\n * `<input type=\"datetime-local\">`, which do carry the handles and do collect\n * the whole value. An honest gap beats a control that looks right and loses\n * either data or its handle.\n *\n * The `TimePicker` half is a react-fancy FINDING rather than a fancy-flow\n * limitation -- per the suite's second rule, a missing primitive capability is\n * filed against the kit rather than routed around locally.\n */\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ConfigFieldRenderFn } from '../
|
|
1
|
+
import { H as HumanFieldRenderers, C as ConfigFieldRenderFn } from '../HumanPrompt-CPl-Spmp.cjs';
|
|
2
2
|
import 'react';
|
|
3
3
|
import '../types-JFYjPJAG.cjs';
|
|
4
4
|
import '@xyflow/react';
|
|
@@ -17,5 +17,38 @@ declare const jsonFieldRenderer: ConfigFieldRenderFn;
|
|
|
17
17
|
* The full renderer map. Spread it to add your own types alongside.
|
|
18
18
|
*/
|
|
19
19
|
declare const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn>;
|
|
20
|
+
/**
|
|
21
|
+
* react-fancy controls for the `user_input` / `human_approval` pause form.
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { humanFieldRenderers } from "@particle-academy/fancy-flow/fields/react-fancy";
|
|
25
|
+
*
|
|
26
|
+
* <FlowEditor … humanFieldRenderers={humanFieldRenderers} />
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ## Why this is opt-in rather than the default
|
|
30
|
+
*
|
|
31
|
+
* Rule 2 of the suite says our surfaces compose react-fancy rather than
|
|
32
|
+
* hand-rolling what a primitive already covers, and the pause form's built-ins
|
|
33
|
+
* are native elements. That is not a gap in the kit — react-fancy has every
|
|
34
|
+
* primitive needed — it is a PACKAGING constraint: react-fancy is an OPTIONAL
|
|
35
|
+
* peer, `HumanPrompt` ships in the main entry, and importing it there would
|
|
36
|
+
* make a standalone `npm install @particle-academy/fancy-flow` fail to resolve
|
|
37
|
+
* at import time while bypassing the `--ff-*` token layer hosts theme
|
|
38
|
+
* `.ff-editor` with.
|
|
39
|
+
*
|
|
40
|
+
* This map is how a host that HAS react-fancy gets the Fancy controls anyway,
|
|
41
|
+
* with one prop and no cost to anyone else. Same shape and same reasoning as
|
|
42
|
+
* `reactFancyFieldRenderers` above.
|
|
43
|
+
*
|
|
44
|
+
* ## What it covers, and what it deliberately does not
|
|
45
|
+
*
|
|
46
|
+
* `datetime` is absent: react-fancy's `DatePicker` is date-only, so claiming
|
|
47
|
+
* the type here would render a control that silently drops the time half of a
|
|
48
|
+
* value the field promised to collect. It falls through to the built-in
|
|
49
|
+
* `<input type="datetime-local">`, which does collect it. An honest gap beats a
|
|
50
|
+
* control that looks right and loses data.
|
|
51
|
+
*/
|
|
52
|
+
declare const humanFieldRenderers: HumanFieldRenderers;
|
|
20
53
|
|
|
21
|
-
export { jsonFieldRenderer, reactFancyFieldRenderers };
|
|
54
|
+
export { humanFieldRenderers, jsonFieldRenderer, reactFancyFieldRenderers };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ConfigFieldRenderFn } from '../
|
|
1
|
+
import { H as HumanFieldRenderers, C as ConfigFieldRenderFn } from '../HumanPrompt-DlJSFi3F.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import '../types-JFYjPJAG.js';
|
|
4
4
|
import '@xyflow/react';
|
|
@@ -17,5 +17,38 @@ declare const jsonFieldRenderer: ConfigFieldRenderFn;
|
|
|
17
17
|
* The full renderer map. Spread it to add your own types alongside.
|
|
18
18
|
*/
|
|
19
19
|
declare const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn>;
|
|
20
|
+
/**
|
|
21
|
+
* react-fancy controls for the `user_input` / `human_approval` pause form.
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { humanFieldRenderers } from "@particle-academy/fancy-flow/fields/react-fancy";
|
|
25
|
+
*
|
|
26
|
+
* <FlowEditor … humanFieldRenderers={humanFieldRenderers} />
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ## Why this is opt-in rather than the default
|
|
30
|
+
*
|
|
31
|
+
* Rule 2 of the suite says our surfaces compose react-fancy rather than
|
|
32
|
+
* hand-rolling what a primitive already covers, and the pause form's built-ins
|
|
33
|
+
* are native elements. That is not a gap in the kit — react-fancy has every
|
|
34
|
+
* primitive needed — it is a PACKAGING constraint: react-fancy is an OPTIONAL
|
|
35
|
+
* peer, `HumanPrompt` ships in the main entry, and importing it there would
|
|
36
|
+
* make a standalone `npm install @particle-academy/fancy-flow` fail to resolve
|
|
37
|
+
* at import time while bypassing the `--ff-*` token layer hosts theme
|
|
38
|
+
* `.ff-editor` with.
|
|
39
|
+
*
|
|
40
|
+
* This map is how a host that HAS react-fancy gets the Fancy controls anyway,
|
|
41
|
+
* with one prop and no cost to anyone else. Same shape and same reasoning as
|
|
42
|
+
* `reactFancyFieldRenderers` above.
|
|
43
|
+
*
|
|
44
|
+
* ## What it covers, and what it deliberately does not
|
|
45
|
+
*
|
|
46
|
+
* `datetime` is absent: react-fancy's `DatePicker` is date-only, so claiming
|
|
47
|
+
* the type here would render a control that silently drops the time half of a
|
|
48
|
+
* value the field promised to collect. It falls through to the built-in
|
|
49
|
+
* `<input type="datetime-local">`, which does collect it. An honest gap beats a
|
|
50
|
+
* control that looks right and loses data.
|
|
51
|
+
*/
|
|
52
|
+
declare const humanFieldRenderers: HumanFieldRenderers;
|
|
20
53
|
|
|
21
|
-
export { jsonFieldRenderer, reactFancyFieldRenderers };
|
|
54
|
+
export { humanFieldRenderers, jsonFieldRenderer, reactFancyFieldRenderers };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JsonEditor } from '@particle-academy/react-fancy';
|
|
1
|
+
import { JsonEditor, DatePicker, Switch, Select, Input, Textarea } from '@particle-academy/react-fancy';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
// src/fields/react-fancy.tsx
|
|
@@ -31,7 +31,72 @@ var jsonFieldRenderer = ({
|
|
|
31
31
|
var reactFancyFieldRenderers = {
|
|
32
32
|
json: jsonFieldRenderer
|
|
33
33
|
};
|
|
34
|
+
var humanFieldRenderers = {
|
|
35
|
+
text: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsx(
|
|
36
|
+
Input,
|
|
37
|
+
{
|
|
38
|
+
id,
|
|
39
|
+
"data-ff-field": field.key,
|
|
40
|
+
ref: autoFocusRef,
|
|
41
|
+
placeholder: field.placeholder,
|
|
42
|
+
value: String(value ?? ""),
|
|
43
|
+
onValueChange: onChange
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
textarea: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsx(
|
|
47
|
+
Textarea,
|
|
48
|
+
{
|
|
49
|
+
id,
|
|
50
|
+
"data-ff-field": field.key,
|
|
51
|
+
ref: autoFocusRef,
|
|
52
|
+
placeholder: field.placeholder,
|
|
53
|
+
rows: 3,
|
|
54
|
+
value: String(value ?? ""),
|
|
55
|
+
onValueChange: onChange
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
number: ({ field, id, value, onChange, autoFocusRef }) => /* @__PURE__ */ jsx(
|
|
59
|
+
Input,
|
|
60
|
+
{
|
|
61
|
+
id,
|
|
62
|
+
"data-ff-field": field.key,
|
|
63
|
+
ref: autoFocusRef,
|
|
64
|
+
type: "number",
|
|
65
|
+
placeholder: field.placeholder,
|
|
66
|
+
value: String(value ?? ""),
|
|
67
|
+
onValueChange: (v) => onChange(v === "" ? "" : Number(v))
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
select: ({ field, id, value, onChange }) => /* @__PURE__ */ jsx(
|
|
71
|
+
Select,
|
|
72
|
+
{
|
|
73
|
+
id,
|
|
74
|
+
"data-ff-field": field.key,
|
|
75
|
+
list: (field.options ?? []).map((o) => ({ value: o.value, label: o.label })),
|
|
76
|
+
value: String(value ?? ""),
|
|
77
|
+
onValueChange: onChange
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
switch: ({ field, id, value, onChange }) => /* @__PURE__ */ jsx(
|
|
81
|
+
Switch,
|
|
82
|
+
{
|
|
83
|
+
id,
|
|
84
|
+
"data-ff-field": field.key,
|
|
85
|
+
checked: !!value,
|
|
86
|
+
onCheckedChange: onChange
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
date: ({ field, id, value, onChange }) => /* @__PURE__ */ jsx(
|
|
90
|
+
DatePicker,
|
|
91
|
+
{
|
|
92
|
+
id,
|
|
93
|
+
"data-ff-field": field.key,
|
|
94
|
+
value: String(value ?? ""),
|
|
95
|
+
onValueChange: onChange
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
};
|
|
34
99
|
|
|
35
|
-
export { jsonFieldRenderer, reactFancyFieldRenderers };
|
|
100
|
+
export { humanFieldRenderers, jsonFieldRenderer, reactFancyFieldRenderers };
|
|
36
101
|
//# sourceMappingURL=react-fancy.js.map
|
|
37
102
|
//# sourceMappingURL=react-fancy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/react-fancy.tsx"],"names":[],"mappings":";;;;AA6CO,IAAM,oBAAyC,CAAC;AAAA,EACrD,KAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAAgC;AAC9B,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ,OAAO,IAAA;AAElC,EAAA;AAAA;AAAA;AAAA;AAAA,oBAIE,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QAIC,EAAA;AAAA,QACA,iBAAe,KAAA,CAAM,GAAA;AAAA,QACrB,KAAA,EAAQ,SAAS,EAAC;AAAA,QAClB,QAAA,EAAU,CAAC,IAAA,KAAoB,QAAA,CAAS,IAAI,CAAA;AAAA,QAI5C,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,IAAA,EAAK,MAAA;AAAA,QACL,IAAA,EAAK,IAAA;AAAA,QACL,WAAW,KAAA,CAAM;AAAA;AAAA;AACnB;AAEJ;AAKO,IAAM,wBAAA,GAAgE;AAAA,EAC3E,IAAA,EAAM;AACR","file":"react-fancy.js","sourcesContent":["/**\n * `@particle-academy/fancy-flow/fields/react-fancy` — richer config fields for\n * hosts that already run react-fancy.\n *\n * ```tsx\n * import { reactFancyFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … fieldRenderers={reactFancyFieldRenderers} />\n * ```\n *\n * ## Why an opt-in subpath rather than the panel itself\n *\n * fancy-flow themes every surface through a `--ff-*` custom-property layer that\n * a host overrides on `.ff-editor`. react-fancy's primitives are hardcoded\n * Tailwind palette classes and read no custom properties — so building them\n * into the panel would trade the theming contract for a nicer widget, which is\n * the trade `panel-labels.test.tsx` already decided against.\n *\n * Making it a subpath keeps both: react-fancy stays an OPTIONAL peer, a\n * standalone install pays nothing, and a Tailwind host opts in with one prop.\n * Same shape as `/llm/vercel-ai` and `/rich-input`.\n *\n * ## What it currently covers\n *\n * Just `json`, because that is the only built-in whose fallback is a raw\n * textarea. The others are already purpose-built controls; replacing them would\n * be churn. This is a map, so a host can spread it and add their own:\n *\n * ```tsx\n * fieldRenderers={{ ...reactFancyFieldRenderers, \"trigger-filters\": myRenderer }}\n * ```\n */\nimport { JsonEditor, type JsonValue } from \"@particle-academy/react-fancy\";\nimport type {\n ConfigFieldRenderContext,\n ConfigFieldRenderFn,\n} from \"../components/NodeConfigPanel/ConfigFieldRenderer\";\n\n/**\n * Render a `json` config field as a react-fancy `JsonEditor`.\n *\n * Returns `null` for every other field type — the seam treats `null` as \"not\n * mine\", so this can be handed over wholesale without claiming controls it has\n * no business replacing.\n */\nexport const jsonFieldRenderer: ConfigFieldRenderFn = ({\n field,\n value,\n onChange,\n id,\n}: ConfigFieldRenderContext) => {\n if (field.type !== \"json\") return null;\n\n return (\n // JSX rather than `createElement` for one concrete reason: `data-*` props\n // are special-cased by JSX but hit excess-property checking in a\n // `createElement` object literal, so the agent handle would not typecheck.\n <JsonEditor\n // The panel's `<label htmlFor>` points at this id, and the Human+\n // contract wants a stable handle an agent can target without guessing at\n // the DOM. Both reach the editor's root element via its rest spread.\n id={id}\n data-ff-field={field.key}\n value={(value ?? {}) as JsonValue}\n onChange={(next: JsonValue) => onChange(next)}\n // `keyMap` is what makes this more than a prettier textarea: it declares\n // a type per path, which picks the control and reports contradictions. A\n // string by design, so it survives an MCP round-trip.\n keyMap={field.keyMap}\n mode=\"edit\"\n size=\"sm\"\n rootLabel={field.label}\n />\n );\n};\n\n/**\n * The full renderer map. Spread it to add your own types alongside.\n */\nexport const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn> = {\n json: jsonFieldRenderer,\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/react-fancy.tsx"],"names":[],"mappings":"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","file":"react-fancy.js","sourcesContent":["/**\n * `@particle-academy/fancy-flow/fields/react-fancy` — richer config fields for\n * hosts that already run react-fancy.\n *\n * ```tsx\n * import { reactFancyFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … fieldRenderers={reactFancyFieldRenderers} />\n * ```\n *\n * ## Why an opt-in subpath rather than the panel itself\n *\n * fancy-flow themes every surface through a `--ff-*` custom-property layer that\n * a host overrides on `.ff-editor`. react-fancy's primitives are hardcoded\n * Tailwind palette classes and read no custom properties — so building them\n * into the panel would trade the theming contract for a nicer widget, which is\n * the trade `panel-labels.test.tsx` already decided against.\n *\n * Making it a subpath keeps both: react-fancy stays an OPTIONAL peer, a\n * standalone install pays nothing, and a Tailwind host opts in with one prop.\n * Same shape as `/llm/vercel-ai` and `/rich-input`.\n *\n * ## What it currently covers\n *\n * Just `json`, because that is the only built-in whose fallback is a raw\n * textarea. The others are already purpose-built controls; replacing them would\n * be churn. This is a map, so a host can spread it and add their own:\n *\n * ```tsx\n * fieldRenderers={{ ...reactFancyFieldRenderers, \"trigger-filters\": myRenderer }}\n * ```\n */\nimport {\n DatePicker,\n Input,\n JsonEditor,\n Select,\n Switch,\n Textarea,\n type JsonValue,\n} from \"@particle-academy/react-fancy\";\nimport type {\n ConfigFieldRenderContext,\n ConfigFieldRenderFn,\n} from \"../components/NodeConfigPanel/ConfigFieldRenderer\";\nimport type { HumanFieldRenderers } from \"../components/FlowEditor/HumanPrompt\";\n\n/**\n * Render a `json` config field as a react-fancy `JsonEditor`.\n *\n * Returns `null` for every other field type — the seam treats `null` as \"not\n * mine\", so this can be handed over wholesale without claiming controls it has\n * no business replacing.\n */\nexport const jsonFieldRenderer: ConfigFieldRenderFn = ({\n field,\n value,\n onChange,\n id,\n}: ConfigFieldRenderContext) => {\n if (field.type !== \"json\") return null;\n\n return (\n // JSX rather than `createElement` for one concrete reason: `data-*` props\n // are special-cased by JSX but hit excess-property checking in a\n // `createElement` object literal, so the agent handle would not typecheck.\n <JsonEditor\n // The panel's `<label htmlFor>` points at this id, and the Human+\n // contract wants a stable handle an agent can target without guessing at\n // the DOM. Both reach the editor's root element via its rest spread.\n id={id}\n data-ff-field={field.key}\n value={(value ?? {}) as JsonValue}\n onChange={(next: JsonValue) => onChange(next)}\n // `keyMap` is what makes this more than a prettier textarea: it declares\n // a type per path, which picks the control and reports contradictions. A\n // string by design, so it survives an MCP round-trip.\n keyMap={field.keyMap}\n mode=\"edit\"\n size=\"sm\"\n rootLabel={field.label}\n />\n );\n};\n\n/**\n * The full renderer map. Spread it to add your own types alongside.\n */\nexport const reactFancyFieldRenderers: Record<string, ConfigFieldRenderFn> = {\n json: jsonFieldRenderer,\n};\n\n/* ------------------------------------------------------------------------- *\n * Pause-form controls\n * ------------------------------------------------------------------------- */\n\n/**\n * react-fancy controls for the `user_input` / `human_approval` pause form.\n *\n * ```tsx\n * import { humanFieldRenderers } from \"@particle-academy/fancy-flow/fields/react-fancy\";\n *\n * <FlowEditor … humanFieldRenderers={humanFieldRenderers} />\n * ```\n *\n * ## Why this is opt-in rather than the default\n *\n * Rule 2 of the suite says our surfaces compose react-fancy rather than\n * hand-rolling what a primitive already covers, and the pause form's built-ins\n * are native elements. That is not a gap in the kit — react-fancy has every\n * primitive needed — it is a PACKAGING constraint: react-fancy is an OPTIONAL\n * peer, `HumanPrompt` ships in the main entry, and importing it there would\n * make a standalone `npm install @particle-academy/fancy-flow` fail to resolve\n * at import time while bypassing the `--ff-*` token layer hosts theme\n * `.ff-editor` with.\n *\n * This map is how a host that HAS react-fancy gets the Fancy controls anyway,\n * with one prop and no cost to anyone else. Same shape and same reasoning as\n * `reactFancyFieldRenderers` above.\n *\n * ## What it covers, and what it deliberately does not\n *\n * `datetime` is absent: react-fancy's `DatePicker` is date-only, so claiming\n * the type here would render a control that silently drops the time half of a\n * value the field promised to collect. It falls through to the built-in\n * `<input type=\"datetime-local\">`, which does collect it. An honest gap beats a\n * control that looks right and loses data.\n */\nexport const humanFieldRenderers: HumanFieldRenderers = {\n text: ({ field, id, value, onChange, autoFocusRef }) => (\n <Input\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLInputElement> | undefined}\n placeholder={field.placeholder}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n textarea: ({ field, id, value, onChange, autoFocusRef }) => (\n <Textarea\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLTextAreaElement> | undefined}\n placeholder={field.placeholder}\n rows={3}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n number: ({ field, id, value, onChange, autoFocusRef }) => (\n <Input\n id={id}\n data-ff-field={field.key}\n ref={autoFocusRef as React.RefObject<HTMLInputElement> | undefined}\n type=\"number\"\n placeholder={field.placeholder}\n value={String(value ?? \"\")}\n // The built-in resolves a number field to a NUMBER, so this must too --\n // the value here is what resumes the paused run, and handing the next\n // node \"41\" where it resolved 41 before is a silent type change that no\n // test downstream would attribute to a renderer swap.\n onValueChange={(v) => onChange(v === \"\" ? \"\" : Number(v))}\n />\n ),\n\n select: ({ field, id, value, onChange }) => (\n <Select\n id={id}\n data-ff-field={field.key}\n list={(field.options ?? []).map((o) => ({ value: o.value, label: o.label }))}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n\n switch: ({ field, id, value, onChange }) => (\n <Switch\n id={id}\n data-ff-field={field.key}\n checked={!!value}\n onCheckedChange={onChange}\n />\n ),\n\n date: ({ field, id, value, onChange }) => (\n <DatePicker\n id={id}\n data-ff-field={field.key}\n value={String(value ?? \"\")}\n onValueChange={onChange}\n />\n ),\n};\n\n/*\n * `time` and `datetime` are ABSENT on purpose, and for different reasons.\n *\n * `datetime`: react-fancy's `DatePicker` is date-only. Claiming the type here\n * would render a control that silently drops the time half of a value the field\n * promised to collect.\n *\n * `time`: `TimePicker` accepts NO `id` and no `data-*` passthrough --\n * `TimePickerProps` is a closed interface of nine props, none of them an\n * identifier. It therefore cannot satisfy the two handles every control in this\n * form owes: the `id` its `<label htmlFor>` points at, and the `data-ff-field`\n * an agent drives the surface by. Wrapping it in a handle-bearing div would put\n * the label on a non-focusable element, which is worse than not claiming it.\n *\n * Both fall through to the built-in `<input type=\"time\">` /\n * `<input type=\"datetime-local\">`, which do carry the handles and do collect\n * the whole value. An honest gap beats a control that looks right and loses\n * either data or its handle.\n *\n * The `TimePicker` half is a react-fancy FINDING rather than a fancy-flow\n * limitation -- per the suite's second rule, a missing primitive capability is\n * filed against the kit rather than routed around locally.\n */\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -11251,7 +11251,7 @@ function resolveWorkflowProps(declared, passed) {
|
|
|
11251
11251
|
// src/runtime/run-flow.ts
|
|
11252
11252
|
async function runFlow(graph, executors, onEvent = () => {
|
|
11253
11253
|
}, options = {}) {
|
|
11254
|
-
const { signal, initialInputs = {}, timeoutMs, depth = 0, resumeOutputs = {} } = options;
|
|
11254
|
+
const { signal, initialInputs = {}, timeoutMs, depth = 0, resumeOutputs = {}, entryNodes } = options;
|
|
11255
11255
|
const run = options.run === void 0 ? void 0 : RunIdentity.from(options.run);
|
|
11256
11256
|
const outputs = {};
|
|
11257
11257
|
const portValues = /* @__PURE__ */ new Map();
|
|
@@ -11290,6 +11290,10 @@ async function runFlow(graph, executors, onEvent = () => {
|
|
|
11290
11290
|
continue;
|
|
11291
11291
|
}
|
|
11292
11292
|
const incoming = incomingByNode.get(node.id) ?? [];
|
|
11293
|
+
if (incoming.length === 0 && entryNodes !== void 0 && !entryNodes.includes(node.id)) {
|
|
11294
|
+
onEvent({ type: "node-status", nodeId: node.id, status: "idle", text: "skipped" });
|
|
11295
|
+
continue;
|
|
11296
|
+
}
|
|
11293
11297
|
if (incoming.length > 0) {
|
|
11294
11298
|
const anyActive = incoming.some((e) => portValues.has(`${e.source}:${e.sourceHandle ?? "out"}`));
|
|
11295
11299
|
if (!anyActive) {
|
|
@@ -14696,7 +14700,11 @@ function initialValues(fields) {
|
|
|
14696
14700
|
}
|
|
14697
14701
|
return v2;
|
|
14698
14702
|
}
|
|
14699
|
-
function HumanPrompt({
|
|
14703
|
+
function HumanPrompt({
|
|
14704
|
+
request,
|
|
14705
|
+
onCancel,
|
|
14706
|
+
fieldRenderers
|
|
14707
|
+
}) {
|
|
14700
14708
|
const firstRef = ReactExports.useRef(null);
|
|
14701
14709
|
ReactExports.useEffect(() => {
|
|
14702
14710
|
firstRef.current?.focus();
|
|
@@ -14708,7 +14716,7 @@ function HumanPrompt({ request, onCancel }) {
|
|
|
14708
14716
|
}, [onCancel]);
|
|
14709
14717
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-prompt-overlay", role: "dialog", "aria-modal": "true", "aria-label": request.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-prompt", onClick: (e) => e.stopPropagation(), children: [
|
|
14710
14718
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-prompt__title", children: request.title }),
|
|
14711
|
-
request.kind === "approval" ? /* @__PURE__ */ jsxRuntime.jsx(ApprovalBody, { request, onCancel }) : /* @__PURE__ */ jsxRuntime.jsx(InputBody, { request, onCancel, firstRef })
|
|
14719
|
+
request.kind === "approval" ? /* @__PURE__ */ jsxRuntime.jsx(ApprovalBody, { request, onCancel }) : /* @__PURE__ */ jsxRuntime.jsx(InputBody, { request, onCancel, firstRef, fieldRenderers })
|
|
14712
14720
|
] }) });
|
|
14713
14721
|
}
|
|
14714
14722
|
function ApprovalBody({ request, onCancel }) {
|
|
@@ -14724,7 +14732,8 @@ function ApprovalBody({ request, onCancel }) {
|
|
|
14724
14732
|
function InputBody({
|
|
14725
14733
|
request,
|
|
14726
14734
|
onCancel,
|
|
14727
|
-
firstRef
|
|
14735
|
+
firstRef,
|
|
14736
|
+
fieldRenderers
|
|
14728
14737
|
}) {
|
|
14729
14738
|
const [values, setValues] = ReactExports.useState(() => initialValues(request.fields));
|
|
14730
14739
|
const set3 = (k2, v2) => setValues((prev) => ({ ...prev, [k2]: v2 }));
|
|
@@ -14760,7 +14769,8 @@ function InputBody({
|
|
|
14760
14769
|
id: fieldId(f.key),
|
|
14761
14770
|
value: values[f.key],
|
|
14762
14771
|
onChange: (v2) => set3(f.key, v2),
|
|
14763
|
-
autoFocusRef: i === 0 ? firstRef : void 0
|
|
14772
|
+
autoFocusRef: i === 0 ? firstRef : void 0,
|
|
14773
|
+
renderers: fieldRenderers
|
|
14764
14774
|
}
|
|
14765
14775
|
)
|
|
14766
14776
|
] }, f.key)) }),
|
|
@@ -14777,8 +14787,14 @@ function FieldControl({
|
|
|
14777
14787
|
id: id2,
|
|
14778
14788
|
value,
|
|
14779
14789
|
onChange,
|
|
14780
|
-
autoFocusRef
|
|
14790
|
+
autoFocusRef,
|
|
14791
|
+
renderers
|
|
14781
14792
|
}) {
|
|
14793
|
+
const override = renderers?.[field.type ?? "text"];
|
|
14794
|
+
if (override) {
|
|
14795
|
+
const rendered = override({ field, id: id2, value, onChange, autoFocusRef });
|
|
14796
|
+
if (rendered !== null && rendered !== void 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: rendered });
|
|
14797
|
+
}
|
|
14782
14798
|
const handle = { id: id2, "data-ff-field": field.key };
|
|
14783
14799
|
if (field.type === "textarea") {
|
|
14784
14800
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -14866,6 +14882,7 @@ function FlowEditorInner({
|
|
|
14866
14882
|
onDelete,
|
|
14867
14883
|
onEdgeDelete,
|
|
14868
14884
|
confirmDelete,
|
|
14885
|
+
humanFieldRenderers,
|
|
14869
14886
|
apiRef
|
|
14870
14887
|
}) {
|
|
14871
14888
|
const internal = useFlowState(initial);
|
|
@@ -15402,10 +15419,17 @@ function FlowEditorInner({
|
|
|
15402
15419
|
}
|
|
15403
15420
|
),
|
|
15404
15421
|
showFeed && (slots.feed ? slots.feed(api) : /* @__PURE__ */ jsxRuntime.jsx(FlowRunFeed, { entries: runner.feed, running: api.running, className: "ff-editor__feed" })),
|
|
15405
|
-
prompt && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
|
|
15422
|
+
prompt && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15423
|
+
HumanPrompt,
|
|
15424
|
+
{
|
|
15425
|
+
request: prompt,
|
|
15426
|
+
onCancel: () => {
|
|
15427
|
+
setPrompt(null);
|
|
15428
|
+
runner.cancel();
|
|
15429
|
+
},
|
|
15430
|
+
fieldRenderers: humanFieldRenderers
|
|
15431
|
+
}
|
|
15432
|
+
)
|
|
15409
15433
|
] }),
|
|
15410
15434
|
showPanel && (slots.panel ? slots.panel(api) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-editor__panel-wrap", children: [
|
|
15411
15435
|
/* @__PURE__ */ jsxRuntime.jsx(
|