Skip to content

Commit

Permalink
Merge pull request #2 from rizo/demo
Browse files Browse the repository at this point in the history
Demo
  • Loading branch information
rizo authored Sep 16, 2024
2 parents 3c7d965 + 49ca98f commit cce543b
Show file tree
Hide file tree
Showing 32 changed files with 1,556 additions and 1,855 deletions.
4 changes: 2 additions & 2 deletions .ocamlformat
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ break-cases = fit
cases-matching-exp-indent = normal
exp-grouping = preserve
cases-exp-indent = 2
margin = 80
margin = 100
parse-docstrings = true
wrap-comments = false
break-cases = fit-or-vertical
Expand All @@ -15,4 +15,4 @@ break-separators = after
space-around-lists = true
dock-collection-brackets = true
wrap-fun-args = true
indicate-multiline-delimiters = closing-on-separate-line
#indicate-multiline-delimiters = closing-on-separate-line
3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
- [ ] Http.get ~url
- [ ] BUG? Sharing html references leads to problems (See shared_ref)
- [ ] Consider structuring each router segment as "path?opts" to allow passing extra params to intermediate views.
- [ ] Unmounting should NOT free. Because remounting is acceptable. Test for this.
- [ ] Signals should have cleanup: for example, Time.timer should cleanup interval.
- [ ] Fix rendering/remounting order. See uplot example.

## shared_ref

Expand Down
7 changes: 3 additions & 4 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
{ pkgs ? import <nixpkgs> { } }:

let
ocamlPackages = pkgs.ocaml-ng.ocamlPackages_5_1;
onix = import (builtins.fetchGit {
url = "https://github.com/rizo/onix.git";
rev = "41bf9e887fa8f1399ac328f1868d6d2ba27aab9f";
rev = "00720d8a87daef3bbf66eb89e2b7d8efcaf577aa";
}) {
inherit pkgs ocamlPackages;
inherit pkgs;
verbosity = "info";
};

in onix.env {
path = ./.;
deps = {
"ocaml-system" = "5.1.1";
"ocaml-base-compiler" = "5.2.0";
};
roots = [ ./helix.opam ];
vars = {
Expand Down
120 changes: 47 additions & 73 deletions examples/7guis/Index.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@ let ( >> ) g f x = f (g x)
let view_counter () =
let count = Signal.make 0 in
let open Html in
fragment
fieldset []
[
h2 [] [ text "Counter" ];
legend [] [ h2 [] [ text "Counter" ] ];
div
[ style_list [ "margin-bottom" => "20px" ] ]
[ text "Increment or decrement a number by 1." ];
div []
[
button
[ on Event.click (fun _ -> Signal.update (fun n -> n + 1) count) ]
[ text "+" ];
button
[ on Event.click (fun _ -> Signal.update (fun n -> n - 1) count) ]
[ text "-" ];
span [ style_list [ "margin-left" => "5px" ] ] [ show int count ];
button [ on Event.click (fun _ -> Signal.update (fun n -> n + 1) count) ] [ text "+" ];
button [ on Event.click (fun _ -> Signal.update (fun n -> n - 1) count) ] [ text "-" ];
span
[
bind (fun n -> if n < 0 then style_list [ ("color", "red") ] else Attr.nop) count;
style_list [ "margin-left" => "5px" ];
]
[ show int count ];
];
]

Expand All @@ -32,76 +33,60 @@ let view_temp_conv () =
let f_signal = Signal.make "" in
let on_temp_input conv signal ev =
let value = Node.get_value (Event.target ev) in
let value' =
try value |> float_of_string |> conv |> string_of_float
with Failure _ -> ""
in
let value' = try value |> float_of_string |> conv |> string_of_float with Failure _ -> "" in
Signal.emit value' signal
in
let open Html in
fragment
fieldset []
[
h2 [] [ text "Temperature Converter" ];
legend [] [ h2 [] [ text "Temperature Converter" ] ];
div
[ style_list [ "margin-bottom" => "20px" ] ]
[ text "Bidirectional temperature converter." ];
input
[ bind value c_signal; on Event.input (on_temp_input f_of_c f_signal) ];
input [ bind value c_signal; on Event.input (on_temp_input f_of_c f_signal) ];
text " Celsius = ";
input
[ bind value f_signal; on Event.input (on_temp_input c_of_f c_signal) ];
input [ bind value f_signal; on Event.input (on_temp_input c_of_f c_signal) ];
text " Fahrenheit";
]

let view_flight_booker () =
let is_valid_date str = String.length str = 10 in
let is_valid_book (d1, d2) ft =
(String.equal "oneway" ft && is_valid_date d1)
|| String.equal "return" ft
&& is_valid_date d1
&& is_valid_date d2
&& d2 >= d1
|| (String.equal "return" ft && is_valid_date d1 && is_valid_date d2 && d2 >= d1)
in
let flight_type = Signal.make "oneway" in
let dates = Signal.make ("2023-01-01", "2023-01-01") in
let msg_signal = Signal.make "" in
let click_submit _ =
let click_submit () =
let d1, d2 = Signal.get dates in
let ft = Signal.get flight_type in
let msg =
String.concat " "
( if String.equal ft "oneway" then
[ "You have booked a one-way flight on"; d1 ]
else [ "You have booked a return flight on"; d1; "and"; d2 ]
)
(if String.equal ft "oneway" then [ "You have booked a one-way flight on"; d1 ]
else [ "You have booked a return flight on"; d1; "and"; d2 ])
in
Signal.emit msg msg_signal
in
let open Html in
fragment
fieldset []
[
h2 [] [ text "Flight Booker" ];
div
[ style_list [ "margin-bottom" => "20px" ] ]
[ text "Demonstrates constraints." ];
legend [] [ h2 [] [ text "Flight Booker" ] ];
div [ style_list [ "margin-bottom" => "20px" ] ] [ text "Demonstrates constraints." ];
div
[
style_list
[
"display" => "flex";
"gap" => "10px";
"flex-direction" => "column";
"width" => "200px";
"display" => "flex"; "gap" => "10px"; "flex-direction" => "column"; "width" => "200px";
];
]
[
select
[
name "flight_type";
on Event.change (fun ev ->
on_change (fun value ->
Signal.emit "" msg_signal;
Signal.emit (Event.target ev |> Node.get_value) flight_type
);
Signal.emit value flight_type);
]
[
option [ value "oneway" ] [ text "one-way flight" ];
Expand All @@ -111,36 +96,29 @@ let view_flight_booker () =
[
placeholder "YYYY-MM-DD";
value (fst (Signal.get dates));
on_input (fun value ->
Signal.update (fun (_, d2) -> (value, d2)) dates
);
on_input (fun value -> Signal.update (fun (_, d2) -> (value, d2)) dates);
toggle
~on:(fun (d1, _) -> not (is_valid_date d1))
(style_list [ "outline" => "1px solid red" ])
dates;
dates
(style_list [ "outline" => "1px solid red" ]);
];
input
[
placeholder "YYYY-MM-DD";
value (snd (Signal.get dates));
on_input (fun value ->
Signal.update (fun (d1, _) -> (d1, value)) dates
);
toggle ~on:(String.equal "oneway") (disabled true) flight_type;
on_input (fun value -> Signal.update (fun (d1, _) -> (d1, value)) dates);
toggle ~on:(String.equal "oneway") flight_type (disabled true);
toggle
~on:(fun ((_, d2), ft) ->
String.equal "return" ft && not (is_valid_date d2)
)
(style_list [ "outline" => "1px solid red" ])
(Signal.pair dates flight_type);
~on:(fun ((_, d2), ft) -> String.equal "return" ft && not (is_valid_date d2))
(Signal.pair dates flight_type)
(style_list [ "outline" => "1px solid red" ]);
];
button
[
on Event.click click_submit;
on_click click_submit;
toggle
~on:(fun (dates, ft) -> not (is_valid_book dates ft))
(disabled true)
(Signal.pair dates flight_type);
(Signal.pair dates flight_type) (disabled true);
]
[ text "Book" ];
show text msg_signal;
Expand All @@ -150,29 +128,22 @@ let view_flight_booker () =
(* [TODO] Incomplete impl. *)
let view_timer () =
let open Html in
fragment
fieldset []
[
h2 [] [ text "Timer" ];
legend [] [ h2 [] [ text "Timer" ] ];
div [ style_list [ "margin-bottom" => "20px" ] ] [ text "Concurrency." ];
div
[
style_list
[
"display" => "flex";
"gap" => "10px";
"flex-direction" => "column";
"width" => "350px";
"display" => "flex"; "gap" => "10px"; "flex-direction" => "column"; "width" => "350px";
];
]
[
div []
[
text "Elapsed time: ";
progress
[
style_list [ "width" => "100%" ]; attr "max" "100"; value "70";
]
[];
progress [ style_list [ "width" => "100%" ]; attr "max" "100"; value "70" ] [];
text "10s";
];
div
Expand All @@ -196,16 +167,19 @@ let view_timer () =

let main () =
let open Html in
div
[ class_list [ "w-full" ] ]
div []
[
h1 [] [ text "Helix 7 GUIs" ];
blockquote []
[
text "See: ";
a
[ href "https://eugenkiss.github.io/7guis/tasks" ]
[ text "https://eugenkiss.github.io/7guis/tasks" ];
];
view_counter ();
hr [];
view_temp_conv ();
hr [];
view_flight_booker ();
hr [];
view_timer ();
]

Expand Down
7 changes: 2 additions & 5 deletions examples/7guis/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
<meta charset="utf-8" />
<title>Helix - 7 GUIs</title>
<style>
body {
padding: 10px;
}
h2 {
margin-top: 10px;
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
</style>
</head>
Expand Down
21 changes: 21 additions & 0 deletions examples/composition/Counter.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
open Helix

let make ?(by = Signal.make 1) lbl =
let count = Signal.make 0 in

let html =
let open Html in
div []
[
span [] [ text lbl ];
button [ on_click (fun () -> Signal.emit 0 count) ] [ text "Reset" ];
button
[ on_click (fun () -> Signal.update (fun n -> n - Signal.get by) count) ]
[ text "" ];
button
[ on_click (fun () -> Signal.update (fun n -> n + Signal.get by) count) ]
[ text "+" ];
span [] [ show int count ];
]
in
(html, count)
Loading

0 comments on commit cce543b

Please sign in to comment.