@d34dman/flowdrop 0.0.21 → 0.0.22
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 +48 -240
- package/dist/components/ConfigForm.svelte +707 -238
- package/dist/components/ConfigForm.svelte.d.ts +9 -2
- package/dist/components/ConfigPanel.svelte +160 -0
- package/dist/components/ConfigPanel.svelte.d.ts +32 -0
- package/dist/components/ReadOnlyDetails.svelte +168 -0
- package/dist/components/ReadOnlyDetails.svelte.d.ts +25 -0
- package/dist/components/WorkflowEditor.svelte +1 -1
- package/dist/components/nodes/NotesNode.svelte +89 -307
- package/dist/components/nodes/NotesNode.svelte.d.ts +3 -22
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +1 -1
- package/dist/components/ConfigSidebar.svelte +0 -916
- package/dist/components/ConfigSidebar.svelte.d.ts +0 -51
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type { WorkflowNode } from '../types/index.js';
|
|
1
|
+
import type { ConfigSchema, WorkflowNode } from '../types/index.js';
|
|
2
2
|
interface Props {
|
|
3
|
-
node
|
|
3
|
+
/** Optional workflow node (if provided, schema and values are derived from it) */
|
|
4
|
+
node?: WorkflowNode;
|
|
5
|
+
/** Direct config schema (used when node is not provided) */
|
|
6
|
+
schema?: ConfigSchema;
|
|
7
|
+
/** Direct config values (used when node is not provided) */
|
|
8
|
+
values?: Record<string, unknown>;
|
|
9
|
+
/** Callback when form is saved */
|
|
4
10
|
onSave: (config: Record<string, unknown>) => void;
|
|
11
|
+
/** Callback when form is cancelled */
|
|
5
12
|
onCancel: () => void;
|
|
6
13
|
}
|
|
7
14
|
declare const ConfigForm: import("svelte").Component<Props, {}, "">;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ConfigPanel Component
|
|
3
|
+
A generic panel for displaying details and configuration
|
|
4
|
+
Can be used for node config, workflow settings, or any entity with an ID
|
|
5
|
+
Accepts a slot for custom form content
|
|
6
|
+
Styled with BEM syntax
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import type { Snippet } from 'svelte';
|
|
11
|
+
import ReadOnlyDetails from './ReadOnlyDetails.svelte';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A single detail item with label and value
|
|
15
|
+
*/
|
|
16
|
+
interface DetailItem {
|
|
17
|
+
/** The label to display */
|
|
18
|
+
label: string;
|
|
19
|
+
/** The value to display */
|
|
20
|
+
value: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Props interface for ConfigPanel component
|
|
25
|
+
*/
|
|
26
|
+
interface Props {
|
|
27
|
+
/** Panel title displayed in the header */
|
|
28
|
+
title: string;
|
|
29
|
+
/** Unique identifier to display with copy button */
|
|
30
|
+
id?: string;
|
|
31
|
+
/** Optional description text */
|
|
32
|
+
description?: string;
|
|
33
|
+
/** Array of label-value pairs to display */
|
|
34
|
+
details?: DetailItem[];
|
|
35
|
+
/** Title for the configuration section */
|
|
36
|
+
configTitle?: string;
|
|
37
|
+
/** Callback function when the panel is closed */
|
|
38
|
+
onClose: () => void;
|
|
39
|
+
/** Slot content for the configuration form */
|
|
40
|
+
children?: Snippet;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
title,
|
|
45
|
+
id,
|
|
46
|
+
description,
|
|
47
|
+
details = [],
|
|
48
|
+
configTitle = 'Configuration',
|
|
49
|
+
onClose,
|
|
50
|
+
children
|
|
51
|
+
}: Props = $props();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if details section should be shown
|
|
55
|
+
*/
|
|
56
|
+
const hasDetails = $derived(id !== undefined || details.length > 0 || description !== undefined);
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<div class="config-panel">
|
|
60
|
+
<!-- Header -->
|
|
61
|
+
<div class="config-panel__header">
|
|
62
|
+
<h2 class="config-panel__title">{title}</h2>
|
|
63
|
+
<button
|
|
64
|
+
class="config-panel__close"
|
|
65
|
+
onclick={onClose}
|
|
66
|
+
aria-label="Close panel"
|
|
67
|
+
>
|
|
68
|
+
×
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<!-- Details Section (between header and content) -->
|
|
73
|
+
{#if hasDetails && id}
|
|
74
|
+
<div class="config-panel__details">
|
|
75
|
+
<ReadOnlyDetails {id} {description} {details} />
|
|
76
|
+
</div>
|
|
77
|
+
{/if}
|
|
78
|
+
|
|
79
|
+
<!-- Content -->
|
|
80
|
+
<div class="config-panel__content">
|
|
81
|
+
{#if children}
|
|
82
|
+
<div class="config-panel__section">
|
|
83
|
+
<h3 class="config-panel__section-title">{configTitle}</h3>
|
|
84
|
+
{@render children()}
|
|
85
|
+
</div>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<style>
|
|
91
|
+
.config-panel {
|
|
92
|
+
height: 100%;
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
background-color: #ffffff;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.config-panel__header {
|
|
99
|
+
display: flex;
|
|
100
|
+
justify-content: space-between;
|
|
101
|
+
align-items: center;
|
|
102
|
+
padding: 0.875rem 1rem;
|
|
103
|
+
border-bottom: 1px solid #e5e7eb;
|
|
104
|
+
background-color: #f9fafb;
|
|
105
|
+
flex-shrink: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.config-panel__title {
|
|
109
|
+
margin: 0;
|
|
110
|
+
font-size: 1rem;
|
|
111
|
+
font-weight: 600;
|
|
112
|
+
color: #111827;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.config-panel__close {
|
|
116
|
+
background: none;
|
|
117
|
+
border: none;
|
|
118
|
+
font-size: 1.25rem;
|
|
119
|
+
line-height: 1;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
color: #6b7280;
|
|
122
|
+
padding: 0.25rem;
|
|
123
|
+
border-radius: 0.25rem;
|
|
124
|
+
transition: color 0.15s, background-color 0.15s;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.config-panel__close:hover {
|
|
128
|
+
color: #374151;
|
|
129
|
+
background-color: #f3f4f6;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.config-panel__details {
|
|
133
|
+
padding: 0.75rem 1rem;
|
|
134
|
+
border-bottom: 1px solid #f3f4f6;
|
|
135
|
+
background-color: #fafafa;
|
|
136
|
+
flex-shrink: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.config-panel__content {
|
|
140
|
+
flex: 1;
|
|
141
|
+
overflow-y: auto;
|
|
142
|
+
padding: 1rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.config-panel__section {
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-direction: column;
|
|
148
|
+
gap: 0.75rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.config-panel__section-title {
|
|
152
|
+
margin: 0;
|
|
153
|
+
font-size: 0.75rem;
|
|
154
|
+
font-weight: 600;
|
|
155
|
+
color: #6b7280;
|
|
156
|
+
text-transform: uppercase;
|
|
157
|
+
letter-spacing: 0.05em;
|
|
158
|
+
}
|
|
159
|
+
</style>
|
|
160
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
/**
|
|
3
|
+
* A single detail item with label and value
|
|
4
|
+
*/
|
|
5
|
+
interface DetailItem {
|
|
6
|
+
/** The label to display */
|
|
7
|
+
label: string;
|
|
8
|
+
/** The value to display */
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Props interface for ConfigPanel component
|
|
13
|
+
*/
|
|
14
|
+
interface Props {
|
|
15
|
+
/** Panel title displayed in the header */
|
|
16
|
+
title: string;
|
|
17
|
+
/** Unique identifier to display with copy button */
|
|
18
|
+
id?: string;
|
|
19
|
+
/** Optional description text */
|
|
20
|
+
description?: string;
|
|
21
|
+
/** Array of label-value pairs to display */
|
|
22
|
+
details?: DetailItem[];
|
|
23
|
+
/** Title for the configuration section */
|
|
24
|
+
configTitle?: string;
|
|
25
|
+
/** Callback function when the panel is closed */
|
|
26
|
+
onClose: () => void;
|
|
27
|
+
/** Slot content for the configuration form */
|
|
28
|
+
children?: Snippet;
|
|
29
|
+
}
|
|
30
|
+
declare const ConfigPanel: import("svelte").Component<Props, {}, "">;
|
|
31
|
+
type ConfigPanel = ReturnType<typeof ConfigPanel>;
|
|
32
|
+
export default ConfigPanel;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ReadOnlyDetails Component
|
|
3
|
+
Displays readonly information with an ID (with copy button), title, description, and label-value pairs
|
|
4
|
+
Compact inline layout with BEM syntax
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
/**
|
|
9
|
+
* A single detail item with label and value
|
|
10
|
+
*/
|
|
11
|
+
interface DetailItem {
|
|
12
|
+
/** The label to display */
|
|
13
|
+
label: string;
|
|
14
|
+
/** The value to display */
|
|
15
|
+
value: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Props interface for ReadOnlyDetails component
|
|
20
|
+
*/
|
|
21
|
+
interface Props {
|
|
22
|
+
/** The unique identifier to display with a copy button */
|
|
23
|
+
id: string;
|
|
24
|
+
/** Optional section title */
|
|
25
|
+
title?: string;
|
|
26
|
+
/** Optional description text */
|
|
27
|
+
description?: string;
|
|
28
|
+
/** Array of label-value pairs to display */
|
|
29
|
+
details: DetailItem[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { id, title, description, details }: Props = $props();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Copy the ID to clipboard
|
|
36
|
+
*/
|
|
37
|
+
function copyId(): void {
|
|
38
|
+
navigator.clipboard.writeText(id);
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<div class="readonly-details">
|
|
43
|
+
{#if title}
|
|
44
|
+
<h3 class="readonly-details__title">{title}</h3>
|
|
45
|
+
{/if}
|
|
46
|
+
|
|
47
|
+
<div class="readonly-details__grid">
|
|
48
|
+
<!-- ID row -->
|
|
49
|
+
<span class="readonly-details__label">ID</span>
|
|
50
|
+
<div class="readonly-details__id-row">
|
|
51
|
+
<code class="readonly-details__id">{id}</code>
|
|
52
|
+
<button
|
|
53
|
+
class="readonly-details__copy-btn"
|
|
54
|
+
onclick={copyId}
|
|
55
|
+
title="Copy ID"
|
|
56
|
+
aria-label="Copy ID to clipboard"
|
|
57
|
+
>
|
|
58
|
+
<svg
|
|
59
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
60
|
+
fill="none"
|
|
61
|
+
width="12"
|
|
62
|
+
height="12"
|
|
63
|
+
viewBox="0 0 24 24"
|
|
64
|
+
stroke-width="2"
|
|
65
|
+
stroke="currentColor"
|
|
66
|
+
>
|
|
67
|
+
<path
|
|
68
|
+
stroke-linecap="round"
|
|
69
|
+
stroke-linejoin="round"
|
|
70
|
+
d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"
|
|
71
|
+
/>
|
|
72
|
+
</svg>
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<!-- Dynamic label-value pairs -->
|
|
77
|
+
{#each details as detail (detail.label)}
|
|
78
|
+
<span class="readonly-details__label">{detail.label}</span>
|
|
79
|
+
<span class="readonly-details__value">{detail.value}</span>
|
|
80
|
+
{/each}
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<!-- Description (if provided) -->
|
|
84
|
+
{#if description}
|
|
85
|
+
<p class="readonly-details__description">{description}</p>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<style>
|
|
90
|
+
.readonly-details {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
gap: 0.5rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.readonly-details__title {
|
|
97
|
+
margin: 0;
|
|
98
|
+
font-size: 0.75rem;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
color: #6b7280;
|
|
101
|
+
text-transform: uppercase;
|
|
102
|
+
letter-spacing: 0.05em;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.readonly-details__grid {
|
|
106
|
+
display: grid;
|
|
107
|
+
grid-template-columns: auto 1fr;
|
|
108
|
+
gap: 0.25rem 0.75rem;
|
|
109
|
+
align-items: center;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.readonly-details__label {
|
|
113
|
+
font-size: 0.75rem;
|
|
114
|
+
font-weight: 500;
|
|
115
|
+
color: #9ca3af;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.readonly-details__value {
|
|
119
|
+
font-size: 0.8125rem;
|
|
120
|
+
color: #374151;
|
|
121
|
+
font-weight: 500;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.readonly-details__id-row {
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
gap: 0.375rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.readonly-details__id {
|
|
131
|
+
font-size: 0.75rem;
|
|
132
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
|
|
133
|
+
color: #6b7280;
|
|
134
|
+
background-color: #f3f4f6;
|
|
135
|
+
padding: 0.125rem 0.375rem;
|
|
136
|
+
border-radius: 0.25rem;
|
|
137
|
+
word-break: break-all;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.readonly-details__copy-btn {
|
|
141
|
+
background: transparent;
|
|
142
|
+
border: none;
|
|
143
|
+
padding: 0.25rem;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
color: #9ca3af;
|
|
146
|
+
border-radius: 0.25rem;
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
justify-content: center;
|
|
150
|
+
transition: color 0.15s, background-color 0.15s;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.readonly-details__copy-btn:hover {
|
|
154
|
+
color: #374151;
|
|
155
|
+
background-color: #f3f4f6;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.readonly-details__copy-btn:active {
|
|
159
|
+
color: #111827;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.readonly-details__description {
|
|
163
|
+
margin: 0;
|
|
164
|
+
font-size: 0.8125rem;
|
|
165
|
+
color: #6b7280;
|
|
166
|
+
line-height: 1.5;
|
|
167
|
+
}
|
|
168
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single detail item with label and value
|
|
3
|
+
*/
|
|
4
|
+
interface DetailItem {
|
|
5
|
+
/** The label to display */
|
|
6
|
+
label: string;
|
|
7
|
+
/** The value to display */
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Props interface for ReadOnlyDetails component
|
|
12
|
+
*/
|
|
13
|
+
interface Props {
|
|
14
|
+
/** The unique identifier to display with a copy button */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Optional section title */
|
|
17
|
+
title?: string;
|
|
18
|
+
/** Optional description text */
|
|
19
|
+
description?: string;
|
|
20
|
+
/** Array of label-value pairs to display */
|
|
21
|
+
details: DetailItem[];
|
|
22
|
+
}
|
|
23
|
+
declare const ReadOnlyDetails: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type ReadOnlyDetails = ReturnType<typeof ReadOnlyDetails>;
|
|
25
|
+
export default ReadOnlyDetails;
|