From 6088447e21dc2e14eb74e9ef65ff99b2c3cb9b7b Mon Sep 17 00:00:00 2001 From: luoxiao Date: Fri, 5 Apr 2024 18:46:12 +0800 Subject: [PATCH] feat: Modal adds close_on_esc prop --- demo_markdown/docs/modal/mod.md | 1 + thaw/src/modal/mod.rs | 35 +++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/demo_markdown/docs/modal/mod.md b/demo_markdown/docs/modal/mod.md index ad9fcf6..a62b3fa 100644 --- a/demo_markdown/docs/modal/mod.md +++ b/demo_markdown/docs/modal/mod.md @@ -20,6 +20,7 @@ view! { | width | `MaybeSignal` | `600px` | Modal width. | | z_index | `MaybeSignal` | `2000` | z-index of the modal. | | mask_closeable | `MaybeSignal` | `true` | Whether to emit hide event when click mask. | +| close_on_esc | `bool` | `true` | Whether to close modal on Esc is pressed. | | children | `Children` | | Modal's content. | ### Modal Slots diff --git a/thaw/src/modal/mod.rs b/thaw/src/modal/mod.rs index 21e955d..790d8fe 100644 --- a/thaw/src/modal/mod.rs +++ b/thaw/src/modal/mod.rs @@ -1,5 +1,5 @@ use crate::{Card, CardFooter, CardHeader, CardHeaderExtra, Icon}; -use leptos::*; +use leptos::{leptos_dom::helpers::WindowListenerHandle, *}; use thaw_components::{CSSTransition, OptionComp, Teleport}; use thaw_utils::{mount_style, use_click_position, Model}; @@ -12,6 +12,7 @@ pub struct ModalFooter { pub fn Modal( #[prop(into)] show: Model, #[prop(default = true.into(), into)] mask_closeable: MaybeSignal, + #[prop(default = true, into)] close_on_esc: bool, #[prop(default = 2000.into(), into)] z_index: MaybeSignal, #[prop(default = MaybeSignal::Static("600px".to_string()), into)] width: MaybeSignal, #[prop(optional, into)] title: MaybeSignal, @@ -21,12 +22,30 @@ pub fn Modal( mount_style("modal", include_str!("./modal.css")); let displayed = RwSignal::new(show.get_untracked()); + let esc_handle = StoredValue::new(None::); Effect::new(move |prev| { - let show = show.get(); - if prev.is_some() && show { + let is_show = show.get(); + if prev.is_some() && is_show { displayed.set(true); } - show + + if close_on_esc { + if is_show && !prev.unwrap_or(false) { + let handle = window_event_listener(ev::keydown, move |e| { + if &e.code() == "Escape" { + show.set(false); + } + }); + esc_handle.set_value(Some(handle)); + } else { + esc_handle.update_value(|handle| { + if let Some(handle) = handle.take() { + handle.remove(); + } + }) + } + } + is_show }); let on_mask_click = move |_| { @@ -60,6 +79,14 @@ pub fn Modal( let _ = modal_el.attr("style", format!("transform-origin: {}px {}px", x, y)); }); + on_cleanup(move || { + esc_handle.update_value(|handle| { + if let Some(handle) = handle.take() { + handle.remove(); + } + }) + }); + view! {