this repo has no description
1(** Interactive widget support for the OCaml toplevel.
2
3 Widgets are rendered in the client as HTML elements built from
4 {!View.node} trees. Event handlers in the view are symbolic string
5 identifiers — when the user interacts with a widget, the client sends
6 the handler ID and input value back to the worker, where the registered
7 callback is invoked.
8
9 Typical usage with Note FRP:
10 {[
11 let e, send = Note.E.create ()
12 let s = Note.S.hold 50 e
13
14 let () =
15 let open Widget.View in
16 Widget.display ~id:"my-slider"
17 ~handlers:["x", (fun v ->
18 send (int_of_string (Option.get v)))]
19 (Element { tag = "input";
20 attrs = [Property ("type", "range")];
21 children = [] })
22
23 (* Wire up automatic updates via Note: *)
24 let _logr = Note.S.log
25 (Note.S.map (fun v -> ... build view ...) s)
26 (Widget.update ~id:"my-slider")
27 ]} *)
28
29(** Re-export of {!Js_top_worker_message.Widget_view} for convenient access
30 from toplevel code. Use [let open Widget.View in ...] to access
31 constructors like [Element], [Text], [Property], [Handler], etc. *)
32module View = Js_top_worker_message.Widget_view
33
34val display :
35 id:string ->
36 handlers:(string * (string option -> unit)) list ->
37 View.node ->
38 unit
39(** [display ~id ~handlers view] registers a widget with the given [id],
40 installs [handlers] for routing incoming events, and sends the
41 initial [view] to the client. If a widget with this [id] already
42 exists, it is replaced. *)
43
44val update : id:string -> View.node -> unit
45(** [update ~id view] sends an updated view for an existing widget.
46 The handler map is not changed. *)
47
48val clear : id:string -> unit
49(** [clear ~id] removes the widget and its handlers. Sends a
50 WidgetClear message to the client. *)
51
52val display_managed :
53 id:string ->
54 kind:string ->
55 config:string ->
56 handlers:(string * (string option -> unit)) list ->
57 unit
58(** [display_managed ~id ~kind ~config ~handlers] registers a managed widget.
59 The client delegates rendering to the adapter registered for [kind].
60 [config] is a JSON string interpreted by the adapter.
61 [handlers] route incoming events, same as {!display}. *)
62
63val update_config : id:string -> string -> unit
64(** [update_config ~id config] sends an updated config to a managed widget.
65 The adapter decides how to reconcile the change (e.g. flyTo, setData). *)
66
67val command : id:string -> string -> string -> unit
68(** [command ~id cmd data] sends an imperative command to a managed widget.
69 [cmd] is the command name, [data] is a JSON string payload.
70 Use for one-shot actions like animations that don't represent state. *)
71
72val register_adapter : kind:string -> js:string -> unit
73(** [register_adapter ~kind ~js] sends a JavaScript adapter to the client.
74 The JS code must be an IIFE that returns an object with methods:
75 - [create(container, config, send)] — creates the widget, returns state
76 - [update(state, config)] — reconciles a config change
77 - [command(state, cmd, data)] — handles an imperative command
78 - [destroy(state)] — cleans up
79 where [send(handler_id, value)] sends an event back to the worker. *)
80
81val handle_event :
82 widget_id:string -> handler_id:string -> value:string option -> unit
83(** [handle_event ~widget_id ~handler_id ~value] routes an incoming
84 event to the registered handler. Called by the worker message loop
85 when a WidgetEvent is received. *)
86
87val set_sender : (string -> unit) -> unit
88(** [set_sender f] installs the function used to send JSON strings to
89 the client. Called once by the worker at startup. The function [f]
90 should call [Worker.post_message]. *)