@flowdrop/flowdrop 2.0.0-beta.3 → 2.0.0-beta.4
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 +25 -0
- package/README.md +5 -5
- package/dist/components/App.svelte +15 -146
- 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 +13 -111
- package/dist/components/NodeSwapPicker.svelte +10 -26
- 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/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/playground/InputCollector.svelte +11 -46
- 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/skins/drafter.js +41 -28
- package/dist/styles/base.css +247 -5
- package/dist/styles/tokens.css +6 -0
- package/dist/svelte-app.js +68 -107
- package/dist/utils/connections.js +14 -50
- package/package.json +1 -1
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
|
};
|
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 */
|
package/dist/svelte-app.js
CHANGED
|
@@ -55,6 +55,58 @@ function releaseInstance(fd, isDefault) {
|
|
|
55
55
|
fd.destroy();
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve endpoint config, port config and categories from mount options and
|
|
60
|
+
* apply them to the given instance (API context, port-compatibility checker,
|
|
61
|
+
* categories). Shared by `mountFlowDropApp` and `mountWorkflowEditor`.
|
|
62
|
+
*
|
|
63
|
+
* @returns the resolved {@link EndpointConfig} (merged with defaults), which the
|
|
64
|
+
* callers forward to their mounted component.
|
|
65
|
+
*/
|
|
66
|
+
async function configureInstance(fd, options) {
|
|
67
|
+
const { endpointConfig, portConfig, categories, authProvider } = options;
|
|
68
|
+
// Create endpoint configuration, merging with defaults so all required
|
|
69
|
+
// endpoints are present.
|
|
70
|
+
const { defaultEndpointConfig } = await import('./config/endpoints.js');
|
|
71
|
+
const config = endpointConfig
|
|
72
|
+
? {
|
|
73
|
+
...defaultEndpointConfig,
|
|
74
|
+
...endpointConfig,
|
|
75
|
+
endpoints: {
|
|
76
|
+
...defaultEndpointConfig.endpoints,
|
|
77
|
+
...endpointConfig.endpoints
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
: defaultEndpointConfig;
|
|
81
|
+
// Initialize port configuration (fetch from API when not supplied).
|
|
82
|
+
let finalPortConfig = portConfig;
|
|
83
|
+
if (!finalPortConfig) {
|
|
84
|
+
try {
|
|
85
|
+
finalPortConfig = await fetchPortConfig(config, authProvider);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
logger.warn('Failed to fetch port config from API, using default:', error);
|
|
89
|
+
finalPortConfig = DEFAULT_PORT_CONFIG;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Configure this instance's API context and port compatibility checker.
|
|
93
|
+
fd.api.configure(config, authProvider);
|
|
94
|
+
fd.portCompatibility.reinitialize(finalPortConfig);
|
|
95
|
+
// Initialize this instance's categories (fetch from API when not supplied).
|
|
96
|
+
if (categories) {
|
|
97
|
+
fd.categories.initialize(categories);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
try {
|
|
101
|
+
const fetchedCategories = await fetchCategories(config, authProvider);
|
|
102
|
+
fd.categories.initialize(fetchedCategories);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
logger.warn('Failed to fetch categories from API, using defaults:', error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return config;
|
|
109
|
+
}
|
|
58
110
|
/**
|
|
59
111
|
* Mount the full FlowDrop App with navbar, sidebars, and workflow editor
|
|
60
112
|
*
|
|
@@ -103,61 +155,14 @@ export async function mountFlowDropApp(container, options = {}) {
|
|
|
103
155
|
await initializeSettings({
|
|
104
156
|
defaults: initialSettings
|
|
105
157
|
});
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
endpoints: {
|
|
115
|
-
...defaultEndpointConfig.endpoints,
|
|
116
|
-
...endpointConfig.endpoints
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// Use default configuration if none provided
|
|
122
|
-
const { defaultEndpointConfig } = await import('./config/endpoints.js');
|
|
123
|
-
config = defaultEndpointConfig;
|
|
124
|
-
}
|
|
125
|
-
// Initialize port configuration
|
|
126
|
-
let finalPortConfig = portConfig;
|
|
127
|
-
if (!finalPortConfig && config) {
|
|
128
|
-
// Try to fetch port configuration from API
|
|
129
|
-
try {
|
|
130
|
-
finalPortConfig = await fetchPortConfig(config, authProvider);
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
logger.warn('Failed to fetch port config from API, using default:', error);
|
|
134
|
-
finalPortConfig = DEFAULT_PORT_CONFIG;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
else if (!finalPortConfig) {
|
|
138
|
-
finalPortConfig = DEFAULT_PORT_CONFIG;
|
|
139
|
-
}
|
|
140
|
-
// Configure this instance's API context (endpoints + auth provider) so
|
|
141
|
-
// <App> and services resolve it via getInstance().api.
|
|
142
|
-
if (config) {
|
|
143
|
-
fd.api.configure(config, authProvider);
|
|
144
|
-
}
|
|
145
|
-
// Re-initialize this instance's port compatibility checker with the resolved
|
|
146
|
-
// config (it was seeded with DEFAULT_PORT_CONFIG at construction).
|
|
147
|
-
fd.portCompatibility.reinitialize(finalPortConfig);
|
|
148
|
-
// Initialize this instance's categories
|
|
149
|
-
if (categories) {
|
|
150
|
-
fd.categories.initialize(categories);
|
|
151
|
-
}
|
|
152
|
-
else if (config) {
|
|
153
|
-
try {
|
|
154
|
-
const fetchedCategories = await fetchCategories(config, authProvider);
|
|
155
|
-
fd.categories.initialize(fetchedCategories);
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
logger.warn('Failed to fetch categories from API, using defaults:', error);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
158
|
+
// Resolve and apply endpoint config, port config and categories to this
|
|
159
|
+
// instance (see configureInstance).
|
|
160
|
+
const config = await configureInstance(fd, {
|
|
161
|
+
endpointConfig,
|
|
162
|
+
portConfig,
|
|
163
|
+
categories,
|
|
164
|
+
authProvider
|
|
165
|
+
});
|
|
161
166
|
// Set up event handler callbacks in this instance's store
|
|
162
167
|
if (eventHandlers?.onDirtyStateChange) {
|
|
163
168
|
fd.workflow.setOnDirtyStateChange(eventHandlers.onDirtyStateChange);
|
|
@@ -338,58 +343,14 @@ export async function mountWorkflowEditor(container, options = {}) {
|
|
|
338
343
|
const { workflow, endpointConfig, portConfig, categories, authProvider, instanceId, builtinEditors } = options;
|
|
339
344
|
// Per-instance state container (see mountFlowDropApp)
|
|
340
345
|
const { fd, isDefault } = acquireInstance(instanceId);
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
endpoints: {
|
|
350
|
-
...defaultEndpointConfig.endpoints,
|
|
351
|
-
...endpointConfig.endpoints
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
else {
|
|
356
|
-
// Use default configuration if none provided
|
|
357
|
-
const { defaultEndpointConfig } = await import('./config/endpoints.js');
|
|
358
|
-
config = defaultEndpointConfig;
|
|
359
|
-
}
|
|
360
|
-
// Initialize port configuration
|
|
361
|
-
let finalPortConfig = portConfig;
|
|
362
|
-
if (!finalPortConfig && config) {
|
|
363
|
-
// Try to fetch port configuration from API
|
|
364
|
-
try {
|
|
365
|
-
finalPortConfig = await fetchPortConfig(config, authProvider);
|
|
366
|
-
}
|
|
367
|
-
catch (error) {
|
|
368
|
-
logger.warn('Failed to fetch port config from API, using default:', error);
|
|
369
|
-
finalPortConfig = DEFAULT_PORT_CONFIG;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
else if (!finalPortConfig) {
|
|
373
|
-
finalPortConfig = DEFAULT_PORT_CONFIG;
|
|
374
|
-
}
|
|
375
|
-
// Configure this instance's API context and port compatibility checker.
|
|
376
|
-
if (config) {
|
|
377
|
-
fd.api.configure(config, authProvider);
|
|
378
|
-
}
|
|
379
|
-
fd.portCompatibility.reinitialize(finalPortConfig);
|
|
380
|
-
// Initialize this instance's categories
|
|
381
|
-
if (categories) {
|
|
382
|
-
fd.categories.initialize(categories);
|
|
383
|
-
}
|
|
384
|
-
else if (config) {
|
|
385
|
-
try {
|
|
386
|
-
const fetchedCategories = await fetchCategories(config, authProvider);
|
|
387
|
-
fd.categories.initialize(fetchedCategories);
|
|
388
|
-
}
|
|
389
|
-
catch (error) {
|
|
390
|
-
logger.warn('Failed to fetch categories from API, using defaults:', error);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
346
|
+
// Resolve and apply endpoint config, port config and categories to this
|
|
347
|
+
// instance (see configureInstance).
|
|
348
|
+
const config = await configureInstance(fd, {
|
|
349
|
+
endpointConfig,
|
|
350
|
+
portConfig,
|
|
351
|
+
categories,
|
|
352
|
+
authProvider
|
|
353
|
+
});
|
|
393
354
|
// Seed the instance's workflow before mounting so the editor renders it
|
|
394
355
|
// immediately. (1.x accepted this option but silently ignored it.)
|
|
395
356
|
if (workflow) {
|