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}