refactor: extract table overlay helpers

This commit is contained in:
lix-2026
2026-05-25 07:32:48 +08:00
parent 6a84d50fbc
commit 06ace3c5e6
5 changed files with 64 additions and 62 deletions
@@ -267,4 +267,4 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 2026-05-25Batch AF 未派发 Reasonix worker;基于 Batch AE Worker B 只读审计和 CodeGraph/`rg` 本地复核,主控完成 table overlay 小切片。 - 2026-05-25Batch AF 未派发 Reasonix worker;基于 Batch AE Worker B 只读审计和 CodeGraph/`rg` 本地复核,主控完成 table overlay 小切片。
- 修改:`editor_runtime/overlays.rs` 新增 `table_overlay_anchor_from_table``current_table_overlay_anchor``table_row_aux_style``table_col_aux_style``lib.rs` 删除同名实现并通过 import 继续调用。 - 修改:`editor_runtime/overlays.rs` 新增 `table_overlay_anchor_from_table``current_table_overlay_anchor``table_row_aux_style``table_col_aux_style``lib.rs` 删除同名实现并通过 import 继续调用。
- 边界:未迁 table selection signal、row/column click handler、overlay DOM view 或 `table_selection_overlay_style`;本批只外置表格 overlay anchor / aux style 的纯 DOM rect 与 CSS 计算。 - 边界:未迁 table selection signal、row/column click handler、overlay DOM view 或 `table_selection_overlay_style`;本批只外置表格 overlay anchor / aux style 的纯 DOM rect 与 CSS 计算。
- 验证待补`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``task489``task488``task479` - 验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
@@ -1284,7 +1284,7 @@ function __wbg_get_imports() {
return ret; return ret;
}, },
__wbindgen_cast_0000000000000006: function(arg0, arg1) { __wbindgen_cast_0000000000000006: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 849, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 294, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf); const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf);
return ret; return ret;
}, },
@@ -6,6 +6,7 @@ use crate::{
editor_runtime::editor_focus::active_editor_stage, editor_runtime::editor_focus::active_editor_stage,
editor_stage_element, editor_stage_element,
}; };
use web_sys::{window, Element};
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub(crate) struct FloatingToolbarAnchor { pub(crate) struct FloatingToolbarAnchor {
@@ -51,6 +52,63 @@ pub(crate) struct TableSelectionOverlayState {
pub(crate) index: usize, pub(crate) index: usize,
} }
pub(crate) fn table_overlay_anchor_from_table(table: &Element) -> Option<TableOverlayAnchor> {
let stage = editor_stage_element()?;
let table_rect = table.get_bounding_client_rect();
let stage_rect = stage.get_bounding_client_rect();
if table_rect.width() <= 0.0 || table_rect.height() <= 0.0 {
return None;
}
let rows = table.get_elements_by_tag_name("tr").length() as usize;
let cols = table
.query_selector("tr")
.ok()
.flatten()
.map(|row| row.children().length() as usize)
.unwrap_or(0);
if rows == 0 || cols == 0 {
return None;
}
Some(TableOverlayAnchor {
top: table_rect.top() - stage_rect.top(),
left: table_rect.left() - stage_rect.left(),
width: table_rect.width(),
height: table_rect.height(),
rows,
cols,
})
}
pub(crate) fn current_table_overlay_anchor() -> Option<TableOverlayAnchor> {
let table = window()
.and_then(|win| win.document())
.and_then(|document| {
document
.query_selector(".editor-surface .ProseMirror table")
.ok()
.flatten()
})?;
table_overlay_anchor_from_table(&table)
}
pub(crate) fn table_row_aux_style(anchor: &TableOverlayAnchor, index: usize) -> String {
let row_height = anchor.height / anchor.rows.max(1) as f64;
format!(
"left:-24px;top:{:.1}px;",
(row_height * index as f64) + (row_height / 2.0) - 9.0
)
}
pub(crate) fn table_col_aux_style(anchor: &TableOverlayAnchor, index: usize) -> String {
let col_width = anchor.width / anchor.cols.max(1) as f64;
format!(
"left:{:.1}px;top:-24px;",
(col_width * index as f64) + (col_width / 2.0) - 9.0
)
}
pub(crate) fn floating_toolbar_anchor_from_selection() -> Option<FloatingToolbarAnchor> { pub(crate) fn floating_toolbar_anchor_from_selection() -> Option<FloatingToolbarAnchor> {
let selection = active_editor_text_selection()?; let selection = active_editor_text_selection()?;
let range = selection.get_range_at(0).ok()?; let range = selection.get_range_at(0).ok()?;
+4 -60
View File
@@ -46,9 +46,10 @@ use editor_runtime::dom_selection::{
use editor_runtime::editor_focus::{active_editor_stage, body_has_focus, schedule_editor_focus}; use editor_runtime::editor_focus::{active_editor_stage, body_has_focus, schedule_editor_focus};
use editor_runtime::overlays::{ use editor_runtime::overlays::{
close_editor_floating_overlays_if_escape, open_block_menu_overlay, open_image_toolbar_overlay, close_editor_floating_overlays_if_escape, open_block_menu_overlay, open_image_toolbar_overlay,
open_slash_menu_overlay, sync_overlays_on_selection_change, toolbar_overlay_locked, open_slash_menu_overlay, current_table_overlay_anchor, sync_overlays_on_selection_change,
try_sync_editor_overlay_state, FloatingToolbarAnchor, ImageToolbarAnchor, TableOverlayAnchor, table_col_aux_style, table_overlay_anchor_from_table, table_row_aux_style,
TableSelectionKind, TableSelectionOverlayState, toolbar_overlay_locked, try_sync_editor_overlay_state, FloatingToolbarAnchor,
ImageToolbarAnchor, TableOverlayAnchor, TableSelectionKind, TableSelectionOverlayState,
}; };
use editor_runtime::persistence::{ use editor_runtime::persistence::{
load_persisted_document, normalize_identity_value, persist_document_state, load_persisted_document, normalize_identity_value, persist_document_state,
@@ -4902,63 +4903,6 @@ fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
}) })
} }
fn table_overlay_anchor_from_table(table: &Element) -> Option<TableOverlayAnchor> {
let stage = editor_stage_element()?;
let table_rect = table.get_bounding_client_rect();
let stage_rect = stage.get_bounding_client_rect();
if table_rect.width() <= 0.0 || table_rect.height() <= 0.0 {
return None;
}
let rows = table.get_elements_by_tag_name("tr").length() as usize;
let cols = table
.query_selector("tr")
.ok()
.flatten()
.map(|row| row.children().length() as usize)
.unwrap_or(0);
if rows == 0 || cols == 0 {
return None;
}
Some(TableOverlayAnchor {
top: table_rect.top() - stage_rect.top(),
left: table_rect.left() - stage_rect.left(),
width: table_rect.width(),
height: table_rect.height(),
rows,
cols,
})
}
fn current_table_overlay_anchor() -> Option<TableOverlayAnchor> {
let table = window()
.and_then(|win| win.document())
.and_then(|document| {
document
.query_selector(".editor-surface .ProseMirror table")
.ok()
.flatten()
})?;
table_overlay_anchor_from_table(&table)
}
fn table_row_aux_style(anchor: &TableOverlayAnchor, index: usize) -> String {
let row_height = anchor.height / anchor.rows.max(1) as f64;
format!(
"left:-24px;top:{:.1}px;",
(row_height * index as f64) + (row_height / 2.0) - 9.0
)
}
fn table_col_aux_style(anchor: &TableOverlayAnchor, index: usize) -> String {
let col_width = anchor.width / anchor.cols.max(1) as f64;
format!(
"left:{:.1}px;top:-24px;",
(col_width * index as f64) + (col_width / 2.0) - 9.0
)
}
fn table_selection_overlay_style( fn table_selection_overlay_style(
anchor: &TableOverlayAnchor, anchor: &TableOverlayAnchor,
selection: &TableSelectionOverlayState, selection: &TableSelectionOverlayState,