@d34dman/flowdrop 0.0.52 → 0.0.53
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/components/App.svelte +2 -0
- package/dist/components/ConfigForm.svelte +1 -0
- package/dist/components/SettingsPanel.svelte +1 -2
- package/dist/components/ThemeToggle.svelte +1 -1
- package/dist/components/WorkflowEditor.svelte +1 -2
- package/dist/components/form/FormAutocomplete.svelte +3 -12
- package/dist/components/form/FormField.svelte +1 -1
- package/dist/components/form/FormFieldLight.svelte +1 -1
- package/dist/components/nodes/TerminalNode.svelte +45 -9
- package/dist/components/nodes/TerminalNode.svelte.d.ts +2 -1
- package/dist/components/nodes/ToolNode.svelte +17 -11
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/settings/index.d.ts +2 -1
- package/dist/settings/index.js +2 -1
- package/dist/stores/settingsStore.d.ts +44 -2
- package/dist/stores/settingsStore.js +37 -15
- package/dist/types/index.d.ts +2 -0
- package/dist/utils/fetchWithAuth.d.ts +25 -0
- package/dist/utils/fetchWithAuth.js +34 -0
- package/package.json +1 -1
- package/dist/stores/themeStore.d.ts +0 -68
- package/dist/stores/themeStore.js +0 -213
|
@@ -738,6 +738,7 @@
|
|
|
738
738
|
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
739
739
|
>
|
|
740
740
|
<ConfigForm
|
|
741
|
+
{authProvider}
|
|
741
742
|
schema={workflowConfigSchema}
|
|
742
743
|
values={workflowConfigValues}
|
|
743
744
|
showUIExtensions={false}
|
|
@@ -765,6 +766,7 @@
|
|
|
765
766
|
onClose={closeConfigSidebar}
|
|
766
767
|
>
|
|
767
768
|
<ConfigForm
|
|
769
|
+
{authProvider}
|
|
768
770
|
node={currentNode}
|
|
769
771
|
workflowId={$workflowStore?.id}
|
|
770
772
|
workflowNodes={$workflowStore?.nodes}
|
|
@@ -144,8 +144,7 @@
|
|
|
144
144
|
proximityConnect: {
|
|
145
145
|
type: 'boolean',
|
|
146
146
|
title: 'Proximity Connect',
|
|
147
|
-
description:
|
|
148
|
-
'Auto-connect compatible ports when dragging nodes near each other',
|
|
147
|
+
description: 'Auto-connect compatible ports when dragging nodes near each other',
|
|
149
148
|
default: false
|
|
150
149
|
},
|
|
151
150
|
proximityConnectDistance: {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
9
|
import Icon from '@iconify/svelte';
|
|
10
|
-
import { theme, resolvedTheme, cycleTheme } from '../stores/
|
|
10
|
+
import { theme, resolvedTheme, cycleTheme } from '../stores/settingsStore.js';
|
|
11
11
|
import type { ThemePreference } from '../types/settings.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
type ColorMode
|
|
17
17
|
} from '@xyflow/svelte';
|
|
18
18
|
import '@xyflow/svelte/dist/style.css';
|
|
19
|
-
import { resolvedTheme } from '../stores/
|
|
20
|
-
import { editorSettings, behaviorSettings } from '../stores/settingsStore.js';
|
|
19
|
+
import { resolvedTheme, editorSettings, behaviorSettings } from '../stores/settingsStore.js';
|
|
21
20
|
import type {
|
|
22
21
|
WorkflowNode as WorkflowNodeType,
|
|
23
22
|
NodeMetadata,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import Icon from '@iconify/svelte';
|
|
26
26
|
import type { AutocompleteConfig, AuthProvider } from '../../types/index.js';
|
|
27
27
|
import type { FieldOption } from './types.js';
|
|
28
|
+
import { buildFetchHeaders } from '../../utils/fetchWithAuth.js';
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Props interface for FormAutocomplete component
|
|
@@ -192,18 +193,8 @@
|
|
|
192
193
|
abortController = new AbortController();
|
|
193
194
|
|
|
194
195
|
try {
|
|
195
|
-
// Build headers with authentication
|
|
196
|
-
const headers
|
|
197
|
-
Accept: 'application/json',
|
|
198
|
-
'Content-Type': 'application/json'
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// Add auth headers if provider is available (call getter to get current value)
|
|
202
|
-
const authProvider = getAuthProvider?.();
|
|
203
|
-
if (authProvider) {
|
|
204
|
-
const authHeaders = await authProvider.getAuthHeaders();
|
|
205
|
-
Object.assign(headers, authHeaders);
|
|
206
|
-
}
|
|
196
|
+
// Build headers with authentication (call getter to get current value)
|
|
197
|
+
const headers = await buildFetchHeaders(getAuthProvider?.());
|
|
207
198
|
|
|
208
199
|
// Fetch with timeout
|
|
209
200
|
const timeoutId = setTimeout(() => {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
import type { FieldSchema } from './types.js';
|
|
45
45
|
import { getSchemaOptions } from './types.js';
|
|
46
46
|
import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
47
|
-
import { resolvedTheme } from '../../stores/
|
|
47
|
+
import { resolvedTheme } from '../../stores/settingsStore.js';
|
|
48
48
|
|
|
49
49
|
interface Props {
|
|
50
50
|
/** Unique key/id for the field */
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
import FormCheckboxGroup from './FormCheckboxGroup.svelte';
|
|
44
44
|
import FormArray from './FormArray.svelte';
|
|
45
45
|
import { resolveFieldComponent } from '../../form/fieldRegistry.js';
|
|
46
|
-
import { resolvedTheme } from '../../stores/
|
|
46
|
+
import { resolvedTheme } from '../../stores/settingsStore.js';
|
|
47
47
|
import type { FieldSchema } from './types.js';
|
|
48
48
|
import { getSchemaOptions } from './types.js';
|
|
49
49
|
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
<script lang="ts">
|
|
12
12
|
import { Position, Handle } from '@xyflow/svelte';
|
|
13
|
-
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
13
|
+
import type { ConfigValues, NodeMetadata, NodeExtensions, NodePort } from '../../types/index.js';
|
|
14
14
|
import Icon from '@iconify/svelte';
|
|
15
15
|
import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
|
|
16
16
|
import { getNodeIcon } from '../../utils/icons.js';
|
|
17
17
|
import { getCircleHandlePosition } from '../../utils/handlePositioning.js';
|
|
18
|
+
import { connectedHandles } from '../../stores/workflowStore.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Terminal node variant types
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
config: ConfigValues;
|
|
71
72
|
metadata: NodeMetadata;
|
|
72
73
|
nodeId?: string;
|
|
74
|
+
extensions?: NodeExtensions;
|
|
73
75
|
onConfigOpen?: (node: {
|
|
74
76
|
id: string;
|
|
75
77
|
type: string;
|
|
@@ -133,6 +135,30 @@
|
|
|
133
135
|
*/
|
|
134
136
|
let variantConfig = $derived(VARIANT_CONFIGS[variant]);
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Get the hideUnconnectedHandles setting from extensions
|
|
140
|
+
* Merges node type defaults with instance overrides
|
|
141
|
+
*/
|
|
142
|
+
const hideUnconnectedHandles = $derived(() => {
|
|
143
|
+
const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
|
|
144
|
+
const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
|
|
145
|
+
return instanceOverride ?? typeDefault;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Check if a port should be visible based on connection state and settings
|
|
150
|
+
*/
|
|
151
|
+
function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
|
|
152
|
+
if (!hideUnconnectedHandles()) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (port.required) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
const handleId = `${props.data.nodeId}-${type}-${port.id}`;
|
|
159
|
+
return $connectedHandles.has(handleId);
|
|
160
|
+
}
|
|
161
|
+
|
|
136
162
|
/**
|
|
137
163
|
* Get icon using the same resolution as WorkflowNode
|
|
138
164
|
* Uses getNodeIcon utility with category fallback, or variant default
|
|
@@ -239,14 +265,24 @@
|
|
|
239
265
|
);
|
|
240
266
|
|
|
241
267
|
/**
|
|
242
|
-
*
|
|
268
|
+
* Visible input ports filtered by hideUnconnectedHandles setting
|
|
269
|
+
*/
|
|
270
|
+
let visibleInputPorts = $derived(inputPorts.filter((port) => isPortVisible(port, 'input')));
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Visible output ports filtered by hideUnconnectedHandles setting
|
|
274
|
+
*/
|
|
275
|
+
let visibleOutputPorts = $derived(outputPorts.filter((port) => isPortVisible(port, 'output')));
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Determine if we should show inputs based on visible ports
|
|
243
279
|
*/
|
|
244
|
-
let showInputs = $derived(
|
|
280
|
+
let showInputs = $derived(visibleInputPorts.length > 0);
|
|
245
281
|
|
|
246
282
|
/**
|
|
247
|
-
* Determine if we should show outputs based on ports
|
|
283
|
+
* Determine if we should show outputs based on visible ports
|
|
248
284
|
*/
|
|
249
|
-
let showOutputs = $derived(
|
|
285
|
+
let showOutputs = $derived(visibleOutputPorts.length > 0);
|
|
250
286
|
|
|
251
287
|
/**
|
|
252
288
|
* Handle configuration sidebar - using global ConfigSidebar
|
|
@@ -317,8 +353,8 @@
|
|
|
317
353
|
<div class="flowdrop-terminal-node__circle-wrapper">
|
|
318
354
|
<!-- Input Handles (for end/exit variants) -->
|
|
319
355
|
{#if showInputs}
|
|
320
|
-
{#each
|
|
321
|
-
{@const pos = getCircleHandlePosition(index,
|
|
356
|
+
{#each visibleInputPorts as port, index (`${port.id}-${visibleInputPorts.length}`)}
|
|
357
|
+
{@const pos = getCircleHandlePosition(index, visibleInputPorts.length, 'left')}
|
|
322
358
|
<Handle
|
|
323
359
|
type="target"
|
|
324
360
|
position={Position.Left}
|
|
@@ -339,8 +375,8 @@
|
|
|
339
375
|
|
|
340
376
|
<!-- Output Handles (for start variant) -->
|
|
341
377
|
{#if showOutputs}
|
|
342
|
-
{#each
|
|
343
|
-
{@const pos = getCircleHandlePosition(index,
|
|
378
|
+
{#each visibleOutputPorts as port, index (`${port.id}-${visibleOutputPorts.length}`)}
|
|
379
|
+
{@const pos = getCircleHandlePosition(index, visibleOutputPorts.length, 'right')}
|
|
344
380
|
<Handle
|
|
345
381
|
type="source"
|
|
346
382
|
position={Position.Right}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
1
|
+
import type { ConfigValues, NodeMetadata, NodeExtensions } from '../../types/index.js';
|
|
2
2
|
type $$ComponentProps = {
|
|
3
3
|
data: {
|
|
4
4
|
label: string;
|
|
5
5
|
config: ConfigValues;
|
|
6
6
|
metadata: NodeMetadata;
|
|
7
7
|
nodeId?: string;
|
|
8
|
+
extensions?: NodeExtensions;
|
|
8
9
|
onConfigOpen?: (node: {
|
|
9
10
|
id: string;
|
|
10
11
|
type: string;
|
|
@@ -67,9 +67,7 @@
|
|
|
67
67
|
* This allows users to customize the badge text per-instance via config.
|
|
68
68
|
*/
|
|
69
69
|
const displayBadge = $derived(
|
|
70
|
-
(props.data.config?.instanceBadge as string) ||
|
|
71
|
-
(props.data.metadata?.badge as string) ||
|
|
72
|
-
'TOOL'
|
|
70
|
+
(props.data.config?.instanceBadge as string) || (props.data.metadata?.badge as string) || 'TOOL'
|
|
73
71
|
);
|
|
74
72
|
|
|
75
73
|
/**
|
|
@@ -96,20 +94,28 @@
|
|
|
96
94
|
*/
|
|
97
95
|
let nodeStyle = $derived(`--fd-tool-node-color: ${toolColor}`);
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Configurable port dataType to expose on this tool node.
|
|
99
|
+
* Defaults to 'tool', but can be overridden via metadata.portDataType
|
|
100
|
+
* to show a different port type (e.g., 'trigger') when the node is
|
|
101
|
+
* repurposed with a custom badge.
|
|
102
|
+
*/
|
|
103
|
+
let portDataType = $derived((props.data.metadata?.portDataType as string) || 'tool');
|
|
104
|
+
|
|
105
|
+
// Check for matching interface ports in metadata
|
|
100
106
|
let hasToolInputPort = $derived(
|
|
101
|
-
props.data.metadata?.inputs?.some((port) => port.dataType ===
|
|
107
|
+
props.data.metadata?.inputs?.some((port) => port.dataType === portDataType) || false
|
|
102
108
|
);
|
|
103
109
|
let hasToolOutputPort = $derived(
|
|
104
|
-
props.data.metadata?.outputs?.some((port) => port.dataType ===
|
|
110
|
+
props.data.metadata?.outputs?.some((port) => port.dataType === portDataType) || false
|
|
105
111
|
);
|
|
106
112
|
|
|
107
|
-
// Get the actual
|
|
113
|
+
// Get the actual matching ports for proper handle generation
|
|
108
114
|
let toolInputPort = $derived(
|
|
109
|
-
props.data.metadata?.inputs?.find((port) => port.dataType ===
|
|
115
|
+
props.data.metadata?.inputs?.find((port) => port.dataType === portDataType)
|
|
110
116
|
);
|
|
111
117
|
let toolOutputPort = $derived(
|
|
112
|
-
props.data.metadata?.outputs?.find((port) => port.dataType ===
|
|
118
|
+
props.data.metadata?.outputs?.find((port) => port.dataType === portDataType)
|
|
113
119
|
);
|
|
114
120
|
|
|
115
121
|
/**
|
|
@@ -159,7 +165,7 @@
|
|
|
159
165
|
position={Position.Left}
|
|
160
166
|
id={`${props.data.nodeId}-input-${toolInputPort.id}`}
|
|
161
167
|
style="top: 40px; transform: translateY(-50%); margin-left: -10px; --fd-handle-fill: {getDataTypeColor(
|
|
162
|
-
|
|
168
|
+
portDataType
|
|
163
169
|
)}; --fd-handle-border-color: var(--fd-handle-border);"
|
|
164
170
|
/>
|
|
165
171
|
{/if}
|
|
@@ -232,7 +238,7 @@
|
|
|
232
238
|
position={Position.Right}
|
|
233
239
|
id={`${props.data.nodeId}-output-${toolOutputPort.id}`}
|
|
234
240
|
style="top: 40px; transform: translateY(-50%); margin-right: -10px; --fd-handle-fill: {getDataTypeColor(
|
|
235
|
-
|
|
241
|
+
portDataType
|
|
236
242
|
)}; --fd-handle-border-color: var(--fd-handle-border);"
|
|
237
243
|
/>
|
|
238
244
|
{/if}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -40,5 +40,5 @@ export { isFieldOptionArray, normalizeOptions } from '../components/form/types.j
|
|
|
40
40
|
export { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
|
|
41
41
|
export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints.js';
|
|
42
42
|
export * from '../adapters/WorkflowAdapter.js';
|
|
43
|
-
export type { ThemePreference, ResolvedTheme } from '../stores/
|
|
44
|
-
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/
|
|
43
|
+
export type { ThemePreference, ResolvedTheme } from '../stores/settingsStore.js';
|
|
44
|
+
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
|
package/dist/core/index.js
CHANGED
|
@@ -51,4 +51,4 @@ export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints
|
|
|
51
51
|
// Adapters
|
|
52
52
|
// ============================================================================
|
|
53
53
|
export * from '../adapters/WorkflowAdapter.js';
|
|
54
|
-
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/
|
|
54
|
+
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
|
package/dist/settings/index.d.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* preferences with hybrid persistence (localStorage + optional API sync).
|
|
6
6
|
*
|
|
7
7
|
* Theme stores and functions (theme, resolvedTheme, setTheme, toggleTheme,
|
|
8
|
-
* cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core
|
|
8
|
+
* cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`
|
|
9
|
+
* (sourced from settingsStore).
|
|
9
10
|
*
|
|
10
11
|
* @module settings
|
|
11
12
|
*
|
package/dist/settings/index.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* preferences with hybrid persistence (localStorage + optional API sync).
|
|
6
6
|
*
|
|
7
7
|
* Theme stores and functions (theme, resolvedTheme, setTheme, toggleTheme,
|
|
8
|
-
* cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core
|
|
8
|
+
* cycleTheme, initializeTheme) are exported from `@d34dman/flowdrop/core`
|
|
9
|
+
* (sourced from settingsStore).
|
|
9
10
|
*
|
|
10
11
|
* @module settings
|
|
11
12
|
*
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* - Hybrid persistence (localStorage primary, optional API sync)
|
|
6
6
|
* - Category-specific derived stores for performance
|
|
7
7
|
* - Deep merge support for partial updates
|
|
8
|
-
* -
|
|
8
|
+
* - Integrated theme system with system preference detection
|
|
9
9
|
*
|
|
10
10
|
* @module stores/settingsStore
|
|
11
11
|
*/
|
|
12
|
-
import type { FlowDropSettings, ThemeSettings, EditorSettings, UISettings, BehaviorSettings, ApiSettings, PartialSettings, SyncStatus, SettingsChangeCallback, SettingsCategory } from '../types/settings.js';
|
|
12
|
+
import type { FlowDropSettings, ThemeSettings, EditorSettings, UISettings, BehaviorSettings, ApiSettings, PartialSettings, SyncStatus, ResolvedTheme, ThemePreference, SettingsChangeCallback, SettingsCategory } from '../types/settings.js';
|
|
13
|
+
export type { ThemePreference, ResolvedTheme } from '../types/settings.js';
|
|
13
14
|
/**
|
|
14
15
|
* Main settings store (read-only access to current settings)
|
|
15
16
|
*/
|
|
@@ -42,6 +43,16 @@ export declare const behaviorSettings: import("svelte/store").Readable<BehaviorS
|
|
|
42
43
|
* API settings store
|
|
43
44
|
*/
|
|
44
45
|
export declare const apiSettings: import("svelte/store").Readable<ApiSettings>;
|
|
46
|
+
/**
|
|
47
|
+
* Theme preference store
|
|
48
|
+
* Derived from themeSettings for convenient access
|
|
49
|
+
*/
|
|
50
|
+
export declare const theme: import("svelte/store").Readable<ThemePreference>;
|
|
51
|
+
/**
|
|
52
|
+
* Resolved theme - the actual theme applied ('light' or 'dark')
|
|
53
|
+
* When preference is 'auto', resolves based on system preference
|
|
54
|
+
*/
|
|
55
|
+
export declare const resolvedTheme: import("svelte/store").Readable<ResolvedTheme>;
|
|
45
56
|
/**
|
|
46
57
|
* Update settings with partial values
|
|
47
58
|
*
|
|
@@ -58,6 +69,37 @@ export declare function resetSettings(categories?: SettingsCategory[]): void;
|
|
|
58
69
|
* Get current settings synchronously
|
|
59
70
|
*/
|
|
60
71
|
export declare function getSettings(): FlowDropSettings;
|
|
72
|
+
/**
|
|
73
|
+
* Set the theme preference
|
|
74
|
+
*
|
|
75
|
+
* @param newTheme - The new theme preference ('light', 'dark', or 'auto')
|
|
76
|
+
*/
|
|
77
|
+
export declare function setTheme(newTheme: ThemePreference): void;
|
|
78
|
+
/**
|
|
79
|
+
* Toggle between light and dark themes
|
|
80
|
+
* If currently 'auto', switches to the opposite of system preference
|
|
81
|
+
*/
|
|
82
|
+
export declare function toggleTheme(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Cycle through theme options: light -> dark -> auto -> light
|
|
85
|
+
*/
|
|
86
|
+
export declare function cycleTheme(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Initialize the theme system
|
|
89
|
+
* Should be called once on app startup
|
|
90
|
+
*
|
|
91
|
+
* This function:
|
|
92
|
+
* 1. Applies the current resolved theme to the document
|
|
93
|
+
* 2. Sets up reactivity to apply theme changes
|
|
94
|
+
*/
|
|
95
|
+
export declare function initializeTheme(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Check if theme system is initialized
|
|
98
|
+
* Useful for SSR scenarios
|
|
99
|
+
*
|
|
100
|
+
* @returns true if running in browser and theme is applied
|
|
101
|
+
*/
|
|
102
|
+
export declare function isThemeInitialized(): boolean;
|
|
61
103
|
/**
|
|
62
104
|
* Set the settings service for API operations
|
|
63
105
|
*
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - Hybrid persistence (localStorage primary, optional API sync)
|
|
6
6
|
* - Category-specific derived stores for performance
|
|
7
7
|
* - Deep merge support for partial updates
|
|
8
|
-
* -
|
|
8
|
+
* - Integrated theme system with system preference detection
|
|
9
9
|
*
|
|
10
10
|
* @module stores/settingsStore
|
|
11
11
|
*/
|
|
@@ -157,7 +157,7 @@ export const behaviorSettings = derived(settingsStore, ($settings) => $settings.
|
|
|
157
157
|
*/
|
|
158
158
|
export const apiSettings = derived(settingsStore, ($settings) => $settings.api);
|
|
159
159
|
// =========================================================================
|
|
160
|
-
// Theme
|
|
160
|
+
// Theme System
|
|
161
161
|
// =========================================================================
|
|
162
162
|
/**
|
|
163
163
|
* System theme preference store
|
|
@@ -188,13 +188,15 @@ if (typeof window !== 'undefined') {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
/**
|
|
191
|
-
* Theme preference
|
|
191
|
+
* Theme preference store
|
|
192
|
+
* Derived from themeSettings for convenient access
|
|
192
193
|
*/
|
|
193
|
-
const theme = derived(themeSettings, ($theme) => $theme.preference);
|
|
194
|
+
export const theme = derived(themeSettings, ($theme) => $theme.preference);
|
|
194
195
|
/**
|
|
195
|
-
* Resolved theme
|
|
196
|
+
* Resolved theme - the actual theme applied ('light' or 'dark')
|
|
197
|
+
* When preference is 'auto', resolves based on system preference
|
|
196
198
|
*/
|
|
197
|
-
const resolvedTheme = derived([themeSettings, systemTheme], ([$themeSettings, $systemTheme]) => {
|
|
199
|
+
export const resolvedTheme = derived([themeSettings, systemTheme], ([$themeSettings, $systemTheme]) => {
|
|
198
200
|
if ($themeSettings.preference === 'auto') {
|
|
199
201
|
return $systemTheme;
|
|
200
202
|
}
|
|
@@ -288,18 +290,21 @@ export function getSettings() {
|
|
|
288
290
|
return get(settingsStore);
|
|
289
291
|
}
|
|
290
292
|
// =========================================================================
|
|
291
|
-
// Theme
|
|
293
|
+
// Theme Actions
|
|
292
294
|
// =========================================================================
|
|
293
295
|
/**
|
|
294
|
-
* Set the theme preference
|
|
296
|
+
* Set the theme preference
|
|
297
|
+
*
|
|
298
|
+
* @param newTheme - The new theme preference ('light', 'dark', or 'auto')
|
|
295
299
|
*/
|
|
296
|
-
function setTheme(newTheme) {
|
|
300
|
+
export function setTheme(newTheme) {
|
|
297
301
|
updateSettings({ theme: { preference: newTheme } });
|
|
298
302
|
}
|
|
299
303
|
/**
|
|
300
|
-
* Toggle between light and dark themes
|
|
304
|
+
* Toggle between light and dark themes
|
|
305
|
+
* If currently 'auto', switches to the opposite of system preference
|
|
301
306
|
*/
|
|
302
|
-
function toggleTheme() {
|
|
307
|
+
export function toggleTheme() {
|
|
303
308
|
const currentTheme = get(theme);
|
|
304
309
|
const currentResolved = get(resolvedTheme);
|
|
305
310
|
if (currentTheme === 'auto') {
|
|
@@ -310,9 +315,9 @@ function toggleTheme() {
|
|
|
310
315
|
}
|
|
311
316
|
}
|
|
312
317
|
/**
|
|
313
|
-
* Cycle through theme options
|
|
318
|
+
* Cycle through theme options: light -> dark -> auto -> light
|
|
314
319
|
*/
|
|
315
|
-
function cycleTheme() {
|
|
320
|
+
export function cycleTheme() {
|
|
316
321
|
const currentTheme = get(theme);
|
|
317
322
|
switch (currentTheme) {
|
|
318
323
|
case 'light':
|
|
@@ -338,9 +343,14 @@ function applyTheme(resolved) {
|
|
|
338
343
|
document.documentElement.setAttribute('data-theme', resolved);
|
|
339
344
|
}
|
|
340
345
|
/**
|
|
341
|
-
* Initialize the theme system
|
|
346
|
+
* Initialize the theme system
|
|
347
|
+
* Should be called once on app startup
|
|
348
|
+
*
|
|
349
|
+
* This function:
|
|
350
|
+
* 1. Applies the current resolved theme to the document
|
|
351
|
+
* 2. Sets up reactivity to apply theme changes
|
|
342
352
|
*/
|
|
343
|
-
function initializeTheme() {
|
|
353
|
+
export function initializeTheme() {
|
|
344
354
|
const resolved = get(resolvedTheme);
|
|
345
355
|
applyTheme(resolved);
|
|
346
356
|
// Subscribe to resolved theme changes and apply them
|
|
@@ -348,6 +358,18 @@ function initializeTheme() {
|
|
|
348
358
|
applyTheme(theme);
|
|
349
359
|
});
|
|
350
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Check if theme system is initialized
|
|
363
|
+
* Useful for SSR scenarios
|
|
364
|
+
*
|
|
365
|
+
* @returns true if running in browser and theme is applied
|
|
366
|
+
*/
|
|
367
|
+
export function isThemeInitialized() {
|
|
368
|
+
if (typeof document === 'undefined') {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
return document.documentElement.hasAttribute('data-theme');
|
|
372
|
+
}
|
|
351
373
|
// =========================================================================
|
|
352
374
|
// API Sync Functions
|
|
353
375
|
// =========================================================================
|
package/dist/types/index.d.ts
CHANGED
|
@@ -511,6 +511,8 @@ export interface NodeMetadata {
|
|
|
511
511
|
color?: string;
|
|
512
512
|
/** Badge label displayed in the node header (e.g., "TOOL", "API", "LLM"). Overridable per-instance via config.instanceBadge. */
|
|
513
513
|
badge?: string;
|
|
514
|
+
/** Port dataType to expose on tool nodes. Defaults to 'tool'. Set to another type (e.g., 'trigger') to show that port instead. */
|
|
515
|
+
portDataType?: string;
|
|
514
516
|
inputs: NodePort[];
|
|
515
517
|
outputs: NodePort[];
|
|
516
518
|
configSchema?: ConfigSchema;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch authentication utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared logic for building HTTP headers with authentication.
|
|
5
|
+
* Used by components that make authenticated API requests (e.g., FormAutocomplete).
|
|
6
|
+
*
|
|
7
|
+
* @module utils/fetchWithAuth
|
|
8
|
+
*/
|
|
9
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build fetch headers with optional authentication
|
|
12
|
+
*
|
|
13
|
+
* Constructs standard JSON request headers and merges in authentication
|
|
14
|
+
* headers from the provided AuthProvider, if available.
|
|
15
|
+
*
|
|
16
|
+
* @param authProvider - Optional auth provider to get headers from
|
|
17
|
+
* @returns Promise resolving to a complete headers object
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const headers = await buildFetchHeaders(authProvider);
|
|
22
|
+
* const response = await fetch(url, { headers });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildFetchHeaders(authProvider?: AuthProvider): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch authentication utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared logic for building HTTP headers with authentication.
|
|
5
|
+
* Used by components that make authenticated API requests (e.g., FormAutocomplete).
|
|
6
|
+
*
|
|
7
|
+
* @module utils/fetchWithAuth
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Build fetch headers with optional authentication
|
|
11
|
+
*
|
|
12
|
+
* Constructs standard JSON request headers and merges in authentication
|
|
13
|
+
* headers from the provided AuthProvider, if available.
|
|
14
|
+
*
|
|
15
|
+
* @param authProvider - Optional auth provider to get headers from
|
|
16
|
+
* @returns Promise resolving to a complete headers object
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const headers = await buildFetchHeaders(authProvider);
|
|
21
|
+
* const response = await fetch(url, { headers });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export async function buildFetchHeaders(authProvider) {
|
|
25
|
+
const headers = {
|
|
26
|
+
Accept: 'application/json',
|
|
27
|
+
'Content-Type': 'application/json'
|
|
28
|
+
};
|
|
29
|
+
if (authProvider) {
|
|
30
|
+
const authHeaders = await authProvider.getAuthHeaders();
|
|
31
|
+
Object.assign(headers, authHeaders);
|
|
32
|
+
}
|
|
33
|
+
return headers;
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme Store for FlowDrop
|
|
3
|
-
*
|
|
4
|
-
* @deprecated This module is deprecated. Use `settingsStore` instead.
|
|
5
|
-
*
|
|
6
|
-
* The theme functionality has been moved to the unified settings system.
|
|
7
|
-
* Import from settingsStore for new code:
|
|
8
|
-
*
|
|
9
|
-
* ```typescript
|
|
10
|
-
* import { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme } from "./settingsStore.js";
|
|
11
|
-
* ```
|
|
12
|
-
*
|
|
13
|
-
* This module re-exports from settingsStore for backward compatibility.
|
|
14
|
-
*
|
|
15
|
-
* Provides reactive theme state management with:
|
|
16
|
-
* - Three theme modes: 'light', 'dark', 'auto' (follows system preference)
|
|
17
|
-
* - localStorage persistence
|
|
18
|
-
* - System preference detection via matchMedia
|
|
19
|
-
* - Automatic data-theme attribute application
|
|
20
|
-
*
|
|
21
|
-
* @module stores/themeStore
|
|
22
|
-
*/
|
|
23
|
-
/** Theme preference options */
|
|
24
|
-
export type ThemePreference = 'light' | 'dark' | 'auto';
|
|
25
|
-
/** Resolved theme (actual applied theme, never 'auto') */
|
|
26
|
-
export type ResolvedTheme = 'light' | 'dark';
|
|
27
|
-
/**
|
|
28
|
-
* User's theme preference store
|
|
29
|
-
* Can be 'light', 'dark', or 'auto'
|
|
30
|
-
*/
|
|
31
|
-
export declare const theme: import("svelte/store").Writable<ThemePreference>;
|
|
32
|
-
/**
|
|
33
|
-
* Resolved theme store
|
|
34
|
-
* Always returns the actual theme being applied ('light' or 'dark')
|
|
35
|
-
* When theme is 'auto', this reflects the system preference
|
|
36
|
-
*/
|
|
37
|
-
export declare const resolvedTheme: import("svelte/store").Readable<ResolvedTheme>;
|
|
38
|
-
/**
|
|
39
|
-
* Set the theme preference
|
|
40
|
-
*
|
|
41
|
-
* @param newTheme - The new theme preference ('light', 'dark', or 'auto')
|
|
42
|
-
*/
|
|
43
|
-
export declare function setTheme(newTheme: ThemePreference): void;
|
|
44
|
-
/**
|
|
45
|
-
* Toggle between light and dark themes
|
|
46
|
-
* If currently 'auto', switches to the opposite of system preference
|
|
47
|
-
*/
|
|
48
|
-
export declare function toggleTheme(): void;
|
|
49
|
-
/**
|
|
50
|
-
* Cycle through theme options: light -> dark -> auto -> light
|
|
51
|
-
*/
|
|
52
|
-
export declare function cycleTheme(): void;
|
|
53
|
-
/**
|
|
54
|
-
* Initialize the theme system
|
|
55
|
-
* Should be called once on app startup
|
|
56
|
-
*
|
|
57
|
-
* This function:
|
|
58
|
-
* 1. Applies the current resolved theme to the document
|
|
59
|
-
* 2. Sets up reactivity to apply theme changes
|
|
60
|
-
*/
|
|
61
|
-
export declare function initializeTheme(): void;
|
|
62
|
-
/**
|
|
63
|
-
* Check if theme system is initialized
|
|
64
|
-
* Useful for SSR scenarios
|
|
65
|
-
*
|
|
66
|
-
* @returns true if running in browser and theme is applied
|
|
67
|
-
*/
|
|
68
|
-
export declare function isThemeInitialized(): boolean;
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme Store for FlowDrop
|
|
3
|
-
*
|
|
4
|
-
* @deprecated This module is deprecated. Use `settingsStore` instead.
|
|
5
|
-
*
|
|
6
|
-
* The theme functionality has been moved to the unified settings system.
|
|
7
|
-
* Import from settingsStore for new code:
|
|
8
|
-
*
|
|
9
|
-
* ```typescript
|
|
10
|
-
* import { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme } from "./settingsStore.js";
|
|
11
|
-
* ```
|
|
12
|
-
*
|
|
13
|
-
* This module re-exports from settingsStore for backward compatibility.
|
|
14
|
-
*
|
|
15
|
-
* Provides reactive theme state management with:
|
|
16
|
-
* - Three theme modes: 'light', 'dark', 'auto' (follows system preference)
|
|
17
|
-
* - localStorage persistence
|
|
18
|
-
* - System preference detection via matchMedia
|
|
19
|
-
* - Automatic data-theme attribute application
|
|
20
|
-
*
|
|
21
|
-
* @module stores/themeStore
|
|
22
|
-
*/
|
|
23
|
-
import { writable, derived, get } from 'svelte/store';
|
|
24
|
-
/** localStorage key for persisting theme preference */
|
|
25
|
-
const STORAGE_KEY = 'flowdrop-theme';
|
|
26
|
-
/** Default theme preference when none is stored */
|
|
27
|
-
const DEFAULT_THEME = 'auto';
|
|
28
|
-
// =========================================================================
|
|
29
|
-
// System Preference Detection
|
|
30
|
-
// =========================================================================
|
|
31
|
-
/**
|
|
32
|
-
* Get the system's color scheme preference
|
|
33
|
-
*
|
|
34
|
-
* @returns 'dark' if system prefers dark mode, 'light' otherwise
|
|
35
|
-
*/
|
|
36
|
-
function getSystemTheme() {
|
|
37
|
-
if (typeof window === 'undefined') {
|
|
38
|
-
return 'light';
|
|
39
|
-
}
|
|
40
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Store for system theme preference
|
|
44
|
-
* Updates when system preference changes
|
|
45
|
-
*/
|
|
46
|
-
const systemTheme = writable(typeof window !== 'undefined' ? getSystemTheme() : 'light');
|
|
47
|
-
// Listen for system theme changes
|
|
48
|
-
if (typeof window !== 'undefined') {
|
|
49
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
50
|
-
/**
|
|
51
|
-
* Handler for system theme preference changes
|
|
52
|
-
*/
|
|
53
|
-
const handleSystemThemeChange = (event) => {
|
|
54
|
-
systemTheme.set(event.matches ? 'dark' : 'light');
|
|
55
|
-
};
|
|
56
|
-
// Modern browsers use addEventListener
|
|
57
|
-
if (mediaQuery.addEventListener) {
|
|
58
|
-
mediaQuery.addEventListener('change', handleSystemThemeChange);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
// Fallback for older browsers
|
|
62
|
-
mediaQuery.addListener(handleSystemThemeChange);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// =========================================================================
|
|
66
|
-
// Theme Preference Store
|
|
67
|
-
// =========================================================================
|
|
68
|
-
/**
|
|
69
|
-
* Load saved theme preference from localStorage
|
|
70
|
-
*
|
|
71
|
-
* @returns Saved theme preference or default
|
|
72
|
-
*/
|
|
73
|
-
function loadSavedTheme() {
|
|
74
|
-
if (typeof window === 'undefined') {
|
|
75
|
-
return DEFAULT_THEME;
|
|
76
|
-
}
|
|
77
|
-
try {
|
|
78
|
-
const saved = localStorage.getItem(STORAGE_KEY);
|
|
79
|
-
if (saved === 'light' || saved === 'dark' || saved === 'auto') {
|
|
80
|
-
return saved;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
// localStorage may be unavailable (e.g., private browsing)
|
|
85
|
-
console.warn('Failed to load theme from localStorage');
|
|
86
|
-
}
|
|
87
|
-
return DEFAULT_THEME;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Save theme preference to localStorage
|
|
91
|
-
*
|
|
92
|
-
* @param theme - Theme preference to save
|
|
93
|
-
*/
|
|
94
|
-
function saveTheme(theme) {
|
|
95
|
-
if (typeof window === 'undefined') {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
localStorage.setItem(STORAGE_KEY, theme);
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// localStorage may be unavailable
|
|
103
|
-
console.warn('Failed to save theme to localStorage');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* User's theme preference store
|
|
108
|
-
* Can be 'light', 'dark', or 'auto'
|
|
109
|
-
*/
|
|
110
|
-
export const theme = writable(loadSavedTheme());
|
|
111
|
-
// =========================================================================
|
|
112
|
-
// Resolved Theme Store
|
|
113
|
-
// =========================================================================
|
|
114
|
-
/**
|
|
115
|
-
* Resolved theme store
|
|
116
|
-
* Always returns the actual theme being applied ('light' or 'dark')
|
|
117
|
-
* When theme is 'auto', this reflects the system preference
|
|
118
|
-
*/
|
|
119
|
-
export const resolvedTheme = derived([theme, systemTheme], ([$theme, $systemTheme]) => {
|
|
120
|
-
if ($theme === 'auto') {
|
|
121
|
-
return $systemTheme;
|
|
122
|
-
}
|
|
123
|
-
return $theme;
|
|
124
|
-
});
|
|
125
|
-
// =========================================================================
|
|
126
|
-
// Theme Actions
|
|
127
|
-
// =========================================================================
|
|
128
|
-
/**
|
|
129
|
-
* Apply theme to the document
|
|
130
|
-
* Sets the data-theme attribute on the document element
|
|
131
|
-
*
|
|
132
|
-
* @param resolved - The resolved theme to apply
|
|
133
|
-
*/
|
|
134
|
-
function applyTheme(resolved) {
|
|
135
|
-
if (typeof document === 'undefined') {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
document.documentElement.setAttribute('data-theme', resolved);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Set the theme preference
|
|
142
|
-
*
|
|
143
|
-
* @param newTheme - The new theme preference ('light', 'dark', or 'auto')
|
|
144
|
-
*/
|
|
145
|
-
export function setTheme(newTheme) {
|
|
146
|
-
theme.set(newTheme);
|
|
147
|
-
saveTheme(newTheme);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Toggle between light and dark themes
|
|
151
|
-
* If currently 'auto', switches to the opposite of system preference
|
|
152
|
-
*/
|
|
153
|
-
export function toggleTheme() {
|
|
154
|
-
const currentTheme = get(theme);
|
|
155
|
-
const currentResolved = get(resolvedTheme);
|
|
156
|
-
if (currentTheme === 'auto') {
|
|
157
|
-
// Switch to opposite of system preference
|
|
158
|
-
setTheme(currentResolved === 'dark' ? 'light' : 'dark');
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
// Toggle between light and dark
|
|
162
|
-
setTheme(currentTheme === 'dark' ? 'light' : 'dark');
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Cycle through theme options: light -> dark -> auto -> light
|
|
167
|
-
*/
|
|
168
|
-
export function cycleTheme() {
|
|
169
|
-
const currentTheme = get(theme);
|
|
170
|
-
switch (currentTheme) {
|
|
171
|
-
case 'light':
|
|
172
|
-
setTheme('dark');
|
|
173
|
-
break;
|
|
174
|
-
case 'dark':
|
|
175
|
-
setTheme('auto');
|
|
176
|
-
break;
|
|
177
|
-
case 'auto':
|
|
178
|
-
setTheme('light');
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// =========================================================================
|
|
183
|
-
// Initialization
|
|
184
|
-
// =========================================================================
|
|
185
|
-
/**
|
|
186
|
-
* Initialize the theme system
|
|
187
|
-
* Should be called once on app startup
|
|
188
|
-
*
|
|
189
|
-
* This function:
|
|
190
|
-
* 1. Applies the current resolved theme to the document
|
|
191
|
-
* 2. Sets up reactivity to apply theme changes
|
|
192
|
-
*/
|
|
193
|
-
export function initializeTheme() {
|
|
194
|
-
// Apply initial theme
|
|
195
|
-
const resolved = get(resolvedTheme);
|
|
196
|
-
applyTheme(resolved);
|
|
197
|
-
// Subscribe to resolved theme changes and apply them
|
|
198
|
-
resolvedTheme.subscribe((resolved) => {
|
|
199
|
-
applyTheme(resolved);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Check if theme system is initialized
|
|
204
|
-
* Useful for SSR scenarios
|
|
205
|
-
*
|
|
206
|
-
* @returns true if running in browser and theme is applied
|
|
207
|
-
*/
|
|
208
|
-
export function isThemeInitialized() {
|
|
209
|
-
if (typeof document === 'undefined') {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
return document.documentElement.hasAttribute('data-theme');
|
|
213
|
-
}
|