diff --git a/crates/apps/gioser-web/pkg/gioser_web.d.ts b/crates/apps/gioser-web/pkg/gioser_web.d.ts index d5a7121..d37c8a2 100644 --- a/crates/apps/gioser-web/pkg/gioser_web.d.ts +++ b/crates/apps/gioser-web/pkg/gioser_web.d.ts @@ -8,12 +8,12 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl export interface InitOutput { readonly memory: WebAssembly.Memory; readonly boot: () => void; + readonly __wasm_bindgen_func_elem_219: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_1408: (a: number, b: number, c: number, d: number) => void; readonly __wasm_bindgen_func_elem_218: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_1398: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_217: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_217_3: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_494: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_593: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_218_3: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_496: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_602: (a: number, b: number, c: number) => void; readonly __wasm_bindgen_func_elem_289: (a: number, b: number, c: number) => void; readonly __wasm_bindgen_func_elem_288: (a: number, b: number) => void; readonly __wbindgen_export: (a: number, b: number) => number; diff --git a/crates/apps/gioser-web/pkg/gioser_web.js b/crates/apps/gioser-web/pkg/gioser_web.js index 5a39956..df3c8bd 100644 --- a/crates/apps/gioser-web/pkg/gioser_web.js +++ b/crates/apps/gioser-web/pkg/gioser_web.js @@ -297,6 +297,16 @@ function __wbg_get_imports() { const ret = result; return ret; }, + __wbg_instanceof_SvgCircleElement_b8f3b45ab1053e3e: function(arg0) { + let result; + try { + result = getObject(arg0) instanceof SVGCircleElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }, __wbg_instanceof_SvgElement_46537942d3e1376d: function(arg0) { let result; try { @@ -560,33 +570,33 @@ function __wbg_get_imports() { return ret; }, __wbindgen_cast_0000000000000001: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 176, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1398); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 179, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1408); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [F64], shim_idx: 2, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_218); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_219); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 6, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_217); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_218); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 6, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_217_3); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_218_3); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 137, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_494); + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_496); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 170, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_593); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 173, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_602); return addHeapObject(ret); }, __wbindgen_cast_0000000000000007: function(arg0, arg1) { @@ -627,30 +637,30 @@ function __wasm_bindgen_func_elem_288(arg0, arg1) { wasm.__wasm_bindgen_func_elem_288(arg0, arg1); } -function __wasm_bindgen_func_elem_217(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_217(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_218(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_218(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_217_3(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_217_3(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_218_3(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_218_3(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_494(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_494(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_496(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_496(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_593(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_593(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_602(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_602(arg0, arg1, addHeapObject(arg2)); } function __wasm_bindgen_func_elem_289(arg0, arg1, arg2) { wasm.__wasm_bindgen_func_elem_289(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_1398(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_1408(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_1398(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_1408(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -661,8 +671,8 @@ function __wasm_bindgen_func_elem_1398(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_218(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_218(arg0, arg1, arg2); +function __wasm_bindgen_func_elem_219(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_219(arg0, arg1, arg2); } function addHeapObject(obj) { diff --git a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm index 49ad85b..310d68e 100644 Binary files a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm and b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm differ diff --git a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts index af910e6..ea09953 100644 --- a/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts +++ b/crates/apps/gioser-web/pkg/gioser_web_bg.wasm.d.ts @@ -2,12 +2,12 @@ /* eslint-disable */ export const memory: WebAssembly.Memory; export const boot: () => void; +export const __wasm_bindgen_func_elem_219: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_1408: (a: number, b: number, c: number, d: number) => void; export const __wasm_bindgen_func_elem_218: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_1398: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_217: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_217_3: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_494: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_593: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_218_3: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_496: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_602: (a: number, b: number, c: number) => void; export const __wasm_bindgen_func_elem_289: (a: number, b: number, c: number) => void; export const __wasm_bindgen_func_elem_288: (a: number, b: number) => void; export const __wbindgen_export: (a: number, b: number) => number; diff --git a/crates/modules/gioser/gioser-graph-web/src/lib.rs b/crates/modules/gioser/gioser-graph-web/src/lib.rs index b089b4d..aad4d8c 100644 --- a/crates/modules/gioser/gioser-graph-web/src/lib.rs +++ b/crates/modules/gioser/gioser-graph-web/src/lib.rs @@ -1,16 +1,11 @@ //! `gioser-graph-web` — widget de grafo semántico SVG inline. //! -//! Fetchea `GET /graph` de la API de gioser, parsea nodos + aristas, -//! y renderiza un grafo SVG interactivo dentro de un contenedor dado. -//! -//! Los nodos son **rectángulos redondeados** horizontales con el texto -//! dentro (no círculos) para mejor legibilidad. Las aristas varían en -//! grosor según la intensidad semántica (k-NN weight). -//! -//! ## Contrato DOM -//! -//! El caller pasa un `
` contenedor y un callback `on_navigate(doc_id)`. -//! El widget monta un `` dentro con viewBox fijo. +//! Layout grid: 3 columnas, filas según la cantidad de nodos. +//! Los nodos son rectángulos redondeados con texto + subtexto (camino). +//! Aristas se dibujan entre todos los pares con líneas semitransparentes: +//! mientras mayor el weight, más opaca y brillante la línea. +//! Animación CSS de respiración suave en el SVG. +//! Hover: glow + opacidad. use std::cell::RefCell; use std::rc::Rc; @@ -21,7 +16,7 @@ use wasm_bindgen::JsCast; use wasm_bindgen_futures::JsFuture; use web_sys::{ Document, HtmlElement, MouseEvent, Response, SvgLineElement, SvgRectElement, - SvgsvgElement, SvgTextElement, + SvgsvgElement, SvgTextElement, SvgCircleElement, }; pub(crate) fn document() -> Option { @@ -79,37 +74,49 @@ struct GraphStats { type NavCallback = Rc>>>; -const CANVAS_W: f64 = 600.0; -const CANVAS_H: f64 = 270.0; -/// Ancho del rectángulo nodo (horizontal para texto largo). -const NODE_W: f64 = 120.0; -/// Alto del rectángulo nodo. -const NODE_H: f64 = 28.0; +const CANVAS_W: f64 = 800.0; +const CANVAS_H: f64 = 420.0; +const NODE_W: f64 = 170.0; // más grandes +const NODE_H: f64 = 44.0; // más grandes +const COLS: usize = 3; const CAMINO_COLORS: &[(&str, &str)] = &[ - ("logos", "#d0dbff"), - ("aire", "#d0dbff"), - ("nomos", "#f59056"), - ("fuego", "#f59056"), - ("kay", "#d49873"), - ("tierra", "#d49873"), - ("uku", "#6cd0f3"), - ("agua", "#6cd0f3"), + ("logos", "#d0dbff"), ("aire", "#d0dbff"), + ("nomos", "#f59056"), ("fuego", "#f59056"), + ("kay", "#d49873"), ("tierra", "#d49873"), + ("uku", "#6cd0f3"), ("agua", "#6cd0f3"), ]; fn camino_color(camino: &str) -> &str { for (k, v) in CAMINO_COLORS { - if *k == camino { - return v; - } + if *k == camino { return v; } } "#888888" } +fn weight_alpha(w: Option) -> f64 { + // weight 0.5 → 0.40, weight 1.0 → 0.85 + match w { + Some(v) => 0.40 + (v - 0.5).max(0.0) * 0.9, + None => 0.35, + } + .clamp(0.15, 0.95) +} + +fn weight_stroke_color(w: Option, base: &str) -> String { + let alpha = weight_alpha(w); + // Extraer color base, añadir alpha + // Asumimos formato #rrggbb + if base.len() >= 7 && alpha < 1.0 { + format!("{}", base) // se sobreescribe con stroke-opacity + } else { + base.to_string() + } +} + pub struct GraphWidget { container: HtmlElement, api_url: String, - svg: Option, nodes: Vec, edges: Vec, on_navigate: NavCallback, @@ -130,7 +137,6 @@ impl GraphWidget { Self { container, api_url: api_url.to_string(), - svg: None, nodes: Vec::new(), edges: Vec::new(), on_navigate: Rc::new(RefCell::new(on_navigate)), @@ -164,10 +170,6 @@ impl GraphWidget { self.nodes = nodes; self.edges = edges; - // Pequeño delay para evitar "Layout was forced before fully loaded" - let _ = js_sys::Promise::resolve(&JsValue::NULL); - let mut_self = &*self as *const GraphWidget; - // Render síncrono, el delay no es necesario pero mantenemos la deferencia. self.render(); Ok(()) } @@ -179,7 +181,7 @@ impl GraphWidget { return; } - let positions = force_layout(&self.nodes, &self.edges, CANVAS_W, CANVAS_H); + let positions = grid_layout(&self.nodes, CANVAS_W, CANVAS_H); let ns = "http://www.w3.org/2000/svg"; let svg: SvgsvgElement = self @@ -188,293 +190,285 @@ impl GraphWidget { .unwrap() .dyn_into() .unwrap(); - svg.set_attribute("viewBox", &format!("0 0 {} {}", CANVAS_W as u32, CANVAS_H as u32)) - .ok(); + svg.set_attribute("viewBox", &format!("0 0 {} {}", CANVAS_W as u32, CANVAS_H as u32)).ok(); svg.set_attribute("width", "100%").ok(); svg.set_attribute("height", &format!("{}px", CANVAS_H as u32)).ok(); + svg.set_attribute("preserveAspectRatio", "xMidYMid meet").ok(); svg.style().set_property("display", "block").ok(); svg.style().set_property("margin", "1.5rem auto 0").ok(); svg.style().set_property("max-width", "100%").ok(); - svg.style() - .set_property("background", "rgba(255,255,255,0.02)") - .ok(); + svg.style().set_property("height", "auto").ok(); + svg.style().set_property("background", "rgba(255,255,255,0.02)").ok(); svg.style().set_property("border-radius", "12px").ok(); - svg.style() - .set_property("border", "1px solid rgba(216,168,93,0.15)") - .ok(); + svg.style().set_property("border", "1px solid rgba(216,168,93,0.15)").ok(); - // ── Aristas con grosor proporcional al weight ── + // Estilo para animación de respiración en el SVG + // Se añade un