Skip to content

Commit

Permalink
Add style helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
rozsival committed Jan 8, 2020
1 parent bcdf2cb commit b55d8b1
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/PropsControl/Exceptions/InvalidArgument.php
@@ -0,0 +1,10 @@
<?php declare (strict_types = 1);

namespace Wavevision\PropsControl\Exceptions;

use Exception;

class InvalidArgument extends Exception
{

}
10 changes: 9 additions & 1 deletion src/PropsControl/Helpers/ClassName.php
Expand Up @@ -29,7 +29,7 @@ class ClassName

private string $subBlockDelimiter;

public function __construct(string $baseClass, ?callable $modifiersCallback)
public function __construct(string $baseClass, ?callable $modifiersCallback = null)
{
$this->baseClass = $baseClass;
$this->elementDelimiter = self::ELEMENT_DELIMITER;
Expand Down Expand Up @@ -59,6 +59,14 @@ public function element(string $className, ?string ...$modifiers): string
return $this->composeClassNames($this->baseClass . $this->elementDelimiter . $className, $modifiers);
}

public function extra(string $className, string $prefix = ''): string
{
if ($prefix !== '') {
return $prefix . $this->subBlockDelimiter . $className;
}
return $className;
}

public function getBaseClass(): string
{
return $this->baseClass;
Expand Down
40 changes: 40 additions & 0 deletions src/PropsControl/Helpers/Style.php
@@ -0,0 +1,40 @@
<?php declare (strict_types = 1);

namespace Wavevision\PropsControl\Helpers;

use Nette\SmartObject;
use Wavevision\PropsControl\Exceptions\InvalidArgument;
use Wavevision\Utils\Strings;

class Style
{

use SmartObject;

/**
* @var mixed[]
*/
private $style = [];

public function __toString(): string
{
$style = [];
foreach ($this->style as $key => $value) {
$style[] = Strings::camelCaseToDashCase($key) . ':' . $value;
}
return implode(';', $style);
}

/**
* @param mixed $value
*/
public function add(string $key, $value): self
{
if (!is_scalar($value)) {
throw new InvalidArgument(sprintf("Style attribute values must be scalar, '%s' given.", gettype($value)));
}
$this->style[$key] = $value;
return $this;
}

}
28 changes: 27 additions & 1 deletion src/PropsControl/PropsControl.php
Expand Up @@ -8,6 +8,7 @@
use Wavevision\PropsControl\Exceptions\InvalidState;
use Wavevision\PropsControl\Helpers\ClassName;
use Wavevision\PropsControl\Helpers\Render;
use Wavevision\PropsControl\Helpers\Style;
use Wavevision\Utils\Strings;

/**
Expand All @@ -24,11 +25,18 @@ abstract class PropsControl extends BaseControl

private const PROPS = 'props';

private const STYLE = 'style';

public function __construct()
{
$this->onCreateTemplate(
function (Template $template): void {
$template->setParameters([self::CLASS_NAME => $this->createClassName()]);
$template->setParameters(
[
self::CLASS_NAME => $this->createClassName(),
self::STYLE => new Style(),
]
);
}
);
}
Expand All @@ -51,6 +59,14 @@ public function getControlName(): string
return Strings::getClassName(static::class, true);
}

/**
* @return string[]
*/
public function getStyleProps(): array
{
return [];
}

/**
* @param mixed[]|object $props
*/
Expand Down Expand Up @@ -114,6 +130,7 @@ final protected function getMappedProps(): ?ValidProps
final protected function mapPropsToTemplate(Props $props): void
{
$props = $props->process();
$this->prepareStyle($props);
$this->beforeMapPropsToTemplate($props);
$this->template->{self::PROPS} = $props;
$this->template->{self::MODIFIERS} = [];
Expand Down Expand Up @@ -182,4 +199,13 @@ private function createInvalidProps(string $message, $props): InvalidProps
);
}

private function prepareStyle(ValidProps $props): void
{
foreach ($this->getStyleProps() as $prop) {
if ($value = $props->get($prop)) {
$this->template->style->add($prop, $value);
}
}
}

}
3 changes: 3 additions & 0 deletions src/PropsControl/PropsControlTemplate.php
Expand Up @@ -4,6 +4,7 @@

use Nette\Bridges\ApplicationLatte\Template;
use Wavevision\PropsControl\Helpers\ClassName;
use Wavevision\PropsControl\Helpers\Style;

class PropsControlTemplate extends Template
{
Expand All @@ -17,4 +18,6 @@ class PropsControlTemplate extends Template

public ValidProps $props;

public Style $style;

}
10 changes: 10 additions & 0 deletions tests/PropsControlTests/Components/TestComponent/TestComponent.php
Expand Up @@ -42,6 +42,16 @@ function (): string {
];
}

/**
* @inheritDoc
*/
public function getStyleProps(): array
{
// Optionally define which prop values will be used to assemble style attribute
parent::getStyleProps();
return [TestComponentProps::LINE_HEIGHT];
}

protected function beforeMapPropsToTemplate(ValidProps $props): void
{
parent::beforeMapPropsToTemplate($props);
Expand Down
Expand Up @@ -14,6 +14,8 @@ class TestComponentProps extends Props

public const ENTITY = 'entity';

public const LINE_HEIGHT = 'lineHeight';

public const NULLABLE_NUMBER = 'nullableNumber';

public const STRING = 'string';
Expand All @@ -37,6 +39,7 @@ protected function define(): array
Expect::structure(['one' => Expect::string(), 'two' => Expect::int(),])
),
self::ENTITY => Expect::type(\stdClass::class)->nullable(),
self::LINE_HEIGHT => Expect::float(1.4),
self::NULLABLE_NUMBER => Expect::int()->nullable(),
self::STRING => Expect::string()->required(),
self::TYPE => Expect::anyOf(...self::TYPES)->default(self::TYPE_ONE),
Expand Down
@@ -1,11 +1,11 @@
<div n:class="$className->block()">
<div n:class="$className->block()" n:attr="style => $style">
<div n:class="$className->element(first-child)">
{$props->string}
{$props->string}
</div>
<div n:class="$className->element(collection)" n:inner-foreach="$props->collection as $item">
<p>{$item->one} / {$item->two}</p>
</div>
{var partClassName = $className->create(part)}
{var partClassName = $className->create(part)}
<div n:class="$partClassName->block()" n:inner-foreach="[1,2,3,4,5] as $part">
<div n:class="$partClassName->element(element, $part === 1 ? first : null, $part === 5 ? last : null)"></div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions tests/PropsControlTests/Helpers/ClassNameTest.php
Expand Up @@ -39,6 +39,13 @@ public function testElement(): void
$this->assertEquals('my-class__element', $className->element('element'));
}

public function testExtra(): void
{
$className = new ClassName('');
$this->assertEquals('extra', $className->extra('extra'));
$this->assertEquals('prefixed-extra', $className->extra('extra', 'prefixed'));
}

private function createClassName(string $baseClass = '', string ...$modifiers): ClassName
{
return new ClassName(
Expand Down
25 changes: 25 additions & 0 deletions tests/PropsControlTests/Helpers/StyleTest.php
@@ -0,0 +1,25 @@
<?php declare (strict_types = 1);

namespace Wavevision\PropsControlTests\Helpers;

use PHPUnit\Framework\TestCase;
use Wavevision\PropsControl\Exceptions\InvalidArgument;
use Wavevision\PropsControl\Helpers\Style;

class StyleTest extends TestCase
{

public function testAdd(): void
{
$style = new Style();
$this->assertSame($style, $style->add('key', 1));
}

public function testAddThrowsInvalidArgument(): void
{
$style = new Style();
$this->expectException(InvalidArgument::class);
$style->add('key', new \stdClass());
}

}
1 change: 1 addition & 0 deletions tests/PropsControlTests/PropsControlTest.php
Expand Up @@ -61,6 +61,7 @@ public function testRender(): void
'tc tc--boolean tc--one tc--custom tc--some-other-modifier',
$root->attr('class')
);
$this->assertEquals('line-height:1.4', $root->attr('style'));
$this->assertEquals(1, $root->count());
$this->assertCount(3, $root->children());
$parts = $crawler->filter('div.tc-part__element');
Expand Down

0 comments on commit b55d8b1

Please sign in to comment.