Move dioxus-specifc code into dioxus-tui crate and rename core crate to Rink

This commit is contained in:
Evan Almloff committed 2023-03-13 12:04:51 -05:00
1 parent 8e8c89c99e
commit f34fa5d974
55 files changed
+241 -55

No files matched your search

@@ -0,0 +1,85 @@
use dioxus::prelude::*;
use dioxus_html::{FocusData, KeyboardData, MouseData, WheelData};
use std::rc::Rc;
fn main() {
dioxus_tui::launch(app);
}
#[derive(Debug)]
enum Event {
MouseMove(Rc<MouseData>),
MouseClick(Rc<MouseData>),
MouseDoubleClick(Rc<MouseData>),
MouseDown(Rc<MouseData>),
MouseUp(Rc<MouseData>),
Wheel(Rc<WheelData>),
KeyDown(Rc<KeyboardData>),
KeyUp(Rc<KeyboardData>),
KeyPress(Rc<KeyboardData>),
FocusIn(Rc<FocusData>),
FocusOut(Rc<FocusData>),
}
const MAX_EVENTS: usize = 8;
fn app(cx: Scope) -> Element {
let events = use_ref(cx, Vec::new);
let events_lock = events.read();
let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
let events_rendered = events_lock[first_index..].iter().map(|event| {
// TUI panics if text overflows (https://github.com/DioxusLabs/dioxus/issues/371)
// temporary hack: just trim the strings (and make sure viewport is big enough)
// todo: remove
let mut trimmed = format!("{event:?}");
trimmed.truncate(200);
rsx!(p { "{trimmed}" })
});
let log_event = move |event: Event| {
events.write().push(event);
};
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
div {
width: "80%",
height: "50%",
border_width: "1px",
justify_content: "center",
align_items: "center",
background_color: "hsl(248, 53%, 58%)",
onmousemove: move |event| log_event(Event::MouseMove(event.inner().clone())),
onclick: move |event| log_event(Event::MouseClick(event.inner().clone())),
ondblclick: move |event| log_event(Event::MouseDoubleClick(event.inner().clone())),
onmousedown: move |event| log_event(Event::MouseDown(event.inner().clone())),
onmouseup: move |event| log_event(Event::MouseUp(event.inner().clone())),
onwheel: move |event| log_event(Event::Wheel(event.inner().clone())),
onkeydown: move |event| log_event(Event::KeyDown(event.inner().clone())),
onkeyup: move |event| log_event(Event::KeyUp(event.inner().clone())),
onkeypress: move |event| log_event(Event::KeyPress(event.inner().clone())),
onfocusin: move |event| log_event(Event::FocusIn(event.inner().clone())),
onfocusout: move |event| log_event(Event::FocusOut(event.inner().clone())),
"Hover, click, type or scroll to see the info down below"
},
div {
width: "80%",
height: "50%",
flex_direction: "column",
events_rendered,
},
},
})
}
+27
View File
@@ -0,0 +1,27 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
let radius = use_state(cx, || 0);
cx.render(rsx! {
div {
width: "100%",
height: "100%",
justify_content: "center",
align_items: "center",
background_color: "hsl(248, 53%, 58%)",
onwheel: move |w| radius.modify(|r| (r + w.delta().strip_units().y as i8).abs()),
border_style: "solid none solid double",
border_width: "thick",
border_radius: "{radius}px",
border_color: "#0000FF #FF00FF #FF0000 #00FF00",
"{radius}"
}
})
}
+94
View File
@@ -0,0 +1,94 @@
use dioxus::prelude::*;
use dioxus_html::input_data::keyboard_types::Code;
fn main() {
dioxus_tui::launch(app);
}
#[derive(PartialEq, Props)]
struct ButtonProps {
color_offset: u32,
layer: u16,
}
#[allow(non_snake_case)]
fn Button(cx: Scope<ButtonProps>) -> Element {
let toggle = use_state(cx, || false);
let hovered = use_state(cx, || false);
let hue = cx.props.color_offset % 255;
let saturation = if *toggle.get() { 50 } else { 25 } + if *hovered.get() { 50 } else { 25 };
let brightness = saturation / 2;
let color = format!("hsl({hue}, {saturation}, {brightness})");
cx.render(rsx! {
div{
width: "100%",
height: "100%",
background_color: "{color}",
tabindex: "{cx.props.layer}",
onkeydown: |e| {
if let Code::Space = e.inner().code() {
toggle.modify(|f| !f);
}
},
onclick: |_| {
toggle.modify(|f| !f);
},
onmouseenter: |_|{
hovered.set(true);
},
onmouseleave: |_|{
hovered.set(false);
},
justify_content: "center",
align_items: "center",
display: "flex",
flex_direction: "column",
p{"tabindex: {cx.props.layer}"}
}
})
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
display: "flex",
flex_direction: "column",
width: "100%",
height: "100%",
(1..8).map(|y|
rsx!{
div{
display: "flex",
flex_direction: "row",
width: "100%",
height: "100%",
(1..8).map(|x|{
if (x + y) % 2 == 0{
rsx!{
div{
width: "100%",
height: "100%",
background_color: "rgb(100, 100, 100)",
}
}
}
else{
let layer = (x + y) % 3;
rsx!{
Button{
color_offset: x * y,
layer: layer as u16,
}
}
}
})
}
}
)
}
})
}
@@ -0,0 +1,45 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch_cfg(
app,
dioxus_tui::Config::default().with_rendering_mode(dioxus_tui::RenderingMode::Ansi),
);
}
fn app(cx: Scope) -> Element {
let steps = 50;
cx.render(rsx! {
div{
width: "100%",
height: "100%",
flex_direction: "column",
(0..=steps).map(|x|
{
let hue = x as f32*360.0/steps as f32;
rsx! {
div{
width: "100%",
height: "100%",
flex_direction: "row",
(0..=steps).map(|y|
{
let alpha = y as f32*100.0/steps as f32;
rsx! {
div {
left: "{x}px",
top: "{y}px",
width: "10%",
height: "100%",
background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
}
}
}
)
}
}
}
)
}
})
}
@@ -0,0 +1,35 @@
use dioxus::core::RenderReturn;
use dioxus::prelude::*;
use dioxus_tui::query::Query;
use dioxus_tui::DioxusElementToNodeId;
use dioxus_tui::Size;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
let hue = use_state(cx, || 0.0);
let brightness = use_state(cx, || 0.0);
let tui_query: Query = cx.consume_context().unwrap();
let mapping: DioxusElementToNodeId = cx.consume_context().unwrap();
// disable templates so that every node has an id and can be queried
cx.render(rsx! {
div{
width: "100%",
background_color: "hsl({hue}, 70%, {brightness}%)",
onmousemove: move |evt| {
if let RenderReturn::Ready(node) = cx.root_node() {
if let Some(id) = node.root_ids.get(0){
let node = tui_query.get(mapping.get_node_id(id).unwrap());
let Size{width, height} = node.size().unwrap();
let pos = evt.inner().element_coordinates();
hue.set((pos.x as f32/width as f32)*255.0);
brightness.set((pos.y as f32/height as f32)*100.0);
}
}
},
"hsl({hue}, 70%, {brightness}%)",
}
})
}
@@ -0,0 +1,67 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_tui::Config;
fn main() {
dioxus_tui::launch_cfg(app, Config::default());
}
#[derive(Props, PartialEq)]
struct QuadrentProps {
color: String,
text: String,
}
fn Quadrant(cx: Scope<QuadrentProps>) -> Element {
cx.render(rsx! {
div {
border_width: "1px",
width: "50%",
height: "100%",
background_color: "{cx.props.color}",
justify_content: "center",
align_items: "center",
"{cx.props.text}"
}
})
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
div {
width: "100%",
height: "50%",
flex_direction: "row",
Quadrant{
color: "red".to_string(),
text: "[A]".to_string()
},
Quadrant{
color: "black".to_string(),
text: "[B]".to_string()
}
}
div {
width: "100%",
height: "50%",
flex_direction: "row",
Quadrant{
color: "green".to_string(),
text: "[C]".to_string()
},
Quadrant{
color: "blue".to_string(),
text: "[D]".to_string()
}
}
}
})
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

+82
View File
@@ -0,0 +1,82 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
// justify_content: "center",
// align_items: "center",
// flex_direction: "row",
// background_color: "red",
p {
background_color: "black",
flex_direction: "column",
justify_content: "center",
align_items: "center",
// height: "10%",
"hi"
"hi"
"hi"
}
li {
background_color: "red",
flex_direction: "column",
justify_content: "center",
align_items: "center",
// height: "10%",
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
}
li {
background_color: "blue",
flex_direction: "column",
justify_content: "center",
align_items: "center",
// height: "10%",
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
}
p {
background_color: "yellow",
"asd"
}
p {
background_color: "green",
"asd"
}
p {
background_color: "white",
"asd"
}
p {
background_color: "cyan",
"asd"
}
}
})
}
+128
View File
@@ -0,0 +1,128 @@
use dioxus::{events::MouseData, prelude::*};
use dioxus_core::Event;
use std::convert::TryInto;
use std::rc::Rc;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
fn to_str(c: &[i32; 3]) -> String {
"#".to_string() + &c.iter().map(|c| format!("{c:02X?}")).collect::<String>()
}
fn get_brightness(m: &Rc<MouseData>) -> i32 {
let b: i32 = m.held_buttons().len().try_into().unwrap();
127 * b
}
let q1_color = use_state(cx, || [200; 3]);
let q2_color = use_state(cx, || [200; 3]);
let q3_color = use_state(cx, || [200; 3]);
let q4_color = use_state(cx, || [200; 3]);
let q1_color_str = to_str(q1_color);
let q2_color_str = to_str(q2_color);
let q3_color_str = to_str(q3_color);
let q4_color_str = to_str(q4_color);
let page_coordinates = use_state(cx, || "".to_string());
let element_coordinates = use_state(cx, || "".to_string());
let buttons = use_state(cx, || "".to_string());
let modifiers = use_state(cx, || "".to_string());
let update_data = move |event: Event<MouseData>| {
let mouse_data = event.inner();
page_coordinates.set(format!("{:?}", mouse_data.page_coordinates()));
element_coordinates.set(format!("{:?}", mouse_data.element_coordinates()));
// Note: client coordinates are also available, but they would be the same as the page coordinates in this example, because there is no scrolling.
// There are also screen coordinates, but they are currently the same as client coordinates due to technical limitations
buttons.set(format!("{:?}", mouse_data.held_buttons()));
modifiers.set(format!("{:?}", mouse_data.modifiers()));
};
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
div {
width: "100%",
height: "50%",
flex_direction: "row",
div {
border_width: "1px",
width: "50%",
height: "100%",
justify_content: "center",
align_items: "center",
background_color: "{q1_color_str}",
onmouseenter: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onmousedown: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onmouseup: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
onwheel: move |w| q1_color.set([q1_color[0] + (10.0*w.delta().strip_units().y) as i32, 0, 0]),
onmouseleave: move |_| q1_color.set([200; 3]),
onmousemove: update_data,
"click me"
}
div {
width: "50%",
height: "100%",
justify_content: "center",
align_items: "center",
background_color: "{q2_color_str}",
onmouseenter: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onmousedown: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onmouseup: move |m| q2_color.set([get_brightness(m.inner()); 3]),
onwheel: move |w| q2_color.set([q2_color[0] + (10.0*w.delta().strip_units().y) as i32;3]),
onmouseleave: move |_| q2_color.set([200; 3]),
onmousemove: update_data,
"click me"
}
}
div {
width: "100%",
height: "50%",
flex_direction: "row",
div {
width: "50%",
height: "100%",
justify_content: "center",
align_items: "center",
background_color: "{q3_color_str}",
onmouseenter: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onmousedown: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onmouseup: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
onwheel: move |w| q3_color.set([0, q3_color[1] + (10.0*w.delta().strip_units().y) as i32, 0]),
onmouseleave: move |_| q3_color.set([200; 3]),
onmousemove: update_data,
"click me"
}
div {
width: "50%",
height: "100%",
justify_content: "center",
align_items: "center",
background_color: "{q4_color_str}",
onmouseenter: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onmousedown: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onmouseup: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
onwheel: move |w| q4_color.set([0, 0, q4_color[2] + (10.0*w.delta().strip_units().y) as i32]),
onmouseleave: move |_| q4_color.set([200; 3]),
onmousemove: update_data,
"click me"
}
},
div {"Page coordinates: {page_coordinates}"},
div {"Element coordinates: {element_coordinates}"},
div {"Buttons: {buttons}"},
div {"Modifiers: {modifiers}"},
}
})
}
+28
View File
@@ -0,0 +1,28 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
border_width: "1px",
h1 { height: "2px", color: "green",
"that's awesome!"
}
ul {
flex_direction: "column",
padding_left: "3px",
(0..10).map(|i| rsx!(
"> hello {i}"
))
}
}
})
}
+50
View File
@@ -0,0 +1,50 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
background_color: "black",
margin_right: "10px",
div {
width: "70%",
height: "70%",
background_color: "green",
margin_left: "4px",
div {
width: "100%",
height: "100%",
margin_top: "2px",
margin_bottom: "2px",
margin_left: "2px",
margin_right: "2px",
flex_shrink: "0",
background_color: "red",
justify_content: "center",
align_items: "center",
flex_direction: "column",
padding_top: "2px",
padding_bottom: "2px",
padding_left: "4px",
padding_right: "4px",
"[A]"
"[A]"
"[A]"
"[A]"
}
}
}
})
}
+60
View File
@@ -0,0 +1,60 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
div {
width: "100%",
height: "50%",
flex_direction: "row",
div {
border_width: "1px",
width: "50%",
height: "100%",
background_color: "red",
justify_content: "center",
align_items: "center",
"[A]"
}
div {
width: "50%",
height: "100%",
background_color: "black",
justify_content: "center",
align_items: "center",
"[B]"
}
}
div {
width: "100%",
height: "50%",
flex_direction: "row",
div {
width: "50%",
height: "100%",
background_color: "green",
justify_content: "center",
align_items: "center",
"[C]"
}
div {
width: "50%",
height: "100%",
background_color: "blue",
justify_content: "center",
align_items: "center",
"[D]"
}
}
}
})
}
+19
View File
@@ -0,0 +1,19 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
width: "100%",
height: "10px",
background_color: "red",
justify_content: "center",
align_items: "center",
"Hello world!"
}
})
}
+114
View File
@@ -0,0 +1,114 @@
use dioxus::prelude::*;
use dioxus_tui::{Config, TuiContext};
/// This benchmarks the cache performance of the TUI for small edits by changing one box at a time.
fn main() {
for size in 1..=20usize {
for _ in 0..10 {
dioxus_tui::launch_cfg_with_props(app, size, Config::default().with_headless())
}
}
}
#[derive(Props, PartialEq)]
struct BoxProps {
x: usize,
y: usize,
hue: f32,
alpha: f32,
}
#[allow(non_snake_case)]
fn Box(cx: Scope<BoxProps>) -> Element {
let count = use_state(cx, || 0);
let x = cx.props.x * 2;
let y = cx.props.y * 2;
let hue = cx.props.hue;
let display_hue = cx.props.hue as u32 / 10;
let count = count.get();
let alpha = cx.props.alpha + (count % 100) as f32;
cx.render(rsx! {
div {
left: "{x}%",
top: "{y}%",
width: "100%",
height: "100%",
background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
align_items: "center",
p{"{display_hue:03}"}
}
})
}
#[derive(Props, PartialEq)]
struct GridProps {
size: usize,
}
#[allow(non_snake_case)]
fn Grid(cx: Scope<GridProps>) -> Element {
let size = cx.props.size;
let count = use_state(cx, || 0);
let counts = use_ref(cx, || vec![0; size * size]);
let ctx: TuiContext = cx.consume_context().unwrap();
if *count.get() + 1 >= (size * size) {
ctx.quit();
} else {
counts.with_mut(|c| {
let i = *count.current();
c[i] += 1;
c[i] %= 360;
});
count.with_mut(|i| {
*i += 1;
*i %= size * size;
});
}
render! {
div{
width: "100%",
height: "100%",
flex_direction: "column",
(0..size).map(|x|
{
rsx! {
div{
width: "100%",
height: "100%",
flex_direction: "row",
(0..size).map(|y|
{
let alpha = y as f32*100.0/size as f32 + counts.read()[x*size + y] as f32;
let key = format!("{}-{}", x, y);
rsx! {
Box{
x: x,
y: y,
alpha: 100.0,
hue: alpha,
key: "{key}",
}
}
}
)
}
}
}
)
}
}
}
fn app(cx: Scope<usize>) -> Element {
cx.render(rsx! {
div{
width: "100%",
height: "100%",
Grid{
size: *cx.props,
}
}
})
}
+32
View File
@@ -0,0 +1,32 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
let count = use_state(cx, || 0);
use_future(cx, (), move |_| {
let count = count.to_owned();
let update = cx.schedule_update();
async move {
loop {
count.with_mut(|f| *f += 1);
tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
update();
}
}
});
cx.render(rsx! {
div { width: "100%",
div { width: "50%", height: "5px", background_color: "blue", justify_content: "center", align_items: "center",
"Hello {count}!"
}
div { width: "50%", height: "10px", background_color: "red", justify_content: "center", align_items: "center",
"Hello {count}!"
}
}
})
}
+113
View File
@@ -0,0 +1,113 @@
use dioxus::prelude::*;
fn main() {
dioxus_tui::launch(app);
}
fn app(cx: Scope) -> Element {
let alpha = use_state(cx, || 100);
cx.render(rsx! {
div {
width: "100%",
height: "100%",
flex_direction: "column",
onwheel: move |evt| alpha.set((**alpha + evt.inner().delta().strip_units().y as i64).clamp(0, 100)),
p {
background_color: "black",
flex_direction: "column",
justify_content: "center",
align_items: "center",
color: "green",
"hi"
"hi"
"hi"
}
li {
background_color: "red",
flex_direction: "column",
justify_content: "center",
align_items: "center",
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
"bib"
}
li {
background_color: "blue",
flex_direction: "column",
justify_content: "center",
align_items: "center",
"zib"
"zib"
"zib"
"zib"
"zib"
"zib"
}
p {
background_color: "yellow",
"asd"
}
p {
background_color: "green",
"asd"
}
p {
background_color: "white",
"asd"
}
p {
background_color: "cyan",
"asd"
}
div {
font_weight: "bold",
color: "#666666",
p {
"bold"
}
p {
font_weight: "normal",
" normal"
}
}
p {
font_style: "italic",
color: "red",
"italic"
}
p {
text_decoration: "underline",
color: "rgba(255, 255, 255)",
"underline"
}
p {
text_decoration: "line-through",
color: "hsla(10, 100%, 70%)",
"line-through"
}
div{
position: "absolute",
top: "1px",
background_color: "rgba(255, 0, 0, 50%)",
width: "100%",
p {
color: "rgba(255, 255, 255, {alpha}%)",
background_color: "rgba(100, 100, 100, {alpha}%)",
"rgba(255, 255, 255, {alpha}%)"
}
p {
color: "rgba(255, 255, 255, 100%)",
"rgba(255, 255, 255, 100%)"
}
}
}
})
}
+92
View File
@@ -0,0 +1,92 @@
use dioxus::prelude::*;
use dioxus_html::FormData;
use dioxus_tui::prelude::*;
fn main() {
dioxus_tui::launch_cfg(app, Config::new());
}
fn app(cx: Scope) -> Element {
let bg_green = use_state(cx, || false);
let color = if *bg_green.get() { "green" } else { "red" };
cx.render(rsx! {
div{
width: "100%",
background_color: "{color}",
flex_direction: "column",
align_items: "center",
justify_content: "center",
Input{
oninput: |data: FormData| if &data.value == "good"{
bg_green.set(true);
} else{
bg_green.set(false);
},
r#type: "checkbox",
value: "good",
width: "50%",
height: "10%",
checked: "true",
}
Input{
oninput: |data: FormData| if &data.value == "hello world"{
bg_green.set(true);
} else{
bg_green.set(false);
},
width: "50%",
height: "10%",
maxlength: "11",
}
Input{
oninput: |data: FormData| {
if (data.value.parse::<f32>().unwrap() - 40.0).abs() < 5.0 {
bg_green.set(true);
} else{
bg_green.set(false);
}
},
r#type: "range",
width: "50%",
height: "10%",
min: "20",
max: "80",
}
Input{
oninput: |data: FormData| {
if data.value == "10"{
bg_green.set(true);
} else{
bg_green.set(false);
}
},
r#type: "number",
width: "50%",
height: "10%",
maxlength: "4",
}
Input{
oninput: |data: FormData| {
if data.value == "hello world"{
bg_green.set(true);
} else{
bg_green.set(false);
}
},
r#type: "password",
width: "50%",
height: "10%",
maxlength: "11",
}
Input{
onclick: |_: FormData| bg_green.set(true),
r#type: "button",
value: "green",
width: "50%",
height: "10%",
}
}
})
}