jon.recoil.org

Module WidgetSource

Interactive widget support for the OCaml toplevel.

Widgets are rendered in the client as HTML elements built from View.node trees. Event handlers in the view are symbolic string identifiers — when the user interacts with a widget, the client sends the handler ID and input value back to the worker, where the registered callback is invoked.

Typical usage with Note FRP:

  let e, send = Note.E.create ()
  let s = Note.S.hold 50 e

  let () =
    let open Widget.View in
    Widget.display ~id:"my-slider"
      ~handlers:["x", (fun v ->
        send (int_of_string (Option.get v)))]
      (Element { tag = "input";
        attrs = [Property ("type", "range")];
        children = [] })

  (* Wire up automatic updates via Note: *)
  let _logr = Note.S.log
    (Note.S.map (fun v -> ... build view ...) s)
    (Widget.update ~id:"my-slider")

Re-export of Js_top_worker_message.Widget_view for convenient access from toplevel code. Use let open Widget.View in ... to access constructors like Element, Text, Property, Handler, etc.

Sourceval display : id:string -> handlers:(string * (string option -> unit)) list -> View.node -> unit

display ~id ~handlers view registers a widget with the given id, installs handlers for routing incoming events, and sends the initial view to the client. If a widget with this id already exists, it is replaced.

Sourceval update : id:string -> View.node -> unit

update ~id view sends an updated view for an existing widget. The handler map is not changed.

Sourceval clear : id:string -> unit

clear ~id removes the widget and its handlers. Sends a WidgetClear message to the client.

Sourceval display_managed : id:string -> kind:string -> config:string -> handlers:(string * (string option -> unit)) list -> unit

display_managed ~id ~kind ~config ~handlers registers a managed widget. The client delegates rendering to the adapter registered for kind. config is a JSON string interpreted by the adapter. handlers route incoming events, same as display.

Sourceval update_config : id:string -> string -> unit

update_config ~id config sends an updated config to a managed widget. The adapter decides how to reconcile the change (e.g. flyTo, setData).

Sourceval command : id:string -> string -> string -> unit

command ~id cmd data sends an imperative command to a managed widget. cmd is the command name, data is a JSON string payload. Use for one-shot actions like animations that don't represent state.

Sourceval register_adapter : kind:string -> js:string -> unit

register_adapter ~kind ~js sends a JavaScript adapter to the client. The JS code must be an IIFE that returns an object with methods:

  • create(container, config, send) — creates the widget, returns state
  • update(state, config) — reconciles a config change
  • command(state, cmd, data) — handles an imperative command
  • destroy(state) — cleans up where send(handler_id, value) sends an event back to the worker.
Sourceval handle_event : widget_id:string -> handler_id:string -> value:string option -> unit

handle_event ~widget_id ~handler_id ~value routes an incoming event to the registered handler. Called by the worker message loop when a WidgetEvent is received.

Sourceval set_sender : (string -> unit) -> unit

set_sender f installs the function used to send JSON strings to the client. Called once by the worker at startup. The function f should call Worker.post_message.