Skip to content

Commit f338572

Browse files
committed
generalize client layout interface
this will allow the upcoming idom-widget package to more easily work with it
1 parent f5f60a1 commit f338572

File tree

4 files changed

+49
-39
lines changed

4 files changed

+49
-39
lines changed

idom/client/static/core_modules/layout.js

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import * as react from "react";
32
import * as reactDOM from "react-dom";
43
import htm from "htm";
@@ -9,13 +8,7 @@ import serializeEvent from "./event-to-object";
98
const html = htm.bind(react.createElement);
109
const alreadyImported = {};
1110

12-
export function renderLayout(mountElement, endpoint) {
13-
const cmpt = html`<${Layout} endpoint=${endpoint} />`;
14-
return reactDOM.render(cmpt, mountElement);
15-
}
16-
17-
export default function Layout({ endpoint }) {
18-
// handle relative endpoint URI
11+
export function mountLayoutWithWebSocket(mountElement, endpoint) {
1912
if (endpoint.startsWith(".") || endpoint.startsWith("/")) {
2013
let loc = window.location;
2114
let protocol;
@@ -31,36 +24,53 @@ export default function Layout({ endpoint }) {
3124
endpoint = new_uri + endpoint;
3225
}
3326

34-
const socket = react.useMemo(() => new WebSocket(endpoint), [endpoint]);
35-
const [state, setState] = react.useState({ model: {} });
36-
37-
socket.onmessage = (event) => {
38-
const [pathPrefix, patch] = JSON.parse(event.data);
39-
setState({
40-
model: jsonpatch.applyPatch(
41-
state.model,
42-
patch.map((op) => {
43-
op.path = pathPrefix + op.path;
44-
return op;
45-
}),
46-
undefined,
47-
false
48-
).newDocument,
49-
});
50-
};
27+
const ws = new WebSocket(endpoint);
5128

52-
const sendMsg = (msg) => {
53-
socket.send(JSON.stringify(msg));
54-
};
55-
const sendEvent = (event) => {
56-
sendMsg({
57-
header: {},
58-
body: { event: event },
29+
function registerUpdateCallback(update) {
30+
ws.onmessage = (event) => {
31+
const [pathPrefix, patch] = JSON.parse(event.data);
32+
update(pathPrefix, patch);
33+
};
34+
}
35+
36+
function sendCallback(event) {
37+
ws.send(
38+
JSON.stringify({
39+
header: {},
40+
body: { event: event },
41+
})
42+
);
43+
}
44+
45+
const cmpt = html`<${Layout}
46+
registerUpdateCallback=${registerUpdateCallback}
47+
sendCallback=${sendCallback}
48+
/>`;
49+
50+
return reactDOM.render(cmpt, mountElement);
51+
}
52+
53+
export default function Layout({ registerUpdateCallback, sendCallback }) {
54+
const [model, setModel] = react.useState({});
55+
56+
react.useEffect(() => {
57+
registerUpdateCallback((pathPrefix, patch) => {
58+
setModel(
59+
jsonpatch.applyPatch(
60+
model,
61+
patch.map((op) => {
62+
op.path = pathPrefix + op.path;
63+
return op;
64+
}),
65+
undefined,
66+
false
67+
).newDocument
68+
);
5969
});
60-
};
70+
}, [model]);
6171

62-
if (state.model.tagName) {
63-
return html`<${Element} sendEvent=${sendEvent} model=${state.model} />`;
72+
if (model.tagName) {
73+
return html`<${Element} sendEvent=${sendCallback} model=${model} />`;
6474
} else {
6575
return html`<div />`;
6676
}

idom/client/static/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<body>
99
<div id="app"></div>
1010
<script type="module">
11-
import { renderLayout } from "./core_modules/layout.js";
11+
import { mountLayoutWithWebSocket } from "./core_modules/layout.js";
1212

1313
const uri = document.location.hostname + ":" + document.location.port;
1414
const url = (uri + document.location.pathname).split("/").slice(0, -1);
@@ -24,7 +24,7 @@
2424

2525
let endpoint = protocol + "//" + url.join("/") + window.location.search;
2626

27-
renderLayout(document.getElementById("app"), endpoint);
27+
mountLayoutWithWebSocket(document.getElementById("app"), endpoint);
2828
</script>
2929
</body>
3030
</html>

idom/client/static/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

idom/widgets/jupyter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def _script(self, mount_id: str) -> str:
8080
fetch(http_proto + idom_url, {{mode: "no-cors"}}).then(rsp => {{
8181
import(http_proto + idom_url + "/client/core_modules/layout.js").then(
8282
(module) => {{
83-
module.renderLayout(
83+
module.mountLayoutWithWebSocket(
8484
document.getElementById("{mount_id}"),
8585
ws_proto + idom_url + "/stream?{self.query}"
8686
);

0 commit comments

Comments
 (0)