@marimo-team/frontend 0.20.5-dev28 → 0.20.5-dev33
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/assets/{CellStatus-Bf3_zqWp.js → CellStatus-rawm41sF.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-BWGS1xUt.js → ConnectedDataExplorerComponent-BmrDShEI.js} +1 -1
- package/dist/assets/{ImperativeModal-l3NQQITL.js → ImperativeModal-BvRpI5NU.js} +1 -1
- package/dist/assets/{JsonOutput-CGdzBqS1.js → JsonOutput-D8vxudTc.js} +1 -1
- package/dist/assets/{MarimoErrorOutput-Bms-kX7B.js → MarimoErrorOutput-ThxhEC9x.js} +1 -1
- package/dist/assets/{RenderHTML-DpbhvZnj.js → RenderHTML-Ci0Pb1aU.js} +1 -1
- package/dist/assets/{add-cell-with-ai-XG5BIwhn.js → add-cell-with-ai-C9Xp-2Lu.js} +1 -1
- package/dist/assets/{add-connection-dialog-DbCfepEj.js → add-connection-dialog-C0_z2T_b.js} +1 -1
- package/dist/assets/{agent-panel-D16-GLG-.js → agent-panel-CFmSkdtw.js} +1 -1
- package/dist/assets/ai-model-dropdown-DJoBltN-.js +5 -0
- package/dist/assets/{app-config-button-CI0WOSLz.js → app-config-button-Cw2wXNR2.js} +1 -1
- package/dist/assets/{cache-panel-DrOCfrS9.js → cache-panel-B4TWdLE9.js} +1 -1
- package/dist/assets/{cell-editor-BU2bXyD1.js → cell-editor-BoDTqwYs.js} +1 -1
- package/dist/assets/{cell-link-CApHIAZF.js → cell-link-TWNu2IkO.js} +1 -1
- package/dist/assets/{chat-display-DwFyJBVB.js → chat-display-Dwlgqtli.js} +1 -1
- package/dist/assets/{chat-panel-CivqPgLR.js → chat-panel-DP052nQF.js} +1 -1
- package/dist/assets/{column-preview-BTufLMhz.js → column-preview-CPJFpq_q.js} +1 -1
- package/dist/assets/{command-DLq1SsAO.js → command-DQqPawJf.js} +1 -1
- package/dist/assets/{command-palette-BYaD9kOd.js → command-palette-BM1QAZTW.js} +1 -1
- package/dist/assets/{common-DC4lyug7.js → common-Df9UcCs1.js} +1 -1
- package/dist/assets/context-CRmPPhx9.js +1 -0
- package/dist/assets/{context-aware-panel-D7L-J6dq.js → context-aware-panel-Bs4Vepkp.js} +1 -1
- package/dist/assets/{dependency-graph-panel-DHjX2IAi.js → dependency-graph-panel-DddysMUS.js} +1 -1
- package/dist/assets/dist-SDO5K7hA.js +3 -0
- package/dist/assets/{documentation-panel-x4uNnKYg.js → documentation-panel-Bs1zlxdM.js} +1 -1
- package/dist/assets/edit-page-D7VD6LD4.js +13 -0
- package/dist/assets/{error-panel-pHxYpjX_.js → error-panel-B_vII0VN.js} +1 -1
- package/dist/assets/{field-jeUVnXuU.js → field-D-izY3ud.js} +1 -1
- package/dist/assets/{file-explorer-panel-CraYsOVj.js → file-explorer-panel-BIzyNOVs.js} +1 -1
- package/dist/assets/{form-KYhtvrIF.js → form-DrpSpDea.js} +1 -1
- package/dist/assets/{gallery-page-mozL4wJd.js → gallery-page-BrljeBFe.js} +1 -1
- package/dist/assets/{glide-data-editor-BhnSrNBl.js → glide-data-editor-8kdd_nPE.js} +1 -1
- package/dist/assets/{home-page-fzpZMqwS.js → home-page-O_c6IiAp.js} +1 -1
- package/dist/assets/{hooks-YZ8YquEB.js → hooks-Z1j4FmRH.js} +1 -1
- package/dist/assets/index-B7vfm6Sw.js +38 -0
- package/dist/assets/input-GLbHj4DF.js +1 -0
- package/dist/assets/layout-DQhzfSJn.js +5 -0
- package/dist/assets/{logs-panel-D_BejkBp.js → logs-panel-BKhNdCxG.js} +1 -1
- package/dist/assets/{name-cell-input-tnyN_rNq.js → name-cell-input-DOyCua0o.js} +1 -1
- package/dist/assets/{packages-panel-BfOynji5.js → packages-panel-n8Ssm9M8.js} +1 -1
- package/dist/assets/{panels-C8RuHp78.js → panels-B4wExe_l.js} +1 -1
- package/dist/assets/{run-page-Cg-HjFtb.js → run-page-BYEyHIaG.js} +1 -1
- package/dist/assets/{scratchpad-panel-BombralT.js → scratchpad-panel-BRTSBHvd.js} +1 -1
- package/dist/assets/{secrets-panel-Cz3H7Kcc.js → secrets-panel-DAnccD-S.js} +1 -1
- package/dist/assets/{session-panel-msqiNt1Z.js → session-panel-k6_Gni4X.js} +1 -1
- package/dist/assets/{snippets-panel-Beh7h7mz.js → snippets-panel-mGo3M47p.js} +1 -1
- package/dist/assets/{tracing-DaGZb1gK.js → tracing-DTCuFbVV.js} +1 -1
- package/dist/assets/{tracing-panel-DvvJq5B5.js → tracing-panel-B1EJu6-W.js} +2 -2
- package/dist/assets/useBoolean-2eWc7NX-.js +1 -0
- package/dist/assets/{useCellActionButton-CKUAt6Sl.js → useCellActionButton-CJ_LAoma.js} +1 -1
- package/dist/assets/{useDateFormatter-DfEfyPT1.js → useDateFormatter-DOoVZUts.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-CH3r9bC-.js → useDependencyPanelTab-nuk9kUr_.js} +1 -1
- package/dist/assets/{useNotebookActions-CXRecmhh.js → useNotebookActions-Bh8YMrlo.js} +1 -1
- package/dist/assets/{useNumberFormatter-DQd-h5xR.js → useNumberFormatter-BXZcbTzH.js} +1 -1
- package/dist/assets/usePress-G817DpBk.js +7 -0
- package/dist/assets/{write-secret-modal-Dj4Ncj4m.js → write-secret-modal-DOyKonZB.js} +1 -1
- package/dist/index.html +20 -20
- package/package.json +9 -9
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +309 -0
- package/src/plugins/impl/mpl-interactive/__tests__/mpl-websocket-shim.test.ts +110 -0
- package/src/plugins/impl/mpl-interactive/mpl-websocket-shim.ts +57 -0
- package/src/plugins/plugins.ts +2 -0
- package/dist/assets/ai-model-dropdown-oin5Fuov.js +0 -5
- package/dist/assets/context-CRApIvpB.js +0 -1
- package/dist/assets/dist-BL52mbxW.js +0 -3
- package/dist/assets/edit-page-JEf4izAb.js +0 -13
- package/dist/assets/index-BqLC0w8B.js +0 -38
- package/dist/assets/input-BwUS1Mg1.js +0 -1
- package/dist/assets/layout-BPSHGKRG.js +0 -5
- package/dist/assets/useBoolean-NLsvxjyM.js +0 -1
- package/dist/assets/usePress-DcdVsIfA.js +0 -7
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { MplCommWebSocket } from "../mpl-websocket-shim";
|
|
4
|
+
|
|
5
|
+
describe("MplCommWebSocket", () => {
|
|
6
|
+
it("starts in OPEN state", () => {
|
|
7
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
8
|
+
expect(ws.readyState).toBe(WebSocket.OPEN);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("send() parses JSON and calls sendFn with parsed object", () => {
|
|
12
|
+
const sendFn = vi.fn();
|
|
13
|
+
const ws = new MplCommWebSocket(sendFn);
|
|
14
|
+
|
|
15
|
+
ws.send(JSON.stringify({ type: "resize", width: 640, height: 480 }));
|
|
16
|
+
|
|
17
|
+
expect(sendFn).toHaveBeenCalledOnce();
|
|
18
|
+
expect(sendFn).toHaveBeenCalledWith({
|
|
19
|
+
type: "resize",
|
|
20
|
+
width: 640,
|
|
21
|
+
height: 480,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("receiveJson() dispatches MessageEvent with JSON string data", () => {
|
|
26
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
27
|
+
const handler = vi.fn();
|
|
28
|
+
ws.onmessage = handler;
|
|
29
|
+
|
|
30
|
+
ws.receiveJson({ type: "figure_size", size: [640, 480] });
|
|
31
|
+
|
|
32
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
33
|
+
const event: MessageEvent = handler.mock.calls[0][0];
|
|
34
|
+
expect(event).toBeInstanceOf(MessageEvent);
|
|
35
|
+
expect(event.type).toBe("message");
|
|
36
|
+
expect(JSON.parse(event.data as string)).toEqual({
|
|
37
|
+
type: "figure_size",
|
|
38
|
+
size: [640, 480],
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("receiveJson() is a no-op if onmessage is not set", () => {
|
|
43
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
44
|
+
ws.receiveJson({ type: "test" });
|
|
45
|
+
expect(ws.onmessage).toBeNull();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("receiveBinary() dispatches MessageEvent with Blob data", () => {
|
|
49
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
50
|
+
const handler = vi.fn();
|
|
51
|
+
ws.onmessage = handler;
|
|
52
|
+
|
|
53
|
+
// Simulate a PNG-like binary buffer
|
|
54
|
+
const bytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0, 1, 2, 3]);
|
|
55
|
+
const dv = new DataView(bytes.buffer);
|
|
56
|
+
|
|
57
|
+
ws.receiveBinary(dv);
|
|
58
|
+
|
|
59
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
60
|
+
const event: MessageEvent = handler.mock.calls[0][0];
|
|
61
|
+
expect(event).toBeInstanceOf(MessageEvent);
|
|
62
|
+
expect(event.data).toBeInstanceOf(Blob);
|
|
63
|
+
expect((event.data as Blob).size).toBe(8);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("receiveBinary() handles DataView with offset", () => {
|
|
67
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
68
|
+
const handler = vi.fn();
|
|
69
|
+
ws.onmessage = handler;
|
|
70
|
+
|
|
71
|
+
// Create a DataView that's a slice of a larger buffer
|
|
72
|
+
const fullBuffer = new ArrayBuffer(16);
|
|
73
|
+
const fullView = new Uint8Array(fullBuffer);
|
|
74
|
+
fullView.set([0, 0, 0, 0, 0x89, 0x50, 0x4e, 0x47, 0, 1, 2, 3, 0, 0, 0, 0]);
|
|
75
|
+
const dv = new DataView(fullBuffer, 4, 8);
|
|
76
|
+
|
|
77
|
+
ws.receiveBinary(dv);
|
|
78
|
+
|
|
79
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
80
|
+
const blob = handler.mock.calls[0][0].data as Blob;
|
|
81
|
+
expect(blob.size).toBe(8);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("close() sets readyState to CLOSED and fires onclose", () => {
|
|
85
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
86
|
+
const closeHandler = vi.fn();
|
|
87
|
+
ws.onclose = closeHandler;
|
|
88
|
+
|
|
89
|
+
ws.close();
|
|
90
|
+
|
|
91
|
+
expect(ws.readyState).toBe(WebSocket.CLOSED);
|
|
92
|
+
expect(closeHandler).toHaveBeenCalledOnce();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("close() does not throw if onclose is not set", () => {
|
|
96
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
97
|
+
ws.close();
|
|
98
|
+
expect(ws.readyState).toBe(WebSocket.CLOSED);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("onopen can be triggered externally", () => {
|
|
102
|
+
const ws = new MplCommWebSocket(vi.fn());
|
|
103
|
+
const openHandler = vi.fn();
|
|
104
|
+
ws.onopen = openHandler;
|
|
105
|
+
|
|
106
|
+
ws.onopen?.();
|
|
107
|
+
|
|
108
|
+
expect(openHandler).toHaveBeenCalledOnce();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fake WebSocket that routes messages through MarimoComm / MODEL_MANAGER
|
|
5
|
+
* instead of a real network WebSocket.
|
|
6
|
+
*
|
|
7
|
+
* mpl.js expects a WebSocket-like object with:
|
|
8
|
+
* - readyState
|
|
9
|
+
* - send(data: string)
|
|
10
|
+
* - onopen / onmessage / onclose callbacks
|
|
11
|
+
*/
|
|
12
|
+
export class MplCommWebSocket {
|
|
13
|
+
readyState: number = WebSocket.OPEN;
|
|
14
|
+
private sendFn: (msg: unknown) => void;
|
|
15
|
+
|
|
16
|
+
onopen: (() => void) | null = null;
|
|
17
|
+
onmessage: ((evt: MessageEvent) => void) | null = null;
|
|
18
|
+
onclose: (() => void) | null = null;
|
|
19
|
+
|
|
20
|
+
constructor(sendFn: (msg: unknown) => void) {
|
|
21
|
+
this.sendFn = sendFn;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Called by mpl.js to send a message to the backend.
|
|
26
|
+
* mpl.js always sends JSON strings.
|
|
27
|
+
*/
|
|
28
|
+
send(data: string): void {
|
|
29
|
+
this.sendFn(JSON.parse(data));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Called when the backend pushes a JSON message via the model custom event.
|
|
34
|
+
*/
|
|
35
|
+
receiveJson(data: unknown): void {
|
|
36
|
+
this.onmessage?.(
|
|
37
|
+
new MessageEvent("message", { data: JSON.stringify(data) }),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Called when the backend pushes binary data (PNG render) via model custom event.
|
|
43
|
+
*/
|
|
44
|
+
receiveBinary(buffer: DataView): void {
|
|
45
|
+
const ab = buffer.buffer.slice(
|
|
46
|
+
buffer.byteOffset,
|
|
47
|
+
buffer.byteOffset + buffer.byteLength,
|
|
48
|
+
) as ArrayBuffer;
|
|
49
|
+
const blob = new Blob([ab]);
|
|
50
|
+
this.onmessage?.(new MessageEvent("message", { data: blob }));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
close(): void {
|
|
54
|
+
this.readyState = WebSocket.CLOSED;
|
|
55
|
+
this.onclose?.();
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/plugins/plugins.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { MatrixPlugin } from "./impl/MatrixPlugin";
|
|
|
26
26
|
import { MicrophonePlugin } from "./impl/MicrophonePlugin";
|
|
27
27
|
import { MultiselectPlugin } from "./impl/MultiselectPlugin";
|
|
28
28
|
import { MatplotlibPlugin } from "./impl/matplotlib/MatplotlibPlugin";
|
|
29
|
+
import { MplInteractivePlugin } from "./impl/mpl-interactive/MplInteractivePlugin";
|
|
29
30
|
import { NumberPlugin } from "./impl/NumberPlugin";
|
|
30
31
|
import { PanelPlugin } from "./impl/panel/PanelPlugin";
|
|
31
32
|
import { PlotlyPlugin } from "./impl/plotly/PlotlyPlugin";
|
|
@@ -92,6 +93,7 @@ export const UI_PLUGINS: IPlugin<any, unknown>[] = [
|
|
|
92
93
|
AnyWidgetPlugin,
|
|
93
94
|
DataEditorPlugin,
|
|
94
95
|
PanelPlugin,
|
|
96
|
+
MplInteractivePlugin,
|
|
95
97
|
];
|
|
96
98
|
|
|
97
99
|
// List of output / layout plugins
|