Skip to content

Commit dcdea3f

Browse files
authored
component
1 parent 48e1557 commit dcdea3f

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

discord/components.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
from .types.components import SeparatorComponent as SeparatorComponentPayload
5959
from .types.components import TextDisplayComponent as TextDisplayComponentPayload
6060
from .types.components import ThumbnailComponent as ThumbnailComponentPayload
61+
from .types.components import LabelComponent as LabelComponentPayload
6162
from .types.components import UnfurledMediaItem as UnfurledMediaItemPayload
6263

6364
__all__ = (
@@ -76,6 +77,7 @@
7677
"FileComponent",
7778
"Separator",
7879
"Container",
80+
"Label",
7981
)
8082

8183
C = TypeVar("C", bound="Component")
@@ -375,6 +377,10 @@ class SelectMenu(Component):
375377
Added support for :attr:`ComponentType.user_select`, :attr:`ComponentType.role_select`,
376378
:attr:`ComponentType.mentionable_select`, and :attr:`ComponentType.channel_select`.
377379
380+
.. versionchanged:: 2.7
381+
382+
Added the :attr:`required` attribute for use in modals.
383+
378384
Attributes
379385
----------
380386
type: :class:`ComponentType`
@@ -399,6 +405,8 @@ class SelectMenu(Component):
399405
except for :attr:`ComponentType.channel_select`.
400406
disabled: :class:`bool`
401407
Whether the select is disabled or not.
408+
required: Optional[:class:`bool`]
409+
Whether the select is required or not. Only useable in modals. Defaults to ``False``.
402410
"""
403411

404412
__slots__: tuple[str, ...] = (
@@ -409,6 +417,7 @@ class SelectMenu(Component):
409417
"options",
410418
"channel_types",
411419
"disabled",
420+
"required",
412421
)
413422

414423
__repr_info__: ClassVar[tuple[str, ...]] = __slots__
@@ -428,6 +437,7 @@ def __init__(self, data: SelectMenuPayload):
428437
self.channel_types: list[ChannelType] = [
429438
try_enum(ChannelType, ct) for ct in data.get("channel_types", [])
430439
]
440+
self.required: bool | None = data.get("required") # Currently defaults to False, pending change
431441

432442
def to_dict(self) -> SelectMenuPayload:
433443
payload: SelectMenuPayload = {
@@ -445,6 +455,8 @@ def to_dict(self) -> SelectMenuPayload:
445455
payload["channel_types"] = [ct.value for ct in self.channel_types]
446456
if self.placeholder:
447457
payload["placeholder"] = self.placeholder
458+
if self.required is not None:
459+
payload["required"] = self.required
448460

449461
return payload
450462

@@ -1037,6 +1049,55 @@ def walk_components(self) -> Iterator[Component]:
10371049
yield c
10381050

10391051

1052+
class Label(Component):
1053+
"""Represents a Label used in modals as the top-level component.
1054+
1055+
This is a component that holda another component alongside additional text in modals.
1056+
``component`` may only be:
1057+
1058+
- :class:`InputText`
1059+
- :class:`SelectMenu` (string)
1060+
1061+
This inherits from :class:`Component`.
1062+
1063+
.. versionadded:: 2.7
1064+
1065+
Attributes
1066+
----------
1067+
component: :class:`Component`
1068+
The component contained in this label. Currently supports :class:`InputText` and :class:`SelectMenu`.
1069+
label: :class:`str`
1070+
The main text associated with this label's ``component``.
1071+
description: Optional[:class:`str`]
1072+
The description associated with this label's ``component``.
1073+
"""
1074+
1075+
__slots__: tuple[str, ...] = ("component", "label", "description")
1076+
1077+
__repr_info__: ClassVar[tuple[str, ...]] = __slots__
1078+
versions: tuple[int, ...] = ()
1079+
1080+
def __init__(self, data: LabelComponentPayload):
1081+
self.type: ComponentType = try_enum(ComponentType, data["type"])
1082+
self.id: int = data.get("id")
1083+
self.component: Component = _component_factory(data.get("component", {}))
1084+
self.label: str = data.get("label")
1085+
self.description: str | None = data.get("description")
1086+
1087+
def to_dict(self) -> LabelComponentPayload:
1088+
payload = {
1089+
"type": int(self.type),
1090+
"id": self.id,
1091+
"component": self.components.to_dict(),
1092+
"label": self.label,
1093+
"description": self.description
1094+
}
1095+
return payload
1096+
1097+
def walk_components(self) -> Iterator[Component]:
1098+
yield from [self.component]
1099+
1100+
10401101
COMPONENT_MAPPINGS = {
10411102
1: ActionRow,
10421103
2: Button,
@@ -1053,6 +1114,7 @@ def walk_components(self) -> Iterator[Component]:
10531114
13: FileComponent,
10541115
14: Separator,
10551116
17: Container,
1117+
18: Label,
10561118
}
10571119

10581120
STATE_COMPONENTS = (Section, Container, Thumbnail, MediaGallery, FileComponent)

discord/types/components.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class LabelComponent(BaseComponent):
156156
type: Literal[18]
157157
label: str
158158
description: NotRequired[str]
159-
Component: SelectMenu | InputText
159+
component: SelectMenu | InputText
160160

161161

162162
Component = Union[ActionRow, ButtonComponent, SelectMenu, InputText]

0 commit comments

Comments
 (0)