@webmcp-auto-ui/ui 2.5.37 → 2.5.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmcp-auto-ui/ui",
3
- "version": "2.5.37",
3
+ "version": "2.5.39",
4
4
  "description": "Svelte 5 UI components — primitives, widgets, window manager",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -70,6 +70,7 @@
70
70
  ],
71
71
  "dependencies": {
72
72
  "@internationalized/date": "^3.8.1",
73
+ "@turf/turf": "^7.3.5",
73
74
  "@types/d3": "^7.4.3",
74
75
  "@webmcp-auto-ui/agent": "*",
75
76
  "@webmcp-auto-ui/core": "*",
@@ -78,6 +79,7 @@
78
79
  "clsx": "^2.1.1",
79
80
  "highlight.js": "^11.10.0",
80
81
  "html-to-image": "^1.11.13",
82
+ "maplibre-gl": "^5.24.0",
81
83
  "marked": "^14.1.3",
82
84
  "tailwind-merge": "^3.5.0",
83
85
  "tailwind-variants": "^3.2.2",
@@ -32,7 +32,7 @@
32
32
  }
33
33
  </script>
34
34
 
35
- <div class="flex items-center gap-2 w-full">
35
+ <div class="chat-inline">
36
36
  <input
37
37
  bind:this={inputEl}
38
38
  bind:value
@@ -40,16 +40,13 @@
40
40
  {placeholder}
41
41
  {disabled}
42
42
  onkeydown={handleKeydown}
43
- class="flex-1 h-9 px-3 rounded-lg border border-border2 bg-surface2 text-sm text-text1
44
- placeholder:text-text2/40 focus:outline-none focus:border-accent/50
45
- disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
43
+ class="chat-inline__input"
46
44
  />
47
45
  {#if disabled}
48
46
  <button
49
47
  type="button"
50
48
  onclick={handleStop}
51
- class="h-9 px-3 rounded-lg border border-accent2/40 bg-accent2/10 text-accent2
52
- text-xs font-mono hover:bg-accent2/20 transition-colors flex-shrink-0"
49
+ class="chat-inline__btn chat-inline__btn--stop"
53
50
  >
54
51
  stop
55
52
  </button>
@@ -58,11 +55,86 @@
58
55
  type="button"
59
56
  onclick={handleSubmit}
60
57
  disabled={!value?.trim()}
61
- class="h-9 px-3 rounded-lg border border-accent/40 bg-accent/10 text-accent
62
- text-xs font-mono hover:bg-accent/20 disabled:opacity-40 disabled:cursor-not-allowed
63
- transition-colors flex-shrink-0"
58
+ class="chat-inline__btn chat-inline__btn--send"
64
59
  >
65
60
  send
66
61
  </button>
67
62
  {/if}
68
63
  </div>
64
+
65
+ <style>
66
+ .chat-inline {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 0.5rem;
70
+ width: 100%;
71
+ }
72
+
73
+ .chat-inline__input {
74
+ flex: 1 1 0%;
75
+ min-width: 0;
76
+ height: 2.25rem;
77
+ padding: 0 0.75rem;
78
+ border-radius: 0.5rem;
79
+ border: 1px solid var(--color-border2, var(--color-border, #2a2a2a));
80
+ background: var(--color-surface2, var(--color-surface, #1a1a1a));
81
+ color: var(--color-text1, #f5f5f5);
82
+ font-size: 0.875rem;
83
+ line-height: 1.25rem;
84
+ font-family: inherit;
85
+ outline: none;
86
+ transition: border-color 150ms ease, background-color 150ms ease, color 150ms ease;
87
+ }
88
+
89
+ .chat-inline__input::placeholder {
90
+ color: var(--color-text2, #888);
91
+ opacity: 0.4;
92
+ }
93
+
94
+ .chat-inline__input:focus {
95
+ border-color: color-mix(in srgb, var(--color-accent, #4a9eff) 50%, transparent);
96
+ }
97
+
98
+ .chat-inline__input:disabled {
99
+ opacity: 0.5;
100
+ cursor: not-allowed;
101
+ }
102
+
103
+ .chat-inline__btn {
104
+ flex-shrink: 0;
105
+ height: 2.25rem;
106
+ padding: 0 0.75rem;
107
+ border-radius: 0.5rem;
108
+ border: 1px solid transparent;
109
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
110
+ font-size: 0.6875rem;
111
+ line-height: 1;
112
+ cursor: pointer;
113
+ transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, opacity 150ms ease;
114
+ }
115
+
116
+ .chat-inline__btn:disabled {
117
+ opacity: 0.4;
118
+ cursor: not-allowed;
119
+ }
120
+
121
+ .chat-inline__btn--send {
122
+ background: color-mix(in srgb, var(--color-accent, #4a9eff) 10%, transparent);
123
+ color: var(--color-accent, #4a9eff);
124
+ border-color: color-mix(in srgb, var(--color-accent, #4a9eff) 40%, transparent);
125
+ }
126
+
127
+ .chat-inline__btn--send:hover:not(:disabled) {
128
+ background: color-mix(in srgb, var(--color-accent, #4a9eff) 20%, transparent);
129
+ }
130
+
131
+ .chat-inline__btn--stop {
132
+ background: color-mix(in srgb, var(--color-accent2, #ff6b6b) 10%, transparent);
133
+ color: var(--color-accent2, #ff6b6b);
134
+ border-color: color-mix(in srgb, var(--color-accent2, #ff6b6b) 40%, transparent);
135
+ }
136
+
137
+ .chat-inline__btn--stop:hover:not(:disabled) {
138
+ background: color-mix(in srgb, var(--color-accent2, #ff6b6b) 20%, transparent);
139
+ }
140
+ </style>
@@ -68,6 +68,7 @@
68
68
  import './rich/gallery.svelte';
69
69
  import './rich/carousel.svelte';
70
70
  import './rich/chat-input.svelte';
71
+ import './rich/map.svelte';
71
72
  // Notebook (1)
72
73
  import './notebook/notebook.svelte';
73
74
  // Agent browsers (registered as widgets for widget_display)
@@ -81,7 +82,7 @@
81
82
  // Rich
82
83
  'stat-card', 'profile', 'json-viewer', 'chart-rich', 'sankey', 'hemicycle',
83
84
  'data-table', 'timeline', 'trombinoscope', 'cards', 'grid-data',
84
- 'js-sandbox', 'log', 'gallery', 'carousel', 'chat-input',
85
+ 'js-sandbox', 'log', 'gallery', 'carousel', 'chat-input', 'map',
85
86
  // Notebook
86
87
  'notebook',
87
88
  // Agent browsers
@@ -169,7 +170,7 @@
169
170
  const tag = `auto-${type}`;
170
171
  // Instantiate on first mount. `data` setter is reactive via Svelte 5 custom-element.
171
172
  const el = document.createElement(tag) as HTMLElement;
172
- (el as unknown as { data: unknown }).data = plainData;
173
+ (el as unknown as { data: unknown }).data = servers ? { ...plainData, webmcpServers: servers } : plainData;
173
174
  const onInteract = (ev: Event) => {
174
175
  const ce = ev as CustomEvent<{ action?: string; payload?: unknown }>;
175
176
  const action = ce.detail?.action ?? 'interact';
@@ -190,7 +191,7 @@
190
191
  $effect(() => {
191
192
  const next = plainData;
192
193
  if (!isNativeCustomElement || !ceElement) return;
193
- (ceElement as unknown as { data: unknown }).data = next;
194
+ (ceElement as unknown as { data: unknown }).data = servers ? { ...next, webmcpServers: servers } : next;
194
195
  });
195
196
 
196
197
  // ── Vanilla renderer container + lifecycle ────────────
@@ -232,7 +233,7 @@
232
233
  let cancelled = false;
233
234
 
234
235
  try {
235
- const result = renderer(container, untrack(() => plainData));
236
+ const result = renderer(container, untrack(() => servers ? { ...plainData, webmcpServers: servers } : plainData));
236
237
  if (result && typeof (result as Promise<unknown>).then === 'function') {
237
238
  (result as Promise<void | (() => void)>).then(
238
239
  (c) => {
@@ -279,7 +280,7 @@
279
280
  runCurrentCleanup();
280
281
  container.innerHTML = '';
281
282
  try {
282
- const result = vanillaRenderer(container, data);
283
+ const result = vanillaRenderer(container, servers ? { ...data, webmcpServers: servers } : data);
283
284
  if (result && typeof (result as Promise<unknown>).then === 'function') {
284
285
  (result as Promise<void | (() => void)>).then(
285
286
  (c) => { currentCleanup = c ?? undefined; },
@@ -67,7 +67,16 @@ export function mountLeftPane(
67
67
  serversEl.innerHTML = '<div class="nb-lp-empty">No servers connected.</div>';
68
68
  return;
69
69
  }
70
+ let lastGroup: 'data' | 'webmcp' | null = null;
70
71
  for (const srv of servers) {
72
+ const group: 'data' | 'webmcp' = srv.kind === 'webmcp' ? 'webmcp' : 'data';
73
+ if (group !== lastGroup) {
74
+ const header = document.createElement('div');
75
+ header.className = 'nb-lp-group-header';
76
+ header.textContent = group === 'webmcp' ? 'Widgets' : 'Data';
77
+ serversEl.appendChild(header);
78
+ lastGroup = group;
79
+ }
71
80
  const section = document.createElement('section');
72
81
  section.className = 'nb-lp-srv';
73
82
  section.innerHTML = `
@@ -132,6 +141,10 @@ export function mountLeftPane(
132
141
  if (!imported.body && recipeBodyCache.has(key)) {
133
142
  imported.body = recipeBodyCache.get(key);
134
143
  }
144
+ // Bundled WebMCP servers expose recipe bodies inline — no MCP roundtrip.
145
+ if (!imported.body && srv.kind === 'webmcp') {
146
+ imported.body = `> ⚠ Recipe \`${r.name}\` (server \`${srv.name}\`) has no inline body.`;
147
+ }
135
148
  if (!imported.body) {
136
149
  try {
137
150
  const res: any = await canvas.callTool(srv.name, 'get_recipe', { name: r.name, id: r.name });
@@ -245,6 +258,13 @@ function injectLeftPaneStyles() {
245
258
  .nb-lp-title { flex: 1; font-weight: 600; font-size: 12px; }
246
259
  .nb-lp-close { background: none; border: none; cursor: pointer; font-size: 16px; color: var(--color-text2, #666); }
247
260
  .nb-lp-servers { overflow-y: auto; padding: 8px 10px 12px; flex: 1; }
261
+ .nb-lp-group-header {
262
+ font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
263
+ color: var(--color-text2, #888); padding: 6px 2px 4px;
264
+ border-bottom: 1px dashed var(--color-border, #e4e4e7);
265
+ margin-bottom: 6px;
266
+ }
267
+ .nb-lp-group-header:not(:first-child) { margin-top: 14px; }
248
268
  .nb-lp-srv { margin-bottom: 10px; }
249
269
  .nb-lp-srv-head {
250
270
  display: flex; align-items: center; gap: 6px;