let search s xs = let results = Js.Array.filter (Js.String.includes s) xs in if Js.Array.length results == 1 && results.(0) == s then [| |] else results let render_completion render_entry on_select entries = H.div [| HA.class_ "g-Autocomplete__Completion" |] (entries |> Js.Array.map (fun c -> Button.raw [| HA.class_ "g-Autocomplete__Entry" ; HA.type_ "button" ; HE.on_click (fun e -> let () = Event.stop_propagation e in let () = Event.prevent_default e in on_select c) |] (render_entry c))) let create attrs id values render_entry on_input = let completion = H.div [| |] [| |] in let update_completion target value = let entries = search value values in Element.mount_on completion (render_completion render_entry (fun selected -> let () = Element.set_value target selected in let () = Element.remove_children completion in on_input selected) entries) in let hide_completion () = Element.mount_on completion (H.text "") in H.div [| HA.class_ "g-Autocomplete" |] [| H.input (HA.concat attrs [| HA.id id ; HA.class_ "g-Autocomplete__Input" ; HA.autocomplete "off" ; HE.on_click (fun e -> let target = Event.target e in let value = Element.value target in update_completion target value) ; HE.on_input (fun e -> let target = Event.target e in let value = Element.value target in let () = update_completion target value in on_input value) ; HE.on_blur (fun _ -> let _ = Js.Global.setTimeout (fun _ -> hide_completion ()) 100 in ()) |]) [| |] ; completion |]