@webmcp-auto-ui/ui 2.5.28 → 2.5.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,164 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * DataServersPanel — manages the list of data (MCP) servers in the canvas store.
4
- *
5
- * Reads/writes through `canvas.dataServers` (reactive, Svelte 5 runes wrapper).
6
- * A companion `MultiMcpBridge` (installed in the app root) observes the store
7
- * and connects/disconnects servers according to their `enabled` flag.
8
- *
9
- * Visual state per server:
10
- * - disabled : grey dot
11
- * - enabled + !connected : yellow dot (connecting)
12
- * - enabled + connected : green dot (ok)
13
- * - error : red dot with tooltip
14
- */
15
- import { canvas } from '@webmcp-auto-ui/sdk/canvas';
16
-
17
- let connectOpen = $state(false);
18
- let newName = $state('');
19
- let newUrl = $state('');
20
- let formError = $state<string | null>(null);
21
- let nameInputEl: HTMLInputElement | null = $state(null);
22
-
23
- function openModal() {
24
- connectOpen = true;
25
- formError = null;
26
- // Focus the name field once the modal mounts.
27
- queueMicrotask(() => nameInputEl?.focus());
28
- }
29
-
30
- function closeModal() {
31
- connectOpen = false;
32
- newName = '';
33
- newUrl = '';
34
- formError = null;
35
- }
36
-
37
- function onKey(e: KeyboardEvent) {
38
- if (e.key === 'Escape' && connectOpen) {
39
- e.preventDefault();
40
- closeModal();
41
- }
42
- }
43
-
44
- function submitConnect(e?: Event) {
45
- e?.preventDefault();
46
- const name = newName.trim();
47
- const url = newUrl.trim();
48
- if (!name) { formError = 'Name required'; return; }
49
- if (canvas.getDataServer(name)) { formError = 'A server with this name already exists'; return; }
50
- try { new URL(url); } catch { formError = 'Invalid URL'; return; }
51
- canvas.addDataServer({ name, url });
52
- // addDataServer initialises enabled=true; the bridge will pick it up.
53
- closeModal();
54
- }
55
- </script>
56
-
57
- <svelte:window onkeydown={onKey} />
58
-
59
- <section class="flex flex-col gap-2">
60
- <div class="flex items-center justify-between">
61
- <span class="text-[9px] font-mono text-text2 uppercase tracking-wider">Data servers</span>
62
- <button
63
- type="button"
64
- class="font-mono text-[10px] h-6 px-2 rounded border border-accent/40 text-accent hover:bg-accent/10 transition-colors"
65
- onclick={openModal}
66
- >
67
- + Connect
68
- </button>
69
- </div>
70
-
71
- {#if canvas.dataServers.length === 0}
72
- <div class="text-[10px] font-mono text-text2/50 italic">No data servers connected.</div>
73
- {:else}
74
- <ul class="flex flex-col gap-1">
75
- {#each canvas.dataServers as s (s.name)}
76
- <li class="flex items-center gap-2 px-2 py-1.5 rounded border border-border2/60 bg-surface2/40">
77
- <label class="flex items-center gap-2 flex-1 min-w-0 cursor-pointer">
78
- <input
79
- type="checkbox"
80
- class="accent-accent w-3.5 h-3.5 flex-shrink-0"
81
- checked={s.enabled}
82
- onchange={() => canvas.toggleDataServer(s.name)}
83
- aria-label={`Toggle ${s.name}`}
84
- />
85
- <span
86
- class="w-1.5 h-1.5 rounded-full flex-shrink-0
87
- {s.error ? 'bg-accent2'
88
- : !s.enabled ? 'bg-text2/40'
89
- : s.connected ? 'bg-teal'
90
- : 'bg-amber animate-pulse'}"
91
- title={s.error
92
- ? `Error: ${s.error}`
93
- : !s.enabled ? 'Disabled'
94
- : s.connected ? 'Connected'
95
- : 'Connecting…'}
96
- ></span>
97
- <span class="font-mono text-xs text-text1 truncate" title={s.url}>{s.name}</span>
98
- {#if s.tools && s.tools.length > 0}
99
- <span class="font-mono text-[9px] text-text2/60 flex-shrink-0">{s.tools.length} tools</span>
100
- {/if}
101
- </label>
102
- <button
103
- type="button"
104
- class="text-text2/60 hover:text-accent2 transition-colors flex-shrink-0 text-sm leading-none px-1"
105
- onclick={() => canvas.removeDataServer(s.name)}
106
- aria-label={`Remove ${s.name}`}
107
- title="Remove"
108
- >&times;</button>
109
- </li>
110
- {/each}
111
- </ul>
112
- {/if}
113
- </section>
114
-
115
- {#if connectOpen}
116
- <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
117
- <div
118
- class="fixed inset-0 bg-black/50 z-[60] flex items-center justify-center p-4"
119
- onclick={closeModal}
120
- >
121
- <form
122
- class="w-full max-w-sm bg-surface border border-border2 rounded-lg shadow-xl p-5 flex flex-col gap-3"
123
- onclick={(e) => e.stopPropagation()}
124
- onsubmit={submitConnect}
125
- >
126
- <h4 class="font-mono text-sm font-bold text-text1">Connect data server</h4>
127
- <label class="flex flex-col gap-1">
128
- <span class="text-[9px] font-mono text-text2 uppercase tracking-wider">Name</span>
129
- <input
130
- bind:this={nameInputEl}
131
- bind:value={newName}
132
- type="text"
133
- placeholder="tricoteuses"
134
- required
135
- class="font-mono text-xs h-7 px-2 rounded border border-border2 bg-surface2 text-text1"
136
- />
137
- </label>
138
- <label class="flex flex-col gap-1">
139
- <span class="text-[9px] font-mono text-text2 uppercase tracking-wider">URL</span>
140
- <input
141
- bind:value={newUrl}
142
- type="url"
143
- placeholder="https://mcp.example.com/mcp"
144
- required
145
- class="font-mono text-xs h-7 px-2 rounded border border-border2 bg-surface2 text-text1"
146
- />
147
- </label>
148
- {#if formError}
149
- <div class="font-mono text-[10px] text-accent2">{formError}</div>
150
- {/if}
151
- <div class="flex items-center justify-end gap-2 pt-1">
152
- <button
153
- type="button"
154
- class="font-mono text-xs h-7 px-3 rounded border border-border2 text-text2 hover:text-text1 transition-colors"
155
- onclick={closeModal}
156
- >Cancel</button>
157
- <button
158
- type="submit"
159
- class="font-mono text-xs h-7 px-3 rounded border border-accent/40 text-accent hover:bg-accent/10 transition-colors"
160
- >Connect</button>
161
- </div>
162
- </form>
163
- </div>
164
- {/if}