perspective_viewer/components/containers/dropdown_menu.rs
1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::marker::PhantomData;
14use std::rc::Rc;
15
16use web_sys::*;
17use yew::prelude::*;
18
19use super::select::SelectItem;
20
21#[derive(Properties, PartialEq)]
22pub struct DropDownMenuProps<T>
23where
24 T: Into<Html> + Clone + PartialEq + 'static,
25{
26 pub values: Rc<Vec<DropDownMenuItem<T>>>,
27 pub callback: Callback<T>,
28}
29
30pub struct DropDownMenu<T>
31where
32 T: Into<Html> + Clone + PartialEq + 'static,
33{
34 _props: PhantomData<T>,
35}
36
37impl<T> Component for DropDownMenu<T>
38where
39 T: Into<Html> + Clone + PartialEq + 'static,
40{
41 type Message = ();
42 type Properties = DropDownMenuProps<T>;
43
44 fn create(_ctx: &Context<Self>) -> Self {
45 Self {
46 _props: Default::default(),
47 }
48 }
49
50 fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
51 false
52 }
53
54 fn view(&self, ctx: &Context<Self>) -> Html {
55 let values = &ctx.props().values;
56 let body = if !values.is_empty() {
57 values
58 .iter()
59 .map(|value| match value {
60 DropDownMenuItem::Option(x) => {
61 let click = ctx.props().callback.reform({
62 let value = x.clone();
63 move |_: MouseEvent| value.clone()
64 });
65
66 html! {
67 <span onmousedown={click} class="selected">{ x.clone().into() }</span>
68 }
69 },
70 DropDownMenuItem::OptGroup(name, xs) => {
71 html! {
72 <>
73 <span class="dropdown-group-label">{ name.as_ref() }</span>
74 <div class="dropdown-group-container">
75 { xs.iter().map(|x| {
76 let click = ctx.props().callback.reform({
77 let value = x.clone();
78 move |_: MouseEvent| value.clone()
79 });
80 html! {
81 <span onmousedown={ click }>
82 { x.clone().into() }
83 </span>
84 }
85 }).collect::<Html>() }
86 </div>
87 </>
88 }
89 },
90 })
91 .collect::<Html>()
92 } else {
93 html! { <span class="no-results">{ "No Completions" }</span> }
94 };
95
96 html! { <>{ body }</> }
97 }
98}
99
100pub type DropDownMenuItem<T> = SelectItem<T>;