refactor: extract block state helper

This commit is contained in:
lix-2026
2026-05-25 08:12:51 +08:00
parent 10a93ac827
commit b37568bda8
5 changed files with 120 additions and 77 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: 566, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 883, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf);
return ret;
},
@@ -3,7 +3,12 @@
//! 本模块只承接拖拽命中所需的窄 helper,不处理 Leptos signal
//! 也不分发 editor command;调用方负责保留编辑器状态编排。
use crate::editor_runtime::block_hover_state::{DropIndicatorState, DropPlacement};
use crate::{
editor_runtime::block_hover_state::{
block_label_for_element, DropIndicatorState, DropPlacement, HoveredBlockState,
},
editor_root_element, editor_stage_element,
};
use web_sys::{window, Element, EventTarget};
pub(crate) struct HandleCorridorGeometry {
@@ -124,6 +129,78 @@ pub(crate) fn drop_indicator_from_block_rects(
)
}
pub(crate) fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
let root = editor_root_element()?;
let stage = editor_stage_element()?;
let block = root.children().item(index as u32)?;
let block_rect = block.get_bounding_client_rect();
let stage_rect = stage.get_bounding_client_rect();
let block_height = if block_rect.height() > 0.0 {
block_rect.height()
} else {
28.0
};
Some(HoveredBlockState {
index,
label: block_label_for_element(&block),
top: block_rect.top() - stage_rect.top(),
height: block_height,
})
}
pub(crate) fn pointer_in_handle_corridor(
client_x: i32,
client_y: i32,
block: &HoveredBlockState,
handle_selector: &str,
handle_left_fallback: f64,
handle_width: f64,
) -> bool {
let Some(stage) = editor_stage_element() else {
return false;
};
let Some(root) = editor_root_element() else {
return false;
};
let Some(block_element) = root.children().item(block.index as u32) else {
return false;
};
let stage_rect = stage.get_bounding_client_rect();
let block_rect = block_element.get_bounding_client_rect();
let handle_rect = window()
.and_then(|win| win.document())
.and_then(|document| document.query_selector(handle_selector).ok().flatten())
.map(|handle| handle.get_bounding_client_rect());
let block_left = block_rect.left() - stage_rect.left();
let block_top = block_rect.top() - stage_rect.top();
let block_bottom = block_rect.bottom() - stage_rect.top();
let handle_left = handle_rect
.as_ref()
.map(|rect| rect.left() - stage_rect.left())
.unwrap_or(handle_left_fallback);
let handle_right = handle_rect
.as_ref()
.map(|rect| rect.right() - stage_rect.left())
.unwrap_or_else(|| handle_left + handle_width);
pointer_in_handle_corridor_geometry(
client_x,
client_y,
&HandleCorridorGeometry {
stage_left: stage_rect.left(),
stage_top: stage_rect.top(),
block_left,
block_top,
block_bottom,
handle_left,
handle_right,
},
)
}
pub(crate) fn top_level_block_index(root: &Element, block: &Element) -> Option<usize> {
let children = root.children();
(0..children.length()).find_map(|index| {
+29 -74
View File
@@ -22,9 +22,9 @@ use web_sys::{
use editor_runtime::attachment_upload::dispatch_editor_upload_request;
use editor_runtime::block_dnd::{
direct_block_from_element, direct_block_index_from_element,
drop_indicator_from_block_rects, element_within_handle_shell, event_target_from_point,
pointer_in_handle_corridor_geometry, top_level_block_index, HandleCorridorGeometry,
block_state_from_index as block_state_from_index_runtime, direct_block_from_element,
direct_block_index_from_element, drop_indicator_from_block_rects, element_within_handle_shell,
event_target_from_point, top_level_block_index,
};
use editor_runtime::block_menu_overlay;
use editor_runtime::block_menu_document::{
@@ -34,8 +34,7 @@ use editor_runtime::block_menu_legacy_html::{
duplicate_top_level_block_html, reorder_top_level_block_html,
};
use editor_runtime::block_hover_state::{
block_label_for_element, BlockMenuLayout, DropIndicatorState, HoveredBlockState,
PendingDragState,
BlockMenuLayout, DropIndicatorState, HoveredBlockState, PendingDragState,
};
use editor_runtime::command_sync::{
read_editor_snapshot, sync_editor_outputs, sync_persisted_editor_command,
@@ -4867,23 +4866,7 @@ fn hovered_block_from_selection() -> Option<HoveredBlockState> {
}
fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
let root = editor_root_element()?;
let stage = editor_stage_element()?;
let block = root.children().item(index as u32)?;
let block_rect = block.get_bounding_client_rect();
let stage_rect = stage.get_bounding_client_rect();
let block_height = if block_rect.height() > 0.0 {
block_rect.height()
} else {
28.0
};
Some(HoveredBlockState {
index,
label: block_label_for_element(&block),
top: block_rect.top() - stage_rect.top(),
height: block_height,
})
block_state_from_index_runtime(index)
}
fn prosemirror_node_size(node: &Value) -> Option<u32> {
@@ -5046,56 +5029,6 @@ fn image_element_from_target(target: web_sys::EventTarget) -> Option<Element> {
.flatten()
}
fn pointer_in_handle_corridor(client_x: i32, client_y: i32, block: &HoveredBlockState) -> bool {
let Some(stage) = editor_stage_element() else {
return false;
};
let Some(root) = editor_root_element() else {
return false;
};
let Some(block_element) = root.children().item(block.index as u32) else {
return false;
};
let stage_rect = stage.get_bounding_client_rect();
let block_rect = block_element.get_bounding_client_rect();
let handle_rect = window()
.and_then(|win| win.document())
.and_then(|document| {
document
.query_selector(HANDLE_SHELL_SELECTOR)
.ok()
.flatten()
})
.map(|handle| handle.get_bounding_client_rect());
let block_left = block_rect.left() - stage_rect.left();
let block_top = block_rect.top() - stage_rect.top();
let block_bottom = block_rect.bottom() - stage_rect.top();
let handle_left = handle_rect
.as_ref()
.map(|rect| rect.left() - stage_rect.left())
.unwrap_or_else(|| handle_lane_left(stage_rect.width()));
let handle_right = handle_rect
.as_ref()
.map(|rect| rect.right() - stage_rect.left())
.unwrap_or_else(|| handle_left + HANDLE_TRIGGER_WIDTH);
pointer_in_handle_corridor_geometry(
client_x,
client_y,
&HandleCorridorGeometry {
stage_left: stage_rect.left(),
stage_top: stage_rect.top(),
block_left,
block_top,
block_bottom,
handle_left,
handle_right,
},
)
}
fn drop_indicator_from_target(
target: web_sys::EventTarget,
client_y: i32,
@@ -7794,7 +7727,18 @@ fn App(mount_options: MountOptions) -> impl IntoView {
}
if let Some(current_block) = hovered_block.get_untracked() {
if pointer_in_handle_corridor(event.client_x(), event.client_y(), &current_block) {
if editor_runtime::block_dnd::pointer_in_handle_corridor(
event.client_x(),
event.client_y(),
&current_block,
HANDLE_SHELL_SELECTOR,
handle_lane_left(
editor_stage_element()
.map(|stage| stage.get_bounding_client_rect().width())
.unwrap_or(0.0),
),
HANDLE_TRIGGER_WIDTH,
) {
return;
}
}
@@ -7818,7 +7762,18 @@ fn App(mount_options: MountOptions) -> impl IntoView {
return;
}
if let Some(current_block) = hovered_block.get_untracked() {
if pointer_in_handle_corridor(event.client_x(), event.client_y(), &current_block) {
if editor_runtime::block_dnd::pointer_in_handle_corridor(
event.client_x(),
event.client_y(),
&current_block,
HANDLE_SHELL_SELECTOR,
handle_lane_left(
editor_stage_element()
.map(|stage| stage.get_bounding_client_rect().width())
.unwrap_or(0.0),
),
HANDLE_TRIGGER_WIDTH,
) {
return;
}
}