66 lines
2.2 KiB
Rust
66 lines
2.2 KiB
Rust
|
|
use reactive_stores::Field;
|
|||
|
|
|
|||
|
|
use crate::prelude::*;
|
|||
|
|
use leptos::prelude::*;
|
|||
|
|
|
|||
|
|
/// The three attunement slots: each is either empty (free-text input and
|
|||
|
|
/// "+" button) or holds an item name with a "×" clear button.
|
|||
|
|
#[component]
|
|||
|
|
pub fn Attunements () -> impl IntoView {
|
|||
|
|
let state = expect_context::<Context>();
|
|||
|
|
let attunements: Field<Attunements> = state.player().attunements().into();
|
|||
|
|
|
|||
|
|
view! {
|
|||
|
|
<div class="attunements">
|
|||
|
|
<h6>"attunements/слоты привязки:"</h6>
|
|||
|
|
<For
|
|||
|
|
// Same state-in-key convention as prepared spells, so a
|
|||
|
|
// slot whose value changed re-renders.
|
|||
|
|
each=move || attunements.get().0.into_iter().enumerate()
|
|||
|
|
key=|(i, s)| format!("{}-{}", i, s.as_deref().unwrap_or(""))
|
|||
|
|
let((idx, slot))
|
|||
|
|
>
|
|||
|
|
{slot_row(attunements, idx, slot)}
|
|||
|
|
</For>
|
|||
|
|
</div>
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// One attunement slot: the free-text entry (empty) or the item itself.
|
|||
|
|
/// A plain function: component tags are not allowed directly inside
|
|||
|
|
/// `For`'s `let(...)` children.
|
|||
|
|
fn slot_row (
|
|||
|
|
attunements: Field<Attunements>,
|
|||
|
|
idx: usize,
|
|||
|
|
slot: Option<String>,
|
|||
|
|
) -> impl IntoView {
|
|||
|
|
let text_sig = RwSignal::new(String::new());
|
|||
|
|
|
|||
|
|
// Binds the typed item name; empty text is ignored.
|
|||
|
|
let bind = move |_| {
|
|||
|
|
let text = text_sig.get_untracked();
|
|||
|
|
if text.trim().is_empty() {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
attunements.update(|a| a.0[idx] = Some(text.trim().to_string()));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let clear = move |_| attunements.update(|a| a.0[idx] = None);
|
|||
|
|
|
|||
|
|
view! {
|
|||
|
|
<div class="attunement-slot">
|
|||
|
|
{if slot.is_some() {
|
|||
|
|
view! {
|
|||
|
|
<div class="attuned-item">{slot.clone().unwrap_or_default()}</div>
|
|||
|
|
<button title="Снять привязку" on:click=clear>"×"</button>
|
|||
|
|
}.into_any()
|
|||
|
|
} else {
|
|||
|
|
view! {
|
|||
|
|
<input type="text" placeholder="Предмет…" bind:value=text_sig />
|
|||
|
|
<button title="Привязать предмет" on:click=bind>"+"</button>
|
|||
|
|
}.into_any()
|
|||
|
|
}}
|
|||
|
|
</div>
|
|||
|
|
}
|
|||
|
|
}
|