@particle-academy/fancy-flow 0.33.0 → 0.33.2
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 +24 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +25 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -391,6 +391,17 @@ type ConfigFieldRendererProps = {
|
|
|
391
391
|
field: ConfigField;
|
|
392
392
|
value: unknown;
|
|
393
393
|
onChange: (value: unknown) => void;
|
|
394
|
+
/**
|
|
395
|
+
* DOM id for the control this renders.
|
|
396
|
+
*
|
|
397
|
+
* Supplied by the caller rather than generated here so the panel's `<label>`
|
|
398
|
+
* can point at it — a label beside a control is not a label attached to one.
|
|
399
|
+
* Also the agent-facing handle: the Human+ contract asks that every
|
|
400
|
+
* interactive element have a stable identity so an agent targets it instead
|
|
401
|
+
* of guessing at the DOM, and until this existed nothing in the editor had
|
|
402
|
+
* one.
|
|
403
|
+
*/
|
|
404
|
+
id?: string;
|
|
394
405
|
renderCredentialField?: (props: {
|
|
395
406
|
credentialType: string;
|
|
396
407
|
value: unknown;
|
|
@@ -410,14 +421,17 @@ type ConfigFieldRendererProps = {
|
|
|
410
421
|
}) => ReactNode;
|
|
411
422
|
};
|
|
412
423
|
/**
|
|
413
|
-
* ConfigFieldRenderer — dispatches to the right input element per field
|
|
414
|
-
*
|
|
415
|
-
*
|
|
424
|
+
* ConfigFieldRenderer — dispatches to the right input element per field type.
|
|
425
|
+
*
|
|
426
|
+
* Plain HTML inputs styled via the package's CSS so the package stays
|
|
427
|
+
* standalone (no react-fancy import required) and every surface stays themeable
|
|
428
|
+
* through the `--ff-*` token layer. Hosts that want react-fancy form components
|
|
429
|
+
* can supply their own field renderers via the kind's `renderPanel`.
|
|
416
430
|
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
431
|
+
* Each control carries the caller's `id` and a `data-ff-field` handle keyed by
|
|
432
|
+
* the field, so a label can point at it and an agent can find it by name.
|
|
419
433
|
*/
|
|
420
|
-
declare function ConfigFieldRenderer({ field, value, onChange, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
434
|
+
declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
421
435
|
|
|
422
436
|
/** Entry-point node — outputs only, no inputs. */
|
|
423
437
|
declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -391,6 +391,17 @@ type ConfigFieldRendererProps = {
|
|
|
391
391
|
field: ConfigField;
|
|
392
392
|
value: unknown;
|
|
393
393
|
onChange: (value: unknown) => void;
|
|
394
|
+
/**
|
|
395
|
+
* DOM id for the control this renders.
|
|
396
|
+
*
|
|
397
|
+
* Supplied by the caller rather than generated here so the panel's `<label>`
|
|
398
|
+
* can point at it — a label beside a control is not a label attached to one.
|
|
399
|
+
* Also the agent-facing handle: the Human+ contract asks that every
|
|
400
|
+
* interactive element have a stable identity so an agent targets it instead
|
|
401
|
+
* of guessing at the DOM, and until this existed nothing in the editor had
|
|
402
|
+
* one.
|
|
403
|
+
*/
|
|
404
|
+
id?: string;
|
|
394
405
|
renderCredentialField?: (props: {
|
|
395
406
|
credentialType: string;
|
|
396
407
|
value: unknown;
|
|
@@ -410,14 +421,17 @@ type ConfigFieldRendererProps = {
|
|
|
410
421
|
}) => ReactNode;
|
|
411
422
|
};
|
|
412
423
|
/**
|
|
413
|
-
* ConfigFieldRenderer — dispatches to the right input element per field
|
|
414
|
-
*
|
|
415
|
-
*
|
|
424
|
+
* ConfigFieldRenderer — dispatches to the right input element per field type.
|
|
425
|
+
*
|
|
426
|
+
* Plain HTML inputs styled via the package's CSS so the package stays
|
|
427
|
+
* standalone (no react-fancy import required) and every surface stays themeable
|
|
428
|
+
* through the `--ff-*` token layer. Hosts that want react-fancy form components
|
|
429
|
+
* can supply their own field renderers via the kind's `renderPanel`.
|
|
416
430
|
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
431
|
+
* Each control carries the caller's `id` and a `data-ff-field` handle keyed by
|
|
432
|
+
* the field, so a label can point at it and an agent can find it by name.
|
|
419
433
|
*/
|
|
420
|
-
declare function ConfigFieldRenderer({ field, value, onChange, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
434
|
+
declare function ConfigFieldRenderer({ field, value, onChange, id, renderCredentialField, renderDocumentField, }: ConfigFieldRendererProps): react.JSX.Element | null;
|
|
421
435
|
|
|
422
436
|
/** Entry-point node — outputs only, no inputs. */
|
|
423
437
|
declare function TriggerNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, valid
|
|
|
14
14
|
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-Q6IPK64P.js';
|
|
15
15
|
import { getRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
16
16
|
export { RichInputPreview, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
17
|
-
import { memo, forwardRef, useState, useMemo, useEffect, useCallback, useRef, useImperativeHandle } from 'react';
|
|
17
|
+
import { memo, forwardRef, useState, useMemo, useEffect, useCallback, useRef, useImperativeHandle, useId } from 'react';
|
|
18
18
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
19
19
|
|
|
20
20
|
function NodeShellInner({
|
|
@@ -565,9 +565,11 @@ function ConfigFieldRenderer({
|
|
|
565
565
|
field,
|
|
566
566
|
value,
|
|
567
567
|
onChange,
|
|
568
|
+
id,
|
|
568
569
|
renderCredentialField,
|
|
569
570
|
renderDocumentField
|
|
570
571
|
}) {
|
|
572
|
+
const handle = { id, "data-ff-field": field.key };
|
|
571
573
|
switch (field.type) {
|
|
572
574
|
case "text": {
|
|
573
575
|
if (field.choices?.length) {
|
|
@@ -576,6 +578,7 @@ function ConfigFieldRenderer({
|
|
|
576
578
|
return /* @__PURE__ */ jsx(
|
|
577
579
|
"input",
|
|
578
580
|
{
|
|
581
|
+
...handle,
|
|
579
582
|
className: "ff-panel__input",
|
|
580
583
|
type: "text",
|
|
581
584
|
value: value ?? "",
|
|
@@ -588,6 +591,7 @@ function ConfigFieldRenderer({
|
|
|
588
591
|
return /* @__PURE__ */ jsx(
|
|
589
592
|
"textarea",
|
|
590
593
|
{
|
|
594
|
+
...handle,
|
|
591
595
|
className: "ff-panel__input ff-panel__input--textarea",
|
|
592
596
|
rows: field.rows ?? 4,
|
|
593
597
|
value: value ?? "",
|
|
@@ -599,6 +603,7 @@ function ConfigFieldRenderer({
|
|
|
599
603
|
return /* @__PURE__ */ jsx(
|
|
600
604
|
"input",
|
|
601
605
|
{
|
|
606
|
+
...handle,
|
|
602
607
|
className: "ff-panel__input",
|
|
603
608
|
type: "number",
|
|
604
609
|
value: value ?? "",
|
|
@@ -613,6 +618,7 @@ function ConfigFieldRenderer({
|
|
|
613
618
|
/* @__PURE__ */ jsx(
|
|
614
619
|
"input",
|
|
615
620
|
{
|
|
621
|
+
...handle,
|
|
616
622
|
type: "checkbox",
|
|
617
623
|
checked: !!value,
|
|
618
624
|
onChange: (e) => onChange(e.target.checked)
|
|
@@ -624,6 +630,7 @@ function ConfigFieldRenderer({
|
|
|
624
630
|
return /* @__PURE__ */ jsxs(
|
|
625
631
|
"select",
|
|
626
632
|
{
|
|
633
|
+
...handle,
|
|
627
634
|
className: "ff-panel__input",
|
|
628
635
|
value: value ?? "",
|
|
629
636
|
onChange: (e) => onChange(e.target.value),
|
|
@@ -639,6 +646,7 @@ function ConfigFieldRenderer({
|
|
|
639
646
|
return /* @__PURE__ */ jsx(
|
|
640
647
|
"textarea",
|
|
641
648
|
{
|
|
649
|
+
...handle,
|
|
642
650
|
className: "ff-panel__input ff-panel__input--expression",
|
|
643
651
|
rows: 2,
|
|
644
652
|
value: value ?? "",
|
|
@@ -939,15 +947,20 @@ function NodeConfigPanel({
|
|
|
939
947
|
className,
|
|
940
948
|
style
|
|
941
949
|
}) {
|
|
950
|
+
const uid = useId();
|
|
951
|
+
const kindName = node ? node.data.kind ?? node.type : null;
|
|
952
|
+
const kind = useMemo(() => kindName ? getNodeKind(kindName) : void 0, [kindName]);
|
|
953
|
+
const config = useMemo(
|
|
954
|
+
() => node?.data?.config ?? {},
|
|
955
|
+
[node?.data]
|
|
956
|
+
);
|
|
957
|
+
const fieldId = (key) => `${uid}-${key}`;
|
|
942
958
|
if (!node) {
|
|
943
959
|
return /* @__PURE__ */ jsxs("aside", { className: ["ff-panel", "ff-panel--empty", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
944
960
|
header,
|
|
945
961
|
/* @__PURE__ */ jsx("p", { className: "ff-panel__empty", children: "Select a node to configure it." })
|
|
946
962
|
] });
|
|
947
963
|
}
|
|
948
|
-
const kindName = node.data.kind ?? node.type;
|
|
949
|
-
const kind = useMemo(() => getNodeKind(kindName), [kindName]);
|
|
950
|
-
const config = useMemo(() => node.data.config ?? {}, [node.data]);
|
|
951
964
|
if (!kind) {
|
|
952
965
|
return /* @__PURE__ */ jsxs("aside", { className: ["ff-panel", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
953
966
|
header,
|
|
@@ -988,10 +1001,12 @@ function NodeConfigPanel({
|
|
|
988
1001
|
] }),
|
|
989
1002
|
kind.description && /* @__PURE__ */ jsx("p", { className: "ff-panel__kind-desc", children: kind.description }),
|
|
990
1003
|
/* @__PURE__ */ jsxs("div", { className: "ff-panel__field", children: [
|
|
991
|
-
/* @__PURE__ */ jsx("label", { className: "ff-panel__label", children: "Label" }),
|
|
1004
|
+
/* @__PURE__ */ jsx("label", { className: "ff-panel__label", htmlFor: fieldId("label"), children: "Label" }),
|
|
992
1005
|
/* @__PURE__ */ jsx(
|
|
993
1006
|
"input",
|
|
994
1007
|
{
|
|
1008
|
+
id: fieldId("label"),
|
|
1009
|
+
"data-ff-field": "label",
|
|
995
1010
|
className: "ff-panel__input",
|
|
996
1011
|
value: node.data.label ?? "",
|
|
997
1012
|
onChange: (e) => setLabel(e.target.value),
|
|
@@ -1000,10 +1015,12 @@ function NodeConfigPanel({
|
|
|
1000
1015
|
)
|
|
1001
1016
|
] }),
|
|
1002
1017
|
/* @__PURE__ */ jsxs("div", { className: "ff-panel__field", children: [
|
|
1003
|
-
/* @__PURE__ */ jsx("label", { className: "ff-panel__label", children: "Description" }),
|
|
1018
|
+
/* @__PURE__ */ jsx("label", { className: "ff-panel__label", htmlFor: fieldId("description"), children: "Description" }),
|
|
1004
1019
|
/* @__PURE__ */ jsx(
|
|
1005
1020
|
"textarea",
|
|
1006
1021
|
{
|
|
1022
|
+
id: fieldId("description"),
|
|
1023
|
+
"data-ff-field": "description",
|
|
1007
1024
|
className: "ff-panel__input ff-panel__input--textarea",
|
|
1008
1025
|
rows: 2,
|
|
1009
1026
|
value: node.data.description ?? "",
|
|
@@ -1018,7 +1035,7 @@ function NodeConfigPanel({
|
|
|
1018
1035
|
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1019
1036
|
(kind.configSchema ?? []).length > 0 && /* @__PURE__ */ jsx("hr", { className: "ff-panel__divider" }),
|
|
1020
1037
|
(kind.configSchema ?? []).map((field) => /* @__PURE__ */ jsxs("div", { className: "ff-panel__field", children: [
|
|
1021
|
-
/* @__PURE__ */ jsxs("label", { className: "ff-panel__label", children: [
|
|
1038
|
+
/* @__PURE__ */ jsxs("label", { className: "ff-panel__label", htmlFor: fieldId(field.key), children: [
|
|
1022
1039
|
field.label,
|
|
1023
1040
|
field.required && /* @__PURE__ */ jsx("span", { className: "ff-panel__required", "aria-hidden": true, children: " *" })
|
|
1024
1041
|
] }),
|
|
@@ -1026,6 +1043,7 @@ function NodeConfigPanel({
|
|
|
1026
1043
|
/* @__PURE__ */ jsx(
|
|
1027
1044
|
ConfigFieldRenderer,
|
|
1028
1045
|
{
|
|
1046
|
+
id: fieldId(field.key),
|
|
1029
1047
|
field,
|
|
1030
1048
|
value: config[field.key],
|
|
1031
1049
|
onChange: (v) => setConfigValue(field.key, v),
|