Skip to content

Commit

Permalink
Add MaybeCallback (#15)
Browse files Browse the repository at this point in the history
* feat(maybe-callback): convenience for leptos 0.7

* docs(cargo): add description

* docs(readme): repository url

* Cleanup

---------

Co-authored-by: geoffreygarrett <[email protected]>
Co-authored-by: Daniëlle Huisman <[email protected]>
  • Loading branch information
3 people authored Feb 10, 2025
1 parent f09042d commit cf016f1
Show file tree
Hide file tree
Showing 10 changed files with 618 additions and 3 deletions.
12 changes: 10 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ version = "0.0.3"

[workspace.dependencies]
leptos = "0.7.0"
log = "0.4.25"
15 changes: 15 additions & 0 deletions packages/leptos-maybe-callback/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "leptos-maybe-callback"
description = "Optional callbacks for Leptos."

authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
version.workspace = true

[dependencies]
leptos.workspace = true

[dev-dependencies]
log.workspace = true
104 changes: 104 additions & 0 deletions packages/leptos-maybe-callback/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Leptos Maybe Callback

Optional callbacks for [Leptos](https://leptos.dev/).

## Documentation

Documentation for the crate is available on [Docs.rs](https://docs.rs/):

- [`leptos-node-ref`](https://docs.rs/leptos-maybe-callback/latest/leptos_maybe_callback/)

## Example

### Component with Optional Callback Prop

Define a component that accepts an optional callback using `#[prop(into, optional)]`. This allows passing a closure, a
`Callback`, or omitting the prop.

```rust
use leptos::{ev::MouseEvent, prelude::*};
use leptos_maybe_callback::MaybeCallback;

/// A button component with an optional `onclick` callback.
#[component]
pub fn Button(
#[prop(into, optional)]
onclick: MaybeCallback<MouseEvent>,
) -> impl IntoView {
view! {
<button on:click=onclick.into_handler()>
"Click me"
</button>
}
}
```

### Using the Component with a Closure

Use the `Button` component and provide a closure for the `onclick` prop.

```rust
use leptos::prelude::*;
use leptos_maybe_callback::MaybeCallback;

/// Parent component using `Button` with a closure.
#[component]
pub fn ButtonWithClosure() -> impl IntoView {
view! {
<div>
<Button onclick=|_| log::info!("Clicked via closure!") />
<Button />
</div>
}
}
```

### Using the Component with a `Callback`

Alternatively, pass a `Callback` as the `onclick` prop.

```rust
use leptos::{ev::MouseEvent, prelude::*};
use leptos_maybe_callback::MaybeCallback;

/// Parent component using `Button` with a `Callback`.
#[component]
pub fn ButtonWithCallback() -> impl IntoView {
let on_click = Callback::new(|event: MouseEvent| {
log::info!("Clicked with event: {:?}", event);
});

view! {
<div>
<Button onclick=on_click />
<Button />
</div>
}
}
```

### Omitting the Callback

If no callback is needed, omit the `onclick` prop or pass `None`.

```rust
use leptos::{ev::MouseEvent, prelude::*};
use leptos_maybe_callback::MaybeCallback;

/// Parent component using `Button` without a callback.
#[component]
pub fn ButtonWithoutCallback() -> impl IntoView {
view! {
<div>
<Button />
<Button onclick={None::<Callback<MouseEvent>>} />
</div>
}
}
```

## Rust For Web

The Leptos Maybe Callback project is part of [Rust For Web](https://github.com/RustForWeb).

[Rust For Web](https://github.com/RustForWeb) creates and ports web UI libraries for Rust. All projects are free and open source.
131 changes: 131 additions & 0 deletions packages/leptos-maybe-callback/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//! Optional callbacks for [Leptos](https://leptos.dev/).
//!
//! # Example
//!
//! ## Component with Optional Callback Prop
//!
//! Define a component that accepts an optional callback using `#[prop(into, optional)]`. This allows passing a closure, a
//! `Callback`, or omitting the prop.
//!
//! ```
//! use leptos::{ev::MouseEvent, prelude::*};
//! use leptos_maybe_callback::MaybeCallback;
//!
//! /// A button component with an optional `onclick` callback.
//! #[component]
//! pub fn Button(
//! #[prop(into, optional)]
//! onclick: MaybeCallback<MouseEvent>,
//! ) -> impl IntoView {
//! view! {
//! <button on:click=onclick.into_handler()>
//! "Click me"
//! </button>
//! }
//! }
//! ```
//!
//! ## Using the Component with a Closure
//!
//! Use the `Button` component and provide a closure for the `onclick` prop.
//!
//! ```
//! # use leptos::ev::MouseEvent;
//! use leptos::prelude::*;
//! use leptos_maybe_callback::MaybeCallback;
//!
//! # #[component]
//! # pub fn Button(
//! # #[prop(into, optional)]
//! # onclick: MaybeCallback<MouseEvent>,
//! # ) -> impl IntoView {
//! # view! {
//! # <button on:click=onclick.into_handler()>
//! # "Click me"
//! # </button>
//! # }
//! # }
//! #
//! /// Parent component using `Button` with a closure.
//! #[component]
//! pub fn ButtonWithClosure() -> impl IntoView {
//! view! {
//! <div>
//! <Button onclick=|_| log::info!("Clicked via closure!") />
//! <Button />
//! </div>
//! }
//! }
//! ```
//!
//! ## Using the Component with a `Callback`
//!
//! Alternatively, pass a `Callback` as the `onclick` prop.
//!
//! ```rust
//! use leptos::{ev::MouseEvent, prelude::*};
//! use leptos_maybe_callback::MaybeCallback;
//!
//! # #[component]
//! # pub fn Button(
//! # #[prop(into, optional)]
//! # onclick: MaybeCallback<MouseEvent>,
//! # ) -> impl IntoView {
//! # view! {
//! # <button on:click=onclick.into_handler()>
//! # "Click me"
//! # </button>
//! # }
//! # }
//! #
//! /// Parent component using `Button` with a `Callback`.
//! #[component]
//! pub fn ButtonWithCallback() -> impl IntoView {
//! let on_click = Callback::new(|event: MouseEvent| {
//! log::info!("Clicked with event: {:?}", event);
//! });
//!
//! view! {
//! <div>
//! <Button onclick=on_click />
//! <Button />
//! </div>
//! }
//! }
//! ```
//!
//! ## Omitting the Callback
//!
//! If no callback is needed, omit the `onclick` prop or pass `None`.
//!
//! ```rust
//! use leptos::{ev::MouseEvent, prelude::*};
//! use leptos_maybe_callback::MaybeCallback;
//!
//! # #[component]
//! # pub fn Button(
//! # #[prop(into, optional)]
//! # onclick: MaybeCallback<MouseEvent>,
//! # ) -> impl IntoView {
//! # view! {
//! # <button on:click=onclick.into_handler()>
//! # "Click me"
//! # </button>
//! # }
//! # }
//! #
//! /// Parent component using `Button` without a callback.
//! #[component]
//! pub fn ButtonWithoutCallback() -> impl IntoView {
//! view! {
//! <div>
//! <Button />
//! <Button onclick={None::<Callback<MouseEvent>>} />
//! </div>
//! }
//! }
//! ```
mod maybe_callback;

pub use maybe_callback::*;
Loading

0 comments on commit cf016f1

Please sign in to comment.