1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
use std::cell::{Ref, RefCell};
use std::collections::HashSet;
use std::hash::Hash;
use std::rc::Rc;
use yew::prelude::*;
use super::use_update;
/// State handle for the [`use_set`] hook.
pub struct UseSetHandle<T> {
inner: Rc<RefCell<HashSet<T>>>,
update: Rc<dyn Fn()>,
}
impl<T> UseSetHandle<T> {
/// Get immutable ref to the set.
///
/// # Panics
///
/// Panics if the value is currently mutably borrowed
pub fn current(&self) -> Ref<HashSet<T>> {
self.inner.borrow()
}
/// Set the hash set.
pub fn set(&self, set: HashSet<T>) {
*self.inner.borrow_mut() = set;
(self.update)();
}
/// Adds a value to the set.
pub fn insert(&self, value: T) -> bool
where
T: Eq + Hash,
{
let present = self.inner.borrow_mut().insert(value);
(self.update)();
present
}
/// Adds a value to the set, replacing the existing value,
/// if any, that is equal to the given one. Returns the replaced value.
pub fn replace(&self, value: T) -> Option<T>
where
T: Eq + Hash,
{
let v = self.inner.borrow_mut().replace(value);
(self.update)();
v
}
/// Removes a value from the set. Returns whether the value was present in the set.
pub fn remove(&self, value: &T) -> bool
where
T: Eq + Hash,
{
let present = self.inner.borrow_mut().remove(value);
(self.update)();
present
}
/// Retains only the elements specified by the predicate.
pub fn retain<F>(&self, f: F)
where
T: Eq + Hash,
F: FnMut(&T) -> bool,
{
self.inner.borrow_mut().retain(f);
(self.update)();
}
/// Clears the set, removing all values.
pub fn clear(&self) {
self.inner.borrow_mut().clear();
(self.update)();
}
}
impl<T> Clone for UseSetHandle<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
update: self.update.clone(),
}
}
}
impl<T> PartialEq for UseSetHandle<T>
where
T: Eq + Hash,
{
fn eq(&self, other: &Self) -> bool {
*self.inner == *other.inner
}
}
/// A hook that tracks a hash set and provides methods to modify it.
///
/// # Example
///
/// ```rust
/// # use std::collections::HashSet;
/// # use yew::prelude::*;
/// #
/// use yew_hooks::prelude::*;
///
/// #[function_component(UseSet)]
/// fn set() -> Html {
/// let set = use_set(HashSet::from(["Mercury", "Venus", "Earth", "Mars"]));
///
/// let onset = {
/// let set = set.clone();
/// Callback::from(move |_| set.set(HashSet::from(["Moon", "Earth"])))
/// };
/// let oninsert = {
/// let set = set.clone();
/// Callback::from(move |_| {
/// let _ = set.insert("Jupiter");
/// })
/// };
/// let onreplace = {
/// let set = set.clone();
/// Callback::from(move |_| {
/// let _ = set.replace("Earth");
/// })
/// };
/// let onremove = {
/// let set = set.clone();
/// Callback::from(move |_| {
/// let _ = set.remove(&"Moon");
/// })
/// };
/// let onretain = {
/// let set = set.clone();
/// Callback::from(move |_| set.retain(|v| v.contains('a')))
/// };
/// let onclear = {
/// let set = set.clone();
/// Callback::from(move |_| set.clear())
/// };
///
/// html! {
/// <div>
/// <button onclick={onset}>{ "Set" }</button>
/// <button onclick={oninsert}>{ "Insert" }</button>
/// <button onclick={onreplace}>{ "Replace" }</button>
/// <button onclick={onremove}>{ "Remove" }</button>
/// <button onclick={onretain}>{ "Retain" }</button>
/// <button onclick={onclear}>{ "Clear all" }</button>
/// <p>
/// <b>{ "Current value: " }</b>
/// </p>
/// {
/// for set.current().iter().map(|v| {
/// html! {
/// <p><b>{ v }</b></p>
/// }
/// })
/// }
/// </div>
/// }
/// }
/// ```
#[hook]
pub fn use_set<T>(initial_value: HashSet<T>) -> UseSetHandle<T>
where
T: 'static,
{
let inner = use_mut_ref(|| initial_value);
let update = use_update();
UseSetHandle { inner, update }
}