mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Move dioxus-specifc code into dioxus-tui crate and rename core crate to Rink
This commit is contained in:
parent
8e8c89c99e
commit
f34fa5d974
55 changed files with 241 additions and 55 deletions
|
@ -15,7 +15,8 @@ members = [
|
|||
"packages/liveview",
|
||||
"packages/autofmt",
|
||||
"packages/rsx",
|
||||
"packages/tui",
|
||||
"packages/dioxus-tui",
|
||||
"packages/rink",
|
||||
"packages/native-core",
|
||||
"packages/native-core-macro",
|
||||
"packages/rsx-rosetta",
|
||||
|
|
|
@ -13,7 +13,7 @@ dioxus-web = { path = "../../packages/web" }
|
|||
dioxus-ssr = { path = "../../packages/ssr" }
|
||||
dioxus-router = { path = "../../packages/router" }
|
||||
dioxus-liveview = { path = "../../packages/liveview", features = ["axum"] }
|
||||
dioxus-tui = { path = "../../packages/tui" }
|
||||
dioxus-tui = { path = "../../packages/dioxus-tui" }
|
||||
fermi = { path = "../../packages/fermi" }
|
||||
|
||||
|
||||
|
|
|
@ -13,25 +13,18 @@ license = "MIT/Apache-2.0"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { path = "../dioxus", version = "^0.3.0", optional = true }
|
||||
dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"], optional = true }
|
||||
dioxus = { path = "../dioxus", version = "^0.3.0" }
|
||||
dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"] }
|
||||
dioxus-html = { path = "../html", version = "^0.3.0" }
|
||||
dioxus-native-core = { path = "../native-core", version = "^0.2.0" }
|
||||
dioxus-native-core = { path = "../native-core", version = "^0.2.0", features = ["dioxus"] }
|
||||
dioxus-native-core-macro = { path = "../native-core-macro", version = "^0.3.0" }
|
||||
dioxus-hot-reload = { path = "../hot-reload", optional = true }
|
||||
rink = { path = "../rink" }
|
||||
|
||||
tui = "0.17.0"
|
||||
crossterm = "0.23.0"
|
||||
anyhow = "1.0.42"
|
||||
tokio = { version = "1.15.0", features = ["full"] }
|
||||
futures = "0.3.19"
|
||||
taffy = "0.2.1"
|
||||
smallvec = "1.6"
|
||||
rustc-hash = "1.1.0"
|
||||
anymap = "1.0.0-beta.2"
|
||||
futures-channel = "0.3.25"
|
||||
shipyard = { version = "0.6.2", features = ["proc", "std"], default-features = false }
|
||||
once_cell = "1.17.1"
|
||||
|
||||
[dev-dependencies]
|
||||
dioxus = { path = "../dioxus" }
|
||||
|
@ -43,6 +36,5 @@ name = "update"
|
|||
harness = false
|
||||
|
||||
[features]
|
||||
default = ["hot-reload", "dioxus-bindings"]
|
||||
default = ["hot-reload"]
|
||||
hot-reload = ["dioxus-hot-reload"]
|
||||
dioxus-bindings = ["dioxus", "dioxus-core", "dioxus-native-core/dioxus"]
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
@ -1,7 +1,6 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_html::FormData;
|
||||
use dioxus_tui::prelude::*;
|
||||
use dioxus_tui::Config;
|
||||
|
||||
fn main() {
|
||||
dioxus_tui::launch_cfg(app, Config::new());
|
|
@ -1,3 +1,6 @@
|
|||
pub mod prelude;
|
||||
pub mod widgets;
|
||||
|
||||
use std::{
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
|
@ -11,7 +14,8 @@ use dioxus_native_core::{
|
|||
NodeId, RealDom,
|
||||
};
|
||||
|
||||
use crate::{query::Query, render, Config, Renderer, TuiContext};
|
||||
pub use rink::Config;
|
||||
use rink::{query::Query, render, Renderer, TuiContext};
|
||||
|
||||
pub fn launch(app: Component<()>) {
|
||||
launch_cfg(app, Config::default())
|
||||
|
@ -29,11 +33,8 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
|
|||
};
|
||||
let dioxus_state = Rc::new(RwLock::new(dioxus_state));
|
||||
let mut vdom = VirtualDom::new_with_props(app, props)
|
||||
.with_root_context(TuiContext { tx: event_tx })
|
||||
.with_root_context(Query {
|
||||
rdom: rdom.clone(),
|
||||
stretch: taffy.clone(),
|
||||
})
|
||||
.with_root_context(TuiContext::new(event_tx))
|
||||
.with_root_context(Query::new(rdom.clone(), taffy.clone()))
|
||||
.with_root_context(DioxusElementToNodeId {
|
||||
mapping: dioxus_state.clone(),
|
||||
});
|
2
packages/dioxus-tui/src/prelude/mod.rs
Normal file
2
packages/dioxus-tui/src/prelude/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub use crate::widgets::*;
|
||||
pub use rink::Config;
|
|
@ -1,11 +1,11 @@
|
|||
use crate::widgets::get_root_id;
|
||||
use crate::Query;
|
||||
use crossterm::{cursor::MoveTo, execute};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_elements::input_data::keyboard_types::Key;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_html::FormData;
|
||||
use dioxus_native_core::utils::cursor::{Cursor, Pos};
|
||||
use rink::Query;
|
||||
use std::{collections::HashMap, io::stdout};
|
||||
use taffy::geometry::Point;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::widgets::get_root_id;
|
||||
use crate::Query;
|
||||
use crossterm::{cursor::*, execute};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_elements::input_data::keyboard_types::Key;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_html::FormData;
|
||||
use dioxus_native_core::utils::cursor::{Cursor, Pos};
|
||||
use rink::Query;
|
||||
use std::{collections::HashMap, io::stdout};
|
||||
use taffy::geometry::Point;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::widgets::get_root_id;
|
||||
use crate::Query;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_elements::input_data::keyboard_types::Key;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_html::FormData;
|
||||
use rink::Query;
|
||||
|
||||
#[derive(Props)]
|
||||
pub(crate) struct SliderProps<'a> {
|
|
@ -1,11 +1,11 @@
|
|||
use crate::widgets::get_root_id;
|
||||
use crate::Query;
|
||||
use crossterm::{cursor::*, execute};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_elements::input_data::keyboard_types::Key;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_html::FormData;
|
||||
use dioxus_native_core::utils::cursor::{Cursor, Pos};
|
||||
use rink::Query;
|
||||
use std::{collections::HashMap, io::stdout};
|
||||
use taffy::geometry::Point;
|
||||
|
2
packages/rink/.gitignore
vendored
Normal file
2
packages/rink/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
2
packages/rink/.vscode/spellright.dict
vendored
Normal file
2
packages/rink/.vscode/spellright.dict
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
esque
|
||||
Tui
|
39
packages/rink/Cargo.toml
Normal file
39
packages/rink/Cargo.toml
Normal file
|
@ -0,0 +1,39 @@
|
|||
[package]
|
||||
name = "rink"
|
||||
version = "0.2.2"
|
||||
authors = ["Jonathan Kelley, @dementhos"]
|
||||
edition = "2021"
|
||||
description = "TUI-based renderer for Dioxus"
|
||||
repository = "https://github.com/DioxusLabs/dioxus/"
|
||||
homepage = "https://dioxuslabs.com"
|
||||
documentation = "https://dioxuslabs.com"
|
||||
keywords = ["dom", "ui", "gui", "react", "terminal"]
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus-html = { path = "../html", version = "^0.3.0" }
|
||||
dioxus-native-core = { path = "../native-core", version = "^0.2.0" }
|
||||
dioxus-native-core-macro = { path = "../native-core-macro", version = "^0.3.0" }
|
||||
|
||||
tui = "0.17.0"
|
||||
crossterm = "0.23.0"
|
||||
anyhow = "1.0.42"
|
||||
tokio = { version = "1.15.0", features = ["full"] }
|
||||
futures = "0.3.19"
|
||||
taffy = "0.2.1"
|
||||
smallvec = "1.6"
|
||||
rustc-hash = "1.1.0"
|
||||
anymap = "1.0.0-beta.2"
|
||||
futures-channel = "0.3.25"
|
||||
shipyard = { version = "0.6.2", features = ["proc", "std"], default-features = false }
|
||||
once_cell = "1.17.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1" }
|
||||
criterion = "0.3.5"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
parallel = ["shipyard/parallel"]
|
90
packages/rink/README.md
Normal file
90
packages/rink/README.md
Normal file
|
@ -0,0 +1,90 @@
|
|||
<div align="center">
|
||||
<h1>Rink</h1>
|
||||
<p>
|
||||
<strong>A beautiful terminal user interfaces library in Rust.</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<!-- Crates version -->
|
||||
<a href="https://crates.io/crates/rink">
|
||||
<img src="https://img.shields.io/crates/v/rink.svg?style=flat-square"
|
||||
alt="Crates.io version" />
|
||||
</a>
|
||||
<!-- Downloads -->
|
||||
<a href="https://crates.io/crates/rink">
|
||||
<img src="https://img.shields.io/crates/d/rink.svg?style=flat-square"
|
||||
alt="Download" />
|
||||
</a>
|
||||
<!-- docs -->
|
||||
<a href="https://docs.rs/rink">
|
||||
<img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square"
|
||||
alt="docs.rs docs" />
|
||||
</a>
|
||||
<!-- CI -->
|
||||
<a href="https://github.com/jkelleyrtp/rink/actions">
|
||||
<img src="https://github.com/dioxuslabs/rink/actions/workflows/main.yml/badge.svg"
|
||||
alt="CI status" />
|
||||
</a>
|
||||
<!-- Discord -->
|
||||
<a href="https://discord.gg/XgGxMSkvUM">
|
||||
<img src="https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square" alt="Discord Link" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces.
|
||||
|
||||
```rust
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
width: "100%",
|
||||
height: "10px",
|
||||
background_color: "red",
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
"Hello world!"
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
![demo app](examples/example.png)
|
||||
|
||||
## Background
|
||||
|
||||
You can use Html-like semantics with inline styles, tree hierarchy, components, and more in your [`text-based user interface (TUI)`](https://en.wikipedia.org/wiki/Text-based_user_interface) application.
|
||||
|
||||
Rink is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/) and [`Dioxus`](https://dioxuslabs.com/). Rink doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful.
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Subset of Html**
|
||||
Terminals can only render a subset of HTML. We support as much as we can.
|
||||
- **Particular frontend design**
|
||||
Terminals and browsers are and look different. Therefore, the same design might not be the best to cover both renderers.
|
||||
|
||||
## Status
|
||||
|
||||
**WARNING: Rink is currently under construction!**
|
||||
|
||||
Rendering a VirtualDom works fine, but the ecosystem of hooks is not yet ready. Additionally, some bugs in the flexbox implementation might be quirky at times.
|
||||
|
||||
## Features
|
||||
|
||||
Rink features:
|
||||
|
||||
- [x] Flexbox-based layout system
|
||||
- [ ] CSS selectors
|
||||
- [x] inline CSS support
|
||||
- [x] Built-in focusing system
|
||||
|
||||
* [x] Widgets<sup>1</sup>
|
||||
* [ ] Support for events, hooks, and callbacks<sup>2</sup>
|
||||
* [ ] Html tags<sup>3</sup>
|
||||
|
||||
<sup>1</sup> Currently only a subset of the input element is implemented as a component (not an element). The `Input` component supports sliders, text, numbers, passwords, buttons, and checkboxes.
|
||||
<sup>2</sup> Basic keyboard, mouse, and focus events are implemented.
|
||||
<sup>3</sup> Currently, most HTML tags don't translate into any meaning inside of Dioxus TUI. So an `input` _element_ won't mean anything nor does it have any additional functionality.
|
BIN
packages/rink/examples/example.png
Normal file
BIN
packages/rink/examples/example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
|
@ -46,18 +46,13 @@ impl Default for Config {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum RenderingMode {
|
||||
/// only 16 colors by accessed by name, no alpha support
|
||||
BaseColors,
|
||||
/// 8 bit colors, will be downsampled from rgb colors
|
||||
Ansi,
|
||||
/// 24 bit colors, most terminals support this
|
||||
#[default]
|
||||
Rgb,
|
||||
}
|
||||
|
||||
impl Default for RenderingMode {
|
||||
fn default() -> Self {
|
||||
RenderingMode::Rgb
|
||||
}
|
||||
}
|
|
@ -19,8 +19,9 @@ use dioxus_native_core::node_ref::NodeView;
|
|||
#[derive(Component)]
|
||||
pub struct Focused(pub bool);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
pub(crate) enum FocusLevel {
|
||||
#[default]
|
||||
Unfocusable,
|
||||
Focusable,
|
||||
Ordered(std::num::NonZeroU16),
|
||||
|
@ -58,12 +59,6 @@ impl Ord for FocusLevel {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for FocusLevel {
|
||||
fn default() -> Self {
|
||||
FocusLevel::Unfocusable
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Default, Component)]
|
||||
pub(crate) struct Focus {
|
||||
pub level: FocusLevel,
|
|
@ -27,8 +27,6 @@ use tokio::select;
|
|||
use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
|
||||
|
||||
mod config;
|
||||
#[cfg(feature = "dioxus-bindings")]
|
||||
pub mod dioxus;
|
||||
mod focus;
|
||||
mod hooks;
|
||||
mod layout;
|
||||
|
@ -39,16 +37,10 @@ mod render;
|
|||
mod style;
|
||||
mod style_attributes;
|
||||
mod widget;
|
||||
#[cfg(feature = "dioxus-bindings")]
|
||||
mod widgets;
|
||||
|
||||
#[cfg(feature = "dioxus-bindings")]
|
||||
pub use crate::dioxus::*;
|
||||
pub use config::*;
|
||||
pub use hooks::*;
|
||||
pub use query::Query;
|
||||
#[cfg(feature = "dioxus-bindings")]
|
||||
pub use widgets::*;
|
||||
|
||||
// the layout space has a multiplier of 10 to minimize rounding errors
|
||||
pub(crate) fn screen_to_layout_space(screen: u16) -> f32 {
|
||||
|
@ -69,6 +61,10 @@ pub struct TuiContext {
|
|||
}
|
||||
|
||||
impl TuiContext {
|
||||
pub fn new(tx: UnboundedSender<InputEvent>) -> Self {
|
||||
Self { tx }
|
||||
}
|
||||
|
||||
pub fn quit(&self) {
|
||||
self.tx.unbounded_send(InputEvent::Close).unwrap();
|
||||
}
|
|
@ -2,7 +2,7 @@ use dioxus_native_core::{node_ref::NodeView, Dependancy, SendAnyMap, State};
|
|||
use dioxus_native_core_macro::partial_derive_state;
|
||||
use shipyard::Component;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Component)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Component, Default)]
|
||||
pub(crate) enum PreventDefault {
|
||||
Focus,
|
||||
KeyPress,
|
||||
|
@ -14,6 +14,7 @@ pub(crate) enum PreventDefault {
|
|||
MouseEnter,
|
||||
MouseLeave,
|
||||
MouseOut,
|
||||
#[default]
|
||||
Unknown,
|
||||
MouseOver,
|
||||
ContextMenu,
|
||||
|
@ -21,12 +22,6 @@ pub(crate) enum PreventDefault {
|
|||
MouseUp,
|
||||
}
|
||||
|
||||
impl Default for PreventDefault {
|
||||
fn default() -> Self {
|
||||
PreventDefault::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
#[partial_derive_state]
|
||||
impl State for PreventDefault {
|
||||
type ParentDependencies = ();
|
|
@ -47,6 +47,10 @@ pub struct Query {
|
|||
}
|
||||
|
||||
impl Query {
|
||||
pub fn new(rdom: Arc<RwLock<RealDom>>, stretch: Arc<Mutex<Taffy>>) -> Self {
|
||||
Self { rdom, stretch }
|
||||
}
|
||||
|
||||
pub fn get(&self, id: NodeId) -> ElementRef {
|
||||
let rdom = self.rdom.read();
|
||||
let stretch = self.stretch.lock();
|
73
packages/rink/test.html
Normal file
73
packages/rink/test.html
Normal file
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: black;
|
||||
/* justify-content: center;
|
||||
align-items: center; */
|
||||
/* margin: auto; */
|
||||
}
|
||||
|
||||
.smaller {
|
||||
height: 70%;
|
||||
width: 70%;
|
||||
background-color: green;
|
||||
/* justify-content: center; */
|
||||
/* align-items: center; */
|
||||
}
|
||||
|
||||
.superinner {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
/* display: flex; */
|
||||
/* */
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
/* */
|
||||
background-color: red;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
/* margin: 20px; */
|
||||
/* margin: 20px; */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="smaller">
|
||||
<div class="superinner">
|
||||
<h1>Hello World</h1>
|
||||
<p>This is a test</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="container">
|
||||
<div class="smaller">
|
||||
hello world
|
||||
<div style="color: green; margin: 40px;">
|
||||
goodbye
|
||||
<div style="color:red;">
|
||||
asdasdasd
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue