mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
parent
ffff14ea9c
commit
84396b7675
7 changed files with 503 additions and 61 deletions
|
@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Changes 🔥
|
||||
|
||||
- The `UseMouseReturn` signals `x`, `y`, and `source_type` are now of type `Signal<f64>` instead of `ReadSignal<f64>`.
|
||||
- You can now convert `leptos::html::HtmlElement<T>` into `Element(s)MaybeSignal`. This should make functions a lot easier to use in directives.
|
||||
- There's now a chapter in the book especially for `Element(s)MaybeSignal`.
|
||||
|
||||
## [0.9.0] - 2023-12-06
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
[Introduction](introduction.md)
|
||||
[Get Started](get_started.md)
|
||||
[Element Parameters](element_parameters.md)
|
||||
[Server-Side Rendering](server_side_rendering.md)
|
||||
[Changelog](changelog.md)
|
||||
[Functions](functions.md)
|
||||
|
|
95
docs/book/src/element_parameters.md
Normal file
95
docs/book/src/element_parameters.md
Normal file
|
@ -0,0 +1,95 @@
|
|||
# Element Parameters
|
||||
|
||||
Many functions in this library operate on HTML/SVG elements. For example, the
|
||||
function [`use_element_size`](elements/use_element_size.md) returns the width and height of an element:
|
||||
|
||||
```rust
|
||||
# use leptos::{*, html::Div};
|
||||
# use leptos_use::{use_element_size, UseElementSizeReturn};
|
||||
#
|
||||
# #[component]
|
||||
# pub fn Component() -> impl IntoView {
|
||||
let el = create_node_ref::<Div>();
|
||||
|
||||
let UseElementSizeReturn { width, height } = use_element_size(el);
|
||||
|
||||
view! {
|
||||
<div node_ref=el></div>
|
||||
}
|
||||
# }
|
||||
```
|
||||
|
||||
In the example above we used a Leptos `NodeRef` to pass into the function. But that is not
|
||||
the only way you can do that. All of these work as well:
|
||||
|
||||
```rust
|
||||
use_element_size(window().body()); // Option<web_sys::Element>
|
||||
use_element_size(window().body().unwrap()); // web_sys::Element
|
||||
use_element_size("div > p.some-class"); // &str or String intepreted as CSS selector
|
||||
|
||||
pub fn some_directive(el: HtmlElement<AnyElement>) {
|
||||
use_element_size(el); // leptos::html::HtmlElement<T>
|
||||
}
|
||||
```
|
||||
|
||||
Signal of Strings: `Signal<String>`, `ReadSignal<String>`, `RwSignal<String>`, `Memo<String>`; also works with `&str`:
|
||||
|
||||
```rust
|
||||
let (str_signal, set_str_signal) = create_signal("div > p.some-class".to_string());
|
||||
use_element_size(str_signal);
|
||||
```
|
||||
|
||||
Signals of Elements: `Signal<web_sys::Element>`, `ReadSignal<web_sys::Element>`, `RwSignal<web_sys::Element>`, `Memo<web_sys::Element>`; also works with `Option<web_sys::Element>`:
|
||||
|
||||
```rust
|
||||
let (el_signal, set_el_signal) = create_signal(document().query_selector("div > p.some-class").unwrap());
|
||||
use_element_size(el_signal);
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
Looking at the source code of `use_element_size` you'll find sth like
|
||||
|
||||
```rust
|
||||
pub fn use_element_size(el: Into<ElementMaybeSignal<...>>) -> UseElementSizeReturn {}
|
||||
```
|
||||
|
||||
All the above code works because there are `From` implementations for all of these
|
||||
types for `ElementMaybeSignal`.
|
||||
|
||||
## `ElementsMaybeSignal`
|
||||
|
||||
Some functions work on one or more elements. Take [`use_resize_observer`](elements/use_resize_observer.md) for example.
|
||||
This works very much the same way as described above but instead of `Into<ElementMaybeSignal>`
|
||||
it takes an `Into<ElementsMaybeSignal>` (note the plural). This means you can use it exactly in
|
||||
the same ways as you saw with the singular `ElementMaybeSignal`. Only this time, when you use
|
||||
`String` or `&str` it will be interpreted as CSS selector with `query_selector_all`.
|
||||
|
||||
But you can also use it with containers.
|
||||
|
||||
```rust
|
||||
// Array of Option<web_sys::Element>
|
||||
use_resize_observer([window().body(), document().query_selector("div > p.some-class").unsrap()]);
|
||||
|
||||
// Vec of &str. All of them will be interpreted as CSS selectors with query_selector_all() and the
|
||||
// results will be merged into one Vec.
|
||||
use_resize_observer(vec!["div > p.some-class", "p.some-class"]);
|
||||
|
||||
// Slice of NodeRef
|
||||
let node_ref1 = create_node_ref::<Div>();
|
||||
let node_ref2 = create_node_ref::<Div>();
|
||||
use_resize_observer(vec![node_ref1, node_ref2].as_slice());
|
||||
```
|
||||
|
||||
## Usage in Options
|
||||
|
||||
Some functions have options that take `Element(s)MaybeSignal`.
|
||||
They can be used in the same way.
|
||||
|
||||
```rust
|
||||
use_mouse_with_options(
|
||||
UseMouseOptions::default().target("div > p.some-class")
|
||||
);
|
||||
```
|
||||
|
||||
See also ["Excluding Elements" in `on_click_outside`](elements/on_click_outside.md#excluding-elements).
|
|
@ -8,7 +8,7 @@ async fn main() {
|
|||
use leptos_use_ssr::app::*;
|
||||
use leptos_use_ssr::fileserv::file_and_error_handler;
|
||||
|
||||
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
|
||||
simple_logger::init_with_level(log::Level::Info).expect("couldn't initialize logging");
|
||||
|
||||
// Setting get_configuration(None) means we'll be using cargo-leptos's env values
|
||||
// For deployment these variables are:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{UseDocument, UseWindow};
|
||||
use cfg_if::cfg_if;
|
||||
use leptos::html::ElementDescriptor;
|
||||
use leptos::html::{ElementDescriptor, HtmlElement};
|
||||
use leptos::*;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
|
@ -196,23 +196,37 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<E> From<Signal<String>> for ElementMaybeSignal<web_sys::Element, E>
|
||||
where
|
||||
E: From<web_sys::Element> + 'static,
|
||||
{
|
||||
fn from(signal: Signal<String>) -> Self {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
let _ = signal;
|
||||
Self::Dynamic(Signal::derive(|| None))
|
||||
} else {
|
||||
Self::Dynamic(
|
||||
create_memo(move |_| document().query_selector(&signal.get()).unwrap_or_default())
|
||||
.into(),
|
||||
)
|
||||
}}
|
||||
}
|
||||
macro_rules! impl_from_signal_string {
|
||||
($ty:ty) => {
|
||||
impl<E> From<$ty> for ElementMaybeSignal<web_sys::Element, E>
|
||||
where
|
||||
E: From<web_sys::Element> + 'static,
|
||||
{
|
||||
fn from(signal: $ty) -> Self {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
let _ = signal;
|
||||
Self::Dynamic(Signal::derive(|| None))
|
||||
} else {
|
||||
Self::Dynamic(
|
||||
create_memo(move |_| document().query_selector(&signal.get()).unwrap_or_default())
|
||||
.into(),
|
||||
)
|
||||
}}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_signal_string!(Signal<String>);
|
||||
impl_from_signal_string!(ReadSignal<String>);
|
||||
impl_from_signal_string!(RwSignal<String>);
|
||||
impl_from_signal_string!(Memo<String>);
|
||||
|
||||
impl_from_signal_string!(Signal<&str>);
|
||||
impl_from_signal_string!(ReadSignal<&str>);
|
||||
impl_from_signal_string!(RwSignal<&str>);
|
||||
impl_from_signal_string!(Memo<&str>);
|
||||
|
||||
// From signal ///////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_signal_option {
|
||||
|
@ -274,3 +288,22 @@ macro_rules! impl_from_node_ref {
|
|||
|
||||
impl_from_node_ref!(web_sys::EventTarget);
|
||||
impl_from_node_ref!(web_sys::Element);
|
||||
|
||||
// From leptos::html::HTMLElement ///////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_html_element {
|
||||
($ty:ty) => {
|
||||
impl<HtmlEl> From<HtmlElement<HtmlEl>> for ElementMaybeSignal<$ty, $ty>
|
||||
where
|
||||
HtmlEl: ElementDescriptor + std::ops::Deref<Target = $ty>,
|
||||
{
|
||||
fn from(value: HtmlElement<HtmlEl>) -> Self {
|
||||
let el: &$ty = value.deref();
|
||||
Self::Static(Some(el.clone()))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_html_element!(web_sys::EventTarget);
|
||||
impl_from_html_element!(web_sys::Element);
|
||||
|
|
|
@ -180,6 +180,9 @@ where
|
|||
{
|
||||
fn from(target: &'a str) -> Self {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
let _ = target;
|
||||
Self::Static(vec![])
|
||||
} else {
|
||||
if let Ok(node_list) = document().query_selector_all(target) {
|
||||
let mut list = Vec::with_capacity(node_list.length() as usize);
|
||||
for i in 0..node_list.length() {
|
||||
|
@ -191,9 +194,6 @@ where
|
|||
} else {
|
||||
Self::Static(vec![])
|
||||
}
|
||||
} else {
|
||||
let _ = target;
|
||||
Self::Static(vec![])
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -207,34 +207,48 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<E> From<Signal<String>> for ElementsMaybeSignal<web_sys::Node, E>
|
||||
where
|
||||
E: From<web_sys::Node> + 'static,
|
||||
{
|
||||
fn from(signal: Signal<String>) -> Self {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
Self::Dynamic(
|
||||
create_memo(move |_| {
|
||||
if let Ok(node_list) = document().query_selector_all(&signal.get()) {
|
||||
let mut list = Vec::with_capacity(node_list.length() as usize);
|
||||
for i in 0..node_list.length() {
|
||||
let node = node_list.get(i).expect("checked the range");
|
||||
list.push(Some(node));
|
||||
}
|
||||
list
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
})
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
let _ = signal;
|
||||
Self::Dynamic(Signal::derive(Vec::new))
|
||||
}}
|
||||
}
|
||||
macro_rules! impl_from_signal_string {
|
||||
($ty:ty) => {
|
||||
impl<E> From<$ty> for ElementsMaybeSignal<web_sys::Node, E>
|
||||
where
|
||||
E: From<web_sys::Node> + 'static,
|
||||
{
|
||||
fn from(signal: $ty) -> Self {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
Self::Dynamic(
|
||||
create_memo(move |_| {
|
||||
if let Ok(node_list) = document().query_selector_all(&signal.get()) {
|
||||
let mut list = Vec::with_capacity(node_list.length() as usize);
|
||||
for i in 0..node_list.length() {
|
||||
let node = node_list.get(i).expect("checked the range");
|
||||
list.push(Some(node));
|
||||
}
|
||||
list
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
})
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
let _ = signal;
|
||||
Self::Dynamic(Signal::derive(Vec::new))
|
||||
}}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_signal_string!(Signal<String>);
|
||||
impl_from_signal_string!(ReadSignal<String>);
|
||||
impl_from_signal_string!(RwSignal<String>);
|
||||
impl_from_signal_string!(Memo<String>);
|
||||
|
||||
impl_from_signal_string!(Signal<&str>);
|
||||
impl_from_signal_string!(ReadSignal<&str>);
|
||||
impl_from_signal_string!(RwSignal<&str>);
|
||||
impl_from_signal_string!(Memo<&str>);
|
||||
|
||||
// From single signal ///////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_signal_option {
|
||||
|
@ -297,7 +311,26 @@ macro_rules! impl_from_node_ref {
|
|||
impl_from_node_ref!(web_sys::EventTarget);
|
||||
impl_from_node_ref!(web_sys::Element);
|
||||
|
||||
// From multiple static elements //////////////////////////////////////////////////////////////
|
||||
// From single leptos::html::HTMLElement ///////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_html_element {
|
||||
($ty:ty) => {
|
||||
impl<HtmlEl> From<HtmlElement<HtmlEl>> for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
HtmlEl: ElementDescriptor + std::ops::Deref<Target = $ty>,
|
||||
{
|
||||
fn from(value: HtmlElement<HtmlEl>) -> Self {
|
||||
let el: &$ty = value.deref();
|
||||
Self::Static(vec![Some(el.clone())])
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_html_element!(web_sys::EventTarget);
|
||||
impl_from_html_element!(web_sys::Element);
|
||||
|
||||
// From multiple static elements //////////////////////////////////////////////////////
|
||||
|
||||
impl<T, E> From<&[T]> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
|
@ -317,6 +350,105 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, E> From<Vec<T>> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(target: Vec<T>) -> Self {
|
||||
Self::Static(target.iter().map(|t| Some(t.clone())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> From<Vec<Option<T>>> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(target: Vec<Option<T>>) -> Self {
|
||||
Self::Static(target.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, const C: usize> From<[T; C]> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(target: [T; C]) -> Self {
|
||||
Self::Static(target.iter().map(|t| Some(t.clone())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, const C: usize> From<[Option<T>; C]> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(target: [Option<T>; C]) -> Self {
|
||||
Self::Static(target.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
// From multiple strings //////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_strings_inner {
|
||||
($el_ty:ty, $str_ty:ty, $target:ident) => {
|
||||
Self::Static(
|
||||
$target
|
||||
.iter()
|
||||
.filter_map(|sel: &$str_ty| -> Option<Vec<Option<$el_ty>>> {
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
let _ = sel;
|
||||
None
|
||||
} else {
|
||||
if let Ok(node_list) = document().query_selector_all(sel) {
|
||||
let mut list = Vec::with_capacity(node_list.length() as usize);
|
||||
for i in 0..node_list.length() {
|
||||
let node: $el_ty = node_list.get(i).expect("checked the range").unchecked_into();
|
||||
list.push(Some(node));
|
||||
}
|
||||
|
||||
Some(list)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}}
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_strings_with_container {
|
||||
($el_ty:ty, $str_ty:ty, $container_ty:ty) => {
|
||||
impl From<$container_ty> for ElementsMaybeSignal<$el_ty, $el_ty> {
|
||||
fn from(target: $container_ty) -> Self {
|
||||
impl_from_strings_inner!($el_ty, $str_ty, target)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_strings {
|
||||
($el_ty:ty, $str_ty:ty) => {
|
||||
impl_from_strings_with_container!($el_ty, $str_ty, Vec<$str_ty>);
|
||||
impl_from_strings_with_container!($el_ty, $str_ty, &[$str_ty]);
|
||||
impl<const C: usize> From<[$str_ty; C]> for ElementsMaybeSignal<$el_ty, $el_ty> {
|
||||
fn from(target: [$str_ty; C]) -> Self {
|
||||
impl_from_strings_inner!($el_ty, $str_ty, target)
|
||||
}
|
||||
}
|
||||
impl<const C: usize> From<&[$str_ty; C]> for ElementsMaybeSignal<$el_ty, $el_ty> {
|
||||
fn from(target: &[$str_ty; C]) -> Self {
|
||||
impl_from_strings_inner!($el_ty, $str_ty, target)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_strings!(web_sys::Element, &str);
|
||||
impl_from_strings!(web_sys::Element, String);
|
||||
impl_from_strings!(web_sys::EventTarget, &str);
|
||||
impl_from_strings!(web_sys::EventTarget, String);
|
||||
|
||||
// From signal of vec ////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<T, E> From<Signal<Vec<T>>> for ElementsMaybeSignal<T, E>
|
||||
|
@ -367,8 +499,77 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, E> From<Vec<Signal<T>>> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(list: Vec<Signal<T>>) -> Self {
|
||||
let list = list.clone();
|
||||
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
list.iter().map(|t| Some(t.get())).collect()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> From<Vec<Signal<Option<T>>>> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(list: Vec<Signal<Option<T>>>) -> Self {
|
||||
let list = list.clone();
|
||||
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
list.iter().map(|t| t.get()).collect()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, const C: usize> From<[Signal<T>; C]> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(list: [Signal<T>; C]) -> Self {
|
||||
let list = list.to_vec();
|
||||
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
list.iter().map(|t| Some(t.get())).collect()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, const C: usize> From<[Signal<Option<T>>; C]> for ElementsMaybeSignal<T, E>
|
||||
where
|
||||
T: Into<E> + Clone + 'static,
|
||||
{
|
||||
fn from(list: [Signal<Option<T>>; C]) -> Self {
|
||||
let list = list.to_vec();
|
||||
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
list.iter().map(|t| t.get()).collect()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
// From multiple NodeRefs //////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_multi_node_ref_inner {
|
||||
($ty:ty, $node_refs:ident) => {
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
$node_refs
|
||||
.iter()
|
||||
.map(|node_ref| {
|
||||
node_ref.get().map(move |el| {
|
||||
let el = el.into_any();
|
||||
let el: $ty = el.deref().clone().into();
|
||||
el
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_multi_node_ref {
|
||||
($ty:ty) => {
|
||||
impl<R> From<&[NodeRef<R>]> for ElementsMaybeSignal<$ty, $ty>
|
||||
|
@ -377,19 +578,27 @@ macro_rules! impl_from_multi_node_ref {
|
|||
{
|
||||
fn from(node_refs: &[NodeRef<R>]) -> Self {
|
||||
let node_refs = node_refs.to_vec();
|
||||
impl_from_multi_node_ref_inner!($ty, node_refs)
|
||||
}
|
||||
}
|
||||
|
||||
Self::Dynamic(Signal::derive(move || {
|
||||
node_refs
|
||||
.iter()
|
||||
.map(|node_ref| {
|
||||
node_ref.get().map(move |el| {
|
||||
let el = el.into_any();
|
||||
let el: $ty = el.deref().clone().into();
|
||||
el
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}))
|
||||
impl<R, const C: usize> From<[NodeRef<R>; C]> for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
R: ElementDescriptor + Clone + 'static,
|
||||
{
|
||||
fn from(node_refs: [NodeRef<R>; C]) -> Self {
|
||||
let node_refs = node_refs.to_vec();
|
||||
impl_from_multi_node_ref_inner!($ty, node_refs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<Vec<NodeRef<R>>> for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
R: ElementDescriptor + Clone + 'static,
|
||||
{
|
||||
fn from(node_refs: Vec<NodeRef<R>>) -> Self {
|
||||
let node_refs = node_refs.clone();
|
||||
impl_from_multi_node_ref_inner!($ty, node_refs)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -398,6 +607,67 @@ macro_rules! impl_from_multi_node_ref {
|
|||
impl_from_multi_node_ref!(web_sys::EventTarget);
|
||||
impl_from_multi_node_ref!(web_sys::Element);
|
||||
|
||||
// From multiple leptos::html::HTMLElement /////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_from_multi_html_element {
|
||||
($ty:ty) => {
|
||||
impl<HtmlEl> From<&[HtmlElement<HtmlEl>]> for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
HtmlEl: ElementDescriptor + std::ops::Deref<Target = $ty>,
|
||||
{
|
||||
fn from(value: &[HtmlElement<HtmlEl>]) -> Self {
|
||||
Self::Static(
|
||||
value
|
||||
.iter()
|
||||
.map(|el| {
|
||||
let el: &$ty = el.deref();
|
||||
Some(el.clone())
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<HtmlEl, const C: usize> From<[HtmlElement<HtmlEl>; C]>
|
||||
for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
HtmlEl: ElementDescriptor + std::ops::Deref<Target = $ty>,
|
||||
{
|
||||
fn from(value: [HtmlElement<HtmlEl>; C]) -> Self {
|
||||
Self::Static(
|
||||
value
|
||||
.iter()
|
||||
.map(|el| {
|
||||
let el: &$ty = el.deref();
|
||||
Some(el.clone())
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<HtmlEl> From<Vec<HtmlElement<HtmlEl>>> for ElementsMaybeSignal<$ty, $ty>
|
||||
where
|
||||
HtmlEl: ElementDescriptor + std::ops::Deref<Target = $ty>,
|
||||
{
|
||||
fn from(value: Vec<HtmlElement<HtmlEl>>) -> Self {
|
||||
Self::Static(
|
||||
value
|
||||
.iter()
|
||||
.map(|el| {
|
||||
let el: &$ty = el.deref();
|
||||
Some(el.clone())
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_multi_html_element!(web_sys::EventTarget);
|
||||
impl_from_multi_html_element!(web_sys::Element);
|
||||
|
||||
// From ElementMaybeSignal //////////////////////////////////////////////////////////////
|
||||
|
||||
impl<T, E> From<ElementMaybeSignal<T, E>> for ElementsMaybeSignal<T, E>
|
||||
|
|
|
@ -27,7 +27,6 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
|||
///
|
||||
/// ```
|
||||
/// # use leptos::*;
|
||||
/// # use leptos::ev::resize;
|
||||
/// # use leptos::logging::log;
|
||||
/// # use leptos::html::Div;
|
||||
/// # use leptos_use::on_click_outside;
|
||||
|
@ -50,6 +49,33 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
|||
/// If you are targeting these browsers, we recommend you to include
|
||||
/// [this code snippet](https://gist.github.com/sibbng/13e83b1dd1b733317ce0130ef07d4efd) on your project.
|
||||
///
|
||||
/// ## Excluding Elements
|
||||
///
|
||||
/// Use this to ignore clicks on certain elements.
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::*;
|
||||
/// # use leptos::logging::log;
|
||||
/// # use leptos::html::Div;
|
||||
/// # use leptos_use::{on_click_outside_with_options, OnClickOutsideOptions};
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # fn Demo() -> impl IntoView {
|
||||
/// # let target = create_node_ref::<Div>();
|
||||
/// #
|
||||
/// on_click_outside_with_options(
|
||||
/// target,
|
||||
/// move |event| { log!("{:?}", event); },
|
||||
/// OnClickOutsideOptions::default().ignore(["input", "#some-id"]),
|
||||
/// );
|
||||
/// #
|
||||
/// # view! {
|
||||
/// # <div node_ref=target>"Hello World"</div>
|
||||
/// # }
|
||||
/// # }
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// ## Server-Side Rendering
|
||||
///
|
||||
/// On the server this amounts to a no-op.
|
||||
|
@ -230,12 +256,13 @@ where
|
|||
|
||||
/// Options for [`on_click_outside_with_options`].
|
||||
#[derive(Clone, DefaultBuilder)]
|
||||
#[cfg_attr(feature = "ssr", allow(dead_code))]
|
||||
pub struct OnClickOutsideOptions<T>
|
||||
where
|
||||
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||
{
|
||||
/// List of elementss that should not trigger the callback. Defaults to `[]`.
|
||||
#[cfg_attr(feature = "ssr", allow(dead_code))]
|
||||
#[builder(skip)]
|
||||
ignore: ElementsMaybeSignal<T, web_sys::EventTarget>,
|
||||
|
||||
/// Use capturing phase for internal event listener. Defaults to `true`.
|
||||
|
@ -257,3 +284,17 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OnClickOutsideOptions<T>
|
||||
where
|
||||
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||
{
|
||||
/// List of elementss that should not trigger the callback. Defaults to `[]`.
|
||||
#[cfg_attr(feature = "ssr", allow(dead_code))]
|
||||
pub fn ignore(self, ignore: impl Into<ElementsMaybeSignal<T, web_sys::EventTarget>>) -> Self {
|
||||
Self {
|
||||
ignore: ignore.into(),
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue