discord-components-v2 3.0.3
An unofficial library for discord components v2.
Requires Python: >=3.8

# discord-components-v2

An unofficial third-party library for discord.py that adds full support for Discord Components V2 API.

## Features

- **Full Discord Components V2 Support** - Complete implementation of the new Components V2 API
- **Advanced Layout System** - Containers with horizontal/vertical direction
- **Rich Content Components** - Text, headings, separators, and media galleries
- **Interactive Components** - Buttons, select menus, text inputs, and modals
- **Easy-to-use API** - Intuitive Python interface
- **Compatible with discord.py** - Drop-in replacement for standard discord.py

## What is Components V2?

Components V2 is Discord's new message composition system that replaces traditional embeds. It provides more control over message layout and appearance with features like:

- Multiple columns and rows
- Separators and dividers
- Image galleries
- Content containers with icons
- Flexible layouts

## Installation

```bash
pip install discord-components-v2
```

## Quick Start

### Basic Components V2 Message

```python
from discord_components_v2 import (
    ComponentsBot,
    Container,
    TextComponent,
    HeadingComponent,
    HeadingLevel,
    Separator,
    Button,
    ButtonStyle
)

bot = ComponentsBot(command_prefix="!")

@bot.command()
async def profile(ctx):
    message_container = Container(
        HeadingComponent("User Profile", level=HeadingLevel.heading_1),
        Separator(divider=True),
        TextComponent(f"Welcome {ctx.author.name}!"),
        Separator(),
        Button(label="View Stats", style=ButtonStyle.primary, custom_id="stats")
    )
    
    await ctx.send(components=[message_container])

@bot.event
async def on_button_click(interaction):
    await interaction.send("Stats loaded!")

bot.run("YOUR_TOKEN")
```

### Multi-Column Layout

```python
from discord_components_v2 import Container, LayoutDirection, TextComponent

left_column = Container(
    TextComponent("Left Column"),
    TextComponent("Content here"),
    direction=LayoutDirection.vertical
)

right_column = Container(
    TextComponent("Right Column"),
    TextComponent("More content"),
    direction=LayoutDirection.vertical
)

main_container = Container(
    left_column,
    right_column,
    direction=LayoutDirection.horizontal
)

await ctx.send(components=[main_container])
```

### Media Gallery

```python
from discord_components_v2 import MediaGallery, MediaItem

gallery = MediaGallery(
    MediaItem(url="https://example.com/image1.png", description="First image"),
    MediaItem(url="https://example.com/image2.png", description="Second image"),
    MediaItem(url="https://example.com/image3.png", spoiler=True)
)

await ctx.send(components=[gallery])
```

### Content Containers

```python
from discord_components_v2 import ContentContainer, TextComponent

container = ContentContainer(
    TextComponent("This is inside a content container"),
    TextComponent("With a custom icon and title"),
    title="Information",
    icon="ℹ️"
)

await ctx.send(components=[container])
```

### Traditional Components (Buttons & Selects)

```python
from discord_components_v2 import Button, ButtonStyle, Select, SelectOption, ActionRow

await ctx.send(
    "Choose an option:",
    components=[
        ActionRow(
            Button(label="Primary", style=ButtonStyle.primary),
            Button(label="Success", style=ButtonStyle.success),
            Button(label="Danger", style=ButtonStyle.danger)
        ),
        ActionRow(
            Select(
                placeholder="Select an option",
                options=[
                    SelectOption(label="Option 1", value="1"),
                    SelectOption(label="Option 2", value="2"),
                    SelectOption(label="Option 3", value="3")
                ]
            )
        )
    ]
)
```

### Modals with Text Inputs

```python
from discord_components_v2 import Modal, TextInput, TextInputStyle

@bot.event
async def on_button_click(interaction):
    if interaction.custom_id == "feedback":
        modal = Modal(
            title="Feedback Form",
            components=[
                TextInput(
                    label="Your Name",
                    style=TextInputStyle.short,
                    placeholder="Enter your name",
                    required=True
                ),
                TextInput(
                    label="Feedback",
                    style=TextInputStyle.paragraph,
                    placeholder="Enter your feedback here",
                    min_length=10,
                    max_length=1000
                )
            ]
        )
        await interaction.send_modal(modal)

@bot.event
async def on_modal_submit(interaction):
    name = interaction.modal_values.get("your_name_custom_id")
    feedback = interaction.modal_values.get("feedback_custom_id")
    await interaction.send(f"Thanks {name}! We received your feedback.")
```

## Component Types

### Layout Components

- **Container** - Organize components vertically or horizontally
- **ActionRow** - Group interactive components (buttons, selects)
- **Separator** - Add spacing or dividers between components

### Content Components

- **TextComponent** - Display text with alignment
- **HeadingComponent** - Display headings (H1, H2, H3)
- **MediaGallery** - Display multiple images
- **ContentContainer** - Group content with title and icon

### Interactive Components

- **Button** - Clickable buttons with various styles
- **Select** - Dropdown menus (string, user, role, channel, mentionable)
- **TextInput** - Text input fields for modals
- **Modal** - Pop-up forms with text inputs

## Component Types Reference

```python
from discord_components_v2 import ComponentType

ComponentType.action_row           # 1
ComponentType.button              # 2
ComponentType.string_select       # 3
ComponentType.text_input         # 4
ComponentType.user_select        # 5
ComponentType.role_select        # 6
ComponentType.mentionable_select # 7
ComponentType.channel_select     # 8
ComponentType.container          # 9
ComponentType.separator          # 10
ComponentType.text               # 11
ComponentType.media_gallery      # 12
ComponentType.content_container  # 13
ComponentType.heading            # 14
ComponentType.file_upload        # 15
```

## Events

The library provides several events for handling interactions:

- `on_button_click` - Triggered when a button is clicked
- `on_select_option` - Triggered when a select menu option is chosen
- `on_modal_submit` - Triggered when a modal form is submitted
- `on_interaction` - Generic interaction event

## Advanced Usage

### Callback System

```python
@bot.command()
async def test(ctx):
    async def my_callback(interaction):
        await interaction.send("Button clicked!")
    
    button = bot.components_manager.add_callback(
        Button(label="Click me", style=ButtonStyle.primary),
        my_callback,
        uses=1
    )
    
    await ctx.send("Test", components=[button])
```

### Wait For Interaction

```python
@bot.command()
async def quiz(ctx):
    await ctx.send(
        "What's 2+2?",
        components=[
            Button(label="3", custom_id="wrong"),
            Button(label="4", custom_id="correct"),
            Button(label="5", custom_id="wrong")
        ]
    )
    
    interaction = await bot.components_manager.wait_for(
        "button_click",
        user=ctx.author,
        timeout=30.0
    )
    
    if interaction.custom_id == "correct":
        await interaction.send("Correct!")
    else:
        await interaction.send("Wrong!")
```

## Migration from Old Components

If you're migrating from the old components system:

1. Replace `ActionRow` usage for layout with `Container`
2. Use `ComponentType` enum instead of magic numbers
3. Add new V2 components like `TextComponent`, `HeadingComponent`, `Separator`
4. Update component type numbers (they've changed in V2)

## Requirements

- Python 3.8+
- discord.py
- aiohttp

## License

MIT License

## Credits

Based on the original discord-components by kiki7000, updated for Components V2 API support.