Skip to content

Commit

Permalink
Merge pull request #5 from ucraft-com/added-breakpoint-media-query
Browse files Browse the repository at this point in the history
Breakpoint media query
  • Loading branch information
miqayelsrapionyan authored Nov 25, 2024
2 parents e30fc26 + 27cbb67 commit e2faf1d
Show file tree
Hide file tree
Showing 8 changed files with 383 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/CssGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use CssGenerator\StyleCollector\StyleCollectorContract;

use function join;

/**
* CssGenerator converts variantsStyles array into css string.
*/
Expand All @@ -17,12 +19,22 @@ public function __construct(protected StyleCollectorContract $styleCollector)
}

/**
* Convert variantsStyles to css string.
* Convert variantsStyles to array of css string key by breakpoint id.
*
* @return array
*/
public function generate(): array
{
return $this->styleCollector->getStylesheet()->generate();
}

/**
* Convert variantsStyles to css string.
*
* @return string
*/
public function generateStylesheet(): string
{
return join($this->styleCollector->getStylesheet()->generate());
}
}
118 changes: 118 additions & 0 deletions src/Decorators/BreakpointMediaQueryDecorator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

declare(strict_types=1);

namespace CssGenerator\Decorators;

use function implode;

class BreakpointMediaQueryDecorator implements StyleDecoratorInterface
{
/**
* @var array|StyleDecorator[]
*/
protected array $styles = [];

/**
* @var bool
*/
protected bool $isDefault = false;

/**
* @var string @media query of breakpoint
*/
protected string $mediaQuery = '';

/**
* @var int ID of breakpoint.
*/
protected int $id;

/**
* @param int $id
*
* @return void
*/
public function setId(int $id): void
{
$this->id = $id;
}

/**
* @return int
*/
public function getId(): int
{
return $this->id;
}

/**
* @param string $mediaQuery
*
* @return void
*/
public function setMediaQuery(string $mediaQuery): void
{
$this->mediaQuery = $mediaQuery;
}

/**
* @return string
*/
public function getMediaQuery(): string
{
return $this->mediaQuery;
}

/**
* @param bool $isDefault
*
* @return void
*/
public function setIsDefault(bool $isDefault): void
{
$this->isDefault = $isDefault;
}

/**
* @return bool
*/
public function isDefault(): bool
{
return $this->isDefault;
}

/**
* @param string $widgetId
* @param \CssGenerator\Decorators\StyleDecorator $style
*
* @return void
*/
public function addStyle(string $widgetId, StyleDecorator $style): void
{
$this->styles[$widgetId][] = $style;
}

/**
* Bring together already generated css blocks.
*
* @return string
*/
public function __toString(): string
{
$css = '';
if (!$this->isDefault) {
$css .= $this->getMediaQuery();
}

foreach ($this->styles as $styles) {
$css .= implode('', $styles);
}

if (!$this->isDefault) {
$css .= '}';
}

return $css;
}
}
36 changes: 36 additions & 0 deletions src/Decorators/StylesheetMediaQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace CssGenerator\Decorators;

use function implode;

/**
* StylesheetMediaQuery contains breakpoints, and generates css with media queries.
*/
class StylesheetMediaQuery implements StylesheetInterface
{
/**
* @var array<\CssGenerator\Decorators\BreakpointDecorator>
*/
protected array $breakpoints = [];

/**
* @param array $breakpoints
*
* @return void
*/
public function setBreakpoints(array $breakpoints): void
{
$this->breakpoints = $breakpoints;
}

/**
* @return array
*/
public function generate(): array
{
return ['default breakpoint id' => implode('', $this->breakpoints)];
}
}
1 change: 0 additions & 1 deletion src/Strategies/BackgroundStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace CssGenerator\Strategies;

use function join;
use function is_string;

class BackgroundStrategy implements StrategyInterfaceWithMediaMapping
{
Expand Down
47 changes: 47 additions & 0 deletions src/StyleCollector/StyleCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace CssGenerator\StyleCollector;

use CssGenerator\Decorators\BreakpointDecorator;
use CssGenerator\Decorators\BreakpointMediaQueryDecorator;
use CssGenerator\Decorators\StaticStyleDecorator;
use CssGenerator\Decorators\StaticStylesheet;
use CssGenerator\Decorators\StyleDecorator;
use CssGenerator\Decorators\StyleInterface;
use CssGenerator\Decorators\Stylesheet;

use function in_array;
use function array_unshift;

/**
* StyleCollector collects all necessary data for generating css.
Expand Down Expand Up @@ -68,6 +70,51 @@ public function assignBreakpoints(array $breakpoints): StyleCollector
return $this;
}

/**
* @param array $breakpoints
*
* @return $this
*/
public function assignMediaQueryBreakpoints(array $breakpoints): StyleCollector
{
$defaultBreakpointWidth = 0;
$sortedBreakpoints = [];

// Sort breakpoints, if breakpoint is less than default, must be reverse sorted
// example: [320, 769, 1281, 1441, 1921] -> [1281, 769, 320, 1441, 1921] (1281 is default)
foreach ($breakpoints as $breakpointIndex => $breakpoint) {
$newBreakpoint = new BreakpointMediaQueryDecorator();
$newBreakpoint->setIsDefault($breakpoint['default']);
$newBreakpoint->setId($breakpoint['id']);

if (!$newBreakpoint->isDefault()) {
if ($defaultBreakpointWidth === 0 || $defaultBreakpointWidth > $breakpoint['width']) {
$width = $breakpoint['width'];

if (isset($breakpoints[$breakpointIndex + 1])) {
$width = $breakpoints[$breakpointIndex + 1]['width'] - 1;
}
$newBreakpoint->setMediaQuery("@media (max-width: {$width}px) {");
array_unshift($sortedBreakpoints, $newBreakpoint);
} else {
$newBreakpoint->setMediaQuery("@media (min-width: {$breakpoint['width']}px) {");
$sortedBreakpoints[] = $newBreakpoint;
}
}

if ($breakpoint['default']) {
$defaultBreakpointWidth = $breakpoint['width'];
array_unshift($sortedBreakpoints, $newBreakpoint);
}
}

foreach ($sortedBreakpoints as $sortedBreakpoint) {
$this->data['breakpoints'][$sortedBreakpoint->getId()] = $sortedBreakpoint;
}

return $this;
}

/**
* @return \CssGenerator\Decorators\StyleInterface
*/
Expand Down
78 changes: 78 additions & 0 deletions tests/Unit/CssGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,84 @@ public function testGenerate_WhenGivenWithBreakpoints_GeneratesBasedOnBreakpoint
$this->assertEquals($expectedBreakpoint3, $css[3]);
}

public function testGenerate_WhenGivenWithMediaQueryBreakpoints_GeneratesBasedOnBreakpoints(): void
{
$breakpoints = [
[
"id" => 1,
"width" => 320,
"default" => false,
"selected" => false,
"createdAt" => "2022-05-19T11:57:40.000000Z",
],
[
"id" => 2,
"width" => 769,
"default" => false,
"selected" => false,
"createdAt" => "2022-05-19T11:57:40.000000Z",
],
[
"id" => 3,
"width" => 1281,
"default" => true,
"selected" => true,
"createdAt" => "2022-05-19T11:57:40.000000Z",
],
[
"id" => 4,
"width" => 1441,
"default" => false,
"selected" => false,
"createdAt" => "2022-05-19T11:57:40.000000Z",
],
[
"id" => 5,
"width" => 1921,
"default" => false,
"selected" => false,
"createdAt" => "2022-05-19T11:57:40.000000Z",
],
];

$variantsStyles = [
'[data-widget-hash="random-hash"]' => [
[
'styles' => [
[
"type" => "font-family",
"value" => "Helvetica"
]
],
'cssState' => 'normal',
'breakpointId' => 3
],
[
'styles' => [
[
"type" => "color",
"value" => "rgb(0, 0, 0)"
]
],
'cssState' => 'hover',
'breakpointId' => 1
]
]
];

$styleCollector = $this->getStyleCollectorInstance();
$styleCollector
->assignMediaQueryBreakpoints($breakpoints)
->assignVariantsStyles($variantsStyles)
->build();

$generator = new CssGenerator($styleCollector);
$css = $generator->generateStylesheet();

$expected = '[data-widget-hash="random-hash"] {font-family: Helvetica;}@media (max-width: 1280px) {}@media (max-width: 768px) {[data-widget-hash="random-hash"]:hover {color: rgb(0, 0, 0);}}@media (min-width: 1441px) {}@media (min-width: 1921px) {}';
$this->assertEquals($expected, $css);
}

public function testGenerateStyles_WithSpecifiedBreakpointId(): void
{
$staticGlobalStyles = [
Expand Down
Loading

0 comments on commit e2faf1d

Please sign in to comment.