refactor: extract block menu overlay layout

This commit is contained in:
lix-2026
2026-05-25 02:50:31 +08:00
parent 630a7870e7
commit 3b8445ffab
6 changed files with 114 additions and 55 deletions
+7 -55
View File
@@ -21,6 +21,7 @@ use web_sys::{
};
use editor_runtime::attachment_upload::dispatch_editor_upload_request;
use editor_runtime::block_menu_overlay;
use editor_runtime::block_menu_legacy_html::{
duplicate_top_level_block_html, reorder_top_level_block_html,
};
@@ -47,7 +48,6 @@ use editor_runtime::persistence::persisted_document_storage_key;
const EDITOR_STAGE_SELECTOR: &str = "[data-testid=\"mnote-leptos-tiptap-editor-stage\"]";
const EDITOR_ROOT_SELECTOR: &str = ".editor-surface .ProseMirror";
const HANDLE_SHELL_SELECTOR: &str = ".block-handle-shell";
const HANDLE_MULTILINE_HEIGHT: f64 = 40.0;
const CONTENT_COLUMN_MAX_WIDTH: f64 = 708.0;
const CONTENT_COLUMN_HORIZONTAL_PADDING: f64 = 48.0;
const HANDLE_STAGE_PADDING_LEFT: f64 = 18.0;
@@ -55,7 +55,6 @@ const HANDLE_TRIGGER_WIDTH: f64 = 22.0;
const HANDLE_TRIGGER_GAP: f64 = 4.0;
const HANDLE_MENU_GAP: f64 = 0.0;
const HANDLE_TEXT_ALIGN_OFFSET: f64 = 96.0;
const HANDLE_MENU_LEFT_LIMIT: f64 = -320.0;
const RUNTIME_NAME: &str = "8123-leptos-tiptap-runtime";
const RUNTIME_VERSION: &str = "1.1.0";
const PROTOCOL: &str = "mnote.leptos_tiptap.bridge.v1";
@@ -5391,18 +5390,6 @@ fn image_element_from_target(target: web_sys::EventTarget) -> Option<Element> {
.flatten()
}
fn hover_anchor_top(block: &HoveredBlockState) -> f64 {
if block.height > HANDLE_MULTILINE_HEIGHT {
block.top + 12.0
} else {
block.top + (block.height / 2.0) - 32.0
}
}
fn hover_anchor_transform(_block: &HoveredBlockState) -> &'static str {
"none"
}
fn pointer_in_handle_corridor(client_x: i32, client_y: i32, block: &HoveredBlockState) -> bool {
let Some(stage) = editor_stage_element() else {
return false;
@@ -5445,44 +5432,6 @@ fn pointer_in_handle_corridor(client_x: i32, client_y: i32, block: &HoveredBlock
x >= corridor_left && x <= corridor_right && y >= block_top - 18.0 && y <= block_bottom + 18.0
}
fn block_menu_layout(block: &HoveredBlockState) -> Option<BlockMenuLayout> {
let stage = editor_stage_element()?;
let stage_rect = stage.get_bounding_client_rect();
let shell_top = hover_anchor_top(block);
let stage_padding = 18.0;
let space_above = (shell_top - stage_padding).max(0.0);
let space_below = (stage_rect.height() - shell_top - stage_padding).max(0.0);
let open_upward = space_below < 340.0 && space_above > space_below;
let available_height = if open_upward {
space_above
} else {
space_below
};
let max_height = if available_height >= 220.0 {
available_height
} else {
available_height.max(160.0)
};
let menu_width = 242.0;
let menu_stage_left =
(content_text_left(stage_rect.width()) - menu_width - 132.0).max(HANDLE_MENU_LEFT_LIMIT);
let viewport_shell_top = stage_rect.top() + shell_top;
let top = if open_upward {
viewport_shell_top + 64.0 - max_height
} else {
viewport_shell_top
}
.max(8.0);
let left = (stage_rect.left() + menu_stage_left).max(8.0);
Some(BlockMenuLayout {
max_height,
open_upward,
top,
left,
})
}
fn drop_indicator_from_target(
target: web_sys::EventTarget,
client_y: i32,
@@ -9714,8 +9663,8 @@ fn App(mount_options: MountOptions) -> impl IntoView {
return ().into_any();
}
let anchor_top = format!("{}px", hover_anchor_top(&block));
let anchor_transform = hover_anchor_transform(&block);
let anchor_top = format!("{}px", block_menu_overlay::hover_anchor_top(&block));
let anchor_transform = block_menu_overlay::hover_anchor_transform(&block);
let handle_left = editor_stage_element()
.map(|stage| {
let stage_rect = stage.get_bounding_client_rect();
@@ -9905,7 +9854,10 @@ fn App(mount_options: MountOptions) -> impl IntoView {
{
let current_duplicate_label = duplicate_block_label.clone();
let current_delete_label = delete_block_label.clone();
let menu_layout = block_menu_layout(&block).unwrap_or(BlockMenuLayout {
let menu_layout = editor_stage_element().and_then(|stage| {
let rect = stage.get_bounding_client_rect();
block_menu_overlay::block_menu_layout(&block, rect.width(), rect.height(), rect.top(), rect.left())
}).unwrap_or(BlockMenuLayout {
max_height: 360.0,
open_upward: false,
top: 80.0,