Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Improve Input component #354

Merged
merged 37 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c9115fa
feat: WIP Enhanced alignments
marc2332 Oct 14, 2023
5d67298
improvements
marc2332 Oct 14, 2023
c926baa
tweak
marc2332 Oct 14, 2023
74544bf
remove display attribute, remove 'both' direction, fix tests, fix doc…
marc2332 Oct 14, 2023
2cfc46a
feat: Updated examples
marc2332 Oct 15, 2023
736dda1
tests
marc2332 Oct 15, 2023
da4a1a2
fixed tests
marc2332 Oct 15, 2023
1bc2a53
Merge branch 'main' into feat/enhanced-alignments
marc2332 Oct 16, 2023
3d49e1d
update table component and example
marc2332 Oct 16, 2023
bb1de28
clean up
marc2332 Oct 17, 2023
981fe9a
clean up
marc2332 Oct 17, 2023
dcc3c57
improvements
marc2332 Oct 18, 2023
60e0ebf
improvements
marc2332 Oct 19, 2023
2e8056a
fixes
marc2332 Oct 19, 2023
f9e43b0
fix tests
marc2332 Oct 19, 2023
e9acaa3
tweak
marc2332 Oct 19, 2023
6503c07
tweaks
marc2332 Oct 20, 2023
2419b51
unsized alignment test
marc2332 Oct 21, 2023
9645714
document code
marc2332 Oct 21, 2023
bbf6c20
tweak
marc2332 Oct 21, 2023
00455d0
rename attributes
marc2332 Oct 22, 2023
d6e548f
fixes and cleanup
marc2332 Oct 22, 2023
24b22ce
Merge branch 'main' into feat/enhanced-alignments
marc2332 Oct 22, 2023
b0194ef
fixes and improvements
marc2332 Oct 22, 2023
3e8c68a
Merge branch 'feat/enhanced-alignments' of https://github.com/marc233…
marc2332 Oct 22, 2023
e7fb53f
Merge branch 'main' into feat/enhanced-alignments
marc2332 Oct 22, 2023
19b61aa
typo
marc2332 Oct 22, 2023
b433db0
feat: Easily change the cursor with use_platform
marc2332 Oct 22, 2023
acbba1c
feat: Improve switch
marc2332 Oct 22, 2023
86f1246
Merge branch 'main' into feat/improve-input
marc2332 Oct 26, 2023
ee39a68
fmt
marc2332 Oct 26, 2023
8ddebeb
fix
marc2332 Oct 26, 2023
cc18b23
simplify
marc2332 Oct 27, 2023
e4df661
Merge branch 'main' into feat/improve-input
marc2332 Nov 1, 2023
50e998b
Merge branch 'main' into feat/improve-input
marc2332 Nov 2, 2023
97fa928
Merge branch 'main' into feat/improve-input
marc2332 Nov 2, 2023
13979be
customizable margin
marc2332 Nov 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 96 additions & 57 deletions crates/components/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::CursorArea;
use crate::ScrollView;
use dioxus::prelude::*;
use freya_elements::elements as dioxus_elements;
use freya_elements::events::keyboard::Key;
use freya_elements::events::{KeyboardData, MouseEvent};
use freya_hooks::ButtonTheme;
use freya_hooks::FontTheme;
use freya_hooks::{
use_editable, use_focus, use_get_theme, EditableConfig, EditableEvent, EditableMode, TextEditor,
};
use freya_hooks::{use_platform, ButtonTheme};

use winit::window::CursorIcon;
/// Enum to declare is [`Input`] hidden.
#[derive(Default)]
Expand All @@ -24,6 +24,17 @@ impl InputMode {
Self::Hidden('*')
}
}

/// Indicates the current status of the Input.
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum InputStatus {
/// Default state.
#[default]
Idle,
/// Mouse is hovering the input.
Hovering,
}

/// [`Input`] component properties.
#[derive(Props)]
pub struct InputProps<'a> {
Expand All @@ -34,15 +45,12 @@ pub struct InputProps<'a> {
/// Is input hidden with a character. By default input text is shown.
#[props(default = InputMode::Shown, into)]
hidden: InputMode,
/// Width of the Input. Default 100.
/// Width of the Input. Default 150.
#[props(default = "150".to_string(), into)]
width: String,
/// Height of the Input. Default 100.
#[props(default = "38".to_string(), into)]
height: String,
/// Max lines for the Input. Default 1.
#[props(default = "1".to_string(), into)]
max_lines: String,
/// Margin of the Input. Default 4.
#[props(default = "4".to_string(), into)]
margin: String,
}

/// `Input` component.
Expand Down Expand Up @@ -76,6 +84,8 @@ pub struct InputProps<'a> {
/// ```
#[allow(non_snake_case)]
pub fn Input<'a>(cx: Scope<'a, InputProps<'a>>) -> Element {
let platform = use_platform(cx);
let status = use_ref(cx, InputStatus::default);
let editable = use_editable(
cx,
|| EditableConfig::new(cx.props.value.to_string()),
Expand All @@ -94,20 +104,26 @@ pub fn Input<'a>(cx: Scope<'a, InputProps<'a>>) -> Element {
InputMode::Hidden(ch) => ch.to_string().repeat(cx.props.value.len()),
InputMode::Shown => cx.props.value.clone(),
};
let cursor_attr = editable.cursor_attr(cx);
let highlights_attr = editable.highlights_attr(cx, 0);
let width = &cx.props.width;
let height = &cx.props.height;
let max_lines = &cx.props.max_lines;

use_on_unmount(cx, {
to_owned![status, platform];
move || {
if *status.read() == InputStatus::Hovering {
platform.set_cursor(CursorIcon::default());
}
}
});

let onkeydown = {
to_owned![editable, focus_manager];
move |e: Event<KeyboardData>| {
if focus_manager.is_focused() {
editable.process_event(&EditableEvent::KeyDown(e.data));
cx.props
.onchange
.call(editable.editor().current().to_string());
if e.data.key != Key::Enter {
editable.process_event(&EditableEvent::KeyDown(e.data));
cx.props
.onchange
.call(editable.editor().current().to_string());
}
}
}
};
Expand All @@ -116,6 +132,7 @@ pub fn Input<'a>(cx: Scope<'a, InputProps<'a>>) -> Element {
to_owned![editable];
move |e: MouseEvent| {
editable.process_event(&EditableEvent::MouseDown(e.data, 0));
focus_manager.focus();
}
};

Expand All @@ -126,57 +143,79 @@ pub fn Input<'a>(cx: Scope<'a, InputProps<'a>>) -> Element {
}
};

let onclick = {
let onmouseenter = {
to_owned![platform];
move |_| {
platform.set_cursor(CursorIcon::Text);
*status.write_silent() = InputStatus::Hovering;
}
};

let onmouseleave = move |_| {
platform.set_cursor(CursorIcon::default());
*status.write_silent() = InputStatus::default();
};

let onglobalclick = {
to_owned![editable];
move |_: MouseEvent| {
editable.process_event(&EditableEvent::Click);
focus_manager.focus();
move |_| match *status.read() {
InputStatus::Idle if focus_manager.is_focused() => {
focus_manager.unfocus();
}
InputStatus::Hovering => {
editable.process_event(&EditableEvent::Click);
}
_ => {}
}
};

let cursor_char = if focus_manager.is_focused() {
editable.editor().cursor_pos().to_string()
let cursor_attr = editable.cursor_attr(cx);
let highlights_attr = editable.highlights_attr(cx, 0);
let width = &cx.props.width;
let margin = &cx.props.margin;
let (background, cursor_char) = if focus_manager.is_focused() {
(
theme.button.hover_background,
editable.editor().cursor_pos().to_string(),
)
} else {
"none".to_string()
(theme.button.background, "none".to_string())
};
let ButtonTheme {
background,
border_fill,
font_theme: FontTheme { color, .. },
..
} = theme.button;

render!(
CursorArea {
icon: CursorIcon::Text,
rect {
rect {
width: "{width}",
direction: "vertical",
color: "{color}",
background: "{background}",
border: "1 solid {border_fill}",
shadow: "0 3 15 0 rgb(0, 0, 0, 70)",
corner_radius: "10",
margin: "{margin}",
cursor_reference: cursor_attr,
main_align: "center",
paragraph {
margin: "8 12",
onkeydown: onkeydown,
onclick: onclick,
width: "{width}",
height: "{height}",
direction: "vertical",
color: "{color}",
background: "{background}",
shadow: "0 3 15 0 rgb(0, 0, 0, 70)",
corner_radius: "5",
padding: "8",
margin: "4",
cursor_reference: cursor_attr,
ScrollView {
scroll_with_arrows: false,
paragraph {
width: "100%",
cursor_id: "0",
cursor_index: "{cursor_char}",
cursor_mode: "editable",
cursor_color: "{color}",
max_lines: "{max_lines}",
onmouseover: onmouseover,
onmousedown: onmousedown,
highlights: highlights_attr,
text {
"{text}"
}
}
onglobalclick: onglobalclick,
onmouseenter: onmouseenter,
onmouseleave: onmouseleave,
onmousedown: onmousedown,
onmouseover: onmouseover,
width: "100%",
cursor_id: "0",
cursor_index: "{cursor_char}",
cursor_mode: "editable",
cursor_color: "{color}",
max_lines: "1",
highlights: highlights_attr,
text {
"{text}"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn measure_dom_events(
*node_id,
element_id,
&request_event,
Some(areas.area),
Some(areas.visible_area()),
scale_factor,
);
new_events.push(event);
Expand Down
1 change: 1 addition & 0 deletions crates/elements/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ builder_constructors! {
decoration_style: String,
decoration_color: String,
text_overflow: String,
overflow: String,
focusable: String,
margin: String,
};
Expand Down
3 changes: 0 additions & 3 deletions examples/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ fn app(cx: Scope) -> Element {
"Your name:"
}
Input {
width: "100%",
height: "100",
max_lines: "none",
value: values.0.clone(),
onchange: |e| {
values.set((e, values.1.clone()))
Expand Down