ported use_textarea_autosize

This commit is contained in:
Maccesch 2024-09-15 22:30:38 +02:00
parent 406b7b2e16
commit 49f89bcb36
6 changed files with 64 additions and 73 deletions

View file

@ -3,6 +3,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.14.0-beta4] - 2024-09-15
- Latest changes from version 0.13.4 and 0.13.5 ported
## [0.14.0-beta3] - 2024-09-02
### Breaking Changes 🛠

View file

@ -1,6 +1,6 @@
[package]
name = "leptos-use"
version = "0.14.0-beta3"
version = "0.14.0-beta4"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming", "wasm"]
@ -27,7 +27,7 @@ http0_2 = { version = "0.2", optional = true, package = "http" }
js-sys = "0.3"
lazy_static = "1"
leptos = "0.7.0-beta5"
leptos_axum = { version = "0.7.0-beta5", optional = true, }
leptos_axum = { version = "0.7.0-beta5", optional = true }
leptos_actix = { version = "0.7.0-beta5", optional = true }
leptos-spin = { version = "0.2", optional = true }
num = { version = "0.4", optional = true }

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.6", features = ["nightly", "csr"] }
leptos = { workspace = true, features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"

View file

@ -1,10 +1,10 @@
use leptos::*;
use leptos::prelude::*;
use leptos_use::docs::demo_or_body;
use leptos_use::{use_textarea_autosize, UseTextareaAutosizeReturn};
#[component]
fn Demo() -> impl IntoView {
let textarea = create_node_ref::<html::Textarea>();
let textarea = NodeRef::new();
let UseTextareaAutosizeReturn {
content,
@ -15,7 +15,7 @@ fn Demo() -> impl IntoView {
view! {
<div class="mb-4">Type, the textarea will grow:</div>
<textarea
value=content
prop:value=content
on:input=move |evt| set_content.set(event_target_value(&evt))
node_ref=textarea
class="resize-none box-border"
@ -28,7 +28,9 @@ fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo /> }
})
let unmount_handle = leptos::mount::mount_to(demo_or_body(), || {
view! { <Demo/> }
});
unmount_handle.forget();
}

View file

@ -1,7 +1,7 @@
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
use crate::core::{ElementMaybeSignal, IntoElementMaybeSignal, MaybeRwSignal};
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::rc::Rc;
use leptos::prelude::*;
use std::sync::Arc;
/// Automatically update the height of a textarea depending on the content.
///
@ -14,13 +14,13 @@ use std::rc::Rc;
/// ### Simple example
///
/// ```
/// # use leptos::*;
/// # use leptos::prelude::*;
/// # use leptos::html::Textarea;
/// # use leptos_use::{use_textarea_autosize, UseTextareaAutosizeReturn};
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let textarea = create_node_ref::<Textarea>();
/// let textarea = NodeRef::new();
///
/// let UseTextareaAutosizeReturn {
/// content,
@ -30,7 +30,7 @@ use std::rc::Rc;
///
/// view! {
/// <textarea
/// value=content
/// prop:value=content
/// on:input=move |evt| set_content.set(event_target_value(&evt))
/// node_ref=textarea
/// class="resize-none"
@ -62,13 +62,13 @@ use std::rc::Rc;
/// `style_prop` option to `"min-height"`.
///
/// ```
/// # use leptos::*;
/// # use leptos::prelude::*;
/// # use leptos::html::Textarea;
/// # use leptos_use::{use_textarea_autosize_with_options, UseTextareaAutosizeOptions, UseTextareaAutosizeReturn};
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let textarea = create_node_ref::<Textarea>();
/// let textarea = NodeRef::new();
///
/// let UseTextareaAutosizeReturn {
/// content,
@ -81,7 +81,7 @@ use std::rc::Rc;
///
/// view! {
/// <textarea
/// value=content
/// prop:value=content
/// on:input=move |evt| set_content.set(event_target_value(&evt))
/// node_ref=textarea
/// class="resize-none"
@ -96,36 +96,30 @@ use std::rc::Rc;
///
/// On the server this will always return an empty string as ´content` and a no-op `trigger_resize`.
// #[doc(cfg(feature = "use_textarea_autosize"))]
pub fn use_textarea_autosize<El, T>(el: El) -> UseTextareaAutosizeReturn<impl Fn() + Clone>
pub fn use_textarea_autosize<El, M>(el: El) -> UseTextareaAutosizeReturn<impl Fn() + Clone>
where
El: Into<ElementMaybeSignal<T, web_sys::Element>> + Clone,
T: Into<web_sys::Element> + Clone + 'static,
El: IntoElementMaybeSignal<web_sys::Element, M> + Clone,
{
use_textarea_autosize_with_options::<El, T, web_sys::Element>(
el,
UseTextareaAutosizeOptions::default(),
)
use_textarea_autosize_with_options::<El, M>(el, UseTextareaAutosizeOptions::default())
}
/// Version of [`fn@crate::use_textarea_autosize`] that takes a `UseTextareaAutosizeOptions`. See [`fn@crate::use_textarea_autosize`] for how to use.
// #[doc(cfg(feature = "use_textarea_autosize"))]
pub fn use_textarea_autosize_with_options<El, T, StyleT>(
pub fn use_textarea_autosize_with_options<El, M>(
el: El,
options: UseTextareaAutosizeOptions<StyleT>,
options: UseTextareaAutosizeOptions,
) -> UseTextareaAutosizeReturn<impl Fn() + Clone>
where
El: Into<ElementMaybeSignal<T, web_sys::Element>> + Clone,
T: Into<web_sys::Element> + Clone + 'static,
StyleT: Into<web_sys::Element> + Clone + 'static,
El: IntoElementMaybeSignal<web_sys::Element, M> + Clone,
{
#[cfg(not(feature = "ssr"))]
{
use wasm_bindgen::JsCast;
let el = el.into();
let textarea = Signal::derive(move || {
let el = el.into_element_maybe_signal();
let textarea = Signal::derive_local(move || {
el.get()
.map(|el| el.into().unchecked_into::<web_sys::HtmlTextAreaElement>())
.map(|el| el.unchecked_into::<web_sys::HtmlTextAreaElement>())
});
let UseTextareaAutosizeOptions {
@ -138,11 +132,11 @@ where
let (content, set_content) = content.into_signal();
let (textarea_scroll_height, set_textarea_scroll_height) = create_signal(1);
let (textarea_old_width, set_textarea_old_width) = create_signal(0.0);
let (textarea_scroll_height, set_textarea_scroll_height) = signal(1);
let (textarea_old_width, set_textarea_old_width) = signal(0.0);
let trigger_resize = move || {
textarea.with(|textarea| {
textarea.with_untracked(|textarea| {
if let Some(textarea) = textarea {
let mut height = "".to_string();
@ -161,13 +155,14 @@ where
0
};
textarea.style().set_property(&style_prop, "1px").ok();
web_sys::HtmlElement::style(textarea)
.set_property(&style_prop, "1px")
.ok();
set_textarea_scroll_height.set(textarea.scroll_height() + border_offset + 1);
if let Some(style_target) = style_target.get() {
// If style target is provided update its height
style_target
.into()
.unchecked_into::<web_sys::HtmlElement>()
.style()
.set_property(
@ -180,15 +175,17 @@ where
height = format!("{}px", textarea_scroll_height.get_untracked());
}
textarea.style().set_property(&style_prop, &height).ok();
web_sys::HtmlElement::style(textarea)
.set_property(&style_prop, &height)
.ok();
}
})
};
let _ = watch(
Effect::watch(
move || {
content.track();
textarea.track();
content.with(|_| ());
textarea.with(|_| ());
},
{
let trigger_resize = trigger_resize.clone();
@ -200,7 +197,7 @@ where
true,
);
let _ = watch(
Effect::watch(
move || textarea_scroll_height.track(),
move |_, _, _| {
on_resize();
@ -223,7 +220,7 @@ where
}
});
let _ = watch(
Effect::watch(
move || watch_fn(),
{
let trigger_resize = trigger_resize.clone();
@ -247,7 +244,7 @@ where
let _ = el;
let _ = options;
let (content, set_content) = create_signal("".to_string());
let (content, set_content) = signal("".to_string());
UseTextareaAutosizeReturn {
content: content.into(),
@ -261,24 +258,21 @@ where
// #[doc(cfg(feature = "use_textarea_autosize"))]
#[derive(DefaultBuilder)]
#[cfg_attr(feature = "ssr", allow(dead_code))]
pub struct UseTextareaAutosizeOptions<T>
where
T: Into<web_sys::Element> + Clone + 'static,
{
pub struct UseTextareaAutosizeOptions {
/// Textarea content
#[builder(into)]
content: MaybeRwSignal<String>,
/// Watch sources that should trigger a textarea resize
watch: Rc<dyn Fn()>,
watch: Arc<dyn Fn() + Send + Sync>,
/// Function called when the textarea size changes
on_resize: Rc<dyn Fn()>,
on_resize: Arc<dyn Fn() + Send + Sync>,
/// Specify style target to apply the height based on textarea content.
/// If not provided it will use textarea it self.
#[builder(skip)]
style_target: ElementMaybeSignal<T, web_sys::Element>,
style_target: ElementMaybeSignal<web_sys::Element>,
/// Specify the style property that will be used to manipulate height.
/// Should be `"height"` or `"min-height"`. Default value is `"height"`.
@ -286,37 +280,28 @@ where
style_prop: String,
}
impl Default for UseTextareaAutosizeOptions<web_sys::Element> {
impl Default for UseTextareaAutosizeOptions {
fn default() -> Self {
Self {
content: MaybeRwSignal::default(),
watch: Rc::new(|| ()),
on_resize: Rc::new(|| ()),
watch: Arc::new(|| ()),
on_resize: Arc::new(|| ()),
style_target: Default::default(),
style_prop: "height".to_string(),
}
}
}
impl<T> UseTextareaAutosizeOptions<T>
where
T: Into<web_sys::Element> + Clone + 'static,
{
impl UseTextareaAutosizeOptions {
/// List of elementss that should not trigger the callback. Defaults to `[]`.
#[cfg_attr(feature = "ssr", allow(dead_code))]
pub fn style_target<NewT>(
pub fn style_target<M>(
self,
style_target: impl Into<ElementMaybeSignal<NewT, web_sys::Element>>,
) -> UseTextareaAutosizeOptions<NewT>
where
NewT: Into<web_sys::Element> + Clone + 'static,
{
UseTextareaAutosizeOptions {
content: self.content,
watch: self.watch,
on_resize: self.on_resize,
style_target: style_target.into(),
style_prop: self.style_prop,
style_target: impl IntoElementMaybeSignal<web_sys::Element, M>,
) -> Self {
Self {
style_target: style_target.into_element_maybe_signal(),
..self
}
}
}

View file

@ -285,7 +285,7 @@ where
let (ready_state, set_ready_state) = signal(ConnectionReadyState::Closed);
let (message, set_message) = signal(None);
let ws_signal = RwSignal::new(None::<WebSocket>);
let ws_signal = RwSignal::new_local(None::<WebSocket>);
let reconnect_timer_ref: StoredValue<Option<TimeoutHandle>> = StoredValue::new(None);
@ -716,7 +716,7 @@ where
/// Latest message received from `WebSocket`.
pub message: Signal<Option<Rx>>,
/// The `WebSocket` instance.
pub ws: Signal<Option<WebSocket>>,
pub ws: Signal<Option<WebSocket>, LocalStorage>,
/// Opens the `WebSocket` connection
pub open: OpenFn,
/// Closes the `WebSocket` connection