@webmcp-auto-ui/ui 2.5.31 → 2.5.33

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.
Files changed (80) hide show
  1. package/package.json +15 -2
  2. package/src/agent/DiagnosticModal.svelte +126 -50
  3. package/src/agent/EphemeralBubble.svelte +13 -3
  4. package/src/agent/MCPserversList.svelte +147 -0
  5. package/src/agent/McpConnector.svelte +10 -1
  6. package/src/agent/RecipeBrowser.svelte +384 -0
  7. package/src/agent/RemoteMCPserversDemo.svelte +5 -121
  8. package/src/agent/ToolBrowser.svelte +133 -0
  9. package/src/agent/WebMCPserversList.svelte +2 -0
  10. package/src/agent/useAgentLoop.svelte.ts +396 -0
  11. package/src/base/chat-inline.svelte +64 -0
  12. package/src/base/dialog-content.svelte +3 -1
  13. package/src/components/HeaderControls.svelte +78 -0
  14. package/src/index.ts +13 -35
  15. package/src/stores/canvas.svelte.ts +0 -6
  16. package/src/widgets/SafeImage.svelte +67 -0
  17. package/src/widgets/WidgetRenderer.svelte +153 -78
  18. package/src/widgets/notebook/executors/index.ts +0 -1
  19. package/src/widgets/notebook/executors/sql.ts +32 -182
  20. package/src/widgets/notebook/import-modal-api.ts +237 -0
  21. package/src/widgets/notebook/import-modal.svelte +738 -0
  22. package/src/widgets/notebook/left-pane.ts +1 -1
  23. package/src/widgets/notebook/notebook.svelte +75 -0
  24. package/src/widgets/notebook/notebook.ts +38 -73
  25. package/src/widgets/notebook/prose.ts +6 -3
  26. package/src/widgets/notebook/shared.ts +68 -49
  27. package/src/widgets/rich/cards.svelte +74 -0
  28. package/src/widgets/rich/carousel.svelte +126 -0
  29. package/src/widgets/rich/chart-rich.svelte +221 -0
  30. package/src/widgets/rich/chat-input.svelte +52 -0
  31. package/src/widgets/rich/data-table.svelte +132 -0
  32. package/src/widgets/rich/gallery.svelte +115 -0
  33. package/src/widgets/rich/grid-data.svelte +85 -0
  34. package/src/widgets/rich/hemicycle.svelte +95 -0
  35. package/src/widgets/rich/js-sandbox.svelte +67 -0
  36. package/src/widgets/rich/json-viewer.svelte +82 -0
  37. package/src/widgets/rich/log.svelte +62 -0
  38. package/src/widgets/rich/profile.svelte +91 -0
  39. package/src/widgets/rich/sankey.svelte +73 -0
  40. package/src/widgets/rich/stat-card.svelte +60 -0
  41. package/src/widgets/rich/timeline.svelte +95 -0
  42. package/src/widgets/rich/trombinoscope.svelte +87 -0
  43. package/src/widgets/simple/actions.svelte +36 -0
  44. package/src/widgets/simple/alert.svelte +52 -0
  45. package/src/widgets/simple/chart.svelte +38 -0
  46. package/src/widgets/simple/code.svelte +30 -0
  47. package/src/widgets/simple/kv.svelte +31 -0
  48. package/src/widgets/simple/list.svelte +35 -0
  49. package/src/widgets/simple/stat.svelte +36 -0
  50. package/src/widgets/simple/tags.svelte +34 -0
  51. package/src/widgets/simple/text.svelte +130 -0
  52. package/src/widgets/helpers/safe-image.ts +0 -78
  53. package/src/widgets/notebook/import-modals.ts +0 -560
  54. package/src/widgets/notebook/recipe-browser.ts +0 -350
  55. package/src/widgets/rich/cards.ts +0 -181
  56. package/src/widgets/rich/carousel.ts +0 -319
  57. package/src/widgets/rich/chart-rich.ts +0 -386
  58. package/src/widgets/rich/d3.ts +0 -503
  59. package/src/widgets/rich/data-table.ts +0 -342
  60. package/src/widgets/rich/gallery.ts +0 -350
  61. package/src/widgets/rich/grid-data.ts +0 -173
  62. package/src/widgets/rich/hemicycle.ts +0 -313
  63. package/src/widgets/rich/js-sandbox.ts +0 -122
  64. package/src/widgets/rich/json-viewer.ts +0 -202
  65. package/src/widgets/rich/log.ts +0 -143
  66. package/src/widgets/rich/map.ts +0 -218
  67. package/src/widgets/rich/profile.ts +0 -256
  68. package/src/widgets/rich/sankey.ts +0 -257
  69. package/src/widgets/rich/stat-card.ts +0 -125
  70. package/src/widgets/rich/timeline.ts +0 -179
  71. package/src/widgets/rich/trombinoscope.ts +0 -246
  72. package/src/widgets/simple/actions.ts +0 -89
  73. package/src/widgets/simple/alert.ts +0 -100
  74. package/src/widgets/simple/chart.ts +0 -189
  75. package/src/widgets/simple/code.ts +0 -79
  76. package/src/widgets/simple/kv.ts +0 -68
  77. package/src/widgets/simple/list.ts +0 -89
  78. package/src/widgets/simple/stat.ts +0 -58
  79. package/src/widgets/simple/tags.ts +0 -125
  80. package/src/widgets/simple/text.ts +0 -198
@@ -1,198 +0,0 @@
1
- /**
2
- * Vanilla renderer for the "text" / TextBlock widget.
3
- *
4
- * Mirrors the Svelte TextBlock.svelte output: a <div class="tb-md ..."> whose
5
- * innerHTML is produced by a minimal, XSS-safe markdown -> HTML function.
6
- *
7
- * XSS note: renderMarkdown() escapes &, <, >, " BEFORE applying inline rules,
8
- * so user-controlled text can only reach the DOM as already-escaped entities or
9
- * as the structural tags we explicitly emit (h1-6, p, strong, em, code, pre, ul,
10
- * ol, li, a, hr). Using innerHTML here is therefore safe — the function is the
11
- * single source of trust for sanitization.
12
- */
13
-
14
- export interface TextBlockData {
15
- content?: string;
16
- }
17
-
18
- /** Minimal markdown → HTML renderer (no deps, naturally XSS-safe: only produces known tags) */
19
- function renderMarkdown(src: string): string {
20
- if (!src) return '';
21
-
22
- // Escape HTML entities first (XSS protection)
23
- const esc = (s: string) =>
24
- s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
25
-
26
- const lines = src.split('\n');
27
- const out: string[] = [];
28
- let inCode = false;
29
- let codeLines: string[] = [];
30
- let inUl = false;
31
- let inOl = false;
32
-
33
- const closeList = () => {
34
- if (inUl) { out.push('</ul>'); inUl = false; }
35
- if (inOl) { out.push('</ol>'); inOl = false; }
36
- };
37
-
38
- /** Inline formatting: bold, italic, code, links */
39
- const inline = (s: string): string => {
40
- return esc(s)
41
- .replace(/`([^`]+)`/g, '<code>$1</code>')
42
- .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
43
- .replace(/\*([^*]+)\*/g, '<em>$1</em>')
44
- // Whitelist URL protocols to block javascript:/data:/vbscript: XSS via markdown links.
45
- .replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label, href) =>
46
- /^(https?:|\/|#|mailto:)/i.test(href)
47
- ? `<a href="${href}" target="_blank" rel="noopener">${label}</a>`
48
- : label,
49
- );
50
- };
51
-
52
- for (const line of lines) {
53
- // Fenced code block toggle
54
- if (line.trimStart().startsWith('```')) {
55
- if (!inCode) {
56
- closeList();
57
- inCode = true;
58
- codeLines = [];
59
- } else {
60
- out.push(`<pre><code>${esc(codeLines.join('\n'))}</code></pre>`);
61
- inCode = false;
62
- }
63
- continue;
64
- }
65
- if (inCode) { codeLines.push(line); continue; }
66
-
67
- const trimmed = line.trim();
68
-
69
- // Empty line → close lists, push break
70
- if (!trimmed) { closeList(); out.push(''); continue; }
71
-
72
- // Headers
73
- const hMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
74
- if (hMatch) {
75
- closeList();
76
- const level = hMatch[1].length;
77
- out.push(`<h${level}>${inline(hMatch[2])}</h${level}>`);
78
- continue;
79
- }
80
-
81
- // Unordered list
82
- if (/^[-*+]\s+/.test(trimmed)) {
83
- if (inOl) { out.push('</ol>'); inOl = false; }
84
- if (!inUl) { out.push('<ul>'); inUl = true; }
85
- out.push(`<li>${inline(trimmed.replace(/^[-*+]\s+/, ''))}</li>`);
86
- continue;
87
- }
88
-
89
- // Ordered list
90
- const olMatch = trimmed.match(/^(\d+)\.\s+(.+)$/);
91
- if (olMatch) {
92
- if (inUl) { out.push('</ul>'); inUl = false; }
93
- if (!inOl) { out.push('<ol>'); inOl = true; }
94
- out.push(`<li>${inline(olMatch[2])}</li>`);
95
- continue;
96
- }
97
-
98
- // Horizontal rule
99
- if (/^[-*_]{3,}$/.test(trimmed)) {
100
- closeList();
101
- out.push('<hr>');
102
- continue;
103
- }
104
-
105
- // Regular paragraph line
106
- closeList();
107
- out.push(`<p>${inline(trimmed)}</p>`);
108
- }
109
-
110
- // Close any open blocks
111
- if (inCode) out.push(`<pre><code>${esc(codeLines.join('\n'))}</code></pre>`);
112
- closeList();
113
-
114
- return out.join('\n');
115
- }
116
-
117
- /** Scoped styles — emitted once per document, matching TextBlock.svelte :global rules. */
118
- const STYLE_ID = 'autoui-text-widget-styles';
119
- const STYLE_CSS = `
120
- .tb-md { color: var(--color-text2); }
121
- .tb-md h1 { font-size: 1.5em; font-weight: 700; color: var(--color-text1); margin: 0.8em 0 0.4em; }
122
- .tb-md h2 { font-size: 1.25em; font-weight: 600; color: var(--color-text1); margin: 0.7em 0 0.35em; }
123
- .tb-md h3 { font-size: 1.1em; font-weight: 600; color: var(--color-text1); margin: 0.6em 0 0.3em; }
124
- .tb-md h4, .tb-md h5, .tb-md h6 { font-size: 1em; font-weight: 600; color: var(--color-text1); margin: 0.5em 0 0.25em; }
125
- .tb-md p { margin: 0.4em 0; }
126
- .tb-md strong { font-weight: 600; color: var(--color-text1); }
127
- .tb-md em { font-style: italic; }
128
- .tb-md a { color: var(--color-accent); text-decoration: underline; text-underline-offset: 2px; }
129
- .tb-md a:hover { opacity: 0.8; }
130
- .tb-md ul, .tb-md ol { margin: 0.4em 0; padding-left: 1.5em; }
131
- .tb-md ul { list-style: disc; }
132
- .tb-md ol { list-style: decimal; }
133
- .tb-md li { margin: 0.15em 0; }
134
- .tb-md code { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: 0.9em; background: var(--color-surface2); padding: 0.15em 0.35em; border-radius: 4px; }
135
- .tb-md pre { background: var(--color-surface2); border-radius: 6px; padding: 0.75em 1em; margin: 0.5em 0; overflow-x: auto; }
136
- .tb-md pre code { background: none; padding: 0; font-size: 0.85em; }
137
- .tb-md hr { border: none; border-top: 1px solid var(--color-surface2); margin: 0.8em 0; }
138
- `;
139
-
140
- function ensureStyles(doc: Document): void {
141
- if (doc.getElementById(STYLE_ID)) return;
142
- const style = doc.createElement('style');
143
- style.id = STYLE_ID;
144
- style.textContent = STYLE_CSS;
145
- doc.head.appendChild(style);
146
- }
147
-
148
- /**
149
- * Mount a text / markdown widget into `container`.
150
- *
151
- * Returns an `unmount()` function that clears the container and removes any
152
- * attached listeners.
153
- */
154
- export function render(container: HTMLElement, data: any): () => void {
155
- const payload = (data ?? {}) as Partial<TextBlockData>;
156
- const content = typeof payload.content === 'string' ? payload.content : '';
157
-
158
- ensureStyles(container.ownerDocument ?? document);
159
-
160
- const root = container.ownerDocument.createElement('div');
161
- root.className = 'tb-md p-4 md:p-5 text-sm leading-relaxed';
162
-
163
- if (!content.trim()) {
164
- // Empty-state placeholder — keeps layout, signals absence to a11y tree.
165
- const placeholder = container.ownerDocument.createElement('p');
166
- placeholder.textContent = '';
167
- placeholder.setAttribute('aria-label', 'empty text block');
168
- placeholder.style.opacity = '0.5';
169
- placeholder.style.fontStyle = 'italic';
170
- root.appendChild(placeholder);
171
- } else {
172
- // Safe: renderMarkdown() escapes user text before emitting tags.
173
- root.innerHTML = renderMarkdown(content);
174
- }
175
-
176
- // Delegated click handler — lets links emit widget:interact for host apps
177
- // (e.g. analytics / canvas telemetry) without blocking default navigation.
178
- const onClick = (ev: MouseEvent) => {
179
- const target = ev.target as HTMLElement | null;
180
- if (!target) return;
181
- const anchor = target.closest('a');
182
- if (!anchor || !root.contains(anchor)) return;
183
- container.dispatchEvent(
184
- new CustomEvent('widget:interact', {
185
- detail: { action: 'link', payload: { href: (anchor as HTMLAnchorElement).href } },
186
- bubbles: true,
187
- }),
188
- );
189
- };
190
- root.addEventListener('click', onClick);
191
-
192
- container.appendChild(root);
193
-
194
- return () => {
195
- root.removeEventListener('click', onClick);
196
- container.innerHTML = '';
197
- };
198
- }