open Js_top_worker_message.Message (** Re-export Widget_view so user code can write [Widget.View.Element] etc. *) module View = Js_top_worker_message.Widget_view (* --- Send function, injected by worker at startup --- *) let sender : (string -> unit) ref = ref (fun _ -> ()) let set_sender f = sender := f let send_msg msg = let json = json_of_worker_msg msg in !sender json (* --- Handler registry --- *) type widget_state = { handlers : (string * (string option -> unit)) list; } let widgets : (string, widget_state) Hashtbl.t = Hashtbl.create 16 (* --- Public API --- *) let display ~id ~handlers view = Hashtbl.replace widgets id { handlers }; send_msg (WidgetUpdate { widget_id = id; view }) let update ~id view = send_msg (WidgetUpdate { widget_id = id; view }) let clear ~id = Hashtbl.remove widgets id; send_msg (WidgetClear { widget_id = id }) let display_managed ~id ~kind ~config ~handlers = Hashtbl.replace widgets id { handlers }; send_msg (WidgetUpdate { widget_id = id; view = View.Managed { kind; config } }) let update_config ~id config = send_msg (WidgetConfig { widget_id = id; config }) let command ~id cmd data = send_msg (WidgetCommand { widget_id = id; command = cmd; data }) let register_adapter ~kind ~js = send_msg (WidgetRegisterAdapter { kind; js_code = js }) let handle_event ~widget_id ~handler_id ~value = match Hashtbl.find_opt widgets widget_id with | None -> () | Some state -> match List.assoc_opt handler_id state.handlers with | None -> () | Some handler -> handler value