aboutsummaryrefslogtreecommitdiff
path: root/lib/elements/input.ml
blob: 62175d55868eb7c176f4d9173fa57cd1eed64608 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
open Brr
open Brr_note
open Note

(** Create a slider element, and a signal with the value *)
let slider
  : at:Brr.At.t list -> Brr.El.t * float S.t

  = fun ~at ->
    let slider =
      El.input ~at () in

    let init_value = (Jstr.to_float (El.prop El.Prop.value slider)) in

    let event =
      Evr.on_el
        Ev.input (fun _ ->
            let raw_value = El.prop El.Prop.value slider in
            Jstr.to_float raw_value)
        slider
      |> S.hold init_value
    in
    slider, event

type file =
  { file : File.t
  ; content : Jstr.t
  }

(** Read the content from the file *)
let file_loader
  : file Note.E.send -> File.t -> unit
  = fun event file ->
    let blob = File.as_blob file in
    Fut.await
      (Blob.text blob)
      (Result.iter
         (fun content ->
            event ({file; content}) ))

(** Create an imput which load a file.

    [file_loader (Jstr.v ".json"] will create an input which only accept json
    files, and an event which gives access to the file.

*)
let file_loader
  : Jstr.t -> Brr.El.t * file Note.event
  = fun selector ->

    let add_file_event, add_file_sender = Note.E.create () in

    let i = El.input ()
        ~at:[ At.type' (Jstr.v "file")
            ; (At.v (Jstr.v "accept")) selector
            ] in

    (* The event return a list of files.

       We are only interested by a single on, and keep only the first from the
       list. *)
    let on_change files =
      file_loader add_file_sender (List.hd files) in

    Ev.listen
      Ev.change
      (fun _e -> on_change (El.Input.files i)) (El.as_target i);

    ( i
    , add_file_event )