ftml_viewer_components/components/
inputref.rs1use flams_ontology::{
2 narration::sections::SectionLevel,
3 uris::{DocumentURI, NarrativeURI},
4};
5use flams_web_utils::{do_css, inject_css};
6use leptos::{context::Provider, either::Either, prelude::*};
7use leptos_posthoc::{DomChildrenCont, OriginalNode};
8
9use crate::{
10 components::{
11 counters::{LogicalLevel, SectionCounters},
12 navigation::{NavElems, SectionOrInputref},
13 },
14 config::IdPrefix,
15 extractor::DOMExtractor,
16};
17
18#[derive(Copy, Clone)]
19pub struct InInputRef(pub bool);
20
21#[component]
22pub fn InputRef<'a>(uri: DocumentURI, id: &'a str) -> impl IntoView {
23 inputref(uri, id)
24}
25
26#[allow(clippy::similar_names)]
27pub(super) fn inputref(uri: DocumentURI, id: &str) -> impl IntoView {
28 use leptos_posthoc::DomStringCont;
29 inject_css("ftml-inputref", include_str!("./inputref.css"));
31 let replace = RwSignal::new(false);
32 let replaced = RwSignal::new(false);
33 let on_click = move |_| {
34 replace.set(true);
35 };
36 let id = expect_context::<IdPrefix>().new_id(id);
37 let title = NavElems::update_untracked(|ne| {
38 ne.ids
39 .insert(id.clone(), SectionOrInputref::Inputref(replace, replaced));
40 ne.get_title(uri.clone())
41 });
42 let ctrs = SectionCounters::inputref(uri.clone(), id.to_string());
43 match ctrs.current_level() {
44 LogicalLevel::Section(lvl) if lvl < SectionLevel::Section => (),
45 _ => replace.set(true),
46 }
47 if !replace.get_untracked() {
48 let uri = uri.clone();
49 let f = move || {
50 NavElems::update_untracked(|ne| {
51 if ne.initialized.get() {
52 if ne
53 .get_title(uri.clone())
54 .with_untracked(|ttl| *ttl == uri.name().to_string())
55 {
56 replace.set(true);
57 }
58 }
59 });
60 };
61 if NavElems::with_untracked(|e| !e.initialized.get_untracked()) {
62 let _ = Effect::new(f);
63 } else {
64 f();
65 }
66 }
67
68 view! {
69 <Provider value=InInputRef(true)><Provider value=IdPrefix(id.clone())><Provider value=ctrs> {
70 move || if replace.get() { Either::Left(do_inputref(uri.clone(),replaced)) } else {
71 Either::Right(view!(<div id=id.clone() on:click=on_click class="ftml-inputref">{
72 move || {
73 let title = title.get();
74 if title.is_empty() { None } else {
75 Some(view!(<DomStringCont html=title cont=crate::iterate/>))
76 }
77 }
78 }</div>))
79 }}</Provider></Provider></Provider>
80 }
81}
82
83fn do_inputref(uri: DocumentURI, on_load: RwSignal<bool>) -> impl IntoView {
84 use flams_web_utils::components::wait_local;
85 use leptos_posthoc::DomStringCont;
86 let uricl = uri.clone();
87 wait_local(
88 move || {
89 let uri = uri.clone();
90 async move { crate::remote::server_config.inputref(uri).await.ok() }
91 },
92 move |(_, css, html)| {
93 for c in css {
94 do_css(c);
95 }
96 view!(<span style="display:contents">
97 <Provider value=NarrativeURI::Document(uricl.clone())>
98 <Provider value = RwSignal::new(DOMExtractor::default())>
99 <DomStringCont html cont=crate::iterate on_load/>
100 </Provider></Provider>
101 </span>)
102 },
103 "Error loading document reference".to_string(),
104 )
105}
106
107#[component]
108pub fn IfInputref<Ch: IntoView + 'static>(
109 value: bool,
110 children: TypedChildren<Ch>,
111) -> impl IntoView {
112 let children = children.into_inner();
113 let in_inputref = use_context::<InInputRef>().map(|i| i.0).unwrap_or(false);
114 if in_inputref == value {
115 Either::Left(children())
116 } else {
117 Either::Right(view! {<span data-if-inputref="false"/>})
118 }
119}
120
121pub(super) fn if_inputref(val: bool, orig: OriginalNode) -> impl IntoView {
122 let in_inputref = use_context::<InInputRef>().map(|i| i.0).unwrap_or(false);
123 if in_inputref == val {
124 Either::Left(view! {<span style="display:contents">
125 <DomChildrenCont orig cont=crate::iterate/>
126 </span>})
127 } else {
128 Either::Right(view! {<span data-if-inputref="false"/>})
129 }
130}