gioser-web: hash routing, clickable graph nodes, hover bounce, line normalization
- Hash routing: each page sets location.hash to #/element (aire/fuego/etc) - Hash read on boot to open direct URL - hashchange listener for browser back/forward - minimize clears hash - Graph node click: dispatches click on the corresponding .tip element, triggering page open animation (expand from center) - Graph hover: CSS bounce animation (scale 1→1.08→0.96→1, 0.4s) - Edge normalization: min-max scale (w-0.80)/0.15 then squared curve for visible weight differentiation in tight cluster (0.83-0.93) - web-sys features: +Location
This commit is contained in:
+17
-17
@@ -248,20 +248,20 @@ members = [
|
||||
"crates/modules/barra/barra-web",
|
||||
|
||||
# ============================================================
|
||||
# modules/cosmobiologia/ — Estudio de astrología profesional
|
||||
# ============================================================
|
||||
"crates/modules/cosmobiologia/cosmobiologia-card",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-model",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-store",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-render",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-corpus",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-engine",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-modules",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-theme",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-canvas",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-tree",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-panel",
|
||||
"crates/modules/cosmobiologia/cosmobiologia-web",
|
||||
# # modules/cosmobiologia/ — Estudio de astrología profesional
|
||||
# # ============================================================
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-card",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-model",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-store",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-render",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-corpus",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-engine",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-modules",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-theme",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-canvas",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-tree",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-panel",
|
||||
# "crates/modules/cosmobiologia/cosmobiologia-web",
|
||||
|
||||
# ============================================================
|
||||
# apps/ — Binarios finales que consumen el protocolo
|
||||
@@ -287,9 +287,9 @@ members = [
|
||||
"crates/apps/pineal-stream-demo",
|
||||
"crates/apps/pineal-phosphor-demo",
|
||||
"crates/apps/pineal-financial-demo",
|
||||
"crates/apps/cosmobiologia",
|
||||
"crates/apps/cosmobiologia-cli",
|
||||
"crates/apps/cosmobiologia-server",
|
||||
# "crates/apps/cosmobiologia",
|
||||
# "crates/apps/cosmobiologia-cli",
|
||||
# "crates/apps/cosmobiologia-server",
|
||||
"crates/apps/dominium",
|
||||
"crates/apps/fana",
|
||||
"crates/apps/agorapura",
|
||||
|
||||
@@ -39,4 +39,5 @@ features = [
|
||||
"NodeList",
|
||||
"Performance",
|
||||
"console",
|
||||
"Location",
|
||||
]
|
||||
|
||||
+8
-8
@@ -8,14 +8,14 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly boot: () => void;
|
||||
readonly __wasm_bindgen_func_elem_216: (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_215: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_215_3: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_492: (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_285: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_284: (a: number, b: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_229: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_1437: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_228: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_228_3: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_510: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_620: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_302: (a: number, b: number, c: number) => void;
|
||||
readonly __wasm_bindgen_func_elem_303: (a: number, b: number) => void;
|
||||
readonly __wbindgen_export: (a: number, b: number) => number;
|
||||
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __wbindgen_export3: (a: number) => void;
|
||||
|
||||
@@ -152,6 +152,10 @@ function __wbg_get_imports() {
|
||||
__wbg_disable_df908054ffee7971: function(arg0, arg1) {
|
||||
getObject(arg0).disable(arg1 >>> 0);
|
||||
},
|
||||
__wbg_dispatchEvent_29c919cea8d37995: function() { return handleError(function (arg0, arg1) {
|
||||
const ret = getObject(arg0).dispatchEvent(getObject(arg1));
|
||||
return ret;
|
||||
}, arguments); },
|
||||
__wbg_document_3540635616a18455: function(arg0) {
|
||||
const ret = getObject(arg0).document;
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
@@ -224,6 +228,13 @@ function __wbg_get_imports() {
|
||||
const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3));
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
},
|
||||
__wbg_hash_db43ea0a219f3045: function() { return handleError(function (arg0, arg1) {
|
||||
const ret = getObject(arg1).hash;
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
}, arguments); },
|
||||
__wbg_height_110f80d27112b6b3: function(arg0) {
|
||||
const ret = getObject(arg0).height;
|
||||
return ret;
|
||||
@@ -399,10 +410,18 @@ function __wbg_get_imports() {
|
||||
__wbg_linkProgram_7689cb555b14a359: function(arg0, arg1) {
|
||||
getObject(arg0).linkProgram(getObject(arg1));
|
||||
},
|
||||
__wbg_location_64bcc53b4356fa39: function(arg0) {
|
||||
const ret = getObject(arg0).location;
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbg_new_02d162bc6cf02f60: function() {
|
||||
const ret = new Object();
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbg_new_972d5c0e1de33223: function() { return handleError(function (arg0, arg1) {
|
||||
const ret = new MouseEvent(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
}, arguments); },
|
||||
__wbg_ok_556a55299dd238ba: function(arg0) {
|
||||
const ret = getObject(arg0).ok;
|
||||
return ret;
|
||||
@@ -459,6 +478,9 @@ function __wbg_get_imports() {
|
||||
__wbg_setProperty_ee784b2651f9ff8d: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||
getObject(arg0).setProperty(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||
}, arguments); },
|
||||
__wbg_set_hash_62c4dbdd31cfb200: function() { return handleError(function (arg0, arg1, arg2) {
|
||||
getObject(arg0).hash = getStringFromWasm0(arg1, arg2);
|
||||
}, arguments); },
|
||||
__wbg_set_height_bdd58e6b04e88cca: function(arg0, arg1) {
|
||||
getObject(arg0).height = arg1 >>> 0;
|
||||
},
|
||||
@@ -570,43 +592,43 @@ 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: 180, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1408);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 187, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1437);
|
||||
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_216);
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_229);
|
||||
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_215);
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_228);
|
||||
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_215_3);
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_228_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_492);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 144, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_510);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_cast_0000000000000006: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 174, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_602);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MouseEvent")], shim_idx: 181, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_620);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_cast_0000000000000007: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 67, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_285);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 74, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_302);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_cast_0000000000000008: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 69, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_284);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 76, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_303);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_cast_0000000000000009: function(arg0, arg1) {
|
||||
@@ -633,34 +655,34 @@ function __wbg_get_imports() {
|
||||
};
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_284(arg0, arg1) {
|
||||
wasm.__wasm_bindgen_func_elem_284(arg0, arg1);
|
||||
function __wasm_bindgen_func_elem_303(arg0, arg1) {
|
||||
wasm.__wasm_bindgen_func_elem_303(arg0, arg1);
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_215(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_215(arg0, arg1, addHeapObject(arg2));
|
||||
function __wasm_bindgen_func_elem_228(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_228(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_215_3(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_215_3(arg0, arg1, addHeapObject(arg2));
|
||||
function __wasm_bindgen_func_elem_228_3(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_228_3(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_492(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_492(arg0, arg1, addHeapObject(arg2));
|
||||
function __wasm_bindgen_func_elem_510(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_510(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_620(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_620(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_285(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_285(arg0, arg1, addHeapObject(arg2));
|
||||
function __wasm_bindgen_func_elem_302(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_302(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_1408(arg0, arg1, arg2) {
|
||||
function __wasm_bindgen_func_elem_1437(arg0, arg1, arg2) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.__wasm_bindgen_func_elem_1408(retptr, arg0, arg1, addHeapObject(arg2));
|
||||
wasm.__wasm_bindgen_func_elem_1437(retptr, arg0, arg1, addHeapObject(arg2));
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
if (r1) {
|
||||
@@ -671,8 +693,8 @@ function __wasm_bindgen_func_elem_1408(arg0, arg1, arg2) {
|
||||
}
|
||||
}
|
||||
|
||||
function __wasm_bindgen_func_elem_216(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_216(arg0, arg1, arg2);
|
||||
function __wasm_bindgen_func_elem_229(arg0, arg1, arg2) {
|
||||
wasm.__wasm_bindgen_func_elem_229(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function addHeapObject(obj) {
|
||||
|
||||
Binary file not shown.
+8
-8
@@ -2,14 +2,14 @@
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export const boot: () => void;
|
||||
export const __wasm_bindgen_func_elem_216: (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_215: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_215_3: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_492: (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_285: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_284: (a: number, b: number) => void;
|
||||
export const __wasm_bindgen_func_elem_229: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_1437: (a: number, b: number, c: number, d: number) => void;
|
||||
export const __wasm_bindgen_func_elem_228: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_228_3: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_510: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_620: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_302: (a: number, b: number, c: number) => void;
|
||||
export const __wasm_bindgen_func_elem_303: (a: number, b: number) => void;
|
||||
export const __wbindgen_export: (a: number, b: number) => number;
|
||||
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
||||
export const __wbindgen_export3: (a: number) => void;
|
||||
|
||||
@@ -79,6 +79,10 @@ impl AppState {
|
||||
self.sync_active_class();
|
||||
self.sync_taskbar();
|
||||
self.load_md_if_empty(element, md_url);
|
||||
// Actualizar hash sin disparar evento (evitar loop)
|
||||
if let Some(win) = web_sys::window() {
|
||||
let _ = win.location().set_hash(&format!("/{}", element));
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_from_tab(&self, element: &str, origin_x: f64, origin_y: f64) {
|
||||
@@ -106,6 +110,10 @@ impl AppState {
|
||||
self.sync_active_class();
|
||||
self.sync_taskbar();
|
||||
self.hide_deck(origin_x, origin_y);
|
||||
// Limpiar hash
|
||||
if let Some(win) = web_sys::window() {
|
||||
let _ = win.location().set_hash("");
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&self, element: &str, origin_x: f64, origin_y: f64) {
|
||||
@@ -312,11 +320,31 @@ impl AppState {
|
||||
);
|
||||
wrapper.append_child(&label).ok();
|
||||
content_clone.append_child(&wrapper).ok();
|
||||
// Cargar el grafo
|
||||
// Callback: recibe 'camino' del nodo clickeado y dispara click
|
||||
// en el tip correspondiente (simula apertura de página)
|
||||
let cb: Box<dyn FnMut(String)> = Box::new(move |target| {
|
||||
// Mapa camino → elemento HTML
|
||||
let el = match target.as_str() {
|
||||
"logos" | "aire" => "logos",
|
||||
"nomos" | "fuego" => "nomos",
|
||||
"kay" | "tierra" => "kay",
|
||||
"uku" | "agua" => "uku",
|
||||
_ => "logos",
|
||||
};
|
||||
if let Some(tip) = document_clone.query_selector(
|
||||
&format!(".tip[data-md][id='tip-{}']", el)
|
||||
).ok().flatten() {
|
||||
// Simular click real en el tip — la animación de
|
||||
// expansión la maneja AppState::open_or_switch
|
||||
let _ = tip.dispatch_event(
|
||||
&web_sys::MouseEvent::new("click").unwrap()
|
||||
);
|
||||
}
|
||||
});
|
||||
let mut graph = GraphWidget::new(
|
||||
wrapper,
|
||||
"https://api.gioser.net",
|
||||
None, // callback simplificado por ahora
|
||||
Some(cb),
|
||||
);
|
||||
if let Err(e) = graph.load().await {
|
||||
web_sys::console::warn_1(&format!("grafo: error al cargar: {:?}", e).into());
|
||||
@@ -420,8 +448,48 @@ pub fn boot() -> Result<(), JsValue> {
|
||||
install_deck_delegation(&document, &app)?;
|
||||
install_taskbar(&document, &app)?;
|
||||
install_keyboard(&document, &app)?;
|
||||
install_hash_listener(&window, &app)?;
|
||||
install_raf(&window, &document, &canvas, &renderer);
|
||||
|
||||
// Leer hash inicial para abrir página directa
|
||||
if let Ok(hash) = window.location().hash() {
|
||||
let clean = hash.trim_start_matches('#').trim_start_matches('/');
|
||||
if !clean.is_empty() && clean != "" {
|
||||
if let Some(el) = document.query_selector(&format!(".tip[data-md][id='tip-{}']", clean)).ok().flatten() {
|
||||
let rect = el.get_bounding_client_rect();
|
||||
let cx = rect.left() + rect.width() / 2.0;
|
||||
let cy = rect.top() + rect.height() / 2.0;
|
||||
if let Some(md_url) = el.get_attribute("data-md") {
|
||||
app.open_or_switch(clean, cx, cy, &md_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn install_hash_listener(window: &Window, app: &Rc<AppState>) -> Result<(), JsValue> {
|
||||
let app2 = app.clone();
|
||||
let doc = app.document.clone();
|
||||
let win2 = window.clone();
|
||||
let cb = Closure::<dyn FnMut(Event)>::new(move |_e: Event| {
|
||||
if let Ok(hash) = win2.location().hash() {
|
||||
let clean = hash.trim_start_matches('#').trim_start_matches('/');
|
||||
if clean.is_empty() {
|
||||
app2.home();
|
||||
} else if let Some(el) = doc.query_selector(&format!(".tip[data-md][id='tip-{}']", clean)).ok().flatten() {
|
||||
let rect = el.get_bounding_client_rect();
|
||||
let cx = rect.left() + rect.width() / 2.0;
|
||||
let cy = rect.top() + rect.height() / 2.0;
|
||||
if let Some(md_url) = el.get_attribute("data-md") {
|
||||
app2.open_or_switch(clean, cx, cy, &md_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
window.add_event_listener_with_callback("hashchange", cb.as_ref().unchecked_ref())?;
|
||||
cb.forget();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,16 @@ impl GraphWidget {
|
||||
}\
|
||||
.gb-svg { animation: graph-breathe 5s ease-in-out infinite; }\
|
||||
.gb-node { transition: filter 250ms ease, opacity 200ms ease; }\
|
||||
.gb-node:hover { filter: drop-shadow(0 0 14px rgba(255,255,255,0.2)); }\
|
||||
.gb-node:hover {\
|
||||
filter: drop-shadow(0 0 14px rgba(255,255,255,0.2));\
|
||||
animation: node-bounce 0.4s ease-out;\
|
||||
}\
|
||||
@keyframes node-bounce {\
|
||||
0% { transform: scale(1); }\
|
||||
40% { transform: scale(1.08); }\
|
||||
70% { transform: scale(0.96); }\
|
||||
100% { transform: scale(1); }\
|
||||
}\
|
||||
.gb-edge-group { pointer-events: none; }\
|
||||
.gb-line { transition: opacity 400ms ease; }",
|
||||
));
|
||||
@@ -412,11 +421,11 @@ impl GraphWidget {
|
||||
g.add_event_listener_with_callback("mouseleave", leave.as_ref().unchecked_ref()).ok();
|
||||
leave.forget();
|
||||
|
||||
let doc_id = node.doc_id.clone().unwrap_or_default();
|
||||
let nav_target = node.camino.clone(); // pasamos el camino (logos, nomos, etc)
|
||||
let on_nav2 = on_nav.clone();
|
||||
let click = Closure::<dyn FnMut(MouseEvent)>::new(move |_| {
|
||||
let mut cb = on_nav2.borrow_mut();
|
||||
if let Some(ref mut f) = *cb { f(doc_id.clone()); }
|
||||
if let Some(ref mut f) = *cb { f(nav_target.clone()); }
|
||||
});
|
||||
g.add_event_listener_with_callback("click", click.as_ref().unchecked_ref()).ok();
|
||||
click.forget();
|
||||
|
||||
Reference in New Issue
Block a user