1use crate::{icons::ICON_X, prelude::*};
2use std::sync::Arc;
3
4pub struct Chip {
6 on_close: Option<Arc<dyn Fn(&mut EventContext) + Send + Sync>>,
7 has_close: Signal<bool>,
8}
9
10impl Chip {
11 pub fn new<T>(cx: &mut Context, text: impl Res<T> + Clone + 'static) -> Handle<Self>
22 where
23 T: ToStringLocalized + 'static,
24 {
25 let has_close = Signal::new(false);
26 Self { on_close: None, has_close }
27 .build(cx, move |cx| {
28 Label::new(cx, text).height(Stretch(1.0)).alignment(Alignment::Left);
29 Binding::new(cx, has_close, move |cx| {
30 if has_close.get() {
31 let on_close = cx.data::<Chip>().on_close.clone().unwrap();
32 Button::new(cx, |cx| Svg::new(cx, ICON_X))
33 .class("close-icon")
34 .height(Pixels(16.0))
35 .width(Pixels(16.0))
36 .alignment(Alignment::Center)
37 .on_press(move |cx| (on_close)(cx));
38 }
39 });
40 })
41 .toggle_class("close", has_close)
42 .layout_type(LayoutType::Row)
43 }
44}
45
46impl View for Chip {
47 fn element(&self) -> Option<&'static str> {
48 Some("chip")
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum ChipVariant {
55 Filled,
57 Outline,
59}
60
61impl_res_simple!(ChipVariant);
62
63impl Handle<'_, Chip> {
64 pub fn on_close(self, callback: impl 'static + Fn(&mut EventContext) + Send + Sync) -> Self {
67 self.modify(|chip: &mut Chip| {
68 chip.on_close = Some(Arc::new(callback));
69 chip.has_close.set(true);
70 })
71 }
72
73 pub fn variant<U: Into<ChipVariant> + Clone + 'static>(
86 self,
87 variant: impl Res<U> + 'static,
88 ) -> Self {
89 let variant = variant.to_signal(self.cx);
90 self.bind(variant, move |handle| {
91 let variant = variant.get();
92 let variant = variant.into();
93
94 match variant {
95 ChipVariant::Filled => {
96 handle.toggle_class("outline", false);
97 }
98
99 ChipVariant::Outline => {
100 handle.toggle_class("outline", true);
101 }
102 }
103 })
104 }
105}