Skip to content

Commit 2fcac8d

Browse files
committed
doc: fix doc, add animation example
1 parent 374a7db commit 2fcac8d

26 files changed

Lines changed: 2357 additions & 144 deletions

doc/002_writing_html/readme.mbt.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ Event arguments are typically functions returning `Cmd`. You can forward events
106106
```moonbit check
107107
///|
108108
enum DrawMsg {
109-
Start(Mouse)
110-
End(Mouse)
109+
Start(@html.Mouse)
110+
End(@html.Mouse)
111111
}
112112
113113
///|

examples/animation/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Animation Example
2+
3+
This example isolates Rabbita's `on_animation_frame` subscription.
4+
5+
It starts on the rabbit tangram and lets you switch patterns manually while the
6+
frame subscription drives the current transition.
7+
8+
Third-party notice:
9+
10+
- `main/logo_animation.mbt` adapts code from `elm/elm-lang.org`
11+
- see [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md)
12+
13+
## Run in development
14+
15+
In this directory:
16+
17+
```bash
18+
npm install
19+
npm run dev
20+
```
21+
22+
Then open the local URL shown by Vite (usually `http://localhost:5173`).
23+
24+
## Build
25+
26+
```bash
27+
npm run build
28+
```
29+
30+
The built assets are generated in `dist/`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Third-Party Notices
2+
3+
## elm/elm-lang.org
4+
5+
The file `main/logo_animation.mbt` contains code adapted from:
6+
7+
- <https://github.com/elm/elm-lang.org/blob/master/src/Logo.elm>
8+
9+
Original copyright notice and license:
10+
11+
Copyright (c) 2012-present Evan Czaplicki
12+
13+
All rights reserved.
14+
15+
Redistribution and use in source and binary forms, with or without
16+
modification, are permitted provided that the following conditions are met:
17+
18+
* Redistributions of source code must retain the above copyright
19+
notice, this list of conditions and the following disclaimer.
20+
21+
* Redistributions in binary form must reproduce the above
22+
copyright notice, this list of conditions and the following
23+
disclaimer in the documentation and/or other materials provided
24+
with the distribution.
25+
26+
* Neither the name of Evan Czaplicki nor the names of other
27+
contributors may be used to endorse or promote products derived
28+
from this software without specific prior written permission.
29+
30+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7.76 KB
Loading

examples/animation/dist/assets/main.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/animation/dist/assets/styles.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/animation/dist/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Rabbita Animation Example</title>
7+
<script type="module" crossorigin src="/assets/main.js"></script>
8+
<link rel="stylesheet" crossorigin href="/assets/styles.css">
9+
</head>
10+
<body>
11+
<div id="app"></div>
12+
</body>
13+
</html>

examples/animation/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Rabbita Animation Example</title>
7+
<link rel="stylesheet" type="text/css" href="/styles.css" />
8+
<script src="/main.js" type="module"></script>
9+
</head>
10+
<body>
11+
<div id="app"></div>
12+
</body>
13+
</html>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
///|
2+
let rabbit_logo_pattern_index = 7
3+
4+
///|
5+
fn reset_animation(model : Model) -> Model {
6+
{
7+
..model,
8+
frame_count: 0,
9+
last_frame_ms: 0.0,
10+
logo: logo_static_pattern(rabbit_logo_pattern_index),
11+
logo_pattern_index: rabbit_logo_pattern_index,
12+
}
13+
}
14+
15+
///|
16+
fn step_animation_frame(timestamp : Double, model : Model) -> Model {
17+
let delta_ms = if model.last_frame_ms == 0.0 {
18+
16.0
19+
} else {
20+
timestamp - model.last_frame_ms
21+
}
22+
if logo_is_moving(model.logo) {
23+
{
24+
..model,
25+
frame_count: model.frame_count + 1,
26+
last_frame_ms: timestamp,
27+
logo: logo_step(delta_ms, model.logo),
28+
}
29+
} else {
30+
{ ..model, frame_count: model.frame_count + 1, last_frame_ms: timestamp }
31+
}
32+
}
33+
34+
///|
35+
fn animation_pattern_indices() -> Array[Int] {
36+
[0, 1, 2, 3, 4, 5, 6, 7]
37+
}
38+
39+
///|
40+
fn set_animation_pattern(index : Int, model : Model) -> Model {
41+
if index == model.logo_pattern_index {
42+
model
43+
} else {
44+
{
45+
..model,
46+
logo_pattern_index: index,
47+
logo: logo_set_pattern_by_index(index, model.logo),
48+
}
49+
}
50+
}
51+
52+
///|
53+
fn animation_pattern_button(
54+
dispatch : @rabbita.Dispatch[Msg],
55+
active_index : Int,
56+
index : Int,
57+
) -> @rabbita.Html {
58+
let class = if active_index == index {
59+
"tab active"
60+
} else {
61+
"tab"
62+
}
63+
@html.button(
64+
class~,
65+
on_click=dispatch(SelectPattern(index)),
66+
logo_pattern_name(index),
67+
)
68+
}
69+
70+
///|
71+
fn animation_actions(
72+
dispatch : @rabbita.Dispatch[Msg],
73+
model : Model,
74+
) -> Array[@rabbita.Html] {
75+
animation_pattern_indices().map(index => {
76+
animation_pattern_button(dispatch, model.logo_pattern_index, index)
77+
})
78+
}
79+

examples/animation/main/client.mbt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
///|
2+
using @html {div, h1}
3+
4+
///|
5+
using @rabbita {type Cmd, type Dispatch, type Html}
6+
7+
///|
8+
enum Msg {
9+
SelectPattern(Int)
10+
AnimationFrameTick(Double)
11+
}
12+
13+
///|
14+
struct Model {
15+
frame_count : Int
16+
last_frame_ms : Double
17+
logo : LogoModel
18+
logo_pattern_index : Int
19+
}
20+
21+
22+
///|
23+
fn update(_ : Dispatch[Msg], msg : Msg, model : Model) -> (Cmd, Model) {
24+
match msg {
25+
SelectPattern(index) => (@rabbita.none, set_animation_pattern(index, model))
26+
AnimationFrameTick(timestamp) =>
27+
(@rabbita.none, step_animation_frame(timestamp, model))
28+
}
29+
}
30+
31+
///|
32+
fn subscriptions(dispatch : Dispatch[Msg], _ : Model) -> @sub.Sub {
33+
@sub.on_animation_frame(
34+
dispatch.map(timestamp => AnimationFrameTick(timestamp)),
35+
)
36+
}
37+
38+
///|
39+
fn view(dispatch : Dispatch[Msg], model : Model) -> Html {
40+
div(class="page") <| [
41+
h1(class="title", "Rabbita Animation"),
42+
div(class="stage") <| [logo_view(model.logo)],
43+
div(class="actions") <| animation_actions(dispatch, model),
44+
]
45+
}
46+
47+
///|
48+
#cfg(target="js")
49+
fn main {
50+
let initial_model = reset_animation({
51+
frame_count: 0,
52+
last_frame_ms: 0.0,
53+
logo: logo_start(),
54+
logo_pattern_index: 0,
55+
})
56+
let app = @rabbita.cell(model=initial_model, update~, view~, subscriptions~)
57+
@rabbita.new(app).mount("app")
58+
}

0 commit comments

Comments
 (0)