perspective_viewer/components/column_selector/
empty_column.rs1use std::collections::HashSet;
14
15use perspective_client::config::Expression;
16use web_sys::*;
17use yew::prelude::*;
18
19use crate::components::style::LocalStyle;
20use crate::css;
21use crate::custom_elements::ColumnDropDownElement;
22
23#[derive(Default)]
24pub struct EmptyColumn {
25 input_ref: NodeRef,
26}
27
28#[derive(Clone, Debug)]
29pub enum InPlaceColumn {
30 Column(String),
31 Expression(Expression<'static>),
32}
33
34#[derive(Properties)]
35pub struct EmptyColumnProps {
36 pub column_dropdown: ColumnDropDownElement,
37 pub exclude: HashSet<String>,
38 pub on_select: Callback<InPlaceColumn>,
39}
40
41impl PartialEq for EmptyColumnProps {
42 fn eq(&self, _other: &Self) -> bool {
43 false
44 }
45}
46
47pub enum EmptyColumnMsg {
48 KeyDown(u32),
49 Blur,
50 Input,
51}
52
53use EmptyColumnMsg::*;
54
55impl Component for EmptyColumn {
56 type Message = EmptyColumnMsg;
57 type Properties = EmptyColumnProps;
58
59 fn view(&self, ctx: &Context<Self>) -> Html {
60 let onblur = ctx.link().callback(|_| Blur);
61 let oninput = ctx.link().callback(|_| Input);
62 let onkeydown = ctx
63 .link()
64 .callback(|event: KeyboardEvent| KeyDown(event.key_code()));
65
66 html! {
67 <div class="pivot-column column-empty">
68 <LocalStyle href={css!("empty-column")} />
69 <input
70 spellcheck="false"
71 ref={self.input_ref.clone()}
72 {onblur}
73 {onkeydown}
74 {oninput}
75 class="column-empty-input"
76 />
77 </div>
78 }
79 }
80
81 fn changed(&mut self, _ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
82 if let Some(elem) = self.input_ref.cast::<HtmlInputElement>() {
83 elem.blur().unwrap();
84 }
85
86 false
87 }
88
89 fn destroy(&mut self, ctx: &Context<Self>) {
90 ctx.props().column_dropdown.hide().unwrap();
91 }
92
93 fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
94 match msg {
95 Blur => {
96 ctx.props().column_dropdown.hide().unwrap();
97 if let Some(elem) = self.input_ref.cast::<HtmlInputElement>() {
98 elem.set_value("");
99 }
100
101 false
102 },
103 KeyDown(40) => {
104 ctx.props().column_dropdown.item_down();
105 false
106 },
107 KeyDown(38) => {
108 ctx.props().column_dropdown.item_up();
109 false
110 },
111 KeyDown(13) => {
112 ctx.props().column_dropdown.item_select();
113 ctx.props().column_dropdown.hide().unwrap();
114 false
115 },
116 KeyDown(_) => false,
117 Input => {
118 if let Some(elem) = self.input_ref.cast::<HtmlInputElement>() {
119 ctx.props().column_dropdown.autocomplete(
120 elem,
121 ctx.props().exclude.clone(),
122 ctx.props().on_select.clone(),
123 );
124 }
125
126 false
127 },
128 }
129 }
130
131 fn create(_ctx: &Context<Self>) -> Self {
132 Self::default()
133 }
134}