refactor: extract table overlay helpers
This commit is contained in:
@@ -267,4 +267,4 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
|
||||
- 2026-05-25:Batch 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 继续调用。
|
||||
- 边界:未迁 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`。
|
||||
|
||||
+1
-1
@@ -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: 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);
|
||||
return ret;
|
||||
},
|
||||
|
||||
BIN
Binary file not shown.
@@ -6,6 +6,7 @@ use crate::{
|
||||
editor_runtime::editor_focus::active_editor_stage,
|
||||
editor_stage_element,
|
||||
};
|
||||
use web_sys::{window, Element};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) struct FloatingToolbarAnchor {
|
||||
@@ -51,6 +52,63 @@ pub(crate) struct TableSelectionOverlayState {
|
||||
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> {
|
||||
let selection = active_editor_text_selection()?;
|
||||
let range = selection.get_range_at(0).ok()?;
|
||||
|
||||
@@ -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::overlays::{
|
||||
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,
|
||||
try_sync_editor_overlay_state, FloatingToolbarAnchor, ImageToolbarAnchor, TableOverlayAnchor,
|
||||
TableSelectionKind, TableSelectionOverlayState,
|
||||
open_slash_menu_overlay, current_table_overlay_anchor, sync_overlays_on_selection_change,
|
||||
table_col_aux_style, table_overlay_anchor_from_table, table_row_aux_style,
|
||||
toolbar_overlay_locked, try_sync_editor_overlay_state, FloatingToolbarAnchor,
|
||||
ImageToolbarAnchor, TableOverlayAnchor, TableSelectionKind, TableSelectionOverlayState,
|
||||
};
|
||||
use editor_runtime::persistence::{
|
||||
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(
|
||||
anchor: &TableOverlayAnchor,
|
||||
selection: &TableSelectionOverlayState,
|
||||
|
||||
Reference in New Issue
Block a user