refactor: extract editor dnd helpers
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
//! Block handle 拖拽命中的纯几何 helper。
|
||||
//!
|
||||
//! 本模块不查询 DOM、不处理 Leptos signal,也不分发 editor command;
|
||||
//! 调用方负责传入已经从页面中读取的坐标。
|
||||
|
||||
use crate::editor_runtime::block_hover_state::DropPlacement;
|
||||
|
||||
pub(crate) struct HandleCorridorGeometry {
|
||||
pub(crate) stage_left: f64,
|
||||
pub(crate) stage_top: f64,
|
||||
pub(crate) block_left: f64,
|
||||
pub(crate) block_top: f64,
|
||||
pub(crate) block_bottom: f64,
|
||||
pub(crate) handle_left: f64,
|
||||
pub(crate) handle_right: f64,
|
||||
}
|
||||
|
||||
pub(crate) fn pointer_in_handle_corridor_geometry(
|
||||
client_x: i32,
|
||||
client_y: i32,
|
||||
geometry: &HandleCorridorGeometry,
|
||||
) -> bool {
|
||||
let x = f64::from(client_x) - geometry.stage_left;
|
||||
let y = f64::from(client_y) - geometry.stage_top;
|
||||
let corridor_left = (geometry.handle_left - 12.0).min(geometry.block_left);
|
||||
let corridor_right = (geometry.block_left + 18.0).max(geometry.handle_right + 12.0);
|
||||
|
||||
x >= corridor_left
|
||||
&& x <= corridor_right
|
||||
&& y >= geometry.block_top - 18.0
|
||||
&& y <= geometry.block_bottom + 18.0
|
||||
}
|
||||
|
||||
pub(crate) fn drop_placement_from_block_point(
|
||||
client_y: i32,
|
||||
block_top: f64,
|
||||
block_height: f64,
|
||||
) -> DropPlacement {
|
||||
let midpoint = block_top + (block_height / 2.0);
|
||||
if f64::from(client_y) <= midpoint {
|
||||
DropPlacement::Before
|
||||
} else {
|
||||
DropPlacement::After
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_indicator_top(
|
||||
stage_top: f64,
|
||||
block_top: f64,
|
||||
block_bottom: f64,
|
||||
placement: DropPlacement,
|
||||
) -> f64 {
|
||||
match placement {
|
||||
DropPlacement::Before => block_top - stage_top,
|
||||
DropPlacement::After => block_bottom - stage_top,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pointer_corridor_accepts_handle_lane_and_block_edge() {
|
||||
let geometry = HandleCorridorGeometry {
|
||||
stage_left: 100.0,
|
||||
stage_top: 20.0,
|
||||
block_left: 140.0,
|
||||
block_top: 40.0,
|
||||
block_bottom: 80.0,
|
||||
handle_left: 108.0,
|
||||
handle_right: 130.0,
|
||||
};
|
||||
|
||||
assert!(pointer_in_handle_corridor_geometry(118, 80, &geometry));
|
||||
assert!(pointer_in_handle_corridor_geometry(250, 80, &geometry));
|
||||
assert!(!pointer_in_handle_corridor_geometry(90, 80, &geometry));
|
||||
assert!(!pointer_in_handle_corridor_geometry(118, 28, &geometry));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_placement_splits_block_at_midpoint() {
|
||||
assert_eq!(
|
||||
drop_placement_from_block_point(50, 40.0, 20.0),
|
||||
DropPlacement::Before
|
||||
);
|
||||
assert_eq!(
|
||||
drop_placement_from_block_point(51, 40.0, 20.0),
|
||||
DropPlacement::After
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub(crate) mod attachment_links;
|
||||
pub(crate) mod attachment_upload;
|
||||
pub(crate) mod block_dnd;
|
||||
pub(crate) mod block_hover_state;
|
||||
pub(crate) mod block_menu_document;
|
||||
pub(crate) mod block_menu_overlay;
|
||||
|
||||
Reference in New Issue
Block a user