@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.
Files changed (36) hide show
  1. package/dist/ConfigFieldRenderer-BHQDZer6.d.ts +92 -0
  2. package/dist/ConfigFieldRenderer-LotNHeG8.d.cts +92 -0
  3. package/dist/{chunk-UX65ML3J.js → chunk-55KQS3LK.js} +25 -2
  4. package/dist/chunk-55KQS3LK.js.map +1 -0
  5. package/dist/{chunk-WOO4B7M5.js → chunk-T3VQX3XB.js} +3 -3
  6. package/dist/{chunk-WOO4B7M5.js.map → chunk-T3VQX3XB.js.map} +1 -1
  7. package/dist/engine.d.cts +3 -3
  8. package/dist/engine.d.ts +3 -3
  9. package/dist/fields/react-fancy.cjs +40 -0
  10. package/dist/fields/react-fancy.cjs.map +1 -0
  11. package/dist/fields/react-fancy.d.cts +20 -0
  12. package/dist/fields/react-fancy.d.ts +20 -0
  13. package/dist/fields/react-fancy.js +37 -0
  14. package/dist/fields/react-fancy.js.map +1 -0
  15. package/dist/index.cjs +343 -33
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +105 -127
  18. package/dist/index.d.ts +105 -127
  19. package/dist/index.js +320 -38
  20. package/dist/index.js.map +1 -1
  21. package/dist/registry/index.d.cts +3 -3
  22. package/dist/registry/index.d.ts +3 -3
  23. package/dist/{registry-BADFn97n.d.cts → registry-C9KMVpn7.d.cts} +1 -1
  24. package/dist/{registry-DYbFLEcW.d.ts → registry-FGCBprcn.d.ts} +1 -1
  25. package/dist/registry.cjs +23 -0
  26. package/dist/registry.cjs.map +1 -1
  27. package/dist/registry.js +1 -1
  28. package/dist/screens.js +3 -3
  29. package/dist/styles.css +99 -0
  30. package/dist/styles.css.map +1 -1
  31. package/dist/{types-D8Dezh9v.d.cts → types-B78Rm69S.d.cts} +94 -2
  32. package/dist/{types-D6lsIGoe.d.ts → types-JViq8reb.d.ts} +94 -2
  33. package/dist/ux.d.cts +1 -1
  34. package/dist/ux.d.ts +1 -1
  35. package/package.json +12 -2
  36. package/dist/chunk-UX65ML3J.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,21 +1,23 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, CSSProperties, ComponentType } from 'react';
2
+ import { ReactNode, CSSProperties, ComponentProps, ComponentType } from 'react';
3
3
  import { ReactFlowProps, Edge, BackgroundVariant, Connection, NodeProps, NodeTypes } from '@xyflow/react';
4
4
  import { ConnectionValidatorOptions } from './registry/index.cjs';
5
5
  export { ANY_PORT_TYPE, BUILTIN_KINDS, PortCompatibility, RegistryNode, RichInputAdapter, RichInputPreview, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerBuiltinKinds, registerRichInputAdapter, resolveNodePorts, resolvePortSpec } from './registry/index.cjs';
6
6
  import { b as FlowNode, F as FlowGraph, e as NodeRunStatus, E as ExecutorRegistry } from './types-sOmpCitB.cjs';
7
7
  export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, a as FlowEdge, c as FlowNodeData, d as FlowNodeKind, N as NodeExecutor, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, R as RunEvent, S as SubgraphNodeData, T as TriggerNodeData } from './types-sOmpCitB.cjs';
8
+ import { C as ConfigFieldRenderFn } from './ConfigFieldRenderer-LotNHeG8.cjs';
9
+ export { a as ConfigFieldRenderContext, b as ConfigFieldRenderer, c as ConfigFieldRendererProps } from './ConfigFieldRenderer-LotNHeG8.cjs';
8
10
  import { WorkflowSchema, WorkflowMetadata } from './schema/index.cjs';
9
11
  export { ImportIssue, ImportOptions, ImportResult, WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, WorkflowSchemaEdge, WorkflowSchemaNode, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './schema/index.cjs';
10
12
  import { AutoLayoutOptions } from './layout/index.cjs';
11
13
  export { AutoLayoutDirection } from './layout/index.cjs';
12
- import { c as NodeCategory, d as NodeKindDefinition, a as ConfigField } from './types-D8Dezh9v.cjs';
13
- export { D as DocumentConfigField, K as KeyValueConfigField, L as LEGACY_PAUSE_PREFIXES, h as PAUSE_PREFIX, P as PauseAwaiting, i as PauseSignal, j as PortSpec, R as RenderBodyContext, t as RepeaterConfigField, u as RepeaterRowField, m as decodePause, n as encodePause, o as isPause, p as pauseForHuman } from './types-D8Dezh9v.cjs';
14
+ import { c as NodeCategory, d as NodeKindDefinition } from './types-B78Rm69S.cjs';
15
+ export { A as AvailableVariable, a as ConfigField, D as DocumentConfigField, z as ExpressionForm, B as ExpressionGrammarHelp, K as KeyValueConfigField, L as LEGACY_PAUSE_PREFIXES, O as OutputField, F as OutputShape, h as PAUSE_PREFIX, P as PauseAwaiting, i as PauseSignal, j as PortSpec, R as RenderBodyContext, t as RepeaterConfigField, u as RepeaterRowField, G as availableVariables, H as baseVariables, m as decodePause, I as describeExpressionGrammar, n as encodePause, o as isPause, Q as outputFieldsFor, p as pauseForHuman } from './types-B78Rm69S.cjs';
14
16
  export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-nLqo7s2E.cjs';
15
17
  import { FlowRunFeedEntry } from './runtime/index.cjs';
16
18
  export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.cjs';
17
19
  export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, R as RunOptions, d as RunResult, r as runCohort, e as runFlow } from './run-cohort-Bjv2ZU6g.cjs';
18
- export { N as NodeKindPresentation, c as categoryAccent, b as clearNodeKindOverrides, d as defaultConfigFor, g as getNodeKind, l as listNodeKinds, o as onNodeKindsChanged, e as overrideNodeKind, r as registerNodeKind, v as validateConfig } from './registry-BADFn97n.cjs';
20
+ export { N as NodeKindPresentation, c as categoryAccent, b as clearNodeKindOverrides, d as defaultConfigFor, g as getNodeKind, l as listNodeKinds, o as onNodeKindsChanged, e as overrideNodeKind, r as registerNodeKind, v as validateConfig } from './registry-C9KMVpn7.cjs';
19
21
  import './capabilities-BtJQTbnw.cjs';
20
22
 
21
23
  type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" | "height"> & {
@@ -67,6 +69,56 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
67
69
  */
68
70
  declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, colorMode, showHelperLines, zoomOnWheel, onNodesChange, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
69
71
 
72
+ type NodeConfigPanelProps = {
73
+ /** Currently-selected node — pass null to render the empty state. */
74
+ node: FlowNode | null;
75
+ /** Called when the user edits the node label, description, or config. */
76
+ onChange: (next: FlowNode) => void;
77
+ /**
78
+ * Called when the user deletes the node from the panel. When provided, the
79
+ * panel renders a "Delete node" button while a node is selected — so the
80
+ * delete affordance lives WITH the panel (a dev composing their own editor
81
+ * gets it for free), rather than in a host toolbar it has to re-implement.
82
+ */
83
+ onDelete?: (node: FlowNode) => void;
84
+ /** Label for the delete button. Default "Delete node". */
85
+ deleteLabel?: string;
86
+ /** Optional header content (e.g. close button). */
87
+ header?: ReactNode;
88
+ /** Optional credential picker hook — host renders the picker. */
89
+ renderCredentialField?: (props: {
90
+ credentialType: string;
91
+ value: unknown;
92
+ onChange: (next: unknown) => void;
93
+ }) => ReactNode;
94
+ /**
95
+ * Optional document editor hook — host renders the editor for `document`
96
+ * fields. Lets rich authored content live in node config without fancy-flow
97
+ * taking on a document model.
98
+ */
99
+ /** Host renderers keyed by field `type`. See {@link ConfigFieldRenderer}. */
100
+ fieldRenderers?: Record<string, ConfigFieldRenderFn>;
101
+ /**
102
+ * The graph the node lives in. Supplying it is what makes the `{{ }}` variable
103
+ * picker context-aware — it reads the UPSTREAM node's declared `outputShape`
104
+ * to list what is actually reachable here (issue #5). Without it the picker
105
+ * still opens, but can only offer the whole input.
106
+ */
107
+ graph?: FlowGraph;
108
+ renderDocumentField?: (props: {
109
+ documentType?: string;
110
+ value: unknown;
111
+ onChange: (next: unknown) => void;
112
+ }) => ReactNode;
113
+ className?: string;
114
+ style?: React.CSSProperties;
115
+ };
116
+ /**
117
+ * NodeConfigPanel — schema-driven form for the selected node. Defers to
118
+ * `kind.renderPanel` if the kind opts out of the auto-form.
119
+ */
120
+ declare function NodeConfigPanel({ node, onChange, onDelete, deleteLabel, header, renderCredentialField, renderDocumentField, fieldRenderers, graph, className, style, }: NodeConfigPanelProps): react.JSX.Element;
121
+
70
122
  /**
71
123
  * Clone a set of nodes AND the edges internal to that set, remapping every id.
72
124
  * This is the piece `duplicateNode` lacks: a copy/paste (or duplicate-selection)
@@ -273,6 +325,20 @@ type FlowEditorProps = {
273
325
  showPalette?: boolean;
274
326
  /** Show the config panel sidebar. Default true. */
275
327
  showPanel?: boolean;
328
+ /**
329
+ * Host renderers for config-field types, keyed by `type`, handed straight to
330
+ * `NodeConfigPanel`.
331
+ *
332
+ * Use it to claim a type the package renders plainly — the built-in `json`
333
+ * field is a bare textarea, and
334
+ * `@particle-academy/fancy-flow/fields/react-fancy` swaps it for a real typed
335
+ * editor — or to supply one the package has never heard of.
336
+ *
337
+ * This forwarding is the whole point: the seam existed on `NodeConfigPanel`
338
+ * and had no route through `FlowEditor`, so reaching it meant abandoning the
339
+ * editor and composing one by hand.
340
+ */
341
+ fieldRenderers?: ComponentProps<typeof NodeConfigPanel>["fieldRenderers"];
276
342
  /** Show run feed below the canvas. Default true. */
277
343
  showFeed?: boolean;
278
344
  /** Total editor height. Default 720. */
@@ -347,128 +413,6 @@ declare function paletteDropHandlers(onDrop: (kindName: string, evt: React.DragE
347
413
  onDrop: (e: React.DragEvent) => void;
348
414
  };
349
415
 
350
- /** What a host renderer is handed. */
351
- type ConfigFieldRenderContext = {
352
- field: ConfigField;
353
- value: unknown;
354
- onChange: (next: unknown) => void;
355
- /** The id the panel's `<label>` points at. Put it on your control. */
356
- id?: string;
357
- };
358
- /**
359
- * Render one field. Return `null` to fall back to the package's own rendering,
360
- * so a host can claim a type conditionally instead of reimplementing every case.
361
- *
362
- * Named `...Fn` because `ConfigFieldRenderer` is already the component this
363
- * module exports; two things with one name in a public API is a paper cut a
364
- * consumer pays for, not us.
365
- */
366
- type ConfigFieldRenderFn = (ctx: ConfigFieldRenderContext) => ReactNode;
367
- type ConfigFieldRendererProps = {
368
- field: ConfigField;
369
- value: unknown;
370
- onChange: (value: unknown) => void;
371
- /**
372
- * DOM id for the control this renders.
373
- *
374
- * Supplied by the caller rather than generated here so the panel's `<label>`
375
- * can point at it — a label beside a control is not a label attached to one.
376
- * Also the agent-facing handle: the Human+ contract asks that every
377
- * interactive element have a stable identity so an agent targets it instead
378
- * of guessing at the DOM, and until this existed nothing in the editor had
379
- * one.
380
- */
381
- id?: string;
382
- renderCredentialField?: (props: {
383
- credentialType: string;
384
- value: unknown;
385
- onChange: (next: unknown) => void;
386
- }) => ReactNode;
387
- /**
388
- * Editor for `document` fields. fancy-flow stores the document but never
389
- * interprets it — the host owns the editing surface, exactly as it does for
390
- * `credential`. This is the seam for rich human-input steps (authored pages,
391
- * required reading, multi-section forms) without the package depending on
392
- * any particular document model.
393
- */
394
- renderDocumentField?: (props: {
395
- documentType?: string;
396
- value: unknown;
397
- onChange: (next: unknown) => void;
398
- }) => ReactNode;
399
- /**
400
- * Host renderers keyed by field `type`.
401
- *
402
- * The generic form of `renderDocumentField` / `renderCredentialField`: those
403
- * cover two types the package deliberately does not interpret, this covers
404
- * any type at all — including one the package has never heard of.
405
- *
406
- * Without it, a richer field had to be rendered OUTSIDE the panel, so that
407
- * node's config stopped living where every other field does. An unknown type
408
- * also fell through to `default:` and rendered nothing, so the schema said the
409
- * field existed and the panel showed empty space.
410
- *
411
- * Consulted BEFORE the built-in switch, so a host can also replace a built-in
412
- * (react-fancy inputs, say) through the same seam rather than a second one.
413
- */
414
- fieldRenderers?: Record<string, ConfigFieldRenderFn>;
415
- };
416
- /**
417
- * ConfigFieldRenderer — dispatches to the right input element per field type.
418
- *
419
- * Plain HTML inputs styled via the package's CSS so the package stays
420
- * standalone (no react-fancy import required) and every surface stays themeable
421
- * through the `--ff-*` token layer. Hosts that want react-fancy form components
422
- * can supply their own field renderers via the kind's `renderPanel`.
423
- *
424
- * Each control carries the caller's `id` and a `data-ff-field` handle keyed by
425
- * the field, so a label can point at it and an agent can find it by name.
426
- */
427
- declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, fieldRenderers, }: ConfigFieldRendererProps): react.JSX.Element | null;
428
-
429
- type NodeConfigPanelProps = {
430
- /** Currently-selected node — pass null to render the empty state. */
431
- node: FlowNode | null;
432
- /** Called when the user edits the node label, description, or config. */
433
- onChange: (next: FlowNode) => void;
434
- /**
435
- * Called when the user deletes the node from the panel. When provided, the
436
- * panel renders a "Delete node" button while a node is selected — so the
437
- * delete affordance lives WITH the panel (a dev composing their own editor
438
- * gets it for free), rather than in a host toolbar it has to re-implement.
439
- */
440
- onDelete?: (node: FlowNode) => void;
441
- /** Label for the delete button. Default "Delete node". */
442
- deleteLabel?: string;
443
- /** Optional header content (e.g. close button). */
444
- header?: ReactNode;
445
- /** Optional credential picker hook — host renders the picker. */
446
- renderCredentialField?: (props: {
447
- credentialType: string;
448
- value: unknown;
449
- onChange: (next: unknown) => void;
450
- }) => ReactNode;
451
- /**
452
- * Optional document editor hook — host renders the editor for `document`
453
- * fields. Lets rich authored content live in node config without fancy-flow
454
- * taking on a document model.
455
- */
456
- /** Host renderers keyed by field `type`. See {@link ConfigFieldRenderer}. */
457
- fieldRenderers?: Record<string, ConfigFieldRenderFn>;
458
- renderDocumentField?: (props: {
459
- documentType?: string;
460
- value: unknown;
461
- onChange: (next: unknown) => void;
462
- }) => ReactNode;
463
- className?: string;
464
- style?: React.CSSProperties;
465
- };
466
- /**
467
- * NodeConfigPanel — schema-driven form for the selected node. Defers to
468
- * `kind.renderPanel` if the kind opts out of the auto-form.
469
- */
470
- declare function NodeConfigPanel({ node, onChange, onDelete, deleteLabel, header, renderCredentialField, renderDocumentField, fieldRenderers, className, style, }: NodeConfigPanelProps): react.JSX.Element;
471
-
472
416
  /** Entry-point node — outputs only, no inputs. */
473
417
  declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
474
418
  declare const TriggerNode: react.MemoExoticComponent<typeof TriggerNodeInner>;
@@ -683,4 +627,38 @@ declare const flowKeys: {
683
627
  readonly run: (runId: string) => readonly ["flow", "runs", string];
684
628
  };
685
629
 
686
- export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, type ConfigFieldRenderContext, type ConfigFieldRenderFn, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, flowKeys, flowLive, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
630
+ type ExpressionFieldProps = {
631
+ value: string;
632
+ onChange: (next: string) => void;
633
+ placeholder?: string;
634
+ rows?: number;
635
+ /** The panel's field id + agent handle. */
636
+ handle: {
637
+ id?: string;
638
+ "data-ff-field": string;
639
+ };
640
+ /**
641
+ * The graph and the node being edited. Both are needed to answer "what can I
642
+ * write here" — without them the picker can still offer `{{ $json }}` but
643
+ * nothing node-specific, which is the static list issue #5 asked us not to
644
+ * ship.
645
+ */
646
+ graph?: FlowGraph;
647
+ nodeId?: string;
648
+ };
649
+ /**
650
+ * ExpressionField — a `{{ }}` field that tells the author what it accepts.
651
+ *
652
+ * Issue #5: the panel rendered a bare textarea with a placeholder and nothing
653
+ * else, so writing an expression required already knowing both the grammar and
654
+ * the exact shape of the upstream node's output. Two affordances close that:
655
+ * typing `{{ ` opens a picker of the variables actually reachable at THIS node,
656
+ * and a reference toggle explains the grammar.
657
+ *
658
+ * The picker deliberately lists only what the resolver can reach — see
659
+ * `availableVariables`. A suggestion that resolves to `null` at runtime is
660
+ * worse than no suggestion, because the author has no reason to doubt it.
661
+ */
662
+ declare function ExpressionField({ value, onChange, placeholder, rows, handle, graph, nodeId, }: ExpressionFieldProps): react.JSX.Element;
663
+
664
+ export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigFieldRenderFn, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, ExpressionField, type ExpressionFieldProps, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, flowKeys, flowLive, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
package/dist/index.d.ts CHANGED
@@ -1,21 +1,23 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, CSSProperties, ComponentType } from 'react';
2
+ import { ReactNode, CSSProperties, ComponentProps, ComponentType } from 'react';
3
3
  import { ReactFlowProps, Edge, BackgroundVariant, Connection, NodeProps, NodeTypes } from '@xyflow/react';
4
4
  import { ConnectionValidatorOptions } from './registry/index.js';
5
5
  export { ANY_PORT_TYPE, BUILTIN_KINDS, PortCompatibility, RegistryNode, RichInputAdapter, RichInputPreview, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerBuiltinKinds, registerRichInputAdapter, resolveNodePorts, resolvePortSpec } from './registry/index.js';
6
6
  import { b as FlowNode, F as FlowGraph, e as NodeRunStatus, E as ExecutorRegistry } from './types-sOmpCitB.js';
7
7
  export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, a as FlowEdge, c as FlowNodeData, d as FlowNodeKind, N as NodeExecutor, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, R as RunEvent, S as SubgraphNodeData, T as TriggerNodeData } from './types-sOmpCitB.js';
8
+ import { C as ConfigFieldRenderFn } from './ConfigFieldRenderer-BHQDZer6.js';
9
+ export { a as ConfigFieldRenderContext, b as ConfigFieldRenderer, c as ConfigFieldRendererProps } from './ConfigFieldRenderer-BHQDZer6.js';
8
10
  import { WorkflowSchema, WorkflowMetadata } from './schema/index.js';
9
11
  export { ImportIssue, ImportOptions, ImportResult, WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, WorkflowSchemaEdge, WorkflowSchemaNode, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './schema/index.js';
10
12
  import { AutoLayoutOptions } from './layout/index.js';
11
13
  export { AutoLayoutDirection } from './layout/index.js';
12
- import { c as NodeCategory, d as NodeKindDefinition, a as ConfigField } from './types-D6lsIGoe.js';
13
- export { D as DocumentConfigField, K as KeyValueConfigField, L as LEGACY_PAUSE_PREFIXES, h as PAUSE_PREFIX, P as PauseAwaiting, i as PauseSignal, j as PortSpec, R as RenderBodyContext, t as RepeaterConfigField, u as RepeaterRowField, m as decodePause, n as encodePause, o as isPause, p as pauseForHuman } from './types-D6lsIGoe.js';
14
+ import { c as NodeCategory, d as NodeKindDefinition } from './types-JViq8reb.js';
15
+ export { A as AvailableVariable, a as ConfigField, D as DocumentConfigField, z as ExpressionForm, B as ExpressionGrammarHelp, K as KeyValueConfigField, L as LEGACY_PAUSE_PREFIXES, O as OutputField, F as OutputShape, h as PAUSE_PREFIX, P as PauseAwaiting, i as PauseSignal, j as PortSpec, R as RenderBodyContext, t as RepeaterConfigField, u as RepeaterRowField, G as availableVariables, H as baseVariables, m as decodePause, I as describeExpressionGrammar, n as encodePause, o as isPause, Q as outputFieldsFor, p as pauseForHuman } from './types-JViq8reb.js';
14
16
  export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-C4QAVgWv.js';
15
17
  import { FlowRunFeedEntry } from './runtime/index.js';
16
18
  export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.js';
17
19
  export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, R as RunOptions, d as RunResult, r as runCohort, e as runFlow } from './run-cohort-BnP6ErHi.js';
18
- export { N as NodeKindPresentation, c as categoryAccent, b as clearNodeKindOverrides, d as defaultConfigFor, g as getNodeKind, l as listNodeKinds, o as onNodeKindsChanged, e as overrideNodeKind, r as registerNodeKind, v as validateConfig } from './registry-DYbFLEcW.js';
20
+ export { N as NodeKindPresentation, c as categoryAccent, b as clearNodeKindOverrides, d as defaultConfigFor, g as getNodeKind, l as listNodeKinds, o as onNodeKindsChanged, e as overrideNodeKind, r as registerNodeKind, v as validateConfig } from './registry-FGCBprcn.js';
19
21
  import './capabilities-CkhKj_U_.js';
20
22
 
21
23
  type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" | "height"> & {
@@ -67,6 +69,56 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
67
69
  */
68
70
  declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, colorMode, showHelperLines, zoomOnWheel, onNodesChange, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
69
71
 
72
+ type NodeConfigPanelProps = {
73
+ /** Currently-selected node — pass null to render the empty state. */
74
+ node: FlowNode | null;
75
+ /** Called when the user edits the node label, description, or config. */
76
+ onChange: (next: FlowNode) => void;
77
+ /**
78
+ * Called when the user deletes the node from the panel. When provided, the
79
+ * panel renders a "Delete node" button while a node is selected — so the
80
+ * delete affordance lives WITH the panel (a dev composing their own editor
81
+ * gets it for free), rather than in a host toolbar it has to re-implement.
82
+ */
83
+ onDelete?: (node: FlowNode) => void;
84
+ /** Label for the delete button. Default "Delete node". */
85
+ deleteLabel?: string;
86
+ /** Optional header content (e.g. close button). */
87
+ header?: ReactNode;
88
+ /** Optional credential picker hook — host renders the picker. */
89
+ renderCredentialField?: (props: {
90
+ credentialType: string;
91
+ value: unknown;
92
+ onChange: (next: unknown) => void;
93
+ }) => ReactNode;
94
+ /**
95
+ * Optional document editor hook — host renders the editor for `document`
96
+ * fields. Lets rich authored content live in node config without fancy-flow
97
+ * taking on a document model.
98
+ */
99
+ /** Host renderers keyed by field `type`. See {@link ConfigFieldRenderer}. */
100
+ fieldRenderers?: Record<string, ConfigFieldRenderFn>;
101
+ /**
102
+ * The graph the node lives in. Supplying it is what makes the `{{ }}` variable
103
+ * picker context-aware — it reads the UPSTREAM node's declared `outputShape`
104
+ * to list what is actually reachable here (issue #5). Without it the picker
105
+ * still opens, but can only offer the whole input.
106
+ */
107
+ graph?: FlowGraph;
108
+ renderDocumentField?: (props: {
109
+ documentType?: string;
110
+ value: unknown;
111
+ onChange: (next: unknown) => void;
112
+ }) => ReactNode;
113
+ className?: string;
114
+ style?: React.CSSProperties;
115
+ };
116
+ /**
117
+ * NodeConfigPanel — schema-driven form for the selected node. Defers to
118
+ * `kind.renderPanel` if the kind opts out of the auto-form.
119
+ */
120
+ declare function NodeConfigPanel({ node, onChange, onDelete, deleteLabel, header, renderCredentialField, renderDocumentField, fieldRenderers, graph, className, style, }: NodeConfigPanelProps): react.JSX.Element;
121
+
70
122
  /**
71
123
  * Clone a set of nodes AND the edges internal to that set, remapping every id.
72
124
  * This is the piece `duplicateNode` lacks: a copy/paste (or duplicate-selection)
@@ -273,6 +325,20 @@ type FlowEditorProps = {
273
325
  showPalette?: boolean;
274
326
  /** Show the config panel sidebar. Default true. */
275
327
  showPanel?: boolean;
328
+ /**
329
+ * Host renderers for config-field types, keyed by `type`, handed straight to
330
+ * `NodeConfigPanel`.
331
+ *
332
+ * Use it to claim a type the package renders plainly — the built-in `json`
333
+ * field is a bare textarea, and
334
+ * `@particle-academy/fancy-flow/fields/react-fancy` swaps it for a real typed
335
+ * editor — or to supply one the package has never heard of.
336
+ *
337
+ * This forwarding is the whole point: the seam existed on `NodeConfigPanel`
338
+ * and had no route through `FlowEditor`, so reaching it meant abandoning the
339
+ * editor and composing one by hand.
340
+ */
341
+ fieldRenderers?: ComponentProps<typeof NodeConfigPanel>["fieldRenderers"];
276
342
  /** Show run feed below the canvas. Default true. */
277
343
  showFeed?: boolean;
278
344
  /** Total editor height. Default 720. */
@@ -347,128 +413,6 @@ declare function paletteDropHandlers(onDrop: (kindName: string, evt: React.DragE
347
413
  onDrop: (e: React.DragEvent) => void;
348
414
  };
349
415
 
350
- /** What a host renderer is handed. */
351
- type ConfigFieldRenderContext = {
352
- field: ConfigField;
353
- value: unknown;
354
- onChange: (next: unknown) => void;
355
- /** The id the panel's `<label>` points at. Put it on your control. */
356
- id?: string;
357
- };
358
- /**
359
- * Render one field. Return `null` to fall back to the package's own rendering,
360
- * so a host can claim a type conditionally instead of reimplementing every case.
361
- *
362
- * Named `...Fn` because `ConfigFieldRenderer` is already the component this
363
- * module exports; two things with one name in a public API is a paper cut a
364
- * consumer pays for, not us.
365
- */
366
- type ConfigFieldRenderFn = (ctx: ConfigFieldRenderContext) => ReactNode;
367
- type ConfigFieldRendererProps = {
368
- field: ConfigField;
369
- value: unknown;
370
- onChange: (value: unknown) => void;
371
- /**
372
- * DOM id for the control this renders.
373
- *
374
- * Supplied by the caller rather than generated here so the panel's `<label>`
375
- * can point at it — a label beside a control is not a label attached to one.
376
- * Also the agent-facing handle: the Human+ contract asks that every
377
- * interactive element have a stable identity so an agent targets it instead
378
- * of guessing at the DOM, and until this existed nothing in the editor had
379
- * one.
380
- */
381
- id?: string;
382
- renderCredentialField?: (props: {
383
- credentialType: string;
384
- value: unknown;
385
- onChange: (next: unknown) => void;
386
- }) => ReactNode;
387
- /**
388
- * Editor for `document` fields. fancy-flow stores the document but never
389
- * interprets it — the host owns the editing surface, exactly as it does for
390
- * `credential`. This is the seam for rich human-input steps (authored pages,
391
- * required reading, multi-section forms) without the package depending on
392
- * any particular document model.
393
- */
394
- renderDocumentField?: (props: {
395
- documentType?: string;
396
- value: unknown;
397
- onChange: (next: unknown) => void;
398
- }) => ReactNode;
399
- /**
400
- * Host renderers keyed by field `type`.
401
- *
402
- * The generic form of `renderDocumentField` / `renderCredentialField`: those
403
- * cover two types the package deliberately does not interpret, this covers
404
- * any type at all — including one the package has never heard of.
405
- *
406
- * Without it, a richer field had to be rendered OUTSIDE the panel, so that
407
- * node's config stopped living where every other field does. An unknown type
408
- * also fell through to `default:` and rendered nothing, so the schema said the
409
- * field existed and the panel showed empty space.
410
- *
411
- * Consulted BEFORE the built-in switch, so a host can also replace a built-in
412
- * (react-fancy inputs, say) through the same seam rather than a second one.
413
- */
414
- fieldRenderers?: Record<string, ConfigFieldRenderFn>;
415
- };
416
- /**
417
- * ConfigFieldRenderer — dispatches to the right input element per field type.
418
- *
419
- * Plain HTML inputs styled via the package's CSS so the package stays
420
- * standalone (no react-fancy import required) and every surface stays themeable
421
- * through the `--ff-*` token layer. Hosts that want react-fancy form components
422
- * can supply their own field renderers via the kind's `renderPanel`.
423
- *
424
- * Each control carries the caller's `id` and a `data-ff-field` handle keyed by
425
- * the field, so a label can point at it and an agent can find it by name.
426
- */
427
- declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, fieldRenderers, }: ConfigFieldRendererProps): react.JSX.Element | null;
428
-
429
- type NodeConfigPanelProps = {
430
- /** Currently-selected node — pass null to render the empty state. */
431
- node: FlowNode | null;
432
- /** Called when the user edits the node label, description, or config. */
433
- onChange: (next: FlowNode) => void;
434
- /**
435
- * Called when the user deletes the node from the panel. When provided, the
436
- * panel renders a "Delete node" button while a node is selected — so the
437
- * delete affordance lives WITH the panel (a dev composing their own editor
438
- * gets it for free), rather than in a host toolbar it has to re-implement.
439
- */
440
- onDelete?: (node: FlowNode) => void;
441
- /** Label for the delete button. Default "Delete node". */
442
- deleteLabel?: string;
443
- /** Optional header content (e.g. close button). */
444
- header?: ReactNode;
445
- /** Optional credential picker hook — host renders the picker. */
446
- renderCredentialField?: (props: {
447
- credentialType: string;
448
- value: unknown;
449
- onChange: (next: unknown) => void;
450
- }) => ReactNode;
451
- /**
452
- * Optional document editor hook — host renders the editor for `document`
453
- * fields. Lets rich authored content live in node config without fancy-flow
454
- * taking on a document model.
455
- */
456
- /** Host renderers keyed by field `type`. See {@link ConfigFieldRenderer}. */
457
- fieldRenderers?: Record<string, ConfigFieldRenderFn>;
458
- renderDocumentField?: (props: {
459
- documentType?: string;
460
- value: unknown;
461
- onChange: (next: unknown) => void;
462
- }) => ReactNode;
463
- className?: string;
464
- style?: React.CSSProperties;
465
- };
466
- /**
467
- * NodeConfigPanel — schema-driven form for the selected node. Defers to
468
- * `kind.renderPanel` if the kind opts out of the auto-form.
469
- */
470
- declare function NodeConfigPanel({ node, onChange, onDelete, deleteLabel, header, renderCredentialField, renderDocumentField, fieldRenderers, className, style, }: NodeConfigPanelProps): react.JSX.Element;
471
-
472
416
  /** Entry-point node — outputs only, no inputs. */
473
417
  declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
474
418
  declare const TriggerNode: react.MemoExoticComponent<typeof TriggerNodeInner>;
@@ -683,4 +627,38 @@ declare const flowKeys: {
683
627
  readonly run: (runId: string) => readonly ["flow", "runs", string];
684
628
  };
685
629
 
686
- export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, type ConfigFieldRenderContext, type ConfigFieldRenderFn, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, flowKeys, flowLive, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
630
+ type ExpressionFieldProps = {
631
+ value: string;
632
+ onChange: (next: string) => void;
633
+ placeholder?: string;
634
+ rows?: number;
635
+ /** The panel's field id + agent handle. */
636
+ handle: {
637
+ id?: string;
638
+ "data-ff-field": string;
639
+ };
640
+ /**
641
+ * The graph and the node being edited. Both are needed to answer "what can I
642
+ * write here" — without them the picker can still offer `{{ $json }}` but
643
+ * nothing node-specific, which is the static list issue #5 asked us not to
644
+ * ship.
645
+ */
646
+ graph?: FlowGraph;
647
+ nodeId?: string;
648
+ };
649
+ /**
650
+ * ExpressionField — a `{{ }}` field that tells the author what it accepts.
651
+ *
652
+ * Issue #5: the panel rendered a bare textarea with a placeholder and nothing
653
+ * else, so writing an expression required already knowing both the grammar and
654
+ * the exact shape of the upstream node's output. Two affordances close that:
655
+ * typing `{{ ` opens a picker of the variables actually reachable at THIS node,
656
+ * and a reference toggle explains the grammar.
657
+ *
658
+ * The picker deliberately lists only what the resolver can reach — see
659
+ * `availableVariables`. A suggestion that resolves to `null` at runtime is
660
+ * worse than no suggestion, because the author has no reason to doubt it.
661
+ */
662
+ declare function ExpressionField({ value, onChange, placeholder, rows, handle, graph, nodeId, }: ExpressionFieldProps): react.JSX.Element;
663
+
664
+ export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigFieldRenderFn, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, ExpressionField, type ExpressionFieldProps, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, flowKeys, flowLive, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };