Giter Site home page Giter Site logo

lwd's People

Contributors

alizter avatar c-cube avatar drup avatar let-def avatar misterda avatar ohadrau avatar oliviernicole avatar rgrinberg avatar scoreunder avatar shubhamkumar13 avatar tmattio 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

lwd's Issues

SVG elements are not rendered with Tyxml_lwd

Hi,

First off, thanks a lot for your work on Lwd! I started porting a JS app to it yesterday and I'm really impressed by the elegance of the API!

I've encountered an issue with the rendering of SVG elements.

While inspecting the generated HTML, the code looks good, but the SVG is not displayed.

I've pushed a small repro here: https://github.com/tmattio/lwd-svg-repro/blob/main/lib/app.ml.

Let me know if there's anything I can do to help debug that ๐Ÿ™‚

modifier keys and mouse events

With Notty it is possible to check for mouse events and modifier keys together. For example shift scrolling. This doesn't appear to be possible in nottui.

widgets to add to Nottui_widgets

Here are some things I think would be convenient for a lot of UIs. I can contribute some of them if needed :).

I also think that Nottui_widget should just be a module in nottui, there's not much point having one without the other imho.

  • basic layout:
    • join_x_list ( reexpose Nottui.Ui.hcat?)
    • pack_x_list (on lists of ui Lwd.t, more convenient than manually using the monoid)
  • buttons
  • line-wrapped text
  • itemized lists (the equivalent of <ul> <li>โ€ฆ</li><li>โ€ฆ)
  • grids/tables (with padding options, etc.)
  • tree with fold/unfold button at each node (and content lazily loaded)
  • progress bar, progress animations (like a \ | / - animation, or something)
  • scroll area as big as possible
  • modal dialog (about/help/confirmation of action)
  • dropdown list selection

Dynamic documents and lost updates

Hi, I was trying out the Brr backend and had a couple of questions.

let ui =
  let count = Lwd.var 0 in
  let on_click () = Lwd.set count (Lwd.peek count + 1) in
  let button =
    Lwd.map
      ~f:(fun i ->
        let btn = El.button [El.txt' (string_of_int i)] in
        Ev.listen Ev.click (fun _e -> on_click ()) (El.as_target btn);
        btn)
      (Lwd.get count)
  in
  Elwd.div [`R button]

The rest of the file is the same as in the Brr example. If I replace the last line with button, the button no longer updates.

  1. I'm guessing this is due to the mismatch between the pure interface and the statefulness of the DOM. Should we always ensure that the top-level node is not dynamic, or is there a better workaround? Maybe this could be documented somewhere.
  2. Is this what the commented line is meant to address?

Anyway, I really like Lwd so far, awesome work!

Error running example code samples

Trying to run either the button or tree example gives a type error when trying to build. I'm not sure if it's something with dune or the package (possible version conflicts with dune?) but the hello world example ran, but none of the UI components seemed to work and caused type errors.

button sample code error ->

dune build
File "tui.ml", line 10, characters 13-20:
10 | Ui_loop.run (Lwd.map button (Lwd.get vcount));;
                  ^^^^^^^
Error (warning 6 [labels-omitted]): label f was omitted in the
 application of this function.
File "tui.ml", line 10, characters 21-27:
10 | Ui_loop.run (Lwd.map button (Lwd.get vcount));;
                          ^^^^^^
Error: This expression has type int -> ui
       but an expression was expected of type 'a Lwd.t

code

open Nottui;;
module W = Nottui_widgets;;

let vcount = Lwd.var 0;;

let button count = 
  W.button (Printf.sprintf "Clicked %d times!" count)
           (fun () -> Lwd.set vcount (count + 1));;

Ui_loop.run (Lwd.map button (Lwd.get vcount));;

dune

(executable
  (name tui)
  (libraries base nottui))

dune-project

(lang dune 2.9)
(name tui)

Ui.zcat is reversed

Contrary to Notty.I.zcat the order of composition for Ui.zcat appears to be reversed.

expose quit in ui loop

Nottui.Ui_loop.run could provide an easy way to combine the default behavior ("quit on escape") with custom behavior (like a quit button).
For that I think it could take an optional bool Lwd.var instead of a bool Lwd.t, and add the escape behavior on top of that?

Avoid unecessary computations when document is constant

It's common to have a Lwd.map node that performs side effects and always return the same value. This constant document must be integrated in bigger documents to receive updates but might cause unecessary computations.

let constant_document =
  let$ some_document in
  do_side_effect some_document;
  ()

let main =
  let$ () = constant_document in
  costly_operation

In this example, do_side_effect might interact with the DOM and costly_operation might wrap many of such constant documents into a sequence used as the children elements in the DOM, which will be fully evaluated every time.

Could these unnecessary computations be avoided by adding a "short circuit" node in the document ?
For example:

let constant_document =
  Lwd.reuse_map some_document ~cmp:(=) ~f:do_side_effect

Scroll area with bounds?

How does one create a scroll area that will stop scrolling down when there's no more widgets to display? Perhaps the answer is to use vscroll_area? But I don't understand this function

Sensors don't do anything?

When trying to fix a scrolling-related bug, I found that sensors don't work:

type sensor_state = {x : int; y : int; w : int; h : int; count : int}

let sensor_text () =
  let state_var = Lwd.var {x = 0; y = 0; w = 0; h = 0; count = 0} in
  let widget state =
    Nottui_widgets.printf ~attr:Notty.A.(bg white ++ fg black) "(%d, %d, %d, %d) updated %d times" state.x state.y state.w state.h state.count
    |> Nottui.Ui.permanent_sensor (fun ~x ~y ~w ~h () ->
      Lwd.set state_var {x; y; w; h; count = succ state.count}
    )
  in
  Lwd.map ~f:widget (Lwd.get state_var)

let () =
  let midpane = Nottui_widgets.v_pane (sensor_text ()) (sensor_text ()) in
  let rightpane = Nottui_widgets.h_pane midpane (sensor_text ()) in
  let root = Nottui_widgets.hbox [sensor_text (); rightpane] in
  Nottui.Ui_loop.run root

No matter what I resize (splits or terminal) I get something vaguely like this:

(0, 0, 0, 0) updated 0 times(0, 0, 0, 0) updated 0 t (0, 0, 0, 0) updated 0 times









                            (0, 0, 0, 0) updated 0 t



Using LWD installed from source at commit 3bfeca4d37560f8778610c51d60d2d1aedfa519d

merge nottui and nottui-widgets

make the widgets into a submodule of Ui? seems a bit useless to have Ui without a collection of standard widgets imho ๐Ÿ™‚

notes on API improvements

  • put everything in a single module Nottui (easily aliasable/openable). I'll refer to it as UI from now on.
  • re-export Lwd as UI.Incremental and Lwd_seq as UI.Seq
  • UI.Syntax with let$ and other bind/map from Lwd, along with UI helpers like <|> or <-> for h/v concatenation of UI elements
  • everything returns lwd-wrapped UI elements. I think UI.t = UI.Pure.t Lwd.t would make a lot of sense (where UI.Pure.t can be the base type for non-reactive elements). Most functions will work on lwd-wrapped things.
  • commonly used functionality is re-exported at toplevel in UI, for example UI.s for a string widget, UI.space, UI.sprintf, hcat (list), hjoin (binary horizontal concat), <|> (alias for hcat)
  • widgets can have their own submodule with all the bells and whistles (maybe as objects?), + a toplevel function to build them easily (like UI.Scrollable for the whole thing, along with a UI.scrollable : โ€ฆ function for the common case)
  • re-export pretty as UI.Pretty (can be just a module alias for lightweightness)

minor quibbles

  • flex needs more testing (but would be useful to keep)
  • scrollable currently doesn't take as much space as it can, so only the used part is actually scrollable

also see #5 for a bigger wishlist ๐Ÿด ๐ŸŽ… ๐ŸŽ

Explicit reuse of values in Lwd_seq.Reducer

The reducer seems to reuse old values, perhaps using physical equality on the elements of the sequence ?
It could be useful to pass a custom equality function and to define some guarantees about which values are reused.

I don't know which guarantees would be useful but I think it should be possible to avoid the lwd_to_remove marking step in tyxml-lwd's DOM update.
This trick cannot be used in a library where it's not possible to store new state on elements.

Reusing old values in a smart way should be able to avoid false-positives when listing dropped elements.
An element that moves would be removed then added again but this could be optimised an other way.

I noticed that in the code below, if I swap Lwd_seq.bind with Lwd_seq.lift, the whole sequence become dropped on every updates.
This might be because physical equality is lost when it wraps every elements of the sequence into a freshly allocated Lwd_seq.element. In the bind case, the sequence nodes are allocated once and shared (allocated outside of the document).

let$ childs = Lwd_seq.bind childs Fun.id in
let dropped, r = R.update_and_get_dropped !reducer childs in

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.