slack_blocks/elems/
mod.rs

1//! # Block Elements - interactive components
2//! [slack api docs 🔗](https://api.slack.com/reference/block-kit/block-elements)
3//!
4//! Block elements can be used inside of `section`, `context`, and `actions` [layout blocks 🔗].
5//! Inputs can only be used inside of `input` blocks.
6//!
7//! Our overview of [app surfaces that support Block Kit 🔗] shows you where those blocks might be relevant.
8//!
9//! Finally, our [handling user interactivity guide 🔗] will help you prepare your app to allow
10//! for the use of the interactive components listed below.
11//!
12//! [app surfaces that support Block Kit 🔗]: https://api.slack.com/messaging/composing/layouts
13//! [handling user interactivity guide 🔗]: https://api.slack.com/interactivity/handling
14//! [layout blocks 🔗]: https://api.slack.com/reference/block-kit/blocks
15
16use serde::{Deserialize, Serialize};
17
18use crate::convert;
19#[cfg(feature = "validation")]
20use crate::val_helpr::ValidationResult;
21
22pub mod button;
23pub mod checkboxes;
24pub mod date_picker;
25pub mod image;
26pub mod overflow;
27pub mod radio;
28pub mod select;
29pub mod text_input;
30
31#[doc(inline)]
32pub use button::Button;
33#[doc(inline)]
34pub use checkboxes::Checkboxes;
35#[doc(inline)]
36pub use date_picker::DatePicker;
37#[doc(inline)]
38pub use image::Image;
39#[doc(inline)]
40pub use overflow::Overflow;
41#[doc(inline)]
42pub use radio::Radio;
43#[doc(inline)]
44pub use text_input::TextInput;
45
46/// # Block Elements - interactive components
47/// [slack api docs 🔗](https://api.slack.com/reference/block-kit/block-elements)
48///
49/// Block elements can be used inside of `section`, `context`, and `actions` [layout blocks 🔗].
50/// Inputs can only be used inside of `input` blocks.
51///
52/// Our overview of [app surfaces that support Block Kit 🔗] shows you where those blocks might be relevant.
53///
54/// Finally, our [handling user interactivity guide 🔗] will help you prepare your app to allow
55/// for the use of the interactive components listed below.
56///
57/// [app surfaces that support Block Kit 🔗]: https://api.slack.com/messaging/composing/layouts
58/// [handling user interactivity guide 🔗]: https://api.slack.com/interactivity/handling
59/// [layout blocks 🔗]: https://api.slack.com/reference/block-kit/blocks
60#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
61#[serde(tag = "type", rename_all = "snake_case")]
62pub enum BlockElement<'a> {
63  /// # Button Element
64  Button(Button<'a>),
65  /// # Checkboxes Element
66  Checkboxes(Checkboxes<'a>),
67  /// # Image Element
68  Image(Image<'a>),
69
70  /// # DatePicker Element
71  #[serde(rename = "datepicker")]
72  DatePicker(DatePicker<'a>),
73
74  /// # Overflow Element
75  Overflow(Overflow<'a>),
76
77  /// # Radio Button Group
78  RadioButtons(Radio<'a>),
79
80  /// # Text Input Element
81  #[serde(rename = "plain_text_input")]
82  TextInput(TextInput<'a>),
83
84  /// # Select a public channel
85  #[serde(rename = "channels_select")]
86  SelectPublicChannel(select::PublicChannel<'a>),
87
88  /// # Select any conversation (DM, Group DM, Public Channel, Private Channel)
89  #[serde(rename = "conversations_select")]
90  SelectConversation(select::Conversation<'a>),
91
92  /// # Select a user from the workspace
93  #[serde(rename = "users_select")]
94  SelectUser(select::User<'a>),
95
96  /// # Select options loaded from an external data source
97  #[serde(rename = "external_select")]
98  SelectExternal(select::External<'a>),
99
100  /// # Select options configured by your application
101  #[serde(rename = "static_select")]
102  SelectStatic(select::Static<'a>),
103
104  /// # Select multiple options configured by your application
105  #[serde(rename = "multi_static_select")]
106  MultiSelectStatic(select::multi::Static<'a>),
107
108  /// # Select multiple users from the workspace
109  #[serde(rename = "multi_users_select")]
110  MultiSelectUser(select::multi::User<'a>),
111
112  /// # Select multiple options loaded from an external data source
113  #[serde(rename = "multi_external_select")]
114  MultiSelectExternal(select::multi::External<'a>),
115
116  /// # Select multiple conversations (DM, Group DM, Public Channel, Private Channel)
117  #[serde(rename = "multi_conversations_select")]
118  MultiSelectConversation(select::multi::Conversation<'a>),
119
120  /// # Select multiple public channels
121  #[serde(rename = "multi_channels_select")]
122  MultiSelectPublicChannel(select::multi::PublicChannel<'a>),
123}
124
125impl<'a> BlockElement<'a> {
126  /// Validate that this block element agrees with Slack's model requirements.
127  ///
128  /// ```
129  /// use slack_blocks::elems::{BlockElement, Button};
130  ///
131  /// let text = std::iter::repeat('a').take(76).collect::<String>();
132  /// let btn = Button::builder().text(text).action_id("").build();
133  ///
134  /// let elem = BlockElement::from(btn.clone());
135  ///
136  /// assert_eq!(elem.validate(), btn.validate())
137  /// ```
138  #[cfg(feature = "validation")]
139  #[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
140  pub fn validate(&self) -> ValidationResult {
141    use BlockElement::*;
142
143    match self {
144      | Button(cts) => cts.validate(),
145      | SelectPublicChannel(cts) => cts.validate(),
146      | SelectConversation(cts) => cts.validate(),
147      | SelectUser(cts) => cts.validate(),
148      | SelectExternal(cts) => cts.validate(),
149      | SelectStatic(cts) => cts.validate(),
150      | MultiSelectPublicChannel(cts) => cts.validate(),
151      | MultiSelectConversation(cts) => cts.validate(),
152      | MultiSelectUser(cts) => cts.validate(),
153      | MultiSelectExternal(cts) => cts.validate(),
154      | MultiSelectStatic(cts) => cts.validate(),
155      | RadioButtons(cts) => cts.validate(),
156      | Overflow(cts) => cts.validate(),
157      | Checkboxes(cts) => cts.validate(),
158      | Image(cts) => cts.validate(),
159      | DatePicker(cts) => cts.validate(),
160      | TextInput(cts) => cts.validate(),
161    }
162  }
163}
164
165convert!(impl<'a> From<Button<'a>> for BlockElement<'a> => |b| BlockElement::Button(b));
166convert!(impl<'a> From<Radio<'a>> for BlockElement<'a> => |b| BlockElement::RadioButtons(b));
167convert!(impl<'a> From<TextInput<'a>> for BlockElement<'a> => |t| BlockElement::TextInput(t));
168convert!(impl<'a> From<Overflow<'a>> for BlockElement<'a> => |t| BlockElement::Overflow(t));
169convert!(impl<'a> From<DatePicker<'a>> for BlockElement<'a> => |t| BlockElement::DatePicker(t));
170convert!(impl<'a> From<Checkboxes<'a>> for BlockElement<'a> => |t| BlockElement::Checkboxes(t));
171convert!(impl<'a> From<Image<'a>> for BlockElement<'a> => |t| BlockElement::Image(t));
172
173convert!(impl<'a> From<select::Static<'a>> for BlockElement<'a> => |s| BlockElement::SelectStatic(s));
174convert!(impl<'a> From<select::External<'a>> for BlockElement<'a> => |s| BlockElement::SelectExternal(s));
175convert!(impl<'a> From<select::PublicChannel<'a>> for BlockElement<'a> => |s| BlockElement::SelectPublicChannel(s));
176convert!(impl<'a> From<select::Conversation<'a>> for BlockElement<'a> => |s| BlockElement::SelectConversation(s));
177convert!(impl<'a> From<select::User<'a>> for BlockElement<'a> => |s| BlockElement::SelectUser(s));
178
179convert!(impl<'a> From<select::multi::Static<'a>> for BlockElement<'a> => |s| BlockElement::MultiSelectStatic(s));
180convert!(impl<'a> From<select::multi::User<'a>> for BlockElement<'a> => |s| BlockElement::MultiSelectUser(s));
181convert!(impl<'a> From<select::multi::Conversation<'a>> for BlockElement<'a> => |s| BlockElement::MultiSelectConversation(s));
182convert!(impl<'a> From<select::multi::External<'a>> for BlockElement<'a> => |s| BlockElement::MultiSelectExternal(s));
183convert!(impl<'a> From<select::multi::PublicChannel<'a>> for BlockElement<'a> => |s| BlockElement::MultiSelectPublicChannel(s));