Skip to content

Commit

Permalink
Merge pull request #7 from Respo/text-node
Browse files Browse the repository at this point in the history
get a text_node short hand
  • Loading branch information
NoEgAm authored Dec 5, 2024
2 parents 44f103f + e8e86ed commit 8fcd665
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 34 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Respo in MoonBit(Early Stage)
# Respo in MoonBit(Beta)

> tiny toy virtual DOM library ported from [Respo.rs](https://github.com/Respo/respo.rs).
Expand All @@ -15,6 +15,10 @@ Core ideas:

This project is in early stage, APIs and structure may change.

TODO:

- immutable data enhancement

### Usage

```bash
Expand Down
4 changes: 2 additions & 2 deletions moon.mod.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tiye/respo",
"version": "0.0.15",
"version": "0.0.17",
"deps": {
"tiye/dom-ffi": "0.0.6",
"tiye/cirru-parser": "0.0.7"
Expand All @@ -9,6 +9,6 @@
"repository": "https://github.com/Respo/respo.mbt/",
"license": "Apache-2.0",
"keywords": ["virtual-dom"],
"description": "A tiny virtual DOM library(preview mode)",
"description": "A tiny virtual DOM library(beta)",
"source": "src"
}
79 changes: 79 additions & 0 deletions src/lib/memo.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! Memoization utilities. based on work of [@hackwaly](https://taolun.moonbitlang.com/t/topic/958/2)

pub fn memoize1[K : Hash + Eq, V](f : (K) -> V) -> (K) -> V {
let map = @hashmap.new()
fn(k : K) -> V {
match map[k] {
Some(v) => v
None => {
let v = f(k)
map[k] = v
v
}
}
}
}

pub fn memoize2[K1 : Hash + Eq, K2 : Hash + Eq, V](
f : (K1, K2) -> V
) -> (K1, K2) -> V {
let map = @hashmap.new()
fn(k1 : K1, k2 : K2) -> V {
match map[(k1, k2)] {
Some(v) => v
None => {
let v = f(k1, k2)
map[(k1, k2)] = v
v
}
}
}
}

pub fn memoize3[K1 : Hash + Eq, K2 : Hash + Eq, K3 : Hash + Eq, V](
f : (K1, K2, K3) -> V
) -> (K1, K2, K3) -> V {
let map = @hashmap.new()
fn(k1 : K1, k2 : K2, k3 : K3) -> V {
match map[(k1, k2, k3)] {
Some(v) => v
None => {
let v = f(k1, k2, k3)
map[(k1, k2, k3)] = v
v
}
}
}
}

pub fn memoize4[K1 : Hash + Eq, K2 : Hash + Eq, K3 : Hash + Eq, K4 : Hash + Eq, V](
f : (K1, K2, K3, K4) -> V
) -> (K1, K2, K3, K4) -> V {
let map = @hashmap.new()
fn(k1 : K1, k2 : K2, k3 : K3, k4 : K4) -> V {
match map[(k1, k2, k3, k4)] {
Some(v) => v
None => {
let v = f(k1, k2, k3, k4)
map[(k1, k2, k3, k4)] = v
v
}
}
}
}

pub fn memoize5[K1 : Hash + Eq, K2 : Hash + Eq, K3 : Hash + Eq, K4 : Hash + Eq, K5 : Hash + Eq, V](
f : (K1, K2, K3, K4, K5) -> V
) -> (K1, K2, K3, K4, K5) -> V {
let map = @hashmap.new()
fn(k1 : K1, k2 : K2, k3 : K3, k4 : K4, k5 : K5) -> V {
match map[(k1, k2, k3, k4, k5)] {
Some(v) => v
None => {
let v = f(k1, k2, k3, k4, k5)
map[(k1, k2, k3, k4, k5)] = v
v
}
}
}
}
14 changes: 14 additions & 0 deletions src/lib/node/alias.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ pub fn span[T](
)
}

/// internally using span element to render text.
pub fn text_node[T](
class_name? : String,
style? : RespoStyle,
text : String
) -> RespoNode[T] {
span(
inner_text=text,
class_name=class_name.or_default(),
style=style.or_default(),
[],
)
}

pub fn button[T](
class_name? : String,
inner_text~ : String,
Expand Down
48 changes: 39 additions & 9 deletions src/lib/node/css.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ pub fn to_string(self : RespoStyle) -> String {
result
}

pub fn insert(
self : RespoStyle,
property : String,
value : String
) -> RespoStyle {
/// for custom styles not defined with enum, use this function to add
pub fn add(self : RespoStyle, property : String, value : String) -> RespoStyle {
self._.push((property, value))
self
}
Expand All @@ -27,7 +24,7 @@ pub fn merge(self : RespoStyle, other : RespoStyle) -> RespoStyle {
let mut result = self
for pair in other._ {
let (property, value) = pair
result = result.insert(property, value)
result = result.add(property, value)
}
result
}
Expand Down Expand Up @@ -111,7 +108,9 @@ pub fn respo_style(
content? : String,
content_visibility? : CssContentVisibility,
filter? : CssFilter,
object_fit? : CssObjectFit
object_fit? : CssObjectFit,
overscroll_behavior_x? : CssOverscrollBehavior,
overscroll_behavior_y? : CssOverscrollBehavior
) -> RespoStyle {
let style : Array[(String, String)] = []
match color {
Expand Down Expand Up @@ -377,6 +376,14 @@ pub fn respo_style(
Some(value) => style.push(("object-fit", value.to_string()))
None => ()
}
match overscroll_behavior_x {
Some(value) => style.push(("overscroll-behavior-x", value.to_string()))
None => ()
}
match overscroll_behavior_y {
Some(value) => style.push(("overscroll-behavior-y", value.to_string()))
None => ()
}
RespoStyle(style)
}

Expand Down Expand Up @@ -458,6 +465,8 @@ pub(all) enum CssColor {
Cyan
Orange
Pink
RawString(String)
Transparent
} derive(Eq)

pub fn CssColor::to_string(self : CssColor) -> String {
Expand All @@ -480,6 +489,8 @@ pub fn CssColor::to_string(self : CssColor) -> String {
Cyan => "cyan"
Orange => "orange"
Pink => "pink"
RawString(value) => value
Transparent => "transparent"
}
}

Expand Down Expand Up @@ -968,6 +979,20 @@ pub fn CssObjectFit::to_string(self : CssObjectFit) -> String {
}
}

pub(all) enum CssOverscrollBehavior {
Auto
Contain
None
}

pub fn CssOverscrollBehavior::to_string(self : CssOverscrollBehavior) -> String {
match self {
Auto => "auto"
Contain => "contain"
None => "none"
}
}

// /// turns `src/a/b.rs` into `a_b`, (used inside macro)
// pub fn css_name_from_path(p: &str) -> String {
// let mut s = p.to_owned();
Expand All @@ -982,7 +1007,12 @@ pub fn CssObjectFit::to_string(self : CssObjectFit) -> String {

let class_name_in_tags : @hashset.T[String] = @hashset.new()

/// Moonbit version, use [T] for <T> for generics, GC language no need to use to_owned() and &
/// Declare a static style in the head of the documentm for example
/// ```moonbit
/// let style_demo : String = declare_static_style(
/// [("&", respo_style(margin=Px(4), background_color=Hsl(200, 90, 96)))],
/// )
/// ```
pub fn declare_static_style[U : Show](
rules : Array[(U, RespoStyle)],
loc~ : SourceLoc = _
Expand Down Expand Up @@ -1020,7 +1050,7 @@ pub fn declare_static_style[U : Show](
}
style_tag.set_inner_html(styles)
head.reinterpret_as_node().append_child(style_tag.reinterpret_as_node())
class_name_in_tags.insert(gen_name)
class_name_in_tags.add(gen_name)
gen_name
}
}
6 changes: 3 additions & 3 deletions src/lib/node/diff.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn diff_tree[T](
let skipped : @hashset.T[Int] = @hashset.new()
for idx, effect in effects {
match old_effects.get(idx) {
Some(old_effect) => if effect == old_effect { skipped.insert(idx) }
Some(old_effect) => if effect == old_effect { skipped.add(idx) }
None => ()
}
}
Expand Down Expand Up @@ -166,7 +166,7 @@ fn diff_attrs[T](
for pair in old_attrs.iter() {
let (key, _) = pair
if not(new_attrs.contains(key)) {
removed.insert(key)
removed.add(key)
if inner_changed(key) {
reset_inner.val = true
}
Expand Down Expand Up @@ -204,7 +204,7 @@ fn diff_style[T](
for pair in old_style {
let (key, _) = pair
if not(new_style.contains(key)) {
removed.insert(key)
removed.add(key)
}
}
if not(added.is_empty()) || not(removed.is_empty()) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/node/element.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub fn set_attribute[T](

// TODO implement methods for RespoElement

/// create attributes for an element
pub fn respo_attrs(
id? : String,
class_name? : String,
Expand Down
Empty file removed src/lib/state.mbt
Empty file.
6 changes: 6 additions & 0 deletions src/lib/states-tree.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ pub(all) struct RespoStatesTree {
branches : Map[String, RespoStatesTree]
}

impl Eq for RespoStatesTree with op_equal(self, other) {
self.cursor == other.cursor &&
self.data == other.data &&
self.branches == other.branches
}

pub fn to_json(self : RespoStatesTree) -> @json.JsonValue {
let object = {}
object.set("data", self.data.to_json()) // TODO need to use manual version by now
Expand Down
23 changes: 23 additions & 0 deletions src/lib/ui.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,26 @@ pub let ui_row_parted : String = declare_static_style(
),
],
)

/// common CSS resets for Respo pages
pub let preset : String = declare_static_style(
[
(
"body",
respo_style(
margin=Px(0),
overscroll_behavior_x=None,
overscroll_behavior_y=None,
),
),
("body *", respo_style(box_sizing=BorderBox)),
("::-webkit-scrollbar", respo_style(width=Px(4), height=Px(4))),
("::-webkit-scrollbar-track", respo_style(background_color=Hsl(0, 0, 100))),
(
"::-webkit-scrollbar-thumb",
respo_style(background_color=Hsla(180, 40, 76, 0.8)),
),
("::-webkit-scrollbar-corner", respo_style(background_color=Transparent)),
("::-webkit-resizer", respo_style(background_color=Transparent)),
],
)
1 change: 0 additions & 1 deletion src/lib/web-sys/moon.pkg.json

This file was deleted.

12 changes: 4 additions & 8 deletions src/main/counter.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,21 @@ fn comp_counter(
),
@respo_node.div(
[
@respo_node.span(
inner_text="value is: " + counted.to_string(),
@respo_node.text_node(
"value is: " + counted.to_string(),
style=respo_style(
color=Hsluv(270, 100, 40),
font_family="Menlo",
font_size=counted.reinterpret_as_uint() + 10,
),
[],
),
],
),
@respo_node.div(
[
@respo_node.span(inner_text="local state: \{counted}", []),
text_node("local state: \{counted}"),
@respo_node.br(),
@respo_node.span(
inner_text="global state: " + global_counted.to_string(),
[],
),
text_node("global state: " + global_counted.to_string()),
],
),
],
Expand Down
2 changes: 1 addition & 1 deletion src/main/main.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn view(
// @dom_ffi.log("Store to render: " + store.to_json().stringify(indent=2))
let states = store.get_states()
div(
class_name=@respo.ui_global,
class_name=str_spaced([@respo.ui_global, @respo.preset]),
style=respo_style(padding=Px(12)),
[
comp_counter(states.pick("counter"), store.counted),
Expand Down
3 changes: 2 additions & 1 deletion src/main/moon.pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"input",
"button",
"declare_static_style",
"respo_style"
"respo_style",
"text_node"
]
},
{ "path": "tiye/respo/lib/dialog", "alias": "dialog" },
Expand Down
2 changes: 1 addition & 1 deletion src/main/panel.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn comp_panel(
inner_text="add",
event={}..set(Click, on_submit),
),
span(inner_text="got panel state: \{state.to_json()}", []),
text_node("got panel state: \{state.to_json()}"),
],
),
)
Expand Down
Loading

0 comments on commit 8fcd665

Please sign in to comment.