Skip to content

Commit

Permalink
Added ModalConfig class
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalbaljet committed Nov 2, 2024
1 parent 69d5ac5 commit acd7b73
Show file tree
Hide file tree
Showing 5 changed files with 401 additions and 0 deletions.
3 changes: 3 additions & 0 deletions demo-app/phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing" />
Expand Down
187 changes: 187 additions & 0 deletions demo-app/tests/Unit/ModalConfigTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php

declare(strict_types=1);

namespace Tests\Unit;

use InertiaUI\Modal\ModalConfig;
use InertiaUI\Modal\ModalPosition;
use InertiaUI\Modal\ModalType;
use InvalidArgumentException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class ModalConfigTest extends TestCase
{
#[Test]
public function it_can_create_a_new_instance()
{
$config = ModalConfig::new();

$this->assertInstanceOf(ModalConfig::class, $config);
$this->assertEquals([
'type' => null,
'modal' => null,
'slideover' => null,
'navigate' => null,
'closeButton' => null,
'closeExplicitly' => null,
'maxWidth' => null,
'paddingClasses' => null,
'panelClasses' => null,
'position' => null,
], $config->toArray());
}

#[Test]
public function it_can_set_the_type_to_modal()
{
$config = ModalConfig::new()->modal();

$this->assertEquals(ModalType::Modal->value, $config->toArray()['type']);
$this->assertTrue($config->toArray()['modal']);
$this->assertFalse($config->toArray()['slideover']);
}

#[Test]
public function it_can_set_the_type_to_slideover()
{
$config = ModalConfig::new()->slideover();

$this->assertEquals(ModalType::Slideover->value, $config->toArray()['type']);
$this->assertFalse($config->toArray()['modal']);
$this->assertTrue($config->toArray()['slideover']);
}

#[Test]
public function it_can_configure_the_navigation_setting()
{
$config = ModalConfig::new()->navigate();
$this->assertTrue($config->toArray()['navigate']);

$config = ModalConfig::new()->navigate(false);
$this->assertFalse($config->toArray()['navigate']);
}

#[Test]
public function it_can_configure_the_close_button()
{
$config = ModalConfig::new()->closeButton();
$this->assertTrue($config->toArray()['closeButton']);

$config = ModalConfig::new()->closeButton(false);
$this->assertFalse($config->toArray()['closeButton']);
}

#[Test]
public function it_can_configure_the_explicit_closing()
{
$config = ModalConfig::new()->closeExplicitly();
$this->assertTrue($config->toArray()['closeExplicitly']);

$config = ModalConfig::new()->closeExplicitly(false);
$this->assertFalse($config->toArray()['closeExplicitly']);
}

#[Test]
#[DataProvider('validMaxWidthProvider')]
public function it_can_set_a_max_width(string $width)
{
$config = ModalConfig::new()->maxWidth($width);
$this->assertEquals($width, $config->toArray()['maxWidth']);
}

public static function validMaxWidthProvider(): array
{
return [
'sm width' => ['sm'],
'md width' => ['md'],
'lg width' => ['lg'],
'xl width' => ['xl'],
'2xl width' => ['2xl'],
'3xl width' => ['3xl'],
'4xl width' => ['4xl'],
'5xl width' => ['5xl'],
'6xl width' => ['6xl'],
'7xl width' => ['7xl'],
];
}

#[Test]
public function it_throws_an_exception_for_invalid_max_width()
{
$this->expectException(InvalidArgumentException::class);

ModalConfig::new()->maxWidth('invalid');
}

#[Test]
public function it_can_set_padding_classes()
{
$config = ModalConfig::new()->paddingClasses('p-4');

$this->assertEquals('p-4', $config->toArray()['paddingClasses']);
}

#[Test]
public function it_can_set_panel_classes()
{
$config = ModalConfig::new()->panelClasses('bg-white');

$this->assertEquals('bg-white', $config->toArray()['panelClasses']);
}

#[Test]
public function it_can_set_the_position()
{
$config = ModalConfig::new()->position(ModalPosition::Center);

$this->assertEquals(ModalPosition::Center->value, $config->toArray()['position']);
}

#[Test]
#[DataProvider('positionMethodsProvider')]
public function it_can_set_a_predefined_positions(string $method, ModalPosition $expectedPosition)
{
$config = ModalConfig::new()->$method();
$this->assertEquals($expectedPosition->value, $config->toArray()['position']);
}

public static function positionMethodsProvider(): array
{
return [
'bottom position' => ['bottom', ModalPosition::Bottom],
'center position' => ['center', ModalPosition::Center],
'left position' => ['left', ModalPosition::Left],
'right position' => ['right', ModalPosition::Right],
'top position' => ['top', ModalPosition::Top],
];
}

#[Test]
public function it_can_chain_multiple_configurations()
{
$config = ModalConfig::new()
->modal()
->navigate()
->closeButton()
->maxWidth('2xl')
->paddingClasses('p-4')
->panelClasses('bg-white')
->center();

$this->assertEquals([
'type' => ModalType::Modal->value,
'modal' => true,
'slideover' => false,
'navigate' => true,
'closeButton' => true,
'closeExplicitly' => null,
'maxWidth' => '2xl',
'paddingClasses' => 'p-4',
'panelClasses' => 'bg-white',
'position' => ModalPosition::Center->value,
], $config->toArray());
}
}
186 changes: 186 additions & 0 deletions src/ModalConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
<?php

declare(strict_types=1);

namespace InertiaUI\Modal;

use Illuminate\Contracts\Support\Arrayable;
use InvalidArgumentException;

class ModalConfig implements Arrayable
{
public function __construct(
protected ?ModalType $type = null,
protected ?bool $navigate = null,
protected ?bool $closeButton = null,
protected ?bool $closeExplicitly = null,
protected ?string $maxWidth = null,
protected ?string $paddingClasses = null,
protected ?string $panelClasses = null,
protected ?ModalPosition $position = null
) {
//
}

/**
* Creates a new instance of the modal configuration.
*/
public static function new(): self
{
return new self;
}

/**
* Sets the type to Modal.
*/
public function modal(): self
{
$this->type = ModalType::Modal;

return $this;
}

/**
* Sets the type to Slideover.
*/
public function slideover(): self
{
$this->type = ModalType::Slideover;

return $this;
}

/**
* Configures whether the Base Route / URL feature should be used.
*/
public function navigate(?bool $navigate = true): self
{
$this->navigate = $navigate;

return $this;
}

/**
* Controls the visibility of the close button in the modal.
*/
public function closeButton(?bool $closeButton = true): self
{
$this->closeButton = $closeButton;

return $this;
}

/**
* Determines if the modal requires an explicit closing action, e.g.
* no clicking outside the modal to close it and no escape key to close it.
*/
public function closeExplicitly(?bool $closeExplicitly = true): self
{
$this->closeExplicitly = $closeExplicitly;

return $this;
}

/**
* Sets the maximum width of the modal using Tailwind conventions.
*/
public function maxWidth(?string $maxWidth): self
{
if (! in_array($maxWidth, ['sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl'])) {
throw new InvalidArgumentException('Invalid max width provided. Please use a value between sm and 7xl.');
}

$this->maxWidth = $maxWidth;

return $this;
}

/**
* Defines custom padding classes for the modal content
*/
public function paddingClasses(?string $paddingClasses): self
{
$this->paddingClasses = $paddingClasses;

return $this;
}

/**
* Sets custom classes for the modal panel element
*/
public function panelClasses(?string $panelClasses): self
{
$this->panelClasses = $panelClasses;

return $this;
}

/**
* Sets the position of the modal on the screen
*/
public function position(?ModalPosition $position): self
{
$this->position = $position;

return $this;
}

/**
* Positions the modal at the bottom of the screen
*/
public function bottom(): self
{
return $this->position(ModalPosition::Bottom);
}

/**
* Centers the modal on the screen
*/
public function center(): self
{
return $this->position(ModalPosition::Center);
}

/**
* Positions the slideover at the left side of the screen
*/
public function left(): self
{
return $this->position(ModalPosition::Left);
}

/**
* Positions the slideover at the right side of the screen
*/
public function right(): self
{
return $this->position(ModalPosition::Right);
}

/**
* Positions the modal at the top of the screen
*/
public function top(): self
{
return $this->position(ModalPosition::Top);
}

/**
* Converts the modal configuration to an array.
*/
public function toArray(): array
{
return [
'type' => $this->type?->value,
'modal' => $this->type && $this->type === ModalType::Modal,
'slideover' => $this->type && $this->type === ModalType::Slideover,
'navigate' => $this->navigate,
'closeButton' => $this->closeButton,
'closeExplicitly' => $this->closeExplicitly,
'maxWidth' => $this->maxWidth,
'paddingClasses' => $this->paddingClasses,
'panelClasses' => $this->panelClasses,
'position' => $this->position?->value,
];
}
}
14 changes: 14 additions & 0 deletions src/ModalPosition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace InertiaUI\Modal;

enum ModalPosition: string
{
case Bottom = 'bottom';
case Center = 'center';
case Left = 'left';
case Right = 'right';
case Top = 'top';
}
Loading

0 comments on commit acd7b73

Please sign in to comment.