at main 95 lines 2.9 kB view raw
1//! DOM-based syntax visibility updates. 2//! 3//! This module applies visibility state to the DOM by toggling CSS classes 4//! on syntax span elements. Works with the core `VisibilityState` calculation. 5//! 6//! # How it works 7//! 8//! 1. Core's `VisibilityState::calculate()` determines which syntax spans should be visible 9//! 2. This module's `update_syntax_visibility()` applies that state to the DOM 10//! 3. Elements with `data-syn-id` attributes get "hidden" class toggled 11//! 12//! # CSS Integration 13//! 14//! Your CSS should hide elements with the "hidden" class: 15//! ```css 16//! [data-syn-id].hidden { 17//! opacity: 0; 18//! /* or display: none, visibility: hidden, etc. */ 19//! } 20//! ``` 21 22use weaver_editor_core::{ParagraphRender, Selection, SyntaxSpanInfo}; 23 24/// Update syntax span visibility in the DOM based on cursor position. 25/// 26/// Calculates which syntax spans should be visible using `VisibilityState::calculate()`, 27/// then toggles the "hidden" class on matching DOM elements. 28/// 29/// # Parameters 30/// - `cursor_offset`: Current cursor position in characters 31/// - `selection`: Optional text selection 32/// - `syntax_spans`: All syntax spans from rendered paragraphs 33/// - `paragraphs`: Rendered paragraph data for boundary detection 34/// 35/// # DOM Requirements 36/// Syntax span elements must have `data-syn-id` attributes matching `SyntaxSpanInfo.syn_id`. 37#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] 38pub fn update_syntax_visibility( 39 cursor_offset: usize, 40 selection: Option<&Selection>, 41 syntax_spans: &[SyntaxSpanInfo], 42 paragraphs: &[ParagraphRender], 43) { 44 use wasm_bindgen::JsCast; 45 46 let visibility = weaver_editor_core::VisibilityState::calculate( 47 cursor_offset, 48 selection, 49 syntax_spans, 50 paragraphs, 51 ); 52 53 let Some(window) = web_sys::window() else { 54 return; 55 }; 56 let Some(document) = window.document() else { 57 return; 58 }; 59 60 // Single querySelectorAll instead of N individual queries. 61 let Ok(node_list) = document.query_selector_all("[data-syn-id]") else { 62 return; 63 }; 64 65 for i in 0..node_list.length() { 66 let Some(node) = node_list.item(i) else { 67 continue; 68 }; 69 70 let Some(element) = node.dyn_ref::<web_sys::Element>() else { 71 continue; 72 }; 73 74 let Some(syn_id) = element.get_attribute("data-syn-id") else { 75 continue; 76 }; 77 78 let class_list = element.class_list(); 79 if visibility.is_visible(&syn_id) { 80 let _ = class_list.remove_1("hidden"); 81 } else { 82 let _ = class_list.add_1("hidden"); 83 } 84 } 85} 86 87/// No-op on non-WASM targets. 88#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] 89pub fn update_syntax_visibility( 90 _cursor_offset: usize, 91 _selection: Option<&Selection>, 92 _syntax_spans: &[SyntaxSpanInfo], 93 _paragraphs: &[ParagraphRender], 94) { 95}