Code Monkey home page Code Monkey logo

bucklescript-tea's People

Contributors

alfredfriedrich avatar benschza avatar bobzhang avatar canadaduane avatar dboris avatar dependabot[bot] avatar feluxe avatar jackalcooper avatar joprice avatar jordwest avatar neochrome avatar overminddl1 avatar pbiggar avatar seadynamic8 avatar shalokshalom avatar soren-n avatar tcoopman avatar utkarshkukreti avatar yatesco avatar yawaramin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bucklescript-tea's Issues

Runtime error by passing a function to an onClick

I'm not sure if this is the best way to use TEA, but I've run into a runtime error in this situation:

type msg = Foo of (int * msg Tea.Cmd.t)

let msgs id = Tea.Cmd.call (fun callbacks -> ....)

let view =
  div [onClick (Foo (1, (msgs 1)))] []

I get an error on

let compareEventHandlerTypes left = function

because this uses ocaml.equal which doesn't like comparing functions:

var b_type = typeof b;
        if (a_type === "function" || b_type === "function") {
          throw [
                invalid_argument,
                "equal: functional value"

is it possible to integrate tea with redux

Concrete question, I have a redux app and parts of it I want to port to bucklescript. This is not that hard, for example I can just switch the reducer with an update function.
The problem is when I have an update function that next to the model also returns msgs and I want to execute them.

I was fiddling around a bit with Tea_cmd.js to call them or run them, but honestly I'm a bit lost and maybe I need to take a step back, but I thought it is worth a shot...

So I'm not sure that it's a good idea what I'm doing, and maybe I need a different approach, but if you have any pointers if it's possible to integreate the tea loop with reducers that would help :)

[discussion] Debugging similar to Elm

So, I've been working a bit on a simple "time travel debugger" like the one in Elm.
A small demo is available at https://neochrome.github.io/debug2/

Example usage:

let () =
  let module D = Debug.Make(struct
    type flags = unit
    type msg = my_msg
    type model = my_model
    let init = init
    let update = update
    let view = view
    let subscriptions = subscriptions
    let string_of_msg = function
      | Increment -> "Increment"
      | Decrement -> "Decrement"
      | Reset -> "Reset"
      | Set _ -> "Set"
  end) in
  D.standardProgram (Web.Document.getElementById "main") () |> ignore;;

Is this something that would be of interest to include in the core bucklescript-tea package or is better off as a peer package that might be added if needed?

Your thoughts?

XMLHttpRequest.open doesn't get generated properly

bucklescript-tea/src/web_xmlhttprequest.ml:

let open_ method' url ?(async=true) ?(user="") ?(password="") x =
      x##open_ method' url async user password
function open_(method$prime, url, $staropt$star, $staropt$star$1, $staropt$star$2, x) {
  var async = $staropt$star ? $staropt$star[0] : /* true */1;
  var user = $staropt$star$1 ? $staropt$star$1[0] : "";
  var password = $staropt$star$2 ? $staropt$star$2[0] : "";
  return x.open_(method$prime, url, async, user, password);
}

Which should be:

xhrReq.open(method, url);
xhrReq.open(method, url, async);
xhrReq.open(method, url, async, user);
xhrReq.open(method, url, async, user, password);

feature request: a skeleton project

Could you add a repo with a small skeleton project, with the javascript pipeline (bundler, watcher etc.) configured and working? It would be a big help for people not coming from the javascript world.

Question: TEA with React based virtual dom

This is just a question. I was wondering if it would be possible (and be useful) to create tea with React as the view layer.

The reason why it could be useful for me is: some of the hooks that react has (for example componentDidMount) are useful when you integrate with existing js code. This is something I don't know how to do with the current vdom layer.

Other reasons why it can be useful:

  • Not having to create/maintain an own vdom layer
  • Huge React eco system that can be used
  • React also has React-Native, so this could be useful as well.

I haven't thought this through completely so there might be some obvious downsides or reasons why this isn't a good idea, so I'd love to get an opinion on this.

Fail to build on [email protected]

[6/27] Building src/web_location.cmj /Users/jackalcooper/elixir/node_modules/bucklescript-tea/lib/js/src/web_location.js src/web_location.cmi
FAILED: src/web_location.cmj /Users/jackalcooper/elixir/node_modules/bucklescript-tea/lib/js/src/web_location.js src/web_location.cmi 
/Users/jackalcooper/elixir/missing_pieces/assets/node_modules/bs-platform/bin/bsc.exe -bs-package-name bucklescript-tea  -bs-package-output commonjs:lib/js/src -bs-assume-no-mli -bs-no-builtin-ppx-ml -bs-no-implicit-include  -I src  -nostdlib -I '/Users/jackalcooper/elixir/node_modules/bs-platform/lib/ocaml' -bs-cross-module-opt -no-alias-deps -color always -w -40+6+7+27+32..39+44+45 -o src/web_location.mlast -c  src/web_location.mlast 
File "/Users/jackalcooper/elixir/node_modules/bucklescript-tea/src/web_location.ml", line 3, characters 9-433:
Error: Unbound module Js.Internal
ninja: build stopped: subcommand failed.
Failure: /Users/jackalcooper/elixir/missing_pieces/assets/node_modules/bs-platform/bin/ninja.exe 
 Location: /Users/jackalcooper/elixir/node_modules/bucklescript-tea/lib/bs
Error happened when running command /Users/jackalcooper/elixir/missing_pieces/assets/node_modules/bs-platform/bin/bsb.exe with args [ '-make-world', '-w' ]

Uncaught TypeError: style.setProperty_ is not a function

When I compile with BS 1.5.0 the following function breaks:

function setStyleProperty(n, $staropt$star, key, value) {
  var priority = $staropt$star ? $staropt$star[0] : /* false */0;
  var style = n.style;
  var match = style.setProperty;
  if (match !== undefined) {
    return style.setProperty_(key, value, priority ? "important" : null);
  }
  else {
    return setStyle(n, key, value);
  }
}

In web_node.ml there is a type definition for 'style'

type style = <
   setProperty : Web_json.t Js.undefined [@bs.get]; (* TODO:  Revamp this and the next line... *)
   setProperty_ : string -> string Js.null -> string Js.null -> unit [@bs.meth];
   > Js.t

Question - mutation during update?

I was about to use an Array for a part of my model, and using Belt.Array.set as part of the update. I am worried that the TEA implementation that this is based on assumes that you're dealing with immutable arrays, like the ones built into elm.

Is bucklescript-tea robust to mutating the model in the update function? Or should we avoid using mutation and rely on immutable data structures?

Thanks!

websocket subscription

The following statement successfully sets up a connection to a websocket server

let ws = WebSockets.WebSocket.make "ws://localhost:5858"

         |> WebSockets.WebSocket.setBinaryType ArrayBuffer

         |> WebSockets.WebSocket.on @@ Open
                                         (fun _ -> Js.log "Open")

         |> WebSockets.WebSocket.on @@ Close
                                         (fun _ -> Js.log "Close")

         |> WebSockets.WebSocket.on @@ Message
                                         on_message

         |> WebSockets.WebSocket.on @@ Error
                                         (fun _ -> Js.log "error")
;;

How can bs-tea easily subscribe to on_message ?

Could we just manually trigger an update in on_message by using some internal function in Vdom.ml ?

I do understand that such an approach might be fundamentally different from traditional TEA ---

However said approach is more logically sensible to me and allows for much more fine-grained tuning & control over the server

Server Side Render Support

It can be cool that Bucklescript support SSR, this can help to improve the user experience and is helpfull for SEO

ReasonML Syntax?

I know you (@OvermindDL1) really dislike the new ReasonML syntax. However, I'd like to make a case for embracing it.

I'm at a coding hackaway with about 25 software engineers right now. We're all building side projects and chatting and generally having a good time. So far, I've heard 3 separate people talk about Reason. I've heard 0 talk about OCaml.

There is a significant need that Reason/Bucklescript is filling in the web development community that I sense has a great deal of momentum gathering behind it. The Elm Architecture (TEA) is a great way to build web front-end code; however, Elm is not pragmatic and software engineers in my circle have mostly relegated it to a toy project. Reason, on the other hand, has great potential, and has a lot of "market fit" to use a business term.

I see a lot of people looking for TEA in Reason, but I see TEA in OCaml as "yet another friction point" in the journey of a javascript developer seeking to harness all of the goodness that the Reason+BuckleScript combo has made available.

What do you say to switching the default examples and docs to Reason? If we need to petition for changes to ReasonML, are there any specific syntax choices that would help make bucklescript-tea more useable?

Http toTask missing

I was hoping to chain a few http requests into a task when I noticed that Elm's Http.toTask function hasn't been adopted (or is missing).

I attempted to split the current Http.send function into 2 parts myself:

  1. Http.toTask - converts the request into a task
  2. Http.send - under the hood, basically does Http.toTask req |> Cmd.attempt msg

... and ran into a problem. Because of the way that Http.send is also being used to track progress events, I don't believe the send function can technically be pulled apart into a task - correct me if I'm wrong. See the following problem lines:

https://github.com/OvermindDL1/bucklescript-tea/blob/master/src/tea_http.ml#L108-L117

I'm torn. If we can't chain api requests into a single task, we'll need to rethink how we transition pages in our SPA (arggg). At the same time, I always found Elm's progress events awkward and disconnected.

Is there a solution that I'm not seeing?

Bug in ~key?

Hi!

Is ~key:_ supposed to work the same as key in React/Value and keyed in Elm? If yes, I have created a test case where some nodes' values are not updated even if the model changes. Here's the code:

open Tea.App
open Tea.Html

type counter = {id: int; value: int}

type model = counter list

let init () = [{id= 0; value= 0}; {id= 1; value= 1}; {id= 2; value= 2}]

type msg = Increment of int

let update model = function
  | Increment id ->
      Belt.List.map model (fun counter ->
          if counter.id = id then {counter with value= counter.value + 1}
          else counter )


let view model =
  let () =
    Belt.List.map model (fun counter -> counter.value) |> Belt.List.toArray
    |> Js.log
  in
  div []
    (Belt.List.map model (fun counter ->
         div ~key:(string_of_int counter.id) []
           [ span [] [text (" " ^ string_of_int counter.value ^ " ")]
           ; button [onClick (Increment counter.id)] [text "+"] ] ))


let main = beginnerProgram {model= init (); update; view}

and repo: https://github.com/utkarshkukreti/bs-tea-key-bug (just run yarn install && yarn start and then open the link webpack prints).

If you press "+", you'll see the correctly incremented value logged to the console but the text display of the counter does not update! If I remove ~key it updates fine.

request: support for ocaml-vdom's ui api

Lexifi's ocaml-vdom has a nice API for declaring UIs, similar to elm's but nicer in a bunch of small ways. It'd be great to have that as an alternative API for bucklescript-tea, especially since that would let people trivially experiment with both frameworks while sharing UI code.

(I might have a go at doing this myself, if I get the time, but I figured I'd put it up here first to see if people were receptive to the idea, and if someone with more bandwidth wants to get to it first :))

Vdom bug

Minimal case

type model = {
  selected: string option;
  languages: string list
}

type message = 
  | Select of string
  | Delete
  [@@bs.deriving {accessors}]

let render_selected = function
| Some selected -> 
  div [] 
    [ text ("you selected " ^ selected)
    ; div [onClick Delete] [text "delete selection"]]
| None -> div [] [text "Nothing selected"]

let lang l is_selected =
  let baseProps = [onClick (Select l); style "color" "blue"] in
  let props = if is_selected == true then (style "border" "1px solid black")::baseProps else baseProps
  in
  li props [text l]

let render_languages selected languages =
  let is_selected selected language =
  match selected with
      | Some l -> language == l
      | None -> false
  in 
  let rendered = List.map (fun l -> lang l (is_selected selected l)) languages in
  ul [] rendered

let update state = function 
| Select lang -> { state with selected = Some lang}
| Delete -> { state with selected = None }

let view state =
  div []
    [ render_selected state.selected 
    ; render_languages state.selected state.languages]

let main =
   let initialState = {
    selected = Some "Erlang"; 
    languages = ["Erlang"; "Ocaml"; "Clojure"]
   } in
   beginnerProgram { 
    model = initialState;
    update;
    view;
  }

Background

captura de pantalla 2017-02-24 a las 10 42 08

You have a list of languages where the first one is selected.
If a language is selected, it gets a border. Then, above the list, a delete-link is displayed to deselect the selected language.

Expected

When deleting a language by clicking on the delete-link, the border should disappear.
All other styling (blue color) should remain, due to

  let baseProps = [onClick (Select l); style "color" "blue"] in
  let props = if is_selected == true then (style "border" "1px solid black")::baseProps else baseProps
  in ...

Actual

captura de pantalla 2017-02-24 a las 10 49 32
All style attributes on that list-item disappear, in favour of an empty style attribute.
I would expect the style to retain the "color: blue"

Unless I'm missing something pretty obvious, this looks like a bug in the vdom diffing.

Failed to build bucklescript-tea on bs-platform 1.5.2

[1/15] Building src/tea_cmd.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_cmd.js src/tea_cmd.cmi
[2/15] Building src/tea_sub.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_sub.js src/tea_sub.cmi
[3/15] Building src/tea_json.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_json.js src/tea_json.cmi
FAILED: src/tea_json.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_json.js src/tea_json.cmi 
/Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bs-platform/bin/bsc.exe -bs-package-name bucklescript-tea  -bs-package-output commonjs:lib/js/src -bs-assume-no-mli -bs-no-builtin-ppx-ml -bs-no-implicit-include  -I src  -nostdlib -I /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bs-platform/lib/ocaml -bs-cross-module-opt -no-alias-deps -color always -w -40+6+7+27+32..39+44+45 -o src/tea_json.mlast -c  src/tea_json.mlast 
File "/Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/src/tea_json.ml", line 118, characters 43-62:
Error: This expression has type 'a Js.Undefined.t -> 'a option
       but an expression was expected of type Web.Json.t option -> 'b
       Type 'a Js.Undefined.t = 'a Js.undefined is not compatible with type
         Web.Json.t option 
[4/15] Building src/tea_svg_attributes.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_svg_attributes.js src/tea_svg_attributes.cmi
[5/15] Building src/tea_html_cmds.cmj /Users/jackalcooper/elixir/subway_umbrella/apps/subway/node_modules/bucklescript-tea/lib/js/src/tea_html_cmds.js src/tea_html_cmds.cmi

[Question] How to use a React-js component?

My daughter is building a singer / singing-teacher feedback app and is using Reason. She will need to use some existing component for the audio player, and js-React has some (like https://github.com/souporserious/react-media-player) with convenient props for things like track, current play position, play / pause control or notification callbacks etc.

Would much rather use bucklescript-tea than reason-react for the overall app. Any recommendation on how to connect her bs-tea to this react-js component? The simpler the better.

Thanks!

Matching elm APIs

Hi,
I just thought I should ask what is the goal regarding matching the elm APIs?
I noted that for instance the Html module currently doesn't follow the elm-html module v2.0.0 with regards to how things are arranged by sub modules.
Is this something that should be considered to be updated to be more like the elm APIs, although it would be a breaking change?

Is it possible to insert a div created in javascript in my view function

Basically, can I do something like this?

type document
type element
external document : document = "" [@@bs.val]
external createElement : document -> string -> element = "" [@@bs.send]

view _ =
  let elem = createElement document "div"
  div [] [elem]

The reason for this is that I use a library (esri api) that attaches itself to a htmlElement. So if I create the element and then pass it, the library works, but now I want to also render that element in my app, and I don't know how to do that.

Vdom bug

Minimal case

type msg' = 
   | Trigger
   [@@bs.deriving {accessors}]

type model = (string option * string option)

let update' model = function
  | Trigger ->
    let (left, _) = model in
    (left, Some "right")
  
let render_model = function 
  | (Some _, Some _) ->
      input' [value "This should be on screen"] []
  | _ -> 
    span [] [text "nothing"]

let view' model =
  div []
    [ button [onClick Trigger] [text "trigger rerender"]
    ; render_model model
    ]

let main =
  beginnerProgram {
    model = (Some "left", None);
    update = update';
    view = view'
  }

Starting state
captura de pantalla 2017-02-10 a las 16 19 21

Expected
Whenever I click the button, it should render a input with This should be on screen as value.
captura de pantalla 2017-02-10 a las 16 19 29

Actual
Whenever I click the button, it renders an empty span instead of the input.
captura de pantalla 2017-02-10 a las 16 19 00

If I wrap input inside render_model in an extra div, it renders correctly. I think this might be a bug in the vdom diffing? I noticed that using noNode instead of span [] [] in the catch-all case of render_model, fixes this

Problem with html styles?

If I use code like this:

  div 
  [styles
    [("position", "absolute")
    ;("left", toPX swipeyStyle##left)
    ;("top", toPX swipeyStyle##top)
    ]
  ]
  [
    img [(src Swipey.image)
    ][]
  ]

(toPX swipey... resolves to values like "200px")

I get the following js error:

[Error] Invalid_argument,-3,List.fold_left2
	fold_left2 (main.js:1019)
	patchVNodesOnElems_PropertiesApply (main.js:1594)
	patchVNodesOnElems_MutateNode (main.js:1718)
	patchVNodesOnElems (main.js:1805)
	patchVNodesOnElems (main.js:1805)
	patchVNodesIntoElement (main.js:2084)
	doRender (main.js:2366)
	handler (main.js:2415)
	handler (main.js:2309)

If instead, I use this code:

  div 
  []
  [
    img [(src Swipey.image)
          ;style "position" "absolute"
          ;style "left" (toPX swipeyStyle##left)
          ;style "top" (toPX swipeyStyle##top)
          ;style "width" Swipey.widthStr
    ][]
  ]

No problem.

Is this an error of mine, or somewhere else?

Separately, I also get messages like:

[Log] VDom:  Failed swapping properties because the property list length changed, use `noProp` to swap properties instead, not by altering the list structure.  This is a massive inefficiency until this issue is resolved. (main.js, line 1731, x2)

What is that about?

discussion: make bs-platform a dev dependency?

currently when user install bucklescript-tea it will also install bs-platform.

Since we have -make-world, currently my workflow is npm install -g bs-platform and when I install a bucklescript project, I do an npm link then run bsb -make-world, this would save installation time significantly, what do you think?

Note this is for discussion, lets find the best workflow for a compiled language on npm

VDOM bug: patchVNodesOnElems_PropertiesApply_Mutate

match clause Style s as _newProp of Vdom.patchVNodesOnElems_PropertiesApply_Mutate can't handle the case two lists have different lengths. It is because OCaml's List.fold_left2 will raise Invalid_argument if the two lists are determined to have different lengths.

Router Support (SPA)

Elm have support for SPA, it can be creat if bucklescript does the same

Basically is give support to a Router (and SSR as complement)

Could we supress the "property list length changed" message?

Regarding this error that pops up :

VDom: Failed swapping properties because the property list length changed, use noProp to swap properties instead, not by altering the list structure. This is a massive inefficiency until this issue is resolved.

Sometimes I know I am changing the property list length and I am happy to take the performance hit because it happens under rare circumstances.

Would it be possible to make it so I could suppress this warning when I know I really don't mind?

typed html properties

In Elm properties of html tags are defined as a list.

profile user =
    div [ class "profile" ]
      [ img [ src user.picture ] []
      , span [] [ text user.name ]
      ]

=> class "profile", src user.picture etc.

I'm wondering if we can fully type those properties instead of using a list with:

(* bs.obj can also be used as an attribute in external declarations, as below: *)

external make_config : hi:int -> lo:int -> unit -> t = "" [@@bs.obj]
let v = make_config ~hi:2 ~lo:3

(* compiles down to *)
(* var u = {hi : 3} *)
(* var v = {hi : 3 , lo: 2} *)

Or I am overseeing something here?

Bug could be related to virtual DOM

This is the code to reproduce it (Bootstrap's css required).
I recorded a video to explain it because it's kind of hard for me to write it down without animation.
video

paginate.ml:

open Tea
open App
open Html

let rec range a b =
  if a > b then []
  else a :: range (a + 1) b

type model =
  { page : int
    ; pages : int
  }


type msg =
  | PriviousPage
  | NextPage
  | SelectPage of int
  | SetPages of int



let init () = { page=1; pages=10 }, Cmd.none


let update model = function
  | PriviousPage -> if model.page - 1 > 0 then
        let newModel = {model with page = model.page - 1} in
            newModel, Cmd.none
      else
        model, Cmd.none
  | NextPage -> let pageNew = model.page + 1 in
      if pageNew < model.pages + 1  then
        let newModel = {model with page = pageNew} in
            newModel, Cmd.none
      else
        model, Cmd.none
  | SelectPage pageNumber -> 
        (if pageNumber == model.page then
      let () = print_endline "Stay in the same page" in
        model, Cmd.none
      else
        let newModel = {model with page = pageNumber} in
          newModel, Cmd.none)
  | SetPages newPages ->
        {model with pages = newPages; page = 1}, Cmd.none

let subscriptions _model =
  Sub.none


let view model =
    let pages = model.pages in
  div [ ]
          [ input' [ type' "text"; class' "form-control";  model.pages |> string_of_int |> value; onInput (fun x -> 
          let newPages = try int_of_string x  with _ -> 10 in
          SetPages newPages) ] []
              ;ul [class' "pagination"]
            ( 
              let () =  Js.log model.page in
              let largerThanLeft = model.page - 1 >= 1 in
              let smallerThanRight = model.page + 1 <= pages in   
              List.concat [
                [ li [classList ["disabled", largerThanLeft != true]]
                  [ a [ href "javascript:void(0)"; onClick PriviousPage ]
                    [ text ([%raw "\"Previous\"" ] : string) ]
                  ]
                ]
                ; (
                    List.map (fun (index) -> 
                      li [classList ["active", index == model.page]]
                        [ a [ href "javascript:void(0)"; onClick (SelectPage index) ]
                          [ text (string_of_int index) ]
                        ]
                  ) 
                  (range 1 pages)
                )
                ; [
                   li [classList ["disabled", smallerThanRight != true]]
                  [ a [ href "javascript:void(0)"; onClick NextPage ]
                    [ text ([%raw "\"Next\"" ] : string) ]
                  ]
                ]
              ]
            )
          ]


let main =
  standardProgram {
    init;
    update;
    view;
    subscriptions;
  }

Bucklescript deprecations

Recently Bucklescript has deprecated some functions without a major version bump as per NPM semver, which caused this library to break on its depended on version of bs-platform. There are more deprections and other various warnings, these should be fixed pro-actively before bs-platform removes them since a major version bump does not seem to happen as per NPM semver requirements for backwards-incompatible API changes (Please change that since Bucklescript is distributed via NPM ^.^).

[discussion] Ideas for specs/tests

Please have a look at https://github.com/neochrome/bucklescript-tea/tree/specs for a simple take on how specs/tests possible could be implemented.

For now it is expected to first be compiled using the bucklescript compiler, then executed using node (see package.json). It's possible it could work to execute more like a script using the -bs-main switch of the compiler, but I couldn't get it to work right away.

Would something like this be interesting?

improve the performance and code size using belt?

As you may know that we published an experimental stdlib which is optimized for performance and size. BuckleScript-Tea is purely OCaml, so the benefit would trickle down naturally, I wonder what's your opinion on this issue?

Pro: Better performance and smaller size, the generated code is also easier to debug

Con: The only con that I have in mind is belt is not on native yet(it is on our road map once it reaches some stability), but as a front-end library, I think it does not matter that much. SSR on nodejs is more natural than ocaml native since there are plenty of existing web servers already in NodeJS (I know OCamlOpt is much nicer, but the reality is NodeJS is running everywhere)

Problem with pushMsg?

Perhaps I don't I understand how to use pushMsg. I'm extending the starter project like this:

in index.html:

 buckle_app = starter.main(document.body);

I've added the msg AnimationUpdate to model

in Main:

open Tea_program (* needed for pushing messages into the app from JS *)
...
external pushMsg : 'a Tea_program.processMsg -> unit = "" [@@bs.val]
external buckle_app : 'a = "buckle_app" [@@bs.val]
let update_handler () = 
  let () = buckle_app##pushMsg (PushMsg `AnimationUpdate) in ()

When my update_handler gets called from JS, (thus calling pushMsg) the model gets set to some large negative integer.

In debugging this, I found out that

type msg =
  | AnimationUpdate
...
  [@@bs.deriving {accessors}]

generates an int for the accessor, rather than a function.

If instead, I have
``
type msg =
| AnimationUpdate of int


then a real accessor is generated:

function animationUpdate(param_0) {
return /* AnimationUpdate */__(0, [param_0]);
}


 **and** my model doesn't get trashed (with suitable changes to references to AnimationUpdate)!

Am I doing something wrong, or is there a bug somewhere?

PS. Thanks so much for your work, it's fantastic!

Bug related to `noProp`

I created a test at bcc32/bucklescript-tea@acc15ec.

When a vdom property is given a non-trivial value and is then changed to
noProp, the attribute ends up having as value the string "undefined". For the
example added in this commit, the element might end up looking like:

<li lang="undefined" style="color: blue;">Ocaml</li>

I ran into this bug when I was adding and removing the href attribute from an <a>, which meant that clicking on the link redirected the browser to the (relative) URL "undefined", rather than doing nothing as expected.

Discussion Place?

I apologize for using an issue for this...feel free to close this.

I don't remember where I first heard about this project, but searching led me to the Elixir Forum post, the bucklescript channel in Discord, and your blog posts.

I've considered writing blog posts about Bucklescript-TEA, writing some tutorials, or contributing to documentation. Would having a dedicated place to ask questions, gauge interest in topics, etc, be worthwhile? Do any of the above-mentioned places (or this one) make sense for discussing Bucklescript-TEA?

Alternative view html function syntax

I get the feeling that the view function is going to be a nightmare of parentheses for folks using the ReasonML syntax:

div([], [div([], [div([], [div([], [div([], [])])])])]);

I'm curious how much effort it would be to add support for JSX (if that is even possible). I might be willing to take a stab at it if you think it's worth while.

BTW: fantastic tea conversion into Bucklescript!

model used in an `onChange` handler doesn't update after each render

I might be doing something wrong here with ocaml, but I can't seem to find a solution. If I use the model in an onChange handler, the model is never updated (the initial model is always used).

The bug in code:

open Tea.App
open Tea.Html

type msg =
  | Increment
  | Set of int
  [@@bs.deriving {accessors}]

let init () = 4

let update model = function 
  | Increment -> model + 1
  | Set i -> i

let view_button title msg =
  button
    [ onClick msg
    ]
    [ text title
    ]

let view model =
  let bug foo =
    print_endline (string_of_int model);
    Set (int_of_string foo)
  in
  div
    []
    [ span
        [ style "text-weight" "bold" ]
        [ text (string_of_int model) ]
    ; br []
    ; view_button "Increment" Increment
    ; input' [onChange bug] []
    ]

let main =
  beginnerProgram { 
    model = init (); 
    update;
    view;
  }

Now every time you type something in the input field and press enter, the model is set to the correct value, but if you look at the console output it always prints 4.
So the model in the bug function is never updated?

Am I doing something wrong or is this a bug.
Something that points in the direction of a bug is that if you change the onClick handler to (bug "10") the model has the correct value.
So this only is a problem in the onChange handler?

Callback / event on DOM insertion

This might turn out to be either a question or a feature request, sorry if opening an issue is not the right place to ask this (btw is there a project related forum/chat somewhere?).

I am trying to achieve auto-resizing of textareas. Resizing on value change is working fine by using something like the following:

external _auto_expand : Web.Node.t -> unit = "textarea_auto_expand" [@@bs.val]
event "input"
  (fun evt ->
    match Js.Undefined.toOption evt##target with
    | None -> None
    | Some target -> begin
       _auto_expand target;
       match Js.Undefined.toOption target##value with
       | None -> None
       | Some value -> Some (action value)
     end)

I am using an external to hack around certain missing fields on Web.Node.t such as scrollHeight and others (tbh I prefer it this way since auto resizing of textareas is a hack regardless):

const textarea_auto_expand = element => {
  const get_value = pixels => parseInt(pixels.substring(0, pixels.length - 2));
  const style = window.getComputedStyle(element);
  const min_height = get_value(style.getPropertyValue("min-height"));
  element.style.height = 0;
  element.style.height = Math.max(min_height, element.scrollHeight) + 'px';
};

This works great, but I also need to have _auto_expand be called when the element is inserted into the DOM. E.g. in React you would implement componentDidMount.

I have been trying to find examples in Elm where you get access to a DOM element on insertion/mount time, but have not found any.

So, the question / feature request is; is it possible to get access to an element at the moment after it is inserted into the document?

Cannot apply node without optional arguments

Tea_html.node is defined as follows:

let node ?(namespace="") tagName ?(key="") ?(unique="") props nodes = fullnode namespace tagName key unique props nodes

Correct me if I'm wrong, but since the optional parameters come after a normal parameter, it's impossible to apply this function without the latter two optional parameters.

Failed to switch to the npm release from testing project

I got this:

File "_none_", line 1, characters 0-0:
Error: Package bucklescript-tea not found or bucklescript-tea/lib/ocaml does not exist or please set npm_config_prefix correctly
ninja: build stopped: subcommand failed.

package.json:

{
  "repository": {},
  "engine": "node 6.0.0",
  "scripts": {
    "deploy": "brunch build --production",
    "watch": "brunch watch --stdin",
    "assets:clean": "rm -rf public/assets",
    "postinstall": "npm run deploy"
  },
  "dependencies": {
    "bucklescript-tea": "^0.1.1"
  },
  "devDependencies": {
    "babel-brunch": "~6.0.0",
    "brunch": "2.7.4",
    "clean-css-brunch": "~2.0.0",
    "css-brunch": "~2.0.0",
    "javascript-brunch": "~2.0.0",
    "uglify-js-brunch": "~2.0.1",
    "bs-platform": "^1.2.0",
    "jquery": ">= 2.1"
  }
}

bsconfig.json:

{
    "name" : "trash_talk",
    "version": "0.0.1",
    "bs-dependencies" : ["bucklescript-tea"],
    "sources" : [
         { "dir" :  "app/bucklescript/trash_talk"}
        ],
    "bsc-flags": ["-bin-annot"],
    "generate-merlin" : true
}

Make the optional `key` argument required?

When I was creating a pagination with bucklescript-tea, I found that I could never get the "next" and "previous" button right. And I found a bug. It is the case if the msg for onClick is a if condition it will always go with one branch (and the value of first run, but in this case below it doesn't require a parameter for the Increment and Decrement msg).
Here is the minimum counter example to reproduce it. The behavior should be that the counter will go down to 2 if it reach 3:

main_counter.ml:

open Tea.App
open Tea.Html

type msg =
  | Increment
  | Decrement
  | Reset
  | Set of int

let update model = function
  | Increment -> model + 1
  | Decrement -> model - 1
  | Reset -> 0
  | Set v -> v


let view_button title msg =
  button
    [ onClick msg
    ]
    [ text title
    ]

let view model =
  div
    []
    [ span
        [ style "text-weight" "bold" ]
        [ text (string_of_int model) ]
    ; br []
    ; view_button "Increment" (
      (*Here comes the bug*)
      if model >= 3 then
      Decrement
      else
      Increment
    )
    ; br []
    ; view_button "Decrement" Decrement
    ; br []
    ; view_button "Set to 42" (Set 42)
    ; br []
    ; if model <> 0 then view_button "Reset" Reset else noNode
    ]


let main =
  beginnerProgram {
    model = 0;
    update;
    view;
  }

I tried it with Elm and on Elm it works fine:

-- Read more about this program in the official Elm guide:
-- https://guide.elm-lang.org/architecture/user_input/buttons.html

import Html exposing (beginnerProgram, div, button, text)
import Html.Events exposing (onClick)


main =
  beginnerProgram { model = 0, view = view, update = update }


view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick 
          (if model >= 3 then
            Decrement
          else
            Increment) 
        ] [ text "+" ]
    ]


type Msg = Increment | Decrement


update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

Missing HTML tags compared to Elm

Currently prototyping with Bucklescript TEA for a project, love it so far :)
But came across that iframes are currently not defined in the HTML module.

I cross-referenced Elm's HTML docs with the definitions in tea_html.ml, and found a small handful of tags, these were then cross-referenced against w3school's list of tags.

These are the tags I found, the scratched tags are ones that Elm defined but I could find on w3schools' list:

hr, blockquote,
code, em, b, u, sub, sup,
dl, dt, dd,
iframe, canvas, math,
address,
caption, colgroup, col,
fieldset, legend, datalist, optgroup, keygen, output, meter,
audio, video, source, track,
embed, object, param,
ins, del,
small, cite, dfn, abbr, var, samp, kbd, s, q,
ruby, rt, rp, bdi, bdo, wbr, menuitem, menu

I am posting this issue since I am not sure how else to generate these missing tags without modifying the TEA source code, and if I am to do this, then I would rather do this proper and make it into a pull-request.

If there is a better way, then I would love to hear it :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.