@d34dman/flowdrop 0.0.51 → 0.0.52

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * API Client for FlowDrop Workflow Library
3
3
  */
4
- import type { NodeMetadata, Workflow, ExecutionResult, PortConfig } from '../types/index.js';
4
+ import type { NodeMetadata, Workflow, ExecutionResult, PortConfig, CategoryDefinition } from '../types/index.js';
5
5
  /**
6
6
  * HTTP API client for FlowDrop
7
7
  */
@@ -80,6 +80,10 @@ export declare class FlowDropApiClient {
80
80
  * Fetch port configuration
81
81
  */
82
82
  getPortConfig(): Promise<PortConfig>;
83
+ /**
84
+ * Fetch category definitions
85
+ */
86
+ getCategories(): Promise<CategoryDefinition[]>;
83
87
  /**
84
88
  * Fetch pipeline data including job information and status
85
89
  */
@@ -215,6 +215,16 @@ export class FlowDropApiClient {
215
215
  }
216
216
  return response.data;
217
217
  }
218
+ /**
219
+ * Fetch category definitions
220
+ */
221
+ async getCategories() {
222
+ const response = await this.request('/categories');
223
+ if (!response.success || !response.data) {
224
+ throw new Error(response.error || 'Failed to fetch categories');
225
+ }
226
+ return response.data;
227
+ }
218
228
  /**
219
229
  * Fetch pipeline data including job information and status
220
230
  */
@@ -10,6 +10,7 @@
10
10
  import Icon from '@iconify/svelte';
11
11
  import { getNodeIcon, getCategoryIcon } from '../utils/icons.js';
12
12
  import { getCategoryColorToken } from '../utils/colors.js';
13
+ import { getCategoryLabel } from '../stores/categoriesStore.js';
13
14
  import { SvelteSet } from 'svelte/reactivity';
14
15
  import { uiSettings, updateSettings } from '../stores/settingsStore.js';
15
16
 
@@ -142,29 +143,11 @@
142
143
  }
143
144
 
144
145
  /**
145
- * Get category display name
146
+ * Get category display name from the categories store.
147
+ * Falls back to auto-capitalizing the category machine name.
146
148
  */
147
149
  function getCategoryDisplayName(category: NodeCategory): string {
148
- const names: Record<NodeCategory, string> = {
149
- triggers: 'Triggers',
150
- inputs: 'Inputs',
151
- outputs: 'Outputs',
152
- prompts: 'Prompts',
153
- models: 'Models',
154
- processing: 'Processing',
155
- logic: 'Logic',
156
- data: 'Data',
157
- tools: 'Tools',
158
- helpers: 'Helpers',
159
- 'vector stores': 'Vector Stores',
160
- embeddings: 'Embeddings',
161
- memories: 'Memories',
162
- agents: 'Agents',
163
- ai: 'AI',
164
- interrupts: 'Interrupts',
165
- bundles: 'Bundles'
166
- };
167
- return names[category] || category;
150
+ return getCategoryLabel(category);
168
151
  }
169
152
 
170
153
  /**
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Default category definitions for FlowDrop
3
+ * Provides built-in categories with icons, colors, and display labels.
4
+ * These serve as fallbacks when the /categories API endpoint is unavailable.
5
+ */
6
+ import type { CategoryDefinition } from '../types/index.js';
7
+ export declare const DEFAULT_CATEGORIES: CategoryDefinition[];
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Default category definitions for FlowDrop
3
+ * Provides built-in categories with icons, colors, and display labels.
4
+ * These serve as fallbacks when the /categories API endpoint is unavailable.
5
+ */
6
+ export const DEFAULT_CATEGORIES = [
7
+ {
8
+ name: 'triggers',
9
+ label: 'Triggers',
10
+ icon: 'mdi:lightning-bolt',
11
+ color: 'var(--fd-node-cyan)',
12
+ weight: 0
13
+ },
14
+ {
15
+ name: 'inputs',
16
+ label: 'Inputs',
17
+ icon: 'mdi:arrow-down-circle',
18
+ color: 'var(--fd-node-emerald)',
19
+ weight: 1
20
+ },
21
+ {
22
+ name: 'outputs',
23
+ label: 'Outputs',
24
+ icon: 'mdi:arrow-up-circle',
25
+ color: 'var(--fd-node-blue)',
26
+ weight: 2
27
+ },
28
+ {
29
+ name: 'prompts',
30
+ label: 'Prompts',
31
+ icon: 'mdi:message-text',
32
+ color: 'var(--fd-node-amber)',
33
+ weight: 3
34
+ },
35
+ {
36
+ name: 'models',
37
+ label: 'Models',
38
+ icon: 'mdi:robot',
39
+ color: 'var(--fd-node-indigo)',
40
+ weight: 4
41
+ },
42
+ {
43
+ name: 'processing',
44
+ label: 'Processing',
45
+ icon: 'mdi:cog',
46
+ color: 'var(--fd-node-teal)',
47
+ weight: 5
48
+ },
49
+ {
50
+ name: 'logic',
51
+ label: 'Logic',
52
+ icon: 'mdi:source-branch',
53
+ color: 'var(--fd-node-purple)',
54
+ weight: 6
55
+ },
56
+ {
57
+ name: 'data',
58
+ label: 'Data',
59
+ icon: 'mdi:database',
60
+ color: 'var(--fd-node-orange)',
61
+ weight: 7
62
+ },
63
+ {
64
+ name: 'tools',
65
+ label: 'Tools',
66
+ icon: 'mdi:wrench',
67
+ color: 'var(--fd-node-amber)',
68
+ weight: 8
69
+ },
70
+ {
71
+ name: 'helpers',
72
+ label: 'Helpers',
73
+ icon: 'mdi:help-circle',
74
+ color: 'var(--fd-node-slate)',
75
+ weight: 9
76
+ },
77
+ {
78
+ name: 'vector stores',
79
+ label: 'Vector Stores',
80
+ icon: 'mdi:vector-square',
81
+ color: 'var(--fd-node-emerald)',
82
+ weight: 10
83
+ },
84
+ {
85
+ name: 'embeddings',
86
+ label: 'Embeddings',
87
+ icon: 'mdi:vector-polygon',
88
+ color: 'var(--fd-node-indigo)',
89
+ weight: 11
90
+ },
91
+ {
92
+ name: 'memories',
93
+ label: 'Memories',
94
+ icon: 'mdi:brain',
95
+ color: 'var(--fd-node-blue)',
96
+ weight: 12
97
+ },
98
+ {
99
+ name: 'agents',
100
+ label: 'Agents',
101
+ icon: 'mdi:account-cog',
102
+ color: 'var(--fd-node-teal)',
103
+ weight: 13
104
+ },
105
+ {
106
+ name: 'ai',
107
+ label: 'AI',
108
+ icon: 'mdi:shimmer',
109
+ color: 'var(--fd-node-purple)',
110
+ weight: 14
111
+ },
112
+ {
113
+ name: 'interrupts',
114
+ label: 'Interrupts',
115
+ icon: 'mdi:hand-back-left',
116
+ color: 'var(--fd-node-red)',
117
+ weight: 15
118
+ },
119
+ {
120
+ name: 'bundles',
121
+ label: 'Bundles',
122
+ icon: 'mdi:package-variant',
123
+ color: 'var(--fd-node-slate)',
124
+ weight: 16
125
+ }
126
+ ];
@@ -14,6 +14,7 @@ export interface EndpointConfig {
14
14
  metadata: string;
15
15
  };
16
16
  portConfig: string;
17
+ categories: string;
17
18
  workflows: {
18
19
  list: string;
19
20
  get: string;
@@ -15,6 +15,7 @@ export const defaultEndpointConfig = {
15
15
  metadata: '/nodes/{id}/metadata'
16
16
  },
17
17
  portConfig: '/port-config',
18
+ categories: '/categories',
18
19
  workflows: {
19
20
  list: '/workflows',
20
21
  get: '/workflows/{id}',
@@ -14,7 +14,7 @@
14
14
  * import { getStatusColor, createDefaultExecutionInfo } from "@d34dman/flowdrop/core";
15
15
  * ```
16
16
  */
17
- export type { NodeCategory, NodeDataType, NodePort, DynamicPort, Branch, NodeMetadata, NodeExtensions, NodeUIExtensions, ConfigValues, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents, BuiltinNodeType, PortConfig, PortCompatibilityRule, ConfigSchema, ConfigProperty, HttpMethod, DynamicSchemaEndpoint, ExternalEditLink, ConfigEditOptions, EdgeCategory } from '../types/index.js';
17
+ export type { NodeCategory, BuiltinNodeCategory, CategoryDefinition, NodeDataType, NodePort, DynamicPort, Branch, NodeMetadata, NodeExtensions, NodeUIExtensions, ConfigValues, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents, BuiltinNodeType, PortConfig, PortCompatibilityRule, ConfigSchema, ConfigProperty, HttpMethod, DynamicSchemaEndpoint, ExternalEditLink, ConfigEditOptions, EdgeCategory } from '../types/index.js';
18
18
  export type { WorkflowEditorConfig, EditorFeatures, UIConfig, APIConfig, ExecutionConfig, StorageConfig } from '../types/config.js';
19
19
  export type { AuthProvider, StaticAuthConfig, CallbackAuthConfig } from '../types/auth.js';
20
20
  export type { WorkflowChangeType, FlowDropEventHandlers, FlowDropFeatures } from '../types/events.js';
@@ -74,6 +74,7 @@ export { currentSession, sessions, messages, isExecuting, isLoading, error as pl
74
74
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
75
75
  export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from '../services/globalSave.js';
76
76
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
77
+ export { fetchCategories, validateCategories } from '../services/categoriesApi.js';
77
78
  export { fetchDynamicSchema, resolveExternalEditUrl, getEffectiveConfigEditOptions, clearSchemaCache, invalidateSchemaCache, hasConfigEditOptions, shouldShowExternalEdit, shouldUseDynamicSchema } from '../services/dynamicSchemaService.js';
78
79
  export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from '../services/draftStorage.js';
79
80
  export { FlowDropApiClient } from '../api/client.js';
@@ -115,6 +115,7 @@ export { currentSession, sessions, messages, isExecuting, isLoading, error as pl
115
115
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
116
116
  export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from '../services/globalSave.js';
117
117
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
118
+ export { fetchCategories, validateCategories } from '../services/categoriesApi.js';
118
119
  export { fetchDynamicSchema, resolveExternalEditUrl, getEffectiveConfigEditOptions, clearSchemaCache, invalidateSchemaCache, hasConfigEditOptions, shouldShowExternalEdit, shouldUseDynamicSchema } from '../services/dynamicSchemaService.js';
119
120
  export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from '../services/draftStorage.js';
120
121
  // ============================================================================
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Categories API Service
3
+ * Handles fetching category definitions from the backend
4
+ */
5
+ import type { CategoryDefinition } from '../types/index.js';
6
+ import type { EndpointConfig } from '../config/endpoints.js';
7
+ /**
8
+ * Fetch category definitions from API
9
+ */
10
+ export declare function fetchCategories(endpointConfig: EndpointConfig): Promise<CategoryDefinition[]>;
11
+ /**
12
+ * Validate category definitions structure
13
+ */
14
+ export declare function validateCategories(categories: CategoryDefinition[]): boolean;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Categories API Service
3
+ * Handles fetching category definitions from the backend
4
+ */
5
+ import { DEFAULT_CATEGORIES } from '../config/defaultCategories.js';
6
+ import { FlowDropApiClient } from '../api/client.js';
7
+ /**
8
+ * Fetch category definitions from API
9
+ */
10
+ export async function fetchCategories(endpointConfig) {
11
+ try {
12
+ const client = new FlowDropApiClient(endpointConfig.baseUrl);
13
+ const categories = await client.getCategories();
14
+ if (!categories || !Array.isArray(categories)) {
15
+ console.warn('Invalid categories received from API, using default');
16
+ return DEFAULT_CATEGORIES;
17
+ }
18
+ return categories;
19
+ }
20
+ catch (error) {
21
+ console.error('Error fetching categories:', error);
22
+ return DEFAULT_CATEGORIES;
23
+ }
24
+ }
25
+ /**
26
+ * Validate category definitions structure
27
+ */
28
+ export function validateCategories(categories) {
29
+ if (!categories || !Array.isArray(categories)) {
30
+ return false;
31
+ }
32
+ for (const category of categories) {
33
+ if (!category.name || typeof category.name !== 'string') {
34
+ return false;
35
+ }
36
+ if (!category.label || typeof category.label !== 'string') {
37
+ return false;
38
+ }
39
+ }
40
+ return true;
41
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Categories Store for FlowDrop
3
+ *
4
+ * Manages category definitions with merged defaults and API-provided overrides.
5
+ * Exposes lookup helpers for icon, color, and label resolution.
6
+ */
7
+ import type { CategoryDefinition, NodeCategory } from '../types/index.js';
8
+ /**
9
+ * Readable store of all category definitions, sorted by weight.
10
+ */
11
+ export declare const categories: import("svelte/store").Readable<CategoryDefinition[]>;
12
+ /**
13
+ * Initialize categories with API data, merging with defaults.
14
+ * API categories override defaults by name; custom categories are appended.
15
+ */
16
+ export declare function initializeCategories(apiCategories: CategoryDefinition[]): void;
17
+ /**
18
+ * Get the display label for a category.
19
+ */
20
+ export declare function getCategoryLabel(category: NodeCategory): string;
21
+ /**
22
+ * Get the icon for a category.
23
+ */
24
+ export declare function getCategoryIcon(category: NodeCategory): string;
25
+ /**
26
+ * Get the color token for a category.
27
+ */
28
+ export declare function getCategoryColor(category: NodeCategory): string;
29
+ /**
30
+ * Get the full category definition, or undefined if not found.
31
+ */
32
+ export declare function getCategoryDefinition(category: NodeCategory): CategoryDefinition | undefined;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Categories Store for FlowDrop
3
+ *
4
+ * Manages category definitions with merged defaults and API-provided overrides.
5
+ * Exposes lookup helpers for icon, color, and label resolution.
6
+ */
7
+ import { writable, derived, get } from 'svelte/store';
8
+ import { DEFAULT_CATEGORIES } from '../config/defaultCategories.js';
9
+ /**
10
+ * Internal writable store holding the category definitions.
11
+ * Initialized with defaults, updated when API data is fetched.
12
+ */
13
+ const categoriesInternal = writable(DEFAULT_CATEGORIES);
14
+ /**
15
+ * Derived lookup map: category name → CategoryDefinition
16
+ */
17
+ const categoryMap = derived(categoriesInternal, ($categories) => {
18
+ const map = new Map();
19
+ for (const cat of $categories) {
20
+ map.set(cat.name, cat);
21
+ }
22
+ return map;
23
+ });
24
+ /**
25
+ * Readable store of all category definitions, sorted by weight.
26
+ */
27
+ export const categories = derived(categoriesInternal, ($categories) => [...$categories].sort((a, b) => (a.weight ?? 999) - (b.weight ?? 999)));
28
+ /**
29
+ * Initialize categories with API data, merging with defaults.
30
+ * API categories override defaults by name; custom categories are appended.
31
+ */
32
+ export function initializeCategories(apiCategories) {
33
+ const defaultMap = new Map();
34
+ for (const cat of DEFAULT_CATEGORIES) {
35
+ defaultMap.set(cat.name, cat);
36
+ }
37
+ // API categories override defaults by name
38
+ for (const cat of apiCategories) {
39
+ defaultMap.set(cat.name, {
40
+ ...defaultMap.get(cat.name),
41
+ ...cat
42
+ });
43
+ }
44
+ categoriesInternal.set(Array.from(defaultMap.values()));
45
+ }
46
+ /**
47
+ * Get the display label for a category.
48
+ */
49
+ export function getCategoryLabel(category) {
50
+ const map = get(categoryMap);
51
+ const def = map.get(category);
52
+ if (def?.label)
53
+ return def.label;
54
+ // Auto-generate: capitalize each word
55
+ return category
56
+ .split(/[\s_-]+/)
57
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
58
+ .join(' ');
59
+ }
60
+ /**
61
+ * Get the icon for a category.
62
+ */
63
+ export function getCategoryIcon(category) {
64
+ const map = get(categoryMap);
65
+ return map.get(category)?.icon ?? 'mdi:folder';
66
+ }
67
+ /**
68
+ * Get the color token for a category.
69
+ */
70
+ export function getCategoryColor(category) {
71
+ const map = get(categoryMap);
72
+ return map.get(category)?.color ?? 'var(--fd-node-slate)';
73
+ }
74
+ /**
75
+ * Get the full category definition, or undefined if not found.
76
+ */
77
+ export function getCategoryDefinition(category) {
78
+ const map = get(categoryMap);
79
+ return map.get(category);
80
+ }
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @module svelte-app
8
8
  */
9
- import type { Workflow, NodeMetadata, PortConfig } from './types/index.js';
9
+ import type { Workflow, NodeMetadata, PortConfig, CategoryDefinition } from './types/index.js';
10
10
  import type { EndpointConfig } from './config/endpoints.js';
11
11
  import type { AuthProvider } from './types/auth.js';
12
12
  import type { FlowDropEventHandlers, FlowDropFeatures } from './types/events.js';
@@ -39,6 +39,8 @@ export interface FlowDropMountOptions {
39
39
  endpointConfig?: EndpointConfig;
40
40
  /** Port configuration for connections */
41
41
  portConfig?: PortConfig;
42
+ /** Category definitions for node categories */
43
+ categories?: CategoryDefinition[];
42
44
  /** Editor height */
43
45
  height?: string | number;
44
46
  /** Editor width */
@@ -140,6 +142,7 @@ export declare function mountWorkflowEditor(container: HTMLElement, options?: {
140
142
  nodes?: NodeMetadata[];
141
143
  endpointConfig?: EndpointConfig;
142
144
  portConfig?: PortConfig;
145
+ categories?: CategoryDefinition[];
143
146
  }): Promise<MountedFlowDropApp>;
144
147
  /**
145
148
  * Unmount a FlowDrop app
@@ -12,6 +12,8 @@ import App from './components/App.svelte';
12
12
  import { initializePortCompatibility } from './utils/connections.js';
13
13
  import { DEFAULT_PORT_CONFIG } from './config/defaultPortConfig.js';
14
14
  import { fetchPortConfig } from './services/portConfigApi.js';
15
+ import { fetchCategories } from './services/categoriesApi.js';
16
+ import { initializeCategories } from './stores/categoriesStore.js';
15
17
  import { isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange } from './stores/workflowStore.js';
16
18
  import { DraftAutoSaveManager, getDraftStorageKey } from './services/draftStorage.js';
17
19
  import { mergeFeatures } from './types/events.js';
@@ -41,7 +43,7 @@ import { initializeSettings } from './stores/settingsStore.js';
41
43
  * ```
42
44
  */
43
45
  export async function mountFlowDropApp(container, options = {}) {
44
- const { workflow, nodes, endpointConfig, portConfig, height = '100vh', width = '100%', showNavbar = false, disableSidebar, lockWorkflow, readOnly, nodeStatuses, pipelineId, navbarTitle, navbarActions, showSettings, authProvider, eventHandlers, features: userFeatures, settings: initialSettings, draftStorageKey: customDraftKey } = options;
46
+ const { workflow, nodes, endpointConfig, portConfig, categories, height = '100vh', width = '100%', showNavbar = false, disableSidebar, lockWorkflow, readOnly, nodeStatuses, pipelineId, navbarTitle, navbarActions, showSettings, authProvider, eventHandlers, features: userFeatures, settings: initialSettings, draftStorageKey: customDraftKey } = options;
45
47
  // Merge features with defaults
46
48
  const features = mergeFeatures(userFeatures);
47
49
  // Apply initial settings overrides and initialize theme
@@ -83,6 +85,19 @@ export async function mountFlowDropApp(container, options = {}) {
83
85
  finalPortConfig = DEFAULT_PORT_CONFIG;
84
86
  }
85
87
  initializePortCompatibility(finalPortConfig);
88
+ // Initialize categories
89
+ if (categories) {
90
+ initializeCategories(categories);
91
+ }
92
+ else if (config) {
93
+ try {
94
+ const fetchedCategories = await fetchCategories(config);
95
+ initializeCategories(fetchedCategories);
96
+ }
97
+ catch (error) {
98
+ console.warn('Failed to fetch categories from API, using defaults:', error);
99
+ }
100
+ }
86
101
  // Set up event handler callbacks in the store
87
102
  if (eventHandlers?.onDirtyStateChange) {
88
103
  setOnDirtyStateChange(eventHandlers.onDirtyStateChange);
@@ -194,7 +209,7 @@ export async function mountFlowDropApp(container, options = {}) {
194
209
  * @returns Promise resolving to a MountedFlowDropApp instance
195
210
  */
196
211
  export async function mountWorkflowEditor(container, options = {}) {
197
- const { nodes = [], endpointConfig, portConfig } = options;
212
+ const { nodes = [], endpointConfig, portConfig, categories } = options;
198
213
  // Create endpoint configuration
199
214
  let config;
200
215
  if (endpointConfig) {
@@ -230,6 +245,19 @@ export async function mountWorkflowEditor(container, options = {}) {
230
245
  finalPortConfig = DEFAULT_PORT_CONFIG;
231
246
  }
232
247
  initializePortCompatibility(finalPortConfig);
248
+ // Initialize categories
249
+ if (categories) {
250
+ initializeCategories(categories);
251
+ }
252
+ else if (config) {
253
+ try {
254
+ const fetchedCategories = await fetchCategories(config);
255
+ initializeCategories(fetchedCategories);
256
+ }
257
+ catch (error) {
258
+ console.warn('Failed to fetch categories from API, using defaults:', error);
259
+ }
260
+ }
233
261
  // Create the Svelte component
234
262
  const svelteApp = mount(WorkflowEditor, {
235
263
  target: container,
@@ -5,10 +5,43 @@ import type { Node, Edge, XYPosition } from '@xyflow/svelte';
5
5
  import { ConnectionLineType } from '@xyflow/svelte';
6
6
  import type { EndpointConfig } from '../config/endpoints.js';
7
7
  /**
8
- * Node category types for organizing nodes in the sidebar
9
- * Based on actual API response categories
8
+ * Built-in node categories that ship with FlowDrop.
9
+ * These categories have predefined icons, colors, and display names.
10
10
  */
11
- export type NodeCategory = 'triggers' | 'inputs' | 'outputs' | 'prompts' | 'models' | 'processing' | 'logic' | 'data' | 'tools' | 'helpers' | 'vector stores' | 'embeddings' | 'memories' | 'agents' | 'ai' | 'interrupts' | 'bundles';
11
+ export type BuiltinNodeCategory = 'triggers' | 'inputs' | 'outputs' | 'prompts' | 'models' | 'processing' | 'logic' | 'data' | 'tools' | 'helpers' | 'vector stores' | 'embeddings' | 'memories' | 'agents' | 'ai' | 'interrupts' | 'bundles';
12
+ /**
13
+ * Node category for organizing nodes in the sidebar.
14
+ * Includes all built-in categories plus any custom string.
15
+ * Custom categories can be defined via the `/categories` API endpoint.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Built-in category
20
+ * const cat: NodeCategory = 'triggers';
21
+ *
22
+ * // Custom category
23
+ * const custom: NodeCategory = 'my-custom-category';
24
+ * ```
25
+ */
26
+ export type NodeCategory = BuiltinNodeCategory | (string & Record<never, never>);
27
+ /**
28
+ * Category definition with metadata for display and organization.
29
+ * Fetched from the `/categories` API endpoint or provided as defaults.
30
+ */
31
+ export interface CategoryDefinition {
32
+ /** Machine name / unique identifier */
33
+ name: string;
34
+ /** Display label shown in UI */
35
+ label: string;
36
+ /** Icon identifier (e.g. 'mdi:brain') */
37
+ icon?: string;
38
+ /** Color token or CSS value (e.g. 'var(--fd-node-purple)') */
39
+ color?: string;
40
+ /** Category description */
41
+ description?: string;
42
+ /** Sort weight for ordering (lower = earlier) */
43
+ weight?: number;
44
+ }
12
45
  /**
13
46
  * Port data type configuration
14
47
  */
@@ -7,10 +7,13 @@ import type { NodeCategory, PortDataTypeConfig } from '../types/index.js';
7
7
  /**
8
8
  * Category color mapping to design tokens (CSS variables)
9
9
  * Uses --fd-node-* tokens from tokens.css
10
+ * These serve as static defaults; the categories store provides dynamic overrides.
10
11
  */
11
- export declare const CATEGORY_COLOR_TOKENS: Record<NodeCategory, string>;
12
+ export declare const CATEGORY_COLOR_TOKENS: Record<string, string>;
12
13
  /**
13
- * Get the design token for a category color
14
+ * Get the design token for a category color.
15
+ * Checks the categories store first (which includes API overrides),
16
+ * then falls back to the static CATEGORY_COLOR_TOKENS map, then to slate.
14
17
  */
15
18
  export declare function getCategoryColorToken(category: NodeCategory): string;
16
19
  /**
@@ -4,9 +4,11 @@
4
4
  * Uses BEM syntax for CSS classes
5
5
  */
6
6
  import { getPortCompatibilityChecker } from './connections.js';
7
+ import { getCategoryColor as getCategoryColorFromStore } from '../stores/categoriesStore.js';
7
8
  /**
8
9
  * Category color mapping to design tokens (CSS variables)
9
10
  * Uses --fd-node-* tokens from tokens.css
11
+ * These serve as static defaults; the categories store provides dynamic overrides.
10
12
  */
11
13
  export const CATEGORY_COLOR_TOKENS = {
12
14
  triggers: 'var(--fd-node-cyan)',
@@ -61,10 +63,12 @@ const DEFAULT_DATA_TYPE_COLORS = {
61
63
  branch: 'var(--fd-node-purple)'
62
64
  };
63
65
  /**
64
- * Get the design token for a category color
66
+ * Get the design token for a category color.
67
+ * Checks the categories store first (which includes API overrides),
68
+ * then falls back to the static CATEGORY_COLOR_TOKENS map, then to slate.
65
69
  */
66
70
  export function getCategoryColorToken(category) {
67
- return CATEGORY_COLOR_TOKENS[category] || 'var(--fd-node-slate)';
71
+ return getCategoryColorFromStore(category);
68
72
  }
69
73
  /**
70
74
  * Get the reference color token for a data type (configurable version)
@@ -124,7 +128,7 @@ export const DEFAULT_COLORS = {
124
128
  * @returns The color configuration for the category
125
129
  */
126
130
  export function getCategoryColors(category) {
127
- return CATEGORY_COLOR_TOKENS[category] || 'var(--fd-node-slate)';
131
+ return getCategoryColorFromStore(category);
128
132
  }
129
133
  /**
130
134
  * Get category background color
@@ -65,9 +65,11 @@ export declare const DEFAULT_ICONS: {
65
65
  readonly BUNDLE: "mdi:package-variant";
66
66
  };
67
67
  /**
68
- * Category-specific icons matching Langflow's visual style
68
+ * Category-specific icons for built-in categories.
69
+ * Custom categories fall back to DEFAULT_ICONS.CATEGORY.
70
+ * These serve as static defaults; the categories store provides dynamic overrides.
69
71
  */
70
- export declare const CATEGORY_ICONS: Record<NodeCategory, string>;
72
+ export declare const CATEGORY_ICONS: Record<string, string>;
71
73
  /**
72
74
  * Get the appropriate icon for a node
73
75
  * @param nodeIcon - The node's specific icon
@@ -76,7 +78,9 @@ export declare const CATEGORY_ICONS: Record<NodeCategory, string>;
76
78
  */
77
79
  export declare function getNodeIcon(nodeIcon?: string, category?: NodeCategory): string;
78
80
  /**
79
- * Get the appropriate icon for a category
81
+ * Get the appropriate icon for a category.
82
+ * Checks the categories store first (which includes API overrides),
83
+ * then falls back to the static CATEGORY_ICONS map, then to the default.
80
84
  * @param category - The category
81
85
  * @returns The icon to use
82
86
  */
@@ -2,6 +2,7 @@
2
2
  * Centralized icon management for FlowDrop
3
3
  * Ensures consistent icon usage across all components
4
4
  */
5
+ import { getCategoryIcon as getCategoryIconFromStore } from '../stores/categoriesStore.js';
5
6
  /**
6
7
  * Default icons for different contexts
7
8
  */
@@ -77,7 +78,9 @@ export const DEFAULT_ICONS = {
77
78
  BUNDLE: 'mdi:package-variant'
78
79
  };
79
80
  /**
80
- * Category-specific icons matching Langflow's visual style
81
+ * Category-specific icons for built-in categories.
82
+ * Custom categories fall back to DEFAULT_ICONS.CATEGORY.
83
+ * These serve as static defaults; the categories store provides dynamic overrides.
81
84
  */
82
85
  export const CATEGORY_ICONS = {
83
86
  triggers: 'mdi:lightning-bolt',
@@ -109,20 +112,22 @@ export function getNodeIcon(nodeIcon, category) {
109
112
  if (nodeIcon) {
110
113
  return nodeIcon;
111
114
  }
112
- // If category is provided, use category icon
113
- if (category && CATEGORY_ICONS[category]) {
114
- return CATEGORY_ICONS[category];
115
+ // If category is provided, use category icon from store (which includes API overrides)
116
+ if (category) {
117
+ return getCategoryIconFromStore(category);
115
118
  }
116
119
  // Fallback to default node icon
117
120
  return DEFAULT_ICONS.NODE;
118
121
  }
119
122
  /**
120
- * Get the appropriate icon for a category
123
+ * Get the appropriate icon for a category.
124
+ * Checks the categories store first (which includes API overrides),
125
+ * then falls back to the static CATEGORY_ICONS map, then to the default.
121
126
  * @param category - The category
122
127
  * @returns The icon to use
123
128
  */
124
129
  export function getCategoryIcon(category) {
125
- return CATEGORY_ICONS[category] || DEFAULT_ICONS.CATEGORY;
130
+ return getCategoryIconFromStore(category);
126
131
  }
127
132
  /**
128
133
  * Get a default icon by key
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@d34dman/flowdrop",
3
3
  "license": "MIT",
4
4
  "private": false,
5
- "version": "0.0.51",
5
+ "version": "0.0.52",
6
6
  "scripts": {
7
7
  "dev": "vite dev",
8
8
  "build": "vite build && npm run prepack",