diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c468f..48c3b3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ #### New Functions - `use_floor` +- `use_max` +- `use_min` #### Other Changes - New feature: `math` that has to be activated in order to use the math functions. diff --git a/Cargo.toml b/Cargo.toml index 203842d..9afcb2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leptos-use" -version = "0.1.4" +version = "0.1.5" edition = "2021" authors = ["Marc-Stefan Cassola"] categories = ["gui", "web-programming"] diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index c4fb650..e4ce538 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -28,6 +28,8 @@ - [use_supported](utilities/use_supported.md) - [use_throttle_fn](utilities/use_throttle_fn.md) -# Math +# @Math -- [use_floor](math/use_floor.md) \ No newline at end of file +- [use_floor](math/use_floor.md) +- [use_max](math/use_max.md) +- [use_min](math/use_min.md) \ No newline at end of file diff --git a/docs/book/src/extract_doc_comment.py b/docs/book/src/extract_doc_comment.py index ad0ec8f..78d2913 100644 --- a/docs/book/src/extract_doc_comment.py +++ b/docs/book/src/extract_doc_comment.py @@ -42,12 +42,19 @@ def main(): initial_doc_finished = False for line in f.readlines(): + stripped_line = line.strip() + if initial_doc_finished: process_further_line(line, types, module) - elif line.startswith("///"): + elif stripped_line.startswith("///") or stripped_line.startswith("#[doc ="): doc_comment_started = True - line = line.strip().replace("/// ", "").replace("///", "") + + if line.startswith("#[doc"): + line = stripped_line.replace("#[doc = \" ", "").replace("#[doc = \"", "")[:-2] + else: + line = stripped_line.replace("/// ", "").replace("///", "") + if "```" in line: if not in_code_block: line = line.replace("```", "```rust,ignore") @@ -60,6 +67,9 @@ def main(): elif doc_comment_started: initial_doc_finished = True + if feature is not None: + append_feature_paragraph(feature) + add_types_paragraph(types) add_source_paragraph(name, module) @@ -119,6 +129,11 @@ def process_further_line(line, types, module=None): append_type(line, "struct", types, module) +def append_feature_paragraph(feature): + print(f"""## Feature +> This function is only available if the crate feature **`{feature}`** is enabled""") + + def append_type(line, ty, types, module=None): start_index = len(f"pub {ty} ") m = re.search(ident_pattern, line[start_index:]) diff --git a/docs/book/src/math/use_max.md b/docs/book/src/math/use_max.md new file mode 100644 index 0000000..deed904 --- /dev/null +++ b/docs/book/src/math/use_max.md @@ -0,0 +1,3 @@ +# use_max + + diff --git a/docs/book/src/math/use_min.md b/docs/book/src/math/use_min.md new file mode 100644 index 0000000..3585914 --- /dev/null +++ b/docs/book/src/math/use_min.md @@ -0,0 +1,3 @@ +# use_min + + diff --git a/src/lib.rs b/src/lib.rs index d2c14ff..d2f06db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(doc_cfg)] //! Collection of essential Leptos utilities inspired by SolidJS USE / VueUse pub mod core; diff --git a/src/math/mod.rs b/src/math/mod.rs index a0b8b7f..6a749c5 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -1,3 +1,8 @@ +mod shared; mod use_floor; +mod use_max; +mod use_min; pub use use_floor::*; +pub use use_max::*; +pub use use_min::*; diff --git a/src/math/shared.rs b/src/math/shared.rs new file mode 100644 index 0000000..8c2fa9c --- /dev/null +++ b/src/math/shared.rs @@ -0,0 +1,42 @@ +macro_rules! use_partial_cmp { + ($(#[$outer:meta])* + $fn_name:ident, + $ord:pat + ) => { + $(#[$outer])* + pub fn $fn_name(cx: Scope, container: S) -> Signal> + where + S: Into>, + C: 'static, + for<'a> &'a C: IntoIterator, + N: PartialOrd + Clone, + { + let container = container.into(); + + create_memo(cx, move |_| { + container.with(|container| { + if container.into_iter().count() == 0 { + return None; + } + + container + .into_iter() + .fold(None, |acc, e| match acc { + Some(acc) => match N::partial_cmp(acc, e) { + Some($ord) => Some(e), + _ => Some(acc), + }, + None => match N::partial_cmp(e, e) { + None => None, + _ => Some(e), + }, + }) + .cloned() + }) + }) + .into() + } + }; +} + +pub(crate) use use_partial_cmp; diff --git a/src/math/use_floor.rs b/src/math/use_floor.rs index ed80722..d0b9621 100644 --- a/src/math/use_floor.rs +++ b/src/math/use_floor.rs @@ -7,7 +7,7 @@ use num::Float; /// /// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_floor) /// -/// ### Usage +/// ## Usage /// /// ``` /// # use leptos::*; @@ -17,9 +17,12 @@ use num::Float; /// # fn Demo(cx: Scope) -> impl IntoView { /// let (value, set_value) = create_signal(cx, 45.95); /// let result: Signal = use_floor(cx, value); // 45 +/// # +/// # assert_eq!(result.get(), 45.0); /// # view! { cx, } /// # } /// ``` +#[doc(cfg(feature = "math"))] pub fn use_floor(cx: Scope, x: S) -> Signal where S: Into>, diff --git a/src/math/use_max.rs b/src/math/use_max.rs new file mode 100644 index 0000000..0cd4332 --- /dev/null +++ b/src/math/use_max.rs @@ -0,0 +1,32 @@ +use crate::math::shared::use_partial_cmp; +use leptos::*; +use std::cmp::Ordering; + +use_partial_cmp!( + /// Reactive `max()`. + /// + /// Works with any container that implements `IntoIterator` (`Vec`, `HashSet`, ...) + /// with any elements that implement `PartialOrd` and `Clone` (floats, ints, strings, ...). + /// + /// If the container is empty or only contains non comparable values like `NaN`, it returns `None`. + /// Otherwise it returns the `Some()` in the container. + /// + /// ## Usage + /// + /// ``` + /// # use leptos::*; + /// # use leptos_use::math::use_max; + /// # + /// # #[component] + /// # fn Demo(cx: Scope) -> impl IntoView { + /// let (values, set_values) = create_signal(cx, vec![1.0, 2.0, 3.0, f32::NAN, 4.0, 5.0]); + /// let result = use_max::, _, _>(cx, values); // Some(5.0) + /// # + /// # assert_eq!(result.get(), Some(5.0)); + /// # view! { cx, } + /// # } + /// ``` + #[doc(cfg(feature = "math"))] + use_max, + Ordering::Less +); diff --git a/src/math/use_min.rs b/src/math/use_min.rs new file mode 100644 index 0000000..cbf9b51 --- /dev/null +++ b/src/math/use_min.rs @@ -0,0 +1,32 @@ +use crate::math::shared::use_partial_cmp; +use leptos::*; +use std::cmp::Ordering; + +use_partial_cmp!( + /// Reactive `min()`. + /// + /// Works with any container that implements `IntoIterator` (`Vec`, `HashSet`, ...) + /// with any elements that implement `PartialOrd` and `Clone` (floats, ints, strings, ...). + /// + /// If the container is empty or only contains non comparable values like `NaN`, it returns `None`. + /// Otherwise it returns the `Some()` in the container. + /// + /// ## Usage + /// + /// ``` + /// # use leptos::*; + /// # use leptos_use::math::use_min; + /// # + /// # #[component] + /// # fn Demo(cx: Scope) -> impl IntoView { + /// let (values, set_values) = create_signal(cx, vec![1.0, 2.0, 3.0, f32::NAN, 4.0, 5.0]); + /// let result = use_min::, _, _>(cx, values); // Some(1.0) + /// # + /// # assert_eq!(result.get(), Some(1.0)); + /// # view! { cx, } + /// # } + /// ``` + #[doc(cfg(feature = "math"))] + use_min, + Ordering::Greater +);