2727
2828from typing import TYPE_CHECKING , Any , ClassVar , TypeVar
2929
30- from .enums import ButtonStyle , ChannelType , ComponentType , InputTextStyle , try_enum
30+ from .enums import ButtonStyle , ChannelType , ComponentType , InputTextStyle , SeparatorSpacingSize , try_enum
3131from .partial_emoji import PartialEmoji , _EmojiTag
3232from .utils import MISSING , get_slots
3333
3636 from .types .components import ActionRow as ActionRowPayload
3737 from .types .components import ButtonComponent as ButtonComponentPayload
3838 from .types .components import Component as ComponentPayload
39+ from .types .components import BaseComponent as BaseComponentPayload
3940 from .types .components import InputText as InputTextComponentPayload
4041 from .types .components import SelectMenu as SelectMenuPayload
4142 from .types .components import SelectOption as SelectOptionPayload
43+ from .types .components import TextDisplayComponent as TextDisplayComponentPayload
44+ from .types .components import SectionComponent as SectionComponentPayload
45+ from .types .components import UnfurledMediaItem as UnfurledMediaItemPayload
46+ from .types .components import ThumbnailComponent as ThumbnailComponentPayload
47+ from .types .components import MediaGalleryItem as MediaGalleryItemPayload
48+ from .types .components import MediaGalleryComponent as MediaGalleryComponentPayload
49+ from .types .components import FileComponent as FileComponentPayload
50+ from .types .components import SeparatorComponent as SeparatorComponentPayload
51+ from .types .components import ContainerComponent as ContainerComponentPayload
4252
4353__all__ = (
4454 "Component" ,
4757 "SelectMenu" ,
4858 "SelectOption" ,
4959 "InputText" ,
60+ "Section" ,
61+ "TextDisplay" ,
5062)
5163
5264C = TypeVar ("C" , bound = "Component" )
5365
54-
5566class Component :
5667 """Represents a Discord Bot UI Kit Component.
5768
@@ -69,12 +80,15 @@ class Component:
6980 ----------
7081 type: :class:`ComponentType`
7182 The type of component.
83+ id: :class:`str`
84+ The component's ID.
7285 """
7386
74- __slots__ : tuple [str , ...] = ("type" ,)
87+ __slots__ : tuple [str , ...] = ("type" , "id" )
7588
7689 __repr_info__ : ClassVar [tuple [str , ...]]
7790 type : ComponentType
91+ id : str
7892
7993 def __repr__ (self ) -> str :
8094 attrs = " " .join (f"{ key } ={ getattr (self , key )!r} " for key in self .__repr_info__ )
@@ -494,16 +508,100 @@ def to_dict(self) -> SelectOptionPayload:
494508 return payload
495509
496510
511+ class Section (Component ):
512+ """Represents a Section from Components V2.
513+
514+ This is a component that contains other components such as :class:`TextDisplay` and :class:`Thumbnail`.
515+
516+ This inherits from :class:`Component`.
517+
518+ .. versionadded:: 2.7
519+
520+ Attributes
521+ ----------
522+ components: List[:class:`Component`]
523+ The components contained in this section.
524+ accessory: Optional[:class:`Component`]
525+ The accessory attached to this Section.
526+ """
527+
528+ __slots__ : tuple [str , ...] = ("components" , "accessory" )
529+
530+ __repr_info__ : ClassVar [tuple [str , ...]] = __slots__
531+
532+ def __init__ (self , data : SectionComponentPayload ):
533+ self .type : ComponentType = try_enum (ComponentType , data ["type" ])
534+ self .id : str = data .get ("id" )
535+ self .components : list [Component ] = [_component_factory (d ) for d in data .get ("components" , [])]
536+ self .accessory : Component | None = None
537+ if _accessory := data .get ("accessory" ):
538+ self .accessory = _component_factory (_accessory )
539+
540+ def to_dict (self ) -> SectionComponentPayload :
541+ payload = {
542+ "type" : int (self .type ),
543+ "id" : self .id ,
544+ "components" : [c .to_dict () for c in self .components ]
545+ }
546+ if self .accessory :
547+ payload ["accessory" ] = self .accessory .to_dict ()
548+ return payload
549+
550+
551+ class TextDisplay (Component ):
552+ """Represents a Text Display from Components V2.
553+
554+ This is a component that displays text.
555+
556+ This inherits from :class:`Component`.
557+
558+ .. versionadded:: 2.7
559+
560+ Attributes
561+ ----------
562+ content: :class:`str`
563+ The component's text content.
564+ """
565+
566+ __slots__ : tuple [str , ...] = ("content" ,)
567+
568+ __repr_info__ : ClassVar [tuple [str , ...]] = __slots__
569+
570+ def __init__ (self , data : TextDisplayComponentPayload ):
571+ self .type : ComponentType = try_enum (ComponentType , data ["type" ])
572+ self .id : str = data .get ("id" )
573+ self .content : str = data .get ("content" )
574+
575+ def to_dict (self ) -> TextDisplayComponentPayload :
576+ return {
577+ "type" : int (self .type ),
578+ "id" : self .id ,
579+ "content" : self .content
580+ }
581+
582+
583+ COMPONENT_MAPPINGS = {
584+ 1 : ActionRow ,
585+ 2 : Button ,
586+ 3 : SelectMenu ,
587+ 4 : InputText ,
588+ 5 : SelectMenu ,
589+ 6 : SelectMenu ,
590+ 7 : SelectMenu ,
591+ 8 : SelectMenu ,
592+ 9 : Section ,
593+ 10 : TextDisplay ,
594+ 11 : None ,
595+ 12 : None ,
596+ 13 : None ,
597+ 14 : None ,
598+ 17 : None ,
599+ }
600+
497601def _component_factory (data : ComponentPayload ) -> Component :
498602 component_type = data ["type" ]
499- if component_type == 1 :
500- return ActionRow (data )
501- elif component_type == 2 :
502- return Button (data ) # type: ignore
503- elif component_type == 4 :
504- return InputText (data ) # type: ignore
505- elif component_type in (3 , 5 , 6 , 7 , 8 ):
506- return SelectMenu (data ) # type: ignore
603+ if cls := COMPONENT_MAPPINGS .get (component_type ):
604+ return cls (data )
507605 else :
508606 as_enum = try_enum (ComponentType , component_type )
509607 return Component ._raw_construct (type = as_enum )
0 commit comments