@reactpy/client 1.0.0 → 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 CHANGED
@@ -6,4 +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";
10
+ export * as preact from "preact";
9
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": "^0.6.2",
8
- "preact": "^10.27.2",
9
- "event-to-object": "file:./packages/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": "^1.0.34",
14
- "typescript": "^5.9.3"
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.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/client.ts CHANGED
@@ -69,7 +69,7 @@ export class ReactPyClient
69
69
  url: this.urls.componentUrl,
70
70
  readyPromise: this.ready,
71
71
  ...props.reconnectOptions,
72
- onMessage: (event) => this.handleIncoming(JSON.parse(event.data)),
72
+ onMessage: async ({ data }) => this.handleIncoming(JSON.parse(data)),
73
73
  });
74
74
  }
75
75
 
@@ -1,18 +1,24 @@
1
1
  import { set as setJsonPointer } from "json-pointer";
2
- import type { ChangeEvent, MutableRefObject } from "preact/compat";
3
- import { createContext, createElement, Fragment, type JSX } from "preact";
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<ReactPyClientInterface>(null as any);
19
+ const ClientContext = createContext<ReactPyClient>(null as any);
14
20
 
15
- export function Layout(props: { client: ReactPyClientInterface }): JSX.Element {
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: ChangeEvent<any>) => {
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
- setBinding(bind(mountPoint.current));
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
- binding &&
203
+ currentBinding &&
194
204
  vdomImportSource &&
195
205
  !vdomImportSource.unmountBeforeUpdate
196
206
  ) {
197
- binding.unmount();
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
@@ -6,3 +6,5 @@ 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";
10
+ export * as preact from "preact";
package/src/types.ts CHANGED
@@ -48,7 +48,6 @@ export type ReactPyComponent = ComponentType<{ model: ReactPyVdom }>;
48
48
 
49
49
  export type ReactPyVdom = {
50
50
  tagName: string;
51
- key?: string;
52
51
  attributes?: { [key: string]: string };
53
52
  children?: (ReactPyVdom | string)[];
54
53
  error?: string;
package/src/vdom.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import type { ReactPyClientInterface } from "./types";
2
- import serializeEvent from "event-to-object";
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: ReactPyClientInterface,
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
- if (typeof module.bind !== "function") {
24
- throw new Error(
25
- `${vdomImportSource.source} did not export a function 'bind'`,
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 = module.bind(node, {
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: ReactPyClientInterface;
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
- log.error(
74
- "Parent element import source " +
75
- stringifyImportSource(props.currentImportSource) +
76
- " does not match child's import source " +
77
- stringifyImportSource(props.model.importSource),
78
- );
79
- return null;
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: ReactPyClientInterface,
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: ReactPyClientInterface,
207
+ client: ReactPyClient,
203
208
  name: string,
204
209
  { target, preventDefault, stopPropagation }: ReactPyVdomEventHandler,
205
210
  ): [string, () => void] {
@@ -212,7 +217,13 @@ function createEventHandler(
212
217
  if (stopPropagation) {
213
218
  event.stopPropagation();
214
219
  }
215
- return serializeEvent(event);
220
+
221
+ // Convert JavaScript objects to plain JSON, if needed
222
+ if (typeof event === "object") {
223
+ return eventToObject(event);
224
+ } else {
225
+ return event;
226
+ }
216
227
  });
217
228
  client.sendMessage({ type: "layout-event", data, target });
218
229
  };
@@ -248,3 +259,93 @@ function createInlineJavaScript(
248
259
  wrappedExecutable.isHandler = false;
249
260
  return [name, wrappedExecutable];
250
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
@@ -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: (event) => this.handleIncoming(JSON.parse(event.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
@@ -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,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClE,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"}
@@ -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
@@ -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"}