1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2018, the Perspective Authors.
//
// This file is part of the Perspective library, distributed under the terms
// of the Apache License 2.0.  The full license can be found in the LICENSE
// file.

use crate::components::string_column_style::*;
use crate::config::*;
use crate::custom_elements::modal::*;
use crate::utils::CustomElementMetadata;
use crate::*;
use wasm_bindgen::prelude::*;
use web_sys::*;
use yew::*;

#[wasm_bindgen]
#[derive(Clone)]
pub struct PerspectiveStringColumnStyleElement {
    elem: HtmlElement,
    modal: Option<ModalElement<StringColumnStyle>>,
}

fn on_change(elem: &web_sys::HtmlElement, config: &StringColumnStyleConfig) {
    let mut event_init = web_sys::CustomEventInit::new();
    event_init.detail(&JsValue::from_serde(config).unwrap());
    let event =
        CustomEvent::new_with_event_init_dict("perspective-column-style-change", &event_init);

    elem.dispatch_event(&event.unwrap()).unwrap();
}

impl CustomElementMetadata for PerspectiveStringColumnStyleElement {
    const CUSTOM_ELEMENT_NAME: &'static str = "perspective-string-column-style";
}

#[wasm_bindgen]
impl PerspectiveStringColumnStyleElement {
    #[wasm_bindgen(constructor)]
    pub fn new(elem: web_sys::HtmlElement) -> Self {
        Self { elem, modal: None }
    }

    /// Reset to a provided JSON config, to be used in place of `new()` when
    /// re-using this component.
    ///
    /// # Arguments
    /// * `config` - a `ColumnStyle` config in JSON form.
    pub fn reset(&mut self, config: JsValue) -> Result<(), JsValue> {
        let msg = StringColumnStyleMsg::Reset(config.into_serde().unwrap());
        self.modal.as_ref().into_jserror()?.send_message(msg);
        Ok(())
    }

    /// Dispatches to `ModalElement::open(target)`
    ///
    /// # Arguments
    /// `target` - the relative target to pin this `ModalElement` to.
    pub fn open(
        &mut self,
        target: web_sys::HtmlElement,
        js_config: JsValue,
        js_default_config: JsValue,
    ) -> Result<(), JsValue> {
        if self.modal.is_some() {
            self.reset(js_config)?;
        } else {
            let config: StringColumnStyleConfig = js_config.into_serde().unwrap();
            let default_config: StringColumnStyleDefaultConfig =
                js_default_config.into_serde().unwrap();

            let on_change = {
                clone!(self.elem);
                Callback::from(move |x: StringColumnStyleConfig| on_change(&elem, &x))
            };

            let props = props!(StringColumnStyleProps {
                config,
                default_config,
                on_change,
            });

            self.modal = Some(ModalElement::new(self.elem.clone(), props, true));
        }

        self.modal.as_ref().into_jserror()?.open(target, None);
        Ok(())
    }

    /// Remove this `ModalElement` from the DOM.
    pub fn close(&mut self) -> Result<(), JsValue> {
        self.modal.as_ref().into_jserror()?.hide()
    }

    pub fn destroy(self) -> Result<(), JsValue> {
        self.modal.into_jserror()?.destroy()
    }

    /// DOM lifecycle method when connected.  We don't use this, as it can fire
    /// during innocuous events like re-parenting.
    pub fn connected_callback(&self) {}
}