perspective_viewer/custom_elements/
function_dropdown.rs1use std::cell::RefCell;
14use std::rc::Rc;
15
16use perspective_client::config::{COMPLETIONS, CompletionItemSuggestion};
17use perspective_js::utils::global;
18use wasm_bindgen::JsCast;
19use wasm_bindgen::prelude::*;
20use web_sys::*;
21use yew::html::ImplicitClone;
22use yew::*;
23
24use crate::components::function_dropdown::*;
25use crate::custom_elements::modal::*;
26use crate::*;
27
28#[wasm_bindgen]
29#[derive(Clone)]
30pub struct FunctionDropDownElement {
31 modal: ModalElement<FunctionDropDown>,
32 target: Rc<RefCell<Option<HtmlElement>>>,
33}
34
35impl PartialEq for FunctionDropDownElement {
36 fn eq(&self, _other: &Self) -> bool {
37 true
38 }
39}
40
41impl ImplicitClone for FunctionDropDownElement {}
42
43impl FunctionDropDownElement {
44 pub fn reautocomplete(&self) {
45 ApiFuture::spawn(
46 self.modal
47 .clone()
48 .open(self.target.borrow().clone().unwrap(), None),
49 );
50 }
51
52 pub fn autocomplete(
53 &self,
54 input: String,
55 target: HtmlElement,
56 callback: Callback<CompletionItemSuggestion>,
57 ) -> ApiResult<()> {
58 let values = filter_values(&input);
59 if values.is_empty() {
60 self.modal.hide()?;
61 } else {
62 self.modal.send_message_batch(vec![
63 FunctionDropDownMsg::SetCallback(callback),
64 FunctionDropDownMsg::SetValues(values),
65 ]);
66
67 ApiFuture::spawn(self.modal.clone().open(target, None));
68 }
69
70 Ok(())
71 }
72
73 pub fn item_select(&self) {
74 self.modal.send_message(FunctionDropDownMsg::ItemSelect);
75 }
76
77 pub fn item_down(&self) {
78 self.modal.send_message(FunctionDropDownMsg::ItemDown);
79 }
80
81 pub fn item_up(&self) {
82 self.modal.send_message(FunctionDropDownMsg::ItemUp);
83 }
84
85 pub fn hide(&self) -> ApiResult<()> {
86 self.modal.hide()
87 }
88
89 pub fn connected_callback(&self) {}
90}
91
92impl Default for FunctionDropDownElement {
93 fn default() -> Self {
94 let dropdown = global::document()
95 .create_element("perspective-dropdown")
96 .unwrap()
97 .unchecked_into::<HtmlElement>();
98
99 let props = props!(FunctionDropDownProps {});
100 let modal = ModalElement::new(dropdown, props, false, None);
101 Self {
102 modal,
103 target: Default::default(),
104 }
105 }
106}
107
108fn filter_values(input: &str) -> Vec<CompletionItemSuggestion> {
109 let input = input.to_lowercase();
110 COMPLETIONS
111 .iter()
112 .filter(|x| x.label.to_lowercase().starts_with(&input))
113 .cloned()
114 .collect::<Vec<_>>()
115}