@particle-academy/fancy-flow 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +42 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -40
- package/dist/index.d.ts +143 -40
- package/dist/index.js +41 -6
- package/dist/index.js.map +1 -1
- package/package.json +199 -198
package/dist/index.d.cts
CHANGED
|
@@ -347,47 +347,23 @@ declare function paletteDropHandlers(onDrop: (kindName: string, evt: React.DragE
|
|
|
347
347
|
onDrop: (e: React.DragEvent) => void;
|
|
348
348
|
};
|
|
349
349
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
onChange: (next:
|
|
355
|
-
/**
|
|
356
|
-
|
|
357
|
-
* panel renders a "Delete node" button while a node is selected — so the
|
|
358
|
-
* delete affordance lives WITH the panel (a dev composing their own editor
|
|
359
|
-
* gets it for free), rather than in a host toolbar it has to re-implement.
|
|
360
|
-
*/
|
|
361
|
-
onDelete?: (node: FlowNode) => void;
|
|
362
|
-
/** Label for the delete button. Default "Delete node". */
|
|
363
|
-
deleteLabel?: string;
|
|
364
|
-
/** Optional header content (e.g. close button). */
|
|
365
|
-
header?: ReactNode;
|
|
366
|
-
/** Optional credential picker hook — host renders the picker. */
|
|
367
|
-
renderCredentialField?: (props: {
|
|
368
|
-
credentialType: string;
|
|
369
|
-
value: unknown;
|
|
370
|
-
onChange: (next: unknown) => void;
|
|
371
|
-
}) => ReactNode;
|
|
372
|
-
/**
|
|
373
|
-
* Optional document editor hook — host renders the editor for `document`
|
|
374
|
-
* fields. Lets rich authored content live in node config without fancy-flow
|
|
375
|
-
* taking on a document model.
|
|
376
|
-
*/
|
|
377
|
-
renderDocumentField?: (props: {
|
|
378
|
-
documentType?: string;
|
|
379
|
-
value: unknown;
|
|
380
|
-
onChange: (next: unknown) => void;
|
|
381
|
-
}) => ReactNode;
|
|
382
|
-
className?: string;
|
|
383
|
-
style?: React.CSSProperties;
|
|
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;
|
|
384
357
|
};
|
|
385
358
|
/**
|
|
386
|
-
*
|
|
387
|
-
*
|
|
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.
|
|
388
365
|
*/
|
|
389
|
-
|
|
390
|
-
|
|
366
|
+
type ConfigFieldRenderFn = (ctx: ConfigFieldRenderContext) => ReactNode;
|
|
391
367
|
type ConfigFieldRendererProps = {
|
|
392
368
|
field: ConfigField;
|
|
393
369
|
value: unknown;
|
|
@@ -420,6 +396,22 @@ type ConfigFieldRendererProps = {
|
|
|
420
396
|
value: unknown;
|
|
421
397
|
onChange: (next: unknown) => void;
|
|
422
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>;
|
|
423
415
|
};
|
|
424
416
|
/**
|
|
425
417
|
* ConfigFieldRenderer — dispatches to the right input element per field type.
|
|
@@ -432,7 +424,50 @@ type ConfigFieldRendererProps = {
|
|
|
432
424
|
* Each control carries the caller's `id` and a `data-ff-field` handle keyed by
|
|
433
425
|
* the field, so a label can point at it and an agent can find it by name.
|
|
434
426
|
*/
|
|
435
|
-
declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
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;
|
|
436
471
|
|
|
437
472
|
/** Entry-point node — outputs only, no inputs. */
|
|
438
473
|
declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
@@ -580,4 +615,72 @@ type FlowRunFeedProps = {
|
|
|
580
615
|
*/
|
|
581
616
|
declare function FlowRunFeed({ entries, showHeader, title, running, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
582
617
|
|
|
583
|
-
|
|
618
|
+
/**
|
|
619
|
+
* The fancy-flow Live Contract — the run / job stream shape.
|
|
620
|
+
*
|
|
621
|
+
* Pure data, with `LiveContract` imported as a TYPE, so this adds no dependency.
|
|
622
|
+
* `FancyFlow\Laravel\LiveContract` declares the identical list and both sides
|
|
623
|
+
* assert parity.
|
|
624
|
+
*
|
|
625
|
+
* ## What makes this shape different
|
|
626
|
+
*
|
|
627
|
+
* A run emits far more than it stores. `NodeStatusChanged` and `NodeOutput`
|
|
628
|
+
* fire per node, many times a second on a wide graph — and a node's log line is
|
|
629
|
+
* not a cache entry, it is a **stream**. So the contract covers the run's
|
|
630
|
+
* DURABLE state (does this run exist, has it finished, is it waiting on a
|
|
631
|
+
* person) and deliberately leaves per-node chatter to `useFancyStream`, the
|
|
632
|
+
* same split the whiteboard makes between its document and its cursors.
|
|
633
|
+
*
|
|
634
|
+
* Get that wrong and a 40-node run invalidates the run list forty times while
|
|
635
|
+
* it executes, each one a re-fetch that tells the UI nothing it did not already
|
|
636
|
+
* learn from the stream.
|
|
637
|
+
*
|
|
638
|
+
* ## `awaiting` is the one that matters
|
|
639
|
+
*
|
|
640
|
+
* A run parking on a human step is the event a host most needs to react to —
|
|
641
|
+
* it is when a form has to appear in front of somebody. It gets its own event
|
|
642
|
+
* rather than folding into `updated`, so a host can subscribe to just that.
|
|
643
|
+
*
|
|
644
|
+
* ## Broadcast status, stated plainly
|
|
645
|
+
*
|
|
646
|
+
* `fancy-flow-php` currently dispatches these as **in-process Laravel events**;
|
|
647
|
+
* none of them implement `ShouldBroadcast` yet. This contract is therefore the
|
|
648
|
+
* agreed vocabulary rather than a description of traffic already on the wire: a
|
|
649
|
+
* host that wants live runs today re-broadcasts these under these names. Making
|
|
650
|
+
* the PHP events broadcast natively is a separate change, because it turns on
|
|
651
|
+
* websocket traffic for every consumer.
|
|
652
|
+
*/
|
|
653
|
+
declare const flowLive: {
|
|
654
|
+
readonly namespace: "flow";
|
|
655
|
+
readonly events: readonly [{
|
|
656
|
+
readonly event: "flow.run.created";
|
|
657
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
658
|
+
}, {
|
|
659
|
+
readonly event: "flow.run.updated";
|
|
660
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
661
|
+
}, {
|
|
662
|
+
readonly event: "flow.run.completed";
|
|
663
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
664
|
+
}, {
|
|
665
|
+
readonly event: "flow.run.awaiting";
|
|
666
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
667
|
+
readonly note: "A run parking on a human step — the moment a form has to appear in front of somebody. Its own event so a host can subscribe to just that, rather than filtering every update.";
|
|
668
|
+
}, {
|
|
669
|
+
readonly event: "flow.run.failed";
|
|
670
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
671
|
+
readonly note: "Not one of the standard verbs: a failed run is a terminal state a host renders differently from a completed one, so collapsing the two would lose the distinction.";
|
|
672
|
+
}];
|
|
673
|
+
};
|
|
674
|
+
/**
|
|
675
|
+
* Per-run keys, for a host showing a single run rather than the list.
|
|
676
|
+
*
|
|
677
|
+
* The contract declares prefixes because it is static data and a run id is not
|
|
678
|
+
* known until runtime. TanStack matches by prefix, so `["flow", "runs"]` still
|
|
679
|
+
* invalidates `["flow", "runs", runId]`.
|
|
680
|
+
*/
|
|
681
|
+
declare const flowKeys: {
|
|
682
|
+
readonly runs: () => readonly ["flow", "runs"];
|
|
683
|
+
readonly run: (runId: string) => readonly ["flow", "runs", string];
|
|
684
|
+
};
|
|
685
|
+
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -347,47 +347,23 @@ declare function paletteDropHandlers(onDrop: (kindName: string, evt: React.DragE
|
|
|
347
347
|
onDrop: (e: React.DragEvent) => void;
|
|
348
348
|
};
|
|
349
349
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
onChange: (next:
|
|
355
|
-
/**
|
|
356
|
-
|
|
357
|
-
* panel renders a "Delete node" button while a node is selected — so the
|
|
358
|
-
* delete affordance lives WITH the panel (a dev composing their own editor
|
|
359
|
-
* gets it for free), rather than in a host toolbar it has to re-implement.
|
|
360
|
-
*/
|
|
361
|
-
onDelete?: (node: FlowNode) => void;
|
|
362
|
-
/** Label for the delete button. Default "Delete node". */
|
|
363
|
-
deleteLabel?: string;
|
|
364
|
-
/** Optional header content (e.g. close button). */
|
|
365
|
-
header?: ReactNode;
|
|
366
|
-
/** Optional credential picker hook — host renders the picker. */
|
|
367
|
-
renderCredentialField?: (props: {
|
|
368
|
-
credentialType: string;
|
|
369
|
-
value: unknown;
|
|
370
|
-
onChange: (next: unknown) => void;
|
|
371
|
-
}) => ReactNode;
|
|
372
|
-
/**
|
|
373
|
-
* Optional document editor hook — host renders the editor for `document`
|
|
374
|
-
* fields. Lets rich authored content live in node config without fancy-flow
|
|
375
|
-
* taking on a document model.
|
|
376
|
-
*/
|
|
377
|
-
renderDocumentField?: (props: {
|
|
378
|
-
documentType?: string;
|
|
379
|
-
value: unknown;
|
|
380
|
-
onChange: (next: unknown) => void;
|
|
381
|
-
}) => ReactNode;
|
|
382
|
-
className?: string;
|
|
383
|
-
style?: React.CSSProperties;
|
|
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;
|
|
384
357
|
};
|
|
385
358
|
/**
|
|
386
|
-
*
|
|
387
|
-
*
|
|
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.
|
|
388
365
|
*/
|
|
389
|
-
|
|
390
|
-
|
|
366
|
+
type ConfigFieldRenderFn = (ctx: ConfigFieldRenderContext) => ReactNode;
|
|
391
367
|
type ConfigFieldRendererProps = {
|
|
392
368
|
field: ConfigField;
|
|
393
369
|
value: unknown;
|
|
@@ -420,6 +396,22 @@ type ConfigFieldRendererProps = {
|
|
|
420
396
|
value: unknown;
|
|
421
397
|
onChange: (next: unknown) => void;
|
|
422
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>;
|
|
423
415
|
};
|
|
424
416
|
/**
|
|
425
417
|
* ConfigFieldRenderer — dispatches to the right input element per field type.
|
|
@@ -432,7 +424,50 @@ type ConfigFieldRendererProps = {
|
|
|
432
424
|
* Each control carries the caller's `id` and a `data-ff-field` handle keyed by
|
|
433
425
|
* the field, so a label can point at it and an agent can find it by name.
|
|
434
426
|
*/
|
|
435
|
-
declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
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;
|
|
436
471
|
|
|
437
472
|
/** Entry-point node — outputs only, no inputs. */
|
|
438
473
|
declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
@@ -580,4 +615,72 @@ type FlowRunFeedProps = {
|
|
|
580
615
|
*/
|
|
581
616
|
declare function FlowRunFeed({ entries, showHeader, title, running, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
582
617
|
|
|
583
|
-
|
|
618
|
+
/**
|
|
619
|
+
* The fancy-flow Live Contract — the run / job stream shape.
|
|
620
|
+
*
|
|
621
|
+
* Pure data, with `LiveContract` imported as a TYPE, so this adds no dependency.
|
|
622
|
+
* `FancyFlow\Laravel\LiveContract` declares the identical list and both sides
|
|
623
|
+
* assert parity.
|
|
624
|
+
*
|
|
625
|
+
* ## What makes this shape different
|
|
626
|
+
*
|
|
627
|
+
* A run emits far more than it stores. `NodeStatusChanged` and `NodeOutput`
|
|
628
|
+
* fire per node, many times a second on a wide graph — and a node's log line is
|
|
629
|
+
* not a cache entry, it is a **stream**. So the contract covers the run's
|
|
630
|
+
* DURABLE state (does this run exist, has it finished, is it waiting on a
|
|
631
|
+
* person) and deliberately leaves per-node chatter to `useFancyStream`, the
|
|
632
|
+
* same split the whiteboard makes between its document and its cursors.
|
|
633
|
+
*
|
|
634
|
+
* Get that wrong and a 40-node run invalidates the run list forty times while
|
|
635
|
+
* it executes, each one a re-fetch that tells the UI nothing it did not already
|
|
636
|
+
* learn from the stream.
|
|
637
|
+
*
|
|
638
|
+
* ## `awaiting` is the one that matters
|
|
639
|
+
*
|
|
640
|
+
* A run parking on a human step is the event a host most needs to react to —
|
|
641
|
+
* it is when a form has to appear in front of somebody. It gets its own event
|
|
642
|
+
* rather than folding into `updated`, so a host can subscribe to just that.
|
|
643
|
+
*
|
|
644
|
+
* ## Broadcast status, stated plainly
|
|
645
|
+
*
|
|
646
|
+
* `fancy-flow-php` currently dispatches these as **in-process Laravel events**;
|
|
647
|
+
* none of them implement `ShouldBroadcast` yet. This contract is therefore the
|
|
648
|
+
* agreed vocabulary rather than a description of traffic already on the wire: a
|
|
649
|
+
* host that wants live runs today re-broadcasts these under these names. Making
|
|
650
|
+
* the PHP events broadcast natively is a separate change, because it turns on
|
|
651
|
+
* websocket traffic for every consumer.
|
|
652
|
+
*/
|
|
653
|
+
declare const flowLive: {
|
|
654
|
+
readonly namespace: "flow";
|
|
655
|
+
readonly events: readonly [{
|
|
656
|
+
readonly event: "flow.run.created";
|
|
657
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
658
|
+
}, {
|
|
659
|
+
readonly event: "flow.run.updated";
|
|
660
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
661
|
+
}, {
|
|
662
|
+
readonly event: "flow.run.completed";
|
|
663
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
664
|
+
}, {
|
|
665
|
+
readonly event: "flow.run.awaiting";
|
|
666
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
667
|
+
readonly note: "A run parking on a human step — the moment a form has to appear in front of somebody. Its own event so a host can subscribe to just that, rather than filtering every update.";
|
|
668
|
+
}, {
|
|
669
|
+
readonly event: "flow.run.failed";
|
|
670
|
+
readonly keys: readonly [readonly ["flow", "runs"]];
|
|
671
|
+
readonly note: "Not one of the standard verbs: a failed run is a terminal state a host renders differently from a completed one, so collapsing the two would lose the distinction.";
|
|
672
|
+
}];
|
|
673
|
+
};
|
|
674
|
+
/**
|
|
675
|
+
* Per-run keys, for a host showing a single run rather than the list.
|
|
676
|
+
*
|
|
677
|
+
* The contract declares prefixes because it is static data and a run id is not
|
|
678
|
+
* known until runtime. TanStack matches by prefix, so `["flow", "runs"]` still
|
|
679
|
+
* invalidates `["flow", "runs", runId]`.
|
|
680
|
+
*/
|
|
681
|
+
declare const flowKeys: {
|
|
682
|
+
readonly runs: () => readonly ["flow", "runs"];
|
|
683
|
+
readonly run: (runId: string) => readonly ["flow", "runs", string];
|
|
684
|
+
};
|
|
685
|
+
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -115,9 +115,15 @@ function ConfigFieldRenderer({
|
|
|
115
115
|
onChange,
|
|
116
116
|
id,
|
|
117
117
|
renderCredentialField,
|
|
118
|
-
renderDocumentField
|
|
118
|
+
renderDocumentField,
|
|
119
|
+
fieldRenderers
|
|
119
120
|
}) {
|
|
120
121
|
const handle = { id, "data-ff-field": field.key };
|
|
122
|
+
const custom = fieldRenderers?.[field.type];
|
|
123
|
+
if (custom) {
|
|
124
|
+
const rendered = custom({ field, value, onChange, id });
|
|
125
|
+
if (rendered !== null && rendered !== void 0) return /* @__PURE__ */ jsx(Fragment, { children: rendered });
|
|
126
|
+
}
|
|
121
127
|
switch (field.type) {
|
|
122
128
|
case "text": {
|
|
123
129
|
if (field.choices?.length) {
|
|
@@ -225,7 +231,8 @@ function ConfigFieldRenderer({
|
|
|
225
231
|
value,
|
|
226
232
|
onChange,
|
|
227
233
|
renderCredentialField,
|
|
228
|
-
renderDocumentField
|
|
234
|
+
renderDocumentField,
|
|
235
|
+
fieldRenderers
|
|
229
236
|
}
|
|
230
237
|
);
|
|
231
238
|
case "keyvalue":
|
|
@@ -278,7 +285,8 @@ function RepeaterField({
|
|
|
278
285
|
value,
|
|
279
286
|
onChange,
|
|
280
287
|
renderCredentialField,
|
|
281
|
-
renderDocumentField
|
|
288
|
+
renderDocumentField,
|
|
289
|
+
fieldRenderers
|
|
282
290
|
}) {
|
|
283
291
|
const rows = Array.isArray(value) ? value : [];
|
|
284
292
|
const max = field.maxItems ?? Infinity;
|
|
@@ -360,7 +368,8 @@ function RepeaterField({
|
|
|
360
368
|
value: row[sub.key],
|
|
361
369
|
onChange: (cell) => setCell(i, sub.key, cell),
|
|
362
370
|
renderCredentialField,
|
|
363
|
-
renderDocumentField
|
|
371
|
+
renderDocumentField,
|
|
372
|
+
fieldRenderers
|
|
364
373
|
}
|
|
365
374
|
)
|
|
366
375
|
] }, sub.key))
|
|
@@ -492,6 +501,7 @@ function NodeConfigPanel({
|
|
|
492
501
|
header,
|
|
493
502
|
renderCredentialField,
|
|
494
503
|
renderDocumentField,
|
|
504
|
+
fieldRenderers,
|
|
495
505
|
className,
|
|
496
506
|
style
|
|
497
507
|
}) {
|
|
@@ -596,7 +606,8 @@ function NodeConfigPanel({
|
|
|
596
606
|
value: config[field.key],
|
|
597
607
|
onChange: (v) => setConfigValue(field.key, v),
|
|
598
608
|
renderCredentialField,
|
|
599
|
-
renderDocumentField: documentField
|
|
609
|
+
renderDocumentField: documentField,
|
|
610
|
+
fieldRenderers
|
|
600
611
|
}
|
|
601
612
|
)
|
|
602
613
|
] }, field.key))
|
|
@@ -1506,9 +1517,33 @@ function NodePort({ side, type, id, style, title, className }) {
|
|
|
1506
1517
|
);
|
|
1507
1518
|
}
|
|
1508
1519
|
|
|
1520
|
+
// src/live.ts
|
|
1521
|
+
var flowLive = {
|
|
1522
|
+
namespace: "flow",
|
|
1523
|
+
events: [
|
|
1524
|
+
{ event: "flow.run.created", keys: [["flow", "runs"]] },
|
|
1525
|
+
{ event: "flow.run.updated", keys: [["flow", "runs"]] },
|
|
1526
|
+
{ event: "flow.run.completed", keys: [["flow", "runs"]] },
|
|
1527
|
+
{
|
|
1528
|
+
event: "flow.run.awaiting",
|
|
1529
|
+
keys: [["flow", "runs"]],
|
|
1530
|
+
note: "A run parking on a human step \u2014 the moment a form has to appear in front of somebody. Its own event so a host can subscribe to just that, rather than filtering every update."
|
|
1531
|
+
},
|
|
1532
|
+
{
|
|
1533
|
+
event: "flow.run.failed",
|
|
1534
|
+
keys: [["flow", "runs"]],
|
|
1535
|
+
note: "Not one of the standard verbs: a failed run is a terminal state a host renders differently from a completed one, so collapsing the two would lose the distinction."
|
|
1536
|
+
}
|
|
1537
|
+
]
|
|
1538
|
+
};
|
|
1539
|
+
var flowKeys = {
|
|
1540
|
+
runs: () => ["flow", "runs"],
|
|
1541
|
+
run: (runId) => ["flow", "runs", runId]
|
|
1542
|
+
};
|
|
1543
|
+
|
|
1509
1544
|
// src/index.ts
|
|
1510
1545
|
registerBuiltinKinds();
|
|
1511
1546
|
|
|
1512
|
-
export { ConfigFieldRenderer, FlowEditor, FlowRunControls, FlowRunFeed, NodeConfigPanel, NodePalette, NodePort, defineNode, paletteDropHandlers };
|
|
1547
|
+
export { ConfigFieldRenderer, FlowEditor, FlowRunControls, FlowRunFeed, NodeConfigPanel, NodePalette, NodePort, defineNode, flowKeys, flowLive, paletteDropHandlers };
|
|
1513
1548
|
//# sourceMappingURL=index.js.map
|
|
1514
1549
|
//# sourceMappingURL=index.js.map
|