refactor: extract editor focus helpers

This commit is contained in:
lix-2026
2026-05-25 02:17:09 +08:00
parent b191a75e04
commit 6d0852e431
6 changed files with 59 additions and 46 deletions
@@ -1284,7 +1284,7 @@ function __wbg_get_imports() {
return ret;
},
__wbindgen_cast_0000000000000006: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 882, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 724, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf);
return ret;
},
@@ -0,0 +1,51 @@
use leptos_tiptap::TiptapEditorHandle;
use wasm_bindgen::{closure::Closure, JsCast};
use web_sys::window;
use crate::{
editor_root_element, editor_runtime::dom_selection::node_is_within_root, EDITOR_STAGE_SELECTOR,
};
pub(crate) fn schedule_editor_focus(editor: TiptapEditorHandle) {
let Some(win) = window() else {
return;
};
let callback = Closure::<dyn FnMut()>::new(move || {
let _ = editor.focus();
});
let _ = win.set_timeout_with_callback_and_timeout_and_arguments_0(
callback.as_ref().unchecked_ref(),
0,
);
callback.forget();
}
pub(crate) fn active_editor_stage() -> bool {
let active_element_inside_stage = window()
.and_then(|win| win.document())
.and_then(|document| document.active_element())
.and_then(|element| element.closest(EDITOR_STAGE_SELECTOR).ok().flatten())
.is_some();
if active_element_inside_stage {
return true;
}
let Some(root) = editor_root_element() else {
return false;
};
let Some(selection) = window().and_then(|win| win.get_selection().ok().flatten()) else {
return false;
};
let anchor_inside = selection
.anchor_node()
.map(|node| node_is_within_root(node, &root))
.unwrap_or(false);
let focus_inside = selection
.focus_node()
.map(|node| node_is_within_root(node, &root))
.unwrap_or(false);
anchor_inside || focus_inside
}
@@ -4,6 +4,7 @@ pub(crate) mod block_menu_document;
pub(crate) mod block_menu_legacy_html;
pub(crate) mod command_sync;
pub(crate) mod dom_selection;
pub(crate) mod editor_focus;
pub(crate) mod history_safe_commands;
pub(crate) mod overlays;
pub(crate) mod persistence;
+2 -45
View File
@@ -28,8 +28,9 @@ use editor_runtime::command_sync::{
read_editor_snapshot, sync_editor_outputs, sync_persisted_editor_command,
};
use editor_runtime::dom_selection::{
has_active_text_selection, node_is_within_root, selection_summary,
has_active_text_selection, selection_summary,
};
use editor_runtime::editor_focus::{active_editor_stage, schedule_editor_focus};
use editor_runtime::overlays::{
floating_toolbar_anchor_from_selection, sync_text_selection_overlay, FloatingToolbarAnchor,
};
@@ -3655,20 +3656,6 @@ fn schedule_scroll_mnote_block_anchor_from_hash_retry(remaining: u8) {
callback.forget();
}
fn schedule_editor_focus(editor: TiptapEditorHandle) {
let Some(win) = window() else {
return;
};
let callback = Closure::<dyn FnMut()>::new(move || {
let _ = editor.focus();
});
let _ = win.set_timeout_with_callback_and_timeout_and_arguments_0(
callback.as_ref().unchecked_ref(),
0,
);
callback.forget();
}
fn current_viewport_scroll() -> Option<(f64, f64)> {
let win = window()?;
let x = win.scroll_x().ok()?;
@@ -6310,36 +6297,6 @@ fn p0_extensions() -> Vec<TiptapExtension> {
]
}
fn active_editor_stage() -> bool {
let active_element_inside_stage = window()
.and_then(|win| win.document())
.and_then(|document| document.active_element())
.and_then(|element| element.closest(EDITOR_STAGE_SELECTOR).ok().flatten())
.is_some();
if active_element_inside_stage {
return true;
}
let Some(root) = editor_root_element() else {
return false;
};
let Some(selection) = window().and_then(|win| win.get_selection().ok().flatten()) else {
return false;
};
let anchor_inside = selection
.anchor_node()
.map(|node| node_is_within_root(node, &root))
.unwrap_or(false);
let focus_inside = selection
.focus_node()
.map(|node| node_is_within_root(node, &root))
.unwrap_or(false);
anchor_inside || focus_inside
}
fn current_block_info_from_index(index: Option<usize>) -> CurrentBlockInfo {
index
.map(|value| CurrentBlockInfo {