@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.
- package/CHANGELOG.md +38 -0
- package/README.md +5 -5
- package/dist/adapters/WorkflowAdapter.js +4 -5
- package/dist/adapters/agentspec/AgentSpecAdapter.js +3 -3
- package/dist/adapters/agentspec/defaultNodeTypes.js +9 -9
- package/dist/commands/executor.js +5 -6
- package/dist/commands/types.js +5 -5
- package/dist/components/App.svelte +19 -150
- package/dist/components/Button.stories.svelte +65 -0
- package/dist/components/Button.stories.svelte.d.ts +19 -0
- package/dist/components/Button.svelte +62 -0
- package/dist/components/Button.svelte.d.ts +24 -0
- package/dist/components/ConfigForm.svelte +4 -4
- package/dist/components/EditorStatusBar.stories.svelte +44 -0
- package/dist/components/EditorStatusBar.stories.svelte.d.ts +27 -0
- package/dist/components/EditorStatusBar.svelte +99 -0
- package/dist/components/EditorStatusBar.svelte.d.ts +15 -0
- package/dist/components/IconButton.svelte +80 -0
- package/dist/components/IconButton.svelte.d.ts +30 -0
- package/dist/components/Input.svelte +74 -0
- package/dist/components/Input.svelte.d.ts +17 -0
- package/dist/components/Navbar.svelte +9 -4
- package/dist/components/Navbar.svelte.d.ts +3 -0
- package/dist/components/NodeSidebar.svelte +17 -115
- package/dist/components/NodeSwapPicker.svelte +12 -28
- package/dist/components/Select.svelte +53 -0
- package/dist/components/Select.svelte.d.ts +15 -0
- package/dist/components/Textarea.svelte +39 -0
- package/dist/components/Textarea.svelte.d.ts +12 -0
- package/dist/components/ThemeToggle.svelte +15 -89
- package/dist/components/UniversalNode.svelte +5 -4
- package/dist/components/UniversalNode.svelte.d.ts +1 -1
- package/dist/components/console/ConsoleInput.svelte +3 -3
- package/dist/components/form/FormArray.svelte +37 -157
- package/dist/components/form/FormCheckboxGroup.svelte +1 -1
- package/dist/components/form/FormField.svelte +5 -44
- package/dist/components/form/FormFieldLight.svelte +5 -44
- package/dist/components/form/FormFieldset.svelte +1 -1
- package/dist/components/form/FormNumberField.svelte +4 -32
- package/dist/components/form/FormRangeField.svelte +17 -7
- package/dist/components/form/FormSelect.svelte +13 -79
- package/dist/components/form/FormTextField.svelte +3 -39
- package/dist/components/form/FormTextarea.svelte +4 -43
- package/dist/components/form/resolveFieldType.d.ts +24 -0
- package/dist/components/form/resolveFieldType.js +55 -0
- package/dist/components/icons/CloseIcon.svelte +6 -0
- package/dist/components/icons/CloseIcon.svelte.d.ts +26 -0
- package/dist/components/nodes/AtomNode.svelte +3 -3
- package/dist/components/nodes/AtomNode.svelte.d.ts +1 -1
- package/dist/components/nodes/GatewayNode.svelte +8 -11
- package/dist/components/nodes/GatewayNode.svelte.d.ts +1 -1
- package/dist/components/nodes/IdeaNode.svelte +10 -8
- package/dist/components/nodes/IdeaNode.svelte.d.ts +8 -4
- package/dist/components/nodes/NotesNode.svelte +6 -4
- package/dist/components/nodes/NotesNode.svelte.d.ts +8 -4
- package/dist/components/nodes/SimpleNode.svelte +10 -8
- package/dist/components/nodes/SimpleNode.svelte.d.ts +4 -4
- package/dist/components/nodes/SquareNode.svelte +10 -8
- package/dist/components/nodes/SquareNode.svelte.d.ts +4 -4
- package/dist/components/nodes/TerminalNode.svelte +10 -8
- package/dist/components/nodes/TerminalNode.svelte.d.ts +4 -4
- package/dist/components/nodes/ToolNode.svelte +10 -8
- package/dist/components/nodes/ToolNode.svelte.d.ts +6 -6
- package/dist/components/nodes/WorkflowNode.svelte +7 -10
- package/dist/components/nodes/WorkflowNode.svelte.d.ts +1 -1
- package/dist/components/playground/InputCollector.svelte +11 -46
- package/dist/components/playground/PipelineKanbanView.svelte +2 -2
- package/dist/components/playground/PipelineTableView.svelte +2 -2
- package/dist/helpers/workflowEditorHelper.js +4 -5
- package/dist/messages/index.d.ts +1 -1
- package/dist/messages/index.js +1 -1
- package/dist/openapi/v1/openapi.yaml +2 -2
- package/dist/registry/nodeComponentRegistry.d.ts +2 -1
- package/dist/services/dynamicSchemaService.d.ts +2 -2
- package/dist/services/dynamicSchemaService.js +8 -8
- package/dist/skins/drafter.js +41 -28
- package/dist/stores/playgroundStore.svelte.js +1 -1
- package/dist/stores/workflowStore.svelte.js +0 -18
- package/dist/styles/base.css +247 -5
- package/dist/styles/tokens.css +6 -0
- package/dist/svelte-app.js +68 -107
- package/dist/types/index.d.ts +6 -7
- package/dist/utils/connections.js +20 -56
- package/dist/utils/nodeIds.d.ts +1 -1
- package/dist/utils/nodeIds.js +1 -1
- package/dist/utils/nodeSwap.js +3 -6
- package/package.json +1 -1
|
@@ -16,9 +16,10 @@ import { BaseRegistry } from './BaseRegistry.svelte.js';
|
|
|
16
16
|
* Any component registered in the registry must be compatible with these props.
|
|
17
17
|
*/
|
|
18
18
|
export interface NodeComponentProps {
|
|
19
|
+
/** The SvelteFlow node id */
|
|
20
|
+
id: string;
|
|
19
21
|
/** Node data containing label, config, metadata, executionInfo */
|
|
20
22
|
data: WorkflowNode['data'] & {
|
|
21
|
-
nodeId?: string;
|
|
22
23
|
onConfigOpen?: (node: {
|
|
23
24
|
id: string;
|
|
24
25
|
type: string;
|
|
@@ -33,7 +33,7 @@ export interface DynamicSchemaResult {
|
|
|
33
33
|
* const endpoint: DynamicSchemaEndpoint = {
|
|
34
34
|
* url: "/api/nodes/{nodeTypeId}/schema",
|
|
35
35
|
* method: "GET",
|
|
36
|
-
* parameterMapping: { nodeTypeId: "metadata.
|
|
36
|
+
* parameterMapping: { nodeTypeId: "metadata.node_type_id" }
|
|
37
37
|
* };
|
|
38
38
|
*
|
|
39
39
|
* const result = await fetchDynamicSchema(endpoint, node);
|
|
@@ -56,7 +56,7 @@ export declare function fetchDynamicSchema(endpointConfig: EndpointConfig | null
|
|
|
56
56
|
* ```typescript
|
|
57
57
|
* const link: ExternalEditLink = {
|
|
58
58
|
* url: "https://admin.example.com/nodes/{nodeTypeId}/edit/{instanceId}",
|
|
59
|
-
* parameterMapping: { nodeTypeId: "metadata.
|
|
59
|
+
* parameterMapping: { nodeTypeId: "metadata.node_type_id", instanceId: "id" }
|
|
60
60
|
* };
|
|
61
61
|
*
|
|
62
62
|
* const url = resolveExternalEditUrl(link, node, workflowId);
|
|
@@ -15,16 +15,16 @@ const schemaCache = new Map();
|
|
|
15
15
|
const DEFAULT_CACHE_TTL = DEFAULT_CACHE_TTL_MS;
|
|
16
16
|
/**
|
|
17
17
|
* Resolves a template variable path from the node context.
|
|
18
|
-
* Supports dot-notation paths like "metadata.
|
|
18
|
+
* Supports dot-notation paths like "metadata.node_type_id", "config.apiKey", "id"
|
|
19
19
|
*
|
|
20
20
|
* @param context - The node context containing all available data
|
|
21
|
-
* @param path - Dot-notation path to resolve (e.g., "metadata.
|
|
21
|
+
* @param path - Dot-notation path to resolve (e.g., "metadata.node_type_id")
|
|
22
22
|
* @returns The resolved value as a string, or undefined if not found
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```typescript
|
|
26
|
-
* const context = { id: "node-1", metadata: {
|
|
27
|
-
* resolveVariablePath(context, "metadata.
|
|
26
|
+
* const context = { id: "node-1", metadata: { node_type_id: "llm-node" } };
|
|
27
|
+
* resolveVariablePath(context, "metadata.node_type_id"); // Returns "llm-node"
|
|
28
28
|
* resolveVariablePath(context, "id"); // Returns "node-1"
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
@@ -60,8 +60,8 @@ function resolveVariablePath(context, path) {
|
|
|
60
60
|
* @example
|
|
61
61
|
* ```typescript
|
|
62
62
|
* const url = "/api/nodes/{nodeTypeId}/schema?instance={instanceId}";
|
|
63
|
-
* const mapping = { nodeTypeId: "metadata.
|
|
64
|
-
* const context = { id: "node-1", metadata: {
|
|
63
|
+
* const mapping = { nodeTypeId: "metadata.node_type_id", instanceId: "id" };
|
|
64
|
+
* const context = { id: "node-1", metadata: { node_type_id: "llm-node" } };
|
|
65
65
|
* resolveTemplate(url, mapping, context);
|
|
66
66
|
* // Returns "/api/nodes/llm-node/schema?instance=node-1"
|
|
67
67
|
* ```
|
|
@@ -127,7 +127,7 @@ function isCacheValid(entry, ttl = DEFAULT_CACHE_TTL) {
|
|
|
127
127
|
* const endpoint: DynamicSchemaEndpoint = {
|
|
128
128
|
* url: "/api/nodes/{nodeTypeId}/schema",
|
|
129
129
|
* method: "GET",
|
|
130
|
-
* parameterMapping: { nodeTypeId: "metadata.
|
|
130
|
+
* parameterMapping: { nodeTypeId: "metadata.node_type_id" }
|
|
131
131
|
* };
|
|
132
132
|
*
|
|
133
133
|
* const result = await fetchDynamicSchema(endpoint, node);
|
|
@@ -279,7 +279,7 @@ export async function fetchDynamicSchema(endpointConfig, endpoint, node, workflo
|
|
|
279
279
|
* ```typescript
|
|
280
280
|
* const link: ExternalEditLink = {
|
|
281
281
|
* url: "https://admin.example.com/nodes/{nodeTypeId}/edit/{instanceId}",
|
|
282
|
-
* parameterMapping: { nodeTypeId: "metadata.
|
|
282
|
+
* parameterMapping: { nodeTypeId: "metadata.node_type_id", instanceId: "id" }
|
|
283
283
|
* };
|
|
284
284
|
*
|
|
285
285
|
* const url = resolveExternalEditUrl(link, node, workflowId);
|
package/dist/skins/drafter.js
CHANGED
|
@@ -28,12 +28,16 @@
|
|
|
28
28
|
*/
|
|
29
29
|
export const drafterSkin = {
|
|
30
30
|
tokens: {
|
|
31
|
-
/* ----- Shell surfaces: fresh white
|
|
31
|
+
/* ----- Shell surfaces: fresh white shell + pale mint chrome ----- */
|
|
32
|
+
/* Neutral greys read as cold admin chrome and fight the mint canvas, so the
|
|
33
|
+
quiet surfaces carry a faint aqua-mint tint instead. muted-foreground is
|
|
34
|
+
a darker teal-slate (≈6.5:1 on white) so secondary/helper text clears
|
|
35
|
+
WCAG AA comfortably — grey body text was the accessibility problem. */
|
|
32
36
|
background: '#ffffff',
|
|
33
37
|
foreground: '#10201c',
|
|
34
|
-
muted: '#
|
|
35
|
-
'muted-foreground': '#
|
|
36
|
-
subtle: '#
|
|
38
|
+
muted: '#eaf5f0',
|
|
39
|
+
'muted-foreground': '#46635b',
|
|
40
|
+
subtle: '#e1f0ea',
|
|
37
41
|
card: '#ffffff',
|
|
38
42
|
'card-foreground': '#10201c',
|
|
39
43
|
header: '#ffffff',
|
|
@@ -44,9 +48,9 @@ export const drafterSkin = {
|
|
|
44
48
|
'panel-bg': 'rgba(255, 255, 255, 0.94)',
|
|
45
49
|
'panel-backdrop-filter': 'blur(10px) saturate(1.04)',
|
|
46
50
|
backdrop: 'rgba(255, 255, 255, 0.92)',
|
|
47
|
-
/* ----- Borders:
|
|
48
|
-
border: '#
|
|
49
|
-
'border-muted': '#
|
|
51
|
+
/* ----- Borders: soft mint hairlines; strong/focus = teal-cyan accent ----- */
|
|
52
|
+
border: '#d3e6df',
|
|
53
|
+
'border-muted': '#e4f0eb',
|
|
50
54
|
'border-strong': 'rgba(15, 118, 110, 0.42)',
|
|
51
55
|
ring: '#06b6d4',
|
|
52
56
|
/* ----- Canvas: fresh aqua-mint, soft cyan/teal square grid ----- */
|
|
@@ -68,7 +72,6 @@ export const drafterSkin = {
|
|
|
68
72
|
/* Notes read as cool annotations, not filled success cards */
|
|
69
73
|
'note-border': '#5b7891',
|
|
70
74
|
'note-border-hover': '#48617a',
|
|
71
|
-
/* Translucent status tints so note/instruction cards stay light + glassy */
|
|
72
75
|
/* Status hues tuned to the cool palette: danger = rose (teal's warm
|
|
73
76
|
complement, not a generic red), warning = golden amber. Success/info stay
|
|
74
77
|
on the emerald/cyan family so they read as part of the theme. */
|
|
@@ -80,15 +83,23 @@ export const drafterSkin = {
|
|
|
80
83
|
'warning-hover': '#b45309',
|
|
81
84
|
error: '#e11d48',
|
|
82
85
|
'error-hover': '#be123c',
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
/* Status/accent tints are FLAT + OPAQUE (not alpha) so the action buttons
|
|
87
|
+
that use them as fills (form add/move/delete, canvas toggles, secondary)
|
|
88
|
+
read as solid chips, never see-through to the grid. Values are the opaque
|
|
89
|
+
equivalent of the former translucent tints over the white shell. */
|
|
90
|
+
'info-muted': '#e6f4f7',
|
|
91
|
+
'success-muted': '#e7f4f3',
|
|
92
|
+
'warning-muted': '#faefe1',
|
|
93
|
+
'error-muted': '#fce8ed',
|
|
87
94
|
/* ----- Crisp drafting geometry + flat chrome (2–6px radius, no soft shadow) ----- */
|
|
88
95
|
'radius-sm': '2px',
|
|
89
96
|
'radius-md': '3px',
|
|
90
97
|
'radius-lg': '4px',
|
|
91
98
|
'radius-xl': '6px',
|
|
99
|
+
/* Form controls + their group containers (fields, array item boxes,
|
|
100
|
+
fieldsets) get the sharpest 2px corner so the config panel reads as
|
|
101
|
+
crisp drafting geometry, not rounded admin chrome. */
|
|
102
|
+
'control-radius': '2px',
|
|
92
103
|
'scrollbar-radius': '0',
|
|
93
104
|
'shadow-sm': 'none',
|
|
94
105
|
'shadow-md': 'none',
|
|
@@ -98,23 +109,23 @@ export const drafterSkin = {
|
|
|
98
109
|
'minimap-mask-stroke': 'rgba(15, 118, 110, 0.35)',
|
|
99
110
|
'minimap-node-bg': 'rgba(15, 118, 110, 0.3)',
|
|
100
111
|
'minimap-node-stroke': 'rgba(15, 118, 110, 0.45)',
|
|
101
|
-
'controls-button-bg': '
|
|
102
|
-
'controls-button-bg-hover': '
|
|
112
|
+
'controls-button-bg': '#ffffff',
|
|
113
|
+
'controls-button-bg-hover': '#ccfbf1',
|
|
103
114
|
'controls-button-color': '#0f766e',
|
|
104
115
|
'controls-button-color-hover': '#0c5f59',
|
|
105
116
|
'controls-button-border': 'rgba(15, 118, 110, 0.25)',
|
|
106
117
|
/* ----- Secondary = mint, accent = cyan, primary = the one allowed green ----- */
|
|
107
|
-
secondary: '
|
|
108
|
-
'secondary-hover': '
|
|
118
|
+
secondary: '#e4f1ed',
|
|
119
|
+
'secondary-hover': '#cfe6e0',
|
|
109
120
|
'secondary-foreground': '#0f3d36',
|
|
110
121
|
accent: '#06b6d4',
|
|
111
122
|
'accent-hover': '#0891b2',
|
|
112
123
|
'accent-foreground': '#ffffff',
|
|
113
|
-
'accent-muted': '
|
|
124
|
+
'accent-muted': '#e1f6fa',
|
|
114
125
|
primary: '#10b981',
|
|
115
126
|
'primary-hover': '#059669',
|
|
116
127
|
'primary-foreground': '#ffffff',
|
|
117
|
-
'primary-muted': '
|
|
128
|
+
'primary-muted': '#def5ed'
|
|
118
129
|
},
|
|
119
130
|
darkTokens: {
|
|
120
131
|
/* ----- Shell surfaces: deep teal-slate glass ----- */
|
|
@@ -156,30 +167,32 @@ export const drafterSkin = {
|
|
|
156
167
|
'warning-hover': '#fcd34d',
|
|
157
168
|
error: '#fb7185',
|
|
158
169
|
'error-hover': '#fda4af',
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
'
|
|
162
|
-
'
|
|
170
|
+
/* Flat + opaque tints (opaque equivalent of the former alpha tints over the
|
|
171
|
+
deep teal-slate shell) so button fills never go see-through. */
|
|
172
|
+
'info-muted': '#10393a',
|
|
173
|
+
'success-muted': '#123934',
|
|
174
|
+
'warning-muted': '#2f3a21',
|
|
175
|
+
'error-muted': '#2a2d2d',
|
|
163
176
|
'minimap-bg': 'rgba(11, 31, 28, 0.7)',
|
|
164
177
|
'minimap-mask-bg': 'rgba(45, 212, 191, 0.06)',
|
|
165
178
|
'minimap-mask-stroke': 'rgba(45, 212, 191, 0.3)',
|
|
166
179
|
'minimap-node-bg': 'rgba(45, 212, 191, 0.28)',
|
|
167
180
|
'minimap-node-stroke': 'rgba(45, 212, 191, 0.45)',
|
|
168
|
-
'controls-button-bg': '
|
|
169
|
-
'controls-button-bg-hover': '
|
|
181
|
+
'controls-button-bg': '#102522',
|
|
182
|
+
'controls-button-bg-hover': '#0d2d2a',
|
|
170
183
|
'controls-button-color': '#2dd4bf',
|
|
171
184
|
'controls-button-color-hover': '#5eead4',
|
|
172
185
|
'controls-button-border': 'rgba(45, 212, 191, 0.3)',
|
|
173
|
-
secondary: '
|
|
174
|
-
'secondary-hover': '
|
|
186
|
+
secondary: '#0d2d2a',
|
|
187
|
+
'secondary-hover': '#133a34',
|
|
175
188
|
'secondary-foreground': '#d8f0ea',
|
|
176
189
|
accent: '#22d3ee',
|
|
177
190
|
'accent-hover': '#67e8f9',
|
|
178
191
|
'accent-foreground': '#03291c',
|
|
179
|
-
'accent-muted': '
|
|
192
|
+
'accent-muted': '#113d3e',
|
|
180
193
|
primary: '#34d399',
|
|
181
194
|
'primary-hover': '#6ee7b7',
|
|
182
195
|
'primary-foreground': '#03291c',
|
|
183
|
-
'primary-muted': '
|
|
196
|
+
'primary-muted': '#144034'
|
|
184
197
|
}
|
|
185
198
|
};
|
|
@@ -212,7 +212,7 @@ export class PlaygroundStore {
|
|
|
212
212
|
// Find input nodes in the workflow
|
|
213
213
|
workflow.nodes.forEach((node) => {
|
|
214
214
|
const category = node.data.metadata?.category;
|
|
215
|
-
const nodeTypeId = node.data.metadata?.
|
|
215
|
+
const nodeTypeId = node.data.metadata?.node_type_id ?? node.type;
|
|
216
216
|
// Check if this is an input-type node
|
|
217
217
|
// The category can be "inputs" (standard) or variations like "input"
|
|
218
218
|
const categoryStr = String(category || '');
|
|
@@ -94,23 +94,6 @@ function hasWorkflowDataChanged(currentWorkflow, newNodes, newEdges) {
|
|
|
94
94
|
}
|
|
95
95
|
return false;
|
|
96
96
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Heal nodes that are missing `data.nodeId`.
|
|
99
|
-
*
|
|
100
|
-
* Node components derive their handle IDs from `data.nodeId` — a node without
|
|
101
|
-
* it renders with zero handles and SvelteFlow silently drops every edge
|
|
102
|
-
* anchored to it, making an intact graph look corrupted on the canvas.
|
|
103
|
-
* `data.nodeId` always equals the node's own `id`, so it is safe to restore.
|
|
104
|
-
*/
|
|
105
|
-
function healMissingNodeIds(workflow) {
|
|
106
|
-
if (!workflow.nodes?.some((node) => !node.data.nodeId)) {
|
|
107
|
-
return workflow;
|
|
108
|
-
}
|
|
109
|
-
return {
|
|
110
|
-
...workflow,
|
|
111
|
-
nodes: workflow.nodes.map((node) => node.data.nodeId ? node : { ...node, data: { ...node.data, nodeId: node.id } })
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
97
|
// =========================================================================
|
|
115
98
|
// WorkflowStore (per-instance reactive state)
|
|
116
99
|
// =========================================================================
|
|
@@ -373,7 +356,6 @@ export class WorkflowStore {
|
|
|
373
356
|
*/
|
|
374
357
|
initialize(workflow) {
|
|
375
358
|
workflow = normalizeWorkflowMetadata(workflow);
|
|
376
|
-
workflow = healMissingNodeIds(workflow);
|
|
377
359
|
this.#workflow = workflow;
|
|
378
360
|
// Reset version counters — workflow is "clean" after initialization
|
|
379
361
|
this.#editVersion = 0;
|
package/dist/styles/base.css
CHANGED
|
@@ -149,6 +149,7 @@ p {
|
|
|
149
149
|
display: inline-flex;
|
|
150
150
|
align-items: center;
|
|
151
151
|
justify-content: center;
|
|
152
|
+
gap: var(--fd-space-xs);
|
|
152
153
|
padding: var(--fd-space-xs) var(--fd-space-xl);
|
|
153
154
|
border: 1px solid transparent;
|
|
154
155
|
border-radius: var(--fd-radius-md);
|
|
@@ -224,37 +225,278 @@ p {
|
|
|
224
225
|
min-height: var(--fd-space-6xl);
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
/*
|
|
228
|
+
/* ───────────────────────────────────────────────────────────────────────────
|
|
229
|
+
Icon buttons — square, icon-only. The typed primitive IconButton.svelte
|
|
230
|
+
routes here (the same way Button.svelte routes through .flowdrop-btn). It
|
|
231
|
+
composes onto .flowdrop-btn, then overrides geometry to a fixed square and
|
|
232
|
+
layers a tint variant. Corners follow --fd-control-radius so the Drafter
|
|
233
|
+
theme gets crisp icon buttons alongside its form controls.
|
|
234
|
+
|
|
235
|
+
Sizes: md (default) is 32px with a 16px glyph — the dominant size across the
|
|
236
|
+
library (form-array actions, modal closes, toolbars). sm maps to the
|
|
237
|
+
canonical --fd-size-icon-btn token (28px); lg is 36px (canvas-scale). */
|
|
238
|
+
.flowdrop-btn--icon {
|
|
239
|
+
width: 2rem;
|
|
240
|
+
height: 2rem;
|
|
241
|
+
min-height: 0;
|
|
242
|
+
padding: 0;
|
|
243
|
+
border-radius: var(--fd-control-radius);
|
|
244
|
+
color: var(--fd-muted-foreground);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.flowdrop-btn--icon svg {
|
|
248
|
+
width: 1rem;
|
|
249
|
+
height: 1rem;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.flowdrop-btn--icon.flowdrop-btn--sm {
|
|
253
|
+
width: var(--fd-size-icon-btn);
|
|
254
|
+
height: var(--fd-size-icon-btn);
|
|
255
|
+
padding: 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.flowdrop-btn--icon.flowdrop-btn--sm svg {
|
|
259
|
+
width: 0.875rem;
|
|
260
|
+
height: 0.875rem;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.flowdrop-btn--icon.flowdrop-btn--lg {
|
|
264
|
+
width: 2.25rem;
|
|
265
|
+
height: 2.25rem;
|
|
266
|
+
padding: 0;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.flowdrop-btn--icon.flowdrop-btn--lg svg {
|
|
270
|
+
width: 1.125rem;
|
|
271
|
+
height: 1.125rem;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Ghost (default for icon buttons) — transparent until hover. */
|
|
275
|
+
.flowdrop-btn--icon.flowdrop-btn--ghost:hover:not(:disabled) {
|
|
276
|
+
background-color: var(--fd-muted);
|
|
277
|
+
color: var(--fd-foreground);
|
|
278
|
+
border-color: transparent;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* Default — flat --fd-background surface with a resting border. */
|
|
282
|
+
.flowdrop-btn--icon-default {
|
|
283
|
+
background-color: var(--fd-background);
|
|
284
|
+
border-color: var(--fd-border);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.flowdrop-btn--icon-default:hover:not(:disabled) {
|
|
288
|
+
background-color: var(--fd-muted);
|
|
289
|
+
color: var(--fd-foreground);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Tinted semantic variants — muted fill + semantic border/text, solid on press.
|
|
293
|
+
Unlike the solid text-button --primary, the icon flavour stays a quiet tint
|
|
294
|
+
so a row of action buttons reads as a group, not a wall of colour. */
|
|
295
|
+
.flowdrop-btn--icon-primary {
|
|
296
|
+
background-color: var(--fd-primary-muted);
|
|
297
|
+
border-color: var(--fd-primary);
|
|
298
|
+
color: var(--fd-primary-hover);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.flowdrop-btn--icon-primary:hover:not(:disabled) {
|
|
302
|
+
border-color: var(--fd-primary-hover);
|
|
303
|
+
color: var(--fd-primary-hover);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.flowdrop-btn--icon-primary:active:not(:disabled) {
|
|
307
|
+
background-color: var(--fd-primary);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.flowdrop-btn--icon-danger {
|
|
311
|
+
background-color: var(--fd-error-muted);
|
|
312
|
+
border-color: var(--fd-error);
|
|
313
|
+
color: var(--fd-error);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.flowdrop-btn--icon-danger:hover:not(:disabled) {
|
|
317
|
+
border-color: var(--fd-error-hover);
|
|
318
|
+
color: var(--fd-error-hover);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.flowdrop-btn--icon-danger:active:not(:disabled) {
|
|
322
|
+
background-color: var(--fd-error);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.flowdrop-btn--icon-success {
|
|
326
|
+
background-color: var(--fd-success-muted);
|
|
327
|
+
border-color: var(--fd-success);
|
|
328
|
+
color: var(--fd-success);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.flowdrop-btn--icon-success:hover:not(:disabled) {
|
|
332
|
+
border-color: var(--fd-success-hover);
|
|
333
|
+
color: var(--fd-success-hover);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.flowdrop-btn--icon-success:active:not(:disabled) {
|
|
337
|
+
background-color: var(--fd-success);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Active / toggled state (e.g. a pressed canvas control) — primary tint. */
|
|
341
|
+
.flowdrop-btn--icon.is-active {
|
|
342
|
+
color: var(--fd-primary);
|
|
343
|
+
background-color: var(--fd-primary-muted);
|
|
344
|
+
border-color: var(--fd-primary);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.flowdrop-btn--icon:disabled {
|
|
348
|
+
opacity: 0.35;
|
|
349
|
+
cursor: not-allowed;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* ───────────────────────────────────────────────────────────────────────────
|
|
353
|
+
Form controls — THE single source of truth for input/select/textarea look.
|
|
354
|
+
|
|
355
|
+
The typed primitives Input.svelte / Select.svelte / Textarea.svelte route
|
|
356
|
+
here (the same way Button.svelte routes through .flowdrop-btn) so every field
|
|
357
|
+
across the library — config form, sidebar search, playground, prompts —
|
|
358
|
+
renders identically. Resting fields are ALWAYS the flat --fd-background
|
|
359
|
+
surface; `:disabled` is the ONLY muted state. Components must not re-declare
|
|
360
|
+
control backgrounds/borders locally. */
|
|
228
361
|
.flowdrop-input {
|
|
229
362
|
display: block;
|
|
230
363
|
width: 100%;
|
|
231
|
-
padding:
|
|
364
|
+
padding: 0.625rem 0.875rem;
|
|
232
365
|
border: 1px solid var(--fd-border);
|
|
233
|
-
border-radius: var(--fd-radius
|
|
366
|
+
border-radius: var(--fd-control-radius);
|
|
234
367
|
font-size: var(--fd-text-sm);
|
|
368
|
+
font-family: inherit;
|
|
235
369
|
line-height: 1.25rem;
|
|
236
370
|
color: var(--fd-foreground);
|
|
237
371
|
background-color: var(--fd-background);
|
|
372
|
+
box-shadow: var(--fd-shadow-sm);
|
|
238
373
|
transition:
|
|
239
374
|
border-color var(--fd-transition-normal),
|
|
240
375
|
box-shadow var(--fd-transition-normal);
|
|
241
376
|
}
|
|
242
377
|
|
|
378
|
+
.flowdrop-input::placeholder {
|
|
379
|
+
color: var(--fd-muted-foreground);
|
|
380
|
+
}
|
|
381
|
+
|
|
243
382
|
/* Active-field hint only; the focus ring itself is centralized (top of file). */
|
|
383
|
+
.flowdrop-input:hover:not(:disabled):not(:focus) {
|
|
384
|
+
border-color: var(--fd-border-strong);
|
|
385
|
+
}
|
|
386
|
+
|
|
244
387
|
.flowdrop-input:focus {
|
|
245
388
|
border-color: var(--fd-ring);
|
|
246
389
|
}
|
|
247
390
|
|
|
391
|
+
.flowdrop-input:disabled {
|
|
392
|
+
background-color: var(--fd-muted);
|
|
393
|
+
border-color: var(--fd-border-muted);
|
|
394
|
+
color: var(--fd-muted-foreground);
|
|
395
|
+
cursor: not-allowed;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* Invalid keeps its error border even on hover. */
|
|
399
|
+
.flowdrop-input--invalid,
|
|
400
|
+
.flowdrop-input--invalid:hover:not(:disabled) {
|
|
401
|
+
border-color: var(--fd-error);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* Sizes */
|
|
248
405
|
.flowdrop-input--sm {
|
|
249
|
-
padding:
|
|
406
|
+
padding: 0.375rem 0.625rem;
|
|
250
407
|
font-size: var(--fd-text-xs);
|
|
251
408
|
}
|
|
252
409
|
|
|
253
410
|
.flowdrop-input--lg {
|
|
254
|
-
padding:
|
|
411
|
+
padding: 0.75rem 1rem;
|
|
255
412
|
font-size: var(--fd-text-base);
|
|
256
413
|
}
|
|
257
414
|
|
|
415
|
+
/* Tabular figures for numeric entry (aligned digits). */
|
|
416
|
+
.flowdrop-input--numeric {
|
|
417
|
+
font-variant-numeric: tabular-nums;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Multiline */
|
|
421
|
+
.flowdrop-input--textarea {
|
|
422
|
+
min-height: 5rem;
|
|
423
|
+
line-height: 1.5;
|
|
424
|
+
resize: vertical;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Select: room for the chevron overlay; native arrow removed. */
|
|
428
|
+
.flowdrop-input--select {
|
|
429
|
+
padding-right: 2.5rem;
|
|
430
|
+
cursor: pointer;
|
|
431
|
+
appearance: none;
|
|
432
|
+
-webkit-appearance: none;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* Select shell carries the chevron; the <select> keeps the field look. */
|
|
436
|
+
.flowdrop-select-wrap {
|
|
437
|
+
position: relative;
|
|
438
|
+
width: 100%;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.flowdrop-select-wrap__icon {
|
|
442
|
+
position: absolute;
|
|
443
|
+
right: 0.75rem;
|
|
444
|
+
top: 50%;
|
|
445
|
+
transform: translateY(-50%);
|
|
446
|
+
display: flex;
|
|
447
|
+
pointer-events: none;
|
|
448
|
+
color: var(--fd-muted-foreground);
|
|
449
|
+
transition: color var(--fd-transition-fast);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.flowdrop-select-wrap:focus-within .flowdrop-select-wrap__icon {
|
|
453
|
+
color: var(--fd-primary);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.flowdrop-select-wrap__icon svg {
|
|
457
|
+
width: 1rem;
|
|
458
|
+
height: 1rem;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/* Input with a leading/trailing affordance (e.g. a search magnifier). */
|
|
462
|
+
.flowdrop-input-wrap {
|
|
463
|
+
position: relative;
|
|
464
|
+
width: 100%;
|
|
465
|
+
display: flex;
|
|
466
|
+
align-items: center;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.flowdrop-input-wrap__icon {
|
|
470
|
+
position: absolute;
|
|
471
|
+
top: 50%;
|
|
472
|
+
transform: translateY(-50%);
|
|
473
|
+
display: flex;
|
|
474
|
+
align-items: center;
|
|
475
|
+
pointer-events: none;
|
|
476
|
+
color: var(--fd-muted-foreground);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.flowdrop-input-wrap__icon--leading {
|
|
480
|
+
left: 0.75rem;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.flowdrop-input-wrap__icon--trailing {
|
|
484
|
+
right: 0.75rem;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.flowdrop-input-wrap__icon svg {
|
|
488
|
+
width: 1rem;
|
|
489
|
+
height: 1rem;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.flowdrop-input--has-leading {
|
|
493
|
+
padding-left: 2.25rem;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.flowdrop-input--has-trailing {
|
|
497
|
+
padding-right: 2.25rem;
|
|
498
|
+
}
|
|
499
|
+
|
|
258
500
|
/* Card styles */
|
|
259
501
|
.flowdrop-card {
|
|
260
502
|
background-color: var(--fd-card);
|
package/dist/styles/tokens.css
CHANGED
|
@@ -253,6 +253,12 @@
|
|
|
253
253
|
--fd-radius-2xl: 1rem; /* @public 16px */
|
|
254
254
|
--fd-radius-full: 9999px; /* @public */
|
|
255
255
|
|
|
256
|
+
/* Corner radius shared by form controls (input/select/textarea) and their
|
|
257
|
+
group containers (array item boxes, fieldsets, checkbox groups, config
|
|
258
|
+
sections). Defaults to --fd-radius-lg; themes can tighten it independently
|
|
259
|
+
of cards/panels — e.g. Drafter sets 2px for crisp drafting corners. */
|
|
260
|
+
--fd-control-radius: var(--fd-radius-lg); /* @public */
|
|
261
|
+
|
|
256
262
|
/* ----- SHADOWS (Refined layered shadows for modern depth) ----- */
|
|
257
263
|
--fd-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.04), 0 1px 3px rgb(0 0 0 / 0.06); /* @public */
|
|
258
264
|
--fd-shadow-md: 0 4px 8px rgb(0 0 0 / 0.06), 0 2px 4px rgb(0 0 0 / 0.04); /* @public */
|