1use crate::reaction::ReactionEmoji;
4use crate::TitanString;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(untagged)]
14pub enum Component<'a> {
15 ActionRow(ActionRow<'a>),
17 Button(Button<'a>),
19 SelectMenu(SelectMenu<'a>),
21 TextInput(TextInput<'a>),
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
27#[serde(from = "u8", into = "u8")]
28pub enum ComponentType {
29 ActionRow = 1,
31 Button = 2,
33 StringSelect = 3,
35 TextInput = 4,
37 UserSelect = 5,
39 RoleSelect = 6,
41 MentionableSelect = 7,
43 ChannelSelect = 8,
45}
46
47impl From<u8> for ComponentType {
48 fn from(value: u8) -> Self {
49 match value {
50 1 => ComponentType::ActionRow,
51 2 => ComponentType::Button,
52 3 => ComponentType::StringSelect,
53 4 => ComponentType::TextInput,
54 5 => ComponentType::UserSelect,
55 6 => ComponentType::RoleSelect,
56 7 => ComponentType::MentionableSelect,
57 8 => ComponentType::ChannelSelect,
58 _ => ComponentType::ActionRow, }
60 }
61}
62
63impl From<ComponentType> for u8 {
64 fn from(value: ComponentType) -> Self {
65 value as u8
66 }
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct ActionRow<'a> {
72 #[serde(rename = "type")]
74 pub component_type: ComponentType,
75 pub components: Vec<Component<'a>>,
77}
78
79impl<'a> Default for ActionRow<'a> {
80 fn default() -> Self {
81 Self {
82 component_type: ComponentType::ActionRow,
83 components: Vec::new(),
84 }
85 }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct Button<'a> {
91 #[serde(rename = "type")]
93 pub component_type: ComponentType,
94 pub style: ButtonStyle,
96 #[serde(default)]
98 pub label: Option<TitanString<'a>>,
99 #[serde(default)]
101 pub emoji: Option<ReactionEmoji<'a>>,
102 #[serde(default)]
104 pub custom_id: Option<TitanString<'a>>,
105 #[serde(default)]
107 pub url: Option<TitanString<'a>>,
108 #[serde(default)]
110 pub disabled: bool,
111}
112
113impl<'a> Button<'a> {
114 pub fn builder(
116 custom_id: impl Into<TitanString<'a>>,
117 style: ButtonStyle,
118 ) -> crate::builder::ButtonBuilder<'a> {
119 crate::builder::ButtonBuilder::new()
120 .custom_id(custom_id)
121 .style(style)
122 }
123
124 pub fn builder_link(url: impl Into<TitanString<'a>>) -> crate::builder::ButtonBuilder<'a> {
126 crate::builder::ButtonBuilder::new()
127 .url(url)
128 .style(ButtonStyle::Link)
129 }
130}
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
132#[serde(from = "u8", into = "u8")]
133pub enum ButtonStyle {
134 Primary = 1,
136 Secondary = 2,
138 Success = 3,
140 Danger = 4,
142 Link = 5,
144}
145
146impl From<u8> for ButtonStyle {
147 fn from(value: u8) -> Self {
148 match value {
149 1 => ButtonStyle::Primary,
150 2 => ButtonStyle::Secondary,
151 3 => ButtonStyle::Success,
152 4 => ButtonStyle::Danger,
153 5 => ButtonStyle::Link,
154 _ => ButtonStyle::Primary,
155 }
156 }
157}
158
159impl From<ButtonStyle> for u8 {
160 fn from(value: ButtonStyle) -> Self {
161 value as u8
162 }
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct SelectMenu<'a> {
168 #[serde(rename = "type")]
170 pub component_type: ComponentType,
171 pub custom_id: TitanString<'a>,
173 #[serde(default)]
175 pub options: Vec<SelectOption<'a>>,
176 #[serde(default)]
178 pub placeholder: Option<TitanString<'a>>,
179 #[serde(default)]
181 pub min_values: Option<u8>,
182 #[serde(default)]
184 pub max_values: Option<u8>,
185 #[serde(default)]
187 pub disabled: bool,
188}
189
190impl<'a> SelectMenu<'a> {
191 pub fn builder(custom_id: impl Into<TitanString<'a>>) -> crate::builder::SelectMenuBuilder<'a> {
193 crate::builder::SelectMenuBuilder::new(custom_id)
194 }
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct SelectOption<'a> {
200 pub label: TitanString<'a>,
202 pub value: TitanString<'a>,
204 #[serde(default)]
206 pub description: Option<TitanString<'a>>,
207 #[serde(default)]
209 pub emoji: Option<ReactionEmoji<'a>>,
210 #[serde(default)]
212 pub default: bool,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct TextInput<'a> {
218 #[serde(rename = "type")]
220 pub component_type: ComponentType,
221 pub custom_id: TitanString<'a>,
223 pub style: TextInputStyle,
225 pub label: TitanString<'a>,
227 #[serde(default)]
229 pub min_length: Option<u16>,
230 #[serde(default)]
232 pub max_length: Option<u16>,
233 #[serde(default)]
235 pub required: Option<bool>,
236 #[serde(default)]
238 pub value: Option<TitanString<'a>>,
239 #[serde(default)]
241 pub placeholder: Option<TitanString<'a>>,
242}
243
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
246#[serde(from = "u8", into = "u8")]
247pub enum TextInputStyle {
248 Short = 1,
250 Paragraph = 2,
252}
253
254impl From<u8> for TextInputStyle {
255 fn from(value: u8) -> Self {
256 match value {
257 1 => TextInputStyle::Short,
258 2 => TextInputStyle::Paragraph,
259 _ => TextInputStyle::Short,
260 }
261 }
262}
263
264impl From<TextInputStyle> for u8 {
265 fn from(value: TextInputStyle) -> Self {
266 value as u8
267 }
268}