@reactpy/client 1.1.0 → 1.3.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/dist/vdom.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vdom.js","sourceRoot":"","sources":["../src/vdom.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vdom.js","sourceRoot":"","sources":["../src/vdom.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAGhE,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,gCAAgC;cAOb,SAAS;EAkDpC;AAED,wBAAgB,YAAY,CAC1B,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,MAAM,CAOR"}
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAgBhE,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,gCAAgC;cAOb,SAAS;EAmDpC;AAED,wBAAgB,YAAY,CAC1B,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,MAAM,CAOR"}
package/dist/websocket.js CHANGED
@@ -1,4 +1,16 @@
1
1
  import log from "./logger";
2
+ function syncBrowserLocation(url) {
3
+ // The window will always have a HTTP path, so ReactPy should always be aware of it.
4
+ url.searchParams.set("path", window.location.pathname);
5
+ if (window.location.search) {
6
+ // Set the query string parameter if the HTTP location has a query string.
7
+ url.searchParams.set("qs", window.location.search);
8
+ }
9
+ else {
10
+ // Remove any existing (potentially stale) query string parameter if the current location doesn't have one
11
+ url.searchParams.delete("qs");
12
+ }
13
+ }
2
14
  export function createReconnectingWebSocket(props) {
3
15
  const { interval, maxInterval, maxRetries, backoffMultiplier } = props;
4
16
  let retries = 0;
@@ -10,6 +22,7 @@ export function createReconnectingWebSocket(props) {
10
22
  if (closed) {
11
23
  return;
12
24
  }
25
+ syncBrowserLocation(props.url);
13
26
  socket.current = new WebSocket(props.url);
14
27
  socket.current.onopen = () => {
15
28
  everConnected = true;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,UAAU,2BAA2B,CACzC,KAAuC;IAEvC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;IACvE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,eAAe,GAAG,QAAQ,CAAC;IAC/B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,MAAM,MAAM,GAAG,KAAK,CAAC;IACrB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,MAAM,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;YAC3B,aAAa,GAAG,IAAI,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACvB,eAAe,GAAG,QAAQ,CAAC;YAC3B,OAAO,GAAG,CAAC,CAAC;YACZ,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;YACnC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE;YAC5B,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClB,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;YACD,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAC/B,OAAO;YACT,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC1B,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;gBAC9C,OAAO;YACT,CAAC;YACD,GAAG,CAAC,IAAI,CACN,mBAAmB,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CACxE,CAAC;YACF,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;YACrC,eAAe,GAAG,YAAY,CAC5B,eAAe,EACf,iBAAiB,EACjB,WAAW,CACZ,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,eAAuB,EACvB,iBAAyB,EACzB,WAAmB;IAEnB,OAAO,IAAI,CAAC,GAAG;IACb,0CAA0C;IAC1C,eAAe,GAAG,iBAAiB;IACnC,4BAA4B;IAC5B,WAAW,CACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -36,5 +36,5 @@
36
36
  "checkTypes": "tsc --noEmit"
37
37
  },
38
38
  "type": "module",
39
- "version": "1.1.0"
39
+ "version": "1.3.0"
40
40
  }
@@ -8,6 +8,13 @@ import {
8
8
  type TargetedEvent,
9
9
  } from "preact";
10
10
  import { useContext, useEffect, useRef, useState } from "preact/hooks";
11
+ import {
12
+ HANDLER_DEBOUNCE,
13
+ HANDLER_MARKER,
14
+ HANDLER_THROTTLE,
15
+ isValidDebounce,
16
+ type TaggedEventHandler,
17
+ } from "./handler";
11
18
  import type {
12
19
  ImportSourceBinding,
13
20
  ReactPyComponent,
@@ -18,6 +25,117 @@ import type { ReactPyClient } from "./client";
18
25
 
19
26
  const ClientContext = createContext<ReactPyClient>(null as any);
20
27
 
28
+ /**
29
+ * Wrap ``handler`` so its outgoing call is throttled to at most once per
30
+ * ``intervalMs`` milliseconds. Subsequent calls inside the window are
31
+ * collapsed and the trailing call (with the most recent arguments) fires
32
+ * once the window expires.
33
+ *
34
+ * Returns the original handler unchanged when ``intervalMs`` is missing or
35
+ * invalid.
36
+ */
37
+ function throttleHandler(
38
+ handler: TaggedEventHandler,
39
+ intervalMs: number,
40
+ ): TaggedEventHandler {
41
+ if (!isValidDebounce(intervalMs)) {
42
+ return handler;
43
+ }
44
+ let pendingArgs: any[] | null = null;
45
+ let timer: number | null = null;
46
+ let lastFireTime = 0;
47
+
48
+ const wrapped = function (...args: any[]) {
49
+ const now = Date.now();
50
+ const elapsed = now - lastFireTime;
51
+ if (elapsed >= intervalMs) {
52
+ // Leading edge: fire immediately, then start a cooldown.
53
+ lastFireTime = now;
54
+ (handler as (...a: any[]) => void)(...args);
55
+ return;
56
+ }
57
+ // Trailing edge: remember the latest args and schedule a fire at the
58
+ // end of the cooldown so no event is silently dropped.
59
+ pendingArgs = args;
60
+ if (timer === null) {
61
+ timer = window.setTimeout(
62
+ () => {
63
+ timer = null;
64
+ if (pendingArgs !== null) {
65
+ const callArgs = pendingArgs;
66
+ pendingArgs = null;
67
+ lastFireTime = Date.now();
68
+ (handler as (...a: any[]) => void)(...callArgs);
69
+ }
70
+ },
71
+ Math.max(0, intervalMs - elapsed),
72
+ );
73
+ }
74
+ } as TaggedEventHandler;
75
+
76
+ // Preserve the tag markers so downstream code can still introspect the
77
+ // wrapped function.
78
+ wrapped[HANDLER_MARKER] = true;
79
+ const debounce = handler[HANDLER_DEBOUNCE];
80
+ if (typeof debounce === "number") {
81
+ wrapped[HANDLER_DEBOUNCE] = debounce;
82
+ }
83
+ return wrapped;
84
+ }
85
+
86
+ /**
87
+ * Wrap ``handler`` so its outgoing call is debounced by
88
+ * ``delayMs`` milliseconds. The first call schedules a fire after
89
+ * the delay; subsequent calls inside the window reset the timer and
90
+ * pass their arguments to the trailing call. Only one call lands
91
+ * on the wrapped handler per debounce window.
92
+ *
93
+ * Returns the original handler unchanged when ``delayMs`` is missing
94
+ * or invalid, so callers can pass a 0 / negative value to opt out.
95
+ *
96
+ * Unlike ``throttleHandler`` (which fires on the leading edge),
97
+ * this strictly trailing-edge debounce is the right semantics for
98
+ * text inputs: the server only sees the final state after the user
99
+ * pauses typing, which is exactly when the reconcile can safely apply
100
+ * a server-side transformation (normalisation, validation, etc.).
101
+ */
102
+ function debounceHandler(
103
+ handler: TaggedEventHandler,
104
+ delayMs: number,
105
+ ): TaggedEventHandler {
106
+ if (!isValidDebounce(delayMs) || delayMs === 0) {
107
+ return handler;
108
+ }
109
+ let timer: number | null = null;
110
+ let pendingArgs: any[] | null = null;
111
+
112
+ const wrapped = function (...args: any[]) {
113
+ pendingArgs = args;
114
+ if (timer !== null) {
115
+ window.clearTimeout(timer);
116
+ }
117
+ timer = window.setTimeout(() => {
118
+ timer = null;
119
+ if (pendingArgs !== null) {
120
+ const callArgs = pendingArgs;
121
+ pendingArgs = null;
122
+ (handler as (...a: any[]) => void)(...callArgs);
123
+ }
124
+ }, delayMs);
125
+ } as TaggedEventHandler;
126
+
127
+ // Preserve the tag markers so downstream code can still introspect
128
+ // the wrapped function.
129
+ wrapped[HANDLER_MARKER] = true;
130
+ if (typeof handler[HANDLER_THROTTLE] === "number") {
131
+ wrapped[HANDLER_THROTTLE] = handler[HANDLER_THROTTLE];
132
+ }
133
+ if (typeof handler[HANDLER_DEBOUNCE] === "number") {
134
+ wrapped[HANDLER_DEBOUNCE] = handler[HANDLER_DEBOUNCE];
135
+ }
136
+ return wrapped;
137
+ }
138
+
21
139
  export function Layout(props: { client: ReactPyClient }): JSX.Element {
22
140
  const currentModel: ReactPyVdom = useState({ tagName: "" })[0];
23
141
  const forceUpdate = useForceUpdate();
@@ -66,12 +184,32 @@ export function Element({ model }: { model: ReactPyVdom }): JSX.Element | null {
66
184
 
67
185
  function StandardElement({ model }: { model: ReactPyVdom }) {
68
186
  const client = useContext(ClientContext);
187
+ const attrs = createAttributes(model, client);
188
+ // Apply the throttle wrapper to tagged handlers. ``throttle`` works on
189
+ // every element; ``debounce`` is intentionally only applied by
190
+ // ``UserInputElement`` (the only place where coalescing keystrokes
191
+ // is meaningful — click handlers don't benefit from trailing-edge
192
+ // coalescing, and applying debounce here would just delay
193
+ // non-input events for no reason).
194
+ for (const [name, prop] of Object.entries(attrs)) {
195
+ if (typeof prop !== "function") {
196
+ continue;
197
+ }
198
+ const handler = prop as TaggedEventHandler;
199
+ if (!handler[HANDLER_MARKER]) {
200
+ continue;
201
+ }
202
+ const throttle = handler[HANDLER_THROTTLE];
203
+ if (isValidDebounce(throttle)) {
204
+ attrs[name] = throttleHandler(handler, throttle as number);
205
+ }
206
+ }
69
207
  // Use createElement here to avoid warning about variable numbers of children not
70
208
  // having keys. Warning about this must now be the responsibility of the client
71
209
  // providing the models instead of the client rendering them.
72
210
  return createElement(
73
211
  model.tagName === "" ? Fragment : model.tagName,
74
- createAttributes(model, client),
212
+ attrs,
75
213
  ...createChildren(model, (child) => {
76
214
  return <Element model={child} key={child.attributes?.key} />;
77
215
  }),
@@ -81,30 +219,195 @@ function StandardElement({ model }: { model: ReactPyVdom }) {
81
219
  function UserInputElement({ model }: { model: ReactPyVdom }): JSX.Element {
82
220
  const client = useContext(ClientContext);
83
221
  const props = createAttributes(model, client);
84
- const [value, setValue] = useState(props.value);
222
+ // ``_reactpy_ack_seq`` is set by the server to the highest sequence
223
+ // number it has received from this element's event handlers. We use
224
+ // it (instead of a time-based debounce) to decide whether the server
225
+ // has caught up to the user's keystrokes.
226
+ const serverAckSeq =
227
+ typeof model.attributes?.["_reactpy_ack_seq"] === "number"
228
+ ? (model.attributes["_reactpy_ack_seq"] as number)
229
+ : -1;
230
+ // Strip the internal key from props so it never reaches the DOM.
231
+ delete (props as Record<string, unknown>)["_reactpy_ack_seq"];
232
+
233
+ const [, setValue] = useState(props.value);
234
+ // Reference to the underlying DOM element. We read its current
235
+ // ``value`` from the reconcile effect to compare against the
236
+ // server's proposed value — reading from Preact state is not
237
+ // enough because the browser mutates the DOM directly between
238
+ // renders (especially during fast typing).
239
+ const inputRef = useRef<
240
+ HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | null
241
+ >(null);
242
+ // Per-element (NOT per-handler) monotonic counter for outgoing
243
+ // events. The wrapper below installs this counter onto every
244
+ // handler via ``_reactpy_set_seq`` so the counter survives
245
+ // handler recreation on every server re-render. Each handler
246
+ // has its own per-handler ``outgoingSeq`` (used as the default
247
+ // when no wrapper is installed), but we override it here so the
248
+ // element owns a single monotonic counter across handlers.
249
+ const sharedOutgoingSeq = useRef(0);
250
+ // Highest sequence number actually sent. The server's
251
+ // ``_reactpy_ack_seq`` will catch up to this. ``sharedOutgoingSeq``
252
+ // is incremented optimistically in the wrapper; ``lastSentSeq``
253
+ // is the high-water mark.
254
+ const lastSentSeq = useRef(-1);
85
255
 
86
256
  // honor changes to value from the client via props
87
- useEffect(() => setValue(props.value), [props.value]);
88
-
89
- const givenOnChange = props.onChange;
90
- if (typeof givenOnChange === "function") {
91
- props.onChange = (event: TargetedEvent<any>) => {
92
- // immediately update the value to give the user feedback
93
- if (event.target) {
94
- setValue((event.target as HTMLInputElement).value);
257
+ useEffect(() => {
258
+ // The sequence number is the single source of truth for whether
259
+ // to apply the server's value. Time-based heuristics (debounce
260
+ // windows, submit-event detection) are not used here because they
261
+ // cannot reliably distinguish a server snapshot from before some
262
+ // keystrokes were processed from a snapshot taken after all
263
+ // keystrokes were processed. The sequence number can,
264
+ // deterministically.
265
+ //
266
+ // If the server has acknowledged every event the user has sent
267
+ // (``serverAckSeq >= lastSentSeq.current``), the server's value
268
+ // is the authoritative one and is applied directly. This
269
+ // includes clears (Enter handlers that reset the input),
270
+ // normalizations, and same-value confirmations.
271
+ // If the server is behind, its value is necessarily a stale
272
+ // snapshot and is ignored; the next layout-update will be
273
+ // applied once the server catches up.
274
+ //
275
+ // We additionally compare against the DOM's actual current
276
+ // value via ``inputRef`` — when the server is supposedly
277
+ // caught up but its snapshot is shorter than what the user
278
+ // has in the DOM (a stale snapshot racing with the user's
279
+ // most recent keystroke), skip applying so we don't clobber
280
+ // the user's text. This handles the realistic case where the
281
+ // user types faster than the server can ack.
282
+ if (serverAckSeq < lastSentSeq.current) {
283
+ return;
284
+ }
285
+ // Apply server's value to the DOM directly via the ref, NOT
286
+ // through Preact's render path. Preact would otherwise set
287
+ // ``inputRef.current.value`` on every render, racing with the
288
+ // browser's own mutations of the DOM value during fast typing
289
+ // and silently dropping keystrokes. By using a ref and writing
290
+ // only when we know the server has caught up, we let the
291
+ // browser manage the DOM value during typing and only override
292
+ // it when it's safe to do so.
293
+ //
294
+ // Crucially, only write when ``props.value`` is a real string.
295
+ // Inputs without a ``value`` attribute in their VDOM (e.g.
296
+ // uncontrolled inputs in the user_data and channel_layer tests)
297
+ // arrive with ``props.value === undefined``; assigning
298
+ // ``input.value = undefined`` coerces to the literal string
299
+ // ``"undefined"`` and seeds the field with garbage that the
300
+ // user's first keystroke will then append to (``test`` becomes
301
+ // ``testundefined``). Skipping the write in that case leaves
302
+ // the DOM at its default empty value, which is what the user
303
+ // actually typed into.
304
+ if (
305
+ inputRef.current &&
306
+ typeof inputRef.current.value === "string" &&
307
+ typeof props.value === "string" &&
308
+ inputRef.current.value !== props.value
309
+ ) {
310
+ inputRef.current.value = props.value;
311
+ }
312
+ setValue(props.value);
313
+ }, [props.value, serverAckSeq]);
314
+
315
+ for (const [name, prop] of Object.entries(props)) {
316
+ if (typeof prop !== "function") {
317
+ continue;
318
+ }
319
+
320
+ const givenHandler = prop as TaggedEventHandler;
321
+ if (!givenHandler[HANDLER_MARKER]) {
322
+ continue;
323
+ }
324
+
325
+ // Apply ``throttle`` and/or ``debounce`` wrappers when the
326
+ // handler opts into them. Throttle fires on the leading edge
327
+ // (good for click-style events); debounce fires on the
328
+ // trailing edge (good for typing, where you want the server
329
+ // to see only the final state after the user pauses). Both
330
+ // are no-ops when the corresponding keyword is absent, which
331
+ // is the common case — the per-element seq reconcile is
332
+ // already responsible for input coherency, so we don't apply
333
+ // a debounce by default.
334
+ const handlerDebounce = givenHandler[HANDLER_DEBOUNCE];
335
+ const handlerThrottle = givenHandler[HANDLER_THROTTLE];
336
+ let wrapped: TaggedEventHandler = givenHandler;
337
+ if (isValidDebounce(handlerThrottle)) {
338
+ wrapped = throttleHandler(wrapped, handlerThrottle as number);
339
+ }
340
+ if (isValidDebounce(handlerDebounce)) {
341
+ wrapped = debounceHandler(wrapped, handlerDebounce as number);
342
+ }
343
+
344
+ props[name] = (event: TargetedEvent<any>) => {
345
+ // Use a per-element (shared across all handlers on this
346
+ // element) monotonic counter for outgoing events. We
347
+ // overwrite the handler's own ``outgoingSeq`` with this
348
+ // counter so the wire-format seq number reflects the
349
+ // element-wide sequence. The handler closure's own
350
+ // ``outgoingSeq`` is unused for sequencing purposes now
351
+ // (it still exists as a default for non-wrapped callers).
352
+ //
353
+ // Critically, we increment the seq counter and update
354
+ // ``lastSentSeq`` on every *user* event, not on every
355
+ // server dispatch. If the handler is wrapped in a
356
+ // debounce that coalesces several events into one server
357
+ // dispatch, ``lastSentSeq`` will be higher than the seq
358
+ // actually sent to the server, which is fine — the seq
359
+ // we sent is the LATEST user-typed value, which is the
360
+ // one the server actually processed.
361
+ const seq = sharedOutgoingSeq.current++;
362
+ if (seq > lastSentSeq.current) {
363
+ lastSentSeq.current = seq;
95
364
  }
96
- // allow the client to respond (and possibly change the value)
97
- givenOnChange(event);
365
+ const taggedHandler = givenHandler as TaggedEventHandler & {
366
+ _reactpy_set_seq?: (n: number) => void;
367
+ };
368
+ if (typeof taggedHandler._reactpy_set_seq === "function") {
369
+ // Push the handler's internal counter past our seq so
370
+ // the next (possibly debounced) dispatch uses a seq
371
+ // number that matches what the user just typed, not
372
+ // whatever stale value the handler closure happened
373
+ // to have left over.
374
+ taggedHandler._reactpy_set_seq(seq + 1);
375
+ }
376
+
377
+ // ``onKeyPress`` fires before the DOM has been updated with
378
+ // the new keystroke — ``event.target.value`` is the value
379
+ // BEFORE the character was added. We deliberately do NOT
380
+ // trust it for value-tracking. ``onChange``/``onInput`` fire
381
+ // after the DOM has been updated and can be trusted, but we
382
+ // don't even need to track it separately here — the
383
+ // reconcile effect reads the DOM directly via ``inputRef``
384
+ // so it always sees the post-keystroke value.
385
+
386
+ wrapped(event);
98
387
  };
99
388
  }
100
389
 
101
390
  // Use createElement here to avoid warning about variable numbers of children not
102
391
  // having keys. Warning about this must now be the responsibility of the client
103
392
  // providing the models instead of the client rendering them.
393
+ // Drop ``value`` from the props we pass to Preact — we want the
394
+ // input to be fully uncontrolled. Preact would otherwise set
395
+ // ``inputRef.current.value`` on every render (because ``value``
396
+ // is a known DOM property), racing with the browser's own
397
+ // mutations of the DOM value during fast typing and silently
398
+ // dropping keystrokes. We instead update the DOM value via the
399
+ // ``inputRef`` in the reconcile effect above, only when the
400
+ // server has caught up and the proposed value is not shorter
401
+ // than what the user has already typed.
402
+ const controlledProps: Record<string, any> = {};
403
+ for (const key of Object.keys(props as Record<string, any>)) {
404
+ if (key !== "value") {
405
+ controlledProps[key] = (props as Record<string, any>)[key];
406
+ }
407
+ }
104
408
  return createElement(
105
409
  model.tagName,
106
- // overwrite
107
- { ...props, value },
410
+ { ...controlledProps, ref: inputRef },
108
411
  ...createChildren(model, (child) => (
109
412
  <Element model={child} key={child.attributes?.key} />
110
413
  )),
package/src/handler.ts ADDED
@@ -0,0 +1,33 @@
1
+ // Shared marker property names attached to event handler functions created by
2
+ // `vdom.tsx::createEventHandler`. Centralizing these strings keeps `components.tsx`
3
+ // and `vdom.tsx` in sync without relying on ad-hoc property names.
4
+
5
+ export const HANDLER_MARKER = "isHandler" as const;
6
+ export const HANDLER_DEBOUNCE = "debounce" as const;
7
+ export const HANDLER_THROTTLE = "throttle" as const;
8
+
9
+ export type HandlerMarker = typeof HANDLER_MARKER;
10
+ export type HandlerDebounce = typeof HANDLER_DEBOUNCE;
11
+ export type HandlerThrottle = typeof HANDLER_THROTTLE;
12
+
13
+ export type TaggedEventHandler = ((event: Event) => void) & {
14
+ [HANDLER_MARKER]: true;
15
+ [HANDLER_DEBOUNCE]?: number;
16
+ [HANDLER_THROTTLE]?: number;
17
+ };
18
+
19
+ /**
20
+ * Returns true when the given value is a finite, non-negative integer.
21
+ * Used to validate debounce/throttle values arriving over the wire from the
22
+ * Python layout.
23
+ */
24
+ export function isValidDebounce(value: unknown): value is number {
25
+ return (
26
+ typeof value === "number" &&
27
+ Number.isFinite(value) &&
28
+ Number.isInteger(value) &&
29
+ value >= 0
30
+ );
31
+ }
32
+
33
+ export const isValidThrottle = isValidDebounce;
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./client";
2
2
  export * from "./components";
3
+ export * from "./handler";
3
4
  export * from "./mount";
4
5
  export * from "./types";
5
6
  export * from "./vdom";
package/src/mount.tsx CHANGED
@@ -12,12 +12,9 @@ export function mountReactPy(props: MountProps) {
12
12
  );
13
13
 
14
14
  // Embed the initial HTTP path into the WebSocket URL
15
- componentUrl.searchParams.append("http_pathname", window.location.pathname);
15
+ componentUrl.searchParams.append("path", window.location.pathname);
16
16
  if (window.location.search) {
17
- componentUrl.searchParams.append(
18
- "http_query_string",
19
- window.location.search,
20
- );
17
+ componentUrl.searchParams.append("qs", window.location.search);
21
18
  }
22
19
 
23
20
  // Configure a new ReactPy client
package/src/types.ts CHANGED
@@ -48,7 +48,7 @@ export type ReactPyComponent = ComponentType<{ model: ReactPyVdom }>;
48
48
 
49
49
  export type ReactPyVdom = {
50
50
  tagName: string;
51
- attributes?: { [key: string]: string };
51
+ attributes?: { [key: string]: any };
52
52
  children?: (ReactPyVdom | string)[];
53
53
  error?: string;
54
54
  eventHandlers?: { [key: string]: ReactPyVdomEventHandler };
@@ -60,6 +60,8 @@ export type ReactPyVdomEventHandler = {
60
60
  target: string;
61
61
  preventDefault?: boolean;
62
62
  stopPropagation?: boolean;
63
+ debounce?: number;
64
+ throttle?: number;
63
65
  };
64
66
 
65
67
  export type ReactPyVdomImportSource = {
package/src/vdom.tsx CHANGED
@@ -1,17 +1,25 @@
1
1
  import eventToObject from "event-to-object";
2
2
  import { Fragment } from "preact";
3
+ import {
4
+ HANDLER_DEBOUNCE,
5
+ HANDLER_MARKER,
6
+ HANDLER_THROTTLE,
7
+ isValidDebounce,
8
+ isValidThrottle,
9
+ type TaggedEventHandler,
10
+ } from "./handler";
11
+ import { infer_bind_from_environment } from "./bind";
12
+ import log from "./logger";
13
+ import type { ReactPyClient } from "./client";
3
14
  import type {
4
- ReactPyVdom,
5
- ReactPyVdomImportSource,
6
- ReactPyVdomEventHandler,
7
- ReactPyModule,
8
15
  BindImportSource,
9
- ReactPyModuleBinding,
10
16
  ImportSourceBinding,
17
+ ReactPyModule,
18
+ ReactPyModuleBinding,
19
+ ReactPyVdom,
20
+ ReactPyVdomEventHandler,
21
+ ReactPyVdomImportSource,
11
22
  } from "./types";
12
- import { infer_bind_from_environment } from "./bind";
13
- import log from "./logger";
14
- import type { ReactPyClient } from "./client";
15
23
 
16
24
  export async function loadImportSource(
17
25
  vdomImportSource: ReactPyVdomImportSource,
@@ -206,8 +214,22 @@ export function createAttributes(
206
214
  function createEventHandler(
207
215
  client: ReactPyClient,
208
216
  name: string,
209
- { target, preventDefault, stopPropagation }: ReactPyVdomEventHandler,
210
- ): [string, () => void] {
217
+ {
218
+ target,
219
+ preventDefault,
220
+ stopPropagation,
221
+ debounce,
222
+ throttle,
223
+ }: ReactPyVdomEventHandler,
224
+ ): [string, TaggedEventHandler] {
225
+ // Sequence number for the next outgoing event on this handler.
226
+ // The wrapper in ``UserInputElement`` may overwrite this before
227
+ // the event is actually sent (so that the wrapper, not this
228
+ // closure, owns the per-element monotonic counter and survives
229
+ // handler recreation on every server re-render). The default
230
+ // behavior (no wrapper) is to use a per-handler counter starting
231
+ // at 0.
232
+ let outgoingSeq = 0;
211
233
  const eventHandler = function (...args: any[]) {
212
234
  const data = Array.from(args).map((value) => {
213
235
  const event = value as Event;
@@ -225,9 +247,37 @@ function createEventHandler(
225
247
  return event;
226
248
  }
227
249
  });
228
- client.sendMessage({ type: "layout-event", data, target });
250
+ const seq = outgoingSeq++;
251
+ client.sendMessage({ type: "layout-event", data, target, seq });
252
+ } as TaggedEventHandler & {
253
+ _reactpy_peek_seq?: () => number;
254
+ _reactpy_set_seq?: (n: number) => void;
229
255
  };
230
- eventHandler.isHandler = true;
256
+ eventHandler[HANDLER_MARKER] = true;
257
+ eventHandler._reactpy_peek_seq = (): number => outgoingSeq;
258
+ eventHandler._reactpy_set_seq = (n: number): void => {
259
+ outgoingSeq = n;
260
+ };
261
+ if (debounce !== undefined) {
262
+ if (!isValidDebounce(debounce)) {
263
+ log.warn(
264
+ `Ignoring invalid debounce value ${JSON.stringify(debounce)} ` +
265
+ `on event handler "${name}": expected a non-negative integer.`,
266
+ );
267
+ } else {
268
+ eventHandler[HANDLER_DEBOUNCE] = debounce;
269
+ }
270
+ }
271
+ if (throttle !== undefined) {
272
+ if (!isValidThrottle(throttle)) {
273
+ log.warn(
274
+ `Ignoring invalid throttle value ${JSON.stringify(throttle)} ` +
275
+ `on event handler "${name}": expected a non-negative integer.`,
276
+ );
277
+ } else {
278
+ eventHandler[HANDLER_THROTTLE] = throttle;
279
+ }
280
+ }
231
281
  return [name, eventHandler];
232
282
  }
233
283
 
package/src/websocket.ts CHANGED
@@ -1,6 +1,19 @@
1
1
  import type { CreateReconnectingWebSocketProps } from "./types";
2
2
  import log from "./logger";
3
3
 
4
+ function syncBrowserLocation(url: URL): void {
5
+ // The window will always have a HTTP path, so ReactPy should always be aware of it.
6
+ url.searchParams.set("path", window.location.pathname);
7
+
8
+ if (window.location.search) {
9
+ // Set the query string parameter if the HTTP location has a query string.
10
+ url.searchParams.set("qs", window.location.search);
11
+ } else {
12
+ // Remove any existing (potentially stale) query string parameter if the current location doesn't have one
13
+ url.searchParams.delete("qs");
14
+ }
15
+ }
16
+
4
17
  export function createReconnectingWebSocket(
5
18
  props: CreateReconnectingWebSocketProps,
6
19
  ) {
@@ -15,6 +28,7 @@ export function createReconnectingWebSocket(
15
28
  if (closed) {
16
29
  return;
17
30
  }
31
+ syncBrowserLocation(props.url);
18
32
  socket.current = new WebSocket(props.url);
19
33
  socket.current.onopen = () => {
20
34
  everConnected = true;