1use std::marker::PhantomData;
2
3use crate::prelude::*;
4use crate::{Avatar, Player};
5
6#[derive(Element)]
7pub struct Facepile<S: 'static + Send + Sync> {
8 state_type: PhantomData<S>,
9 players: Vec<Player>,
10}
11
12impl<S: 'static + Send + Sync> Facepile<S> {
13 pub fn new<P: Iterator<Item = Player>>(players: P) -> Self {
14 Self {
15 state_type: PhantomData,
16 players: players.collect(),
17 }
18 }
19
20 fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
21 let player_count = self.players.len();
22 let player_list = self.players.iter().enumerate().map(|(ix, player)| {
23 let isnt_last = ix < player_count - 1;
24
25 div()
26 .when(isnt_last, |div| div.neg_mr_1())
27 .child(Avatar::new(player.avatar_src().to_string()))
28 });
29 div().p_1().flex().items_center().children(player_list)
30 }
31}
32
33#[cfg(feature = "stories")]
34pub use stories::*;
35
36#[cfg(feature = "stories")]
37mod stories {
38 use crate::{static_players, Story};
39
40 use super::*;
41
42 #[derive(Element)]
43 pub struct FacepileStory<S: 'static + Send + Sync> {
44 state_type: PhantomData<S>,
45 }
46
47 impl<S: 'static + Send + Sync> FacepileStory<S> {
48 pub fn new() -> Self {
49 Self {
50 state_type: PhantomData,
51 }
52 }
53
54 fn render(
55 &mut self,
56 _view: &mut S,
57 cx: &mut ViewContext<S>,
58 ) -> impl Element<ViewState = S> {
59 let players = static_players();
60
61 Story::container(cx)
62 .child(Story::title_for::<_, Facepile<S>>(cx))
63 .child(Story::label(cx, "Default"))
64 .child(
65 div()
66 .flex()
67 .gap_3()
68 .child(Facepile::new(players.clone().into_iter().take(1)))
69 .child(Facepile::new(players.clone().into_iter().take(2)))
70 .child(Facepile::new(players.clone().into_iter().take(3))),
71 )
72 }
73 }
74}