1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162openCoreopenVirtual_domtypet={filename:string;mimetype:string;contents:string}[@@derivingfields]letcreate=Fields.createletsexp_of_tt=Sexp.Atom(sprintf"<downloader: %s>"t.filename)lettrigger{filename;mimetype;contents}=letopenJs_of_ocamlinifam_running_inline_testthenprint_s[%message"Download triggered"(filename:string)(mimetype:string)contents]else((* https://stackoverflow.com/a/19328891/558592 *)leta=Dom_html.createADom_html.documentinletcontents_bigstr=Typed_array.Bigstring.to_arrayBuffer(Bigstring.of_stringcontents)inletblob=(* Don't use [blob_from_string]. That has an attractive type but works by first
converting our OCaml string to a Javascript string, which converts to
UTF-16. If the string contains random binary data that will distort it. *)File.blob_from_any[`arrayBuffercontents_bigstr]~contentType:mimetypeinleturl=Dom_html.window##._URL##createObjectURLblobina##setAttribute(Js.string"href")url;a##setAttribute(Js.string"download")(Js.stringfilename);a##click;Dom_html.window##._URL##revokeObjectURLurl);;moduleButton=structletcreate?(enabled=true)?(on_click=fun_->Vdom.Effect.Ignore)?(extra_attrs=[])~get_download~button_text()=letopenVdominlettrigger_csv_downloadev=trigger(get_download());on_clickevinletenabled_disabled=ifenabledthen[]else[Attr.disabled;Attr.style(Css_gen.color(`Name"grey"))]inletattrs=[extra_attrs;enabled_disabled;[Attr.on_clicktrigger_csv_download]]|>List.concatinNode.button~attr:(Attr.many_without_mergeattrs)[Node.textbutton_text];;end