@mcp-b/interactive-components 0.2.0
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/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/code-editor-B94tewLC.js +425 -0
- package/dist/code-preview-gKk0nBKP.js +269 -0
- package/dist/components/code-editor/code-editor.d.ts +65 -0
- package/dist/components/code-editor/code-editor.js +2 -0
- package/dist/components/code-preview/code-preview.d.ts +58 -0
- package/dist/components/code-preview/code-preview.js +3 -0
- package/dist/components/interactive-editor/interactive-editor.d.ts +77 -0
- package/dist/components/interactive-editor/interactive-editor.js +3 -0
- package/dist/components/r-editor/r-editor.d.ts +68 -0
- package/dist/components/r-editor/r-editor.js +2 -0
- package/dist/components/sql-editor/sql-editor.d.ts +78 -0
- package/dist/components/sql-editor/sql-editor.js +2 -0
- package/dist/decorate-DcF3lt7P.js +9 -0
- package/dist/docs/custom-elements.json +2807 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/interactive-editor-WfTWxJGF.js +1454 -0
- package/dist/lib/runner-channel.d.ts +25 -0
- package/dist/lib/runner-channel.js +55 -0
- package/dist/lib/runner-url.d.ts +15 -0
- package/dist/lib/runner-url.js +19 -0
- package/dist/lib/transform.d.ts +2 -0
- package/dist/lib/transform.js +210 -0
- package/dist/r-editor-DwSyDo2i.js +743 -0
- package/dist/runners/ephemeral-indexeddb.js +114 -0
- package/dist/runners/pglite-runner.js +175 -0
- package/dist/runners/pyscript-runner.html +189 -0
- package/dist/runners/webr-runner.html +282 -0
- package/dist/sql-editor-CsNrjJ2_.js +968 -0
- package/dist/themes/interactive.css +79 -0
- package/dist/transform-DWhHlnkw.d.ts +53 -0
- package/dist/vite.d.ts +14 -0
- package/dist/vite.js +62 -0
- package/package.json +96 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta name="referrer" content="no-referrer" />
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<canvas id="plot-canvas" width="800" height="600" style="display: none"></canvas>
|
|
10
|
+
<script type="module">
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createRunnerEndpoint(onMessage) {
|
|
16
|
+
var port = null;
|
|
17
|
+
var pending = [];
|
|
18
|
+
var params = new URLSearchParams(window.location.hash.slice(1));
|
|
19
|
+
var channelId = params.get("sigvelo-channel");
|
|
20
|
+
var parentOrigin = params.get("sigvelo-parent-origin");
|
|
21
|
+
|
|
22
|
+
function connect(event) {
|
|
23
|
+
if (
|
|
24
|
+
event.source !== window.parent ||
|
|
25
|
+
!parentOrigin ||
|
|
26
|
+
event.origin !== parentOrigin ||
|
|
27
|
+
!isRecord(event.data) ||
|
|
28
|
+
event.data.type !== "sigvelo-runner-connect-v1" ||
|
|
29
|
+
event.data.channelId !== channelId ||
|
|
30
|
+
event.data.parentOrigin !== parentOrigin ||
|
|
31
|
+
event.ports.length !== 1
|
|
32
|
+
)
|
|
33
|
+
return;
|
|
34
|
+
|
|
35
|
+
port = event.ports[0];
|
|
36
|
+
port.onmessage = function (message) {
|
|
37
|
+
onMessage(message.data);
|
|
38
|
+
};
|
|
39
|
+
port.start();
|
|
40
|
+
pending.splice(0).forEach(function (message) {
|
|
41
|
+
port.postMessage(message);
|
|
42
|
+
});
|
|
43
|
+
window.removeEventListener("message", connect);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
window.addEventListener("message", connect);
|
|
47
|
+
return {
|
|
48
|
+
postMessage(message) {
|
|
49
|
+
if (port) port.postMessage(message);
|
|
50
|
+
else if (pending.length < 100) pending.push(message);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var runnerEndpoint = createRunnerEndpoint(handleRunnerMessage);
|
|
56
|
+
|
|
57
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
58
|
+
function postToParent(msg) {
|
|
59
|
+
runnerEndpoint.postMessage(msg);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function postConsole(level, text) {
|
|
63
|
+
postToParent({
|
|
64
|
+
__sigvelo_console: true,
|
|
65
|
+
level: level,
|
|
66
|
+
args: [String(text)],
|
|
67
|
+
ts: Date.now(),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var plotCanvas = document.getElementById("plot-canvas");
|
|
72
|
+
var plotCtx = plotCanvas.getContext("2d");
|
|
73
|
+
|
|
74
|
+
function canvasToDataUrl() {
|
|
75
|
+
return plotCanvas.toDataURL("image/png");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function clearCanvas() {
|
|
79
|
+
plotCtx.clearRect(0, 0, plotCanvas.width, plotCanvas.height);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── WebR initialization ─────────────────────────────────────────────
|
|
83
|
+
var webR = null;
|
|
84
|
+
var installedPackages = new Set();
|
|
85
|
+
|
|
86
|
+
// A sandbox without allow-same-origin has an opaque origin. Browsers
|
|
87
|
+
// therefore reject WebR's direct Worker(httpUrl) bootstrap even when the
|
|
88
|
+
// asset opts into CORS. Fetch the trusted packaged worker, turn it into a
|
|
89
|
+
// blob owned by this opaque realm, and remap only that one construction.
|
|
90
|
+
async function constructWebR(WebR, baseUrl) {
|
|
91
|
+
var workerUrl = new URL("webr-worker.js", baseUrl).href;
|
|
92
|
+
var response = await fetch(workerUrl);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error("Unable to load WebR worker: HTTP " + response.status);
|
|
95
|
+
}
|
|
96
|
+
var workerBlobUrl = URL.createObjectURL(
|
|
97
|
+
new Blob([await response.text()], { type: "text/javascript" }),
|
|
98
|
+
);
|
|
99
|
+
var NativeWorker = globalThis.Worker;
|
|
100
|
+
globalThis.Worker = new Proxy(NativeWorker, {
|
|
101
|
+
construct: function (Target, args) {
|
|
102
|
+
var requestedUrl = new URL(String(args[0]), window.location.href).href;
|
|
103
|
+
var mappedArgs = requestedUrl === workerUrl ? [workerBlobUrl, args[1]] : args;
|
|
104
|
+
return Reflect.construct(Target, mappedArgs);
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
try {
|
|
108
|
+
return { instance: new WebR({ baseUrl: baseUrl }), workerBlobUrl: workerBlobUrl };
|
|
109
|
+
} finally {
|
|
110
|
+
globalThis.Worker = NativeWorker;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
postToParent({ __sigvelo_webr_loading: true, message: "Downloading WebR runtime..." });
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
var mod = await import("./webr/webr.js");
|
|
118
|
+
var WebR = mod.WebR;
|
|
119
|
+
var baseUrl = new URL("./webr/", window.location.href).href;
|
|
120
|
+
var constructed = await constructWebR(WebR, baseUrl);
|
|
121
|
+
webR = constructed.instance;
|
|
122
|
+
try {
|
|
123
|
+
await webR.init();
|
|
124
|
+
} finally {
|
|
125
|
+
URL.revokeObjectURL(constructed.workerBlobUrl);
|
|
126
|
+
}
|
|
127
|
+
postToParent({ __sigvelo_webr_ready: true });
|
|
128
|
+
} catch (err) {
|
|
129
|
+
postConsole(
|
|
130
|
+
"error",
|
|
131
|
+
"WebR init failed: " + (err.message || err) + "\n" + (err.stack || ""),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ── Code execution ──────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
async function runCode(payload) {
|
|
138
|
+
if (!webR) {
|
|
139
|
+
postConsole("error", "WebR is not initialized");
|
|
140
|
+
postToParent({ __sigvelo_webr_done: true, ts: Date.now() });
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
var code = payload.code;
|
|
145
|
+
var packages = payload.packages || [];
|
|
146
|
+
|
|
147
|
+
// Install requested packages
|
|
148
|
+
for (var pkg of packages) {
|
|
149
|
+
if (!installedPackages.has(pkg)) {
|
|
150
|
+
postToParent({ __sigvelo_webr_loading: true, message: "Installing: " + pkg + "..." });
|
|
151
|
+
try {
|
|
152
|
+
await webR.installPackages([pkg]);
|
|
153
|
+
installedPackages.add(pkg);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
postConsole("error", "Failed to install " + pkg + ": " + (e.message || e));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Drain stale messages
|
|
161
|
+
await webR.flush();
|
|
162
|
+
|
|
163
|
+
var shelter;
|
|
164
|
+
try {
|
|
165
|
+
shelter = await new webR.Shelter();
|
|
166
|
+
} catch (e) {
|
|
167
|
+
postConsole("error", "Shelter creation failed: " + (e.message || e));
|
|
168
|
+
postToParent({ __sigvelo_webr_done: true, ts: Date.now() });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
// 1. Open canvas device so plot() calls go there
|
|
174
|
+
await webR.evalRVoid("webr::canvas(width=800, height=600)");
|
|
175
|
+
|
|
176
|
+
// 2. Execute user code with captureR for text output
|
|
177
|
+
var capture = await shelter.captureR(code, {
|
|
178
|
+
withAutoprint: true,
|
|
179
|
+
captureStreams: true,
|
|
180
|
+
captureConditions: true,
|
|
181
|
+
captureGraphics: false,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// 3. Close the graphics device
|
|
185
|
+
try {
|
|
186
|
+
await webR.evalRVoid("dev.off()");
|
|
187
|
+
} catch (e) {}
|
|
188
|
+
|
|
189
|
+
// 4. Forward captured text output
|
|
190
|
+
for (var entry of capture.output || []) {
|
|
191
|
+
if (entry.type === "stdout") {
|
|
192
|
+
postConsole("log", entry.data);
|
|
193
|
+
} else if (entry.type === "stderr") {
|
|
194
|
+
postConsole("error", entry.data);
|
|
195
|
+
} else if (entry.type === "warning") {
|
|
196
|
+
postConsole("warn", "Warning: " + (entry.data.message || entry.data));
|
|
197
|
+
} else if (entry.type === "error") {
|
|
198
|
+
postConsole("error", "R Error: " + (entry.data.message || entry.data));
|
|
199
|
+
} else if (entry.type === "message") {
|
|
200
|
+
postConsole("info", entry.data.message || entry.data);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 5. Process canvas messages using a real <canvas> element
|
|
205
|
+
// Draw each canvasImage onto the canvas (full-frame snapshot).
|
|
206
|
+
// On canvasNewPage, capture the current canvas and start fresh.
|
|
207
|
+
var msgs = await webR.flush();
|
|
208
|
+
var plots = [];
|
|
209
|
+
var hasContent = false;
|
|
210
|
+
|
|
211
|
+
clearCanvas();
|
|
212
|
+
|
|
213
|
+
for (var msg of msgs) {
|
|
214
|
+
if (msg.type !== "canvas" || !msg.data) continue;
|
|
215
|
+
|
|
216
|
+
if (msg.data.event === "canvasNewPage") {
|
|
217
|
+
// Save current plot if it has content
|
|
218
|
+
if (hasContent) {
|
|
219
|
+
plots.push(canvasToDataUrl());
|
|
220
|
+
}
|
|
221
|
+
// Resize canvas to match device dimensions if provided
|
|
222
|
+
if (msg.data.width) plotCanvas.width = msg.data.width;
|
|
223
|
+
if (msg.data.height) plotCanvas.height = msg.data.height;
|
|
224
|
+
clearCanvas();
|
|
225
|
+
// Fill with background color if provided
|
|
226
|
+
if (msg.data.fill) {
|
|
227
|
+
plotCtx.fillStyle = msg.data.fill;
|
|
228
|
+
plotCtx.fillRect(0, 0, plotCanvas.width, plotCanvas.height);
|
|
229
|
+
}
|
|
230
|
+
hasContent = false;
|
|
231
|
+
} else if (msg.data.event === "canvasImage") {
|
|
232
|
+
// Resize canvas to match image dimensions on first draw
|
|
233
|
+
var img = msg.data.image;
|
|
234
|
+
if (img.width && img.width !== plotCanvas.width) plotCanvas.width = img.width;
|
|
235
|
+
if (img.height && img.height !== plotCanvas.height) plotCanvas.height = img.height;
|
|
236
|
+
plotCtx.drawImage(img, 0, 0);
|
|
237
|
+
hasContent = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Capture the last plot
|
|
242
|
+
if (hasContent) {
|
|
243
|
+
plots.push(canvasToDataUrl());
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 6. Send plots to parent
|
|
247
|
+
for (var j = 0; j < plots.length; j++) {
|
|
248
|
+
postToParent({ __sigvelo_plot: true, dataUrl: plots[j], index: j, ts: Date.now() });
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
try {
|
|
252
|
+
await webR.evalRVoid("dev.off()");
|
|
253
|
+
} catch (e2) {}
|
|
254
|
+
try {
|
|
255
|
+
await webR.flush();
|
|
256
|
+
} catch (e3) {}
|
|
257
|
+
postConsole("error", e.message || String(e));
|
|
258
|
+
} finally {
|
|
259
|
+
try {
|
|
260
|
+
await shelter.purge();
|
|
261
|
+
} catch (e) {}
|
|
262
|
+
postToParent({ __sigvelo_webr_done: true, ts: Date.now() });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function handleRunnerMessage(data) {
|
|
267
|
+
if (
|
|
268
|
+
!isRecord(data) ||
|
|
269
|
+
data.type !== "webr-run" ||
|
|
270
|
+
typeof data.code !== "string" ||
|
|
271
|
+
!Array.isArray(data.packages) ||
|
|
272
|
+
!data.packages.every(function (pkg) {
|
|
273
|
+
return typeof pkg === "string";
|
|
274
|
+
})
|
|
275
|
+
) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
void runCode(data);
|
|
279
|
+
}
|
|
280
|
+
</script>
|
|
281
|
+
</body>
|
|
282
|
+
</html>
|