@reactpy/client 1.0.1 → 1.0.2
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/index.js +1 -0
- package/package.json +6 -6
- package/src/bind.tsx +59 -0
- package/src/components.tsx +25 -12
- package/src/index.ts +1 -0
- package/src/types.ts +0 -1
- package/src/vdom.tsx +113 -18
- package/dist/client.d.ts +0 -29
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -60
- package/dist/client.js.map +0 -1
- package/dist/components.d.ts +0 -9
- package/dist/components.d.ts.map +0 -1
- package/dist/components.js +0 -171
- package/dist/components.js.map +0 -1
- package/dist/index.d.ts +0 -10
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -8
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -7
- package/dist/logger.js.map +0 -1
- package/dist/mount.d.ts +0 -3
- package/dist/mount.d.ts.map +0 -1
- package/dist/mount.js +0 -32
- package/dist/mount.js.map +0 -1
- package/dist/types.d.ts +0 -126
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +0 -1
- package/dist/vdom.d.ts +0 -8
- package/dist/vdom.d.ts.map +0 -1
- package/dist/vdom.js +0 -174
- package/dist/vdom.js.map +0 -1
- package/dist/websocket.d.ts +0 -6
- package/dist/websocket.d.ts.map +0 -1
- package/dist/websocket.js +0 -57
- package/dist/websocket.js.map +0 -1
- package/tsconfig.tsbuildinfo +0 -1
package/dist/index.js
CHANGED
|
@@ -6,5 +6,6 @@ export * from "./vdom";
|
|
|
6
6
|
export * from "./websocket";
|
|
7
7
|
export { default as React } from "preact/compat";
|
|
8
8
|
export { default as ReactDOM } from "preact/compat";
|
|
9
|
+
export { jsx, jsxs, Fragment } from "preact/jsx-runtime";
|
|
9
10
|
export * as preact from "preact";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"Ryan Morshead"
|
|
5
5
|
],
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"json-pointer": "
|
|
8
|
-
"preact": "
|
|
9
|
-
"event-to-object": "
|
|
7
|
+
"json-pointer": "catalog:",
|
|
8
|
+
"preact": "catalog:",
|
|
9
|
+
"event-to-object": "catalog:"
|
|
10
10
|
},
|
|
11
11
|
"description": "A client for ReactPy implemented in React",
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@types/json-pointer": "
|
|
14
|
-
"typescript": "
|
|
13
|
+
"@types/json-pointer": "catalog:",
|
|
14
|
+
"typescript": "catalog:"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
17
17
|
"react",
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"checkTypes": "tsc --noEmit"
|
|
32
32
|
},
|
|
33
33
|
"type": "module",
|
|
34
|
-
"version": "1.0.
|
|
34
|
+
"version": "1.0.2"
|
|
35
35
|
}
|
package/src/bind.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as preact from "preact";
|
|
2
|
+
|
|
3
|
+
export async function infer_bind_from_environment() {
|
|
4
|
+
try {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const React = await import("react");
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
const ReactDOM = await import("react-dom/client");
|
|
9
|
+
return (node: HTMLElement) => reactjs_bind(node, React, ReactDOM);
|
|
10
|
+
} catch {
|
|
11
|
+
console.error(
|
|
12
|
+
"Unknown error occurred: 'react' is missing within this ReactPy environment! \
|
|
13
|
+
Your JavaScript components may not work as expected!",
|
|
14
|
+
);
|
|
15
|
+
return (node: HTMLElement) => local_preact_bind(node);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function local_preact_bind(node: HTMLElement) {
|
|
20
|
+
return {
|
|
21
|
+
create: (type: any, props: any, children?: any[]) =>
|
|
22
|
+
preact.createElement(type, props, ...(children || [])),
|
|
23
|
+
render: (element: any) => {
|
|
24
|
+
preact.render(element, node);
|
|
25
|
+
},
|
|
26
|
+
unmount: () => preact.render(null, node),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const roots = new WeakMap<HTMLElement, any>();
|
|
31
|
+
|
|
32
|
+
function reactjs_bind(node: HTMLElement, React: any, ReactDOM: any) {
|
|
33
|
+
let root: any = null;
|
|
34
|
+
return {
|
|
35
|
+
create: (type: any, props: any, children?: any[]) =>
|
|
36
|
+
React.createElement(type, props, ...(children || [])),
|
|
37
|
+
render: (element: any) => {
|
|
38
|
+
if (!root) {
|
|
39
|
+
if (!roots.get(node)) {
|
|
40
|
+
root = ReactDOM.createRoot(node);
|
|
41
|
+
roots.set(node, root);
|
|
42
|
+
} else {
|
|
43
|
+
root = roots.get(node);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
root.render(element);
|
|
48
|
+
},
|
|
49
|
+
unmount: () => {
|
|
50
|
+
if (root) {
|
|
51
|
+
root.unmount();
|
|
52
|
+
if (roots.get(node) === root) {
|
|
53
|
+
roots.delete(node);
|
|
54
|
+
}
|
|
55
|
+
root = null;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
package/src/components.tsx
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { set as setJsonPointer } from "json-pointer";
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
2
|
+
import type { MutableRefObject } from "preact/compat";
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
createElement,
|
|
6
|
+
Fragment,
|
|
7
|
+
type JSX,
|
|
8
|
+
type TargetedEvent,
|
|
9
|
+
} from "preact";
|
|
4
10
|
import { useContext, useEffect, useRef, useState } from "preact/hooks";
|
|
5
11
|
import type {
|
|
6
12
|
ImportSourceBinding,
|
|
7
13
|
ReactPyComponent,
|
|
8
14
|
ReactPyVdom,
|
|
9
|
-
ReactPyClientInterface,
|
|
10
15
|
} from "./types";
|
|
11
16
|
import { createAttributes, createChildren, loadImportSource } from "./vdom";
|
|
17
|
+
import type { ReactPyClient } from "./client";
|
|
12
18
|
|
|
13
|
-
const ClientContext = createContext<
|
|
19
|
+
const ClientContext = createContext<ReactPyClient>(null as any);
|
|
14
20
|
|
|
15
|
-
export function Layout(props: { client:
|
|
21
|
+
export function Layout(props: { client: ReactPyClient }): JSX.Element {
|
|
16
22
|
const currentModel: ReactPyVdom = useState({ tagName: "" })[0];
|
|
17
23
|
const forceUpdate = useForceUpdate();
|
|
18
24
|
|
|
@@ -67,7 +73,7 @@ function StandardElement({ model }: { model: ReactPyVdom }) {
|
|
|
67
73
|
model.tagName === "" ? Fragment : model.tagName,
|
|
68
74
|
createAttributes(model, client),
|
|
69
75
|
...createChildren(model, (child) => {
|
|
70
|
-
return <Element model={child} key={child.key} />;
|
|
76
|
+
return <Element model={child} key={child.attributes?.key} />;
|
|
71
77
|
}),
|
|
72
78
|
);
|
|
73
79
|
}
|
|
@@ -82,7 +88,7 @@ function UserInputElement({ model }: { model: ReactPyVdom }): JSX.Element {
|
|
|
82
88
|
|
|
83
89
|
const givenOnChange = props.onChange;
|
|
84
90
|
if (typeof givenOnChange === "function") {
|
|
85
|
-
props.onChange = (event:
|
|
91
|
+
props.onChange = (event: TargetedEvent<any>) => {
|
|
86
92
|
// immediately update the value to give the user feedback
|
|
87
93
|
if (event.target) {
|
|
88
94
|
setValue((event.target as HTMLInputElement).value);
|
|
@@ -100,7 +106,7 @@ function UserInputElement({ model }: { model: ReactPyVdom }): JSX.Element {
|
|
|
100
106
|
// overwrite
|
|
101
107
|
{ ...props, value },
|
|
102
108
|
...createChildren(model, (child) => (
|
|
103
|
-
<Element model={child} key={child.key} />
|
|
109
|
+
<Element model={child} key={child.attributes?.key} />
|
|
104
110
|
)),
|
|
105
111
|
);
|
|
106
112
|
}
|
|
@@ -135,7 +141,7 @@ function ScriptElement({ model }: { model: ReactPyVdom }) {
|
|
|
135
141
|
return () => {
|
|
136
142
|
ref.current?.removeChild(scriptElement);
|
|
137
143
|
};
|
|
138
|
-
}, [model.key]);
|
|
144
|
+
}, [model.attributes?.key]);
|
|
139
145
|
|
|
140
146
|
return <div ref={ref} />;
|
|
141
147
|
}
|
|
@@ -175,14 +181,18 @@ function useImportSource(model: ReactPyVdom): MutableRefObject<any> {
|
|
|
175
181
|
const mountPoint = useRef<HTMLElement>(null);
|
|
176
182
|
const client = useContext(ClientContext);
|
|
177
183
|
const [binding, setBinding] = useState<ImportSourceBinding | null>(null);
|
|
184
|
+
const bindingSource = useRef<string | null>(null);
|
|
178
185
|
|
|
179
186
|
useEffect(() => {
|
|
180
187
|
let unmounted = false;
|
|
188
|
+
let currentBinding: ImportSourceBinding | null = null;
|
|
181
189
|
|
|
182
190
|
if (vdomImportSource) {
|
|
183
191
|
loadImportSource(vdomImportSource, client).then((bind) => {
|
|
184
192
|
if (!unmounted && mountPoint.current) {
|
|
185
|
-
|
|
193
|
+
currentBinding = bind(mountPoint.current);
|
|
194
|
+
bindingSource.current = vdomImportSourceJsonString;
|
|
195
|
+
setBinding(currentBinding);
|
|
186
196
|
}
|
|
187
197
|
});
|
|
188
198
|
}
|
|
@@ -190,11 +200,11 @@ function useImportSource(model: ReactPyVdom): MutableRefObject<any> {
|
|
|
190
200
|
return () => {
|
|
191
201
|
unmounted = true;
|
|
192
202
|
if (
|
|
193
|
-
|
|
203
|
+
currentBinding &&
|
|
194
204
|
vdomImportSource &&
|
|
195
205
|
!vdomImportSource.unmountBeforeUpdate
|
|
196
206
|
) {
|
|
197
|
-
|
|
207
|
+
currentBinding.unmount();
|
|
198
208
|
}
|
|
199
209
|
};
|
|
200
210
|
}, [client, vdomImportSourceJsonString, setBinding, mountPoint.current]);
|
|
@@ -204,6 +214,9 @@ function useImportSource(model: ReactPyVdom): MutableRefObject<any> {
|
|
|
204
214
|
if (!(binding && vdomImportSource)) {
|
|
205
215
|
return;
|
|
206
216
|
}
|
|
217
|
+
if (bindingSource.current !== vdomImportSourceJsonString) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
207
220
|
binding.render(model);
|
|
208
221
|
if (vdomImportSource.unmountBeforeUpdate) {
|
|
209
222
|
return binding.unmount;
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
package/src/vdom.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ReactPyClientInterface } from "./types";
|
|
2
1
|
import eventToObject from "event-to-object";
|
|
2
|
+
import { Fragment } from "preact";
|
|
3
3
|
import type {
|
|
4
4
|
ReactPyVdom,
|
|
5
5
|
ReactPyVdomImportSource,
|
|
@@ -7,12 +7,15 @@ import type {
|
|
|
7
7
|
ReactPyModule,
|
|
8
8
|
BindImportSource,
|
|
9
9
|
ReactPyModuleBinding,
|
|
10
|
+
ImportSourceBinding,
|
|
10
11
|
} from "./types";
|
|
12
|
+
import { infer_bind_from_environment } from "./bind";
|
|
11
13
|
import log from "./logger";
|
|
14
|
+
import type { ReactPyClient } from "./client";
|
|
12
15
|
|
|
13
16
|
export async function loadImportSource(
|
|
14
17
|
vdomImportSource: ReactPyVdomImportSource,
|
|
15
|
-
client:
|
|
18
|
+
client: ReactPyClient,
|
|
16
19
|
): Promise<BindImportSource> {
|
|
17
20
|
let module: ReactPyModule;
|
|
18
21
|
if (vdomImportSource.sourceType === "URL") {
|
|
@@ -20,14 +23,14 @@ export async function loadImportSource(
|
|
|
20
23
|
} else {
|
|
21
24
|
module = await client.loadModule(vdomImportSource.source);
|
|
22
25
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
26
|
+
|
|
27
|
+
let { bind } = module;
|
|
28
|
+
if (typeof bind !== "function") {
|
|
29
|
+
bind = await infer_bind_from_environment();
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
return (node: HTMLElement) => {
|
|
30
|
-
const binding =
|
|
33
|
+
const binding = bind(node, {
|
|
31
34
|
sendMessage: client.sendMessage,
|
|
32
35
|
onMessage: client.onMessage,
|
|
33
36
|
});
|
|
@@ -59,7 +62,7 @@ export async function loadImportSource(
|
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
function createImportSourceElement(props: {
|
|
62
|
-
client:
|
|
65
|
+
client: ReactPyClient;
|
|
63
66
|
module: ReactPyModule;
|
|
64
67
|
binding: ReactPyModuleBinding;
|
|
65
68
|
model: ReactPyVdom;
|
|
@@ -70,13 +73,15 @@ function createImportSourceElement(props: {
|
|
|
70
73
|
if (
|
|
71
74
|
!isImportSourceEqual(props.currentImportSource, props.model.importSource)
|
|
72
75
|
) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
return props.binding.create("reactpy-child", {
|
|
77
|
+
ref: (node: ReactPyChild | null) => {
|
|
78
|
+
if (node) {
|
|
79
|
+
node.client = props.client;
|
|
80
|
+
node.model = props.model;
|
|
81
|
+
node.requestUpdate();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
80
85
|
} else {
|
|
81
86
|
type = getComponentFromModule(
|
|
82
87
|
props.module,
|
|
@@ -89,7 +94,7 @@ function createImportSourceElement(props: {
|
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
96
|
} else {
|
|
92
|
-
type = props.model.tagName;
|
|
97
|
+
type = props.model.tagName === "" ? Fragment : props.model.tagName;
|
|
93
98
|
}
|
|
94
99
|
return props.binding.create(
|
|
95
100
|
type,
|
|
@@ -176,7 +181,7 @@ export function createChildren<Child>(
|
|
|
176
181
|
|
|
177
182
|
export function createAttributes(
|
|
178
183
|
model: ReactPyVdom,
|
|
179
|
-
client:
|
|
184
|
+
client: ReactPyClient,
|
|
180
185
|
): { [key: string]: any } {
|
|
181
186
|
return Object.fromEntries(
|
|
182
187
|
Object.entries({
|
|
@@ -199,7 +204,7 @@ export function createAttributes(
|
|
|
199
204
|
}
|
|
200
205
|
|
|
201
206
|
function createEventHandler(
|
|
202
|
-
client:
|
|
207
|
+
client: ReactPyClient,
|
|
203
208
|
name: string,
|
|
204
209
|
{ target, preventDefault, stopPropagation }: ReactPyVdomEventHandler,
|
|
205
210
|
): [string, () => void] {
|
|
@@ -254,3 +259,93 @@ function createInlineJavaScript(
|
|
|
254
259
|
wrappedExecutable.isHandler = false;
|
|
255
260
|
return [name, wrappedExecutable];
|
|
256
261
|
}
|
|
262
|
+
|
|
263
|
+
class ReactPyChild extends HTMLElement {
|
|
264
|
+
mountPoint: HTMLDivElement;
|
|
265
|
+
binding: ImportSourceBinding | null = null;
|
|
266
|
+
_client: ReactPyClient | null = null;
|
|
267
|
+
_model: ReactPyVdom | null = null;
|
|
268
|
+
currentImportSource: ReactPyVdomImportSource | null = null;
|
|
269
|
+
|
|
270
|
+
constructor() {
|
|
271
|
+
super();
|
|
272
|
+
this.mountPoint = document.createElement("div");
|
|
273
|
+
this.mountPoint.style.display = "contents";
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
connectedCallback() {
|
|
277
|
+
this.appendChild(this.mountPoint);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
set client(value: ReactPyClient) {
|
|
281
|
+
this._client = value;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
set model(value: ReactPyVdom) {
|
|
285
|
+
this._model = value;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
requestUpdate() {
|
|
289
|
+
this.update();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async update() {
|
|
293
|
+
if (!this._client || !this._model || !this._model.importSource) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const newImportSource = this._model.importSource;
|
|
298
|
+
|
|
299
|
+
if (
|
|
300
|
+
!this.binding ||
|
|
301
|
+
!this.currentImportSource ||
|
|
302
|
+
!isImportSourceEqual(this.currentImportSource, newImportSource)
|
|
303
|
+
) {
|
|
304
|
+
if (this.binding) {
|
|
305
|
+
this.binding.unmount();
|
|
306
|
+
this.binding = null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.currentImportSource = newImportSource;
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
const bind = await loadImportSource(newImportSource, this._client);
|
|
313
|
+
if (
|
|
314
|
+
this.isConnected &&
|
|
315
|
+
this.currentImportSource &&
|
|
316
|
+
isImportSourceEqual(this.currentImportSource, newImportSource)
|
|
317
|
+
) {
|
|
318
|
+
const oldBinding = this.binding as ImportSourceBinding | null;
|
|
319
|
+
if (oldBinding) {
|
|
320
|
+
oldBinding.unmount();
|
|
321
|
+
}
|
|
322
|
+
this.binding = bind(this.mountPoint);
|
|
323
|
+
if (this.binding) {
|
|
324
|
+
this.binding.render(this._model);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.error("Failed to load import source", error);
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
if (this.binding) {
|
|
332
|
+
this.binding.render(this._model);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
disconnectedCallback() {
|
|
338
|
+
if (this.binding) {
|
|
339
|
+
this.binding.unmount();
|
|
340
|
+
this.binding = null;
|
|
341
|
+
this.currentImportSource = null;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (
|
|
347
|
+
typeof customElements !== "undefined" &&
|
|
348
|
+
!customElements.get("reactpy-child")
|
|
349
|
+
) {
|
|
350
|
+
customElements.define("reactpy-child", ReactPyChild);
|
|
351
|
+
}
|
package/dist/client.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { ReactPyClientInterface, ReactPyModule, GenericReactPyClientProps, ReactPyUrls } from "./types";
|
|
2
|
-
export declare abstract class BaseReactPyClient implements ReactPyClientInterface {
|
|
3
|
-
private readonly handlers;
|
|
4
|
-
protected readonly ready: Promise<void>;
|
|
5
|
-
private resolveReady;
|
|
6
|
-
constructor();
|
|
7
|
-
onMessage(type: string, handler: (message: any) => void): () => void;
|
|
8
|
-
abstract sendMessage(message: any): void;
|
|
9
|
-
abstract loadModule(moduleName: string): Promise<ReactPyModule>;
|
|
10
|
-
/**
|
|
11
|
-
* Handle an incoming message.
|
|
12
|
-
*
|
|
13
|
-
* This should be called by subclasses when a message is received.
|
|
14
|
-
*
|
|
15
|
-
* @param message The message to handle. The message must have a `type` property.
|
|
16
|
-
*/
|
|
17
|
-
protected handleIncoming(message: any): void;
|
|
18
|
-
}
|
|
19
|
-
export declare class ReactPyClient extends BaseReactPyClient implements ReactPyClientInterface {
|
|
20
|
-
urls: ReactPyUrls;
|
|
21
|
-
socket: {
|
|
22
|
-
current?: WebSocket;
|
|
23
|
-
};
|
|
24
|
-
mountElement: HTMLElement;
|
|
25
|
-
constructor(props: GenericReactPyClientProps);
|
|
26
|
-
sendMessage(message: any): void;
|
|
27
|
-
loadModule(moduleName: string): Promise<ReactPyModule>;
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,aAAa,EACb,yBAAyB,EACzB,WAAW,EACZ,MAAM,SAAS,CAAC;AAGjB,8BAAsB,iBAAkB,YAAW,sBAAsB;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqD;IAC9E,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,YAAY,CAA6B;;IAOjD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI;IAQpE,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IACxC,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAE/D;;;;;;OAMG;IACH,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;CAe7C;AAED,qBAAa,aACX,SAAQ,iBACR,YAAW,sBAAsB;IAEjC,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IAChC,YAAY,EAAE,WAAW,CAAC;gBAEd,KAAK,EAAE,yBAAyB;IAa5C,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAI/B,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CAGvD"}
|
package/dist/client.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import logger from "./logger";
|
|
2
|
-
import { createReconnectingWebSocket } from "./websocket";
|
|
3
|
-
export class BaseReactPyClient {
|
|
4
|
-
handlers = {};
|
|
5
|
-
ready;
|
|
6
|
-
resolveReady;
|
|
7
|
-
constructor() {
|
|
8
|
-
this.resolveReady = () => { };
|
|
9
|
-
this.ready = new Promise((resolve) => (this.resolveReady = resolve));
|
|
10
|
-
}
|
|
11
|
-
onMessage(type, handler) {
|
|
12
|
-
(this.handlers[type] || (this.handlers[type] = [])).push(handler);
|
|
13
|
-
this.resolveReady(undefined);
|
|
14
|
-
return () => {
|
|
15
|
-
this.handlers[type] = this.handlers[type].filter((h) => h !== handler);
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Handle an incoming message.
|
|
20
|
-
*
|
|
21
|
-
* This should be called by subclasses when a message is received.
|
|
22
|
-
*
|
|
23
|
-
* @param message The message to handle. The message must have a `type` property.
|
|
24
|
-
*/
|
|
25
|
-
handleIncoming(message) {
|
|
26
|
-
if (!message.type) {
|
|
27
|
-
logger.warn("Received message without type", message);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const messageHandlers = this.handlers[message.type];
|
|
31
|
-
if (!messageHandlers) {
|
|
32
|
-
logger.warn("Received message without handler", message);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
messageHandlers.forEach((h) => h(message));
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export class ReactPyClient extends BaseReactPyClient {
|
|
39
|
-
urls;
|
|
40
|
-
socket;
|
|
41
|
-
mountElement;
|
|
42
|
-
constructor(props) {
|
|
43
|
-
super();
|
|
44
|
-
this.urls = props.urls;
|
|
45
|
-
this.mountElement = props.mountElement;
|
|
46
|
-
this.socket = createReconnectingWebSocket({
|
|
47
|
-
url: this.urls.componentUrl,
|
|
48
|
-
readyPromise: this.ready,
|
|
49
|
-
...props.reconnectOptions,
|
|
50
|
-
onMessage: async ({ data }) => this.handleIncoming(JSON.parse(data)),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
sendMessage(message) {
|
|
54
|
-
this.socket.current?.send(JSON.stringify(message));
|
|
55
|
-
}
|
|
56
|
-
loadModule(moduleName) {
|
|
57
|
-
return import(`${this.urls.jsModulesPath}${moduleName}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,UAAU,CAAC;AAO9B,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,OAAgB,iBAAiB;IACpB,QAAQ,GAAkD,EAAE,CAAC;IAC3D,KAAK,CAAgB;IAChC,YAAY,CAA6B;IAEjD;QACE,IAAI,CAAC,YAAY,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,OAA+B;QACrD,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;QACzE,CAAC,CAAC;IACJ,CAAC;IAKD;;;;;;OAMG;IACO,cAAc,CAAC,OAAY;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,OAAO,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,OAAO,aACX,SAAQ,iBAAiB;IAGzB,IAAI,CAAc;IAClB,MAAM,CAA0B;IAChC,YAAY,CAAc;IAE1B,YAAY,KAAgC;QAC1C,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,2BAA2B,CAAC;YACxC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY;YAC3B,YAAY,EAAE,IAAI,CAAC,KAAK;YACxB,GAAG,KAAK,CAAC,gBAAgB;YACzB,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACrE,CAAC,CAAC;IACL,CAAC;IAED,WAAW,CAAC,OAAY;QACtB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,UAAU,CAAC,UAAkB;QAC3B,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;CACF"}
|
package/dist/components.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type JSX } from "preact";
|
|
2
|
-
import type { ReactPyVdom, ReactPyClientInterface } from "./types";
|
|
3
|
-
export declare function Layout(props: {
|
|
4
|
-
client: ReactPyClientInterface;
|
|
5
|
-
}): JSX.Element;
|
|
6
|
-
export declare function Element({ model }: {
|
|
7
|
-
model: ReactPyVdom;
|
|
8
|
-
}): JSX.Element | null;
|
|
9
|
-
//# sourceMappingURL=components.d.ts.map
|
package/dist/components.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/components.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA0C,KAAK,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE1E,OAAO,KAAK,EAGV,WAAW,EACX,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAKjB,wBAAgB,MAAM,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,sBAAsB,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAsB7E;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAoB7E"}
|