@flowdrop/flowdrop 2.0.0-beta.3 → 2.0.0-beta.5

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 (87) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +5 -5
  3. package/dist/adapters/WorkflowAdapter.js +4 -5
  4. package/dist/adapters/agentspec/AgentSpecAdapter.js +3 -3
  5. package/dist/adapters/agentspec/defaultNodeTypes.js +9 -9
  6. package/dist/commands/executor.js +5 -6
  7. package/dist/commands/types.js +5 -5
  8. package/dist/components/App.svelte +19 -150
  9. package/dist/components/Button.stories.svelte +65 -0
  10. package/dist/components/Button.stories.svelte.d.ts +19 -0
  11. package/dist/components/Button.svelte +62 -0
  12. package/dist/components/Button.svelte.d.ts +24 -0
  13. package/dist/components/ConfigForm.svelte +4 -4
  14. package/dist/components/EditorStatusBar.stories.svelte +44 -0
  15. package/dist/components/EditorStatusBar.stories.svelte.d.ts +27 -0
  16. package/dist/components/EditorStatusBar.svelte +99 -0
  17. package/dist/components/EditorStatusBar.svelte.d.ts +15 -0
  18. package/dist/components/IconButton.svelte +80 -0
  19. package/dist/components/IconButton.svelte.d.ts +30 -0
  20. package/dist/components/Input.svelte +74 -0
  21. package/dist/components/Input.svelte.d.ts +17 -0
  22. package/dist/components/Navbar.svelte +9 -4
  23. package/dist/components/Navbar.svelte.d.ts +3 -0
  24. package/dist/components/NodeSidebar.svelte +17 -115
  25. package/dist/components/NodeSwapPicker.svelte +12 -28
  26. package/dist/components/Select.svelte +53 -0
  27. package/dist/components/Select.svelte.d.ts +15 -0
  28. package/dist/components/Textarea.svelte +39 -0
  29. package/dist/components/Textarea.svelte.d.ts +12 -0
  30. package/dist/components/ThemeToggle.svelte +15 -89
  31. package/dist/components/UniversalNode.svelte +5 -4
  32. package/dist/components/UniversalNode.svelte.d.ts +1 -1
  33. package/dist/components/console/ConsoleInput.svelte +3 -3
  34. package/dist/components/form/FormArray.svelte +37 -157
  35. package/dist/components/form/FormCheckboxGroup.svelte +1 -1
  36. package/dist/components/form/FormField.svelte +5 -44
  37. package/dist/components/form/FormFieldLight.svelte +5 -44
  38. package/dist/components/form/FormFieldset.svelte +1 -1
  39. package/dist/components/form/FormNumberField.svelte +4 -32
  40. package/dist/components/form/FormRangeField.svelte +17 -7
  41. package/dist/components/form/FormSelect.svelte +13 -79
  42. package/dist/components/form/FormTextField.svelte +3 -39
  43. package/dist/components/form/FormTextarea.svelte +4 -43
  44. package/dist/components/form/resolveFieldType.d.ts +24 -0
  45. package/dist/components/form/resolveFieldType.js +55 -0
  46. package/dist/components/icons/CloseIcon.svelte +6 -0
  47. package/dist/components/icons/CloseIcon.svelte.d.ts +26 -0
  48. package/dist/components/nodes/AtomNode.svelte +3 -3
  49. package/dist/components/nodes/AtomNode.svelte.d.ts +1 -1
  50. package/dist/components/nodes/GatewayNode.svelte +8 -11
  51. package/dist/components/nodes/GatewayNode.svelte.d.ts +1 -1
  52. package/dist/components/nodes/IdeaNode.svelte +10 -8
  53. package/dist/components/nodes/IdeaNode.svelte.d.ts +8 -4
  54. package/dist/components/nodes/NotesNode.svelte +6 -4
  55. package/dist/components/nodes/NotesNode.svelte.d.ts +8 -4
  56. package/dist/components/nodes/SimpleNode.svelte +10 -8
  57. package/dist/components/nodes/SimpleNode.svelte.d.ts +4 -4
  58. package/dist/components/nodes/SquareNode.svelte +10 -8
  59. package/dist/components/nodes/SquareNode.svelte.d.ts +4 -4
  60. package/dist/components/nodes/TerminalNode.svelte +10 -8
  61. package/dist/components/nodes/TerminalNode.svelte.d.ts +4 -4
  62. package/dist/components/nodes/ToolNode.svelte +10 -8
  63. package/dist/components/nodes/ToolNode.svelte.d.ts +6 -6
  64. package/dist/components/nodes/WorkflowNode.svelte +7 -10
  65. package/dist/components/nodes/WorkflowNode.svelte.d.ts +1 -1
  66. package/dist/components/playground/InputCollector.svelte +11 -46
  67. package/dist/components/playground/PipelineKanbanView.svelte +2 -2
  68. package/dist/components/playground/PipelineTableView.svelte +2 -2
  69. package/dist/helpers/workflowEditorHelper.js +4 -5
  70. package/dist/messages/index.d.ts +1 -1
  71. package/dist/messages/index.js +1 -1
  72. package/dist/openapi/v1/openapi.yaml +2 -2
  73. package/dist/registry/nodeComponentRegistry.d.ts +2 -1
  74. package/dist/services/dynamicSchemaService.d.ts +2 -2
  75. package/dist/services/dynamicSchemaService.js +8 -8
  76. package/dist/skins/drafter.js +41 -28
  77. package/dist/stores/playgroundStore.svelte.js +1 -1
  78. package/dist/stores/workflowStore.svelte.js +0 -18
  79. package/dist/styles/base.css +247 -5
  80. package/dist/styles/tokens.css +6 -0
  81. package/dist/svelte-app.js +68 -107
  82. package/dist/types/index.d.ts +6 -7
  83. package/dist/utils/connections.js +20 -56
  84. package/dist/utils/nodeIds.d.ts +1 -1
  85. package/dist/utils/nodeIds.js +1 -1
  86. package/dist/utils/nodeSwap.js +3 -6
  87. package/package.json +1 -1
@@ -9,7 +9,7 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
- import Icon from '@iconify/svelte';
12
+ import Select from '../Select.svelte';
13
13
  import { normalizeOptions, type FieldOption } from './types.js';
14
14
 
15
15
  interface Props {
@@ -53,81 +53,15 @@
53
53
  }
54
54
  </script>
55
55
 
56
- <div class="form-select-wrapper">
57
- <select
58
- {id}
59
- class="form-select"
60
- value={value ?? ''}
61
- {disabled}
62
- aria-describedby={ariaDescribedBy}
63
- aria-required={required}
64
- onchange={handleChange}
65
- >
66
- {#each normalizedOptions as option (option.value)}
67
- <option value={option.value}>{option.label}</option>
68
- {/each}
69
- </select>
70
- <span class="form-select__icon" aria-hidden="true">
71
- <Icon icon="heroicons:chevron-down" />
72
- </span>
73
- </div>
74
-
75
- <style>
76
- .form-select-wrapper {
77
- position: relative;
78
- }
79
-
80
- .form-select {
81
- width: 100%;
82
- padding: 0.625rem 2.5rem 0.625rem 0.875rem;
83
- border: 1px solid var(--fd-border);
84
- border-radius: var(--fd-radius-lg);
85
- font-size: var(--fd-text-sm);
86
- font-family: inherit;
87
- color: var(--fd-foreground);
88
- background-color: var(--fd-background);
89
- transition: all var(--fd-transition-normal);
90
- box-shadow: var(--fd-shadow-sm);
91
- cursor: pointer;
92
- appearance: none;
93
- }
94
-
95
- .form-select:hover {
96
- border-color: var(--fd-border-strong);
97
- background-color: var(--fd-background);
98
- }
99
-
100
- .form-select:focus {
101
- border-color: var(--fd-ring);
102
- background-color: var(--fd-background);
103
- }
104
-
105
- .form-select:disabled {
106
- background-color: var(--fd-muted);
107
- border-color: var(--fd-border-muted);
108
- color: var(--fd-muted-foreground);
109
- cursor: not-allowed;
110
- opacity: 1;
111
- }
112
-
113
- .form-select__icon {
114
- position: absolute;
115
- right: 0.75rem;
116
- top: 50%;
117
- transform: translateY(-50%);
118
- pointer-events: none;
119
- color: var(--fd-muted-foreground);
120
- display: flex;
121
- align-items: center;
122
- transition: color var(--fd-transition-normal);
123
- }
124
-
125
- .form-select__icon :global(svg) {
126
- width: 1rem;
127
- height: 1rem;
128
- }
129
-
130
- .form-select:focus + .form-select__icon {
131
- color: var(--fd-primary);
132
- }
133
- </style>
56
+ <Select
57
+ {id}
58
+ value={value ?? ''}
59
+ {disabled}
60
+ aria-describedby={ariaDescribedBy}
61
+ aria-required={required}
62
+ onchange={handleChange}
63
+ >
64
+ {#each normalizedOptions as option (option.value)}
65
+ <option value={option.value}>{option.label}</option>
66
+ {/each}
67
+ </Select>
@@ -9,6 +9,8 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
+ import Input from '../Input.svelte';
13
+
12
14
  interface Props {
13
15
  /** Field identifier */
14
16
  id: string;
@@ -45,10 +47,9 @@
45
47
  }
46
48
  </script>
47
49
 
48
- <input
50
+ <Input
49
51
  {id}
50
52
  type="text"
51
- class="form-text-field"
52
53
  value={value ?? ''}
53
54
  {placeholder}
54
55
  {disabled}
@@ -56,40 +57,3 @@
56
57
  aria-required={required}
57
58
  oninput={handleInput}
58
59
  />
59
-
60
- <style>
61
- .form-text-field {
62
- width: 100%;
63
- padding: 0.625rem 0.875rem;
64
- border: 1px solid var(--fd-border);
65
- border-radius: var(--fd-radius-lg);
66
- font-size: var(--fd-text-sm);
67
- font-family: inherit;
68
- color: var(--fd-foreground);
69
- background-color: var(--fd-background);
70
- transition: all var(--fd-transition-normal);
71
- box-shadow: var(--fd-shadow-sm);
72
- }
73
-
74
- .form-text-field::placeholder {
75
- color: var(--fd-muted-foreground);
76
- }
77
-
78
- .form-text-field:hover {
79
- border-color: var(--fd-border-strong);
80
- background-color: var(--fd-background);
81
- }
82
-
83
- .form-text-field:focus {
84
- border-color: var(--fd-ring);
85
- background-color: var(--fd-background);
86
- }
87
-
88
- .form-text-field:disabled {
89
- background-color: var(--fd-muted);
90
- border-color: var(--fd-border-muted);
91
- color: var(--fd-muted-foreground);
92
- cursor: not-allowed;
93
- opacity: 1;
94
- }
95
- </style>
@@ -9,6 +9,8 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
+ import Textarea from '../Textarea.svelte';
13
+
12
14
  interface Props {
13
15
  /** Field identifier */
14
16
  id: string;
@@ -48,9 +50,8 @@
48
50
  }
49
51
  </script>
50
52
 
51
- <textarea
53
+ <Textarea
52
54
  {id}
53
- class="form-textarea"
54
55
  value={value ?? ''}
55
56
  {placeholder}
56
57
  {rows}
@@ -58,44 +59,4 @@
58
59
  aria-describedby={ariaDescribedBy}
59
60
  aria-required={required}
60
61
  oninput={handleInput}
61
- ></textarea>
62
-
63
- <style>
64
- .form-textarea {
65
- width: 100%;
66
- padding: 0.625rem 0.875rem;
67
- border: 1px solid var(--fd-border);
68
- border-radius: var(--fd-radius-lg);
69
- font-size: var(--fd-text-sm);
70
- font-family: inherit;
71
- color: var(--fd-foreground);
72
- background-color: var(--fd-background);
73
- transition: all var(--fd-transition-normal);
74
- box-shadow: var(--fd-shadow-sm);
75
- resize: vertical;
76
- min-height: 5rem;
77
- line-height: 1.5;
78
- }
79
-
80
- .form-textarea::placeholder {
81
- color: var(--fd-muted-foreground);
82
- }
83
-
84
- .form-textarea:hover {
85
- border-color: var(--fd-border-strong);
86
- background-color: var(--fd-background);
87
- }
88
-
89
- .form-textarea:focus {
90
- border-color: var(--fd-ring);
91
- background-color: var(--fd-background);
92
- }
93
-
94
- .form-textarea:disabled {
95
- background-color: var(--fd-muted);
96
- border-color: var(--fd-border-muted);
97
- color: var(--fd-muted-foreground);
98
- cursor: not-allowed;
99
- opacity: 1;
100
- }
101
- </style>
62
+ />
@@ -0,0 +1,24 @@
1
+ import type { FieldSchema } from './types.js';
2
+ /**
3
+ * The dependency-free field kinds that {@link FormField} and
4
+ * {@link FormFieldLight} render identically — i.e. everything that does not
5
+ * pull in a heavy editor or depend on the field registry.
6
+ */
7
+ export type BaseFieldType = 'checkbox-group' | 'select-enum' | 'select-options' | 'textarea' | 'range' | 'text' | 'number' | 'toggle' | 'array';
8
+ /**
9
+ * Resolve the basic field type for a schema — the single source of truth for
10
+ * the decision both the full and light field factories share.
11
+ *
12
+ * Returns `null` when none of the basic cases match, so each caller can apply
13
+ * its OWN special-case handling and fallback in its own order. The heavy and
14
+ * entry-point-specific cases (hidden, autocomplete, code/markdown/template
15
+ * editors, `object` → editor, registry-resolved components) are deliberately
16
+ * NOT decided here: `FormField` and `FormFieldLight` route those differently
17
+ * (static imports vs. the lazy field registry that keeps the `/form` light
18
+ * entry free of heavy deps), and must keep doing so before delegating here.
19
+ *
20
+ * Order matters and mirrors the original in-component chains: `enum` and
21
+ * `oneOf` are checked before the primitive `type` branches because option
22
+ * schemas frequently carry `type: 'string'`.
23
+ */
24
+ export declare function resolveBaseFieldType(schema: FieldSchema): BaseFieldType | null;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Resolve the basic field type for a schema — the single source of truth for
3
+ * the decision both the full and light field factories share.
4
+ *
5
+ * Returns `null` when none of the basic cases match, so each caller can apply
6
+ * its OWN special-case handling and fallback in its own order. The heavy and
7
+ * entry-point-specific cases (hidden, autocomplete, code/markdown/template
8
+ * editors, `object` → editor, registry-resolved components) are deliberately
9
+ * NOT decided here: `FormField` and `FormFieldLight` route those differently
10
+ * (static imports vs. the lazy field registry that keeps the `/form` light
11
+ * entry free of heavy deps), and must keep doing so before delegating here.
12
+ *
13
+ * Order matters and mirrors the original in-component chains: `enum` and
14
+ * `oneOf` are checked before the primitive `type` branches because option
15
+ * schemas frequently carry `type: 'string'`.
16
+ */
17
+ export function resolveBaseFieldType(schema) {
18
+ // Enum with multiple selection -> checkbox group
19
+ if (schema.enum && schema.multiple) {
20
+ return 'checkbox-group';
21
+ }
22
+ // Enum with single selection -> select
23
+ if (schema.enum) {
24
+ return 'select-enum';
25
+ }
26
+ // oneOf with labeled options (standard JSON Schema) -> select
27
+ if (schema.oneOf && schema.oneOf.length > 0) {
28
+ return 'select-options';
29
+ }
30
+ // Multiline string -> textarea
31
+ if (schema.type === 'string' && schema.format === 'multiline') {
32
+ return 'textarea';
33
+ }
34
+ // Range slider for number/integer with format: "range"
35
+ if ((schema.type === 'number' || schema.type === 'integer') && schema.format === 'range') {
36
+ return 'range';
37
+ }
38
+ // String -> text field
39
+ if (schema.type === 'string') {
40
+ return 'text';
41
+ }
42
+ // Number or integer -> number field
43
+ if (schema.type === 'number' || schema.type === 'integer') {
44
+ return 'number';
45
+ }
46
+ // Boolean -> toggle
47
+ if (schema.type === 'boolean') {
48
+ return 'toggle';
49
+ }
50
+ // Array -> array field
51
+ if (schema.type === 'array') {
52
+ return 'array';
53
+ }
54
+ return null;
55
+ }
@@ -0,0 +1,6 @@
1
+ <!-- Inline SVG equivalent of mdi:close (Material Design Icons) -->
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
3
+ <path
4
+ d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"
5
+ />
6
+ </svg>
@@ -0,0 +1,26 @@
1
+ export default CloseIcon;
2
+ type CloseIcon = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const CloseIcon: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -28,7 +28,6 @@
28
28
  label: string;
29
29
  config: ConfigValues;
30
30
  metadata: NodeMetadata;
31
- nodeId?: string;
32
31
  extensions?: NodeExtensions;
33
32
  onConfigOpen?: (node: {
34
33
  id: string;
@@ -38,18 +37,19 @@
38
37
  }
39
38
 
40
39
  interface Props {
40
+ id: string;
41
41
  data: AtomNodeData;
42
42
  selected?: boolean;
43
43
  isProcessing?: boolean;
44
44
  isError?: boolean;
45
45
  }
46
46
 
47
- let { data, selected, isProcessing, isError }: Props = $props();
47
+ let { id, data, selected, isProcessing, isError }: Props = $props();
48
48
 
49
49
  const fd = getInstance();
50
50
  const checker = fd.portCompatibility;
51
51
 
52
- const nodeId = $derived(data.nodeId ?? 'unknown');
52
+ const nodeId = $derived(id);
53
53
  const nodeType = $derived(data.metadata?.type ?? 'atom');
54
54
 
55
55
  // Instance extensions override node-type defaults.
@@ -3,7 +3,6 @@ interface AtomNodeData {
3
3
  label: string;
4
4
  config: ConfigValues;
5
5
  metadata: NodeMetadata;
6
- nodeId?: string;
7
6
  extensions?: NodeExtensions;
8
7
  onConfigOpen?: (node: {
9
8
  id: string;
@@ -16,6 +15,7 @@ interface AtomNodeData {
16
15
  }) => void;
17
16
  }
18
17
  interface Props {
18
+ id: string;
19
19
  data: AtomNodeData;
20
20
  selected?: boolean;
21
21
  isProcessing?: boolean;
@@ -23,8 +23,8 @@
23
23
  import { m } from '../../messages/index.js';
24
24
 
25
25
  interface Props {
26
+ id: string;
26
27
  data: WorkflowNode['data'] & {
27
- nodeId?: string;
28
28
  onConfigOpen?: (node: { id: string; type: string; data: WorkflowNode['data'] }) => void;
29
29
  };
30
30
  selected?: boolean;
@@ -83,7 +83,7 @@
83
83
  }
84
84
 
85
85
  // Check if port is connected
86
- const handleId = `${props.data.nodeId}-${type}-${port.id}`;
86
+ const handleId = `${props.id}-${type}-${port.id}`;
87
87
  return fd.workflow.connectedHandles.has(handleId);
88
88
  }
89
89
 
@@ -106,7 +106,7 @@
106
106
  }
107
107
 
108
108
  // Check if branch output is connected
109
- const handleId = `${props.data.nodeId}-output-${branchName}`;
109
+ const handleId = `${props.id}-output-${branchName}`;
110
110
  return fd.workflow.connectedHandles.has(handleId);
111
111
  }
112
112
 
@@ -127,7 +127,7 @@
127
127
  function handleNodeDoubleClick(): void {
128
128
  if (props.data.onConfigOpen) {
129
129
  props.data.onConfigOpen({
130
- id: props.data.nodeId || '',
130
+ id: props.id,
131
131
  type: 'gateway',
132
132
  data: props.data
133
133
  });
@@ -151,7 +151,7 @@
151
151
  class:flowdrop-workflow-node--selected={props.selected}
152
152
  ondblclick={handleNodeDoubleClick}
153
153
  aria-label={graph.gatewayNode({ title: displayTitle })}
154
- aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
154
+ aria-describedby="node-description-{props.id}"
155
155
  >
156
156
  <!-- Node Header: expands in multiples of 10 (title row 40px + gap 10px + description 20px per line) -->
157
157
  <div class="flowdrop-workflow-node__header">
@@ -173,10 +173,7 @@
173
173
  </h3>
174
174
  </div>
175
175
  <!-- Node Description - line-height 20px so header grows in steps of 10 -->
176
- <p
177
- class="flowdrop-workflow-node__header-desc"
178
- id="node-description-{props.data.nodeId || 'unknown'}"
179
- >
176
+ <p class="flowdrop-workflow-node__header-desc" id="node-description-{props.id}">
180
177
  {displayDescription}
181
178
  </p>
182
179
  </div>
@@ -191,7 +188,7 @@
191
188
  <Handle
192
189
  type="target"
193
190
  position={Position.Left}
194
- id={`${props.data.nodeId}-input-${port.id}`}
191
+ id={`${props.id}-input-${port.id}`}
195
192
  class="flowdrop-workflow-node__handle"
196
193
  style="top: var(--fd-node-port-row-height); transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
197
194
  checker,
@@ -280,7 +277,7 @@
280
277
  <Handle
281
278
  type="source"
282
279
  position={Position.Right}
283
- id={`${props.data.nodeId}-output-${branch.name}`}
280
+ id={`${props.id}-output-${branch.name}`}
284
281
  class={`flowdrop-workflow-node__handle ${isActive ? 'flowdrop-workflow-node__handle--active' : ''}`}
285
282
  style="top: var(--fd-node-port-row-height); transform: translateY(-50%); --fd-handle-fill: {isActive
286
283
  ? getDataTypeColorToken(checker, 'trigger')
@@ -1,7 +1,7 @@
1
1
  import type { WorkflowNode } from '../../types/index.js';
2
2
  interface Props {
3
+ id: string;
3
4
  data: WorkflowNode['data'] & {
4
- nodeId?: string;
5
5
  onConfigOpen?: (node: {
6
6
  id: string;
7
7
  type: string;
@@ -19,12 +19,12 @@
19
19
  * IdeaNode component props
20
20
  * Displays a card-style node for conceptual flow diagrams
21
21
  */
22
- const props = $props<{
22
+ interface Props {
23
+ id: string;
23
24
  data: {
24
25
  label: string;
25
26
  config: ConfigValues;
26
27
  metadata: NodeMetadata;
27
- nodeId?: string;
28
28
  onConfigOpen?: (node: {
29
29
  id: string;
30
30
  type: string;
@@ -34,7 +34,9 @@
34
34
  selected?: boolean;
35
35
  isProcessing?: boolean;
36
36
  isError?: boolean;
37
- }>();
37
+ }
38
+
39
+ let props: Props = $props();
38
40
 
39
41
  const checker = getInstance().portCompatibility;
40
42
 
@@ -101,7 +103,7 @@
101
103
  function openConfigSidebar(): void {
102
104
  if (props.data.onConfigOpen) {
103
105
  const nodeForConfig = {
104
- id: props.data.nodeId || 'unknown',
106
+ id: props.id,
105
107
  type: 'idea',
106
108
  data: props.data
107
109
  };
@@ -139,7 +141,7 @@
139
141
  checker,
140
142
  IDEA_DATA_TYPE
141
143
  )}; --fd-handle-border-color: var(--fd-handle-border); top: 40px; transform: translateY(-50%); z-index: 30;"
142
- id={`${props.data.nodeId}-input-left`}
144
+ id={`${props.id}-input-left`}
143
145
  />
144
146
  {/if}
145
147
 
@@ -152,7 +154,7 @@
152
154
  checker,
153
155
  IDEA_DATA_TYPE
154
156
  )}; --fd-handle-border-color: var(--fd-handle-border); left: 140px; transform: translateX(-50%); z-index: 30;"
155
- id={`${props.data.nodeId}-input-top`}
157
+ id={`${props.id}-input-top`}
156
158
  />
157
159
  {/if}
158
160
 
@@ -203,7 +205,7 @@
203
205
  checker,
204
206
  IDEA_DATA_TYPE
205
207
  )}; --fd-handle-border-color: var(--fd-handle-border); top: 40px; transform: translateY(-50%); z-index: 30;"
206
- id={`${props.data.nodeId}-output-right`}
208
+ id={`${props.id}-output-right`}
207
209
  />
208
210
  {/if}
209
211
 
@@ -216,7 +218,7 @@
216
218
  checker,
217
219
  IDEA_DATA_TYPE
218
220
  )}; --fd-handle-border-color: var(--fd-handle-border); left: 140px; transform: translateX(-50%); z-index: 30;"
219
- id={`${props.data.nodeId}-output-bottom`}
221
+ id={`${props.id}-output-bottom`}
220
222
  />
221
223
  {/if}
222
224
  </div>
@@ -1,10 +1,14 @@
1
1
  import type { ConfigValues, NodeMetadata } from '../../types/index.js';
2
- type $$ComponentProps = {
2
+ /**
3
+ * IdeaNode component props
4
+ * Displays a card-style node for conceptual flow diagrams
5
+ */
6
+ interface Props {
7
+ id: string;
3
8
  data: {
4
9
  label: string;
5
10
  config: ConfigValues;
6
11
  metadata: NodeMetadata;
7
- nodeId?: string;
8
12
  onConfigOpen?: (node: {
9
13
  id: string;
10
14
  type: string;
@@ -18,7 +22,7 @@ type $$ComponentProps = {
18
22
  selected?: boolean;
19
23
  isProcessing?: boolean;
20
24
  isError?: boolean;
21
- };
22
- declare const IdeaNode: import("svelte").Component<$$ComponentProps, {}, "">;
25
+ }
26
+ declare const IdeaNode: import("svelte").Component<Props, {}, "">;
23
27
  type IdeaNode = ReturnType<typeof IdeaNode>;
24
28
  export default IdeaNode;
@@ -9,12 +9,12 @@
9
9
  * NotesNode component props
10
10
  * Displays a styled note with markdown content
11
11
  */
12
- const props = $props<{
12
+ interface Props {
13
+ id: string;
13
14
  data: {
14
15
  label: string;
15
16
  config: ConfigValues;
16
17
  metadata: NodeMetadata;
17
- nodeId?: string;
18
18
  onConfigOpen?: (node: {
19
19
  id: string;
20
20
  type: string;
@@ -24,7 +24,9 @@
24
24
  selected?: boolean;
25
25
  isProcessing?: boolean;
26
26
  isError?: boolean;
27
- }>();
27
+ }
28
+
29
+ let props: Props = $props();
28
30
 
29
31
  // Hoist the notes branch — read for placeholder, every type name, processing,
30
32
  // error, and configure tooltip.
@@ -75,7 +77,7 @@
75
77
  function openConfigSidebar(): void {
76
78
  if (props.data.onConfigOpen) {
77
79
  const nodeForConfig = {
78
- id: props.data.nodeId || 'unknown',
80
+ id: props.id,
79
81
  type: 'note',
80
82
  data: props.data
81
83
  };
@@ -1,10 +1,14 @@
1
1
  import type { ConfigValues, NodeMetadata } from '../../types/index.js';
2
- type $$ComponentProps = {
2
+ /**
3
+ * NotesNode component props
4
+ * Displays a styled note with markdown content
5
+ */
6
+ interface Props {
7
+ id: string;
3
8
  data: {
4
9
  label: string;
5
10
  config: ConfigValues;
6
11
  metadata: NodeMetadata;
7
- nodeId?: string;
8
12
  onConfigOpen?: (node: {
9
13
  id: string;
10
14
  type: string;
@@ -18,7 +22,7 @@ type $$ComponentProps = {
18
22
  selected?: boolean;
19
23
  isProcessing?: boolean;
20
24
  isError?: boolean;
21
- };
22
- declare const NotesNode: import("svelte").Component<$$ComponentProps, {}, "">;
25
+ }
26
+ declare const NotesNode: import("svelte").Component<Props, {}, "">;
23
27
  type NotesNode = ReturnType<typeof NotesNode>;
24
28
  export default NotesNode;