@d34dman/flowdrop 0.0.21 → 0.0.23

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 (51) hide show
  1. package/dist/components/App.svelte +69 -260
  2. package/dist/components/ConfigForm.svelte +357 -267
  3. package/dist/components/ConfigForm.svelte.d.ts +12 -3
  4. package/dist/components/ConfigPanel.svelte +160 -0
  5. package/dist/components/ConfigPanel.svelte.d.ts +32 -0
  6. package/dist/components/ReadOnlyDetails.svelte +168 -0
  7. package/dist/components/ReadOnlyDetails.svelte.d.ts +25 -0
  8. package/dist/components/WorkflowEditor.svelte +1 -1
  9. package/dist/components/form/FormArray.svelte +1049 -0
  10. package/dist/components/form/FormArray.svelte.d.ts +22 -0
  11. package/dist/components/form/FormCheckboxGroup.svelte +152 -0
  12. package/dist/components/form/FormCheckboxGroup.svelte.d.ts +15 -0
  13. package/dist/components/form/FormField.svelte +279 -0
  14. package/dist/components/form/FormField.svelte.d.ts +18 -0
  15. package/dist/components/form/FormFieldWrapper.svelte +133 -0
  16. package/dist/components/form/FormFieldWrapper.svelte.d.ts +18 -0
  17. package/dist/components/form/FormNumberField.svelte +109 -0
  18. package/dist/components/form/FormNumberField.svelte.d.ts +23 -0
  19. package/dist/components/form/FormSelect.svelte +126 -0
  20. package/dist/components/form/FormSelect.svelte.d.ts +18 -0
  21. package/dist/components/form/FormTextField.svelte +88 -0
  22. package/dist/components/form/FormTextField.svelte.d.ts +17 -0
  23. package/dist/components/form/FormTextarea.svelte +94 -0
  24. package/dist/components/form/FormTextarea.svelte.d.ts +19 -0
  25. package/dist/components/form/FormToggle.svelte +123 -0
  26. package/dist/components/form/FormToggle.svelte.d.ts +17 -0
  27. package/dist/components/form/index.d.ts +41 -0
  28. package/dist/components/form/index.js +45 -0
  29. package/dist/components/form/types.d.ts +208 -0
  30. package/dist/components/form/types.js +29 -0
  31. package/dist/components/nodes/GatewayNode.svelte +84 -12
  32. package/dist/components/nodes/NotesNode.svelte +89 -307
  33. package/dist/components/nodes/NotesNode.svelte.d.ts +3 -22
  34. package/dist/components/nodes/SimpleNode.svelte +41 -5
  35. package/dist/components/nodes/SimpleNode.svelte.d.ts +2 -1
  36. package/dist/components/nodes/SquareNode.svelte +41 -5
  37. package/dist/components/nodes/SquareNode.svelte.d.ts +2 -1
  38. package/dist/components/nodes/WorkflowNode.svelte +88 -5
  39. package/dist/index.d.ts +4 -4
  40. package/dist/index.js +3 -4
  41. package/dist/stores/workflowStore.d.ts +15 -0
  42. package/dist/stores/workflowStore.js +28 -0
  43. package/dist/types/index.d.ts +77 -0
  44. package/dist/types/index.js +16 -0
  45. package/package.json +3 -3
  46. package/dist/components/ConfigSidebar.svelte +0 -916
  47. package/dist/components/ConfigSidebar.svelte.d.ts +0 -51
  48. package/dist/config/demo.d.ts +0 -58
  49. package/dist/config/demo.js +0 -142
  50. package/dist/data/samples.d.ts +0 -51
  51. package/dist/data/samples.js +0 -3245
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Form Components Module
3
+ *
4
+ * Modular form components for dynamic form rendering based on JSON Schema.
5
+ * Designed for extensibility to support complex types like arrays and objects.
6
+ *
7
+ * @module form
8
+ *
9
+ * @example
10
+ * ```svelte
11
+ * <script>
12
+ * import { FormField } from "./";
13
+ * import type { FieldSchema } from "./";
14
+ *
15
+ * const schema: FieldSchema = {
16
+ * type: "string",
17
+ * title: "Name",
18
+ * description: "Enter your name"
19
+ * };
20
+ *
21
+ * let value = $state("");
22
+ * </script>
23
+ *
24
+ * <FormField
25
+ * fieldKey="name"
26
+ * {schema}
27
+ * {value}
28
+ * onChange={(v) => value = v}
29
+ * />
30
+ * ```
31
+ */
32
+ // Types
33
+ export * from "./types.js";
34
+ // Main factory component
35
+ export { default as FormField } from "./FormField.svelte";
36
+ // Wrapper component
37
+ export { default as FormFieldWrapper } from "./FormFieldWrapper.svelte";
38
+ // Individual field components
39
+ export { default as FormTextField } from "./FormTextField.svelte";
40
+ export { default as FormTextarea } from "./FormTextarea.svelte";
41
+ export { default as FormNumberField } from "./FormNumberField.svelte";
42
+ export { default as FormToggle } from "./FormToggle.svelte";
43
+ export { default as FormSelect } from "./FormSelect.svelte";
44
+ export { default as FormCheckboxGroup } from "./FormCheckboxGroup.svelte";
45
+ export { default as FormArray } from "./FormArray.svelte";
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Form Field Types
3
+ * Shared types for form components in the FlowDrop workflow editor
4
+ *
5
+ * These types provide a foundation for dynamic form rendering based on JSON Schema
6
+ * and support extensibility for complex field types like arrays and objects.
7
+ */
8
+ /**
9
+ * Supported field types for form rendering
10
+ * Can be extended to support complex types like 'array' and 'object'
11
+ */
12
+ export type FieldType = "string" | "number" | "integer" | "boolean" | "select" | "array" | "object";
13
+ /**
14
+ * Field format for specialized rendering
15
+ * - multiline: Renders as textarea
16
+ * - hidden: Field is hidden from UI but included in form submission
17
+ */
18
+ export type FieldFormat = "multiline" | "hidden" | string;
19
+ /**
20
+ * Option type for select and checkbox group fields
21
+ */
22
+ export interface FieldOption {
23
+ /** The value stored when this option is selected */
24
+ value: string;
25
+ /** The display label for this option */
26
+ label: string;
27
+ }
28
+ /**
29
+ * Base properties shared by all form fields
30
+ */
31
+ export interface BaseFieldProps {
32
+ /** Unique identifier for the field (used for id and name attributes) */
33
+ id: string;
34
+ /** Current value of the field */
35
+ value: unknown;
36
+ /** Whether the field is required */
37
+ required?: boolean;
38
+ /** Whether the field is disabled */
39
+ disabled?: boolean;
40
+ /** Placeholder text for input fields */
41
+ placeholder?: string;
42
+ /** ARIA description ID for accessibility */
43
+ ariaDescribedBy?: string;
44
+ /** Callback when the field value changes */
45
+ onChange: (value: unknown) => void;
46
+ }
47
+ /**
48
+ * Properties for text input fields
49
+ */
50
+ export interface TextFieldProps extends BaseFieldProps {
51
+ value: string;
52
+ onChange: (value: string) => void;
53
+ }
54
+ /**
55
+ * Properties for multiline text fields (textarea)
56
+ */
57
+ export interface TextareaFieldProps extends BaseFieldProps {
58
+ value: string;
59
+ /** Number of visible rows */
60
+ rows?: number;
61
+ onChange: (value: string) => void;
62
+ }
63
+ /**
64
+ * Properties for number input fields
65
+ */
66
+ export interface NumberFieldProps extends BaseFieldProps {
67
+ value: number | string;
68
+ /** Minimum allowed value */
69
+ min?: number;
70
+ /** Maximum allowed value */
71
+ max?: number;
72
+ /** Step increment for the input */
73
+ step?: number;
74
+ onChange: (value: number | string) => void;
75
+ }
76
+ /**
77
+ * Properties for boolean toggle fields
78
+ */
79
+ export interface ToggleFieldProps extends BaseFieldProps {
80
+ value: boolean;
81
+ /** Label shown when toggle is on */
82
+ onLabel?: string;
83
+ /** Label shown when toggle is off */
84
+ offLabel?: string;
85
+ onChange: (value: boolean) => void;
86
+ }
87
+ /**
88
+ * Properties for select dropdown fields
89
+ */
90
+ export interface SelectFieldProps extends BaseFieldProps {
91
+ value: string;
92
+ /** Available options for selection */
93
+ options: FieldOption[] | string[];
94
+ onChange: (value: string) => void;
95
+ }
96
+ /**
97
+ * Properties for checkbox group fields (multiple selection)
98
+ */
99
+ export interface CheckboxGroupFieldProps extends BaseFieldProps {
100
+ value: string[];
101
+ /** Available options for selection */
102
+ options: string[];
103
+ onChange: (value: string[]) => void;
104
+ }
105
+ /**
106
+ * Properties for array fields (dynamic lists)
107
+ */
108
+ export interface ArrayFieldProps extends BaseFieldProps {
109
+ value: unknown[];
110
+ /** Schema for array items */
111
+ itemSchema: FieldSchema;
112
+ /** Minimum number of items required */
113
+ minItems?: number;
114
+ /** Maximum number of items allowed */
115
+ maxItems?: number;
116
+ /** Label for the add button */
117
+ addLabel?: string;
118
+ onChange: (value: unknown[]) => void;
119
+ }
120
+ /**
121
+ * Field schema definition derived from JSON Schema property
122
+ * Used to determine which field component to render
123
+ */
124
+ export interface FieldSchema {
125
+ /** The field type from JSON Schema */
126
+ type: FieldType | string;
127
+ /** Display title for the field */
128
+ title?: string;
129
+ /** Description for help text */
130
+ description?: string;
131
+ /** Default value for the field */
132
+ default?: unknown;
133
+ /** Enum values for select/checkbox fields */
134
+ enum?: unknown[];
135
+ /** Whether multiple values can be selected */
136
+ multiple?: boolean;
137
+ /** Format hint for specialized rendering */
138
+ format?: FieldFormat;
139
+ /** Options for select type fields (alternative to enum) */
140
+ options?: FieldOption[];
141
+ /** Placeholder text */
142
+ placeholder?: string;
143
+ /** Minimum value for numbers */
144
+ minimum?: number;
145
+ /** Maximum value for numbers */
146
+ maximum?: number;
147
+ /** Minimum length for strings */
148
+ minLength?: number;
149
+ /** Maximum length for strings */
150
+ maxLength?: number;
151
+ /** Validation pattern for strings */
152
+ pattern?: string;
153
+ /** Item schema for array fields */
154
+ items?: FieldSchema;
155
+ /** Minimum number of items for array fields */
156
+ minItems?: number;
157
+ /** Maximum number of items for array fields */
158
+ maxItems?: number;
159
+ /** Property schemas for object fields (future use) */
160
+ properties?: Record<string, FieldSchema>;
161
+ /** Required properties for object fields (future use) */
162
+ required?: string[];
163
+ /** Allow additional properties not defined by the schema */
164
+ [key: string]: unknown;
165
+ }
166
+ /**
167
+ * Props for the FormField factory component
168
+ * Renders the appropriate field component based on schema
169
+ */
170
+ export interface FormFieldFactoryProps {
171
+ /** Unique key/id for the field */
172
+ fieldKey: string;
173
+ /** Field schema definition */
174
+ schema: FieldSchema;
175
+ /** Current field value */
176
+ value: unknown;
177
+ /** Whether the field is required */
178
+ required?: boolean;
179
+ /** Animation delay index for staggered animations */
180
+ animationIndex?: number;
181
+ /** Callback when the field value changes */
182
+ onChange: (value: unknown) => void;
183
+ }
184
+ /**
185
+ * Props for the FormFieldWrapper component
186
+ * Provides label, description, and layout for field content
187
+ */
188
+ export interface FormFieldWrapperProps {
189
+ /** Field identifier for label association */
190
+ id: string;
191
+ /** Display label text */
192
+ label: string;
193
+ /** Whether the field is required */
194
+ required?: boolean;
195
+ /** Description/help text for the field */
196
+ description?: string;
197
+ /** Animation delay in milliseconds */
198
+ animationDelay?: number;
199
+ }
200
+ /**
201
+ * Type guard to check if options are FieldOption objects
202
+ */
203
+ export declare function isFieldOptionArray(options: FieldOption[] | string[]): options is FieldOption[];
204
+ /**
205
+ * Normalize options to FieldOption format
206
+ * Converts string arrays to FieldOption arrays for consistent handling
207
+ */
208
+ export declare function normalizeOptions(options: FieldOption[] | string[] | unknown[]): FieldOption[];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Form Field Types
3
+ * Shared types for form components in the FlowDrop workflow editor
4
+ *
5
+ * These types provide a foundation for dynamic form rendering based on JSON Schema
6
+ * and support extensibility for complex field types like arrays and objects.
7
+ */
8
+ /**
9
+ * Type guard to check if options are FieldOption objects
10
+ */
11
+ export function isFieldOptionArray(options) {
12
+ return options.length > 0 && typeof options[0] === "object" && "value" in options[0];
13
+ }
14
+ /**
15
+ * Normalize options to FieldOption format
16
+ * Converts string arrays to FieldOption arrays for consistent handling
17
+ */
18
+ export function normalizeOptions(options) {
19
+ if (!options || options.length === 0) {
20
+ return [];
21
+ }
22
+ if (isFieldOptionArray(options)) {
23
+ return options;
24
+ }
25
+ return options.map((opt) => ({
26
+ value: String(opt),
27
+ label: String(opt)
28
+ }));
29
+ }
@@ -3,19 +3,29 @@
3
3
  Visual representation of gateway/branch nodes with branching flow indicators
4
4
  Shows active branches and execution paths
5
5
  Styled with BEM syntax following WorkflowNode pattern
6
+
7
+ UI Extensions Support:
8
+ - hideUnconnectedHandles: Hides ports that are not connected to reduce visual clutter
6
9
  -->
7
10
 
8
11
  <script lang="ts">
9
12
  import { Position, Handle } from '@xyflow/svelte';
10
- import type { WorkflowNode } from '../../types/index.js';
13
+ import type { WorkflowNode, NodePort } from '../../types/index.js';
11
14
  import Icon from '@iconify/svelte';
12
15
  import { getNodeIcon } from '../../utils/icons.js';
13
16
  import { getDataTypeColorToken, getCategoryColorToken } from '../../utils/colors.js';
17
+ import { connectedHandles } from '../../stores/workflowStore.js';
14
18
 
15
- // Define simplified branch interface - conditions are handled by backend
19
+ /**
20
+ * Branch interface for gateway nodes
21
+ * - name: Internal identifier used for handle IDs and connections
22
+ * - label: Display label shown in the UI (optional, defaults to name)
23
+ * - value: Optional value associated with the branch (e.g., for Switch matching)
24
+ */
16
25
  interface Branch {
17
26
  name: string;
18
- label: string;
27
+ label?: string;
28
+ value?: string;
19
29
  }
20
30
 
21
31
  interface Props {
@@ -28,10 +38,70 @@
28
38
 
29
39
  let props: Props = $props();
30
40
 
41
+ /**
42
+ * Get the hideUnconnectedHandles setting from extensions
43
+ * Merges node type defaults with instance overrides
44
+ */
45
+ const hideUnconnectedHandles = $derived(() => {
46
+ const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
47
+ const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
48
+ return instanceOverride ?? typeDefault;
49
+ });
50
+
51
+ /**
52
+ * Check if a port should be visible based on connection state and settings
53
+ * @param port - The port to check
54
+ * @param type - Whether this is an 'input' or 'output' port
55
+ * @returns true if the port should be visible
56
+ */
57
+ function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
58
+ // Always show if hideUnconnectedHandles is disabled
59
+ if (!hideUnconnectedHandles()) {
60
+ return true;
61
+ }
62
+
63
+ // Always show required ports
64
+ if (port.required) {
65
+ return true;
66
+ }
67
+
68
+ // Check if port is connected
69
+ const handleId = `${props.data.nodeId}-${type}-${port.id}`;
70
+ return $connectedHandles.has(handleId);
71
+ }
72
+
73
+ /**
74
+ * Derived list of visible input ports based on hideUnconnectedHandles setting
75
+ */
76
+ const visibleInputPorts = $derived(
77
+ props.data.metadata.inputs.filter((port) => isPortVisible(port, 'input'))
78
+ );
79
+
80
+ /**
81
+ * Check if a branch output should be visible based on connection state
82
+ * @param branchName - The branch name to check
83
+ * @returns true if the branch should be visible
84
+ */
85
+ function isBranchVisible(branchName: string): boolean {
86
+ // Always show if hideUnconnectedHandles is disabled
87
+ if (!hideUnconnectedHandles()) {
88
+ return true;
89
+ }
90
+
91
+ // Check if branch output is connected
92
+ const handleId = `${props.data.nodeId}-output-${branchName}`;
93
+ return $connectedHandles.has(handleId);
94
+ }
95
+
31
96
  // Gateway-specific data - branches are calculated at runtime from config
32
97
  let branches = $derived((props.data.config?.branches as Branch[]) || []);
33
98
  let activeBranches = $derived((props.data.executionInfo as any)?.output?.active_branches || []);
34
99
 
100
+ /**
101
+ * Derived list of visible branches based on hideUnconnectedHandles setting
102
+ */
103
+ const visibleBranches = $derived(branches.filter((branch) => isBranchVisible(branch.name)));
104
+
35
105
  /**
36
106
  * Handle node click - only handle selection, no config opening
37
107
  */
@@ -107,14 +177,14 @@
107
177
  </p>
108
178
  </div>
109
179
 
110
- <!-- Input Ports Container -->
111
- {#if props.data.metadata.inputs.length > 0}
180
+ <!-- Input Ports Container (filtered based on hideUnconnectedHandles) -->
181
+ {#if visibleInputPorts.length > 0}
112
182
  <div class="flowdrop-workflow-node__ports">
113
183
  <div class="flowdrop-workflow-node__ports-header">
114
184
  <h5 class="flowdrop-workflow-node__ports-title">Inputs</h5>
115
185
  </div>
116
186
  <div class="flowdrop-workflow-node__ports-list">
117
- {#each props.data.metadata.inputs as port (port.id)}
187
+ {#each visibleInputPorts as port (port.id)}
118
188
  <div class="flowdrop-workflow-node__port">
119
189
  <!-- Input Handle -->
120
190
  <Handle
@@ -158,17 +228,17 @@
158
228
  </div>
159
229
  {/if}
160
230
 
161
- <!-- Branches Section (Output Ports) -->
162
- {#if branches.length > 0}
231
+ <!-- Branches Section (Output Ports) - filtered based on hideUnconnectedHandles -->
232
+ {#if visibleBranches.length > 0}
163
233
  <div class="flowdrop-workflow-node__ports">
164
234
  <div class="flowdrop-workflow-node__ports-header">
165
235
  <h5 class="flowdrop-workflow-node__ports-title">
166
236
  <Icon icon="mdi:source-branch" />
167
- <span>Branches ({branches.length})</span>
237
+ <span>Branches ({visibleBranches.length})</span>
168
238
  </h5>
169
239
  </div>
170
240
  <div class="flowdrop-workflow-node__ports-list">
171
- {#each branches as branch (branch.name)}
241
+ {#each visibleBranches as branch (branch.name)}
172
242
  {@const isActive = isBranchActive(branch.name)}
173
243
  <div class="flowdrop-workflow-node__port">
174
244
  <!-- Port Info -->
@@ -185,7 +255,7 @@
185
255
  class="flowdrop-text--xs flowdrop-font--medium"
186
256
  class:flowdrop-text--active={isActive}
187
257
  >
188
- {branch.name}
258
+ {branch.label || branch.name}
189
259
  </span>
190
260
  <span
191
261
  class="flowdrop-badge flowdrop-badge--sm"
@@ -213,7 +283,8 @@
213
283
  {/each}
214
284
  </div>
215
285
  </div>
216
- {:else}
286
+ {:else if branches.length === 0}
287
+ <!-- No branches configured at all -->
217
288
  <div class="flowdrop-workflow-node__ports">
218
289
  <div class="workflow-node__no-branches">
219
290
  <Icon icon="mdi:alert-circle-outline" />
@@ -221,6 +292,7 @@
221
292
  </div>
222
293
  </div>
223
294
  {/if}
295
+ <!-- Note: When all branches are hidden due to hideUnconnectedHandles, we don't show anything -->
224
296
 
225
297
  <!-- Config button -->
226
298
  <button