summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorLibravatar Billy Messenger <BillyDM@tutamail.com>2021-07-22 12:37:39 -0500
committerLibravatar Billy Messenger <BillyDM@tutamail.com>2021-07-22 12:37:39 -0500
commite822f654e44d2d7375b7fda966bb772055f377d4 (patch)
tree8707561f1bb09c9e58cc9d9884bfb16d956f9f65 /web
parent1c06920158e1a47977b2762bf8b34e56fd1a935a (diff)
parentdc0b96ce407283f2ffd9add5ad339f89097555d3 (diff)
downloadiced-e822f654e44d2d7375b7fda966bb772055f377d4.tar.gz
iced-e822f654e44d2d7375b7fda966bb772055f377d4.tar.bz2
iced-e822f654e44d2d7375b7fda966bb772055f377d4.zip
Merge branch 'master' of https://github.com/hecrj/iced into wgpu_outdatedframe
Diffstat (limited to 'web')
-rw-r--r--web/Cargo.toml8
-rw-r--r--web/README.md2
-rw-r--r--web/src/clipboard.rs21
-rw-r--r--web/src/css.rs67
-rw-r--r--web/src/lib.rs19
-rw-r--r--web/src/widget.rs3
-rw-r--r--web/src/widget/button.rs52
-rw-r--r--web/src/widget/checkbox.rs1
-rw-r--r--web/src/widget/column.rs20
-rw-r--r--web/src/widget/container.rs21
-rw-r--r--web/src/widget/radio.rs1
-rw-r--r--web/src/widget/row.rs20
-rw-r--r--web/src/widget/scrollable.rs11
-rw-r--r--web/src/widget/slider.rs2
-rw-r--r--web/src/widget/text_input.rs32
-rw-r--r--web/src/widget/toggler.rs171
16 files changed, 356 insertions, 95 deletions
diff --git a/web/Cargo.toml b/web/Cargo.toml
index e063a021..06573b95 100644
--- a/web/Cargo.toml
+++ b/web/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_web"
-version = "0.3.0"
+version = "0.4.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2018"
description = "A web backend for Iced"
@@ -22,15 +22,15 @@ url = "2.0"
num-traits = "0.2"
[dependencies.iced_core]
-version = "0.3"
+version = "0.4"
path = "../core"
[dependencies.iced_futures]
-version = "0.2"
+version = "0.3"
path = "../futures"
[dependencies.iced_style]
-version = "0.2"
+version = "0.3"
path = "../style"
[dependencies.web-sys]
diff --git a/web/README.md b/web/README.md
index 0e770589..58ad8235 100644
--- a/web/README.md
+++ b/web/README.md
@@ -16,7 +16,7 @@ The crate is currently a __very experimental__, simple abstraction layer over [`
Add `iced_web` as a dependency in your `Cargo.toml`:
```toml
-iced_web = "0.3"
+iced_web = "0.4"
```
__Iced moves fast and the `master` branch can contain breaking changes!__ If
diff --git a/web/src/clipboard.rs b/web/src/clipboard.rs
new file mode 100644
index 00000000..167a1e53
--- /dev/null
+++ b/web/src/clipboard.rs
@@ -0,0 +1,21 @@
+/// A buffer for short-term storage and transfer within and between
+/// applications.
+#[derive(Debug, Clone, Copy)]
+pub struct Clipboard;
+
+impl Clipboard {
+ /// Creates a new [`Clipboard`].
+ pub fn new() -> Self {
+ Self
+ }
+
+ /// Reads the current content of the [`Clipboard`] as text.
+ pub fn read(&self) -> Option<String> {
+ unimplemented! {}
+ }
+
+ /// Writes the given text contents to the [`Clipboard`].
+ pub fn write(&mut self, _contents: String) {
+ unimplemented! {}
+ }
+}
diff --git a/web/src/css.rs b/web/src/css.rs
index bdde23f3..21f51f85 100644
--- a/web/src/css.rs
+++ b/web/src/css.rs
@@ -1,5 +1,5 @@
//! Style your widgets.
-use crate::{bumpalo, Align, Background, Color, Length};
+use crate::{bumpalo, Align, Background, Color, Length, Padding};
use std::collections::BTreeMap;
@@ -12,11 +12,11 @@ pub enum Rule {
/// Container with horizonal distribution
Row,
- /// Padding of the container
- Padding(u16),
-
/// Spacing between elements
Spacing(u16),
+
+ /// Toggler input for a specific size
+ Toggler(u16),
}
impl Rule {
@@ -25,8 +25,8 @@ impl Rule {
match self {
Rule::Column => String::from("c"),
Rule::Row => String::from("r"),
- Rule::Padding(padding) => format!("p-{}", padding),
Rule::Spacing(spacing) => format!("s-{}", spacing),
+ Rule::Toggler(size) => format!("toggler-{}", size),
}
}
@@ -45,13 +45,6 @@ impl Rule {
bumpalo::format!(in bump, ".{} {}", class, body).into_bump_str()
}
- Rule::Padding(padding) => bumpalo::format!(
- in bump,
- ".{} {{ box-sizing: border-box; padding: {}px }}",
- class,
- padding
- )
- .into_bump_str(),
Rule::Spacing(spacing) => bumpalo::format!(
in bump,
".c.{} > * {{ margin-bottom: {}px }} \
@@ -66,6 +59,46 @@ impl Rule {
class
)
.into_bump_str(),
+ Rule::Toggler(size) => bumpalo::format!(
+ in bump,
+ ".toggler-{} {{ display: flex; cursor: pointer; justify-content: space-between; }} \
+ .toggler-{} input {{ display:none; }} \
+ .toggler-{} span {{ background-color: #b1b1b1; position: relative; display: inline-flex; width:{}px; height: {}px; border-radius: {}px;}} \
+ .toggler-{} span > span {{ background-color: #FFFFFF; width: {}px; height: {}px; border-radius: 50%; top: 1px; left: 1px;}} \
+ .toggler-{}:hover span > span {{ background-color: #f1f1f1 !important; }} \
+ .toggler-{} input:checked + span {{ background-color: #00FF00; }} \
+ .toggler-{} input:checked + span > span {{ -webkit-transform: translateX({}px); -ms-transform:translateX({}px); transform: translateX({}px); }}
+ ",
+ // toggler
+ size,
+
+ // toggler input
+ size,
+
+ // toggler span
+ size,
+ size*2,
+ size,
+ size,
+
+ // toggler span > span
+ size,
+ size-2,
+ size-2,
+
+ // toggler: hover + span > span
+ size,
+
+ // toggler input:checked + span
+ size,
+
+ // toggler input:checked + span > span
+ size,
+ size,
+ size,
+ size
+ )
+ .into_bump_str(),
}
}
}
@@ -170,3 +203,13 @@ pub fn align(align: Align) -> &'static str {
Align::End => "flex-end",
}
}
+
+/// Returns the style value for the given [`Padding`].
+///
+/// [`Padding`]: struct.Padding.html
+pub fn padding(padding: Padding) -> String {
+ format!(
+ "{}px {}px {}px {}px",
+ padding.top, padding.right, padding.bottom, padding.left
+ )
+}
diff --git a/web/src/lib.rs b/web/src/lib.rs
index 58f6591d..6b7d0115 100644
--- a/web/src/lib.rs
+++ b/web/src/lib.rs
@@ -49,7 +49,7 @@
//!
//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack
//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
-//! [`tour` example]: https://github.com/hecrj/iced/tree/0.2/examples/tour
+//! [`tour` example]: https://github.com/hecrj/iced/tree/0.3/examples/tour
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
@@ -59,6 +59,7 @@ use dodrio::bumpalo;
use std::{cell::RefCell, rc::Rc};
mod bus;
+mod clipboard;
mod element;
mod hasher;
@@ -67,13 +68,14 @@ pub mod subscription;
pub mod widget;
pub use bus::Bus;
+pub use clipboard::Clipboard;
pub use css::Css;
pub use dodrio;
pub use element::Element;
pub use hasher::Hasher;
pub use iced_core::{
- keyboard, mouse, Align, Background, Color, Font, HorizontalAlignment,
- Length, Point, Rectangle, Size, Vector, VerticalAlignment,
+ keyboard, menu, mouse, Align, Background, Color, Font, HorizontalAlignment,
+ Length, Menu, Padding, Point, Rectangle, Size, Vector, VerticalAlignment,
};
pub use iced_futures::{executor, futures, Command};
pub use subscription::Subscription;
@@ -126,7 +128,11 @@ pub trait Application {
/// this method.
///
/// Any [`Command`] returned will be executed immediately in the background.
- fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
+ fn update(
+ &mut self,
+ message: Self::Message,
+ clipboard: &mut Clipboard,
+ ) -> Command<Self::Message>;
/// Returns the widgets to display in the [`Application`].
///
@@ -156,6 +162,8 @@ pub trait Application {
let document = window.document().unwrap();
let body = document.body().unwrap();
+ let mut clipboard = Clipboard::new();
+
let (sender, receiver) =
iced_futures::futures::channel::mpsc::unbounded();
@@ -182,7 +190,8 @@ pub trait Application {
let event_loop = receiver.for_each(move |message| {
let (command, subscription) = runtime.enter(|| {
- let command = application.borrow_mut().update(message);
+ let command =
+ application.borrow_mut().update(message, &mut clipboard);
let subscription = application.borrow().subscription();
(command, subscription)
diff --git a/web/src/widget.rs b/web/src/widget.rs
index 023f5f13..4cb0a9cc 100644
--- a/web/src/widget.rs
+++ b/web/src/widget.rs
@@ -24,6 +24,7 @@ pub mod radio;
pub mod scrollable;
pub mod slider;
pub mod text_input;
+pub mod toggler;
mod column;
mod row;
@@ -40,6 +41,8 @@ pub use slider::Slider;
pub use text::Text;
#[doc(no_inline)]
pub use text_input::TextInput;
+#[doc(no_inline)]
+pub use toggler::Toggler;
pub use checkbox::Checkbox;
pub use column::Column;
diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs
index e7cff6a0..cd450b55 100644
--- a/web/src/widget/button.rs
+++ b/web/src/widget/button.rs
@@ -1,7 +1,7 @@
//! Allow your users to perform actions by pressing a button.
//!
//! A [`Button`] has some local [`State`].
-use crate::{css, Background, Bus, Css, Element, Length, Widget};
+use crate::{css, Background, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::button::{Style, StyleSheet};
@@ -20,15 +20,37 @@ use dodrio::bumpalo;
/// let button = Button::new(&mut state, Text::new("Press me!"))
/// .on_press(Message::ButtonPressed);
/// ```
+///
+/// If a [`Button::on_press`] handler is not set, the resulting [`Button`] will
+/// be disabled:
+///
+/// ```
+/// # use iced_web::{button, Button, Text};
+/// #
+/// #[derive(Clone)]
+/// enum Message {
+/// ButtonPressed,
+/// }
+///
+/// fn disabled_button(state: &mut button::State) -> Button<'_, Message> {
+/// Button::new(state, Text::new("I'm disabled!"))
+/// }
+///
+/// fn enabled_button(state: &mut button::State) -> Button<'_, Message> {
+/// disabled_button(state).on_press(Message::ButtonPressed)
+/// }
+/// ```
#[allow(missing_debug_implementations)]
pub struct Button<'a, Message> {
content: Element<'a, Message>,
on_press: Option<Message>,
width: Length,
+ #[allow(dead_code)]
height: Length,
min_width: u32,
+ #[allow(dead_code)]
min_height: u32,
- padding: u16,
+ padding: Padding,
style: Box<dyn StyleSheet>,
}
@@ -46,7 +68,7 @@ impl<'a, Message> Button<'a, Message> {
height: Length::Shrink,
min_width: 0,
min_height: 0,
- padding: 5,
+ padding: Padding::new(5),
style: Default::default(),
}
}
@@ -75,9 +97,9 @@ impl<'a, Message> Button<'a, Message> {
self
}
- /// Sets the padding of the [`Button`].
- pub fn padding(mut self, padding: u16) -> Self {
- self.padding = padding;
+ /// Sets the [`Padding`] of the [`Button`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
self
}
@@ -88,6 +110,7 @@ impl<'a, Message> Button<'a, Message> {
}
/// Sets the message that will be produced when the [`Button`] is pressed.
+ /// If on_press isn't set, button will be disabled.
pub fn on_press(mut self, msg: Message) -> Self {
self.on_press = Some(msg);
self
@@ -120,9 +143,6 @@ where
// TODO: State-based styling
let style = self.style.active();
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
let background = match style.background {
None => String::from("none"),
Some(background) => match background {
@@ -130,25 +150,19 @@ where
},
};
- let class = {
- use dodrio::bumpalo::collections::String;
-
- String::from_str_in(&padding_class, bump).into_bump_str()
- };
-
let mut node = button(bump)
- .attr("class", class)
.attr(
"style",
bumpalo::format!(
in bump,
"background: {}; border-radius: {}px; width:{}; \
- min-width: {}; color: {}",
+ min-width: {}; color: {}; padding: {}",
background,
style.border_radius,
css::length(self.width),
css::min_length(self.min_width),
- css::color(style.text_color)
+ css::color(style.text_color),
+ css::padding(self.padding)
)
.into_bump_str(),
)
@@ -160,6 +174,8 @@ where
node = node.on("click", move |_root, _vdom, _event| {
event_bus.publish(on_press.clone());
});
+ } else {
+ node = node.attr("disabled", "");
}
node.finish()
diff --git a/web/src/widget/checkbox.rs b/web/src/widget/checkbox.rs
index 543af99a..43110aa7 100644
--- a/web/src/widget/checkbox.rs
+++ b/web/src/widget/checkbox.rs
@@ -30,6 +30,7 @@ pub struct Checkbox<Message> {
label: String,
id: Option<String>,
width: Length,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs
index d832fdcb..8738c2af 100644
--- a/web/src/widget/column.rs
+++ b/web/src/widget/column.rs
@@ -1,4 +1,4 @@
-use crate::{css, Align, Bus, Css, Element, Length, Widget};
+use crate::{css, Align, Bus, Css, Element, Length, Padding, Widget};
use dodrio::bumpalo;
use std::u32;
@@ -9,7 +9,7 @@ use std::u32;
#[allow(missing_debug_implementations)]
pub struct Column<'a, Message> {
spacing: u16,
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
@@ -28,7 +28,7 @@ impl<'a, Message> Column<'a, Message> {
pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
Column {
spacing: 0,
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Fill,
height: Length::Shrink,
max_width: u32::MAX,
@@ -48,9 +48,9 @@ impl<'a, Message> Column<'a, Message> {
self
}
- /// Sets the padding of the [`Column`].
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`Column`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
self
}
@@ -114,23 +114,21 @@ impl<'a, Message> Widget<Message> for Column<'a, Message> {
let spacing_class =
style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
// TODO: Complete styling
div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {} {}", column_class, spacing_class, padding_class)
+ bumpalo::format!(in bump, "{} {}", column_class, spacing_class)
.into_bump_str(),
)
.attr("style", bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; max-height: {}; align-items: {}",
+ "width: {}; height: {}; max-width: {}; max-height: {}; padding: {}; align-items: {}",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
css::max_length(self.max_height),
+ css::padding(self.padding),
css::align(self.align_items)
).into_bump_str()
)
diff --git a/web/src/widget/container.rs b/web/src/widget/container.rs
index 7187a4f0..c006e011 100644
--- a/web/src/widget/container.rs
+++ b/web/src/widget/container.rs
@@ -1,5 +1,5 @@
//! Decorate content and apply alignment.
-use crate::{bumpalo, css, Align, Bus, Css, Element, Length, Widget};
+use crate::{bumpalo, css, Align, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::container::{Style, StyleSheet};
@@ -8,10 +8,11 @@ pub use iced_style::container::{Style, StyleSheet};
/// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)]
pub struct Container<'a, Message> {
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
+ #[allow(dead_code)]
max_height: u32,
horizontal_alignment: Align,
vertical_alignment: Align,
@@ -28,7 +29,7 @@ impl<'a, Message> Container<'a, Message> {
use std::u32;
Container {
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Shrink,
height: Length::Shrink,
max_width: u32::MAX,
@@ -40,9 +41,9 @@ impl<'a, Message> Container<'a, Message> {
}
}
- /// Sets the padding of the [`Container`].
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`Container`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
self
}
@@ -105,24 +106,22 @@ where
let column_class = style_sheet.insert(bump, css::Rule::Column);
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
let style = self.style_sheet.style();
let node = div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {}", column_class, padding_class).into_bump_str(),
+ bumpalo::format!(in bump, "{}", column_class).into_bump_str(),
)
.attr(
"style",
bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; align-items: {}; justify-content: {}; background: {}; color: {}; border-width: {}px; border-color: {}; border-radius: {}px",
+ "width: {}; height: {}; max-width: {}; padding: {}; align-items: {}; justify-content: {}; background: {}; color: {}; border-width: {}px; border-color: {}; border-radius: {}px",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
+ css::padding(self.padding),
css::align(self.horizontal_alignment),
css::align(self.vertical_alignment),
style.background.map(css::background).unwrap_or(String::from("initial")),
diff --git a/web/src/widget/radio.rs b/web/src/widget/radio.rs
index 5a9bc379..fbc88d29 100644
--- a/web/src/widget/radio.rs
+++ b/web/src/widget/radio.rs
@@ -37,6 +37,7 @@ pub struct Radio<Message> {
label: String,
id: Option<String>,
name: Option<String>,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs
index f00a544a..ffb515cf 100644
--- a/web/src/widget/row.rs
+++ b/web/src/widget/row.rs
@@ -1,4 +1,4 @@
-use crate::{css, Align, Bus, Css, Element, Length, Widget};
+use crate::{css, Align, Bus, Css, Element, Length, Padding, Widget};
use dodrio::bumpalo;
use std::u32;
@@ -9,7 +9,7 @@ use std::u32;
#[allow(missing_debug_implementations)]
pub struct Row<'a, Message> {
spacing: u16,
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
@@ -28,7 +28,7 @@ impl<'a, Message> Row<'a, Message> {
pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
Row {
spacing: 0,
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Fill,
height: Length::Shrink,
max_width: u32::MAX,
@@ -48,9 +48,9 @@ impl<'a, Message> Row<'a, Message> {
self
}
- /// Sets the padding of the [`Row`].
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`Row`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
self
}
@@ -114,23 +114,21 @@ impl<'a, Message> Widget<Message> for Row<'a, Message> {
let spacing_class =
style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
// TODO: Complete styling
div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {} {}", row_class, spacing_class, padding_class)
+ bumpalo::format!(in bump, "{} {}", row_class, spacing_class)
.into_bump_str(),
)
.attr("style", bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; max-height: {}; align-items: {}",
+ "width: {}; height: {}; max-width: {}; max-height: {}; padding: {}; align-items: {}",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
css::max_length(self.max_height),
+ css::padding(self.padding),
css::align(self.align_items)
).into_bump_str()
)
diff --git a/web/src/widget/scrollable.rs b/web/src/widget/scrollable.rs
index f9135dd6..ce0a10d4 100644
--- a/web/src/widget/scrollable.rs
+++ b/web/src/widget/scrollable.rs
@@ -1,5 +1,7 @@
//! Navigate an endless amount of content with a scrollbar.
-use crate::{bumpalo, css, Align, Bus, Column, Css, Element, Length, Widget};
+use crate::{
+ bumpalo, css, Align, Bus, Column, Css, Element, Length, Padding, Widget,
+};
pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
@@ -11,6 +13,7 @@ pub struct Scrollable<'a, Message> {
height: Length,
max_height: u32,
content: Column<'a, Message>,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
@@ -38,9 +41,9 @@ impl<'a, Message> Scrollable<'a, Message> {
self
}
- /// Sets the padding of the [`Scrollable`].
- pub fn padding(mut self, units: u16) -> Self {
- self.content = self.content.padding(units);
+ /// Sets the [`Padding`] of the [`Scrollable`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.content = self.content.padding(padding);
self
}
diff --git a/web/src/widget/slider.rs b/web/src/widget/slider.rs
index 91a4d2ec..f457aa4c 100644
--- a/web/src/widget/slider.rs
+++ b/web/src/widget/slider.rs
@@ -38,7 +38,9 @@ pub struct Slider<'a, T, Message> {
step: T,
value: T,
on_change: Rc<Box<dyn Fn(T) -> Message>>,
+ #[allow(dead_code)]
width: Length,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
diff --git a/web/src/widget/text_input.rs b/web/src/widget/text_input.rs
index bc2048a8..e4877f2a 100644
--- a/web/src/widget/text_input.rs
+++ b/web/src/widget/text_input.rs
@@ -1,7 +1,7 @@
//! Display fields that can be filled with text.
//!
//! A [`TextInput`] has some local [`State`].
-use crate::{bumpalo, css, Bus, Css, Element, Length, Widget};
+use crate::{bumpalo, css, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::text_input::{Style, StyleSheet};
@@ -35,7 +35,7 @@ pub struct TextInput<'a, Message> {
is_secure: bool,
width: Length,
max_width: u32,
- padding: u16,
+ padding: Padding,
size: Option<u16>,
on_change: Rc<Box<dyn Fn(String) -> Message>>,
on_submit: Option<Message>,
@@ -66,7 +66,7 @@ impl<'a, Message> TextInput<'a, Message> {
is_secure: false,
width: Length::Fill,
max_width: u32::MAX,
- padding: 0,
+ padding: Padding::ZERO,
size: None,
on_change: Rc::new(Box::new(on_change)),
on_submit: None,
@@ -92,9 +92,9 @@ impl<'a, Message> TextInput<'a, Message> {
self
}
- /// Sets the padding of the [`TextInput`].
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`TextInput`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
self
}
@@ -126,20 +126,11 @@ where
&self,
bump: &'b bumpalo::Bump,
bus: &Bus<Message>,
- style_sheet: &mut Css<'b>,
+ _style_sheet: &mut Css<'b>,
) -> dodrio::Node<'b> {
use dodrio::builder::*;
use wasm_bindgen::JsCast;
- let class = {
- use dodrio::bumpalo::collections::String;
-
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
- String::from_str_in(&padding_class, bump).into_bump_str()
- };
-
let placeholder = {
use dodrio::bumpalo::collections::String;
@@ -159,16 +150,16 @@ where
let style = self.style_sheet.active();
input(bump)
- .attr("class", class)
.attr(
"style",
bumpalo::format!(
in bump,
- "width: {}; max-width: {}; font-size: {}px; \
+ "width: {}; max-width: {}; padding: {}; font-size: {}px; \
background: {}; border-width: {}px; border-color: {}; \
border-radius: {}px; color: {}",
css::length(self.width),
css::max_length(self.max_width),
+ css::padding(self.padding),
self.size.unwrap_or(20),
css::background(style.background),
style.border_width,
@@ -232,4 +223,9 @@ impl State {
// TODO
Self::default()
}
+
+ /// Selects all the content of the [`TextInput`].
+ pub fn select_all(&mut self) {
+ // TODO
+ }
}
diff --git a/web/src/widget/toggler.rs b/web/src/widget/toggler.rs
new file mode 100644
index 00000000..0a198079
--- /dev/null
+++ b/web/src/widget/toggler.rs
@@ -0,0 +1,171 @@
+//! Show toggle controls using togglers.
+use crate::{css, Bus, Css, Element, Length, Widget};
+
+pub use iced_style::toggler::{Style, StyleSheet};
+
+use dodrio::bumpalo;
+use std::rc::Rc;
+
+/// A toggler that can be toggled.
+///
+/// # Example
+///
+/// ```
+/// # use iced_web::Toggler;
+///
+/// pub enum Message {
+/// TogglerToggled(bool),
+/// }
+///
+/// let is_active = true;
+///
+/// Toggler::new(is_active, String::from("Toggle me!"), Message::TogglerToggled);
+/// ```
+///
+#[allow(missing_debug_implementations)]
+pub struct Toggler<Message> {
+ is_active: bool,
+ on_toggle: Rc<dyn Fn(bool) -> Message>,
+ label: Option<String>,
+ id: Option<String>,
+ width: Length,
+ style: Box<dyn StyleSheet>,
+}
+
+impl<Message> Toggler<Message> {
+ /// Creates a new [`Toggler`].
+ ///
+ /// It expects:
+ /// * a boolean describing whether the [`Toggler`] is active or not
+ /// * An optional label for the [`Toggler`]
+ /// * a function that will be called when the [`Toggler`] is toggled. It
+ /// will receive the new state of the [`Toggler`] and must produce a
+ /// `Message`.
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn new<F>(
+ is_active: bool,
+ label: impl Into<Option<String>>,
+ f: F,
+ ) -> Self
+ where
+ F: 'static + Fn(bool) -> Message,
+ {
+ Toggler {
+ is_active,
+ on_toggle: Rc::new(f),
+ label: label.into(),
+ id: None,
+ width: Length::Shrink,
+ style: Default::default(),
+ }
+ }
+
+ /// Sets the width of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn width(mut self, width: Length) -> Self {
+ self.width = width;
+ self
+ }
+
+ /// Sets the style of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
+ self.style = style.into();
+ self
+ }
+
+ /// Sets the id of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn id(mut self, id: impl Into<String>) -> Self {
+ self.id = Some(id.into());
+ self
+ }
+}
+
+impl<Message> Widget<Message> for Toggler<Message>
+where
+ Message: 'static,
+{
+ fn node<'b>(
+ &self,
+ bump: &'b bumpalo::Bump,
+ bus: &Bus<Message>,
+ style_sheet: &mut Css<'b>,
+ ) -> dodrio::Node<'b> {
+ use dodrio::builder::*;
+ use dodrio::bumpalo::collections::String;
+
+ let toggler_label = &self
+ .label
+ .as_ref()
+ .map(|label| String::from_str_in(&label, bump).into_bump_str());
+
+ let event_bus = bus.clone();
+ let on_toggle = self.on_toggle.clone();
+ let is_active = self.is_active;
+
+ let row_class = style_sheet.insert(bump, css::Rule::Row);
+ let toggler_class = style_sheet.insert(bump, css::Rule::Toggler(16));
+
+ let (label, input) = if let Some(id) = &self.id {
+ let id = String::from_str_in(id, bump).into_bump_str();
+
+ (label(bump).attr("for", id), input(bump).attr("id", id))
+ } else {
+ (label(bump), input(bump))
+ };
+
+ let checkbox = input
+ .attr("type", "checkbox")
+ .bool_attr("checked", self.is_active)
+ .on("click", move |_root, vdom, _event| {
+ let msg = on_toggle(!is_active);
+ event_bus.publish(msg);
+
+ vdom.schedule_render();
+ })
+ .finish();
+
+ let toggler = span(bump).children(vec![span(bump).finish()]).finish();
+
+ label
+ .attr(
+ "class",
+ bumpalo::format!(in bump, "{} {}", row_class, toggler_class)
+ .into_bump_str(),
+ )
+ .attr(
+ "style",
+ bumpalo::format!(in bump, "width: {}; align-items: center", css::length(self.width))
+ .into_bump_str()
+ )
+ .children(
+ if let Some(label) = toggler_label {
+ vec![
+ text(label),
+ checkbox,
+ toggler,
+ ]
+ } else {
+ vec![
+ checkbox,
+ toggler,
+ ]
+ }
+ )
+ .finish()
+ }
+}
+
+impl<'a, Message> From<Toggler<Message>> for Element<'a, Message>
+where
+ Message: 'static,
+{
+ fn from(toggler: Toggler<Message>) -> Element<'a, Message> {
+ Element::new(toggler)
+ }
+}