diff --git a/Cargo.toml b/Cargo.toml index d416f658e..fa9591911 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,24 @@ version = "0.0.0" edition = "2021" [workspace] -members = ["crates/renderer", "crates/state", "crates/freya", "crates/elements", "crates/components", "crates/hooks", "crates/common", "crates/core", "crates/testing", "crates/devtools", "crates/torin", "crates/engine", "./examples/installer", "crates/native-core", "crates/native-core-macro"] +members = [ + "crates/renderer", + "crates/state", + "crates/freya", + "crates/elements", + "crates/components", + "crates/hooks", + "crates/common", + "crates/core", + "crates/testing", + "crates/devtools", + "crates/torin", + "crates/engine", + "./examples/installer", + "./examples/all-components", + "crates/native-core", + "crates/native-core-macro", +] [features] log = ["freya/log"] @@ -39,15 +56,21 @@ torin = { path = "crates/torin", version = "0.2" } freya-native-core-macro = { path = "crates/native-core-macro", version = "0.2" } freya-native-core = { path = "crates/native-core", version = "0.2" } -dioxus = { version = "0.5", default-features = false, features = ["macro", "signals", "hooks"]} +dioxus = { version = "0.5", default-features = false, features = [ + "macro", + "signals", + "hooks", +] } dioxus-rsx = { version = "0.5", features = ["hot_reload"] } dioxus-core-macro = { version = "0.5" } dioxus-hooks = { version = "0.5" } dioxus-signals = { version = "0.5" } dioxus-core = { version = "0.5" } -dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-features = false } +dioxus-hot-reload = { version = "0.5", features = [ + "file_watcher", +], default-features = false } dioxus-router = { version = "0.5", default-features = false } -dioxus-sdk = { version = "0.5", features = ["clipboard"]} +dioxus-sdk = { version = "0.5", features = ["clipboard"] } skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } @@ -56,14 +79,23 @@ glutin = "0.32.0" glutin-winit = "0.5.0" raw-window-handle = "0.6.0" winit = "0.30.0" -tokio = { version = "1.33.0", features = ["sync", "rt-multi-thread", "time", "macros"] } -accesskit = { version = "0.16.0", features = ["serde"]} +tokio = { version = "1.33.0", features = [ + "sync", + "rt-multi-thread", + "time", + "macros", +] } +accesskit = { version = "0.16.0", features = ["serde"] } accesskit_winit = "0.22.0" -shipyard = { version = "0.6.2", features = ["proc", "std", "parallel"], default-features = false } +shipyard = { version = "0.6.2", features = [ + "proc", + "std", + "parallel", +], default-features = false } smallvec = "1.13.1" euclid = "0.22.9" -uuid = { version = "1.4.1", features = ["v4"]} +uuid = { version = "1.4.1", features = ["v4"] } futures-util = "0.3.30" futures-task = "0.3.30" tracing = "0.1" @@ -72,7 +104,7 @@ rustc-hash = "2.0.0" [dev-dependencies] skia-safe = { workspace = true } -tokio = { workspace = true, features = ["fs"]} +tokio = { workspace = true, features = ["fs"] } dioxus = { workspace = true } freya = { workspace = true } freya-core = { workspace = true } diff --git a/examples/all-components/Cargo.toml b/examples/all-components/Cargo.toml new file mode 100644 index 000000000..6827b6be8 --- /dev/null +++ b/examples/all-components/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "freya-design-system-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +freya = { workspace = true } +dioxus = { workspace = true } +dioxus-router = { workspace = true } +strum = { version = "0.26", features = ["derive"] } +itertools = "0.13.0" diff --git a/examples/all-components/src/ds/components/accordion.rs b/examples/all-components/src/ds/components/accordion.rs new file mode 100644 index 000000000..24fecb8aa --- /dev/null +++ b/examples/all-components/src/ds/components/accordion.rs @@ -0,0 +1,37 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsAccordion() -> Element { + rsx!( + Accordion { + summary: rsx!(AccordionSummary { + label { + "Accordion 1" + } + }), + AccordionBody { + label { + "This is the body" + } + label { + "This is the body" + } + label { + "This is the body" + } + label { + "This is the body" + } + label { + "This is the body" + } + label { + "This is the body" + } + label { + "This is the body" + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/activable_route.rs b/examples/all-components/src/ds/components/activable_route.rs new file mode 100644 index 000000000..ca55a4513 --- /dev/null +++ b/examples/all-components/src/ds/components/activable_route.rs @@ -0,0 +1,15 @@ +use freya::prelude::*; + +use crate::Route; + +#[allow(non_snake_case)] +pub fn DsActivableRoute() -> Element { + rsx!( + ActivableRoute { + route: Route::Home, + label { + "ActivableRoute 1" + } + } + ) +} diff --git a/examples/all-components/src/ds/components/button.rs b/examples/all-components/src/ds/components/button.rs new file mode 100644 index 000000000..597cd2b8a --- /dev/null +++ b/examples/all-components/src/ds/components/button.rs @@ -0,0 +1,23 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsButton() -> Element { + rsx!( + Button { + onclick: move |_| { + println!("button clicked") + }, + label { + "A button" + } + } + ) +} + +#[component] +pub fn ButtonThemeEditor(theme: Signal) -> Element { + rsx!(Input { + value: theme().button.background, + onchange: move |e: String| { theme.write().button.background = e.into() } + }) +} diff --git a/examples/all-components/src/ds/components/choice.rs b/examples/all-components/src/ds/components/choice.rs new file mode 100644 index 000000000..385d020b1 --- /dev/null +++ b/examples/all-components/src/ds/components/choice.rs @@ -0,0 +1,104 @@ +use std::collections::HashSet; + +use freya::prelude::*; + +#[derive(PartialEq, Eq, Hash)] +enum Choice { + First, + Second, + Third, +} + +#[allow(non_snake_case)] +pub fn DsCheckbox() -> Element { + let mut selected = use_signal::>(HashSet::default); + + rsx!( + Tile { + onselect: move |_| { + if selected.read().contains(&Choice::First) { + selected.write().remove(&Choice::First); + } else { + selected.write().insert(Choice::First); + } + }, + leading: rsx!( + Checkbox { + selected: selected.read().contains(&Choice::First), + }, + ), + label { "First choice" } + } + Tile { + onselect: move |_| { + if selected.read().contains(&Choice::Second) { + selected.write().remove(&Choice::Second); + } else { + selected.write().insert(Choice::Second); + } + }, + leading: rsx!( + Checkbox { + selected: selected.read().contains(&Choice::Second), + }, + ), + label { "Second choice" } + } + Tile { + onselect: move |_| { + if selected.read().contains(&Choice::Third) { + selected.write().remove(&Choice::Third); + } else { + selected.write().insert(Choice::Third); + } + }, + leading: rsx!( + Checkbox { + selected: selected.read().contains(&Choice::Third), + }, + ), + label { "Third choice" } + } + ) +} + +#[allow(non_snake_case)] +pub fn DsRadio() -> Element { + let mut selected = use_signal(|| Choice::First); + + rsx!( + Tile { + onselect: move |_| { + selected.set(Choice::First); + }, + leading: rsx!( + Radio { + selected: *selected.read() == Choice::First, + }, + ), + label { "First choice" } + } + Tile { + onselect: move |_| { + selected.set(Choice::Second); + }, + leading: rsx!( + Radio { + selected: *selected.read() == Choice::Second, + }, + ), + label { "Second choice" } + } + Tile { + onselect: move |_| { + selected.set(Choice::Third); + }, + leading: rsx!( + Radio { + selected: *selected.read() == Choice::Third, + }, + ), + label { "Third choice" } + } + ) +} diff --git a/examples/all-components/src/ds/components/drag_drop.rs b/examples/all-components/src/ds/components/drag_drop.rs new file mode 100644 index 000000000..b7908609f --- /dev/null +++ b/examples/all-components/src/ds/components/drag_drop.rs @@ -0,0 +1,37 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsDragProvider() -> Element { + let column = vec!["I Like".to_string(), "Rust".to_string(), "🦀!".to_string()]; + + rsx!( + DragProvider:: { + DropZone { + ondrop: move |data: String| { + println!("drop {data}"); + }, + rect { + width: "100%", + height: "100%", + direction: "vertical", + for el in column { + DragZone { + data: el.to_string(), + drag_element: rsx!( + label { + width: "200", + font_size: "20", + "Moving '{el}'" + } + ), + label { + font_size: "30", + "{el}" + } + } + } + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/dropdown.rs b/examples/all-components/src/ds/components/dropdown.rs new file mode 100644 index 000000000..0305cc384 --- /dev/null +++ b/examples/all-components/src/ds/components/dropdown.rs @@ -0,0 +1,29 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsDropdown() -> Element { + let values = use_hook(|| { + vec![ + "First Option".to_string(), + "Second Option".to_string(), + "Rust".to_string(), + ] + }); + let mut selected_dropdown = use_signal(|| "First Option".to_string()); + + rsx!( + Dropdown { + value: selected_dropdown.read().clone(), + for ch in values { + DropdownItem { + value: ch.clone(), + onclick: { + to_owned![ch]; + move |_| selected_dropdown.set(ch.clone()) + }, + label { "{ch}" } + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/icon.rs b/examples/all-components/src/ds/components/icon.rs new file mode 100644 index 000000000..ad32b5156 --- /dev/null +++ b/examples/all-components/src/ds/components/icon.rs @@ -0,0 +1,19 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsArrowIcon() -> Element { + rsx!(ArrowIcon { + fill: "black", + rotate: "0" + }) +} + +#[allow(non_snake_case)] +pub fn DsCrossIcon() -> Element { + rsx!(CrossIcon { fill: "black" }) +} + +#[allow(non_snake_case)] +pub fn DsTickIcon() -> Element { + rsx!(TickIcon { fill: "black" }) +} diff --git a/examples/all-components/src/ds/components/input.rs b/examples/all-components/src/ds/components/input.rs new file mode 100644 index 000000000..fcc0d7127 --- /dev/null +++ b/examples/all-components/src/ds/components/input.rs @@ -0,0 +1,18 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsInput() -> Element { + let mut value = use_signal(String::new); + + rsx!( + label { + "Value: {value}" + } + Input { + value: value.read().clone(), + onchange: move |e| { + value.set(e) + } + } + ) +} diff --git a/examples/all-components/src/ds/components/link.rs b/examples/all-components/src/ds/components/link.rs new file mode 100644 index 000000000..3b7ca8571 --- /dev/null +++ b/examples/all-components/src/ds/components/link.rs @@ -0,0 +1,11 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsLink() -> Element { + rsx! { + Link { + to: "https://crates.io/crates/freya", + label { "Freya crates.io" } + } + } +} diff --git a/examples/all-components/src/ds/components/menu.rs b/examples/all-components/src/ds/components/menu.rs new file mode 100644 index 000000000..4e1d8e927 --- /dev/null +++ b/examples/all-components/src/ds/components/menu.rs @@ -0,0 +1,52 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsMenu() -> Element { + let mut show_menu = use_signal(|| false); + + rsx!( + Body { + Button { + onclick: move |_| show_menu.toggle(), + label { "Open Menu" } + }, + if *show_menu.read() { + Menu { + onclose: move |_| show_menu.set(false), + MenuItem { + label { + "MenuItem" + } + } + MenuButton { + label { + "Open" + } + } + MenuButton { + label { + "Save" + } + } + SubMenu { + menu: rsx!( + MenuButton { + label { + "Some option" + } + } + ), + label { + "Options" + } + } + MenuButton { + label { + "Close" + } + } + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/mod.rs b/examples/all-components/src/ds/components/mod.rs new file mode 100644 index 000000000..ff549afe1 --- /dev/null +++ b/examples/all-components/src/ds/components/mod.rs @@ -0,0 +1,35 @@ +mod accordion; +mod activable_route; +mod button; +mod choice; +mod drag_drop; +mod dropdown; +mod icon; +mod input; +mod link; +mod menu; +mod popup; +mod progress; +mod slider; +mod snackbar; +mod switch; +mod table; +mod tooltip; + +pub use accordion::*; +pub use activable_route::*; +pub use button::*; +pub use choice::*; +pub use drag_drop::*; +pub use dropdown::*; +pub use icon::*; +pub use input::*; +pub use link::*; +pub use menu::*; +pub use popup::*; +pub use progress::*; +pub use slider::*; +pub use snackbar::*; +pub use switch::*; +pub use table::*; +pub use tooltip::*; diff --git a/examples/all-components/src/ds/components/popup.rs b/examples/all-components/src/ds/components/popup.rs new file mode 100644 index 000000000..31acf942f --- /dev/null +++ b/examples/all-components/src/ds/components/popup.rs @@ -0,0 +1,32 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsPopup() -> Element { + let mut show_popup = use_signal(|| false); + + rsx!( + if *show_popup.read() { + Popup { + oncloserequest: move |_| { + show_popup.set(false) + }, + PopupTitle { + label { + "Awesome Popup" + } + } + PopupContent { + label { + "Some content" + } + } + } + } + Button { + onclick: move |_| show_popup.set(true), + label { + "Open" + } + } + ) +} diff --git a/examples/all-components/src/ds/components/progress.rs b/examples/all-components/src/ds/components/progress.rs new file mode 100644 index 000000000..3594697bc --- /dev/null +++ b/examples/all-components/src/ds/components/progress.rs @@ -0,0 +1,11 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsProgressBar() -> Element { + rsx!(ProgressBar { progress: 75.0 }) +} + +#[allow(non_snake_case)] +pub fn DsLoader() -> Element { + rsx!(Loader {}) +} diff --git a/examples/all-components/src/ds/components/slider.rs b/examples/all-components/src/ds/components/slider.rs new file mode 100644 index 000000000..3c0e50b02 --- /dev/null +++ b/examples/all-components/src/ds/components/slider.rs @@ -0,0 +1,13 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsSlider() -> Element { + let mut value = use_signal(|| 10.0); + + rsx!(Slider { + value: *value.read(), + onmoved: move |p| { + value.set(p); + } + }) +} diff --git a/examples/all-components/src/ds/components/snackbar.rs b/examples/all-components/src/ds/components/snackbar.rs new file mode 100644 index 000000000..1699a2b5e --- /dev/null +++ b/examples/all-components/src/ds/components/snackbar.rs @@ -0,0 +1,23 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsSnackBar() -> Element { + let mut show = use_signal(|| false); + + rsx!( + rect { + height: "100%", + width: "100%", + Button { + onclick: move |_| show.toggle(), + label { "Open" } + } + SnackBar { + show, + label { + "Hello, World!" + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/switch.rs b/examples/all-components/src/ds/components/switch.rs new file mode 100644 index 000000000..f4a4b14e5 --- /dev/null +++ b/examples/all-components/src/ds/components/switch.rs @@ -0,0 +1,10 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsSwitch() -> Element { + let mut is_enabled = use_signal(|| true); + rsx!(Switch { + enabled: is_enabled(), + ontoggled: move |_| { is_enabled.toggle() } + }) +} diff --git a/examples/all-components/src/ds/components/table.rs b/examples/all-components/src/ds/components/table.rs new file mode 100644 index 000000000..be6f00990 --- /dev/null +++ b/examples/all-components/src/ds/components/table.rs @@ -0,0 +1,127 @@ +use std::fmt::Display; + +use freya::prelude::*; +use itertools::{Either, Itertools}; + +#[derive(PartialEq, Clone)] +enum OrderBy { + Name, + Type, + Rank, +} + +impl Display for OrderBy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OrderBy::Name => f.write_str("Name"), + OrderBy::Type => f.write_str("Type"), + OrderBy::Rank => f.write_str("Rank"), + } + } +} + +#[allow(non_snake_case)] +pub fn DsTable() -> Element { + let mut order_direction = use_signal(|| OrderDirection::Down); + let mut order = use_signal(|| OrderBy::Name); + let data = use_signal(|| { + vec![ + vec!["Zeus".to_owned(), "Sky".to_owned(), "01".to_owned()], + vec!["Poseidon".to_owned(), "Sea".to_owned(), "03".to_owned()], + vec!["Ares".to_owned(), "War".to_owned(), "08".to_owned()], + vec!["Aphrodite".to_owned(), "Love".to_owned(), "10".to_owned()], + vec!["Hera".to_owned(), "Women".to_owned(), "02".to_owned()], + vec!["Demeter".to_owned(), "Harvest".to_owned(), "04".to_owned()], + vec!["Athena".to_owned(), "Strategy".to_owned(), "05".to_owned()], + vec!["Apollo".to_owned(), "Sun".to_owned(), "06".to_owned()], + vec!["Artemis".to_owned(), "Hunt".to_owned(), "07".to_owned()], + vec!["Hephaestus".to_owned(), "Fire".to_owned(), "09".to_owned()], + vec!["Hermes".to_owned(), "Messenger".to_owned(), "11".to_owned()], + vec!["Dionysus".to_owned(), "Wine".to_owned(), "12".to_owned()], + ] + }); + let columns = use_hook(|| { + vec![ + ("Name", OrderBy::Name), + ("Type", OrderBy::Type), + ("Rank", OrderBy::Rank), + ] + }); + let data = data.read(); + + let filtered_data = { + let filtered_data = data.iter().sorted_by(|a, b| match *order.read() { + OrderBy::Name => Ord::cmp(&a[0].to_lowercase(), &b[0].to_lowercase()), + OrderBy::Type => Ord::cmp(&a[1].to_lowercase(), &b[1].to_lowercase()), + OrderBy::Rank => Ord::cmp(&a[2].to_lowercase(), &b[2].to_lowercase()), + }); + + if *order_direction.read() == OrderDirection::Down { + Either::Left(filtered_data) + } else { + Either::Right(filtered_data.rev()) + } + }; + + let mut on_column_head_click = move |column_order: &OrderBy| { + // Change order diection + if &*order.read() == column_order { + if *order_direction.read() == OrderDirection::Up { + order_direction.set(OrderDirection::Down) + } else { + order_direction.set(OrderDirection::Up) + } + // Change order column + } else { + order.set(column_order.clone()); + order_direction.set(OrderDirection::default()) + } + }; + + rsx!( + rect { + padding: "10", + label { + height: "25", + "Ordering by {order}" + } + Table { + columns: 3, + TableHead { + TableRow { + for (n, (text, order_by)) in columns.into_iter().enumerate() { + TableCell { + key: "{n}", + order_direction: if *order.read() == order_by { Some(*order_direction.read()) } else { None }, + onclick: move |_| on_column_head_click(&order_by), + label { + "{text}" + } + } + } + } + } + TableBody { + ScrollView { + for (i, items) in filtered_data.enumerate() { + TableRow { + key: "{i}", + alternate_colors: i % 2 == 0, + for (n, item) in items.iter().enumerate() { + TableCell { + key: "{n}", + label { + width: "100%", + text_align: "right", + "{item}" + } + } + } + } + } + } + } + } + } + ) +} diff --git a/examples/all-components/src/ds/components/tooltip.rs b/examples/all-components/src/ds/components/tooltip.rs new file mode 100644 index 000000000..410d11598 --- /dev/null +++ b/examples/all-components/src/ds/components/tooltip.rs @@ -0,0 +1,6 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsTooltip() -> Element { + rsx!(Tooltip { url: "tooltip url" }) +} diff --git a/examples/all-components/src/ds/elements/ferris.svg b/examples/all-components/src/ds/elements/ferris.svg new file mode 100644 index 000000000..0d8a78b37 --- /dev/null +++ b/examples/all-components/src/ds/elements/ferris.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/all-components/src/ds/elements/image.rs b/examples/all-components/src/ds/elements/image.rs new file mode 100644 index 000000000..bddbdb75e --- /dev/null +++ b/examples/all-components/src/ds/elements/image.rs @@ -0,0 +1,14 @@ +use freya::prelude::*; + +static RUST_LOGO: &[u8] = include_bytes!("./rust_logo.png"); + +#[allow(non_snake_case)] +pub fn DsImage() -> Element { + let image_data = static_bytes(RUST_LOGO); + + rsx!(image { + image_data: image_data, + width: "250", + height: "250", + }) +} diff --git a/examples/all-components/src/ds/elements/label.rs b/examples/all-components/src/ds/elements/label.rs new file mode 100644 index 000000000..f7a8b676d --- /dev/null +++ b/examples/all-components/src/ds/elements/label.rs @@ -0,0 +1,8 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsLabel() -> Element { + rsx!(label { + "This is a label" + }) +} diff --git a/examples/all-components/src/ds/elements/mod.rs b/examples/all-components/src/ds/elements/mod.rs new file mode 100644 index 000000000..4c6d1f0b0 --- /dev/null +++ b/examples/all-components/src/ds/elements/mod.rs @@ -0,0 +1,13 @@ +mod image; +mod label; +mod paragraph; +mod rect; +mod svg; +mod text; + +pub use image::*; +pub use label::*; +pub use paragraph::*; +pub use rect::*; +pub use svg::*; +pub use text::*; diff --git a/examples/all-components/src/ds/elements/paragraph.rs b/examples/all-components/src/ds/elements/paragraph.rs new file mode 100644 index 000000000..fdf01f2b4 --- /dev/null +++ b/examples/all-components/src/ds/elements/paragraph.rs @@ -0,0 +1,14 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsParagraph() -> Element { + let loremipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + + rsx!( + paragraph { + text{ + {loremipsum} + } + } + ) +} diff --git a/examples/all-components/src/ds/elements/rect.rs b/examples/all-components/src/ds/elements/rect.rs new file mode 100644 index 000000000..1f2d5d5c3 --- /dev/null +++ b/examples/all-components/src/ds/elements/rect.rs @@ -0,0 +1,10 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +pub fn DsRect() -> Element { + rsx!(rect { + background: "green", + width: "150", + height: "150" + }) +} diff --git a/examples/all-components/src/ds/elements/rust_logo.png b/examples/all-components/src/ds/elements/rust_logo.png new file mode 100644 index 000000000..1793f8198 Binary files /dev/null and b/examples/all-components/src/ds/elements/rust_logo.png differ diff --git a/examples/all-components/src/ds/elements/svg.rs b/examples/all-components/src/ds/elements/svg.rs new file mode 100644 index 000000000..2891581cb --- /dev/null +++ b/examples/all-components/src/ds/elements/svg.rs @@ -0,0 +1,14 @@ +use freya::prelude::*; + +static FERRIS: &[u8] = include_bytes!("./ferris.svg"); + +#[allow(non_snake_case)] +pub fn DsSvg() -> Element { + let image_data = static_bytes(FERRIS); + + rsx!(svg { + width: "100%", + height: "50%", + svg_data: image_data, + }) +} diff --git a/examples/all-components/src/ds/elements/text.rs b/examples/all-components/src/ds/elements/text.rs new file mode 100644 index 000000000..f4dc5e876 --- /dev/null +++ b/examples/all-components/src/ds/elements/text.rs @@ -0,0 +1,23 @@ +use freya::prelude::*; + +static RUST_LOGO: &[u8] = include_bytes!("./rust_logo.png"); + +#[allow(non_snake_case)] +pub fn DsText() -> Element { + let loremipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + + rsx!(paragraph { + text{ + color: "red", + {loremipsum} + } + text{ + color: "green", + {loremipsum} + } + text{ + color: "blue", + {loremipsum} + } + }) +} diff --git a/examples/all-components/src/ds/mod.rs b/examples/all-components/src/ds/mod.rs new file mode 100644 index 000000000..56cacf6b0 --- /dev/null +++ b/examples/all-components/src/ds/mod.rs @@ -0,0 +1,38 @@ +mod components; +mod elements; +mod theme; + +pub use components::*; +pub use elements::*; +pub use theme::*; + +use freya::prelude::*; + +#[component] +pub fn DsGui(children: Element) -> Element { + let theme_signal = use_init_default_theme(); + + rsx!( + rect{ + main_align: "center", + cross_align: "center", + height: "100%", + width: "100%", + rect { + height: "80%", + width: "100%", + ThemeProvider { + theme: theme_signal() + {children} + } + } + rect{ + height: "20%", + width: "100%", + ThemeEditor{ + theme: theme_signal + } + } + } + ) +} diff --git a/examples/all-components/src/ds/theme.rs b/examples/all-components/src/ds/theme.rs new file mode 100644 index 000000000..0e8e14b23 --- /dev/null +++ b/examples/all-components/src/ds/theme.rs @@ -0,0 +1,34 @@ +use dioxus_router::{components::Outlet, hooks::use_route}; +use freya::prelude::*; + +use crate::{ButtonThemeEditor, Route}; + +#[component] +pub fn ThemeEditor(theme: Signal) -> Element { + let route = use_route::(); + + rsx!( + rect { + width: "100%", + height: "100%", + background: "rgb(230, 230, 230)", + ScrollView { + rect{ + padding: "20", + { + match route { + Route::DsButton => { + rsx!(ButtonThemeEditor {theme: theme}) + }, + _ => rsx!( + label{ + "No theme editor for this component" + } + ) + } + } + } + } + } + ) +} diff --git a/examples/all-components/src/home.rs b/examples/all-components/src/home.rs new file mode 100644 index 000000000..852699c4e --- /dev/null +++ b/examples/all-components/src/home.rs @@ -0,0 +1,172 @@ +use dioxus_router::prelude::{Outlet, Routable}; +use freya::prelude::*; +use strum::IntoEnumIterator; + +use crate::DsGui; + +use super::Route; + +#[allow(non_snake_case)] +pub fn Home() -> Element { + rsx!( + rect { + main_align: "start", + padding: "50", + background: "rgb(200, 200, 200)", + corner_radius: "10", + label{ + font_size: "28", + "Welcome to Freya components preview" + } + rect{ + height: "10" + } + label{ + "Here you can:" + } + rect{ + height: "10" + } + label{ + "- View all components" + } + rect{ + height: "10" + } + label{ + "- Play with theming" + } + } + ) +} + +#[allow(non_snake_case)] +pub fn AppSidebar() -> Element { + let mut search = use_signal(|| String::default()); + + rsx!( + NativeRouter { + Sidebar { + sidebar: rsx!( + Input { + value: search(), + placeholder: "Search...", + onchange: move |e| { + search.set(e) + } + } + for route in Route::iter().filter(|r| r != &Route::PageNotFound { } ) { + { + let (code, entry_type) = route_entry(route); + if search().is_empty() + || code.map(|c| + c.to_lowercase().contains(search().to_lowercase().as_str()) + ).unwrap_or_default() { + rsx!( + SideBarEntry { + route: route, + code: code, + entry_type: entry_type + } + ) + } + else { + rsx!() + } + } + } + ), + Body { + DsGui { + rect { + main_align: "center", + cross_align: "start", + width: "100%", + height: "100%", + padding: "20", + Outlet:: { } + } + } + } + } + } + ) +} + +fn route_entry(route: Route) -> (Option<&'static str>, &'static str) { + match route { + Route::Home => (None, "Welcome"), + Route::DsImage => (Some("image"), "element"), + Route::DsLabel => (Some("label"), "element"), + Route::DsParagraph => (Some("paragraph"), "element"), + Route::DsRect => (Some("rect"), "element"), + Route::DsSvg => (Some("svg"), "element"), + Route::DsText => (Some("text"), "element"), + Route::DsAccordion => (Some("Accordion"), "component"), + Route::DsActivableRoute => (Some("ActivableRoute"), "component"), + Route::DsArrowIcon => (Some("ArrowIcon"), "component"), + Route::DsButton => (Some("Button"), "component"), + // Route::DsCanvas => (Some("Canvas"), "component"), + Route::DsCheckbox => (Some("Checkbox"), "component"), + Route::DsCrossIcon => (Some("CrossIcon"), "component"), + // Route::DsCursorArea => (Some("CursorArea"), "component"), + Route::DsDragProvider => (Some("DragProvider"), "component"), + Route::DsDropdown => (Some("Dropdown"), "component"), + // Route::DsGestureArea => (Some("GestureArea"), "component"), + // Route::DsGraph => (Some("Graph"), "component"), + Route::DsInput => (Some("Input"), "component"), + // Route::DsKeyboardNavigator => (Some("KeyboardNavigator"), "component"), + Route::DsLink => (Some("Link"), "component"), + Route::DsLoader => (Some("Loader"), "component"), + Route::DsMenu => (Some("Menu"), "component"), + // Route::DsMenuButton => (Some("MenuButton"), "component"), + // Route::DsNetworkImage => (Some("NetworkImage"), "component"), + Route::DsPopup => (Some("Popup"), "component"), + Route::DsProgressBar => (Some("ProgressBar"), "component"), + Route::DsRadio => (Some("Radio"), "component"), + // Route::DsScrollView => (Some("ScrollView"), "component"), + // Route::DsScrollBar => (Some("ScrollBar"), "component"), + // Route::DsScrollThumb => (Some("ScrollThumb"), "component"), + // Route::DsSideBar => (Some("SideBar"), "component"), + Route::DsSlider => (Some("Slider"), "component"), + Route::DsSnackBar => (Some("SnackBar"), "component"), + // Route::DsSubMenu => (Some("SubMenu"), "component"), + Route::DsSwitch => (Some("Switch"), "component"), + Route::DsTable => (Some("Table"), "component"), + Route::DsTickIcon => (Some("TickIcon"), "component"), + // Route::DsTile => (Some("Tile"), "component"), + Route::DsTooltip => (Some("Tooltip"), "component"), + // Route::DsVirtualScrollView => (Some("VirtualScrollView"), "component"), + _ => unimplemented!(), + } +} + +#[component] +fn SideBarEntry(route: Route, code: Option<&'static str>, entry_type: &'static str) -> Element { + rsx!( + Link { + to: route, + ActivableRoute { + route: route, + exact: true, + SidebarItem { + if let Some(code) = code { + label { + font_style: "mono", + {code} + } + label { + font_size: "11", + {entry_type} + } + } + else { + label { + {entry_type} + } + } + }, + } + } + ) +} diff --git a/examples/all-components/src/main.rs b/examples/all-components/src/main.rs new file mode 100644 index 000000000..9b0566327 --- /dev/null +++ b/examples/all-components/src/main.rs @@ -0,0 +1,116 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +mod ds; +mod home; +mod not_found; + +use dioxus_router::prelude::{Routable, Router}; +use ds::*; +use freya::prelude::*; +use home::*; +use not_found::*; +use strum::EnumIter; + +fn main() { + launch_with_props(app, "Freya Components Preview", (800.0, 600.0)); +} + +fn app() -> Element { + rsx!(Router:: {}) +} + +#[derive(Routable, Clone, Copy, PartialEq, EnumIter)] +#[rustfmt::skip] +pub enum Route { + #[layout(AppSidebar)] + #[route("/")] + Home, + #[nest("/elements")] + #[route("/image")] + DsImage, + #[route("/label")] + DsLabel, + #[route("/paragraph")] + DsParagraph, + #[route("/rect")] + DsRect, + #[route("/svg")] + DsSvg, + #[route("/text")] + DsText, + #[end_nest] + #[nest("/components")] + #[route("/arrow-icon")] + DsArrowIcon, + #[route("/cross-icon")] + DsCrossIcon, + #[route("/tick-icon")] + DsTickIcon, + #[route("/accordion")] + DsAccordion, + #[route("/activable-route")] + DsActivableRoute, + #[route("/button")] + DsButton, + // #[route("/canvas")] + // DsCanvas, + #[route("/checkbox")] + DsCheckbox, + // #[route("/cursor-area")] + // DsCursorArea, + #[route("/drag-provider")] + DsDragProvider, + #[route("/dropdown")] + DsDropdown, + // #[route("/gesture-area")] + // DsGestureArea, + // #[route("/graph")] + // DsGraph, + #[route("/input")] + DsInput, + // #[route("/keyboard-navigator")] + // DsKeyboardNavigator, + #[route("/link")] + DsLink, + #[route("/loader")] + DsLoader, + #[route("/menu")] + DsMenu, + // #[route("/network-image")] + // DsNetworkImage, + #[route("/popup")] + DsPopup, + #[route("/progress-bar")] + DsProgressBar, + #[route("/radio")] + DsRadio, + // #[route("/scroll-view")] + // DsScrollView, + // #[route("/scroll-bar")] + // DsScrollBar, + // #[route("/scroll-thumb")] + // DsScrollThumb, + // #[route("/side-bar")] + // DsSideBar, + #[route("/slider")] + DsSlider, + #[route("/snack-bar")] + DsSnackBar, + #[route("/switch")] + DsSwitch, + #[route("/table")] + DsTable, + // #[route("/tile")] + // DsTile, + #[route("/tooltip")] + DsTooltip, + // #[route("/virtual-scorll-view")] + // DsVirtualScrollView, + #[end_nest] + #[end_layout] + #[route("/..route")] + PageNotFound { }, +} diff --git a/examples/all-components/src/not_found.rs b/examples/all-components/src/not_found.rs new file mode 100644 index 000000000..b9d9f80ca --- /dev/null +++ b/examples/all-components/src/not_found.rs @@ -0,0 +1,17 @@ +use freya::prelude::*; + +#[allow(non_snake_case)] +#[component] +pub fn PageNotFound() -> Element { + rsx!( + label { + "Oh, no! Freya doesn't have such component..." + } + Link{ + to: "https://github.com/marc2332/freya/", + label { + "Contribute" + } + } + ) +}