@particle-academy/fancy-flow 0.24.0 → 0.26.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 (41) hide show
  1. package/dist/{chunk-OHVSEHDC.js → chunk-N5ICD2WZ.js} +3 -3
  2. package/dist/{chunk-OHVSEHDC.js.map → chunk-N5ICD2WZ.js.map} +1 -1
  3. package/dist/{chunk-ZS6DVGB3.js → chunk-OFW7GN3Y.js} +4 -4
  4. package/dist/{chunk-ZS6DVGB3.js.map → chunk-OFW7GN3Y.js.map} +1 -1
  5. package/dist/{chunk-YXRLIV7A.js → chunk-Q6IPK64P.js} +4 -2
  6. package/dist/chunk-Q6IPK64P.js.map +1 -0
  7. package/dist/{chunk-KDHLKBL2.js → chunk-U2VJB7HR.js} +7 -5
  8. package/dist/chunk-U2VJB7HR.js.map +1 -0
  9. package/dist/{chunk-QAA4CA22.js → chunk-YOFCVO2W.js} +118 -6
  10. package/dist/chunk-YOFCVO2W.js.map +1 -0
  11. package/dist/engine.cjs +4 -2
  12. package/dist/engine.cjs.map +1 -1
  13. package/dist/engine.js +3 -3
  14. package/dist/index.cjs +287 -24
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -8
  17. package/dist/index.d.ts +3 -8
  18. package/dist/index.js +180 -33
  19. package/dist/index.js.map +1 -1
  20. package/dist/registry/index.d.cts +2 -2
  21. package/dist/registry/index.d.ts +2 -2
  22. package/dist/registry.cjs +111 -2
  23. package/dist/registry.cjs.map +1 -1
  24. package/dist/registry.js +3 -3
  25. package/dist/runtime.cjs +4 -2
  26. package/dist/runtime.cjs.map +1 -1
  27. package/dist/runtime.js +3 -3
  28. package/dist/schema.cjs.map +1 -1
  29. package/dist/schema.js +2 -2
  30. package/dist/styles.css +198 -0
  31. package/dist/styles.css.map +1 -1
  32. package/dist/{types-DwRpXXNy.d.ts → types-BGtR3k9J.d.ts} +1 -1
  33. package/dist/{types-BekE5JTG.d.cts → types-B_pxRqfw.d.cts} +1 -1
  34. package/dist/ux.cjs.map +1 -1
  35. package/dist/ux.d.cts +1 -1
  36. package/dist/ux.d.ts +1 -1
  37. package/dist/ux.js +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-KDHLKBL2.js.map +0 -1
  40. package/dist/chunk-QAA4CA22.js.map +0 -1
  41. package/dist/chunk-YXRLIV7A.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { a as NodeKindDefinition, P as PortSpec } from '../types-BekE5JTG.cjs';
2
- export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-BekE5JTG.cjs';
1
+ import { a as NodeKindDefinition, P as PortSpec } from '../types-B_pxRqfw.cjs';
2
+ export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-B_pxRqfw.cjs';
3
3
  import { P as PortDescriptor, a as FlowNode, N as NodeExecutor } from '../types-CMSrWVYM.cjs';
4
4
  import { Connection, Edge, NodeProps, NodeTypes } from '@xyflow/react';
5
5
  import { b as LlmRoute } from '../capabilities-exVeADXz.cjs';
@@ -1,5 +1,5 @@
1
- import { a as NodeKindDefinition, P as PortSpec } from '../types-DwRpXXNy.js';
2
- export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-DwRpXXNy.js';
1
+ import { a as NodeKindDefinition, P as PortSpec } from '../types-BGtR3k9J.js';
2
+ export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-BGtR3k9J.js';
3
3
  import { P as PortDescriptor, a as FlowNode, N as NodeExecutor } from '../types-CMSrWVYM.js';
4
4
  import { Connection, Edge, NodeProps, NodeTypes } from '@xyflow/react';
5
5
  import { b as LlmRoute } from '../capabilities-85Mjn4uW.js';
package/dist/registry.cjs CHANGED
@@ -181,6 +181,8 @@ function categoryAccent(category) {
181
181
  return "#a855f7";
182
182
  case "layout":
183
183
  return "#64748b";
184
+ case "annotation":
185
+ return "#eab308";
184
186
  default:
185
187
  return "#71717a";
186
188
  }
@@ -324,12 +326,14 @@ async function runFlow(graph, executors, onEvent = () => {
324
326
  }
325
327
  }
326
328
  const visualKind = getNodeKind(node.type ?? "");
327
- if (node.type === "note" || visualKind?.category === "layout") {
329
+ const isLayout = visualKind?.category === "layout";
330
+ const isAnnotation = node.type === "note" || visualKind?.category === "annotation";
331
+ if (isLayout || isAnnotation) {
328
332
  onEvent({
329
333
  type: "node-status",
330
334
  nodeId: node.id,
331
335
  status: "idle",
332
- text: visualKind?.category === "layout" ? "lane" : "annotation"
336
+ text: isLayout ? "lane" : "annotation"
333
337
  });
334
338
  continue;
335
339
  }
@@ -9711,6 +9715,7 @@ function portStyle(i, total) {
9711
9715
  }
9712
9716
  function DefaultBody({ config, kind }) {
9713
9717
  const fields = kind ?? [];
9718
+ if (fields.length === 0) return null;
9714
9719
  const visible = fields.map((f) => ({ field: f, value: config[f.key] })).filter(({ value }) => value !== void 0 && value !== "" && value !== null);
9715
9720
  if (visible.length === 0) {
9716
9721
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-node__body-empty", children: "\u2014 configure in the panel" });
@@ -9776,6 +9781,81 @@ function LaneNodeInner(props) {
9776
9781
  );
9777
9782
  }
9778
9783
  var LaneNode = ReactExports.memo(LaneNodeInner);
9784
+ var FlowEditorContext = ReactExports.createContext(null);
9785
+ FlowEditorContext.Provider;
9786
+ function useFlowEditorOptional() {
9787
+ return ReactExports.useContext(FlowEditorContext);
9788
+ }
9789
+ var NOTE_COLORS = {
9790
+ amber: { bg: "rgba(234, 179, 8, 0.14)", border: "rgba(234, 179, 8, 0.55)", title: "#a16207" },
9791
+ sky: { bg: "rgba(14, 165, 233, 0.12)", border: "rgba(14, 165, 233, 0.5)", title: "#0369a1" },
9792
+ violet: { bg: "rgba(139, 92, 246, 0.13)", border: "rgba(139, 92, 246, 0.5)", title: "#6d28d9" },
9793
+ emerald: { bg: "rgba(16, 185, 129, 0.13)", border: "rgba(16, 185, 129, 0.5)", title: "#047857" },
9794
+ rose: { bg: "rgba(244, 63, 94, 0.12)", border: "rgba(244, 63, 94, 0.5)", title: "#be123c" },
9795
+ slate: { bg: "rgba(100, 116, 139, 0.12)", border: "rgba(100, 116, 139, 0.5)", title: "#475569" }
9796
+ };
9797
+ function coerceColor(v) {
9798
+ return typeof v === "string" && v in NOTE_COLORS ? v : "amber";
9799
+ }
9800
+ function NoteNodeInner(props) {
9801
+ const data = props.data;
9802
+ const config = data.config ?? {};
9803
+ const api = useFlowEditorOptional();
9804
+ const hasConfigText = typeof config.text === "string" && config.text.length > 0;
9805
+ const text = hasConfigText ? String(config.text) : typeof data.body === "string" ? data.body : typeof data.text === "string" ? data.text : "";
9806
+ const title = typeof config.title === "string" && config.title || (!hasConfigText && typeof data.body === "string" && typeof data.label === "string" ? data.label : "");
9807
+ const skin = NOTE_COLORS[coerceColor(config.color)];
9808
+ const [editing, setEditing] = ReactExports.useState(false);
9809
+ const [draft, setDraft] = ReactExports.useState(text);
9810
+ const areaRef = ReactExports.useRef(null);
9811
+ ReactExports.useEffect(() => {
9812
+ if (editing && areaRef.current) {
9813
+ const el = areaRef.current;
9814
+ el.focus();
9815
+ el.setSelectionRange(el.value.length, el.value.length);
9816
+ }
9817
+ }, [editing]);
9818
+ const commit = () => {
9819
+ setEditing(false);
9820
+ if (!api || draft === text) return;
9821
+ const current = api.nodes.find((n) => n.id === props.id);
9822
+ if (!current) return;
9823
+ api.updateNode({
9824
+ ...current,
9825
+ data: { ...current.data, config: { ...config, text: draft } }
9826
+ });
9827
+ };
9828
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9829
+ "div",
9830
+ {
9831
+ className: ["ff-note", props.selected ? "ff-note--selected" : ""].filter(Boolean).join(" "),
9832
+ style: { background: skin.bg, borderColor: skin.border },
9833
+ onDoubleClick: api ? () => {
9834
+ setDraft(text);
9835
+ setEditing(true);
9836
+ } : void 0,
9837
+ children: [
9838
+ /* @__PURE__ */ jsxRuntime.jsx(NodeResizer, { isVisible: props.selected ?? false, color: skin.border, minWidth: 140, minHeight: 80 }),
9839
+ title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-note__title", style: { color: skin.title }, children: title }),
9840
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
9841
+ "textarea",
9842
+ {
9843
+ ref: areaRef,
9844
+ className: "ff-note__input nodrag nowheel",
9845
+ value: draft,
9846
+ onChange: (e) => setDraft(e.target.value),
9847
+ onBlur: commit,
9848
+ onKeyDown: (e) => {
9849
+ if (e.key === "Escape") setEditing(false);
9850
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) commit();
9851
+ }
9852
+ }
9853
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ff-note__body", children: text || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-note__placeholder", children: api ? "Double-click to write a note\u2026" : "Note" }) })
9854
+ ]
9855
+ }
9856
+ );
9857
+ }
9858
+ var NoteNode = ReactExports.memo(NoteNodeInner);
9779
9859
 
9780
9860
  // src/registry/builtin.ts
9781
9861
  function casePorts(cases) {
@@ -10544,6 +10624,35 @@ var KINDS = [
10544
10624
  defaultConfig: { title: "Lane", orientation: "horizontal" },
10545
10625
  resizable: { minWidth: 160, minHeight: 72 },
10546
10626
  component: LaneNode
10627
+ },
10628
+ {
10629
+ // Note — a sticky-note annotation. Portless + visual-only: the runtime skips
10630
+ // the `annotation` category, so a note's text NEVER reaches a runner — it
10631
+ // rides in the document purely for people, editors, and MCP tools. Uses its
10632
+ // own renderer (NoteNode); double-click on the canvas to edit in place.
10633
+ name: "@particle-academy/note",
10634
+ aliases: ["note", "@fancy/note"],
10635
+ category: "annotation",
10636
+ label: "Note",
10637
+ description: "A sticky note that documents the canvas. Never runs \u2014 editor + agent only.",
10638
+ icon: "\u{1F5D2}",
10639
+ inputs: [],
10640
+ outputs: [],
10641
+ configSchema: [
10642
+ { type: "text", key: "title", label: "Title", placeholder: "Optional heading" },
10643
+ { type: "textarea", key: "text", label: "Note", rows: 5, placeholder: "What does this part of the flow do?" },
10644
+ { type: "select", key: "color", label: "Color", default: "amber", options: [
10645
+ { value: "amber", label: "Amber" },
10646
+ { value: "sky", label: "Sky" },
10647
+ { value: "violet", label: "Violet" },
10648
+ { value: "emerald", label: "Emerald" },
10649
+ { value: "rose", label: "Rose" },
10650
+ { value: "slate", label: "Slate" }
10651
+ ] }
10652
+ ],
10653
+ defaultConfig: { text: "", color: "amber" },
10654
+ resizable: { minWidth: 140, minHeight: 80 },
10655
+ component: NoteNode
10547
10656
  }
10548
10657
  ];
10549
10658
  function registerBuiltinKinds() {