Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/Component/Modal/Checkbox.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

use Ragnarok\Fenrir\Component\Component;
use Ragnarok\Fenrir\Enums\MessageComponentType;

/**
* A single on or off checkbox.
*
* @see https://discord.com/developers/docs/components/reference#checkbox
*/
class Checkbox extends Component
{
public function __construct(
private readonly string $customId,
private readonly ?bool $default = null,
private readonly ?int $id = null
) {
}

public function get(): array
{
$data = [
'type' => MessageComponentType::CHECKBOX->value,
'custom_id' => $this->customId,
];

if (!is_null($this->default)) {
$data['default'] = $this->default;
}

if (!is_null($this->id)) {
$data['id'] = $this->id;
}

return $data;
}
}
74 changes: 74 additions & 0 deletions src/Component/Modal/CheckboxGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

use Ragnarok\Fenrir\Component\Component;
use Ragnarok\Fenrir\Enums\MessageComponentType;
use Ragnarok\Fenrir\Exceptions\Component\TooManyItemsException;

/**
* Several checkboxes the user can tick independently.
*
* @see https://discord.com/developers/docs/components/reference#checkbox-group
*/
class CheckboxGroup extends Component
{
public const MAX_OPTIONS = 10;

/** @var Option[] */
private array $options = [];

public function __construct(
private readonly string $customId,
private readonly ?int $minValues = null,
private readonly ?int $maxValues = null,
private readonly ?bool $required = null,
private readonly ?int $id = null
) {
}

/**
* @throws TooManyItemsException
*/
public function add(Option $option): self
{
if (count($this->options) === self::MAX_OPTIONS) {
throw new TooManyItemsException(
'A checkbox group can hold at most ' . self::MAX_OPTIONS . ' options'
);
}

$this->options[] = $option;

return $this;
}

public function get(): array
{
$data = [
'type' => MessageComponentType::CHECKBOX_GROUP->value,
'custom_id' => $this->customId,
'options' => array_map(static fn (Option $option) => $option->get(), $this->options),
];

if (!is_null($this->minValues)) {
$data['min_values'] = $this->minValues;
}

if (!is_null($this->maxValues)) {
$data['max_values'] = $this->maxValues;
}

if (!is_null($this->required)) {
$data['required'] = $this->required;
}

if (!is_null($this->id)) {
$data['id'] = $this->id;
}

return $data;
}
}
56 changes: 56 additions & 0 deletions src/Component/Modal/FileUpload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

use Ragnarok\Fenrir\Component\Component;
use Ragnarok\Fenrir\Enums\MessageComponentType;

/**
* Lets the user attach files to a modal submission.
*
* @see https://discord.com/developers/docs/components/reference#file-upload
*/
class FileUpload extends Component
{
public function __construct(
private readonly string $customId,
private readonly ?int $minValues = null,
private readonly ?int $maxValues = null,
private readonly ?bool $required = null,
private readonly ?array $fileTypes = null,
private readonly ?int $id = null
) {
}

public function get(): array
{
$data = [
'type' => MessageComponentType::FILE_UPLOAD->value,
'custom_id' => $this->customId,
];

if (!is_null($this->minValues)) {
$data['min_values'] = $this->minValues;
}

if (!is_null($this->maxValues)) {
$data['max_values'] = $this->maxValues;
}

if (!is_null($this->required)) {
$data['required'] = $this->required;
}

if (!is_null($this->fileTypes)) {
$data['file_types'] = array_values($this->fileTypes);
}

if (!is_null($this->id)) {
$data['id'] = $this->id;
}

return $data;
}
}
44 changes: 44 additions & 0 deletions src/Component/Modal/Label.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

use Ragnarok\Fenrir\Component\Component;
use Ragnarok\Fenrir\Enums\MessageComponentType;

/**
* Wraps a single input with the text shown above it. Every interactive
* component in a modal sits inside one of these.
*
* @see https://discord.com/developers/docs/components/reference#label
*/
class Label extends Component
{
public function __construct(
private readonly string $label,
private readonly Component $component,
private readonly ?string $description = null,
private readonly ?int $id = null
) {
}

public function get(): array
{
$data = [
'type' => MessageComponentType::LABEL->value,
'label' => $this->label,
'component' => $this->component->get(),
];

if (!is_null($this->description)) {
$data['description'] = $this->description;
}

if (!is_null($this->id)) {
$data['id'] = $this->id;
}

return $data;
}
}
39 changes: 39 additions & 0 deletions src/Component/Modal/Option.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

/**
* One choice within a radio group or checkbox group. Both take the same shape.
*
* @see https://discord.com/developers/docs/components/reference#radio-group
*/
class Option
{
public function __construct(
private readonly string $label,
private readonly string $value,
private readonly ?string $description = null,
private readonly ?bool $default = null
) {
}

public function get(): array
{
$data = [
'label' => $this->label,
'value' => $this->value,
];

if (!is_null($this->description)) {
$data['description'] = $this->description;
}

if (!is_null($this->default)) {
$data['default'] = $this->default;
}

return $data;
}
}
65 changes: 65 additions & 0 deletions src/Component/Modal/RadioGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Ragnarok\Fenrir\Component\Modal;

use Ragnarok\Fenrir\Component\Component;
use Ragnarok\Fenrir\Enums\MessageComponentType;
use Ragnarok\Fenrir\Exceptions\Component\TooManyItemsException;

/**
* A set of mutually exclusive choices. Discord requires at least two.
*
* @see https://discord.com/developers/docs/components/reference#radio-group
*/
class RadioGroup extends Component
{
public const MIN_OPTIONS = 2;
public const MAX_OPTIONS = 10;

/** @var Option[] */
private array $options = [];

public function __construct(
private readonly string $customId,
private readonly ?bool $required = null,
private readonly ?int $id = null
) {
}

/**
* @throws TooManyItemsException
*/
public function add(Option $option): self
{
if (count($this->options) === self::MAX_OPTIONS) {
throw new TooManyItemsException(
'A radio group can hold at most ' . self::MAX_OPTIONS . ' options'
);
}

$this->options[] = $option;

return $this;
}

public function get(): array
{
$data = [
'type' => MessageComponentType::RADIO_GROUP->value,
'custom_id' => $this->customId,
'options' => array_map(static fn (Option $option) => $option->get(), $this->options),
];

if (!is_null($this->required)) {
$data['required'] = $this->required;
}

if (!is_null($this->id)) {
$data['id'] = $this->id;
}

return $data;
}
}
Loading