leptos_use/
use_sorted.rs

1use leptos::prelude::*;
2use leptos::reactive::wrappers::read::Signal;
3use std::cmp::Ordering;
4use std::ops::DerefMut;
5
6/// Reactive sort of iterable
7///
8/// ## Demo
9///
10/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_sorted)
11///
12/// ## Usage
13///
14/// ```
15/// # use leptos::prelude::*;
16/// # use leptos_use::use_sorted;
17/// #
18/// # #[component]
19/// # fn Demo() -> impl IntoView {
20/// let source = vec![10, 3, 5, 7, 2, 1, 8, 6, 9, 4];
21/// let sorted: Signal<Vec<i32>> = use_sorted(source); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
22/// #
23/// # view! { }
24/// # }
25/// ```
26///
27/// You can also sort by key or with a compare function.
28///
29/// ```
30/// # use leptos::prelude::*;
31/// # use leptos_use::{use_sorted_by, use_sorted_by_key};
32/// #
33/// #[derive(Clone, PartialEq)]
34/// pub struct Person {
35///     pub name: String,
36///     pub age: u16,
37/// }
38///
39/// # #[component]
40/// # fn Demo() -> impl IntoView {
41/// let source = vec![
42///     Person {
43///         name: "John".to_string(),
44///         age: 40,
45///     },
46///     Person {
47///         name: "Jane".to_string(),
48///         age: 20,
49///     },
50///     Person {
51///         name: "Joe".to_string(),
52///         age: 30,
53///     },
54///     Person {
55///         name: "Jenny".to_string(),
56///         age: 22,
57///     },
58/// ];
59///
60/// // sort by key
61/// let sorted: Signal<Vec<Person>> = use_sorted_by_key(
62///     source.clone(),
63///     |person: &Person| person.age,
64/// );
65///
66/// // sort with compare function
67/// let sorted: Signal<Vec<Person>> = use_sorted_by(
68///     source,
69///     |p1: &Person, p2: &Person| p1.age.cmp(&p2.age),
70/// );
71/// #
72/// # view! { }
73/// # }
74/// ```
75///
76/// Please note that these two ways of sorting are equivalent.
77pub fn use_sorted<S, I, T>(iterable: S) -> Signal<I>
78where
79    S: Into<Signal<I>>,
80    T: Ord,
81    I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
82{
83    let iterable = iterable.into();
84
85    Signal::derive(move || {
86        let mut iterable = iterable.get();
87        iterable.sort();
88        iterable
89    })
90}
91
92/// Version of [`use_sorted`] with a compare function.
93pub fn use_sorted_by<S, I, T, F>(iterable: S, cmp_fn: F) -> Signal<I>
94where
95    S: Into<Signal<I>>,
96    I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
97    F: FnMut(&T, &T) -> Ordering + Clone + Send + Sync + 'static,
98{
99    let iterable = iterable.into();
100
101    Signal::derive(move || {
102        let mut iterable = iterable.get();
103        iterable.sort_by(cmp_fn.clone());
104        iterable
105    })
106}
107
108/// Version of [`use_sorted`] by key.
109pub fn use_sorted_by_key<S, I, T, K, F>(iterable: S, key_fn: F) -> Signal<I>
110where
111    S: Into<Signal<I>>,
112    I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
113    K: Ord,
114    F: FnMut(&T) -> K + Clone + Send + Sync + 'static,
115{
116    let iterable = iterable.into();
117
118    Signal::derive(move || {
119        let mut iterable = iterable.get();
120        iterable.sort_by_key(key_fn.clone());
121        iterable
122    })
123}