ftml_viewer_components/components/
inputref.rs

1use 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    //leptos::logging::log!("inputref");
30    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}